def create_application_menubar(cls): if not cls.__actions: mb = QMenuBar(None) menu = QMenu() for action in cls.get_menubar_actions(): menu.addAction(action) cls.__actions.append(action) mb.addMenu(menu) cls.___menu_bar = mb cls.___menu = menu return cls.__actions
class ImageViewer(QWidget): def __init__(self): super(ImageViewer, self).__init__() pal = QPalette() pal.setColor(QPalette.Background, Qt.lightGray) self.factor = 3.0 self.config = Config() self.currentRep = "" self.createActions() self.createToolbarMenus() #self.createMenus() self.browserFile() self.imgqLabel() self.boxSliders() self.verticalLayout = QVBoxLayout(self) self.horizontalLayout = QHBoxLayout(self) self.textInfo = QTextEdit() self.textInfoTop = QTextEdit() self.textInfoTop.setEnabled(True) self.textInfoTop.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Ignored) self.textInfoTop.setFontPointSize(11) self.textInfoTop.setStyleSheet("background-color: lightgray") #self.textInfoTop.adjustSize() self.textInfoTop.setText('Welcome to IRMaGe') self.tableJson = QTableWidget() self.tableJson.setColumnCount(2) self.tableJson.setColumnWidth(0, 150) self.tableJson.setColumnWidth(1, 400) self.tableJson.setSizeAdjustPolicy( QAbstractScrollArea.AdjustToContents) self.tableJson.setHorizontalHeaderLabels(['Keys', 'Values']) #self.tableJson.setBackgroundRole(QPalette.Light) self.scrollText = QScrollArea() self.scrollText.setBackgroundRole(QPalette.Dark) self.scrollText.setWidget(self.textInfoTop) self.scrollText.setWidgetResizable(True) #======================================================================= # self.adjustScrollBar(self.scrollText.horizontalScrollBar(), 1.0) # self.adjustScrollBar(self.scrollText.verticalScrollBar(), 2.0) #======================================================================= self.scrollTable = QScrollArea() self.scrollTable.setBackgroundRole(QPalette.Dark) self.scrollTable.setWidget(self.tableJson) self.scrollTable.setWidgetResizable(True) #======================================================================= # self.adjustScrollBar(self.scrollTable.horizontalScrollBar(), 2.0) # self.adjustScrollBar(self.scrollTable.verticalScrollBar(), 2.0) #======================================================================= self.headerTabData = [ 'Data', 'PatientName', 'StudyName', 'DateCreation', 'PatientSex', 'PatientWeight', 'ProtocolName', 'SequenceName' ] self.tableData = TableDataBrower(self) self.tableData.setColumnCount(8) self.tableData.setRowCount(10) self.tableData.setColumnWidth(0, 200) self.tableData.setHorizontalHeaderLabels(self.headerTabData) self.tableData.setBackgroundRole(QPalette.Light) self.tableData.setSizeAdjustPolicy( QAbstractScrollArea.AdjustToContents) self.tableData.verticalHeader().hide() self.scrollBrowser = QScrollArea() self.scrollBrowser.setBackgroundRole(QPalette.Dark) self.scrollBrowser.setWidget(self.tableData) self.scrollBrowser.setWidgetResizable(True) self.splitter0 = QSplitter(Qt.Vertical) self.splitter0.addWidget(self.scrollText) self.splitter0.addWidget(self.scrollTable) self.scrollArea = QScrollArea() self.scrollArea.setBackgroundRole(QPalette.Dark) self.scrollArea.setWidget(self.imageLabel) self.scrollArea.setWidgetResizable(False) self.scrollArea.setAlignment(Qt.AlignCenter) self.adjustScrollBar(self.scrollArea.horizontalScrollBar(), 0.8) self.adjustScrollBar(self.scrollArea.verticalScrollBar(), 1.0) self.splitter1 = QSplitter(Qt.Horizontal) self.splitter1.addWidget(self.splitter0) self.splitter1.addWidget(self.scrollArea) self.splitter1.addWidget(self.layoutSlide) self.splitter3 = QSplitter(Qt.Horizontal) self.splitter3.addWidget(self.browser) self.splitter3.addWidget(self.scrollBrowser) self.splitter2 = QSplitter(Qt.Vertical) self.splitter2.addWidget(self.splitter1) self.splitter2.addWidget(self.splitter3) self.splitter2.setHandleWidth(15) #======================================================================= # self.splitter2. #======================================================================= self.verticalLayout.addWidget(self.menuToolBar) self.verticalLayout.addWidget(self.splitter2) self.setWindowTitle("MRImage Viewer (IRMaGe)") self.resize(800, 600) self.setAutoFillBackground(True) self.setPalette(pal) def changeSel(self): print('Tab changed') def adjustScrollBar(self, scrollBar, factor): scrollBar.setValue( int(factor * scrollBar.value() + ((factor - 1) * scrollBar.pageStep() / 2))) def imgqLabel(self): QLabel.__init__(self) image = QImage('sources_images/LogoIRMaGe.png') self.scaleFactor = 1.0 self.imageLabel = QLabel() self.imageLabel.setBackgroundRole(QPalette.Base) self.imageLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.imageLabel.setScaledContents(True) self.imageLabel.setPixmap(QPixmap.fromImage(image)) self.scaleFactor *= self.factor self.imageLabel.adjustSize() self.imageLabel.resize(self.scaleFactor * self.imageLabel.pixmap().size()) def open(self, filePath): self.img = nib.load(filePath) self.textInfoTop.setText('File : ' + filePath + '\n') self.textInfoTop.append('Dim : ' + str(self.img.shape) + '\n') self.enableSliders() self.a1.setValue(0) self.a2.setValue(0) self.a3.setValue(0) self.c2.setMaximum(self.img.shape[0]) self.c2.setMinimum(-self.img.shape[0]) self.c3.setMaximum(self.img.shape[1]) self.c3.setMinimum(-self.img.shape[1]) self.navigImage() self.fitToWindowAct.setEnabled(True) self.fitToWindow() def openJson(self, pathJson, fileName): with open(pathJson, 'r') as stream: try: json_object = json.load(stream) data = json.dumps(json_object, indent=0, sort_keys=True) data = json.loads(data) rowPosition = 0 self.tableJson.setRowCount(0) i = 0 for keyd in self.headerTabData: try: val = str(data[keyd]) val = val.replace('[', '') val = val.replace(']', '') except: val = '' #=========================================================== # self.tableData.insertRow(i) # self.tableData.setItem(0,i,QTableWidgetItem(val)) # i+=1 #=========================================================== #=============================================================== # self.tableData.setItem(0,0,QTableWidgetItem(fileName)) # self.tableData.selectRow(0) #=============================================================== for keys in data: stringValue = str(data[keys]) stringValue = stringValue.replace('[', '') stringValue = stringValue.replace(']', '') self.tableJson.insertRow(rowPosition) self.tableJson.setItem(rowPosition, 0, QTableWidgetItem(keys)) self.tableJson.setItem(rowPosition, 1, QTableWidgetItem(stringValue)) rowPosition += 1 self.tableJson.resizeColumnsToContents() except json.JSONDecodeError as exc: itemError = 'Error Json format' self.tableJson.setRowCount(0) self.tableJson.insertRow(0) self.tableJson.setItem(0, 0, QTableWidgetItem(itemError)) print(exc) def jsonParser(self, pathJson): with open(pathJson, 'r') as stream: try: json_object = json.load(stream) listTag = json.dumps(json_object, indent=0, sort_keys=True) listTag = json.loads(listTag) except json.JSONDecodeError as exc: itemError = 'Error Json format' return listTag def tableDataFill(self, pathRepertory): files = [f for f in fnmatch.filter(os.listdir(pathRepertory), '*.nii')] self.tableData.setRowCount(0) j = 0 for f in files: base = os.path.splitext(f)[0] g = os.path.join(pathRepertory, base + ".json") self.tableData.insertRow(j) if os.path.isfile(g): data = self.jsonParser(g) i = 0 for keyw in self.headerTabData: try: val = str(data[keyw]) val = val.replace('[', '') val = val.replace(']', '') except: val = '' self.tableData.setItem(j, i, QTableWidgetItem(val)) i += 1 else: self.tableData.setItem(j, 1, QTableWidgetItem('No json file found')) self.tableData.setItem(j, 0, QTableWidgetItem(f)) self.tableData.resizeColumnsToContents() j += 1 def indexImage(self): sl1 = self.a1.value() sl2 = self.a2.value() sl3 = self.a3.value() if len(self.img.shape) == 3: x = self.img.get_data()[:, :, sl1].copy() self.a1.setMaximum(self.img.shape[2] - 1) self.a2.setMaximum(0) self.a3.setMaximum(0) if len(self.img.shape) == 4: x = self.img.get_data()[:, :, sl1, sl2].copy() self.a1.setMaximum(self.img.shape[2] - 1) self.a2.setMaximum(self.img.shape[3] - 1) self.a3.setMaximum(0) if len(self.img.shape) == 5: x = self.img.get_data()[:, :, sl1, sl2, sl3].copy() self.a1.setMaximum(self.img.shape[2] - 1) self.a2.setMaximum(self.img.shape[3] - 1) self.a3.setMaximum(self.img.shape[4] - 1) x = rotate(x, -90, reshape=False) x = np.uint8((x - x.min()) / x.ptp() * 255.0) self.x = x ############################ Slice controls ######################################### def boxSliders(self): self.k1 = QLabel('Slider 1 ') self.k2 = QLabel('Slider 2') self.k3 = QLabel('Slider 3') self.a1 = self.createSlider(0, 0, 0) self.a2 = self.createSlider(0, 0, 0) self.a3 = self.createSlider(0, 0, 0) self.a1.valueChanged.connect(self.changePosValue) self.a2.valueChanged.connect(self.changePosValue) self.a3.valueChanged.connect(self.changePosValue) self.txta1 = self.createFieldValue() self.txta2 = self.createFieldValue() self.txta3 = self.createFieldValue() self.controlsGroup = QGroupBox('Slice Controls') gridCtrl = QGridLayout() gridCtrl.addWidget(self.k1, 0, 0) gridCtrl.addWidget(self.a1, 0, 1) gridCtrl.addWidget(self.txta1, 0, 2) gridCtrl.addWidget(self.k2, 1, 0) gridCtrl.addWidget(self.a2, 1, 1) gridCtrl.addWidget(self.txta2, 1, 2) gridCtrl.addWidget(self.k3, 2, 0) gridCtrl.addWidget(self.a3, 2, 1) gridCtrl.addWidget(self.txta3, 2, 2) self.controlsGroup.setLayout(gridCtrl) ############################ brightness and contrast ################################ self.txtb1 = self.createFieldValue() self.txtb2 = self.createFieldValue() self.txtb3 = self.createFieldValue() self.txtb4 = self.createFieldValue() self.l1 = QLabel('Brightness ') self.b1 = self.createSlider(101, 0, 50) self.l2 = QLabel('Contrast') self.b2 = self.createSlider(101, 0, 50) self.l3 = QLabel('Sharpness') self.b3 = self.createSlider(101, 0, 50) self.l4 = QLabel('Color') self.b4 = self.createSlider(101, 0, 50) self.b1.valueChanged.connect(self.changeContValue) self.b2.valueChanged.connect(self.changeContValue) self.b3.valueChanged.connect(self.changeContValue) self.b4.valueChanged.connect(self.changeContValue) self.txtb1.setText(str(0)) self.txtb2.setText(str(0)) self.txtb3.setText(str(0)) self.txtb4.setText(str(0)) self.buttonResetContrast = QPushButton('reset', self) self.buttonResetContrast.setToolTip('Reset all values') self.buttonResetContrast.setEnabled(False) self.buttonResetContrast.clicked.connect(self.resetValuesContrast) self.contrastGroup = QGroupBox('Brightness and Contrast') gridCont = QGridLayout() gridCont.addWidget(self.l1, 0, 0) gridCont.addWidget(self.b1, 0, 1) gridCont.addWidget(self.txtb1, 0, 2) gridCont.addWidget(self.l2, 1, 0) gridCont.addWidget(self.b2, 1, 1) gridCont.addWidget(self.txtb2, 1, 2) gridCont.addWidget(self.l3, 2, 0) gridCont.addWidget(self.b3, 2, 1) gridCont.addWidget(self.txtb3, 2, 2) gridCont.addWidget(self.l4, 3, 0) gridCont.addWidget(self.b4, 3, 1) gridCont.addWidget(self.txtb4, 3, 2) gridCont.addWidget(self.buttonResetContrast, 4, 2) self.contrastGroup.setLayout(gridCont) ############################ Transformation ######################################### self.txtc1 = self.createFieldValue() self.txtc2 = self.createFieldValue() self.txtc3 = self.createFieldValue() self.txtc4 = self.createFieldValue() self.m1 = QLabel('Rotation') self.c1 = self.createSlider(180, -180, 0) self.m2 = QLabel('Translate X ') self.c2 = self.createSlider(1, -1, 0) self.m3 = QLabel('Translate Y ') self.c3 = self.createSlider(1, -1, 0) self.m4 = QLabel('Resize') self.c4 = self.createSlider(10, 0, 0) self.c1.valueChanged.connect(self.changeTransValue) self.c2.valueChanged.connect(self.changeTransValue) self.c3.valueChanged.connect(self.changeTransValue) self.c4.valueChanged.connect(self.changeTransValue) self.txtc1.setText(str(0)) self.txtc2.setText(str(0)) self.txtc3.setText(str(0)) self.txtc4.setText(str(0)) self.buttonResetTransform = QPushButton('reset', self) self.buttonResetTransform.setToolTip('Reset all values') self.buttonResetTransform.setEnabled(False) self.buttonResetTransform.clicked.connect(self.resetValuesTransform) self.transformationGroup = QGroupBox('Transformations') gridTransf = QGridLayout() gridTransf.addWidget(self.m1, 0, 0) gridTransf.addWidget(self.c1, 0, 1) gridTransf.addWidget(self.txtc1, 0, 2) gridTransf.addWidget(self.m2, 1, 0) gridTransf.addWidget(self.c2, 1, 1) gridTransf.addWidget(self.txtc2, 1, 2) gridTransf.addWidget(self.m3, 2, 0) gridTransf.addWidget(self.c3, 2, 1) gridTransf.addWidget(self.txtc3, 2, 2) gridTransf.addWidget(self.m4, 3, 0) gridTransf.addWidget(self.c4, 3, 1) gridTransf.addWidget(self.txtc4, 3, 2) gridTransf.addWidget(self.buttonResetTransform, 4, 2) self.transformationGroup.setLayout(gridTransf) #################################################################################### self.layoutSliders = QVBoxLayout() self.layoutSliders.addWidget(self.controlsGroup) self.layoutSliders.addWidget(self.contrastGroup) self.layoutSliders.addWidget(self.transformationGroup) self.layoutSlide = QWidget() self.layoutSlide.setLayout(self.layoutSliders) def createSlider(self, maxm=0, minm=0, pos=0): slider = QSlider(Qt.Horizontal) slider.setFocusPolicy(Qt.StrongFocus) #slider.setTickPosition(QSlider.TicksBothSides) slider.setTickInterval(1) #slider.setSingleStep(1) slider.setMaximum(maxm) slider.setMinimum(minm) slider.setValue(pos) slider.setEnabled(False) return slider def createFieldValue(self): fieldValue = QLineEdit() fieldValue.setEnabled(False) fieldValue.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) return fieldValue def displayPosValue(self): self.txta1.setText( str(self.a1.value() + 1) + ' / ' + str(self.a1.maximum() + 1)) self.txta2.setText( str(self.a2.value() + 1) + ' / ' + str(self.a2.maximum() + 1)) self.txta3.setText( str(self.a3.value() + 1) + ' / ' + str(self.a3.maximum() + 1)) def changePosValue(self): self.navigImage() def navigImage(self): self.indexImage() self.displayPosValue() w, h = self.x.shape image = QImage(self.x.data, w, h, QImage.Format_Indexed8) self.pixm = QPixmap.fromImage(image) self.imageLabel.setPixmap(self.pixm) self.imageLabel.adjustSize() self.imageLabel.resize(self.scaleFactor * self.imageLabel.pixmap().size()) self.filter() def changeContValue(self): self.txtb1.setText(str(self.b1.value() - 50)) self.txtb2.setText(str(self.b2.value() - 50)) self.txtb3.setText(str(self.b3.value() - 50)) self.txtb4.setText(str(self.b4.value() - 50)) self.filter() def changeTransValue(self): self.txtc1.setText(str(self.c1.value())) self.txtc2.setText(str(self.c2.value())) self.txtc3.setText(str(self.c3.value())) self.txtc4.setText(str(self.c4.value())) self.filter() def filter(self): img = Image.fromarray(self.x, 'L') brightness = ImageEnhance.Brightness(img) newImg = brightness.enhance(1.2 * (self.b1.value() + 1) / 50.0) contrast = ImageEnhance.Contrast(newImg) newImg = contrast.enhance((self.b2.value() + 1) / 50.0) sharpness = ImageEnhance.Sharpness(newImg) newImg = sharpness.enhance(2.0 * (self.b3.value() + 1) / 50.0) color = ImageEnhance.Color(newImg) newImg = color.enhance((self.b4.value() + 1) / 50.0) newImg = newImg.rotate(self.c1.value()) newImg = newImg.transform( img.size, Image.AFFINE, (1, 0, self.c2.value(), 0, 1, self.c3.value())) size1 = int(img.size[0] * (self.c4.value() + 1)) size2 = int(img.size[1] * (self.c4.value() + 1)) newImg = newImg.resize((size1, size2), Image.ANTIALIAS) self.pixm = QPixmap.fromImage(newImg.toqimage()) self.imageLabel.setPixmap(self.pixm) self.imageLabel.adjustSize() self.imageLabel.resize(self.scaleFactor * self.imageLabel.pixmap().size()) def resetValuesContrast(self): self.b1.setSliderPosition(50) self.b2.setSliderPosition(50) self.b3.setSliderPosition(50) self.b4.setSliderPosition(50) self.changeContValue() def resetValuesTransform(self): self.c1.setSliderPosition(0) self.c2.setSliderPosition(0) self.c3.setSliderPosition(0) self.c4.setSliderPosition(0) self.changeTransValue() def enableSliders(self): self.a1.setEnabled(True) self.a2.setEnabled(True) self.a3.setEnabled(True) self.b1.setEnabled(True) self.b2.setEnabled(True) self.b3.setEnabled(True) self.b4.setEnabled(True) self.c1.setEnabled(True) self.c2.setEnabled(True) self.c3.setEnabled(True) self.c4.setEnabled(True) self.buttonResetContrast.setEnabled(True) self.buttonResetTransform.setEnabled(True) #################################################################################### def browserFile(self): global Browser, Model self.browser = QTreeView() model = QFileSystemModel() model.setNameFilters(['*.nii']) model.setNameFilterDisables(False) model.setReadOnly(True) self.browser.setModel(model) self.browser.expandAll() self.browser.setColumnWidth(0, 400) self.browser.selectionModel().selectionChanged.connect(self.select) Browser = self.browser Model = model #======================================================================= # self.browser.doubleClicked.connect(self.selection) #self.browser.clicked.connect(self.selection) #======================================================================= def select(self, signal): file_path = self.browser.model().filePath(signal.indexes()[0]) shortName, fileExt = os.path.splitext(file_path) filePath, fileName = os.path.split(file_path) self.textInfo.setText(filePath) blackColor = QColor(0, 0, 0) if os.path.isfile(file_path): if fileExt == ".nii": if self.currentRep != filePath: self.tableDataFill(filePath) self.currentRep = filePath self.open(file_path) self.tableData.selectRow( self.tableData.findItems(fileName, Qt.MatchExactly)[0].row()) if os.path.isfile(shortName + '.json'): greenColor = QColor(50, 150, 100) self.textInfoTop.setTextColor(greenColor) self.textInfoTop.append('Json file exists ' + '\n') self.openJson(shortName + '.json', fileName) else: redColor = QColor(255, 0, 0) self.textInfoTop.setTextColor(redColor) self.textInfoTop.append('Json file doesn\'t exist' + '\n') self.tableJson.setRowCount(0) else: self.tableData.setRowCount(0) self.currentRep = filePath self.textInfoTop.setTextColor(blackColor) self.scrollText.setWidgetResizable(True) #################################################################################### def createMenus(self): self.fileMenu = QMenu("&File", self) self.fileMenu.addAction(self.exitAct) self.viewMenu = QMenu("&View", self) self.viewMenu.addAction(self.zoomInAct) self.viewMenu.addAction(self.zoomOutAct) self.viewMenu.addAction(self.normalSizeAct) self.viewMenu.addSeparator() self.viewMenu.addAction(self.fitToWindowAct) self.viewMenu.addSeparator() self.helpMenu = QMenu("&Help", self) self.helpMenu.addAction(self.aboutAct) self.menuBar = QMenuBar() self.menuBar.addMenu(self.fileMenu) self.menuBar.addMenu(self.viewMenu) self.menuBar.addMenu(self.helpMenu) def createToolbarMenus(self): self.menuToolBar = QToolBar() viewMenu = QToolButton() viewMenu.setText('View') viewMenu.setPopupMode(QToolButton.MenuButtonPopup) aMenu = QMenu() aMenu.addAction(self.zoomInAct) aMenu.addAction(self.zoomOutAct) aMenu.addAction(self.normalSizeAct) aMenu.addSeparator() aMenu.addAction(self.fitToWindowAct) viewMenu.setMenu(aMenu) helpMenu = QToolButton() helpMenu.setText('Help') helpMenu.setPopupMode(QToolButton.MenuButtonPopup) bMenu = QMenu() helpMenu.setMenu(bMenu) self.menuToolBar.addWidget(viewMenu) self.menuToolBar.addWidget(helpMenu) def createActions(self): self.exitAct = QAction("Exit", self, shortcut="Ctrl+Q", triggered=self.close) self.zoomInAct = QAction("Zoom In (25%)", self, shortcut="Ctrl++", enabled=False, triggered=self.zoomIn) self.zoomOutAct = QAction("Zoom Out (25%)", self, shortcut="Ctrl+-", enabled=False, triggered=self.zoomOut) self.normalSizeAct = QAction("Normal Size", self, shortcut="Ctrl+S", enabled=False, triggered=self.normalSize) self.fitToWindowAct = QAction("Fit to Window", self, enabled=False, checkable=True, shortcut="Ctrl+F", triggered=self.fitToWindow) def zoomIn(self): self.factor = 1.25 self.scaleImage(self.factor) def zoomOut(self): self.factor = 0.8 self.scaleImage(self.factor) def normalSize(self): self.imageLabel.adjustSize() self.scaleFactor = 1.0 def fitToWindow(self): fitToWindow = self.fitToWindowAct.isChecked() self.scrollArea.setWidgetResizable(fitToWindow) self.scrollText.setWidgetResizable(fitToWindow) if not fitToWindow: self.normalSize() self.updateActions() def updateActions(self): self.zoomInAct.setEnabled(not self.fitToWindowAct.isChecked()) self.zoomOutAct.setEnabled(not self.fitToWindowAct.isChecked()) self.normalSizeAct.setEnabled(not self.fitToWindowAct.isChecked()) def scaleImage(self, factor): self.scaleFactor *= factor self.imageLabel.resize(self.scaleFactor * self.imageLabel.pixmap().size()) self.adjustScrollBar(self.scrollArea.horizontalScrollBar(), factor) self.adjustScrollBar(self.scrollArea.verticalScrollBar(), factor) self.zoomInAct.setEnabled(self.scaleFactor < 5.0) self.zoomOutAct.setEnabled(self.scaleFactor > 0.333) def close(self): self.close()
class MainWindow(QMainWindow): def __init__(self, app): super(MainWindow, self).__init__() self.app = app print('window created') self.setWindowIcon(QIcon('img/icon.png')) self.setWindowTitle('Kasino') self.setPalette(QPalette(Qt.darkGreen)) self.setup_music() self.statusbar = QStatusBar(self) self.statusbar.setStyleSheet('background: white') self.setStatusBar(self.statusbar) self.statusbar.showMessage('Welcome to the Cassino game!') self.menubar = QMenuBar(self) self.optionsMenu = self.menubar.addMenu('Options') self.music_toggle = QAction() self.music_toggle.setText('Music') self.music_toggle.setShortcut('Ctrl+m') self.music_toggle.setCheckable(True) self.music_toggle.setChecked(True) self.optionsMenu.addAction(self.music_toggle) self.music_toggle.triggered.connect(self.toggle_music) self.speedGroup = QActionGroup(self) self.speedGroup.triggered.connect(self.set_speed) self.slow_speed = QAction('Slow', self.speedGroup) self.slow_speed.setCheckable(True) self.normal_speed = QAction('Normal', self.speedGroup) self.normal_speed.setCheckable(True) self.fast_speed = QAction('Fast', self.speedGroup) self.fast_speed.setCheckable(True) self.vfast_speed = QAction('Very Fast', self.speedGroup) self.vfast_speed.setCheckable(True) self.normal_speed.setChecked(True) self.speed_menu = self.optionsMenu.addMenu('Speed') self.speed_menu.addActions(self.speedGroup.actions()) self.menubar.setMouseTracking(False) self.setMenuBar(self.menubar) self.play_widget = PlayWidget(self) self.main_menu = MainMenu(self) self.start_menu = StartMenu(self) self.widgets = QStackedWidget(self) self.widgets.addWidget(self.play_widget) self.widgets.addWidget(self.main_menu) self.widgets.addWidget(self.start_menu) self.widgets.setCurrentWidget(self.main_menu) self.setCentralWidget(self.widgets) self.setGeometry(25, 50, 1028, 720) self.main_menu.startbutton.clicked.connect(self.init_game) self.main_menu.loadbutton.clicked.connect(self.load_game) self.main_menu.quitbutton.clicked.connect(self.quit) self.play_widget.quit_button.clicked.connect(self.quit_to_menu) self.play_widget.save_button.clicked.connect(self.save_game) self.start_menu.startbutton.clicked.connect(self.start_game) def setup_music(self): self.music = QMediaPlayer() self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.Loop) file_name = "sound/bg.mp3" self.media = QMediaContent(QUrl.fromLocalFile(file_name)) self.playlist.addMedia(self.media) self.music.setPlaylist(self.playlist) self.music.setVolume(20) self.music.play() def toggle_music(self): if self.music.isMuted(): self.music.setMuted(False) self.statusbar.showMessage('Music on', 5000) else: self.music.setMuted(True) self.statusbar.showMessage('Music off', 5000) def set_speed(self, action): if action == self.slow_speed: self.play_widget.speed = 1 elif action == self.normal_speed: self.play_widget.speed = 3 elif action == self.fast_speed: self.play_widget.speed = 4 else: self.play_widget.speed = 6 def start_game(self): self.play_widget.init_game( self.start_menu.extract_info_and_init_game()) self.widgets.setCurrentWidget(self.play_widget) self.statusbar.showMessage('Game launched', 2000) def load_game(self): path = QFileDialog.getOpenFileName(self, 'Open save file', QDir.currentPath() + '/sav')[0] if path != '': game, msg, count = load(path) self.play_widget.resume_from_save(game, msg, count) self.widgets.setCurrentWidget(self.play_widget) self.statusbar.showMessage('Loaded save file', 5000) def save_game(self): path = QFileDialog.getSaveFileName(self, 'Create save file', QDir.currentPath() + '/sav')[0] if path != '': save(path, self.play_widget.game, self.play_widget.export_log(), self.play_widget.move_count) self.statusbar.showMessage('Game saved', 5000) def init_game(self): self.widgets.setCurrentWidget(self.start_menu) self.statusbar.showMessage('Starting new game') def quit_to_menu(self): #Reset playwidget self.widgets.removeWidget(self.play_widget) speed = self.play_widget.speed self.play_widget.setParent(None) self.play_widget = PlayWidget(self) self.play_widget.speed = speed self.widgets.addWidget(self.play_widget) self.play_widget.quit_button.clicked.connect(self.quit_to_menu) self.play_widget.save_button.clicked.connect(self.save_game) self.widgets.setCurrentWidget(self.main_menu) def closeEvent(self, *args, **kwargs): #for handling closing from 'x' button self.quit() def quit(self): print('Exited game. Thanks for playing!\n') self.app.exit()
class MainWidget(QWidget): """Main window class that provides logic of the program. Allows to search concept and to show information about concepts and relations """ def __init__(self, parent=None, application=None): super().__init__(parent) self.parent = parent self.application = application self.db = self.openDatabase() self.initUI() def initActions(self): """initalization of actions for main windows""" self.help_action = QAction("&Help", self) self.help_action.setShortcut("F1") self.help_action.setStatusTip('Help') self.help_action.triggered.connect(lambda: HelpDialog(self)) self.about_action = QAction("&About", self) self.about_action.setStatusTip('About') self.about_action.triggered.connect(self.showAboutMessage) self.new_db_action = QAction("New DB", self) self.new_db_action.setShortcut("Ctrl+N") self.new_db_action.triggered.connect(self.openNewDB) self.delete_сoncept_action = QAction("&Delete", self) self.delete_сoncept_action.setShortcut("DEL") self.delete_сoncept_action.setStatusTip("Delete") self.delete_сoncept_action.triggered.connect(lambda: self.delete(Concept)) self.delete_subcategory_action = QAction("&Delete subcategory", self) self.delete_subcategory_action.triggered.connect(lambda: self.delete(Subcategory)) self.edit_concept_action = QAction("&Edit", self) self.edit_concept_action.setShortcut("F2") self.edit_concept_action.triggered.connect(self.editConcept) self.edit_relation_action = QAction("&Edit", self) self.edit_relation_action.setShortcut("Ctrl+F2") self.edit_relation_action.triggered.connect(self.editRelation) self.exit_action = QAction("&Exit", self) self.exit_action.setShortcut("ESC") self.exit_action.triggered.connect(self.close) self.select_relation_action = QAction("&Select relation", self) self.select_relation_action.triggered.connect(self.setRelationDescription) self.delete_relation_action = QAction("&Delete", self) self.delete_relation_action.setShortcut("Ctrl+DEL") self.delete_relation_action.triggered.connect(lambda: self.delete(Relation)) def showAboutMessage(self): try: with open("about.txt") as f: text = f.read() QMessageBox.about(self.parent, "About application", text) except: pass def openNewDB(self): """This method deletes setting.py file and closes current application session. This uses for creating a new instance of Main Window. """ if os.path.exists("setting.py"): os.remove("setting.py") self.parent.close() self.application.exit(1) def initUI(self): self.initActions() self.add_data_button = QPushButton("Add data", self) self.export_button = QPushButton("Export references", self) self.search_box = QGroupBox() self.concept_list = QListWidget(self) self.relation_list = QListWidget(self) self.result_table = QTextEdit(self) self.concept_list.selectionModel().selectionChanged.connect(self.searchRelations) self.concept_list.setSelectionMode(QAbstractItemView.ContiguousSelection) self.concept_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.concept_list.setContextMenuPolicy(Qt.CustomContextMenu) self.concept_list.customContextMenuRequested.connect(self.showConceptContextMenu) self.relation_list.setContextMenuPolicy(Qt.CustomContextMenu) self.relation_list.customContextMenuRequested.connect(self.showRelationContextMenu) self.relation_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.relation_list.selectionModel().selectionChanged.connect(self.setRelationDescription) self.initSearchFrame(self.search_box) self.grid = QGridLayout() self.result_table.setReadOnly(True) self.search() self.configWidgets() self.bindWidgets() self.show() def showConceptContextMenu(self, pos): if not len(self.concept_list.selectedItems()) == 1: return global_position = self.concept_list.mapToGlobal(pos) my_menu = QMenu() my_menu.addAction(self.edit_concept_action) my_menu.addAction(self.delete_сoncept_action) my_menu.addAction(self.delete_subcategory_action) my_menu.addSeparator() my_menu.addAction(self.help_action) my_menu.addAction(self.exit_action) my_menu.exec(global_position) def initSearchFrame(self, frame): self.search_line = QLineEdit(frame) checkboxes = QGroupBox() checkboxes.setStyleSheet("border:0;") self.concept_checkbox = QCheckBox("Concept", checkboxes) self.description_checkbox = QCheckBox("Description", checkboxes) self.study_checkbox = QCheckBox("Study", checkboxes) self.reference_checkbox = QCheckBox("Reference", checkboxes) self.in_selected_checkbox = QCheckBox("Search in selected concepts", checkboxes) self.search_button = QPushButton("Search", checkboxes) checkboxes_layout = QGridLayout(checkboxes) checkboxes_layout.addWidget(self.concept_checkbox, 0, 0) checkboxes_layout.addWidget(self.description_checkbox, 0, 1) checkboxes_layout.addWidget(self.study_checkbox, 0, 2) checkboxes_layout.addWidget(self.reference_checkbox, 0, 3) checkboxes_layout.addWidget(self.in_selected_checkbox, 0, 4) checkboxes_layout.setContentsMargins(0, 0, 0, 0) self.concept_checkbox.setChecked(True) self.in_selected_checkbox.setChecked(True) grid = QGridLayout(frame) grid.addWidget(self.search_line, 1, 0) grid.addWidget(self.search_button, 1, 1) grid.addWidget(checkboxes, 2, 0, Qt.AlignLeft) frame.setLayout(grid) def getSearchData(self): """This method reads parameters of search line and checkboxes, and returns "Subcategory" class. None and [] uses for showing checkboxes that have been checked. """ concept = self.search_line.text() if self.concept_checkbox.isChecked() else None if self.reference_checkbox.isChecked(): reference = [ #RelationReference(text=self.search_line.text()), ConceptReference(text=self.search_line.text()) ] else: reference = [] if self.description_checkbox.isChecked(): description = [Description(text=self.search_line.text(), reference=reference)] else: description = [Description(reference=reference)] study = self.search_line.text() if self.study_checkbox.isChecked() else None if self.in_selected_checkbox.isChecked and len(self.concept_list.selectedItems()) > 1: selected_items_raw = self.concept_list.selectedItems() selected_items = [item.data(Qt.UserRole)[1] for item in selected_items_raw] else: selected_items = [] return Subcategory(subcategory=concept, description=description, study=study), selected_items # todo: doesn't work, becouse need html + bib --> rendered bib def searchRelations(self): """This method triggers when the user clicked on the concept. This method selected ID of a subcategory from selected item in conceptions list and then searches and setting all information about this selected concept. """ if not self.concept_list.selectedItems(): self.setConceptDescription() self.setResult([], self.relation_list) return subcategory_id = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1].id self.setConceptDescription() result = self.db.search_relation(subcategory_id) self.setResult(result, self.relation_list) def showRelationContextMenu(self, pos): global_position = self.relation_list.mapToGlobal(pos) my_menu = QMenu() my_menu.addAction(self.edit_relation_action) my_menu.addAction(self.delete_relation_action) my_menu.addSeparator() my_menu.exec(global_position) def editRelation(self): """This method opens dialog for editing Relation""" if hasSlelectedItems(self.relation_list): relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2] dlg = EditRelationDialog(self, relation) if dlg.exec_(): relation = dlg.getValue() self.db.update_relation(relation) self.select_relation_action.trigger() def editConcept(self): """This method opens dialog for editing Concept""" if hasSlelectedItems(self.concept_list): concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0] subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1] dlg = EditConceptDialog(self, concept, subcategory) if dlg.exec_(): concept, subcategory = dlg.getValue() self.db.update_concept(concept) self.db.update_subcategory(subcategory) self.search() def delete(self, something): """This universal method for deleting something from the list and database. "something" parameter needs to be any of this types: Concept, Subcategory, Relation """ if something == Concept: number = 0 target_list = self.concept_list elif something == Subcategory: number = 1 target_list = self.concept_list elif something == Relation: number = 2 target_list = self.relation_list if hasSlelectedItems(target_list): something = target_list.selectedItems()[0].data(Qt.UserRole)[number] self.db.delete(something) self.search() # need refactoring def setRelationDescription(self): """This method retrieves information about relation, formats and sets it in description field. """ if hasSlelectedItems(self.relation_list): relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2] concept1 = "{}{}".format(relation.node1.concept.name, ", {}".format(relation.node1.subcategory) if relation.node1.subcategory else "") concept2 = "{}{}".format(relation.node2.concept.name, ", {}".format(relation.node2.subcategory) if relation.node2.subcategory else "") description = relation.description study = relation.study references = relation.reference # HTML is used for a better information formating text = "<b>Relation between </b> \"{}\" <b>and</b> \"{}\"<p>".format(concept1, concept2) text += r"<b>Description:</b>" + "<br> {} <p>".format(description) text += r"<b>Study:</b> {} <p>".format(study) text += r"<b>References:</b><ol>" for ref in references: text += " <li> {} </li>".format(getBibRenderFromHTML(ref.text)) text += "</ol><br>" self.result_table.setHtml(text) else: self.result_table.clear() # need refactoring def setConceptDescription(self): """This method retrieves information about concept, formats and sets it in description field. """ if not self.concept_list.selectedItems(): self.result_table.setHtml("") return concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0] subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1] description = subcategory.description # HTML is used for a better information formating text = "<b>Concept:</b> {}<p>".format(concept.name) text += "<b>Subcategory:</b> {}<p>".format(subcategory.subcategory) text += "<b>Synonyms:</b> {}<p>".format(concept.synonyms) text += "<ol>" for des in description: text += "<li> {}".format("<b>Description:</b> <br>") text += " {} <p>".format(des.text) text += "<ol>" text += "<b>References: </b>" for ref in des.reference: text += "<li>" text += "{}".format(getBibRenderFromHTML(ref.text)) text += "</li>" text += "</ol>" text += "</li>" text += "</ol>" self.result_table.setHtml(text) def setResult(self, result, list): """This is a universal method for showing information in a relation field or in a concept field. """ list.clear() for concept, subcategory, *other in result: item = QListWidgetItem() item.setData(Qt.UserRole, (concept, subcategory, *other)) item.setText("{}{} {}".format(concept.name, "" if subcategory.subcategory == "" else ", ", subcategory.subcategory)) list.insertItem(0, item) def search(self): subcategory, selected_items = self.getSearchData() result = self.db.search_nodes(subcategory, selected_items) self.setResult([], self.relation_list) self.setResult(result, self.concept_list) self.setResult([], self.relation_list) self.setRelationDescription() def configWidgets(self): self.grid.setAlignment(Qt.AlignTop) self.grid.setSpacing(5) self.menu_bar = QMenuBar(self) self.database_menu = self.menu_bar.addMenu("Database") self.database_menu.addAction(self.new_db_action) self.database_menu.addSeparator() self.database_menu.addAction(self.exit_action) self.concept_menu = self.menu_bar.addMenu("Concept") self.concept_menu.addAction(self.edit_concept_action) self.concept_menu.addAction(self.delete_сoncept_action) self.concept_menu.addAction(self.delete_subcategory_action) self.relation_menu = self.menu_bar.addMenu("Relation") self.relation_menu.addAction(self.edit_relation_action) self.relation_menu.addAction(self.delete_relation_action) self.help_menu = self.menu_bar.addMenu("Help") self.help_menu.addAction(self.help_action) self.help_menu.addAction(self.about_action) self.grid.setMenuBar(self.menu_bar) self.concept_box = QGroupBox("Concepts") self.concept_grid = QGridLayout() self.concept_grid.setContentsMargins(0, 10, 0, 0) self.concept_grid.addWidget(self.concept_list) self.concept_box.setLayout(self.concept_grid) self.relation_box = QGroupBox("Relations") self.relation_grid = QGridLayout() self.relation_grid.setContentsMargins(0, 10, 0, 0) self.relation_grid.addWidget(self.relation_list) self.relation_box.setLayout(self.relation_grid) self.description_box = QGroupBox("Description") self.description_grid = QGridLayout() self.description_grid.setContentsMargins(0, 10, 0, 0) self.description_grid.addWidget(self.result_table) self.description_box.setLayout(self.description_grid) self.concept_splitter = QSplitter(self) self.concept_splitter.addWidget(self.concept_box) self.concept_splitter.addWidget(self.relation_box) self.description_splitter = QSplitter(self) self.description_splitter.setOrientation(Qt.Vertical) self.description_splitter.addWidget(self.concept_splitter) self.description_splitter.addWidget(self.description_box) self.grid.addWidget(self.add_data_button, 1, 0, Qt.AlignLeft) self.grid.addWidget(self.export_button, 1, 1, Qt.AlignRight) self.grid.addWidget(self.search_box, 2, 0, 1, 2) self.grid.addWidget(self.description_splitter, 5, 0, 1, 2) self.setLayout(self.grid) def bindWidgets(self): self.add_data_button.clicked.connect(self.addData) self.search_button.clicked.connect(self.search) self.export_button.clicked.connect(self.exportReferences) self.search_line.returnPressed.connect(self.search) def exportReferences(self): references = self.db.get_all_references() references = [getPlainText(ref.text) for ref in references] references = list(set(references)) references = [prepareBibStr(ref) for ref in references] final_text = ",\n\n".join(references) dlg = QFileDialog() file_path = dlg.getSaveFileName(self, "Save bibtex file")[0] if not (file_path == ""): # todo: check readBibsFromFile try: with open(file_path, 'w') as f: f.write(final_text) except Exception as error: showError(error) def addData(self): dlg = NewDataDialog(self.db) dlg.exec_() self.search() def getPath(self): dialog = NewDBDialog() if dialog.exec_(): path = dialog.path with open("setting.py", "w") as f: f.write("{{ 'last': r'{0}' }}".format(path)) return path else: self.close() def openDatabase(self): if os.path.exists("setting.py"): with open("setting.py") as f: setting = eval(f.read()) if "last" in setting: if os.path.exists(setting["last"]): path = setting["last"] else: path = self.getPath() else: path = self.getPath() else: path = self.getPath() if path is None: self.close() exit(0) else: return Graph(path) def closeEvent(self, event): event.ignore()
class MainWindow(QWidget): """Main window class that provides logic of the program. Allows to search concept and to show information about concepts and relations """ def __init__(self, application): super().__init__() self.application = application self.db = self.openDatabase() self._initUI() def initActions(self): """initalization of actions for main windows""" self.help_action = QAction("&Help", self) self.help_action.setShortcut("F1") self.help_action.setStatusTip('Help') self.help_action.triggered.connect(lambda: HelpDialog(self)) self.new_db_action = QAction("New DB", self) self.new_db_action.setShortcut("Ctrl+N") self.new_db_action.triggered.connect(self.openNewDB) self.delete_сoncept_action = QAction("&Delete", self) self.delete_сoncept_action.setShortcut("DEL") self.delete_сoncept_action.setStatusTip("Delete") self.delete_сoncept_action.triggered.connect(lambda: self.delete(Concept)) self.delete_subcategory_action = QAction("&Delete subcategory", self) self.delete_subcategory_action.triggered.connect(lambda: self.delete(Subcategory)) self.edit_concept_action = QAction("&Edit", self) self.edit_concept_action.setShortcut("F2") self.edit_concept_action.triggered.connect(self.editConcept) self.edit_relation_action = QAction("&Edit", self) self.edit_relation_action.setShortcut("Ctrl+F2") self.edit_relation_action.triggered.connect(self.editRelation) self.exit_action = QAction("&Exit", self) self.exit_action.setShortcut("ESC") self.exit_action.triggered.connect(self.close) self.select_relation_action = QAction("&Select relation", self) self.select_relation_action.triggered.connect(self.setRelationDescription) self.delete_relation_action = QAction("&Delete", self) self.delete_relation_action.setShortcut("Ctrl+DEL") self.delete_relation_action.triggered.connect(lambda: self.delete(Relation)) def openNewDB(self): """This method deletes setting.py file and closes current application session. This uses for creating a new instance of Main Window. """ if os.path.exists("setting.py"): os.remove("setting.py") self.application.exit(1) def _initUI(self): self.setWindowIcon(QIcon("logo.png")) self.setWindowTitle('GraphNotes') self.resize(1000, 700) self.initActions() self.add_data_button = QPushButton("Add data", self) self.search_box = QGroupBox() self._initSearchFrame(self.search_box) self.concept_list = QListWidget(self) self.relation_list = QListWidget(self) self.result_table = QTextEdit(self) self.concept_list.itemClicked.connect(self.searchRelations) self.concept_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.concept_list.setContextMenuPolicy(Qt.CustomContextMenu) self.concept_list.customContextMenuRequested.connect(self._showConceptContextMenu) self.relation_list.setContextMenuPolicy(Qt.CustomContextMenu) self.relation_list.customContextMenuRequested.connect(self._showRelationContextMenu) self.relation_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.relation_list.itemClicked.connect(self.setRelationDescription) self.grid = QGridLayout() self.result_table.setReadOnly(True) self.search() self._configWidgets() self._bindWidgets() self.show() def _showConceptContextMenu(self, pos): global_position = self.concept_list.mapToGlobal(pos) my_menu = QMenu() my_menu.addAction(self.edit_concept_action) my_menu.addAction(self.delete_сoncept_action) my_menu.addAction(self.delete_subcategory_action) my_menu.addSeparator() my_menu.addAction(self.help_action) my_menu.addAction(self.exit_action) my_menu.exec(global_position) def _initSearchFrame(self, frame): self.search_line = QLineEdit(frame) checkboxes = QGroupBox() checkboxes.setStyleSheet("border:0;") self.concept_checkbox = QCheckBox("Concept", checkboxes) self.description_checkbox = QCheckBox("Description", checkboxes) self.study_checkbox = QCheckBox("Study", checkboxes) self.search_button = QPushButton("Search", checkboxes) checkboxes_layout = QGridLayout(checkboxes) checkboxes_layout.addWidget(self.concept_checkbox, 0, 0) checkboxes_layout.addWidget(self.description_checkbox, 0, 1) checkboxes_layout.addWidget(self.study_checkbox, 0, 2) checkboxes_layout.setContentsMargins(0, 0, 0, 0) self.concept_checkbox.setChecked(True) grid = QGridLayout(frame) grid.addWidget(self.search_line, 1, 0) grid.addWidget(self.search_button, 1, 1) grid.addWidget(checkboxes, 2, 0, Qt.AlignLeft) frame.setLayout(grid) def getSearchData(self): """This method reads parameters of search line and checkboxes, and returns "Subcategory" class. None and [] uses for showing checkboxes that have been checked. """ concept = self.search_line.text() if self.concept_checkbox.isChecked() else None description = [Description(text=self.search_line.text())] if self.description_checkbox.isChecked() else [] study = self.search_line.text() if self.study_checkbox.isChecked() else None return Subcategory(subcategory=concept, description=description, study=study) def searchRelations(self): """This method triggers when the user clicked on the concept. This method selected ID of a subcategory from selected item in conceptions list and then searches and setting all information about this selected concept. """ subcategory_id = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1].id self.setConceptDescription() result = self.db.search_relation(subcategory_id) self.setResult(result, self.relation_list) def _showRelationContextMenu(self, pos): global_position = self.relation_list.mapToGlobal(pos) my_menu = QMenu() my_menu.addAction(self.edit_relation_action) my_menu.addAction(self.delete_relation_action) my_menu.addSeparator() my_menu.exec(global_position) def editRelation(self): """This method opens dialog for editing Relation""" if self.relation_list.currentIndex().isValid(): relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2] dlg = EditRelationDialog(self, relation) if dlg.exec_(): relation = dlg.getValue() self.db.update_relation(relation) self.select_relation_action.trigger() def editConcept(self): """This method opens dialog for editing Concept""" if self.concept_list.currentIndex().isValid(): concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0] subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1] dlg = EditConceptDialog(self, concept, subcategory) if dlg.exec_(): concept, subcategory = dlg.getValue() self.db.update_concept(concept) self.db.update_subcategory(subcategory) self.search() def delete(self, something): """This universal method for deleting something from the list and database. "something" parameter needs to be any of this types: Concept, Subcategory, Relation """ if something == Concept: number = 0 target_list = self.concept_list elif something == Subcategory: number = 1 target_list = self.concept_list elif something == Relation: number = 2 target_list = self.relation_list if target_list.currentIndex().isValid(): something = target_list.selectedItems()[0].data(Qt.UserRole)[number] self.db.delete(something) self.search() def setRelationDescription(self): """This method retrieves information about relation, formats and sets it in description field. """ if self.relation_list.currentIndex().isValid(): relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2] concept1 = "{}{}".format(relation.node1.concept.name, ", {}".format(relation.node1.subcategory) if relation.node1.subcategory else "") concept2 = "{}{}".format(relation.node2.concept.name, ", {}".format(relation.node2.subcategory) if relation.node2.subcategory else "") description = relation.description study = relation.study references = relation.reference # HTML is used for a better information formating text = "<b>Relation between </b> \"{}\" <b>and</b> \"{}\"<p>".format(concept1, concept2) text += r"<b>Description:</b>" + "<br> {} <p>".format(description) text += r"<b>Study:</b> {} <p>".format(study) text += r"<b>References:</b><ol>" for ref in references: text += " <li> {} </li>".format(ref.text) text += "</ol><br>" self.result_table.setText(text) else: self.result_table.clear() def setConceptDescription(self): """This method retrieves information about concept, formats and sets it in description field. """ concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0] subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1] description = subcategory.description # HTML is used for a better information formating text = "<b>Concept:</b> {}<p>".format(concept.name) text += "<b>Subcategory:</b> {}<p>".format(subcategory.subcategory) text += "<b>Synonyms:</b> {}<p>".format(concept.synonyms) text += "<ol>" for des in description: text += "<li> {}".format("<b>Description:</b> <br>") text += " {} <p>".format(des.text) text += "<ol>" text += "<b>References: </b>" for ref in des.reference: text += "<li>" text += "{}".format(ref.text) text += "</li>" text += "</ol>" text += "</li>" text += "</ol>" self.result_table.setText(text) def setResult(self, result, list): """This is a universal method for showing information in a relation field or in a concept field. """ list.clear() for concept, subcategory, *other in result: item = QListWidgetItem() item.setData(Qt.UserRole, (concept, subcategory, *other)) item.setText("{}{} {}".format(concept.name, "" if subcategory.subcategory == "" else ", ", subcategory.subcategory)) list.insertItem(0, item) def search(self): parameters = self.getSearchData() result = self.db.search_nodes(parameters) self.setResult([], self.relation_list) self.setResult(result, self.concept_list) self.setResult([], self.relation_list) self.setRelationDescription() def _configWidgets(self): self.grid.setAlignment(Qt.AlignTop) self.grid.setSpacing(5) self.menu_bar = QMenuBar(self) self.database_menu = self.menu_bar.addMenu("Database") self.database_menu.addAction(self.new_db_action) self.database_menu.addSeparator() self.database_menu.addAction(self.exit_action) self.concept_menu = self.menu_bar.addMenu("Concept") self.concept_menu.addAction(self.edit_concept_action) self.concept_menu.addAction(self.delete_сoncept_action) self.concept_menu.addAction(self.delete_subcategory_action) self.relation_menu = self.menu_bar.addMenu("Relation") self.relation_menu.addAction(self.edit_relation_action) self.relation_menu.addAction(self.delete_relation_action) self.help_menu = self.menu_bar.addMenu("Help") self.help_menu.addAction(self.help_action) self.grid.setMenuBar(self.menu_bar) self.concept_box = QGroupBox("Concepts") self.concept_grid = QGridLayout() self.concept_grid.setContentsMargins(0, 10, 0, 0) self.concept_grid.addWidget(self.concept_list) self.concept_box.setLayout(self.concept_grid) self.relation_box = QGroupBox("Relations") self.relation_grid = QGridLayout() self.relation_grid.setContentsMargins(0, 10, 0, 0) self.relation_grid.addWidget(self.relation_list) self.relation_box.setLayout(self.relation_grid) self.description_box = QGroupBox("Description") self.description_grid = QGridLayout() self.description_grid.setContentsMargins(0, 10, 0, 0) self.description_grid.addWidget(self.result_table) self.description_box.setLayout(self.description_grid) self.concept_splitter = QSplitter(self) self.concept_splitter.addWidget(self.concept_box) self.concept_splitter.addWidget(self.relation_box) self.description_splitter = QSplitter(self) self.description_splitter.setOrientation(Qt.Vertical) self.description_splitter.addWidget(self.concept_splitter) self.description_splitter.addWidget(self.description_box) self.grid.addWidget(self.add_data_button, 1, 0, Qt.AlignLeft) self.grid.addWidget(self.search_box, 2, 0, 1, 2) self.grid.addWidget(self.description_splitter, 5, 0, 1, 2) self.setLayout(self.grid) def _bindWidgets(self): self.add_data_button.clicked.connect(self.addData) self.search_button.clicked.connect(self.search) self.search_line.returnPressed.connect(self.search) def addData(self): dlg = NewDataDialog(self.db) dlg.exec_() self.search() def getPath(self): dialog = NewDBDialog() if dialog.exec_(): print("EXEc") path = dialog.path with open("setting.py", "w") as f: f.write("{{ 'last': r'{0}' }}".format(path)) return path else: self.close() def openDatabase(self): if os.path.exists("setting.py"): with open("setting.py") as f: setting = eval(f.read()) if "last" in setting: if os.path.exists(setting["last"]): path = setting["last"] else: path = self.getPath() else: path = self.getPath() else: path = self.getPath() if path is None: self.close() exit(0) else: return Graph(path)
class UFDebugToolUI(object): def __init__(self, window=None): self.window = window if window is not None else QWidget super(UFDebugToolUI, self).__init__() self.lang = 'en' self.set_ui() def set_ui(self): self._set_window() self._set_menubar() self._set_tab() def _set_window(self): self.window.setWindowTitle(self.window.tr('UF-Debug-Tool')) self.window.setMinimumHeight(800) self.window.setMinimumWidth(1080) self.main_layout = QVBoxLayout(self.window) def _set_menubar(self): self.menuBar = QMenuBar() self.main_layout.setMenuBar(self.menuBar) fileMenu = self.menuBar.addMenu('File') self.newFileAction = QAction(self.window.tr('New'), self.window) self.newFileAction.setShortcut('Ctrl+N') self.newFileAction.setStatusTip('New File') fileMenu.addAction(self.newFileAction) self.openFileAction = QAction(self.window.tr('Open'), self.window) self.openFileAction.setShortcut('Ctrl+O') self.openFileAction.setToolTip('Open File') fileMenu.addAction(self.openFileAction) self.saveFileAction = QAction(self.window.tr('Save'), self.window) self.saveFileAction.setShortcut('Ctrl+S') self.saveFileAction.setStatusTip('Save File') fileMenu.addAction(self.saveFileAction) self.closeFileAction = QAction(self.window.tr('Close'), self.window) self.closeFileAction.setShortcut('Ctrl+W') self.closeFileAction.setStatusTip('Close File') fileMenu.addAction(self.closeFileAction) self.newFileAction.triggered.connect(self.new_dialog) self.openFileAction.triggered.connect(self.open_dialog) self.saveFileAction.triggered.connect(self.save_dialog) self.closeFileAction.triggered.connect(self.close_dialog) debugMenu = self.menuBar.addMenu('Debug') self.logAction = QAction(self.window.tr('Log'), self.window) self.logAction.setShortcut('Ctrl+D') self.logAction.setStatusTip('Open-Log') self.logAction.triggered.connect(self.control_log_window) debugMenu.addAction(self.logAction) def control_log_window(self): if self.window.log_window.isHidden(): self.window.log_window.show() self.logAction.setText('Close-Log') else: self.window.log_window.hide() self.logAction.setText('Open-Log') def switch_tab(self, index): pass # if index == 2: # self.menuBar.setHidden(False) # else: # self.menuBar.setHidden(True) def _set_tab(self): self.tab_widget = QTabWidget() # self.tab_widget.currentChanged.connect(self.switch_tab) # tab_widget.setMaximumHeight(self.window.geometry().height() // 2) self.main_layout.addWidget(self.tab_widget) toolbox1 = QToolBox() toolbox2 = QToolBox() toolbox3 = QToolBox() toolbox4 = QToolBox() toolbox5 = QToolBox() groupbox1 = QGroupBox() groupbox2 = QGroupBox() groupbox3 = QGroupBox() groupbox4 = QGroupBox() groupbox5 = QGroupBox() toolbox1.addItem(groupbox1, "") toolbox2.addItem(groupbox2, "") toolbox3.addItem(groupbox3, "") toolbox4.addItem(groupbox4, "") toolbox5.addItem(groupbox5, "") self.tab_widget.addTab(toolbox1, "uArm") self.tab_widget.addTab(toolbox2, "xArm") self.tab_widget.addTab(toolbox3, "OpenMV") self.tab_widget.addTab(toolbox4, "Gcode") self.tab_widget.addTab(toolbox5, "WebView") uarm_layout = QVBoxLayout(groupbox1) xarm_layout = QVBoxLayout(groupbox2) openmv_layout = QHBoxLayout(groupbox3) gcode_layout = QVBoxLayout(groupbox4) webview_layout = QVBoxLayout(groupbox5) self.uarm_ui = UArmUI(self, uarm_layout) self.xarm_ui = XArmUI(self, xarm_layout) self.openmv_ui = OpenMV_UI(self, openmv_layout) self.gcode_ui = GcodeUI(self, gcode_layout) self.webview_ui = WebViewUI(self, webview_layout) self.tab_widget.setCurrentIndex(0) def new_dialog(self): self.openmv_ui.textEdit.setText('') self.openmv_ui.textEdit.filename = None self.openmv_ui.label_title.setText('untitled') self.tab_widget.setCurrentIndex(2) self.openmv_ui.textEdit.setDisabled(False) def open_dialog(self): fname = QFileDialog.getOpenFileName(self.window, 'Open file', '') if fname and fname[0]: with open(fname[0], "r") as f: self.openmv_ui.textEdit.setText(f.read()) self.openmv_ui.label_title.setText(fname[0]) self.openmv_ui.textEdit.filename = fname[0] self.tab_widget.setCurrentIndex(2) self.openmv_ui.textEdit.setDisabled(False) def save_dialog(self): widget = self.window.focusWidget() if widget: if not self.openmv_ui.textEdit.filename: fname = QFileDialog.getSaveFileName(self.window, 'Save File', '') if fname and fname[0]: self.openmv_ui.textEdit.filename = fname[0] if self.openmv_ui.textEdit.filename: data = widget.toPlainText() with open(self.openmv_ui.textEdit.filename, "w") as f: f.write(data) def close_dialog(self): self.openmv_ui.textEdit.clear() self.openmv_ui.textEdit.filename = None self.openmv_ui.label_title.setText('') self.openmv_ui.textEdit.setDisabled(True)