class RadioBox(QWidget): def __init__(self, parent=None, items=None, spread=True, **kwargs): # If spread is False, insert a spacer in the layout so that the items don't use all the # space they're given but rather align left. if items is None: items = [] super().__init__(parent, **kwargs) self._buttons = [] self._labels = items self._selected_index = 0 self._spacer = horizontalSpacer() if not spread else None self._layout = QHBoxLayout(self) self._update_buttons() # --- Private def _update_buttons(self): if self._spacer is not None: self._layout.removeItem(self._spacer) to_remove = self._buttons[len(self._labels):] for button in to_remove: self._layout.removeWidget(button) button.setParent(None) del self._buttons[len(self._labels):] to_add = self._labels[len(self._buttons):] for _ in to_add: button = QRadioButton(self) self._buttons.append(button) self._layout.addWidget(button) button.toggled.connect(self.buttonToggled) if self._spacer is not None: self._layout.addItem(self._spacer) if not self._buttons: return for button, label in zip(self._buttons, self._labels): button.setText(label) self._update_selection() def _update_selection(self): self._selected_index = max( 0, min(self._selected_index, len(self._buttons) - 1)) selected = self._buttons[self._selected_index] selected.setChecked(True) # --- Event Handlers def buttonToggled(self): for i, button in enumerate(self._buttons): if button.isChecked(): self._selected_index = i self.itemSelected.emit(i) break # --- Signals itemSelected = pyqtSignal(int) # --- Properties @property def buttons(self): return self._buttons[:] @property def items(self): return self._labels[:] @items.setter def items(self, value): self._labels = value self._update_buttons() @property def selected_index(self): return self._selected_index @selected_index.setter def selected_index(self, value): self._selected_index = value self._update_selection()
class RadioBox(QWidget): def __init__(self, parent=None, items=None, spread=True, **kwargs): # If spread is False, insert a spacer in the layout so that the items don't use all the # space they're given but rather align left. if items is None: items = [] super().__init__(parent, **kwargs) self._buttons = [] self._labels = items self._selected_index = 0 self._spacer = horizontalSpacer() if not spread else None self._layout = QHBoxLayout(self) self._update_buttons() #--- Private def _update_buttons(self): if self._spacer is not None: self._layout.removeItem(self._spacer) to_remove = self._buttons[len(self._labels):] for button in to_remove: self._layout.removeWidget(button) button.setParent(None) del self._buttons[len(self._labels):] to_add = self._labels[len(self._buttons):] for _ in to_add: button = QRadioButton(self) self._buttons.append(button) self._layout.addWidget(button) button.toggled.connect(self.buttonToggled) if self._spacer is not None: self._layout.addItem(self._spacer) if not self._buttons: return for button, label in zip(self._buttons, self._labels): button.setText(label) self._update_selection() def _update_selection(self): self._selected_index = max(0, min(self._selected_index, len(self._buttons)-1)) selected = self._buttons[self._selected_index] selected.setChecked(True) #--- Event Handlers def buttonToggled(self): for i, button in enumerate(self._buttons): if button.isChecked(): self._selected_index = i self.itemSelected.emit(i) break #--- Signals itemSelected = pyqtSignal(int) #--- Properties @property def buttons(self): return self._buttons[:] @property def items(self): return self._labels[:] @items.setter def items(self, value): self._labels = value self._update_buttons() @property def selected_index(self): return self._selected_index @selected_index.setter def selected_index(self, value): self._selected_index = value self._update_selection()
class CPinUI(QWidget): def __init__(self, pinID, parent=None): super(CPinUI, self).__init__(parent) self.m_PinID = pinID self.m_NodeID = interface.GetNodeIDByPinID(pinID) self.m_GraphicID = interface.GetGraphicIDByNodeID(self.m_NodeID) self.m_Btn = None self.m_Label = None self.m_HLayout = None self.m_DefaultWidget = None # 默认值控件 self._InitUI() self.SetIcon() self.SetText() self.ShowDefaultWidget() GetUIMgr().AddPinUI(pinID, self) def __del__(self): GetUIMgr().DelPinUI(self.m_PinID) def _InitUI(self): hBox = QHBoxLayout(self) hBox.setContentsMargins(0, 0, 0, 0) hBox.setSpacing(6) self.m_Btn = CTypeButton(self.m_PinID, self) self.m_Label = QLabel(self) self.m_HLayout = QHBoxLayout() self.m_HLayout.setContentsMargins(0, 0, 0, 0) self.m_HLayout.setSpacing(6) hBox.addWidget(self.m_Btn) hBox.addWidget(self.m_Label) hBox.addLayout(self.m_HLayout) def contextMenuEvent(self, event): super(CPinUI, self).contextMenuEvent(event) lstLineID = interface.GetAllLineByPin(self.m_PinID) menu = QMenu() for lineID in lstLineID: oPinID = interface.GetLineOtherPin(lineID, self.m_PinID) sPinDisplayName = interface.GetPinAttr(oPinID, bddefine.PinAttrName.DISPLAYNAME) nodeID = interface.GetNodeIDByPinID(oPinID) sNodeDisplayName = interface.GetNodeAttr(nodeID, bddefine.NodeAttrName.DISPLAYNAME) sMsg = "删除与\"%s\"-\"%s\"的连线" % (sNodeDisplayName, sPinDisplayName) func = functor.Functor(interface.DelLine, lineID) menu.addAction(sMsg, func) menu.exec_(QCursor.pos()) event.accept() def SetIcon(self, iDataType=None): if iDataType is None: iPinType = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.PIN_TYPE) if bddefine.PinIsFlow(iPinType): iDataType = -1 else: iDataType = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.DATA_TYPE) icon = QIcon() pix = ":/icon/btn_%s.png" % iDataType icon.addPixmap(QPixmap(pix), QIcon.Normal, QIcon.Off) self.m_Btn.setIcon(icon) def SetText(self, sText=None): if sText is None: sText = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.DISPLAYNAME) self.m_Label.setText(sText) def ShowDefaultWidget(self): iPinType = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.PIN_TYPE) if iPinType != bddefine.PIN_INPUT_DATA_TYPE: return lstLine = interface.GetAllLineByPin(self.m_PinID) if lstLine: return oWidget = None iDataTye = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.DATA_TYPE) if iDataTye in (bddefine.Type.INT, bddefine.Type.FLOAT, bddefine.Type.STR): oWidget = subpinui.CValidatorLineEdit(self.m_PinID, iDataTye) elif iDataTye == bddefine.Type.BOOL: oWidget = subpinui.CCheckBox(self.m_PinID) elif iDataTye == bddefine.Type.ENUM: oWidget = subpinui.CEnum(self.m_PinID) elif iDataTye == bddefine.Type.VECTOR3: oWidget = subpinui.CVector3(self.m_PinID) elif iDataTye == bddefine.Type.CHECKBOX: oWidget = subpinui.CComCheckBox(self.m_PinID) if oWidget: self.m_HLayout.addWidget(oWidget) self.m_DefaultWidget = oWidget self.adjustSize() def HideDefaultWidget(self): if not self.m_DefaultWidget: return self.m_DefaultWidget.setParent(None) index = self.m_HLayout.indexOf(self.m_DefaultWidget) item = self.m_HLayout.itemAt(index) self.m_HLayout.removeWidget(self.m_DefaultWidget) self.m_HLayout.removeItem(item) self.m_DefaultWidget = None self.adjustSize() def enterEvent(self, event): super(CPinUI, self).enterEvent(event) GetSignal().UI_LINE_CONNECT.emit(self.m_GraphicID, self.m_PinID) event.accept()
class SaveDataWindow(QWidget): def __init__(self, dest, schema, callback, parent=None): super(SaveDataWindow, self).__init__() self.dests = ["console", "text", "file", "database"] self.dest = dest self.schema = schema #Determine screen settings geo = self.frameGeometry() self.width = QDesktopWidget().availableGeometry().width() self.height = QDesktopWidget().availableGeometry().height() #Define window par meters self.resize(self.width * .5, self.height * .5) self.setWindowTitle("Aqueti Schema Editor") # self.mainLayout = QVBoxLayout() self.titleLayout = QHBoxLayout() self.destLayout = QHBoxLayout() #Create title title = QLabel() title.setText("Schema Saving Dialog") self.titleLayout.addWidget(title) self.mainLayout.addLayout(self.titleLayout) #Destination Layout self.destLayout = QHBoxLayout() self.mainLayout.addLayout(self.destLayout) #Add Button Layout self.buttonLayout = QHBoxLayout() self.submitButton = QPushButton("Save") self.submitButton.clicked.connect(lambda: self.saveButtonCallback()) self.buttonLayout.addWidget(self.submitButton) cancelButton = QPushButton("Cancel") cancelButton.clicked.connect(lambda: self.cancelButtonCallback()) self.buttonLayout.addWidget(cancelButton) self.mainLayout.addLayout(self.buttonLayout) self.setLayout(self.mainLayout) self.show() self.updateDestLayout() self.draw() ## # \brief updates the destinatino layout # def updateDestLayout(self): #Remove current layout information #Remove all widgets from the current layout while self.destLayout.count(): item = self.destLayout.takeAt(0) self.destLayout.removeItem(item) widget = item.widget() if widget is not None: widget.deleteLater() try: item.deleteLater() except: pass ############################################# # Layout to select a destination ############################################# destTitle = QLabel() destTitle.setText("OutputType:") self.destCombo = QComboBox() self.destCombo.addItems(self.dests) #Find what our current dest is and set the appropriate index index = 0 for i in range(0, self.destCombo.count()): if self.destCombo.itemText(i) == self.dest["type"]: index = i self.destCombo.setCurrentIndex(index) self.destLayout.addWidget(destTitle) self.destLayout.addWidget(self.destCombo) #### # Fill in details base on source tpye #### if self.dest["type"] == "console": pass elif self.dest["type"] == "file": fileLabel = QLabel() fileLabel.setText("file: ") try: name = self.dest["filename"] except: name = "" self.fileNameBox = QLineEdit() self.fileNameBox.setText(name) self.destLayout.addWidget(fileLabel) self.destLayout.addWidget(self.fileNameBox) ## # \brief Function to draw the object def draw(self): #Add a submitDest Button selectDestButton = QPushButton("Select") selectDestButton.currentIndexChanged.connect( lambda: self.destChangeCallback()) self.destLayout.addWidget(destTitle) self.destLayout.addWidget(self.destCombo) self.destLayout.addWidget(selectDestButton) self.destLayout.addLayout(self.destLayout) ## # \brief callback for the Cancel button # def cancelButtonCallback(self): self.close() ## # \brief callback for a save button press # def saveButtonCallback(self): print("Saving:" + str(self.dest)) if self.dest["type"] == "console": print() print("Schema (" + str(time.time()) + ")") print(str(self.schema)) elif self.dest["type"] == "file": with open(self.dest["filename"], 'w') as outfile: json.dump(self.schema, outfile) else: print("Source type: " + str(self.dest["type"]) + " is not currently supported") self.close()
class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.numberShapes = 0 self.dict = {2: 1, 0: -1} self.cb = [] self.layouts = [] self.spasers = [] self.layout = QHBoxLayout() self.sp = QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.hopfieldnet = HopfieldNet(SHAPE_SIDE_HEIGHT, SHAPE_SIDE_WIDHT) self.create_ui() def create_ui(self): gb = QGroupBox() gb.setLayout(self.layout) self.layout.addItem(self.sp) self.ui.scrollArea.setWidget(gb) self.ui.scrollArea.setWidgetResizable(True) self.ui.scrollArea.setFixedHeight((SHAPE_SIDE_HEIGHT + 2) * 30) self.ui.incorrect_share.addLayout(self.Add_Shape('Incorrect')) self.ui.correct_share.addLayout(self.Add_Shape('Reshare')) self.ui.save.clicked.connect(self.Save) self.ui.recognize.clicked.connect(self.Recognize) self.ui.recognize.setEnabled(False) self.ui.delete_shape.clicked.connect(self.Delete_Shape) self.ui.add_shape.clicked.connect(self.Add_Learned_Shape) for _ in range(3): self.Add_Learned_Shape() def Add_Shape(self, name): grid = QGridLayout() l1 = QLabel(name) l1.setFont(QtGui.QFont("SansSerif", 11)) grid.addWidget(l1, 0, 0, 1, 3) cb1 = [QCheckBox('', self) for _ in range(SHAPE_SIDE_HEIGHT * SHAPE_SIDE_WIDHT)] _ = [cb.setFixedSize(20, 20) for cb in cb1] for i in range(len(cb1)): grid.addWidget(cb1[i], i // SHAPE_SIDE_WIDHT + 1, i % SHAPE_SIDE_WIDHT) self.cb.append(cb1) self.layouts.append(grid) return grid def Add_Learned_Shape(self): self.numberShapes += 1 self.layout.removeItem(self.sp) if self.numberShapes > 1: sp = QSpacerItem(40, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) self.spasers.append(sp) self.layout.addItem(sp) l1 = QLabel(f'{self.numberShapes} share') l1.setFont(QtGui.QFont("SansSerif", 11)) self.layout.addLayout(self.Add_Shape(f"{self.numberShapes} shape")) self.layout.addItem(self.sp) def Save(self): self.hopfieldnet.clear() for i in range(2, len(self.cb)): tmp = [self.dict[check.checkState()] for check in self.cb[i]] if 1 in tmp: self.hopfieldnet.teach(tmp) if len(self.hopfieldnet.shapes): self.ui.recognize.setEnabled(True) def Recognize(self): redict = {1: 2, -1: 0} rezult, reshare = self.hopfieldnet.recognize([self.dict[check.checkState()] for check in self.cb[0]]) _ = [checkbox.setCheckState(redict[reshare[i]]) for i, checkbox in enumerate(self.cb[1])] self.ui.status.setText(rezult) self.ui.status.setFont(QtGui.QFont("SansSerif", 16)) self.ui.status.setStyleSheet(f"color: {'red' if rezult == 'Failed' else 'green'}") def Delete_Shape(self): if self.numberShapes < 3: return self.numberShapes -= 1 self.cb.pop() for i in reversed(range(self.layouts[-1].count())): self.layouts[-1].itemAt(i).widget().deleteLater() self.layout.removeItem(self.layouts[-1]) self.layout.removeItem(self.spasers[-1]) self.spasers.pop() self.layouts.pop()
class Game(QWidget): add_number_signal = pyqtSignal(tuple) pop_number_signal = pyqtSignal() rotate_signal = pyqtSignal() def __init__(self): super().__init__() self.move(20, 20) self.hbox = QHBoxLayout() self.grid = Grid(self) self.vbox = QVBoxLayout() self.actual_piece = Piece("blank", self) self.rotate_button = QPushButton('Rotar', self) self.end_game_button = QPushButton('Terminar Juego', self) self.back_button = QPushButton('Retroceder', self) self.save_button = QPushButton('Guardar', self) self.state_grid = StateGrid(self) self.p1_points = QLabel(self) self.p2_points = QLabel(self) self.set_points(1, 0) self.set_points(2, 0) def initUi(self): self.setWindowTitle('Best Tarea Ever :P') self.setMouseTracking(True) self.setLayout(self.hbox) self.hbox.addStretch(1) self.hbox.addWidget(self.grid) self.hbox.addStretch(1) self.hbox.addLayout(self.vbox) self.hbox.addStretch(1) self.grid.show() self.piece_layout = QHBoxLayout(self) self.piece_layout.addStretch(1) self.piece_layout.addWidget(self.actual_piece) self.piece_layout.addStretch(1) self.vbox.addStretch(1) self.vbox.addLayout(self.piece_layout) self.vbox.addStretch(1) hlayout = QHBoxLayout(self) self.vbox.addLayout(hlayout, 1) hlayout.addWidget(self.save_button, 1) hlayout.addWidget(self.rotate_button, 1) hlayout.addWidget(self.end_game_button, 1) hlayout.addWidget(self.back_button, 1) self.vbox.addStretch(1) self.vbox.addWidget(self.state_grid, 1) hlayout_points = QHBoxLayout(self) self.vbox.addLayout(hlayout_points, 1) self.p1_points.show() self.p2_points.show() hlayout_points.addWidget(self.p1_points) hlayout_points.addWidget(self.p2_points) self.rotate_button.clicked.connect(self.rotate_piece) self.back_button.clicked.connect(self.back_move) self.end_game_button.clicked.connect(self.end_game) self.save_button.clicked.connect(self.save_game) self.add_number_signal.connect(self.state_grid.add_number) self.pop_number_signal.connect(self.state_grid.pop_number) self.rotate_signal.connect(self.rotate_piece) self.grid.initUI() self.new_piece() @staticmethod def back_move(): variables.GAME_INTERFACE.retroceder() @staticmethod def end_game(): variables.GAME_INTERFACE.terminar_juego() @staticmethod def save_game(): variables.GAME_INTERFACE.guardar_juego() def user_rotate(self): self.rotate_signal.emit() def add_number(self, number, color): self.add_number_signal.emit((number, color)) def pop_number(self): self.pop_number_signal.emit() def new_piece(self, color=None, piece_type=None): if piece_type is None: piece_type = choice(variables.TYPES) if color is None and piece_type != "hint": color = choice(variables.COLORS) self.piece_layout.removeItem(self.piece_layout.itemAt(2)) self.piece_layout.removeWidget(self.actual_piece) self.actual_piece.hide() self.actual_piece.deleteLater() self.actual_piece = Piece(piece_type, color, self) self.piece_layout.addWidget(self.actual_piece) self.piece_layout.addStretch(1) def addPiece(self, i, j, color=None, piece_type=None, on_move_ended=None): if piece_type is None: self.grid.addPiece(i, j, self.actual_piece, on_move_ended) elif piece_type == 'blank' or piece_type == 'hint': self.grid.addPiece(i, j, Piece(piece_type, color, self.grid)) else: raise TypeError('No es un tipo valido') def getPiece(self, i, j): return self.grid.getPiece(i, j) def popPiece(self, i, j): pop_piece = self.grid.popPiece(i, j) self.addPiece(i, j, piece_type='blank') return pop_piece def movePiece(self, i, j, piece, on_move_end=None): self.grid.movePiece(i, j, piece, on_move_end) def set_points(self, player_numb, points): # self.label_puntaje.setText(str(points)) if player_numb == 1: self.p1_points.setText("Jugador 1: {}".format(points)) elif player_numb == 2: self.p2_points.setText("Jugador 2: {}".format(points)) def rotate_piece(self): self.actual_piece.rotate() variables.GAME_INTERFACE.rotar_pieza('Derecha') def keyPressEvent(self, event): if event.key() == Qt.Key_H: variables.GAME_INTERFACE.hint_asked()
class MainWindow(QWidget): ## # \brief Initialization Function def __init__(self): super(MainWindow, self).__init__() #Default variables self.valid = False #Field to determine if the value is valid self.selectorLayout = None #Layout used for selecting a specific source self.sources = ["none", "text", "file", "database"] self.source = {"type": None} self.dests = ["console", "file"] self.dest = {"type": "console"} self.sourceValue = None self.sourceSchema = None #Determine screen settings geo = self.frameGeometry() self.width = QDesktopWidget().availableGeometry().width() self.height = QDesktopWidget().availableGeometry().height() #Define window par meters self.resize(self.width * .5, self.height * .5) self.setWindowTitle("Aqueti Schema Editor") self.show() #create Layouts in UI self.titleLayout = QHBoxLayout() self.mainLayout = QVBoxLayout() self.sourceLayout = QHBoxLayout() self.destLayout = QHBoxLayout() self.valueLayout = QVBoxLayout() self.buttonLayout = QHBoxLayout() #Create frames self.sourceFrame = QFrame() self.destFrame = QFrame() self.valueFrame = QFrame() self.sourceFrame.setFrameStyle(QFrame.Box) self.valueFrame.setFrameStyle(QFrame.Box) self.destFrame.setFrameStyle(QFrame.Box) self.sourceFrame.setLayout(self.sourceLayout) self.destFrame.setLayout(self.destLayout) self.valueFrame.setLayout(self.valueLayout) self.valueFrame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) #Create Scoll Area for valueFrame self.valueScrollArea = QScrollArea() self.valueScrollArea.updateGeometry() self.valueScrollArea.setWidget(self.valueFrame) self.valueScrollArea.setWidgetResizable(True) #Create title title = QLabel() title.setText("Aqueti Schema Editor") self.titleLayout.addWidget(title) #Add persistent source items sourceTitle = QLabel() sourceTitle.setText("Source:") self.sourceCombo = QComboBox() self.sourceCombo.addItems(self.sources) self.sourceCombo.currentTextChanged.connect( lambda: self.sourceChangeCallback()) selectSourceButton = QPushButton("Load") self.sourceLayout.addWidget(sourceTitle) self.sourceLayout.addWidget(self.sourceCombo) self.sourceMetaLayout = QHBoxLayout() self.sourceMetaLayout.setSizeConstraint(QHBoxLayout.SetMinimumSize) self.sourceLayout.addLayout(self.sourceMetaLayout) self.sourceLayout.addWidget(selectSourceButton) #Add persistent dest destTitle = QLabel() destTitle.setText("Dest:") self.destCombo = QComboBox() self.destCombo.addItems(self.dests) self.destCombo.currentTextChanged.connect( lambda: self.destChangeCallback()) selectDestButton = QPushButton("Load") self.destLayout.addWidget(destTitle) self.destLayout.addWidget(self.destCombo) self.destMetaLayout = QHBoxLayout() self.destMetaLayout.setSizeConstraint(QHBoxLayout.SetMinimumSize) self.destLayout.addLayout(self.destMetaLayout) self.destLayout.addWidget(selectDestButton) #Add Submit Button self.submitButton = QPushButton("Submit") self.submitButton.clicked.connect(lambda: self.submitCallback()) self.buttonLayout.addWidget(self.submitButton) #Add cancel Button cancelButton = QPushButton("Cancel") cancelButton.clicked.connect(lambda: self.cancelCallback()) self.buttonLayout.addWidget(cancelButton) #Add Layouts and draw self.mainLayout.addLayout(self.titleLayout) self.mainLayout.addWidget(self.sourceFrame) self.mainLayout.addWidget(self.destFrame) # self.mainLayout.addWidget( self.valueFrame ) self.mainLayout.addWidget(self.valueScrollArea) # self.mainLayout.addStretch(1) self.mainLayout.addLayout(self.buttonLayout) self.draw() ## # \brief updates the source Layout def updateSourceLayout(self): #Remove current layout information #Remove all widgets from the current layout while self.sourceMetaLayout.count(): item = self.sourceMetaLayout.takeAt(0) self.sourceMetaLayout.removeItem(item) widget = item.widget() if widget is not None: widget.deleteLater() try: item.deleteLater() except: pass #Find what our current source is and set the appropriate index index = 0 for i in range(0, self.sourceCombo.count()): if self.sourceCombo.itemText(i) == self.source["type"]: index = i self.sourceCombo.setCurrentIndex(index) #Add fields based on source type if self.source["type"] == "file": #Add filename fileLabel = QLabel() fileLabel.setText("file: ") try: name = self.source["filename"] except: name = "" self.sourceFilenameBox = QLineEdit() self.sourceFilenameBox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) self.sourceFilenameBox.setText(name) # self.sourceFilenameBox.readOnly = True # self.sourceFilenameBox.sizeHint() # self.sourceFilenameBox.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.sourceMetaLayout.addWidget(fileLabel) self.sourceMetaLayout.addWidget(self.sourceFilenameBox) # #Add a submitSource Button # selectSourceButton = QPushButton("Load") # selectSourceButton.clicked.connect( lambda: self.sourceChangeCallback()) # self.sourceLayout.addWidget(selectSourceButton) # self.sourceLayout.addStretch(1) ## # \brief updates the destination layout # def updateDestLayout(self): #Remove current layout information #Remove all widgets from the current layout while self.destMetaLayout.count(): item = self.destMetaLayout.takeAt(0) self.destMetaLayout.removeItem(item) widget = item.widget() if widget is not None: widget.deleteLater() try: item.deleteLater() except: pass """ ############################################# # Layout to select a destination ############################################# destTitle = QLabel() destTitle.setText("Dest:") self.destCombo = QComboBox() self.destCombo.addItems(self.dests) """ #Find what our current dest is and set the appropriate index index = 0 for i in range(0, self.destCombo.count()): if self.destCombo.itemText(i) == self.dest["type"]: index = i self.destCombo.setCurrentIndex(index) self.destCombo.currentTextChanged.connect( lambda: self.destChangeCallback()) # self.destLayout.addWidget(destTitle) # self.destLayout.addWidget(self.destCombo) # self.destLayout.addStretch(1) #### # Fill in details base on dest tpye #### if self.dest["type"] == "console": pass elif self.dest["type"] == "file": fileLabel = QLabel() fileLabel.setText("file: ") try: name = self.dest["filename"] except: name = "" self.fileNameBox = QLineEdit() self.fileNameBox.setText(name) # self.destMetaLayout.addWidget(fileLabel) self.destMetaLayout.addWidget(self.fileNameBox) ## # \brief function that is called when the source is changed # def destChangeCallback(self): print("Changing dest") newType = self.destCombo.itemText(self.destCombo.currentIndex()) print("New Type: " + str(newType)) if newType != self.dest["type"]: self.dest = {} self.dest["type"] = newType if self.dest["type"] == "console": pass elif self.dest["type"] == "file": options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog destName, _ = QFileDialog.getSaveFileName( self, "QFileDialog.getSaveFileName()", "", "All Files (*);;JSON Files (*.json)", options=options) self.dest["filename"] = str(destName) else: print("Unsupported Type") self.draw() ## # \brief Update the value layout def updateValueLayout(self): #Remove all widgets from the current layout while self.valueLayout.count(): item = self.valueLayout.takeAt(0) self.valueLayout.removeItem(item) widget = item.widget() if widget is not None: widget.deleteLater() try: item.deleteLater() except: pass #If we have data, let's display it if self.sourceSchema != None: valueTitle = QLabel() valueTitle.setText("Schema") self.schemaWidget = SmartWidget().init("Schema", self.sourceValue, self.sourceSchema, showSchema=False) self.valueLayout.addWidget(self.schemaWidget.frame) #Disable the submit button if we don't have a schema if self.sourceSchema == None: self.submitButton.setEnabled(False) else: self.submitButton.setEnabled(True) self.setLayout(self.mainLayout) ## # \brief redraws all dynamic layouts def draw(self): self.updateDestLayout() self.updateSourceLayout() self.updateValueLayout() ## # \brief callback for when the source type changes # def sourceChangeCallback(self): #SDF Add popup to notify of schema loss #Clear the schema to disable the submit button self.sourceSchema = None self.source["type"] = self.sourceCombo.itemText( self.sourceCombo.currentIndex()) if self.source["type"] == "none": self.sourceSchema = {"bsonType": "object"} #If we are a file read the file contents as the value elif self.source["type"] == "file": options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog sourceName, _ = QFileDialog.getOpenFileName( self, "QFileDialog.getOpenFileName()", "", "All Files (*);;JSON Files (*.json)", options=options) self.source["filename"] = str(sourceName) print("Loading: " + str(self.source["filename"])) with open(self.source["filename"]) as json_file: self.sourceSchema = json.load(json_file) print("Loaded Schema:" + str(json.dumps(self.sourceSchema, indent=4))) self.updateSourceLayout() self.updateValueLayout() ## #\brief callback to get result from SmartWidget # # This function assumes that the schema is done. It will produce a popup # asking where and how to save the data # def submitCallback(self): schema = self.schemaWidget.getSchema() if self.dest["type"] == "console": print() print("Schema: (" + str(time.time()) + ")") print(json.dumps(schema, indent=4)) elif self.dest["type"] == "file": print("Writing to: " + str(self.dest["filename"])) with open(self.dest["filename"], 'w') as outfile: json.dump(schema, outfile, indent=4) else: print("Source type: " + str(self.dest["type"]) + " is not currently supported") self.close() #Use save pop-up to save data #self.saveWindow = SaveDataWindow(self.source, schema, self.saveCallback ) print(str(time.time()) + "- schema:") print(str(schema)) ## # \brief Function called after data is saved # def saveCallback(self, success): print("Data Result: " + str(success)) ## # \brief Cancels the change and exits # def cancelCallback(self): print("Exited. No changes were saved") sys.exit(1)
class OptionsBar(QWidget): def __init__(self, task_widget): super().__init__(task_widget) self.task_widget = task_widget self.area = None self.options = [] self.v_options = [] self.buttons = [] self.layout = QHBoxLayout() self.layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(self.layout) def with_area(self): self.area = AreaOptions() self.layout.addLayout(self.area) return self def with_int_options_v(self, top=1, bottom=10, top_name='α', bottom_name='β', min=-10000): v_option = VerticalIntOption(top, bottom, top_name, bottom_name, min) self.v_options.append(v_option) self.layout.addLayout(v_option) return self def with_int_option(self, name, default=0, min=-10000, max=10000): option = IntOption(name, default, min, max) self.options.append(option) self.layout.addLayout(option) return self def with_button(self, name, callback): button = QPushButton(name, self) button.clicked.connect(callback) self.buttons.append(button) self.layout.addWidget(button) return self def with_image(self, path): pixmap = QPixmap(path) label = QLabel() label.setPixmap(pixmap) self.layout.addWidget(label) return self def clear(self): self.options = [] self.v_options = [] self.buttons = [] for i in range(self.layout.count() - 1, -1, -1): item = self.layout.takeAt(i) self.layout.removeItem(item)
class App(QWidget): def __init__(self, controller): super().__init__() self.controller = controller self.window_edit = QComboBox() self.batch_edit = QComboBox() self.epochs_edit = QComboBox() self.eta_edit = QComboBox() self.layers_edit = QComboBox() self.layers = [] self.nb_neurons = ['15', '25', '50', '100'] self.train_button = QPushButton() self.layers_box = QHBoxLayout() self.init_UI() def init_UI(self): self.setFont(QFont("Arial", 18)) info_label = QLabel( 'This is an application for predicting protein secondary structure ' + 'using an artificial neural network. Please select the desired parameters ' + 'and then train the network.') info_label.setWordWrap(True) # parameter labels and combo boxes window = QLabel('Window size') batch = QLabel('Batch size') epochs = QLabel('Number of epochs') eta = QLabel('Learning rate') layers = QLabel('Number of hidden layers') self.window_edit.addItems(['11', '13', '15', '25']) self.batch_edit.addItems(['50', '100', '200']) self.epochs_edit.addItems(['100', '1000', '5000', '10000']) self.eta_edit.addItems(['0.01', '0.02', '0.03']) self.layers_edit.addItems(['1', '2', '3', '4']) # add labels and combo boxes into grid layout params_box = QVBoxLayout() grid = QGridLayout() grid.setContentsMargins(10, 20, 20, 20) grid.addWidget(window, 1, 0) grid.addWidget(self.window_edit, 1, 1) grid.addWidget(batch, 2, 0) grid.addWidget(self.batch_edit, 2, 1) grid.addWidget(epochs, 3, 0) grid.addWidget(self.epochs_edit, 3, 1) grid.addWidget(eta, 4, 0) grid.addWidget(self.eta_edit, 4, 1) grid.addWidget(layers, 5, 0) grid.addWidget(self.layers_edit, 5, 1) params_box.addWidget(info_label) params_box.addLayout(grid) # layout for the button and hidden layers self.train_button.setText('Train network') self.train_button.clicked.connect(self.train_and_evaluate) self.layers_box.addWidget(self.train_button) self.create_layers_layout() # add parameters layout and layers layout to the overall layout general_box = QVBoxLayout() general_box.addLayout(params_box) general_box.addLayout(self.layers_box) self.layers_edit.currentIndexChanged.connect(self.create_layers_layout) self.setLayout(general_box) self.setGeometry(100, 100, 800, 500) self.setWindowIcon(QIcon('protein.png')) self.setWindowTitle('Secondary Structure Prediction') self.show() def create_layers_layout(self): layer_count = int(self.layers_edit.currentText()) # layers to be shown layers_on_window = len(self.layers) # layers already shown # add new layout for more layers if layers_on_window < layer_count: for i in range(layers_on_window + 1, layer_count + 1): new_layer_neurons = QComboBox() self.layers.append(new_layer_neurons) new_layer_neurons.addItems(self.nb_neurons) new_layer = QVBoxLayout() new_label = QLabel('Layer ' + str(i) + ':') new_layer.addWidget(new_label) new_layer.addWidget(new_layer_neurons) self.layers_box.addLayout(new_layer) else: # remove layouts for less layers for j in range(layers_on_window, layer_count, -1): layout_item = self.layers_box.itemAt(j) # remove all the widgets from this layout while layout_item.count(): item = layout_item.takeAt(0) widget = item.widget() if widget is not None: widget.setParent(None) self.layers_box.removeItem(layout_item) self.layers.pop() def train_and_evaluate(self): window_size = int(self.window_edit.currentText()) batch_size = int(self.batch_edit.currentText()) epochs = int(self.epochs_edit.currentText()) learning_rate = float(self.eta_edit.currentText()) hidden_layers = [] for layer in self.layers: hidden_layers.append(int(layer.currentText())) ann = self.controller.ann self.controller = Controller(ann, window_size, batch_size, epochs, learning_rate, hidden_layers) self.controller.train_and_evaluate() self.enter_protein = EvaluateProtein(self.controller) self.enter_protein.show()
class KeyboardStatusWidget(QWidget): updateStatusSignal = pyqtSignal(list, list, list) def __init__(self): super(KeyboardStatusWidget, self).__init__() self.updateStatusSignal.connect(self.onUpdateStatus) self.hlayout = QHBoxLayout() self.hlayout.setAlignment(Qt.AlignLeft) self.items = [] self.hlayout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.hlayout) def addPlusLabel(self): label = QLabel() label.setContentsMargins(5, 5, 5, 5) label.setAlignment(Qt.AlignVCenter) fontsize = 10 label.setText( "<font size='{fontsize}'>+</font>".format(fontsize=fontsize)) item = QVBoxLayout() item.addWidget(label) self.items.append(item) self.hlayout.addLayout(item) def onUpdateStatus(self, keys, modifiers, unknown_keys): def layout_del_inner(layout): for i in reversed(range(layout.count())): layout.itemAt(i).widget().setParent(None) for item in self.items: self.hlayout.removeItem(item) layout_del_inner(item) self.items = [] for i in range(len(keys)): key = keys[i] label = QLabel() label.setContentsMargins(5, 5, 5, 5) label.setAlignment(Qt.AlignVCenter) fontsize = 10 label.setText( "<font style='font-weight:bold;' size='{fontsize}'>{text}</font>" .format(text=key, fontsize=fontsize)) item = QVBoxLayout() item.addWidget(label) self.items.append(item) self.hlayout.addLayout(item) if i + 1 != len(keys) or len(modifiers) > 0: self.addPlusLabel() for i in range(len(modifiers)): mod = modifiers[i] label = QLabel() label.setContentsMargins(5, 5, 5, 5) label.setAlignment(Qt.AlignVCenter) fontsize = 10 label.setText( "<font style='font-weight:bold;' size='{fontsize}'>{text}</font>" .format(text=mod, fontsize=fontsize)) item = QVBoxLayout() item.addWidget(label) self.items.append(item) self.hlayout.addLayout(item) if i + 1 != len(modifiers) or len(unknown_keys) > 0: self.addPlusLabel() for i in range(len(unknown_keys)): key = unknown_keys[i] label = QLabel() label.setContentsMargins(5, 5, 5, 5) label.setAlignment(Qt.AlignVCenter) fontsize = 10 label.setText( "<font style='font-weight:bold;color:darkred;' size='{fontsize}'>{text}</font>" .format(text="??(0x{:02x})".format(key), fontsize=fontsize)) item = QVBoxLayout() item.addWidget(label) self.items.append(item) self.hlayout.addLayout(item) if i + 1 != len(unknown_keys): self.addPlusLabel()
class UserWindow(QDialog): columnLabel = None columnTable = None userButtons = None windowButtons = None userButtonBox = None windowButtonBox = None mainLayout = None leftLayout = None rightLayout = None initLayout = None userGeneral = None userFolders = None userPage = None addUserDialog = None buttonAdd = None buttonRemove = None def __init__(self): super(UserWindow, self).__init__() self.setModal(True) self.setWindowTitle('Settings') self.setFixedSize(600, 400) self.userPage = UserPage() self.initLayout = FirstPage() self.initUi() self.initSetting() def initUi(self): self.initColumnLabel() self.initColumnTable() self.initUserButtons() self.initWindowButtons() self.leftLayout = QVBoxLayout() self.leftLayout.addStretch() self.leftLayout.addWidget(self.columnLabel) self.leftLayout.addWidget(self.columnTable) self.leftLayout.addWidget(self.userButtonBox) self.leftLayout.addWidget(self.windowButtonBox) self.rightLayout = self.initLayout self.mainLayout = QHBoxLayout() self.mainLayout.addLayout(self.leftLayout) self.mainLayout.addLayout(self.rightLayout) self.mainLayout.setStretchFactor(self.leftLayout, 1) self.mainLayout.setStretchFactor(self.rightLayout, 2) self.setLayout(self.mainLayout) def initColumnLabel(self): self.columnLabel = QLabel('Users:') def initColumnTable(self): self.columnTable = QTableWidget() self.columnTable.setColumnCount(1) self.columnTable.setRowCount(0) self.columnTable.verticalHeader().setHidden(True) self.columnTable.horizontalHeader().setHidden(True) self.columnTable.setEditTriggers(QAbstractItemView.NoEditTriggers) self.columnTable.setSelectionMode(QAbstractItemView.SingleSelection) self.columnTable.itemClicked.connect(self.itemClickedTriggered) def itemClickedTriggered(self): self.mainLayout.removeItem(self.rightLayout) self.rightLayout.accountSettingBox.close() self.rightLayout.sharedFolderBox.close() for index in range(self.columnTable.rowCount()): item = self.columnTable.item(index, 0) if item.isSelected(): self.rightLayout = item.page break self.mainLayout.addLayout(self.rightLayout) self.mainLayout.setStretchFactor(self.leftLayout, 1) self.mainLayout.setStretchFactor(self.rightLayout, 2) self.rightLayout.accountSettingBox.show() self.rightLayout.sharedFolderBox.show() def initUserButtons(self): self.userButtonBox = QGroupBox() self.buttonAdd = QPushButton('Add') self.buttonRemove = QPushButton('Remove') self.buttonRemove.setEnabled(False) self.buttonAdd.clicked.connect(self.addTriggered) self.buttonRemove.clicked.connect(self.removeTriggered) subLayout = QHBoxLayout() subLayout.addWidget(self.buttonAdd) subLayout.addWidget(self.buttonRemove) self.userButtonBox.setLayout(subLayout) def addTriggered(self): self.addUserDialog = addDialog() self.addUserDialog.userOKButton.clicked.connect(self.addOKTriggered) self.addUserDialog.userCancelButton.clicked.connect( self.addCancelTriggered) self.addUserDialog.exec() name = self.addUserDialog.userNameEdit def addOKTriggered(self): name = self.addUserDialog.userNameEdit.text() icon = QPixmap('resource/fail.png') if name == '': box1 = QMessageBox() box1.setText('Please enter a name.') box1.setIconPixmap(icon.scaled(100, 100)) box1.exec() return for index in range(self.columnTable.rowCount()): item = self.columnTable.item(index, 0) if name == item.text(): box2 = QMessageBox() box2.setText('User %s has existed.' % name) box2.setIconPixmap(icon.scaled(100, 100)) box2.exec() return nameItem = NewTypeItem() nameItem.setText(name) nameItem.page.sharedFolderEdit.setText('/%s' % name) self.columnTable.setRowCount(self.columnTable.rowCount() + 1) self.columnTable.setItem(self.columnTable.rowCount() - 1, 0, nameItem) self.addUserDialog.close() self.buttonRemove.setEnabled(True) def addCancelTriggered(self): self.addUserDialog.close() def removeTriggered(self): for index in range(self.columnTable.rowCount()): item = self.columnTable.item(index, 0) if item.isSelected(): self.columnTable.removeRow(index) if self.columnTable.rowCount() == 0: self.buttonRemove.setEnabled(False) break self.mainLayout.removeItem(self.rightLayout) self.rightLayout.accountSettingBox.close() self.rightLayout.sharedFolderBox.close() self.rightLayout = self.initLayout self.mainLayout.addLayout(self.rightLayout) self.rightLayout.accountSettingBox.show() self.rightLayout.sharedFolderBox.show() def initWindowButtons(self): self.windowButtonBox = QGroupBox() buttonOK = QPushButton('OK') buttonCancel = QPushButton('Cancel') buttonOK.clicked.connect(self.okTriggered) buttonCancel.clicked.connect(self.cancelTriggered) subLayout = QVBoxLayout() subLayout.addWidget(buttonOK) subLayout.addWidget(buttonCancel) self.windowButtonBox.setLayout(subLayout) def okTriggered(self): self.updateSetting() msg = SettingMessage() msg.exec() self.close() def cancelTriggered(self): self.close() def initSetting(self): with open('./setting.json', 'r') as load_f: load_j = json.load(load_f) userList = load_j['Users'] for user in userList: userItem = NewTypeItem() userItem.setText(user['Name']) userItem.page = UserPage() # if user['UsePassword']: # userItem.page.passwordCheckBox.setChecked(True) # else: # userItem.page.passwordCheckBox.setChecked(False) userItem.page.passwordEdit.setText(user['Password']) userItem.page.sharedFolderEdit.setText(user['SharedFolder']) self.columnTable.setRowCount(self.columnTable.rowCount() + 1) self.columnTable.setItem(self.columnTable.rowCount() - 1, 0, userItem) if self.columnTable.rowCount() != 0: self.buttonRemove.setEnabled(True) pass def updateSetting(self): with open('./setting.json', 'r+') as lw_f: lw_j = json.load(lw_f) lw_f.seek(0) lw_f.truncate() itemJsonList = [] for index in range(self.columnTable.rowCount()): item = self.columnTable.item(index, 0) # if item.page.passwordCheckBox.isChecked() == True: # itemJsonList.append({"Name": item.text(), "UsePassword": 1, "Password": item.page.passwordEdit.text(), # "SharedFolder": item.page.sharedFolderEdit.text()}) # else: # itemJsonList.append({"Name": item.text(), "UsePassword": 0, "Password": item.page.passwordEdit.text(), # "SharedFolder": item.page.sharedFolderEdit.text()}) itemJsonList.append({ "Name": item.text(), "Password": item.page.passwordEdit.text(), "SharedFolder": item.page.sharedFolderEdit.text() }) lw_j['Users'] = itemJsonList json.dump(lw_j, lw_f) pass
class GridWidget(QWidget): def __init__(self, kind, im_width, num_rows=3, num_cols=4, labeler=False): super(GridWidget, self).__init__() self.num_rows = num_rows self.num_cols = num_cols self.page = 1 self.gridLayout = QGridLayout() self.kind = kind #fullname=str(self.model) #self.name= (fullname[fullname.find(":")+2:fullname.find(">")].strip()+'_set').lower() self.images = [None] * (self.num_rows * self.num_cols) self.updated = True self.num_pages = 1 for i in range(self.num_rows): for j in range(self.num_cols): index = i * self.num_cols + j self.images[index] = ImageView(im_width, labeler) self.gridLayout.addWidget(self.images[index], i, j) self.next = QPushButton('Next') self.previous = QPushButton('Previous') self.last = QPushButton('Last') self.first = QPushButton('First') self.of = QLabel('of') self.total = QLabel() self.current = QLineEdit("1") self.current.setValidator(QIntValidator()) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.addWidget(self.first) self.horizontalLayout.addWidget(self.previous) self.horizontalLayout.addWidget(self.current) self.horizontalLayout.addWidget(self.of) self.horizontalLayout.addWidget(self.total) self.horizontalLayout.addWidget(self.next) self.horizontalLayout.addWidget(self.last) self.verticalLayout = QVBoxLayout() self.verticalLayout.addLayout(self.gridLayout, stretch=1) self.verticalLayout.addLayout(self.horizontalLayout, stretch=0) self.labeler = labeler if labeler: self.horizontalLayout2 = QHBoxLayout() self.horizontalLayout2.addLayout(self.verticalLayout) self.refreshLabeler() self.setLayout(self.horizontalLayout2) else: self.setLayout(self.verticalLayout) self.updatePages() self.next.clicked.connect(self.doNext) self.previous.clicked.connect(self.doPrevious) self.last.clicked.connect(self.doLast) self.first.clicked.connect(self.doFirst) self.current.returnPressed.connect(self.doJump) def refreshLabeler(self): if hasattr(self, "labelerGrid"): for i in reversed(range(self.labelerGrid.count())): self.labelerGrid.itemAt(i).widget().deleteLater() self.labelerGrid.deleteLater() self.labelerGrid.setParent(None) self.horizontalLayout2.removeItem(self.labelerGrid) del self.labelerGrid self.labelerGrid = QGridLayout() query = Category.select() i = 0 for cat in query: button = QPushButton(cat.name) button.clicked.connect(self.clickgen(cat)) self.labelerGrid.addWidget(button, i // 2, i % 2) i += 1 button = QPushButton("Delete") button.clicked.connect(self.delete) self.labelerGrid.addWidget(button, i // 2, i % 2) self.horizontalLayout2.addLayout(self.labelerGrid) self.update() def clickgen(self, cat): def labelerClicked(event): for i in range(self.num_rows): for j in range(self.num_cols): index = i * self.num_cols + j ex_label = self.images[index] for label in ex_label.tags: if label.tik.isVisible() and label.tik.checkState(): label.updateLabel(cat) return labelerClicked def delete(self, event): for i in range(self.num_rows): for j in range(self.num_cols): index = i * self.num_cols + j ex_label = self.images[index] for tag in ex_label.tags: if tag.tik.isVisible() and tag.tik.checkState(): tag.setParent(None) ex_label.tags.remove(tag) def updatePages(self): count = Image.select().join(Detection).where( Detection.kind == self.kind.value).count() self.num_pages = (count // (self.num_rows * self.num_cols)) + 1 self.total.setText(str(self.num_pages)) self.current.setText(str(self.page)) if self.page == 1: self.previous.setEnabled(False) else: self.previous.setEnabled(True) if self.page == self.num_pages: self.next.setEnabled(False) else: self.next.setEnabled(True) def doNext(self, event): if self.page <= self.num_pages: self.page += 1 self.updated = True self.showCurrentPage() self.updatePages() def doPrevious(self, event): if self.page > 1: self.page -= 1 self.updated = True self.showCurrentPage() self.updatePages() def doLast(self, event): self.page = self.num_pages self.updated = True self.showCurrentPage() self.updatePages() def doFirst(self, event): self.page = 1 self.updated = True self.showCurrentPage() self.updatePages() def doJump(self): val = int(self.current.text()) if val >= 1 and val <= self.num_pages: self.page = val self.updated = True self.showCurrentPage() else: self.current.setText("1") self.updatePages() def showCurrentPage(self, force=False): if self.labeler: self.refreshLabeler() if self.updated or force: #print("Parent", self.parentWidget().width(), self.parentWidget().height()) self.clear() query = Image.select().join(Detection).where( Detection.kind == self.kind.value).paginate( self.page, self.num_rows * self.num_cols) #print(self.model,self.name,query.sql()) index = 0 for r in query: self.images[index].setSample( r.id, os.path.join('/project/evolvingai/mnorouzz/Serengiti/SER', r.file_name), r.detection_set) index += 1 self.updated = False def clear(self): self.visited = False for i in range(self.num_rows): for j in range(self.num_cols): index = i * self.num_cols + j self.images[index].clear()
class PlotWidget(QWidget): """ PlotWidget widget. Widget used to show data plots. Inherits from: QWidget Signals: None """ def __init__(self, label, plot_typ, dock_widget, twin_container, *args, parent=None, **kwargs): """ Setup the layout for the widget. Arguments: label - Label of the plot. plot_typ - Type of plot (e.g. histogram, values) parent - Parent widget (Default None) *args - Unused additional arguments **kwargs - Unused named additional arguments Return: None """ super(PlotWidget, self).__init__(parent=parent) self.parent = parent self.label = label self.plot_typ = plot_typ self.dock_widget = dock_widget self.twin_container = twin_container self.twin_canvas = None self._is_first = True layout_v = QVBoxLayout(self) self.layout_canvas = QHBoxLayout() self._plot_ref = [] self._image_ref = [] self._mean_ref = [] self._median_ref = [] self._canvas_list = [] self._is_started = False self.setup_values() if self.plot_typ in ('values', 'histogram'): self._hide_marker = False self.markersize = 4 self.trim_widget = TrimWidget(self.plot_typ, self._minimum_x, self._maximum_x, self._minimum_y, self._maximum_y, self._bins, self) self.trim_widget.sig_update.connect(self.update_trim) self.trim_widget.sig_hide.connect(self.hide_twin) layout_v.addWidget(self.trim_widget, stretch=0) self.view_widget = ViewWidget(self) self.view_widget.sig_hide.connect(self.hide_marker) layout_v.addWidget(self.view_widget, stretch=0) elif plot_typ == 'image' and label == 'image': self.select_widget = SelectWidget(self) self.select_widget.sig_update.connect(self.set_current_image_name) layout_v.addWidget(self.select_widget, stretch=0) self.current_image_name = 'latest' layout_v.addLayout(self.layout_canvas, stretch=1) def setup_values(self): self._xdata = np.array([]) self._ydata = np.array([]) self._data = None self._basenames = None self._directory_name = None self._color = '#68a3c3' self._cur_min_x = 0 self._cur_max_x = 0 self._cur_min_y = 0 self._cur_max_y = 0 self._applied_min_x = 0 self._applied_max_x = 0 self._applied_min_y = 0 self._applied_max_y = 0 self._xdata_raw = np.array([]) self._ydata_raw = np.array([]) self._bins = 50 self._minimum_x = float('-inf') self._maximum_x = float('inf') self._minimum_y = float('-inf') self._maximum_y = float('inf') self._previous_dict = {} self.mean = None self.median = None @pyqtSlot() def hide_marker(self): self._hide_marker = not self._hide_marker self.force_update() @pyqtSlot(int) def hide_twin(self, state): if self.twin_canvas is not None: self.twin_container.handle_show(self.plot_typ, self.twin_canvas, not state) @pyqtSlot(str) def set_current_image_name(self, text): self.current_image_name = text self.update_figure() def start_plotting(self): if not self._is_started: self.add_canvas() self.parent.parent.content[ self.parent.parent_layout].sig_start_plot.connect( self.update_figure) self._is_started = True def add_canvas(self): layout_v = QVBoxLayout() is_image = self.plot_typ == 'image' canvas_settings = { 'parent': self, 'no_grid': is_image, 'plot_type': self.plot_typ, } self.canvas = MplCanvasWidget(**canvas_settings) self._canvas_list.append(self.canvas) self._plot_ref.append(None) self._mean_ref.append(None) self._median_ref.append(None) if self.twin_container is not None and not is_image: self.twin_canvas = MplCanvasWidget(**canvas_settings, is_twin=True) self._canvas_list.append(self.twin_canvas) self.twin_container.add_to_layout(self.plot_typ, self.twin_canvas) self._plot_ref.append(None) self._mean_ref.append(None) self._median_ref.append(None) else: self.twin_canvas = None toolbar = NavigationToolbar(self.canvas.mpl_canvas, self) toolbar.actions()[0].triggered.connect(self.force_update) layout_v.addWidget(toolbar) layout_v.addWidget(self.canvas, stretch=1) self.layout_canvas.addLayout(layout_v) def clear_canvas(self): for idx in reversed(range(self.layout_canvas.count())): current_layout = self.layout_canvas.itemAt(idx) for idx2 in reversed(range(current_layout.count())): widget = current_layout.itemAt(idx2).widget() try: self._canvas_list.remove(widget) except ValueError: pass current_layout.removeWidget(widget) widget.setParent(None) widget = None del widget self.layout_canvas.removeItem(current_layout) current_layout.setParent(None) current_layout = None del current_layout self._plot_ref = [] self._mean_ref = [] self._median_ref = [] @pyqtSlot(str, str, object, str, object) def set_settings(self, name, name_no_feedback, data, directory_name, settings): self._directory_name = directory_name self._data = data self._basenames = np.array( [os.path.basename(entry) for entry in data['file_name']]) if self.plot_typ in ('values', 'histogram'): self._xdata_raw, self._ydata_raw, labels_x, label_y, title = tu.get_function_dict( )[name_no_feedback]['plot']( data=data, settings=settings, label=self.label, ) if self._is_first: self._is_first = False for canvas in self._canvas_list: canvas.update_labels(title, labels_x, label_y) self.update_figure() elif self.plot_typ == 'image': self.select_widget.set_values(self._basenames) @pyqtSlot() def update_trim(self): return_value, self._previous_dict = self.trim_widget.get_values() if return_value is not None: self._minimum_x, self._maximum_x, self._minimum_y, self._maximum_y, self._bins = \ return_value self.force_update(do_message=True) self.force_update() def update_data(self, do_message=False): if self.plot_typ in ('values', 'histogram'): mask_y = np.logical_and(self._ydata_raw >= self._minimum_y, self._ydata_raw <= self._maximum_y) mask_x = np.logical_and(self._xdata_raw >= self._minimum_x, self._xdata_raw <= self._maximum_x) mask = np.logical_and(mask_y, mask_x) if self._ydata_raw[mask].size == 0 or self._xdata_raw[ mask].size == 0: self.trim_widget.set_values(self._previous_dict) if do_message: tu.message( 'Masking values do not contain any data points! Falling back to previous values!' ) return False self.mean = np.mean(self._ydata_raw[mask]) self.median = np.median(self._ydata_raw[mask]) self.view_widget.update_label({ 'Min': np.min(self._ydata_raw[mask]), 'Max': np.max(self._ydata_raw[mask]), 'Sum': np.sum(self._ydata_raw[mask]), 'Mean': self.mean, 'Median': self.median, 'In range': np.count_nonzero(mask), 'of': mask.shape[0], }) if self.plot_typ == 'values': self._xdata = self._xdata_raw[mask] self._ydata = self._ydata_raw[mask] elif self.plot_typ == 'histogram': self._ydata, self._xdata = np.histogram( self._ydata_raw[mask], self._bins) return True @pyqtSlot() def force_update(self, do_message=False): for plot_line in self._median_ref: if plot_line is not None: for entry in plot_line: entry.remove() for plot_line in self._mean_ref: if plot_line is not None: for entry in plot_line: entry.remove() for plot_line in self._plot_ref: if plot_line is not None: for entry in plot_line: entry.remove() self._plot_ref = [None] * len(self._plot_ref) self._median_ref = [None] * len(self._median_ref) self._mean_ref = [None] * len(self._mean_ref) self.update_figure(do_message) def prepare_axes(self, update): if ( ( self._cur_min_x > np.min(self._xdata) or \ self._cur_min_y > np.min(self._ydata) or \ self._cur_max_x < np.max(self._xdata) or \ self._cur_max_y < np.max(self._ydata) ) and \ self.canvas.mpl_canvas.axes.get_xlim() == (self._applied_min_x, self._applied_max_x) and \ self.canvas.mpl_canvas.axes.get_ylim() == (self._applied_min_y, self._applied_max_y) ) or \ update: is_histogram = bool(self.plot_typ == 'histogram') try: width = self._xdata[1] - self._xdata[0] except IndexError: width = 0 assert not is_histogram, (self._xdata, self._ydata) diff_x = np.max(self._xdata) - np.min(self._xdata) diff_x = np.maximum(diff_x, 1) diff_y = np.max( self._ydata) - np.min(self._ydata) * bool(not is_histogram) diff_y = np.maximum(diff_y, 1) mult = 0.05 boarder_x = np.maximum(diff_x * mult / 2, width * is_histogram) boarder_y = diff_y * mult / 2 if self.plot_typ == 'values': self._cur_min_x = np.min(self._xdata) - boarder_x self._cur_min_y = np.min(self._ydata) - boarder_y self._cur_max_x = np.max(self._xdata) + boarder_x self._cur_max_y = np.max(self._ydata) + boarder_y self._applied_min_x = self._cur_min_x - boarder_x / 2 self._applied_min_y = self._cur_min_y - boarder_y / 2 self._applied_max_x = self._cur_max_x + boarder_x / 2 self._applied_max_y = self._cur_max_y + boarder_y / 2 elif self.plot_typ == 'histogram': self._cur_min_x = np.min(self._xdata[:-1]) - boarder_x self._cur_min_y = 0 self._cur_max_x = np.max(self._xdata[:-1]) + boarder_x self._cur_max_y = np.max(self._ydata) + boarder_y self._applied_min_x = self._cur_min_x self._applied_min_y = self._cur_min_y self._applied_max_x = self._cur_max_x self._applied_max_y = self._cur_max_y + boarder_y / 2 update = True return update @pyqtSlot() def do_data_reset(self): if self.plot_typ in ('values', 'histogram'): self._cur_min_x = 0.5 self._cur_max_x = 0.6 self._cur_min_y = 0.5 self._cur_max_y = 0.6 self._applied_min_x = 0.5 self._applied_max_x = 0.6 self._applied_min_y = 0.5 self._applied_max_y = 0.6 for canvas in self._canvas_list: canvas.mpl_canvas.axes.set_xlim(self._applied_min_x, self._applied_max_x) canvas.mpl_canvas.axes.set_ylim(self._applied_min_y, self._applied_max_y) canvas.mpl_canvas.draw() @pyqtSlot() def update_figure(self, do_message=False): try: is_active = self.parent.parent.content[ self.parent.parent_layout] == self.parent.parent.content[ self.parent.parent_layout].latest_active[0] overview_is_floating = self.twin_container.dock_widget.isFloating( ) if self.twin_canvas is not None else False if not self.dock_widget.isFloating( ) and not is_active and not overview_is_floating: return if not self._plot_ref: return if not self.update_data(do_message): return if self.plot_typ in ('values', 'histogram'): try: update = self.prepare_axes( update=self._plot_ref[0] is None) except ValueError as e: print(e) return for plot_idx, canvas in enumerate(self._canvas_list): if update and self._mean_ref[plot_idx] is not None: for entry in self._mean_ref[plot_idx]: entry.remove() if update and self._median_ref[plot_idx] is not None: for entry in self._median_ref[plot_idx]: entry.remove() if update and self._plot_ref[plot_idx] is not None: for entry in self._plot_ref[plot_idx]: entry.remove() if self.plot_typ == 'values': self.update_values(canvas.mpl_canvas, plot_idx, update) elif self.plot_typ == 'histogram': self.update_histogram(canvas.mpl_canvas, plot_idx, update) self.update_helpers(canvas.mpl_canvas, plot_idx, update, self.plot_typ) if update: canvas.mpl_canvas.axes.set_xlim( self._applied_min_x, self._applied_max_x) canvas.mpl_canvas.axes.set_ylim( self._applied_min_y, self._applied_max_y) canvas.mpl_canvas.draw() else: canvas.mpl_canvas.update() canvas.mpl_canvas.flush_events() if plot_idx == 0: output_name = os.path.join( self._directory_name, 'overview_plots', '{0}_{1}.png'.format( self.label, self.plot_typ, )).replace(' ', '_') try: tu.mkdir_p(os.path.dirname(output_name)) canvas.mpl_canvas.fig.savefig(output_name) except Exception as e: print(e) pass elif self.plot_typ in ('image'): self.update_image() except Exception: pass def update_image(self): current_name = self.current_image_name if current_name == 'latest': try: current_name = self._basenames[-1] except IndexError: return except TypeError: return elif not current_name: return try: data_list = self._data['image'][self._basenames == current_name][0].split(';;;') except IndexError: return except KeyError: self.clear_canvas() return if len(data_list) != len(self._canvas_list): self.clear_canvas() for _ in range(len(data_list)): self.add_canvas() for idx, data_file in enumerate(data_list): label_x = '' label_y = '' if data_file.endswith('.jpg'): try: data = imageio.imread(data_file)[::-1, ...] except Exception as e: print('Error reading image: {}. - {}'.format( data_file, str(e))) continue if self._plot_ref[idx] is None: self._plot_ref[idx] = [ self._canvas_list[idx].mpl_canvas.axes.imshow( data, resample=False, aspect='equal') ] self._canvas_list[idx].mpl_canvas.axes.set_xlim( 0, data.shape[1] - 1) self._canvas_list[idx].mpl_canvas.axes.set_ylim( 0, data.shape[0] - 1) else: self._plot_ref[idx][0].set_data(data) self._canvas_list[idx].mpl_canvas.axes.grid(False) self._canvas_list[idx].mpl_canvas.axes.get_xaxis().set_visible( False) self._canvas_list[idx].mpl_canvas.axes.get_yaxis().set_visible( False) elif data_file.endswith('.json'): try: with open(data_file, 'r') as read: json_data = json.load(read) except Exception as e: print('Error reading image: {}. - {}'.format( data_file, str(e))) continue for entry in self._image_ref: for plot_obj in entry: try: plot_obj.remove() except Exception as e: print(e, plot_obj) self._image_ref = [] plot_idx = 0 label_x = json_data['label_x'] label_y = json_data['label_y'] try: is_equal = json_data['is_equal'] except KeyError: is_equal = True min_x = [] max_x = [] min_y = [] max_y = [] for data_dict in json_data['data']: if is_equal: max_abs = np.maximum( np.max(np.abs(data_dict['values_x'])), np.max(np.abs(data_dict['values_y'])), ) min_x.append(-max_abs - np.maximum(max_abs * 0.1, 1)) max_x.append(max_abs + np.maximum(max_abs * 0.1, 1)) min_y.append(-max_abs - np.maximum(max_abs * 0.1, 1)) max_y.append(max_abs + np.maximum(max_abs * 0.1, 1)) else: min_x.append(np.min(data_dict['values_x'])) max_x.append(np.max(data_dict['values_x'])) min_y.append(np.min(data_dict['values_y'])) max_y.append(np.max(data_dict['values_y'])) self.update_image_plot( self._canvas_list[idx].mpl_canvas, data_dict['values_x'], data_dict['values_y'], data_dict['is_high_res'], data_dict['label_plot'], data_dict['marker'], data_dict['color'], plot_idx, ) plot_idx += 1 self._canvas_list[idx].mpl_canvas.axes.set_xlim( np.min(min_x), np.max(max_x)) self._canvas_list[idx].mpl_canvas.axes.set_ylim( np.min(min_y), np.max(max_y)) self._canvas_list[idx].update_labels( tu.split_maximum(tu.get_name(data_file), 20, '_'), label_x, label_y, ) self._canvas_list[idx].mpl_canvas.draw() def update_histogram(self, canvas, plot_idx, update): try: width = self._xdata[1] - self._xdata[0] except IndexError: return if update: self._plot_ref[plot_idx] = canvas.axes.bar(self._xdata[:-1], self._ydata, width, facecolor=self._color, edgecolor='k') else: try: canvas.axes.draw_artist(canvas.axes.patch) canvas.axes.draw_artist(canvas.axes.gridline) except AttributeError: canvas.draw() for value, patch in zip(self._ydata, self._plot_ref[plot_idx]): if patch.get_height() != value: patch.set_height(value) patch.set_width(width) try: canvas.axes.draw_artist(patch) except AttributeError: canvas.draw() def update_helpers(self, canvas, plot_idx, update, plot_type): if not self._hide_marker: mean = [self.mean, self.mean] median = [self.median, self.median] if plot_type == 'values': max_x = np.max(np.abs(self._xdata)) * 1e5 values_x = [ np.min(self._xdata) - max_x, np.max(self._xdata) + max_x ] values = [[self._mean_ref, values_x, mean, LIGHTBLUE], [self._median_ref, values_x, median, LIGHTRED]] elif plot_type == 'histogram': max_y = np.max(np.abs(self._ydata)) * 1e5 values_y = [ np.min(self._ydata) - max_y, np.max(self._ydata) + max_y ] values = [[self._mean_ref, mean, values_y, LIGHTBLUE], [self._median_ref, median, values_y, LIGHTRED]] for aim_list, values_x, values_y, color in values: if update: aim_list[plot_idx] = canvas.axes.plot( values_x, values_y, color=color, linewidth=0.8, ) else: aim_list[plot_idx][0].set_data(values_x, values_y) try: canvas.axes.draw_artist(aim_list[plot_idx][0]) except AttributeError: canvas.draw() def update_values(self, canvas, plot_idx, update): if update: self._plot_ref[plot_idx] = canvas.axes.plot( self._xdata, self._ydata, '.', color=self._color, markersize=self.markersize / (plot_idx + 1)) else: self._plot_ref[plot_idx][0].set_data(self._xdata, self._ydata) try: canvas.axes.draw_artist(canvas.axes.patch) canvas.axes.draw_artist(canvas.axes.gridline) canvas.axes.draw_artist(self._plot_ref[plot_idx][0]) except AttributeError: canvas.draw() @staticmethod def high_res(x_data, y_data, splits): cm = matplotlib.cm.get_cmap('viridis') if splits != 1: n_points = (len(x_data) - 1) * (splits - 1) colors = [cm(1. * i / (n_points - 1)) for i in range(n_points)] new_values = [] for i in range(len(x_data) - 1): new_x = np.linspace(x_data[i], x_data[i + 1], splits) new_y = np.linspace(y_data[i], y_data[i + 1], splits) for i in range(splits - 1): new_values.append([new_x[i:i + 2], new_y[i:i + 2]]) else: n_points = len(x_data) colors = [cm(1. * i / (n_points - 1)) for i in range(n_points)] new_values = np.array([x_data, y_data]).T return colors, new_values def update_image_plot(self, canvas, data_x, data_y, high_res, label, marker, color, idx): if high_res: color, vals = self.high_res(data_x, data_y, 30) canvas.axes.set_prop_cycle('color', color) for x, y in vals: self._image_ref.append(canvas.axes.plot( x, y, '-', )) color, vals = self.high_res(data_x, data_y, 1) canvas.axes.set_prop_cycle('color', color) for x, y in vals: self._image_ref.append(canvas.axes.plot( x, y, 'o', )) else: if color is None: color = self._color self._image_ref.append( canvas.axes.plot( data_x, data_y, marker, label=label, color=color, markeredgecolor='black', markersize=6, )) self._image_ref.append([canvas.axes.legend(loc='best')])
class View(QWidget): def __init__(self, W): self.W = int(W) super().__init__() self.sounds = Models(self) self.sounds.initSound() self.image_index = 0 # Keeps track of the first image in image list to be displayed in the thumbnail bar self.mode = 0 # Determines and Tracks current mode of view (1 - Full Screen, 0 - Thumbnail) self.selected_index = 0 # Keeps track of the current selected index in the thumbnail bar self.loadTags() self.initUI() def initUI(self): self.setWindowTitle("Image Browser") self.setStyleSheet("background-color: #324d7a") self.H = (self.W/4)*3 self.move(250, 250) self.setFixedSize(self.W, self.H) # Setting-up Layout for images self.layout = QHBoxLayout(self) # Creates a Horizontal Layout self.layout.setContentsMargins(20, 0, 20, 0) # Removes margins around stored object in the layout self.layout.setSpacing(0) # Removes spaces between layout objects self.layout.setAlignment(Qt.AlignCenter) # Pushes image to the top of the window # Setting-up text box for adding tags self.textBox = QLineEdit(self) self.textBox.setStyleSheet("QLineEdit{ background: #f8f8f8; selection-background-color: #f8f8f8; }") self.textBox.setPlaceholderText("Enter your tags here") self.textBox.resize(self.W/2,self.H/10) self.textBox.move(20, self.H*(5/6)) # Setting-up add and save buttons for tags self.addButton = QPushButton('Add Tag', self) self.addButton.setStyleSheet("background-color: #F5F5F5") self.addButton.move(self.W/1.9,self.H*(5/6)) self.addButton.resize(self.W/6, self.H/10) self.addButton.clicked.connect(self.addTag) self.saveButton = QPushButton('Save Tags', self) self.saveButton.setStyleSheet("background-color: #F5F5F5") self.saveButton.move(self.W/1.42,self.H*(5/6)) self.saveButton.resize(self.W/6, self.H/10) self.saveButton.clicked.connect(self.saveTags) # Setting up layout for holding tags self.tagList = QVBoxLayout() self.tagList.setSpacing(10) self.tagList.setContentsMargins(40, 0, 5, 0) self.textBox.hide() self.addButton.hide() self.saveButton.hide() self.thumbnail_bar() self.select(0) # Selects first image-box in layou self.show() def thumbnail_bar(self): # Creates a List of QLabels and places them in a horizontal Layout labels = [] for i in range(0, 6): labels.insert(i, QLabel(self)) if i != (5): labels[i].setPixmap(QPixmap("data/"+Models.images[i]).scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) # Sets images to each label in layout labels[i].setFixedSize((self.W-40)/5, (self.W-40)/5) labels[i].setAlignment(Qt.AlignCenter) # Align images to the center of the label labels[i].setStyleSheet('border: 10px solid red') self.layout.addWidget(labels[i]) # Add label into layout container clickable(self.getWidget(i)).connect(self.indexOfLabel) # Connects the click even to the indexOfLabel function # Properties of full screen view label: self.getWidget(5).setStyleSheet('border: 20px solid red') self.getWidget(5).setFixedSize(self.W/1.33, self.H/1.28) self.getWidget(5).hide() def drawTags(self): image_key = str((self.image_index+self.selected_index)%len(Models.images)) if image_key in self.tags: for i in range(0, len(self.getTags())): self.getTags().itemAt(0).widget().setParent(None) for tag in self.tags[image_key]: self.getTags().addWidget(QPushButton(tag, self)) self.getTags().itemAt(len(self.getTags())-1).widget().setStyleSheet("background-color: #f5f5f5") else: for i in range(0, len(self.getTags())): item = self.getTags().itemAt(0).widget().setParent(None) def enlarge(self, index): # Makes necessary changes to change to Full Screen (Window Fill) Mode self.sounds.expand_sound.play() self.layout.addLayout(self.tagList) # Adding TagList layout to main layout self.mode = 1 self.selected_index = index pixContainer = self.getWidget(index).pixmap() for i in range(0, 5): self.getWidget(i).hide() self.getWidget(5).show() # Shows label that displays in full screen self.getWidget(5).setPixmap(pixContainer.scaled((self.W/1.33)-40, (self.H/1.28)-40, Qt.KeepAspectRatio)) # Sets image in selected label to full screen label self.layout.setContentsMargins(0, 0, 0, 0) # Pushes image to the top of the window self.layout.setAlignment(Qt.AlignTop | Qt.AlignLeft) # Pushes image to the top of the window self.getTags().setAlignment(Qt.AlignRight) self.textBox.show() self.addButton.show() self.saveButton.show() self.drawTags() def circularTraverse(self, steps, direction): # Responsible for Circular Traversing the image list in the given direction if direction == "left": return (self.image_index-steps)%(len(Models.images)) else: return (self.image_index+steps)%(len(Models.images)) def select(self, selected_index): # Selects new item self.getWidget(self.selected_index).setStyleSheet("border: 10px solid red") # Changes old image box to not selected border self.getWidget(selected_index).setStyleSheet("border: 10px solid green") # Changes new image box to selected border self.selected_index = selected_index # Updates Current selection index def shiftLeft(self): # Shifts the select box and scope of the Thumbnail Bar to the left if self.selected_index != 0: # Shift select box till first image if self.mode == 1: pixContainer = self.getWidget(self.selected_index-1).pixmap() self.getWidget(5).setPixmap(pixContainer.scaled((self.W/1.33)-40, (self.H/1.28)-40, Qt.KeepAspectRatio)) self.select(self.selected_index-1) else: if 5 == 5: # If there are more than 5 images, shift scope of Thumbnail Bar to left for i in range(4, 0, -1): # Shifts scope self.getWidget(i).setPixmap(self.getWidget(i-1).pixmap().scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) self.getWidget(0).setPixmap(QPixmap("data/"+Models.images[self.circularTraverse(1, "left")]).scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) if self.mode == 1: # If in full screen mode, load previous image self.getWidget(5).setPixmap(self.getWidget(0).pixmap().scaled((self.W/1.33)-40, (self.H/1.28)-40, Qt.KeepAspectRatio)) self.image_index = self.circularTraverse(1, "left") def shiftRight(self): # Shifts the select box and scope of the Thumbnail Bar to the right if self.selected_index != 4: # Shift select box till last image if self.mode == 1: pixContainer = self.getWidget(self.selected_index+1).pixmap() self.getWidget(5).setPixmap(pixContainer.scaled((self.W/1.33)-40, (self.H/1.28)-40, Qt.KeepAspectRatio)) self.select(self.selected_index+1) else: if 5 == 5: # If there are more than 5 images, shift scope of Thumbnail Bar to rght for i in range(0, 4): # Shifts scope self.getWidget(i).setPixmap(self.getWidget(i+1).pixmap().scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) self.getWidget(4).setPixmap(QPixmap("data/"+Models.images[self.circularTraverse(5, "right")]).scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) if self.mode == 1: # If in full screen mode, load next image self.getWidget(5).setPixmap(self.getWidget(4).pixmap().scaled((self.W/1.33)-40, (self.H/1.28)-40, Qt.KeepAspectRatio)) self.image_index = self.circularTraverse(1, "right") def shrink(self, index): # Makes necessary changes to change back to Thumbnail Mode self.sounds.expand_sound.play() self.mode = 0 # Upadates mode variable self.getWidget(5).hide() # Hides full screen label for i in range(0,5): # Un-hides thumbnail labels self.getWidget(i).show() self.layout.setContentsMargins(20, 0, 20, 0) self.layout.setAlignment(Qt.AlignVCenter) # Pushes image to the top of the window self.textBox.hide() self.addButton.hide() self.saveButton.hide() for i in range(0, len(self.getTags())): self.getTags().itemAt(0).widget().setParent(None) self.layout.removeItem(self.tagList) #=========================================== EVENT HANDLERS ========================================= def loadTags(self): # If file exists, open and load tags. If does not exist, initialize empty tags dictionary try: f = open("tags.json","r") self.tags = json.load(f) f.close() except: self.tags = {} def addTag(self): # Add tag if not empty string or spaces if not (self.textBox.text().isspace() or self.textBox.text() == ""): image_key = str((self.image_index+self.selected_index)%len(Models.images)) # Generating image key for dictionary from unique combination of image_index and selected_index if image_key not in self.tags: # If no tags exist, create a new list for tags self.tags[image_key] = [] self.tags[image_key].append(self.textBox.text()) # Append to the tags lis of image self.textBox.setText("") self.setFocus() # Return focus to main window self.drawTags() def saveTags(self): f = open("tags.json", "w+") # Create file if does not exist json.dump(self.tags, f) # save tags in file print("{} saved".format(self.tags)) f.close() self.setFocus() # Return focus back to window def getWidget(self, index): # Gets stored widget from layout in the passed index return self.layout.itemAt(index).widget() def getTags(self): return self.layout.itemAt(6).layout() def indexOfLabel(self, label): # Provides the index of the clicked label for further operations self.setFocus() if self.mode == 0: self.select(self.layout.indexOf(label)) self.enlarge(self.layout.indexOf(label)) def keyPressEvent(self, e): # Handles all key press events if e.key() == Qt.Key_Right: self.sounds.select_sound.play() self.shiftRight() if self.mode == 1: self.drawTags() if e.key() == Qt.Key_Left: self.sounds.select_sound.play() self.shiftLeft() if self.mode == 1: self.drawTags() elif e.key() == Qt.Key_Period and self.mode == 0 and 5 == 5: # Moves to the next 5 images only if there are enough images to overflow self.sounds.next_set_sound.play() self.image_index=self.circularTraverse(5, "right") for i in range(0,5): self.getWidget(i).setPixmap(QPixmap("data/"+Models.images[self.circularTraverse(i, "right")]).scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) self.select(0) elif e.key() == Qt.Key_Comma and self.mode == 0 and 5 == 5: # Moves to the previous 5 images only if there are enough images to overflow self.sounds.next_set_sound.play() self.image_index=self.circularTraverse(5, "left") for i in range(0,5): self.getWidget(i).setPixmap(QPixmap("data/"+Models.images[self.circularTraverse(i, "right")]).scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) self.select(0) elif e.key() == Qt.Key_Up and self.mode == 0: self.enlarge(self.selected_index) elif e.key() == Qt.Key_Down and self.mode == 1: self.setFocus() self.shrink(self.selected_index) if 5 == 5: # Checks if there are more than 5 images center_distance = self.selected_index - 2 # Calculates the distance of the seleted image from the center box if center_distance > 0: # Checks if the selected image is right of center # Shifts thumbnail bar accordingly to place selected image in middle on coming back to thumbnai bar mode: for i in range(0, center_distance): for j in range(0,4): self.getWidget(j).setPixmap(self.getWidget(j+1).pixmap().scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) self.getWidget(4).setPixmap(QPixmap("data/"+Models.images[self.circularTraverse(5, "right")]).scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) self.image_index = self.circularTraverse(1, "right") elif center_distance < 0: # Checks if selected image is left of center # Shifts thumbnail bar accordingly to place selected image in middle on coming back to thumbnai bar mode: for i in range(0, abs(center_distance)): for j in range(4, 0, -1): self.getWidget(j).setPixmap(self.getWidget(j-1).pixmap().scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) self.getWidget(0).setPixmap(QPixmap("data/"+Models.images[self.circularTraverse(1, "left")]).scaled(((self.W-40)/5)-20, ((self.W-40)/5)-20, Qt.KeepAspectRatio)) self.image_index = self.circularTraverse(1, "left") self.select(2) elif e.key() == Qt.Key_Escape: # Returns focus back to main window self.setFocus()