Esempio n. 1
0
 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
Esempio n. 2
0
 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
Esempio n. 3
0
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()
Esempio n. 4
0
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()
Esempio n. 5
0
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()
Esempio n. 6
0
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)
Esempio n. 7
0
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)