class Sound(object): def __init__(self, filename, volume): super(Sound, self).__init__() file = os.path.join(BASEDIR, 'sounds', filename) self.volume = volume or 0 self.effect = QSoundEffect() self.effect.setSource(QUrl.fromLocalFile(file)) def play(self, volume=None, loop=True): volume = self.volume if volume is None else volume self.effect.setLoopCount(0) self.effect.setVolume(int(volume) / 100) if loop: self.effect.setLoopCount(QSoundEffect.Infinite) else: self.effect.setLoopCount(1) if not self.effect.isPlaying(): self.effect.play() def stop(self): self.effect.stop() def setVolume(self, volume): self.volume = volume
class SoftKey(QLabel): def __init__(self, num, parent): assert num >= 0 and num <= 3 labels = ['\u21ba', '\u25bc', '\u25b2', '\u23ce'] xpositions = [0, 40, 80, 120] sfxfiles = ['sfx014.wav', 'sfx013.wav', 'sfx033.wav', 'sfx061.wav'] label = labels[num] xpos = xpositions[num] sfx = sfxfiles[num] super().__init__(label, parent) self.sfx = QSoundEffect(self) self.sfx.setSource(QUrl.fromLocalFile(sfx)) self.sfx.setVolume(0.5) self.resize(40, 27) self.move(xpos, 100) self.setFrameStyle(QFrame.Panel | QFrame.Raised) self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.showPressed(False) self.show() def showPressed(self, pressed): if pressed: self.sfx.play() self.setLineWidth(4) else: self.setLineWidth(2)
class noiseGenerator(QThread): def __init__(self, playnoise, volume): super().__init__() pathname = os.path.dirname(os.path.realpath('whitenoise.wav')) self.sound = QSoundEffect() self.sound.setSource(QUrl.fromLocalFile(pathname + '/whitenoise.wav')) self.sound.setLoopCount(QSoundEffect.Infinite) self.settings(playnoise, volume) def settings(self, playnoise, volume): self.playnoise = playnoise self.sound.setVolume(volume) def run(self): if self.playnoise: self.sound.play() def stop(self): self.sound.stop()
class CardGraphicsItem(QGraphicsPixmapItem): suitnames = {'Spades': 'S', 'Clubs': 'C', 'Diamonds': 'D', 'Hearts': 'H'} def __init__(self, card): super(CardGraphicsItem, self).__init__() self.path = 'img/' + str( card.value) + CardGraphicsItem.suitnames[card.suit] self.show_face() self.setScale(0.12) self.card = card self.click_sound = QSoundEffect() self.click_sound.setSource(QUrl.fromLocalFile('sound/playcard.wav')) def mousePressEvent(self, *args, **kwargs): self.click_sound.play() if not self.card.selected: self.select() else: self.deselect() def select(self): self.moveBy(0, -20) self.card.select() def deselect(self): self.moveBy(0, 20) self.card.deselect() def show_face(self): self.setPixmap(QPixmap(self.path)) def show_back(self): self.setPixmap(QPixmap('img/red_back')) #img/red_back def __str__(self): return '{} of {}'.format(self.card.value, self.card.suit)
class view(QWidget): def __init__(self, Model, width): super().__init__() # resize the width self.width = self.Resize(width) # pass the reference of model to self.model self.model = Model self.title = 'project 2.5 imge browser with sound effect and tags' self.mode = 1 # mode 1 is list of thumbnails, mode 2 is one large image self.idx = 0 # index to images for display self.center = 0 # index to highlight image self.w = self.width # width of full screen image self.h = 0.75 * self.w # height of full screen image self.b = 20 # border of full screen image self.h1 = self.h / 6.0 # height of thumbnail image self.w1 = self.w / 6.0 # width of thumbnail image self.b1 = 5 # border of thumbnail image self.margintop = self.w / 8.0 # margin of thumbnail to top self.marginleft = self.w / 8.0 # margin of thumbnail to left self.scaleratio = 0.75 # a parameter for scaling of full screen image # create a list of tags labels self.taglist = [] self.tagsLeft = self.w * 0.8 self.tagsTop = self.h * 0.1 self.tagsW = self.w * 0.15 self.tagsH = self.h * 0.1 # create an editable label self.EditLabel = QLabel(self) self.EditLabel.setText("Edit the label: ") self.EditLabelMarginLeft = self.w * 0.2 self.EditLabelMarginTop = self.h * 0.87 self.line = QLineEdit(self) self.lineMarginLeft = self.w * 0.33 self.lineMarginTop = self.h * 0.85 self.lineWidth = self.w * 0.32 self.lineHeight = self.h * 0.08 # create a push button for add label self.button1 = QPushButton('Add Tag', self) self.button1.clicked.connect(self.Bclick1) self.btnTop = self.h * 0.85 self.btnLeft = self.w * 0.7 self.btnW = self.w * 0.1 self.btnH = self.h * 0.08 # create a push button for save all tags self.button2 = QPushButton('Save All Tags', self) self.button2.clicked.connect(self.Bclick2) self.btnTop2 = self.h * 0.85 self.btnLeft2 = self.w * 0.82 self.btnW2 = self.w * 0.15 self.btnH2 = self.h * 0.08 # create the label for full scree image self.fullabel = QLabel(self) # create a mouse click event to clear focus on input text box self.fullabel.mousePressEvent = self.mclickFull # create a list of labels for 5 thumbnails self.labels = [] for i in range(5): self.labels.append(QLabel(self)) # define mouse click functions to each thumbnail labels self.labels[0].mousePressEvent = self.mclick1 self.labels[1].mousePressEvent = self.mclick2 self.labels[2].mousePressEvent = self.mclick3 self.labels[3].mousePressEvent = self.mclick4 self.labels[4].mousePressEvent = self.mclick5 # initialize sound effect self.sound1 = QSoundEffect() # for arrow key self.sound2 = QSoundEffect() # for < and > self.sound3 = QSoundEffect() # for mouse click # begin the view self.initUI() # a function to resize the window according to user's input def Resize(self, width): if int(width) >= 1200: return 1200 elif int(width) <= 600: return 600 else: return int(width) # initialize the UI def initUI(self): # set up the window self.setWindowTitle(self.title) self.setGeometry(100, 100, self.w, self.h) # set up the full screen label self.fullabel.setGeometry(0, 0, self.w * 0.75, self.h * 0.75) self.fullabel.setStyleSheet("border: " + str(self.b) + "px solid blue;background-color:grey") # set up the edit label for full screen image self.line.move(self.lineMarginLeft, self.lineMarginTop) self.line.resize(self.lineWidth, self.lineHeight) self.EditLabel.move(self.EditLabelMarginLeft, self.EditLabelMarginTop) self.EditLabel.setStyleSheet("font:15px") self.line.clearFocus() # set up the push button for add tag self.button1.setGeometry(self.btnLeft, self.btnTop, self.btnW, self.btnH) # set up the push button for save all tags self.button2.setGeometry(self.btnLeft2, self.btnTop2, self.btnW2, self.btnH2) # set up the thumbnail labels for i in range(5): self.labels[i].setGeometry(self.w1 * 0.45 + self.w1 * i, self.h * 0.4, self.w1, self.h1) self.labels[i].setStyleSheet( "border: " + str(self.b1) + "px solid green;background-color:grey") self.DisplayImg() # a function to rescale the image def RescaleImg(self, pixmap): # rescale for full screen label image if self.mode == 2: if pixmap.size().height() / float( self.h) > pixmap.size().width() / float(self.w): pixmap = pixmap.scaledToHeight( (self.h - 2 * self.b) * self.scaleratio) # rescale according to height else: pixmap = pixmap.scaledToWidth( (self.w - 2 * self.b) * self.scaleratio) # rescale according to width # rescale for thumbnail label image else: if pixmap.size().height() / float( self.h1) > pixmap.size().width() / float(self.w1): pixmap = pixmap.scaledToHeight( self.h1) # rescale according to height else: pixmap = pixmap.scaledToWidth( self.w1) # rescale according to width return pixmap # a function to display the pixmap in full size or in thumbnail list def DisplayImg(self): # determine mode if self.mode == 2: # print("show the full size image") # hide the thumbnail list for i in range(5): self.labels[i].hide() # set up the tag label list for full screen image for tag in self.taglist: tag.hide() self.taglist = [] # clear previous tag list taglen = len(self.model.tags[self.idx % len(self.model.imgs)]) for i in range(taglen): self.taglist.append(QLabel(self)) self.taglist[i].setText( self.model.tags[self.idx % len(self.model.tags)][i]) self.taglist[i].setGeometry(self.tagsLeft, self.tagsTop + i * self.tagsH, self.tagsW, self.tagsH) self.taglist[i].setStyleSheet("font: 20px") self.taglist[i].show() # show the tag label # show the full screen image self.fullabel.show() self.line.show() self.EditLabel.show() self.button1.show() self.button2.show() # rescale the image as needed pixmap = self.RescaleImg(self.model.imgs[self.idx % len(self.model.imgs)]) # load image onto label self.fullabel.setPixmap(pixmap) # apply style to label self.fullabel.setAlignment(Qt.AlignCenter) self.fullabel.setStyleSheet("border: " + str(self.b) + "px solid red;background-color:grey") self.show() else: # hide the full screen image and other tags self.fullabel.hide() self.line.hide() self.EditLabel.hide() self.button1.hide() self.button2.hide() for tag in self.taglist: tag.hide() # show the thumbnails for i in range(5): self.labels[i].show() self.labels[i].setPixmap( self.RescaleImg(self.model.imgs[(self.idx + i) % len(self.model.imgs)])) self.labels[i].setAlignment(Qt.AlignCenter) # print("idx: ", self.idx,"center: ", self.center) # print((self.idx+i) % 5, self.center) if i == self.center: self.labels[i].setStyleSheet( "border: " + str(self.b1) + "px solid red;background-color:grey") else: self.labels[i].setStyleSheet( "border: " + str(self.b1) + "px solid green;background-color:grey") self.show() # add tag button click function, append user input to tag file def Bclick1(self, event): self.model.tags[self.idx % len(self.model.tags)].append( self.line.text()) self.taglist.append(QLabel(self)) self.taglist[len(self.taglist) - 1].setText(self.line.text()) self.DisplayImg() # save tag button click function def Bclick2(self, event): fout = open( self.model.tagpath + self.model.taglist[self.idx % len(self.model.taglist)], 'w') # print(self.model.tags[self.idx % len(self.model.tags)]) for line in self.model.tags[self.idx % len(self.model.tags)]: fout.write(line + '\n') fout.close() # click on the full window image to clear focus on qline def mclickFull(self, event): self.line.clearFocus() def mclick1(self, event): self.ShortSound3() # print("label 1 clicked!!!") self.mode = 2 self.center = 0 self.idx += self.center self.DisplayImg() def mclick2(self, event): # print("label 2 clicked!!!") self.ShortSound3() self.mode = 2 self.center = 1 self.idx += self.center self.DisplayImg() def mclick3(self, event): # print("label 3 clicked!!!") self.ShortSound3() self.mode = 2 self.center = 2 self.idx += self.center self.DisplayImg() def mclick4(self, event): # print("label 4 clicked!!!") self.ShortSound3() self.mode = 2 self.center = 3 self.idx += self.center self.DisplayImg() def mclick5(self, event): # print("label 5 clicked!!!") self.ShortSound3() self.mode = 2 self.center = 4 self.idx += self.center self.DisplayImg() def LeftArrowEvent(self): if self.mode == 1: self.center -= 1 if self.center < 0: self.idx -= 5 self.center = 4 else: self.idx -= 1 self.DisplayImg() def RightArrowEvent(self): if self.mode == 1: self.center += 1 if self.center >= 5: self.idx += 5 self.center = 0 else: self.idx += 1 self.DisplayImg() def DownArrowEvent(self): if self.mode == 1: return # change to thumbnail list self.mode = 1 self.idx -= 2 self.center = 2 self.DisplayImg() def UpArrowEvent(self): if self.mode == 2: return # change to full image self.mode = 2 self.idx += self.center self.DisplayImg() def SmallerThanEvent(self): if self.mode == 2: return self.idx -= 5 self.center = 0 self.DisplayImg() def LargerThanEvent(self): if self.mode == 2: return self.idx += 5 self.center = 0 self.DisplayImg() # a short for arrow keypress event def ShortSound1(self): self.sound1.setSource( QUrl.fromLocalFile( os.path.join('sounds', '191617__dwsd__jhd-bd-35.wav'))) self.sound1.play() # a short sound for < and > key event def ShortSound2(self): self.sound2.setSource( QUrl.fromLocalFile( os.path.join('sounds', '195937__michimuc2__short-wind-noise.wav'))) self.sound2.play() # a short sound for mouse click def ShortSound3(self): self.sound3.setSource( QUrl.fromLocalFile(os.path.join('sounds', 'keyevent2.wav'))) self.sound3.play() def keyPressEvent(self, event): # print(event.key()) # print(event) # print(event.modifiers()) if event.key() == 16777234: # left arrow key self.ShortSound1() self.LeftArrowEvent() elif event.key() == 16777236: # right arrow key self.ShortSound1() self.RightArrowEvent() elif event.key() == 16777237: # down arrow key self.ShortSound1() self.DownArrowEvent() elif event.key() == 16777235: # up arrow key self.ShortSound1() self.UpArrowEvent() elif event.modifiers(): # print(event.key()) if event.key() == 60: # less than key self.ShortSound2() self.SmallerThanEvent() elif event.key() == 62: # greater than key self.ShortSound2() self.LargerThanEvent() else: print("unknown key")
class Window(QWidget): def __init__(self, width, height): super().__init__() self.height = height self.width = width self.index = 0 self.leftBreak = 0 self.rightBreak = 4 self.bigPixList = [] self.pixList = [] self.label = [] self.tagLabels = [] self.bigLabel = QLabel(self) self.bigLabel.resize(self.width * 3 / 4, self.height * 3 / 4) self.bigLabel.move(self.width / 8, self.height / 8) self.bigLabel.hide() #adding buttons and textbox self.textBox = QLineEdit(self) self.textBox.setStyleSheet("color: rgb(255, 255, 255);") self.textBox.move(self.width / 6, self.height * 7 / 8) self.textBox.resize(150, self.height / 16) self.textBox.hide() self.tagButton = QPushButton('Add Tag', self) self.tagButton.setStyleSheet("background-color: rgb(125,125,125);") self.tagButton.move(self.width / 6, self.height * 15 / 16) self.tagButton.clicked.connect(self.tagClick) self.tagButton.hide() self.saveTagButton = QPushButton('Save All Tags', self) self.saveTagButton.setStyleSheet( "background-color: rgb(125, 125, 125);") self.saveTagButton.move(self.width / 6 + 75, self.height * 15 / 16) self.saveTagButton.clicked.connect(self.saveClick) self.saveTagButton.hide() self.setFocus() #item that holds the current string to be stored as tag self.currentString = [] self.mode = 0 #Sets up the warning message for too long strings self.warningMessage = QLabel(self) self.warningMessage.resize(self.width / 5, self.height / 16) self.warningMessage.setStyleSheet( "background-color: red; font: bold 14px") self.warningMessage.setText("String too long") self.warningMessage.move(self.width / 2, self.height * 7 / 8) self.warningMessage.hide() #setting up the sounds to use self.soundClick = QSoundEffect() self.soundClickWah = QSoundEffect() self.soundLoop = QSoundEffect() self.soundLoopWah = QSoundEffect() self.soundShift = QSoundEffect() self.soundShiftWah = QSoundEffect() self.soundClick.setSource( QUrl.fromLocalFile(os.path.join('sounds', 'PianoNote.wav'))) self.soundClickWah.setSource( QUrl.fromLocalFile(os.path.join('sounds', 'PianoNoteWah.wav'))) self.soundShift.setSource( QUrl.fromLocalFile(os.path.join('sounds', 'PianoMultiNote.wav'))) self.soundShiftWah.setSource( QUrl.fromLocalFile(os.path.join('sounds', 'PianoMultiNoteWah.wav'))) self.soundLoop.setSource( QUrl.fromLocalFile(os.path.join('sounds', 'loop08.wav'))) self.soundLoopWah.setSource( QUrl.fromLocalFile(os.path.join('sounds', 'loop08Wah.wav'))) self.soundLoop.setLoopCount(QSoundEffect.Infinite) self.soundLoopWah.setLoopCount(QSoundEffect.Infinite) self.soundLoop.play() self.soundLoopWah.play() self.soundLoopWah.setMuted(1) self.initUI() #Adds the tag to the list triggered by clicking on the button only if the string is less than 11 characters, otherwise shows warning message def tagClick(self): tagValue = self.textBox.text() if (len(tagValue) < 11): self.currentString[self.index % len(self.pixList)] += (tagValue + "\n") self.tagLabels[self.index % len(self.pixList)].setText( self.currentString[self.index % len(self.pixList)]) self.textBox.setText("") self.setFocus() self.warningMessage.hide() else: self.warningMessage.show() def saveClick(self): f = open('SavedTags.txt', 'w') f.truncate() for i in range(0, len(self.pixList), 1): f.write(self.tagLabels[i].text()) f.write("#") def initUI(self): # title of window self.setWindowTitle('PyQt5 Main Window') # place window on screen at x=0, y=0 self.setGeometry(0, 0, self.width, self.height) self.setStyleSheet('background-color: black') #sets up QLabels for later input for i in range(0, 5, 1): self.label.append(QLabel(self)) self.label[i].move(self.width / 12 + i * self.width / 6, self.height / 3) self.label[i].resize(self.width / 6, self.height / 6) self.label[i].setStyleSheet('background-color: red') if (i == 0): self.label[i].setStyleSheet('background-color: blue') #places pictures into pixmap array i = 0 for file in os.listdir('data'): self.pixList.append(QPixmap(os.path.join('data', file))) self.bigPixList.append(QPixmap(os.path.join('data', file))) self.tagLabels.append(QLabel(self)) self.currentString.append("") self.tagLabels[i].resize(self.width / 8, self.height) self.tagLabels[i].move(self.width * 7 / 8, 0) self.tagLabels[i].setStyleSheet( 'border-color: grey; border-style: outset; border-width: 5px; font: bold 14px; color: white' ) self.tagLabels[i].setAlignment(Qt.AlignTop) self.tagLabels[i].hide() if (self.pixList[i].height() > self.height / 6 - 10): self.pixList[i] = self.pixList[i].scaledToHeight(self.height / 6 - 10) if (self.pixList[i].width() > self.width / 6 - 10): self.pixList[i] = self.pixList[i].scaledToWidth(self.width / 6 - 10) if (self.bigPixList[i].width() > self.width * 3 / 4): self.bigPixList[i] = self.bigPixList[i].scaledToWidth( self.width * 3 / 4) if (self.bigPixList[i].height() > self.height * 3 / 4): self.bigPixList[i] = self.bigPixList[i].scaledToHeight( self.height * 3 / 4) i = i + 1 self.bigLabel.setAlignment(Qt.AlignCenter) self.bigLabel.setPixmap(self.bigPixList[0]) #puts initial pixmaps into the designated qlabels for i in range(0, 5, 1): self.label[i].setPixmap(self.pixList[i]) self.label[i].setAlignment(Qt.AlignCenter) self.show() self.loadTags() def loadTags(self): f = open('SavedTags.txt', 'r') tempString = f.read() j = 0 for i in range(0, len(tempString), 1): if (tempString[i] != "#"): self.currentString[j] += tempString[i] else: self.tagLabels[j].setText(self.currentString[j]) j = j + 1 #Moves the pointer to the picture one to the left. If it breaks the bounds, it will move the frame def moveIndexLeft(self): j = 0 if (self.mode == 1): self.tagLabels[self.index % len(self.pixList)].hide() self.tagLabels[(self.index - 1) % len(self.pixList)].show() self.label[self.index % 5].setStyleSheet('background-color:red') self.index = self.index - 1 if (self.index < self.leftBreak): self.leftBreak = self.leftBreak - 5 self.rightBreak = self.rightBreak - 5 for i in range(self.leftBreak, 1 + self.rightBreak, 1): self.label[j].setPixmap(self.pixList[i % len(self.pixList)]) self.label[j].setAlignment(Qt.AlignCenter) j = j + 1 self.label[self.index % 5].setStyleSheet('background-color: blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) self.textBox.setText("") #Moves the pointer one picture to the right. If it breaks the bounds of QLabel it will move the frame def moveIndexRight(self): j = 0 if (self.mode == 1): self.tagLabels[self.index % len(self.pixList)].hide() self.tagLabels[(self.index + 1) % len(self.pixList)].show() self.label[self.index % 5].setStyleSheet('background-color: red') self.index = self.index + 1 if (self.index > self.rightBreak): self.leftBreak = self.leftBreak + 5 self.rightBreak = self.rightBreak + 5 for i in range(self.leftBreak, 1 + self.rightBreak, 1): self.label[j].setPixmap(self.pixList[i % len(self.pixList)]) self.label[j].setAlignment(Qt.AlignCenter) j = j + 1 self.label[self.index % 5].setStyleSheet('background-color: blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) self.textBox.setText("") #Zooms in on the specific picture selected and puts it into a 700 x 500 frame def zoomIn(self): self.mode = 1 for i in range(0, 5, 1): self.label[i].hide() self.bigLabel.setAlignment(Qt.AlignCenter) self.bigLabel.show() self.tagButton.show() self.saveTagButton.show() self.textBox.show() self.tagLabels[self.index % len(self.pixList)].show() #Goes back to default view def zoomOut(self): self.mode = 0 self.bigLabel.hide() for i in range(0, 5, 1): self.label[i].show() self.tagButton.hide() self.saveTagButton.hide() self.textBox.hide() self.tagLabels[self.index % len(self.pixList)].hide() #shifts the frame 5 pictures to the left def shiftLeft(self): if (self.mode == 1): self.tagLabels[self.index % len(self.pixList)].hide() self.label[self.index % 5].setStyleSheet('background-color:red') j = 0 self.index = self.leftBreak - 1 if (self.mode == 1): self.tagLabels[self.index % len(self.pixList)].show() self.leftBreak = self.leftBreak - 5 self.rightBreak = self.rightBreak - 5 for i in range(self.leftBreak, 1 + self.rightBreak, 1): self.label[j].setPixmap(self.pixList[i % len(self.pixList)]) j = j + 1 self.label[self.index % 5].setStyleSheet('background-color: blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) self.textBox.setText("") #shifts the frame 5 pictures to the right def shiftRight(self): if (self.mode == 1): self.tagLabels[self.index % len(self.pixList)].hide() self.label[self.index % 5].setStyleSheet('background-color: red') j = 0 self.index = self.rightBreak + 1 if (self.mode == 1): self.tagLabels[self.index % len(self.pixList)].show() self.rightBreak = self.rightBreak + 5 self.leftBreak = self.leftBreak + 5 for i in range(self.leftBreak, 1 + self.rightBreak, 1): self.label[j].setPixmap(self.pixList[i % len(self.pixList)]) j = j + 1 self.label[self.index % 5].setStyleSheet('background-color: blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) self.textBox.setText("") #all of the key inputs and their responses in functions def keyPressEvent(self, event): if (event.key() == 16777234): self.moveIndexLeft() if (self.mode == 0): self.soundClick.play() else: self.soundClickWah.play() if (event.key() == 16777236): self.moveIndexRight() if (self.mode == 0): self.soundClick.play() else: self.soundClickWah.play() if (event.key() == 16777235): self.zoomIn() self.soundLoop.setMuted(1) self.soundLoopWah.setMuted(0) if (event.key() == 16777237): self.zoomOut() self.soundLoopWah.setMuted(1) self.soundLoop.setMuted(0) if (event.key() == 44): self.shiftLeft() if (self.mode == 0): self.soundShift.play() else: self.soundShiftWah.play() if (event.key() == 46): self.shiftRight() if (self.mode == 0): self.soundShift.play() else: self.soundShiftWah.play() def mousePressEvent(self, QMouseEvent): if (QMouseEvent.y() < self.height / 7 * 8 or QMouseEvent.y() > self.height / 15 * 16 and QMouseEvent.x() < self.width / 6 or QMouseEvent.x() > self.width / 3): self.setFocus() if (self.mode == 0): setPicTo = -1 if (QMouseEvent.y() > self.height / 3 - 1 and QMouseEvent.y() < self.height / 2 + 1): if (QMouseEvent.x() > self.width / 12 and QMouseEvent.x() < self.width * 3 / 12 + 1): setPicTo = 0 if (QMouseEvent.x() > self.width * 3 / 12 and QMouseEvent.x() < self.width * 5 / 12 + 1): setPicTo = 1 if (QMouseEvent.x() > self.width * 5 / 12 and QMouseEvent.x() < self.width * 7 / 12 + 1): setPicTo = 2 if (QMouseEvent.x() > self.width * 7 / 12 and QMouseEvent.x() < self.width * 9 / 12 + 1): setPicTo = 3 if (QMouseEvent.x() > self.width * 9 / 12 and QMouseEvent.x() < self.width * 11 / 12 + 1): setPicTo = 4 if (setPicTo > -1): self.label[self.index % 5].setStyleSheet('background-color:red') self.mode = 1 self.index = self.leftBreak + setPicTo self.label[self.index % 5].setStyleSheet('background-color:blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) for i in range(0, 5, 1): self.label[i].hide() self.bigLabel.setAlignment(Qt.AlignCenter) self.bigLabel.show()
class VArcMain(QWidget): def __init__(self): global bgm, wheel_anims super().__init__() # Controls self.up = [] self.down = [] self.left = [] self.right = [] self.select = [] self.labels = [] # Wheel/Game List self.wheel = None self.center = None self.splash = None wheel_anims = QParallelAnimationGroup() self.games = populate_games() # Media self.click = QSoundEffect() self.click.setSource(QUrl.fromLocalFile(config['audio_path'] + 'wheelSFX.wav')) bgm = QMediaPlayer(self) bgm.setMedia(QMediaContent(QUrl.fromLocalFile(config['audio_path'] + 'bgm.mp3'))) bgm.setVolume(30) bgm.play() # Startup read_conf() self.read_keys() if config['flip_scrolling'] == 'True': self.up, self.down = self.down, self.up self.init_ui() def init_ui(self): global v_player, cur_game, config, top_pos, bot_pos, wheel_anims backgrounds = [] for file in os.listdir(config['image_path'] + 'background/'): if config['gif_bg'] == 'True': if file.endswith(".gif"): backgrounds.append(file) elif file.endswith(('.png', '.jpg')): backgrounds.append(file) bg_mov = QMovie(config['image_path'] + 'background/' + random.choice(backgrounds)) bg_mov.setScaledSize(QSize(1920, 1080)) bg = QLabel(self) bg.setMovie(bg_mov) bg_mov.start() h_box = QHBoxLayout(bg) v_box = QVBoxLayout(bg) self.wheel = v_box h_box.addLayout(v_box) h_box.addStretch(1) v_player = VideoPlayer(640, 480) v_player.setFixedSize(640, 480) v_player.setEnabled(0) self.splash = QLabel() v_container = QVBoxLayout() v_container.addStretch(1) v_container.addWidget(self.splash, alignment=Qt.AlignCenter) v_container.addWidget(v_player, alignment=Qt.AlignAbsolute) v_container.addStretch(1) h_box.addLayout(v_container) h_box.addStretch(1) w_labels = [] for a, x in enumerate(self.games): lbl = QLabel(self) lbl.hide() lbl.setFixedSize(400, 175) self.labels.append(lbl) if a < 5: if a == 2: cur_game = [x, 2] self.center = lbl self.splash.setStyleSheet('color: white; font-size: 24pt;') self.splash.setText(x.display + ' - ' + x.emu_info) v_player.load(x.name + '.mp4') v_player.play() lbl.show() v_box.addWidget(lbl) lbl.setFocus() w_label = QLabel(self) anim = WheelAnimation(w_label, b'pos', lbl) w_labels.append((w_label, lbl)) wheel_anims.addAnimation(anim) anim.setEasingCurve(QEasingCurve.OutQuad) anim.setDuration(100) if os.path.isfile(config['image_path'] + x.name + '.png'): w_label.setPixmap(QPixmap(config['image_path'] + x.name + '.png') .scaled(400, 175, Qt.IgnoreAspectRatio)) else: w_label.setStyleSheet('color: white; font-size 36pt;') w_label.setText(x.display) self.setWindowTitle('VArc') self.showFullScreen() top_pos = QPoint(10, -400) bot_pos = QPoint(10, 1480) for a in w_labels: pos = a[1].pos() if pos.x() is not 0: if a[1] == self.center: a[0].move(pos.x() + 30, pos.y()) else: a[0].move(pos) else: a[0].hide() def keyPressEvent(self, e): if e.key() in self.down: self.move_wheel(False) try_preview() elif e.key() in self.up: self.move_wheel(True) try_preview() elif e.key() in self.select: start_game() elif e.key() in self.left: print('Going left!') elif e.key() in self.right: print('Going right!') def move_wheel(self, up: bool): global cur_game self.click.play() layout = self.wheel if up: to_show = self.labels[5] to_show.show() to_remove = layout.itemAt(0).widget() to_remove.hide() layout.removeWidget(to_remove) layout.addWidget(to_show) self.labels.append(self.labels.pop(0)) cur_game[1] = (cur_game[1] + 1) % len(self.games) cur_game[0] = self.games[cur_game[1]] self.center = layout.itemAt(3).widget() else: to_show = self.labels.pop() to_show.show() to_remove = layout.itemAt(4).widget() to_remove.hide() layout.removeWidget(to_remove) layout.insertWidget(0, to_show) self.labels.insert(0, to_show) cur_game[1] = (cur_game[1] - 1) % len(self.games) cur_game[0] = self.games[cur_game[1]] self.center = layout.itemAt(2).widget() QApplication.instance().processEvents() self.anim_wheel(up) self.splash.setText(cur_game[0].display + ' - ' + cur_game[0].emu_info) self.center.resize(self.center.width() + 2000, self.center.height() + 2000) def anim_wheel(self, up: bool): global top_pos, bot_pos, wheel_anims for a in range(wheel_anims.animationCount()): anim = wheel_anims.animationAt(a) if anim.shadow_lbl.isVisible(): pos = anim.shadow_lbl.pos() if anim.shadow_lbl == self.center: pos.setX(pos.x() + 120) anim.targetObject().show() anim.setDuration(100) anim.setEndValue(pos) else: anim.targetObject().hide() if up: anim.setEndValue(bot_pos) anim.setDuration(0) anim.targetObject().move(bot_pos) else: anim.setEndValue(top_pos) anim.setDuration(0) anim.targetObject().move(top_pos) wheel_anims.start(QAbstractAnimation.KeepWhenStopped) def read_keys(self): root = elTree.parse('keybinds.xml').getroot() for bind in root: key = bind.find('key').text try: value = eval('Qt.' + bind.find('value').text) except AttributeError: print('Invalid keybind: ' + bind.find('value').text) value = None if value is not None: if key == 'Up': self.up.append(value) elif key == 'Down': self.down.append(value) elif key == 'Left': self.left.append(value) elif key == 'Right': self.right.append(value) elif key == 'Select': self.select.append(value)
def paintEvent(self, event): painter = QPainter(self) if self.show_menu: painter.setFont(QFont("Times", 50)) painter.drawText(50, 50, "Welcome to my maze!") painter.setFont(QFont("Times", 20)) painter.drawRoundedRect(30, 80, 25, 25, 5, 5) painter.drawText(33, 100, "W") painter.drawRoundedRect(5, 105, 25, 25, 5, 5) painter.drawText(10, 125, "A") painter.drawRoundedRect(30, 105, 25, 25, 5, 5) painter.drawText(35, 125, "S") painter.drawRoundedRect(55, 105, 25, 25, 5, 5) painter.drawText(60, 125, "D") painter.drawText(100, 125, "Move your character with the WASD keys") painter.drawRoundedRect(10, 155, 60, 20, 5, 5) painter.drawText(75, 170, "Toggle flight by pressing the spacebar") painter.setPen(Qt.yellow) painter.setBrush(Qt.yellow) painter.drawEllipse(400, 150, 30, 30) painter.setPen(Qt.black) painter.setBrush(Qt.black) painter.drawEllipse(410, 155, 5, 5) painter.drawEllipse(420, 155, 5, 5) painter.drawArc(415, 165, 6, 4, 180 * 16, 180 * 16) painter.setPen(Qt.yellow) painter.setBrush(Qt.yellow) painter.drawEllipse(470, 150, 35, 35) painter.setPen(Qt.black) painter.setBrush(Qt.black) painter.drawEllipse(480, 155, 5, 5) painter.drawEllipse(490, 155, 5, 5) painter.drawEllipse(485, 165, 6, 4) painter.drawLine(435, 155, 465, 155) painter.drawLine(465, 155, 455, 145) painter.drawLine(465, 155, 455, 165) painter.drawLine(465, 175, 435, 175) painter.drawLine(435, 175, 445, 165) painter.drawLine(435, 175, 445, 185) # draw the smiley face guy painter.drawText(75, 220, "You can walk under green walls") painter.setPen(QPen(Qt.green, 4, Qt.SolidLine)) painter.drawLine(60, 195, 60, 235) painter.setPen(Qt.black) painter.drawText(75, 270, "You can fly under blue walls") painter.setPen(QPen(Qt.blue, 4, Qt.SolidLine)) painter.drawLine(60, 245, 60, 285) painter.setPen(Qt.black) painter.drawText( 75, 320, "Press 0 if you're stuck. It'll show you what path to take :-)" ) painter.drawText( 75, 360, "Alternatively, press 9 if you want to see how the path is found!" ) painter.setFont(QFont("Times", 10)) painter.drawText( 75, 380, "(Although some might call this cheating! This will also reset your points to 0)" ) painter.setPen(Qt.red) painter.setFont(QFont("Times", 20)) if not self.challenge_mode: painter.drawText( 75, 410, "Press 'C' to play in challenge mode!! (Includes zombies)") else: painter.drawText( 75, 410, "Scared? Press 'C' again to not play in challenge mode :-)" ) painter.setPen(Qt.black) painter.drawText( 75, 440, f"Maze size is currently {self.grid.get_width()} by {self.grid.get_height()}." ) painter.drawText(75, 470, "Press the + and - buttons to change the size,") painter.drawText( 75, 490, "or press I for a custom input and U for a random input") if not self.show_animation: painter.drawText( 75, 520, "Press the enter key to show the maze's animation") painter.drawText(75, 550, "(this might take a while)") else: painter.drawText(75, 520, "Animation toggled on!") painter.drawText( 75, 550, "Press the enter key to remove the maze's animation") painter.drawText(75, 590, "Left click to start the game") painter.drawText(75, 620, "Press F to read a file of your choice") painter.setFont(QFont("Times", 10)) painter.drawText( 75, 630, "Make sure you have saved it in the right directory!") else: painter.setPen(Qt.black) if not self.challenge_mode: painter.setFont(QFont("Times", 18)) painter.drawText( 75, 530, f"Press R at anytime to save your progress onto a file!") if self.file_successful: painter.setFont(QFont("Times", 10)) painter.drawText(75, 540, f"File saved successfully!") if self.msg == "": painter.setFont(QFont("Times", 14)) painter.drawText(75, 555, f"Current points: {self.points}") else: painter.drawText(75, 550, f"{self.msg}") painter.setFont(QFont("Times", 14)) if not self.msg.endswith("Did you type it in correctly?"): #painter.drawText(75, 570, "(Please note that we do not check whether or not " # "mazes from files are possible to complete)") painter.drawText(75, 590, f"Current points: {self.points}") else: painter.drawText(75, 570, f"Current points: {self.points}") painter.drawText( 75, 610, f"Lost? Press 0 to find the way to the goal! (resets points to 0)" ) painter.drawText( 75, 630, f"If you want to see how a recursive search " f"algorithm finds the route to the goal, press 9!") else: painter.drawText( 75, 550, f"No saving or finding solutions in challenge mode! Sorry!" ) s = self.square_size # The following code looks janky becuase drawing on PyQt is a pain if self.challenge_mode and self.maze_done: if any(self.player_is_on_square == i for i in self.zombie_positions) or any( self.player_is_on_square == i for i in self.previous_zombie_positions): painter.setFont(QFont("Times", 34)) painter.drawText(50, 300, "you died!") self.player_is_dead = True else: def draw_zombie(paintr, pos): painter.setBrush(Qt.green) painter.setPen(Qt.black) paintr.drawEllipse(pos[0] * s + 12, pos[1] * s + 12, s / 1.2, s / 1.2) painter.setBrush(Qt.black) painter.drawEllipse(pos[0] * s + 12, pos[1] * s + (s / 3.5) + 12, s / 5, s / 5) painter.drawEllipse(pos[0] * s + (s / 3.5) + 12, pos[1] * s + (s / 3.5) + 12, s / 5, s / 5) painter.drawLine(12 + pos[0] * s + s / 4, 12 + pos[1] * s + s / 3, 12 + pos[0] * s + s / 2.5, 12 + pos[1] * s + s / 6) painter.drawLine(12 + pos[0] * s + s / 10, 12 + pos[1] * s + s / 6, 12 + pos[0] * s + s / 4.5, 12 + pos[1] * s + s / 3) painter.setPen(Qt.white) painter.setBrush(Qt.white) painter.drawEllipse(pos[0] * s + 12, pos[1] * s + (s / 1.7) + 12, s / 3, s / 4) painter.setPen(Qt.black) painter.drawLine(pos[0] * s + 12 + s / 20, pos[1] * s + (s / 1.7) + 12 + s / 20, pos[0] * s + 12 + s / 10, pos[1] * s + (s / 1.7) + 12 + s / 10) painter.drawLine(pos[0] * s + 12 + s / 10, pos[1] * s + (s / 1.7) + 12 + s / 10, pos[0] * s + 12 + s / 8, pos[1] * s + (s / 1.7) + 12) for i in range(len(self.zombie_positions)): draw_zombie(painter, self.zombie_positions[i]) self.previous_zombie_positions = self.zombie_positions def get_next_zombie_square(current_square): ret, ignore = solve_maze(self.grid, self.walls, current_square, self.player_is_on_square) return ret[1][::-1] self.zombie_positions = [ get_next_zombie_square(i) for i in self.zombie_positions ] painter.setBrush(Qt.white) painter.setPen(Qt.black) def draw_key(pos, colour): painter.setBrush(colour) painter.drawEllipse(pos[0] * s + 12 + s / 3, pos[1] * s + 12, s / 2.5, s / 2.5) painter.drawRect(pos[0] * s + 12 + s / 2.2, pos[1] * s + 12 + s / 2.6, s / 8, s / 3) painter.drawRect(pos[0] * s + 12 + s / 3, pos[1] * s + 12 + s / 2.2, s / 8, s / 15) painter.drawRect(pos[0] * s + 12 + s / 3, pos[1] * s + 12 + s / 1.7, s / 8, s / 15) painter.setBrush(Qt.white) painter.drawEllipse(pos[0] * s + 12 + s / 2.1, pos[1] * s + 12 + s / 20, s / 8, s / 8) if self.challenge_mode: if self.player_is_on_square == self.challenge_key[::-1]: self.challenge_mode_key_found = True if not self.challenge_mode_key_found: draw_key(self.challenge_key[::-1], Qt.yellow) if not self.maze_done: for i in range(len(self.grid.get_grid())): for j in range(len(self.grid.get_grid()[i])): if not self.grid.get_grid()[i][j].get_active(): color = QColor(220, 220, 220) painter.setBrush(color) painter.setPen(color) painter.drawRect(i * s + 11, j * s + 11, s, s) painter.setPen(QPen(QColor(150, 120, 150), 3, Qt.SolidLine)) painter.drawRect(self.the_chosen_one[1] * s + 10, self.the_chosen_one[0] * s + 10, s, s) # sleep(1 / (self.x_squares + self.y_squares)) painter.setPen(Qt.black) painter.setBrush(Qt.white) horizontal_walls = self.walls.get_horizontal() vertical_walls = self.walls.get_vertical() for i in range(len(horizontal_walls)): for j in range(len(horizontal_walls[i])): if horizontal_walls[i][j].get_activity(): if horizontal_walls[i][j].get_activity() == 3: if max(self.x_squares, self.y_squares) <= 15: painter.setPen(QPen(Qt.green, 2, Qt.SolidLine)) else: painter.setPen(Qt.green) painter.drawLine(i * s + 10, j * s + 10, i * s + 10, (j + 1) * s + 10) painter.setPen(QPen(Qt.black, 1, Qt.SolidLine)) elif horizontal_walls[i][j].get_activity() == 2: if max(self.x_squares, self.y_squares) <= 15: painter.setPen(QPen(Qt.blue, 2, Qt.SolidLine)) else: painter.setPen(Qt.blue) painter.drawLine(i * s + 10, j * s + 10, i * s + 10, (j + 1) * s + 10) painter.setPen(QPen(Qt.black, 1, Qt.SolidLine)) else: painter.drawLine(i * s + 10, j * s + 10, i * s + 10, (j + 1) * s + 10) for i in range(len(vertical_walls)): for j in range(len(vertical_walls[i])): if vertical_walls[i][j].get_activity(): if vertical_walls[i][j].get_activity() == 3: if max(self.x_squares, self.y_squares) <= 15: painter.setPen(QPen(Qt.green, 2, Qt.SolidLine)) else: painter.setPen(Qt.green) painter.drawLine(i * s + 10, j * s + 10, (i + 1) * s + 10, j * s + 10) painter.setPen(QPen(Qt.black, 1, Qt.SolidLine)) elif vertical_walls[i][j].get_activity() == 2: if max(self.x_squares, self.y_squares) <= 15: painter.setPen(QPen(Qt.blue, 2, Qt.SolidLine)) else: painter.setPen(Qt.blue) painter.drawLine(i * s + 10, j * s + 10, (i + 1) * s + 10, j * s + 10) painter.setPen(QPen(Qt.black, 1, Qt.SolidLine)) else: painter.drawLine(i * s + 10, j * s + 10, (i + 1) * s + 10, j * s + 10) # Draw walls, some with blue and some with green colors # yeah it's kinda ugly self.goal_is_on_square = self.get_goal_square() if self.goal_is_on_square != [-1, -1]: painter.setPen(QPen(Qt.red, 2, Qt.SolidLine)) painter.setBrush(Qt.white) goal_x = self.goal_is_on_square[0] goal_y = self.goal_is_on_square[1] painter.drawRect(goal_x * s + 12, goal_y * s + 12, s / 1.2, s / 1.2) if self.challenge_mode and not self.challenge_mode_key_found: painter.setBrush(Qt.gray) painter.setPen(QPen(Qt.red, 1, Qt.SolidLine)) painter.drawRect(goal_x * s + 12, goal_y * s + 12, s / 1.2, s / 1.2) # to get a grey square draw_key(self.goal_is_on_square, Qt.black) player_x = self.player_is_on_square[0] player_y = self.player_is_on_square[1] if not self.player_is_dead: if self.player_is_on_ground: painter.setPen(Qt.yellow) painter.setBrush(Qt.yellow) painter.drawEllipse(player_x * s + 12, player_y * s + 12, s / 1.2, s / 1.2) painter.setPen(Qt.black) painter.setBrush(Qt.black) painter.drawEllipse(player_x * s + (s / 2.7) + 12, player_y * s + (s / 4) + 12, s / 6, s / 6) painter.drawEllipse(player_x * s + (s / 1.6) + 12, player_y * s + (s / 4) + 12, s / 6, s / 6) painter.drawArc(player_x * s + (s / 2.7) + 12, player_y * s + (s / 2) + 12, s / 4, s / 6, 180 * 16, 180 * 16) else: painter.setPen(Qt.yellow) painter.setBrush(Qt.yellow) painter.drawEllipse(player_x * s + 12, player_y * s + 12, s, s) painter.setPen(Qt.black) painter.setBrush(Qt.black) painter.drawEllipse(player_x * s + (s / 2.7) + 12, player_y * s + (s / 3.5) + 12, s / 5, s / 5) painter.drawEllipse(player_x * s + (s / 1.6) + 12, player_y * s + (s / 3.5) + 12, s / 5, s / 5) painter.drawEllipse(player_x * s + (s / 2.6) + 12, player_y * s + (s / 1.5) + 12, s / 3.5, s / 5) # mouth open vs mouth closes (space bar animation) else: painter.setPen(QColor(150, 190, 50)) painter.setBrush(QColor(150, 190, 50)) painter.drawEllipse(player_x * s + 12, player_y * s + 12, s / 1.2, s / 1.2) painter.setPen(Qt.black) painter.setBrush(Qt.black) painter.drawEllipse(player_x * s + (s / 2.7) + 12, player_y * s + (s / 4) + 12, s / 6, s / 6) painter.drawEllipse(player_x * s + (s / 1.6) + 12, player_y * s + (s / 4) + 12, s / 6, s / 6) painter.drawArc(player_x * s + (s / 2.7) + 12, player_y * s + (s / 2) + 12, s / 4, s / 6, 0, 180 * 16) # dead player after zombie eats it # Yes, i should really be working more with percentages here. Yes, the +12 is also # HORRIBLE coding practice. Please forgive me. I'll try to fix this later if self.show_animation and not self.maze_done: self.grid, self.walls, self.maze_done, self._grid_inactive_neighbours, self.the_chosen_one = \ maze.construct_maze(self.grid, self.walls, self._grid_inactive_neighbours, self.show_animation, self.player_is_on_square) self.goal_is_on_square = self.get_goal_square() if self.maze_done: self.my_maze_solution = solve_maze( self.grid, self.walls, self.player_is_on_square, self.goal_is_on_square) self.points = len(self.my_maze_solution) + 22 self.update() if self.display_solution: def draw_solution(route): prev = route[0] for square in route: painter.drawLine(prev[1] * s + 10 + s / 2, prev[0] * s + 10 + s / 2, square[1] * s + 10 + s / 2, square[0] * s + 10 + s / 2) prev = square painter.setPen(Qt.red) if len( self.all_answer_routes ) > self.count + 1: # draw the routes taken to find answer, if animation is toggled draw_solution(self.all_answer_routes[self.count]) self.count += 1 self.update() else: draw_solution(self.my_maze_solution) painter.setPen(Qt.black) if self.player_is_on_square == self.goal_is_on_square: self.allow_movement = False explosion = QSoundEffect() explosion.setSource( QUrl("explosion.wav" )) # TODO: fix sound not playing (needs a loop?) explosion.play() painter.setOpacity(0.7) for i in range(100): # draw the "explosion" at the end painter.setBrush( choice([Qt.red, Qt.yellow, Qt.darkRed, Qt.white])) s = randint(2, 250) painter.drawEllipse(randint(0, 400), randint(0, 400), s, s) painter.setPen(Qt.black) painter.setOpacity(1) painter.setFont(QFont("Times", 65)) painter.drawText(150, 270, "You won!") if not self.challenge_mode: painter.drawText(50, 350, f"Your points: {self.points}") if self.points >= 20: painter.setFont(QFont("Times", 35)) painter.drawText(50, 400, "You are a true master of mazes!") elif self.points >= 18: painter.drawText(50, 400, "Well done!") elif self.points > 0: painter.drawText(50, 400, "Good try!") else: if not self.display_solution: painter.setFont(QFont("Times", 25)) painter.drawText( 50, 400, "Everyone solves mazes at their own pace :)") else: painter.drawText(50, 400, "I saw you cheat!")
def on_btnEffect_Resource_clicked(self): url = QUrl.fromLocalFile(":/Wave/sound/blast.wav") player = QSoundEffect(self) player.setLoopCount(2) player.setSource(url) player.play() #无法播放资源文件
def on_btnEffect_File_clicked(self): url = QUrl.fromLocalFile("Ak47.wav") player = QSoundEffect(self) player.setLoopCount(2) #播放循环次数 player.setSource(url) #设置源文件 player.play()
class Window(QWidget): def __init__(self,width,height): super().__init__() self.height = height self.width = width #index for the navigation self.index = 0 #index for changing the color of the selected image self.colorIndex = 0 #determines when to load new images self.leftBreak = 0 self.rightBreak = 4 #large zoomed in image list self.bigPixList = [] #thumbnail image list self.pixList = [] #labels to store thumbnails self.label = [] #labels to store tags self.tagLabels = [] #big label for zoomed in image self.bigLabel = QLabel(self) self.bigLabel.resize(self.width * 3 / 4, self.height * 3 / 4) self.bigLabel.move(self.width / 8, self.height / 8) self.bigLabel.hide() #for saving all of the search images self.saveURL = "" #adding buttons and textbox self.textBox = QLineEdit(self) self.textBox.setStyleSheet("color: rgb(255, 255, 255);") self.textBox.move(self.width / 6, self.height * 7 / 8) self.textBox.resize(150,self.height / 16) self.textBox.hide() self.tagButton = QPushButton('Add Tag', self) self.tagButton.setStyleSheet("background-color: rgb(125,125,125);") self.tagButton.move(self.width / 6, self.height * 15 / 16) self.tagButton.clicked.connect(self.tagClick) self.tagButton.hide() self.saveTagButton = QPushButton('Save All Tags', self) self.saveTagButton.setStyleSheet("background-color: rgb(125, 125, 125);") self.saveTagButton.move(self.width / 6 + 75, self.height * 15 / 16) self.saveTagButton.clicked.connect(self.saveTagClick) self.saveTagButton.hide() self.searchBar = QLineEdit(self) self.searchBar.setStyleSheet("color: rgb(255, 255,255);") self.searchBar.move(self.width/6, self.height * 7 / 8) self.searchBar.resize(300, self.height / 16) self.setFocus() self.testButton = QPushButton('Test', self) self.testButton.setStyleSheet("background-color: rgb(125, 125, 125);") self.testButton.move(self.width / 6, self.height * 15 / 16) self.testButton.clicked.connect(self.testClick) self.saveButton = QPushButton('Save', self) self.saveButton.setStyleSheet("background-color: rgb(125, 125, 125);") self.saveButton.move(self.width / 6 + 75, self.height * 15 / 16) self.saveButton.clicked.connect(self.saveClick) self.exitButton = QPushButton('Exit',self) self.exitButton.setStyleSheet("background-color: rgb(125, 125, 125);") self.exitButton.move(self.width / 6 + 150, self.height * 15 / 16) self.exitButton.clicked.connect(self.exitClick) self.deleteButton = QPushButton('Delete', self) self.deleteButton.setStyleSheet("background-color: rgb(125, 125, 125);") self.deleteButton.move(self.width / 6 + 225, self.height * 15 / 16) self.deleteButton.clicked.connect(self.deleteClick) self.searchButton = QPushButton('Search', self) self.searchButton.setStyleSheet("background-color: rgb(125, 125, 125);") self.searchButton.clicked.connect(self.searchClick) self.searchButton.move(self.width/6 +325, self.height * 29 / 32) self.searchResults = QLineEdit(self) self.searchResults.setStyleSheet("background-color: rgb(255, 255, 255);") self.searchResults.resize(25, self. height / 16) self.searchResults.move(self.width/6 + 425, self.height * 29 / 32) self.searchResults.setText("10") self.searchText = QLabel(self) self.searchText.resize(150, 50) self.searchText.move(self.width/6 + 455, self.height * 29 / 32) self.searchText.setText("Max Search Results") self.searchText.setStyleSheet("color: rgb(255, 255, 255);") #item that holds the current string to be stored as tag self.currentString = [] self.mode = 0 #Sets up the warning message for too long strings self.warningMessage = QLabel(self) self.warningMessage.resize(self.width / 5, self.height / 16) self.warningMessage.setStyleSheet("background-color: red; font: bold 14px") self.warningMessage.setText("String too long") self.warningMessage.move(self.width / 2, self.height * 7 / 8) self.warningMessage.hide() #setting up the sounds to use self.soundClick = QSoundEffect() self.soundClickWah = QSoundEffect() self.soundLoop = QSoundEffect() self.soundLoopWah = QSoundEffect() self.soundShift = QSoundEffect() self.soundShiftWah = QSoundEffect() self.soundClick.setSource(QUrl.fromLocalFile(os.path.join('sounds','PianoNote.wav'))) self.soundClickWah.setSource(QUrl.fromLocalFile(os.path.join('sounds','PianoNoteWah.wav'))) self.soundShift.setSource(QUrl.fromLocalFile(os.path.join('sounds','PianoMultiNote.wav'))) self.soundShiftWah.setSource(QUrl.fromLocalFile(os.path.join('sounds','PianoMultiNoteWah.wav'))) self.soundLoop.setSource(QUrl.fromLocalFile(os.path.join('sounds','loop08.wav'))) self.soundLoopWah.setSource(QUrl.fromLocalFile(os.path.join('sounds','loop08Wah.wav'))) self.soundLoop.setLoopCount(QSoundEffect.Infinite) self.soundLoopWah.setLoopCount(QSoundEffect.Infinite) self.soundLoop.play() self.soundLoopWah.play() self.soundLoopWah.setMuted(1) self.initUI() #Adds the tag to the list triggered by clicking on the button only if the string is less than 11 characters, otherwise shows warning message def tagClick(self): tagValue = self.textBox.text() if(len(tagValue) < 11): self.currentString[self.index % len(self.pixList)] += (tagValue + "\n") self.tagLabels[self.index % len(self.pixList)].setText(self.currentString[self.index % len(self.pixList)]) self.textBox.setText("") self.setFocus() self.warningMessage.hide() else: self.warningMessage.show() def saveTagClick(self): f = open('SavedTags.txt','w') f.truncate() for i in range(0, len(self.pixList), 1): f.write(self.tagLabels[i].text()) f.write("#") self.setFocus() #takes a URL entered into the search bar and adds an image to the two pixmap lists. It also appends the URL onto the saved URLs string if the user wants to save them later def testClick(self): path = self.searchBar.text() self.searchBar.setText("") self.saveURL = self.saveURL + path + "\n" url_data = urllib.request.urlopen(path).read() tmpPixmap = QPixmap() tmpPixmap.loadFromData(url_data) if(tmpPixmap.height() > self.height * 3 / 4): tmpPixmap = tmpPixmap.scaledToHeight(self.height * 3 / 4) if(tmpPixmap.width() > self.width * 3 / 4): tmpPixmap = tmpPixmap.scaledToWidth(self.width * 3 / 4) self.bigPixList.append(tmpPixmap) if(tmpPixmap.height() > self.height / 6 - 10): tmpPixmap = tmpPixmap.scaledToHeight(self.height / 6 - 10) if(tmpPixmap.width() > self.width / 6 - 10): tmpPixmap = tmpPixmap.scaledToWidth(self.width / 6 - 10) self.pixList.append(tmpPixmap) for i in range(-1,4,1): self.label[i + 1].setPixmap(self.pixList[i % len(self.pixList)]) self.label[self.colorIndex].setStyleSheet('background-color: red') self.index = -1 self.colorIndex = 0 self.leftBreak = -1 self.rightBreak = 3 self.label[self.colorIndex].setStyleSheet('background-color: blue') self.tagLabels.append(self.tagLabels[i]) self.tagLabels[-1 % len(self.pixList)].setText("") self.bigLabel.setPixmap(self.bigPixList[-1 % len(self.pixList)]) self.setFocus() #saves all the URLS searched for into a text file separated by a new line def saveClick(self): f = open('SavedURLS.txt','w') f.truncate() f.write(self.saveURL) self.saveTags() self.setFocus() #exits the program def exitClick(self): sys.exit() #simply deletes the image out of the array and fixes it so that the images get truncated to fit def deleteClick(self): del self.pixList[self.index % len(self.pixList)] del self.bigPixList[self.index % len(self.pixList)] self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) for i in range(0, 5, 1): self.label[i].setPixmap(self.pixList[i + self.leftBreak]) self.setFocus() #searches using the flickr API and json responses. Stores those images in the same two pixmap lists and appends the URLS to the saved urls string if the user wants to save them def searchClick(self): self.index = len(self.pixList) self.leftBreak = self.index self.rightBreak = self.index + 4 self.label[self.colorIndex].setStyleSheet('background-color: red') self.colorIndex = 0 self.label[0].setStyleSheet('background-color: blue') tempStr = self.searchBar.text() tempStr.replace(" ", "%20") self.searchBar.setText("") req = 'https://api.flickr.com/services/rest/' req = req + '?method=flickr.photos.search' req = req + '&per_page=' + self.searchResults.text() req = req + '&format=json&nojsoncallback=1' req = req + '&api_key=a0ab0abe9800e8352ae0364a9b595cd2' req = req + '&tags=' + tempStr jsonRespDict = requests.get(req).json() photoset = jsonRespDict['photos'] for p in photoset['photo']: farm = p['farm'] server = p['server'] eyedee = p['id'] secret = p['secret'] tempStr = "http://farm" +str(farm) + ".static.flickr.com/" + str(server) + "/" + str(eyedee) + "_" + str(secret) + ".jpg" print(tempStr) self.saveURL = self.saveURL + tempStr + "\n" url_data = urllib.request.urlopen(tempStr).read() tmpPixmap = QPixmap() tmpPixmap.loadFromData(url_data) if(tmpPixmap.height() > self.height * 3 / 4): tmpPixmap = tmpPixmap.scaledToHeight(self.height * 3 / 4) if(tmpPixmap.width() > self.width * 3 / 4): tmpPixmap = tmpPixmap.scaledToWidth(self.width * 3 / 4) self.bigPixList.append(tmpPixmap) if(tmpPixmap.height() > self.height / 6 - 10): tmpPixmap = tmpPixmap.scaledToHeight(self.height / 6 - 10) if(tmpPixmap.width() > self.width / 6 - 10): tmpPixmap = tmpPixmap.scaledToWidth(self.width / 6 - 10) self.pixList.append(tmpPixmap) self.tagLabels.append(self.tagLabels[0]) for i in range(self.index, len(self.pixList), 1): self.tagLabels[i].setText("") for i in range(self.index, self.index + 5, 1): self.label[i-self.index].setPixmap(self.pixList[i % len(self.pixList)]) self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) self.setFocus() def initUI(self): # title of window self.setWindowTitle('PyQt5 Main Window') # place window on screen at x=0, y=0 self.setGeometry(0, 0, self.width, self.height) self.setStyleSheet('background-color: black') #sets up QLabels for later input for i in range(0, 5, 1): self.label.append(QLabel(self)) self.label[i].move(self.width / 12 + i * self.width / 6, self.height / 3) self.label[i].resize(self.width / 6, self.height / 6) self.label[i].setStyleSheet('background-color: red') if(i == 0): self.label[i].setStyleSheet('background-color: blue') #places pictures into pixmap array i = 0 for file in os.listdir('data'): self.pixList.append(QPixmap(os.path.join('data', file))) self.bigPixList.append(QPixmap(os.path.join('data',file))) self.tagLabels.append(QLabel(self)) self.currentString.append("") self.tagLabels[i].resize(self.width / 8, self.height) self.tagLabels[i].move(self.width * 7 / 8, 0) self.tagLabels[i].setStyleSheet('border-color: grey; border-style: outset; border-width: 5px; font: bold 14px; color: white') self.tagLabels[i].setAlignment(Qt.AlignTop) self.tagLabels[i].hide() if(self.pixList[i].height() > self.height / 6 - 10): self.pixList[i] = self.pixList[i].scaledToHeight(self.height / 6 - 10) if(self.pixList[i].width() > self.width / 6 - 10): self.pixList[i] = self.pixList[i].scaledToWidth(self.width / 6 - 10) if(self.bigPixList[i].width() > self.width*3/4 ): self.bigPixList[i] = self.bigPixList[i].scaledToWidth(self.width*3/4) if(self.bigPixList[i].height() > self.height*3/4): self.bigPixList[i] = self.bigPixList[i].scaledToHeight(self.height*3/4) i = i + 1 self.bigLabel.setAlignment(Qt.AlignCenter) self.bigLabel.setPixmap(self.bigPixList[0]) #puts initial pixmaps into the designated qlabels for i in range(0, 5, 1): self.label[i].setPixmap(self.pixList[i]) self.label[i].setAlignment(Qt.AlignCenter) self.loadURLS() self.show() self.loadTags() #Loads URLS from the text file and places them into the pixmap array def loadURLS(self): f = open('SavedURLS.txt','r') tempString = f.read() self.savedURLS = tempString tempString2 = tempString.split("\n") for i in range(0, len(tempString2)-1, 1): url_data = urllib.request.urlopen(tempString2[i]).read() tmpPixmap = QPixmap() tmpPixmap.loadFromData(url_data) if(tmpPixmap.height() > self.height * 3 / 4): tmpPixmap = tmpPixmap.scaledToHeight(self.height * 3 / 4) if(tmpPixmap.width() > self.width * 3 / 4): tmpPixmap = tmpPixmap.scaledToWidth(self.width * 3 / 4) self.bigPixList.append(tmpPixmap) if(tmpPixmap.height() > self.height / 6 - 10): tmpPixmap = tmpPixmap.scaledToHeight(self.height / 6 - 10) if(tmpPixmap.width() > self.width / 6 - 10): tmpPixmap = tmpPixmap.scaledToWidth(self.width / 6 - 10) self.pixList.append(tmpPixmap) self.tagLabels.append(QLabel(self)) self.currentString.append("") self.tagLabels[len(self.pixList)-1].resize(self.width / 8, self.height) self.tagLabels[len(self.pixList)-1].move(self.width * 7 / 8, 0) self.tagLabels[len(self.pixList)-1].setStyleSheet('border-color: grey; border-style: outset; border-width: 5px; font:bold 14px; color: white') self.tagLabels[len(self.pixList)-1].setAlignment(Qt.AlignTop) self.tagLabels[len(self.pixList)-1].hide() #loads all saved tags def loadTags(self): f = open('SavedTags.txt','r') tempString = f.read() j = 0 for i in range(0, len(tempString), 1): if(tempString[i] != "#"): self.currentString[j]+=tempString[i] else: self.tagLabels[j].setText(self.currentString[j]) j = j + 1 #Moves the pointer to the picture one to the left. If it breaks the bounds, it will move the frame def moveIndexLeft(self): j = 0 if(self.mode == 1): self.tagLabels[self.index % len(self.pixList)].hide() self.tagLabels[(self.index - 1) % len(self.pixList)].show() self.label[self.colorIndex].setStyleSheet('background-color:red') self.colorIndex = self.colorIndex -1 if(self.colorIndex < 0): self.colorIndex = 4 self.index = self.index - 1 if(self.index < self.leftBreak): self.leftBreak = self.leftBreak - 5 self.rightBreak = self.rightBreak - 5 for i in range(self.leftBreak, 1 + self.rightBreak, 1): self.label[j].setPixmap(self.pixList[i % len(self.pixList)]) self.label[j].setAlignment(Qt.AlignCenter) j = j + 1 self.label[self.colorIndex].setStyleSheet('background-color: blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) self.textBox.setText("") #Moves the pointer one picture to the right. If it breaks the bounds of QLabel it will move the frame def moveIndexRight(self): j = 0 if(self.mode == 1): self.tagLabels[self.index % len(self.pixList)].hide() self.tagLabels[(self.index + 1) % len(self.pixList)].show() self.label[self.colorIndex].setStyleSheet('background-color: red') self.colorIndex = self.colorIndex + 1 if(self.colorIndex > 4): self.colorIndex = 0 self.index = self.index + 1 if(self.index > self.rightBreak): self.leftBreak = self.leftBreak + 5 self.rightBreak = self.rightBreak + 5 for i in range(self.leftBreak, 1 + self.rightBreak, 1): self.label[j].setPixmap(self.pixList[i % len(self.pixList)]) self.label[j].setAlignment(Qt.AlignCenter) j = j + 1 self.label[self.colorIndex].setStyleSheet('background-color: blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) self.textBox.setText("") #Zooms in on the specific picture selected and puts it into a 700 x 500 frame def zoomIn(self): self.mode = 1 for i in range(0, 5, 1): self.label[i].hide() self.bigLabel.setAlignment(Qt.AlignCenter) self.bigLabel.show() self.tagButton.show() self.saveTagButton.show() self.textBox.show() self.tagLabels[self.index % len(self.pixList)].show() self.searchBar.hide() self.testButton.hide() self.saveButton.hide() self.exitButton.hide() self.deleteButton.hide() self.searchButton.hide() self.searchResults.hide() self.searchText.hide() #Goes back to default view def zoomOut(self): self.mode = 0 self.bigLabel.hide() for i in range(0, 5, 1): self.label[i].show() self.tagButton.hide() self.saveTagButton.hide() self.textBox.hide() self.tagLabels[self.index % len(self.pixList)].hide() self.searchBar.show() self.testButton.show() self.saveButton.show() self.exitButton.show() self.deleteButton.show() self.searchButton.show() self.searchResults.show() self.searchText.show() #shifts the frame 5 pictures to the left def shiftLeft(self): if(self.mode == 1): self.tagLabels[self.index % len(self.pixList)].hide() self.label[self.colorIndex].setStyleSheet('background-color:red') j = 0 self.colorIndex = 0 self.index = self.leftBreak - 5 if(self.mode == 1): self.tagLabels[self.index % len(self.pixList)].show() self.leftBreak = self.leftBreak - 5 self.rightBreak = self.rightBreak - 5 for i in range(self.leftBreak, 1 + self.rightBreak, 1): self.label[j].setPixmap(self.pixList[i % len(self.pixList)]) j = j + 1 self.label[0].setStyleSheet('background-color: blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) self.textBox.setText("") #shifts the frame 5 pictures to the right def shiftRight(self): if(self.mode == 1): self.tagLabels[self.index % len(self.pixList)].hide() self.label[self.colorIndex].setStyleSheet('background-color: red') self.colorIndex = 0 j = 0 self.index = self.rightBreak + 1 if(self.mode == 1): self.tagLabels[self.index % len(self.pixList)].show() self.rightBreak = self.rightBreak + 5 self.leftBreak = self.leftBreak + 5 for i in range(self.leftBreak, 1 + self.rightBreak, 1): self.label[j].setPixmap(self.pixList[i % len(self.pixList)]) j = j + 1 self.label[0].setStyleSheet('background-color: blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) self.textBox.setText("") #all of the key inputs and their responses in functions def keyPressEvent(self, event): if(event.key() == 16777234): self.moveIndexLeft() if(self.mode == 0): self.soundClick.play() else: self.soundClickWah.play() if(event.key() == 16777236): self.moveIndexRight() if(self.mode == 0): self.soundClick.play() else: self.soundClickWah.play() if(event.key() == 16777235): self.zoomIn() self.soundLoop.setMuted(1) self.soundLoopWah.setMuted(0) if(event.key() == 16777237): self.zoomOut() self.soundLoopWah.setMuted(1) self.soundLoop.setMuted(0) if(event.key() == 44): self.shiftLeft() if(self.mode == 0): self.soundShift.play() else: self.soundShiftWah.play() if(event.key() == 46): self.shiftRight() if(self.mode == 0): self.soundShift.play() else: self.soundShiftWah.play() def mousePressEvent(self, QMouseEvent): if(QMouseEvent.y() < self.height / 7 * 8 or QMouseEvent.y() > self.height / 15 * 16 and QMouseEvent.x() < self.width / 6 or QMouseEvent.x() > self.width / 3): self.setFocus() if(self.mode == 0): setPicTo = -1 if(QMouseEvent.y() > self.height / 3 - 1 and QMouseEvent.y() < self.height / 2 + 1): if(QMouseEvent.x() > self.width / 12 and QMouseEvent.x() < self.width * 3 / 12 + 1): setPicTo = 0 if(QMouseEvent.x() > self.width * 3 / 12 and QMouseEvent.x() < self.width * 5 / 12 + 1): setPicTo = 1 if(QMouseEvent.x() > self.width * 5 / 12 and QMouseEvent.x() < self.width * 7 / 12 + 1): setPicTo = 2 if(QMouseEvent.x() > self.width * 7 / 12 and QMouseEvent.x() < self.width * 9 / 12 + 1): setPicTo = 3 if(QMouseEvent.x() > self.width * 9 / 12 and QMouseEvent.x() < self.width * 11 / 12 + 1): setPicTo = 4 if(setPicTo > -1): self.label[self.index % 5].setStyleSheet('background-color:red') self.mode = 1 self.index = self.leftBreak + setPicTo self.colorIndex = setPicTo self.label[self.index % 5].setStyleSheet('background-color:blue') self.bigLabel.setPixmap(self.bigPixList[self.index % len(self.pixList)]) for i in range(0, 5, 1): self.label[i].hide() self.bigLabel.setAlignment(Qt.AlignCenter) self.bigLabel.show()
class Notification(QMainWindow): '''Transparent window containing an image or animated gif, used to display notifications.''' def __init__(self, name, notifier, artPath, link, sound=None, *args, **kwargs): '''- name : a string - notifier : a Notifier object used to manage this notification - artPath : a string containing the path to the image file to be displayed - link : a string containing the link to be opened when left-clicking the notification - sound : a string containing the path to the object or None. Set to None for silent notifiations.''' super().__init__(*args, **kwargs) self.setCursor(QCursor(Qt.PointingHandCursor)) self.name = name self.notifier = notifier self.link = link self.artPath = artPath self.isMovie = self.artPath.endswith(".gif") if sound == None: self.sound = None else: self.sound = QSoundEffect() self.sound.setSource(QUrl.fromLocalFile(sound)) self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool) self.setAttribute(Qt.WA_TranslucentBackground) imageLabel = QLabel() self.setCentralWidget(imageLabel) if self.isMovie: self.art = QMovie(self.artPath) self.art.jumpToNextFrame() imageLabel.setMovie(self.art) self.moveToBottomRight(self.art.frameRect().width(), self.art.frameRect().height()) else: self.art = QPixmap(self.artPath) imageLabel.setPixmap(self.art) self.moveToBottomRight(self.art.width(), self.art.height()) def moveToBottomRight(self, x, y): '''Moves the notification window to the bottom-right of the screen, above the taskbar''' screen = QDesktopWidget().availableGeometry() x_pos = screen.width() - x y_pos = screen.height() - y self.move(x_pos, y_pos) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.close() webbrowser.open_new_tab(self.link) elif event.button() == Qt.RightButton: self.close() def display(self, volume=1): '''Show the notification window and plays the sound.''' super().show() if self.isMovie: self.art.start() if self.sound: self.sound.setVolume(volume) self.sound.play() def close(self): '''Updates notifier and closes window''' super().close() self.notifier.update()
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): super(MainWindow, self).__init__() self.setupUi(self) self.shootDesktopBn.clicked.connect(self.shootFullScreen) self.shootAreaBn.clicked.connect(self.rectangularSelection) self.shootWindowBn.clicked.connect(self.enableWindowSelectionMode) self.loginBn.clicked.connect(self.loginUser) self.preferencesBn.clicked.connect(self.openPreferences) self.selectorWindows = [] self.highlightWindows = [] self.uploadThreads = [] self.lastUpload = "" self.currentGeometry = QRect() self.currentWId = -1 self.doneSound = QSoundEffect() self.doneSound.setSource(QUrl.fromLocalFile("done.wav")) self.errorSound = QSoundEffect() self.errorSound.setSource(QUrl.fromLocalFile("error.wav")) icon = QIcon(":static/angry.svg") icon.setIsMask(True) self.trayIcon = QSystemTrayIcon(self) self.trayIcon.setIcon(icon) self.trayIcon.show() self.trayIcon.setContextMenu(self.createMenu()) self.trayIcon.messageClicked.connect(self.openLastUpload) self.settings = QSettings(QSettings.IniFormat, QSettings.UserScope, "GliTch_ Is Mad Studios", "PostIt") self.readSettings() def openLastUpload(self): webbrowser.open_new_tab(self.lastUpload) def createMenu(self): menu = QMenu(self) menu.addAction("Desktop Screenshot", self.shootFullScreen) menu.addAction("Window Screenshot", self.enableWindowSelectionMode) menu.addAction("Select Area", self.rectangularSelection) menu.addSeparator() menu.addAction("Open Gallery ...", self.openGallery) menu.addSeparator() menu.addAction("Preferences...", self.openPreferences) menu.addAction("Show", self.show) menu.addAction("Quit", qApp.exit) return menu def openGallery(self): webbrowser.open_new_tab( self.settings.value("internet/address") + "/gallery") def openPreferences(self): prefDiag = PreferencesDialog(self.settings, self) prefDiag.exec_() def readSettings(self): if self.settings.contains("internet/authToken"): self.authToken = self.settings.value("internet/authToken") else: self.loginUser() if not self.settings.contains("internet/address"): self.settings.setValue("internet/address", "https://nsfw.run") def loginUser(self): diag = LoginDialog(self) if diag.exec_(): self.settings.setValue("internet/authToken", diag.loginToken) def shootWindowId(self, WId): screen = self.windowHandle().screen() pixmap = screen.grabWindow(WId) self.uploadHandle(pixmap2bytesIO(pixmap)) def enableWindowSelectionMode(self): if RUNNING_IN_STEVE_JOBS: fn = wrappers.captureWindow() if fn: self.uploadFile(fn) def mouseIsMoving(self, pos): if not self.windowSelectionMode: return pos = self.mapFromGlobal(self.mapToGlobal(pos)) print("cursor is at X: {}, Y: {}".format(pos.x(), pos.y())) if self.currentWId == -1: self.rememberWindowAtPos(pos) ## TODO: draw box here elif self.currentWId > 0 and not self.currentGeometry.contains(pos): print("moved outside of previous window dimensions") self.rememberWindowAtPos(pos) def rememberWindowAtPos(self, pos): WId = getWindowUnderCursor(pos) if WId == 0: print("cursor is on the desktop, ignored") return if WId == self.currentWId: print( "EH?! grabbed the same window even though the cursor moved outside of it..." ) self.currentWId = WId self.currentGeometry = QRect(*getWindowDimensions(WId)) print("stored WId {} ({}) @ {}".format(WId, getWindowText(WId), self.currentGeometry)) def rectangularSelection(self): if RUNNING_IN_STEVE_JOBS: fn = wrappers.captureSelection() if fn: self.uploadFile(fn) else: self.showSelectors(RectangularSelectionWindow) def shootFullScreen(self): shots = [] w = 0 h = 0 for screen in QGuiApplication.screens(): rect = screen.geometry() shot = screen.grabWindow(0, rect.x(), rect.y(), rect.width(), rect.height()) w += shot.width() if h < shot.height( ): # in case one screen is larger than the other h = shot.height() shots.append(shot) pixmap = QPixmap(w, h) painter = QPainter(pixmap) pixmap.fill(Qt.black) p = 0 for ss in shots: painter.drawPixmap(QPoint(p, 0), ss) p += ss.width() painter.end() self.uploadHandle(pixmap2bytesIO(pixmap)) def showSelectors(self, selectorClass): self.selectorWindows = [] desktop = qApp.desktop() for i in range(desktop.screenCount()): selector = selectorClass() self.selectorWindows.append(selector) selector.setGeometry(desktop.screenGeometry(i)) selector.selectionCanceled.connect(self.hideSelectors) selector.selectionMade.connect(self.selectionMade) selector.showFullScreen() selector.windowHandle().setScreen(qApp.screens()[i]) def hideSelectors(self): for selector in self.selectorWindows: selector.hide() def selectionMade(self, screen, x, y, w, h): self.hideSelectors() pixmap = screen.grabWindow(0, x, y, w, h) strIO = pixmap2bytesIO(pixmap) self.uploadHandle(strIO) def uploadFile(self, path): """ used for uploading a file on the file-system """ thread = UploadThread( self.settings.value("internet/address") + "/api/upload", self.settings.value("internet/authToken"), path, self) thread.resultReady.connect(self.uploadComplete) thread.start() self.uploadThreads.append(thread) def uploadHandle(self, handle): """ used for uploading a file-like object that has a .read() method """ thread = UploadHandleThread( self.settings.value("internet/address") + "/api/upload", self.settings.value("internet/authToken"), handle, self) thread.resultReady.connect(self.uploadComplete) thread.start() self.uploadThreads.append(thread) def uploadComplete(self, uri, error): if uri and not error: self.doneSound.play() URL = self.settings.value("internet/address") + uri clipboard = QGuiApplication.clipboard() clipboard.setText(URL) self.lastUpload = URL self.trayIcon.showMessage( "Upload Complete", "Image upload complete. The URL is in your clipboard.") if self.settings.value("preferences/openInBrowser"): logging.debug("opening in browser") webbrowser.open_new_tab(URL) else: self.errorSound.play() try: raise error except requests.exceptions.HTTPError as http_error: if http_error.response.status_code == 401: logging.info( "received 401 during upload request. need to login again" ) self.trayIcon.showMessage( "Invalid Login", "Uh oh, invaild login token. Please login again.") self.loginUser() self.trayIcon.showMessage("Retry", "Try your upload again.") return QMessageBox.critical(self, "Upload Error", str(error)) raise error def purgeAllThreads(self): for thread in self.uploadThreads: if thread.isRunning(): thread.terminate() def closeEvent(self, event): if self.isVisible(): QMessageBox.information( self, "Systray", "I'm running in the system tray. " "Use Quit from the tray menu to end me.") event.ignore() self.hide() else: event.accept()
class TypingWindow(QtWidgets.QWidget, typing_window.Ui_typingWindow): def __init__(self, highscore_obj: highscores.Highscores, *args, **kwargs): super().__init__(*args, **kwargs) # Multiple inheritance allows us to have the ui and window together so # setupui can be given self in for a window self.setupUi(self) self.lineInput.textChanged.connect(self._on_input_text_changed) self.buttonNewText.clicked.connect(self.on_clicked_new) self.buttonRestart.clicked.connect(self.on_clicked_restart) # time and timer self.timer = QtCore.QTimer(self) self.timer.timeout.connect(self._update_time) self.timer.setInterval(100) self._reset_time() # Object to handle saving and updating of highscore values self.highscore = highscore_obj # Defaults self.key_sound = QSoundEffect() self.set_colours(DEFAULT_COLOURS) # Public Methods def set_mode(self, mode: str) -> None: """ Sets the mode for the typing window, by getting a specific generator from texts.py and setting a title for the window. """ self.mode = mode self.labelTitle.setText(mode) if mode == "Common Phrases": self.labelMainText.setAlignment(QtCore.Qt.AlignCenter) self.text_generator = texts._translate[mode]() self._set_main_text() def set_colours(self, colours: List[str]) -> None: """ Sets the colours to be used for rich text formatting. Dictionary provided should be in the order: [green_colour, red_colour] """ self.colours = colours def set_key_sound(self, key_sound: QSoundEffect) -> None: """ Set the sound to be played on a keystroke (should be a QSoundEffect object). """ self.key_sound = key_sound # Private methods def _set_main_text(self) -> None: """ Sets the text to be typed out by the user by getting a value from self.text_generator. If the list of strings from self.text_generator is already exhausted, a default warning string is set instead. """ try: self.text = next(self.text_generator) except StopIteration: self.text = "You have typed all the texts in this category!" self.labelMainText.setText(self.text) def _calculate_score(self, accuracy: int) -> int: """Returns wpm score after calculations including accuracy.""" self.start_time: float seconds: float = perf_counter() - self.start_time return round(((len(self.text) / 5) / (seconds / 60)) * accuracy / 100) def _calculate_accuracy(self, input_text: str) -> int: """Returns accuracy as an int between 1-100 representing a percentage.""" correct: int = 0 for i, character in enumerate(input_text): if character == self.text[i]: correct += 1 return int(correct / len(self.text) * 100) def _set_stats(self, input_text: str) -> None: """Sets instance variables for wpm score and accuracy.""" self.accuracy = self._calculate_accuracy(input_text) self.wpm = self._calculate_score(self.accuracy) def _display_highscore_result(self) -> None: """ Updates the highscore in the highscore object and displays the result. """ self.highscore_result = self.highscore.update(self.wpm) self.results_window.labelHighscoreSet.setText( _TRANSLATE_RESULT[self.highscore_result]) def _get_rich_text(self, input_text: str) -> str: """ Returns the rich text to be displayed so characters typed correctly are highlighted green while incorrect characters are highlighted red. """ typed_text = [] rest_of_text = self.text[len(input_text):] for i, character in enumerate(input_text): if self.text[i] == character: typed_text.append( f'<span style="background-color:{self.colours[0]};">{self.text[i]}</span>' ) else: typed_text.append( f'<span style="background-color:{self.colours[1]};">{self.text[i]}</span>' ) rich_text = ("<html><head/><body><p>" f'{"".join(typed_text)}' f"{rest_of_text}</p></body></html>") return rich_text def _update_time(self) -> None: """ Updates the displayed time on self.labelTime in seconds since self.start_time. """ self.labelTime.setText(str(int(perf_counter() - self.start_time))) def _reset_time(self) -> None: """Resets self.timer, self.start_time and self.labelTime.""" self.start_time = 0.0 self.timer.stop() self.labelTime.setText("0") def _make_results_window(self) -> None: """Generates the results window.""" self.results_window = results.ResultsWindow() self.results_window.setWindowIcon(self.windowIcon()) self.results_window.labelAccuracy.setText(f"{str(self.accuracy)}%") self.results_window.labelSpeed.setText(f"{str(self.wpm)} WPM") self._display_highscore_result() self.results_window.buttonNext.clicked.connect(self.on_clicked_next) # Apply same functionality as for the self.buttonMainMenu, which # is set in main.py self.results_window.buttonMainMenu.clicked.connect( self.on_clicked_results_main_menu) def _on_finished(self, input_text: str) -> None: """ Opens the results window, and is called when the user has typed out all the given text. """ self._set_stats(input_text) self._make_results_window() self.hide() self.results_window.show() if self.isMaximized(): self.results_window.setWindowState(QtCore.Qt.WindowMaximized) # stylesheet for results window must be set after the window is shown self.results_window.setStyleSheet(self.styleSheet()) def _on_input_text_changed(self, input_text: str) -> None: """ Updates background of each letter as user types and calls a function when the user is finished. """ # Break out of function if the text characters are exceeded # This is required to avoid an error if the user spams keys # right at the end of the text they are typing if len(input_text) > len(self.text): return None # Update displayed time or start timer if not self.start_time: self.timer.start() self.start_time = perf_counter() # Try to play key sound effect, if it exists self.key_sound.play() # Set label text to rich text so typed characters are highlighted # based on whether they match self.text rich_text = self._get_rich_text(input_text) self.labelMainText.setText(rich_text) if len(input_text) >= len(self.text): self._on_finished(input_text) # BUTTON METHODS def on_clicked_restart(self) -> None: self.lineInput.clear() self._reset_time() def on_clicked_new(self) -> None: self.on_clicked_restart() self._set_main_text() def on_clicked_next(self) -> None: self.show() self.on_clicked_new() self.results_window.close() del self.results_window def on_clicked_results_main_menu(self) -> None: """ Clicks the typing window's main menu button and closes the results window. This is done because the functionality for the main menu button is given in main.py. """ self.buttonMainMenu.click() self.results_window.close()
class QAVButton(QPushButton): def __init__(self, label): """ builds a custom button and displays it""" # calls super constuctor super(QAVButton, self).__init__(label) self.sound = QSoundEffect() self.volume = 1. self.color = QColor(Qt.gray) self.count = 0 self.duration = 1000 self.rate = 20 self.timer = QTimer() self.timer.timeout.connect(self.update_anim) self.mode = "sin" self.pressed.connect(self.start) self.released.connect(self.stop) self.is_accelerating = False self.update_color_with_alha(1) def setSound(self, sound_file): self.sound.setSource(QUrl.fromLocalFile(sound_file)) self.sound.setLoopCount(QSoundEffect.Infinite) def start(self): self.count = 0 self.sound.play() self.timer.start(self.rate) def stop(self): self.timer.stop() self.sound.stop() def set_color(self, col): self.color = col self.update_color_with_alha(1) def update_color_with_alha(self, alpha): red = self.color.red() green = self.color.green() blue = self.color.blue() bg_style = f"background-color:rgba({red},{green},{blue}, {alpha})" self.setStyleSheet(bg_style) def update_anim(self): #logarithmic (check with perception of luminosity/brighness) #val = math.log(count + 1) #linear if self.mode == "sin": val = math.sin(self.count * 2 * math.pi) / 2 + 0.5 elif self.mode == "lin": val = 1 - self.count else: val = math.log(self.count + 1) alpha = round(val * 100) + 155 self.update_color_with_alha(alpha) amplitude = val * 0.8 + 0.2 self.sound.setVolume(amplitude) self.count = self.count + self.rate / self.duration # print(count) if self.count >= 1 - self.rate / self.duration: self.count = 0 if self.is_accelerating: self.duration = max(200, self.duration * 0.95)
class Window(QWidget): def __init__(self): super().__init__() self.title = 'CSC 690 - Project 1' self.model = Model('./data/') self.view_mode = 'thumbnails' self.mode = 'thumbnails' self.stylesheet = '' self.selected_thumbnail_stylesheet = 'border: 5px solid red;' self.window_width = 800 self.window_height = 600 if len(sys.argv) > 1: self.window_width = int(sys.argv[1]) self.window_height = self.window_width * (3/4) self.thumbnail_labels = [] self.thumbnail_pixmaps = [] self.tag_labels = [] self.window_width = 800 self.window_height = 600 if len(sys.argv) > 1: if int(sys.argv[1]) >= 600 and int(sys.argv[1]) <= 1200: self.window_width = int(sys.argv[1]) self.window_height = self.window_width * (3/4) else: print("Given width out of range. Defaulting to 600.") self.init_labels() self.init_controls() if len(self.model.nodes) > 0: self.init_UI() self.init_sounds() def init_UI(self): self.fullscreen_pixmap = QPixmap(self.model.get_current_filename()) self.setWindowTitle(self.title) self.setGeometry(100, 100, self.window_width, self.window_height) self.setStyleSheet('background: #00C0FF;') self.load_thumbnails() # start with first thumbnail selected self.thumbnail_labels[0].setStyleSheet(self.selected_thumbnail_stylesheet) self.fullscreen_label.hide() for label in self.tag_labels: label.hide() self.show() def init_labels(self): self.fullscreen_label = QLabel(self) self.fullscreen_label.resize(self.window_width / 2, self.window_height / 2) self.fullscreen_label.setStyleSheet(self.selected_thumbnail_stylesheet) self.fullscreen_label.setAlignment(Qt.AlignCenter) self.fullscreen_label.setFocusPolicy(Qt.StrongFocus) self.fullscreen_label.move((self.window_width - (self.window_width / 2)) / 2, (self.window_height - (self.window_height/ 2)) /2) for index in range(0, CONST_NUM_TAGS): temp_label = QLabel(self) temp_label.move(650, 400 - (index * 30)) self.tag_labels.append(temp_label) temp_label.hide() def init_controls(self): self.add_tag_button = QPushButton('Add tag', self) self.add_tag_button.setFocusPolicy(Qt.ClickFocus) self.add_tag_button.move((self.window_width / 2) - 180, self.window_height - 50) self.add_tag_button.clicked.connect(self.add_tag) self.add_tag_button.hide() self.search_button = QPushButton('Search', self) self.search_button.setFocusPolicy(Qt.ClickFocus) self.search_button.move(self.window_width / 3.7, self.window_height - (self.window_height / 10)) self.search_button.clicked.connect(self.search_flickr) self.save_tags_button = QPushButton('Save all tags', self) self.save_tags_button.setFocusPolicy(Qt.ClickFocus) self.save_tags_button.move((self.window_width / 2) - 10, self.window_height - 50) self.save_tags_button.clicked.connect(self.save_tags) self.save_tags_button.hide() self.tag_field = QLineEdit(self) self.tag_field.setFocusPolicy(Qt.ClickFocus) self.tag_field.setAlignment(Qt.AlignCenter) self.tag_field.move((self.window_width / 2) - 90, self.window_height - 100) self.tag_field.hide() self.search_text_field = QLineEdit(self) self.search_text_field.setFocusPolicy(Qt.ClickFocus) self.search_text_field.move(self.window_width / 28, self.window_height - (self.window_height / 10)) self.search_number_field = QLineEdit(self) self.search_number_field.setFocusPolicy(Qt.ClickFocus) self.search_number_field.move(self.window_width / 2.5, self.window_height - (self.window_height / 10)) self.search_number_field.setFixedWidth(60) self.test_button = QPushButton('Test', self) self.test_button.setFocusPolicy(Qt.ClickFocus) self.test_button.move(self.window_width / 28, self.window_height - (self.window_height / 19)) self.test_button.clicked.connect(self.test) self.save_photos_button = QPushButton('Save', self) self.save_photos_button.setFocusPolicy(Qt.ClickFocus) self.save_photos_button.move(self.window_width / 7.3, self.window_height - (self.window_height / 19)) self.save_photos_button.clicked.connect(self.save_photos) self.exit_button = QPushButton('Exit', self) self.exit_button.setFocusPolicy(Qt.ClickFocus) self.exit_button.move(self.window_width / 4.2, self.window_height - (self.window_height / 19)) self.exit_button.clicked.connect(self.close) self.delete_button = QPushButton('Delete', self) self.delete_button.setFocusPolicy(Qt.ClickFocus) self.delete_button.move(self.window_width / 2.95, self.window_height - (self.window_height / 19)) self.delete_button.clicked.connect(self.delete) def init_sounds(self): self.train_sound = QSoundEffect() self.train_sound.setSource(QUrl.fromLocalFile('./audio/TRAIN06.WAV')) self.train_sound.setVolume(0.5) self.conk_sound = QSoundEffect() self.conk_sound.setSource(QUrl.fromLocalFile('./audio/CONK.WAV')) self.conk_sound.setVolume(0.5) def delete(self): self.model.delete() self.reload_thumbnails('forward') self.delete_button.clearFocus() def add_tag(self): self.model.add_tag(self.tag_field.text()) self.tag_field.setText('') self.add_tag_button.clearFocus() self.show_tags() def hide_thumbnail_controls(self): self.search_text_field.hide() self.search_number_field.hide() def keyPressEvent(self, event): key_pressed = event.key() if key_pressed == Qt.Key_Right: if self.mode == 'thumbnails': self.next_image() elif self.mode == 'fullscreen': self.next_image() self.show_fullscreen_image() self.show_tags() elif key_pressed == Qt.Key_Left: if self.mode == 'thumbnails': self.prev_image() elif self.mode == 'fullscreen': self.prev_image() self.show_fullscreen_image() self.show_tags() elif key_pressed == Qt.Key_Up: if self.mode == 'thumbnails': self.mode = 'fullscreen' #self.conk_sound.play() self.show_fullscreen_image() self.show_fullscreen_view() elif key_pressed == Qt.Key_Down: if self.mode == 'fullscreen': self.mode = 'thumbnails' #self.conk_sound.play() self.fullscreen_label.hide() self.show_thumbnails_view() elif key_pressed == 46: if self.mode == 'thumbnails': self.train_sound.play() for _ in range(0, CONST_THUMBNAIL_COUNT): self.next_image() self.thumbnail_labels[self.model.get_current_index() % 5].setStyleSheet('') self.model.set_current_index(self.model.get_leftmost_index()) self.thumbnail_labels[self.model.get_current_index() % 5].setStyleSheet(self.selected_thumbnail_stylesheet) elif key_pressed == 44: if self.mode == 'thumbnails': self.train_sound.play() for _ in range(0, CONST_THUMBNAIL_COUNT): self.prev_image() self.thumbnail_labels[self.model.get_current_index() % 5].setStyleSheet('') self.model.set_current_index(self.model.get_leftmost_index()) self.thumbnail_labels[self.model.get_current_index() % 5].setStyleSheet(self.selected_thumbnail_stylesheet) def load_thumbnails(self): # load images into pixmap array # for _ in self.model.image_files: # self.thumbnail_pixmaps.append(QPixmap(self.model.get_current_filename()).scaled(CONST_THUMBNAIL_SIZE, CONST_THUMBNAIL_SIZE, Qt.KeepAspectRatio)) # self.model.next_filename() # create labels for index in range(0, CONST_THUMBNAIL_COUNT): # init thumbnail labels with corresponding pixmap self.thumbnail_labels.append(QLabel(self)) if(index < len(self.model.nodes)): self.thumbnail_labels[index].setPixmap(self.model.nodes[index].get_image().scaled(CONST_THUMBNAIL_SIZE, CONST_THUMBNAIL_SIZE, Qt.KeepAspectRatio)) # positioning labels self.thumbnail_labels[index].resize(CONST_THUMBNAIL_SIZE, CONST_THUMBNAIL_SIZE) self.thumbnail_labels[index].setAlignment(Qt.AlignCenter) # TODO: remove magic numbers below self.thumbnail_labels[index].move(self.window_width / (self.window_width / 30) + (index * self.window_width / 5), (self.window_height - CONST_THUMBNAIL_SIZE) / 2) #self.thumbnail_labels[index].move((self.window_width / (self.window_width / 10)) + index * self.window_width / 5, (self.window_height - CONST_THUMBNAIL_SIZE) / 2) def next_image(self): # remove red highlight from current selection self.thumbnail_labels[self.model.get_current_index() % 5].setStyleSheet('') self.model.select_next_node() self.reload_thumbnails('forward') def prev_image(self): # remove red highlight from current self.thumbnail_labels[self.model.get_current_index() % 5].setStyleSheet('') self.model.select_prev_node() self.reload_thumbnails('backward') def reload_thumbnails(self, direction): if (self.model.get_current_index() % 5 == 0): self.model.set_leftmost_index(self.model.get_current_index()) elif (self.model.get_current_index() == self.model.get_leftmost_index() - 1): self.model.set_leftmost_index(self.model.get_leftmost_index() - 5) if direction == 'forward': temp_index = self.model.get_leftmost_index() for label in self.thumbnail_labels: temp_index = self.model.check_index_bounds(temp_index, direction) label.setPixmap(self.model.nodes[temp_index].get_image().scaled(CONST_THUMBNAIL_SIZE, CONST_THUMBNAIL_SIZE, Qt.KeepAspectRatio)) temp_index += 1 self.thumbnail_labels[self.model.get_current_index() % 5].setStyleSheet(self.selected_thumbnail_stylesheet) elif direction == 'backward': temp_index = self.model.get_leftmost_index() + 4 for label in reversed(self.thumbnail_labels): temp_index = self.model.check_index_bounds(temp_index, direction) label.setPixmap(self.model.nodes[temp_index].get_image().scaled(CONST_THUMBNAIL_SIZE, CONST_THUMBNAIL_SIZE, Qt.KeepAspectRatio)) temp_index -= 1 if (self.model.get_current_index() == len(self.model.nodes) - 1): self.thumbnail_labels[4].setStyleSheet(self.selected_thumbnail_stylesheet) else: self.thumbnail_labels[self.model.get_current_index() % 5].setStyleSheet(self.selected_thumbnail_stylesheet) def save_photos(self): self.model.save_nodes() self.save_photos_button.clearFocus() def save_tags(self): self.model.save_tags('tags.txt') self.save_tags_button.clearFocus() def search_flickr(self): search_string = ''.join('%20' if char == ' ' else char for char in self.search_text_field.text()) self.model.search_flickr(search_string, self.search_number_field.text()) self.reload_thumbnails('forward') self.search_text_field.setText('') self.search_button.clearFocus() def show_fullscreen_image(self): self.fullscreen_pixmap = self.model.nodes[self.model.get_current_index()].get_image() self.fullscreen_pixmap = self.fullscreen_pixmap.scaled(self.window_width / 2, self.window_height / 2, Qt.KeepAspectRatio) self.fullscreen_label.setPixmap(self.fullscreen_pixmap) self.fullscreen_label.show() self.show_tags() def show_fullscreen_view(self): self.add_tag_button.show() self.save_tags_button.show() self.tag_field.show() self.show_tags() for label in self.thumbnail_labels: label.hide() self.search_button.hide() self.search_text_field.hide() self.search_number_field.hide() self.test_button.hide() self.save_photos_button.hide() self.exit_button.hide() self.delete_button.hide() def show_tags(self): tags = self.model.get_tags() for label in self.tag_labels: label.setText('') for label, tag in zip(self.tag_labels, tags): label.hide() label.setText(str(tag)) label.show() def show_thumbnail_controls(self): self.search_text_field.show() self.search_number_field.show() def show_thumbnails_view(self): for label in self.thumbnail_labels: label.show() self.add_tag_button.hide() self.save_tags_button.hide() self.tag_field.hide() for label in self.tag_labels: label.hide() self.search_button.show() self.search_text_field.show() self.search_number_field.show() self.search_button.show() self.search_text_field.show() self.search_number_field.show() self.test_button.show() self.save_photos_button.show() self.exit_button.show() self.delete_button.show() def test(self): self.test_button.clearFocus()