Exemple #1
0
    def __init__(self):
        super().__init__()
        self.setWindowTitle('World Country Diagram')
        self.resize(500, 700)
        treeView = QTreeView()
        treeView.setHeaderHidden(True)
        treeModel = QStandardItemModel()
        rootNode = treeModel.invisibleRootItem()

        # America
        america = StandardItem('America', 16, set_bold=True)
        california = StandardItem('California', 14)
        america.appendRow(california)

        oakland = StandardItem('Oakland', 12, color=QColor(155, 0, 0))
        sanfrancisco = StandardItem('San Francisco',
                                    12,
                                    color=QColor(155, 0, 0))
        sanjose = StandardItem('San Jose', 12, color=QColor(155, 0, 0))

        california.appendRow(oakland)
        california.appendRow(sanfrancisco)
        california.appendRow(sanjose)

        texas = StandardItem('Texas', 14)
        america.appendRow(texas)

        austin = StandardItem('Austin', 12, color=QColor(155, 0, 0))
        houston = StandardItem('Houston', 12, color=QColor(155, 0, 0))
        dallas = StandardItem('dallas', 12, color=QColor(155, 0, 0))

        texas.appendRow(austin)
        texas.appendRow(houston)
        texas.appendRow(dallas)

        # Canada
        canada = StandardItem('Canada', 16, set_bold=True)

        alberta = StandardItem('Alberta', 14)
        bc = StandardItem('British Columbia', 14)
        ontario = StandardItem('Ontario', 14)
        canada.appendRows([alberta, bc, ontario])

        rootNode.appendRow(america)
        rootNode.appendRow(canada)

        treeView.setModel(treeModel)
        treeView.expandAll()
        treeView.doubleClicked.connect(self.getValue)

        self.setCentralWidget(treeView)
Exemple #2
0
class MainWindow(QMainWindow):
    def __init__(self, app):
        super(MainWindow, self).__init__()
        self._app = app
        self._selectedIndex = None

        # model
        nodeFactory = NodeFactory()
        rootNode = nodeFactory.create(NodeType.General, 'Root')
        # for i in range(10000):  # for testing
        childNode0 = nodeFactory.create(NodeType.General, 'RightPirateLeg',
                                        rootNode)
        childNode1 = nodeFactory.create(NodeType.General, 'RightPirateLeg_END',
                                        childNode0)
        childNode2 = nodeFactory.create(NodeType.General, 'LeftFemur',
                                        rootNode)
        childNode3 = nodeFactory.create(NodeType.Sphere, 'LeftTibia',
                                        childNode2)
        childNode4 = nodeFactory.create(NodeType.Sphere, 'LeftFoot',
                                        childNode3)
        transform = childNode4.component(ComponentType.Transform)
        qTransform = transform.component()
        translation = qTransform.translation()
        translation.setX(5)
        qTransform.setTranslation(translation)

        # childNode5 = nodeFactory.create(NodeType.Box, 'LeftFoot_END', childNode4)
        self._model = SceneGraphModel(rootNode)

        self._sceneView = SceneView(rootNode.entity())
        self._container = self.createWindowContainer(self._sceneView)

        # scene graph view
        self._treeView = QTreeView()
        self._treeView.setModel(self._model)
        self._treeView.setHeaderHidden(True)
        self._treeView.setAlternatingRowColors(True)

        dockWidget = QDockWidget()
        dockWidget.setWidget(self._treeView)
        dockWidget.setWindowTitle('Scene Graph')
        dockWidget.setObjectName('sceneGraph')
        sceneGraphToggleAction = dockWidget.toggleViewAction()
        self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget)

        # property editor
        propertyEditor = PropertyEditor(self._model, nodeFactory,
                                        FieldFactory())

        dockWidget = QDockWidget()
        dockWidget.setWidget(propertyEditor)
        dockWidget.setWindowTitle('Property Editor')
        dockWidget.setObjectName('propertyEditor')
        propertyEditorToggleAction = dockWidget.toggleViewAction()
        self.addDockWidget(Qt.RightDockWidgetArea, dockWidget)

        # menu
        menuBar = self.menuBar()
        menu = menuBar.addMenu('&File')
        exitAction = menu.addAction('E&xit')
        exitAction.triggered.connect(self.close)
        menu.addAction(exitAction)
        menu = menuBar.addMenu('&Windows')
        menu.addAction(sceneGraphToggleAction)
        menu.addAction(propertyEditorToggleAction)
        menuBar.addMenu(menu)

        # central widget
        #button = QPushButton()
        self.setCentralWidget(self._container)

        # selection change event
        selectionModel = self._treeView.selectionModel()
        selectionModel.currentChanged.connect(propertyEditor.changeSelection)

        # click event
        #button.clicked.connect(self.buttonClicked)

    def selectedNode(self):
        indices = self._treeView.selectedIndexes()
        result = None
        if len(indices) == 1:
            self._selectedIndex = indices[0]
            result = self._selectedIndex.internalPointer()
        return result

    def commitChange(self):
        self._model.dataChanged.emit(self._selectedIndex, self._selectedIndex)

    def closeEvent(self, event):
        self._app.exit()

    # data change example
    def buttonClicked(self):
        node = self.selectedNode()
        if not node:
            return
        general = node.component(ComponentType.General)
        general.setName('CLICKED')
        self.commitChange()
Exemple #3
0
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        #QWidget.__init__(self)

        self.createActions()
        self.createMenus()
        self.setWindowTitle("Map")
        self.painter = MyPainter()
        self.createLayout()

        self.fileName = ''

        #按钮 选取状态
        self.state = False
        #QObject.connect(self.painter, QtCore.SIGNAL("get_point_id()"), self, QtCore.SLOT("stateDisplay()"))
        self.painter.valueChanged.connect(self.stateDisplay)
        self.button3.clicked.connect(self.clearPoint)
        self.button0.clicked.connect(self.displayPoint)
        self.button4.clicked.connect(self.createLane)
        self.button5.clicked.connect(self.createConn)

    #读取点号
    def stateDisplay(self):
        self.brower1.setText(str(self.painter.start_point.id))
        self.brower2.setText(str(self.painter.end_point.id))

    def clearPoint(self):
        self.painter.target_point = 0
        self.painter.start_point.id = ''
        self.painter.end_point.id = ''
        self.painter.repaint()
        self.brower1.setText(str(self.painter.start_point.id))
        self.brower2.setText(str(self.painter.end_point.id))

    #根据输入框内id显示点号。当不显示时,需点击鼠标两下,由self.target_point的设计决定
    def displayPoint(self):
        self.painter.start_point.id = int(self.brower1.text())
        self.painter.start_point.draw_point = self.painter.allPoint[
            self.painter.start_point.id].draw_point
        self.painter.end_point.id = int(self.brower2.text())
        self.painter.end_point.draw_point = self.painter.allPoint[
            self.painter.end_point.id].draw_point
        self.painter.repaint()

    #可能需要加入条件,起始点id小于终止点id。conn同
    def createLane(self):
        #self.painter.data
        msgBox = QtWidgets.QMessageBox()

        if (self.painter.start_point.id == ''
                or self.painter.end_point.id == ''):
            msgBox.setText("输入错误")
        else:
            startline = self.painter.data[self.painter.data[0] ==
                                          self.painter.start_point.id]
            endline = self.painter.data[self.painter.data[0] ==
                                        self.painter.end_point.id]

            start_index = startline.index.values[0]
            end_index = endline.index.values[0]
            output_data = self.painter.data.iloc[start_index:end_index + 1, :]
            #输出
            output_data[0] = output_data[0].astype('int64')
            num = len(os.listdir("outputDATA\\Lane"))
            output_data.to_csv('outputDATA\\Lane\\' + str(num) + '.txt',
                               sep='\t',
                               index=False,
                               header=False)

            #此处不加等于即路段留有衔接点
            #存有部分点没删除?for in和remove的问题。
            #12.12 保留路段末尾处衔接点,用于生成道路
            for item in self.painter.allPoint:
                if int(item.id) >= int(self.painter.start_point.id) and int(
                        item.id) < int(self.painter.end_point.id):
                    self.painter.displayPoint.remove(item)
                    #print(item.id,self.painter.start_point.id,self.painter.end_point.id)
            self.painter.repaint()

            msgBox.setText("已生成目标道路Lane" + str(num))
        msgBox.exec_()

    def createConn(self):
        #self.painter.data
        msgBox = QtWidgets.QMessageBox()
        if (self.painter.start_point.id == ''
                or self.painter.end_point.id == ''):
            msgBox.setText("输入错误")
        else:
            startline = self.painter.data[self.painter.data[0] ==
                                          self.painter.start_point.id]
            endline = self.painter.data[self.painter.data[0] ==
                                        self.painter.end_point.id]

            start_index = startline.index.values[0]
            end_index = endline.index.values[0]
            output_data = self.painter.data.iloc[start_index:end_index + 1, :]
            #输出
            output_data[0] = output_data[0].astype('int64')
            num = len(os.listdir("outputDATA\\Conn"))
            output_data.to_csv('outputDATA\\Conn\\' + str(num) + '.txt',
                               sep='\t',
                               index=False,
                               header=False)

            for item in self.painter.allPoint:
                if int(item.id) >= int(self.painter.start_point.id) and int(
                        item.id) < int(self.painter.end_point.id):
                    self.painter.displayPoint.remove(item)
                    #print(item.id,self.painter.start_point.id,self.painter.end_point.id)
            self.painter.repaint()

            msgBox.setText("已生成目标道路Conn" + str(num))
        msgBox.exec_()

    def fileList(self):
        #树状文件列表
        self.model = QDirModel()
        self.view = QTreeView(self)
        self.view.setModel(self.model)
        self.view.setColumnHidden(1, True)
        self.view.setColumnHidden(2, True)
        self.view.setColumnHidden(3, True)
        self.view.setHeaderHidden(True)
        #self.view.setRootIndex(self.model.index("c:/"))
        self.layout.addWidget(self.view, 0, 0, 2, 1)

    def createLayout(self):
        self.widget = QWidget()
        self.setCentralWidget(self.widget)

        #栅格布局
        self.layout = QGridLayout()
        #设置拉伸因子,每一列的比例
        self.layout.setColumnStretch(0, 1)
        self.layout.setColumnStretch(1, 4)
        #控件
        self.fileList()
        self.layout.addWidget(self.painter, 0, 1)
        #页面
        self.button1 = QtWidgets.QLabel("起始点")
        self.brower1 = QtWidgets.QLineEdit()
        self.button2 = QtWidgets.QLabel("终止点")
        self.brower2 = QtWidgets.QLineEdit()
        self.button3 = QtWidgets.QPushButton("清除")

        self.button0 = QtWidgets.QPushButton("显示点号")
        self.button4 = QtWidgets.QPushButton("生成Lane")
        self.button5 = QtWidgets.QPushButton("生成Conn")

        labelLayout1 = QtWidgets.QHBoxLayout()
        labelLayout2 = QtWidgets.QHBoxLayout()

        labelLayout1.addWidget(self.button1)
        labelLayout1.addWidget(self.brower1)
        labelLayout1.addWidget(self.button2)
        labelLayout1.addWidget(self.brower2)
        labelLayout1.addWidget(self.button3)

        labelLayout2.addWidget(self.button0)
        labelLayout2.addWidget(self.button4)
        labelLayout2.addWidget(self.button5)

        self.layout.addLayout(labelLayout1, 1, 1)
        self.layout.addLayout(labelLayout2, 2, 1)
        self.widget.setLayout(self.layout)

    def createActions(self):
        self.openRoadAct = QtWidgets.QAction("加载道路数据",
                                             self,
                                             shortcut="Ctrl+O",
                                             triggered=self.openRoad)

        self.openPointAct = QtWidgets.QAction("加载点数据",
                                              self,
                                              shortcut="Ctrl+P",
                                              triggered=self.openPoint)
        #self.saveAsAct = QtWidgets.QAction("&Save As...", self, shortcut="Ctrl+S",triggered=self.saveAs)

        self.exitAct = QtWidgets.QAction("退出",
                                         self,
                                         shortcut="Ctrl+Q",
                                         triggered=self.close)

        #self.aboutAct = QtWidgets.QAction("&About", self, triggered=self.about)

        #self.aboutQtAct = QtWidgets.QAction("About &Qt", self,triggered=QtWidgets.qApp.aboutQt)

    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&打开")
        self.fileMenu.addAction(self.openRoadAct)
        self.fileMenu.addAction(self.openPointAct)
        #self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addAction(self.exitAct)

        self.menuBar().addSeparator()

        #self.helpMenu = self.menuBar().addMenu("&Help")
        #self.helpMenu.addAction(self.aboutAct)
        #self.helpMenu.addAction(self.aboutQtAct)

    #加载NovAtel文件数据
    def openRoad(self):
        fileName = QtWidgets.QFileDialog.getOpenFileName(
            self, "加载数据", QtCore.QDir.currentPath(), "Files (*.txt *.csv)")[0]

        if not fileName:
            return

        inFile = QtCore.QFile(fileName)
        if not inFile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtWidgets.QMessageBox.warning(
                self, "Text",
                "Cannot read file %s:\n%s." % (fileName, inFile.errorString()))
            return

        #data = QtCore.QTextStream(inFile)
        #self.line=data.readAll()
        inFile.close()
        self.painter.addData(fileName)

    #加载MissionPoint文件数据
    #getOpenFileNames()函数,可打开多个文件
    def openPoint(self):
        fileName = QtWidgets.QFileDialog.getOpenFileName(
            self, "加载数据", QtCore.QDir.currentPath(), "Files (*.txt *.csv)")[0]
        if not fileName:
            return

        inFile = QtCore.QFile(fileName)
        if not inFile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtWidgets.QMessageBox.warning(
                self, "Text",
                "Cannot read file %s:\n%s." % (fileName, inFile.errorString()))
            return
        inFile.close()
        self.painter.addPointData(fileName)
Exemple #4
0
class MVCConfigurationGUI(MVCConfigurationBase):
    """
    GUI implementation of MVCConfigurationBase
    """
    def __init__(self, configuration):
        super().__init__(configuration)
        assertMainThread()
        srv = Services.getService("MainWindow")
        srv.aboutToClose.connect(self._aboutToClose)
        confMenu = srv.menuBar().addMenu("&Configuration")
        toolBar = srv.getToolBar()

        configuration.configNameChanged.connect(self._configNameChanged)
        configuration.dirtyChanged.connect(self._dirtyChanged)

        style = QApplication.style()
        self.actLoad = QAction(
            QIcon.fromTheme("document-open",
                            style.standardIcon(QStyle.SP_DialogOpenButton)),
            "Open config", self)
        self.actLoad.triggered.connect(self._execLoad)
        self.actSave = QAction(
            QIcon.fromTheme("document-save",
                            style.standardIcon(QStyle.SP_DialogSaveButton)),
            "Save config", self)
        self.actSave.triggered.connect(self._execSaveConfig)
        self.actSaveWithGuiState = QAction(
            QIcon.fromTheme("document-save",
                            style.standardIcon(QStyle.SP_DialogSaveButton)),
            "Save config sync gui state", self)
        self.actSaveWithGuiState.triggered.connect(
            self._execSaveConfigWithGuiState)
        self.actNew = QAction(
            QIcon.fromTheme("document-new",
                            style.standardIcon(QStyle.SP_FileIcon)),
            "New config", self)
        self.actNew.triggered.connect(self._execNew)

        self.actActivate = QAction(
            QIcon.fromTheme("arrow-up", style.standardIcon(QStyle.SP_ArrowUp)),
            "Initialize", self)
        self.actActivate.triggered.connect(self.activate)
        self.actDeactivate = QAction(
            QIcon.fromTheme("arrow-down",
                            style.standardIcon(QStyle.SP_ArrowDown)),
            "Deinitialize", self)
        self.actDeactivate.triggered.connect(self.deactivate)

        confMenu.addAction(self.actLoad)
        confMenu.addAction(self.actSave)
        confMenu.addAction(self.actSaveWithGuiState)
        confMenu.addAction(self.actNew)
        confMenu.addAction(self.actActivate)
        confMenu.addAction(self.actDeactivate)
        toolBar.addAction(self.actLoad)
        toolBar.addAction(self.actSave)
        toolBar.addAction(self.actNew)
        toolBar.addAction(self.actActivate)
        toolBar.addAction(self.actDeactivate)

        self.recentConfigs = [QAction() for i in range(10)]
        self.recentConfigs[0].setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
        confMenu.addSeparator()
        recentMenu = confMenu.addMenu("Recent")
        for a in self.recentConfigs:
            a.setVisible(False)
            a.triggered.connect(self._openRecent)
            recentMenu.addAction(a)

        self.mainWidget = srv.newDockWidget("Configuration", None,
                                            Qt.LeftDockWidgetArea)
        self.treeView = QTreeView(self.mainWidget)
        self.treeView.setHeaderHidden(False)
        self.treeView.setSelectionMode(QAbstractItemView.NoSelection)
        self.treeView.setEditTriggers(self.treeView.EditKeyPressed
                                      | self.treeView.AnyKeyPressed)
        self.treeView.setAllColumnsShowFocus(True)
        self.treeView.setExpandsOnDoubleClick(False)
        self.treeView.setDragEnabled(True)
        self.treeView.setDropIndicatorShown(True)
        self.treeView.setDragDropMode(QAbstractItemView.DragOnly)
        self.mainWidget.setWidget(self.treeView)
        self.treeView.setModel(self.model)
        self.treeView.header().setStretchLastSection(True)
        self.treeView.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.treeView.doubleClicked.connect(self._onItemDoubleClicked)
        self.treeView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeView.customContextMenuRequested.connect(
            self._execTreeViewContextMenu)
        # expand applications by default
        self.treeView.setExpanded(self.model.index(1, 0), True)
        self.delegate = PropertyDelegate(self.model, ITEM_ROLE,
                                         ConfigurationModel.PropertyContent,
                                         self)
        self.treeView.setItemDelegate(self.delegate)

        self.restoreState()
        srv.aboutToClose.connect(self.saveState)
        # a list of dock widgets displaying subgraphs
        self._graphViews = []
        # make sure that the graph views are closed when the config is closed
        self._configuration.subConfigRemoved.connect(self._subConfigRemoved)
        self._waitForActivated = None
        self._waitForOpenState = None

    def _execLoad(self):
        assertMainThread()
        if self._checkDirty():
            return
        fn, _ = QFileDialog.getOpenFileName(self.mainWidget,
                                            "Load configuration",
                                            self.cfgfile,
                                            filter="*.json")
        if fn is not None and fn != "":
            logger.debug("Loading config file %s", fn)
            try:
                self.loadConfig(fn)
            except Exception as e:  # pylint: disable=broad-except
                logger.exception("Error while loading configuration %s: %s",
                                 fn, str(e))
                QMessageBox.warning(self.mainWidget,
                                    "Error while loading configuration",
                                    str(e))

    def _openRecent(self):
        """
        Called when the user clicks on a recent config.

        :return:
        """
        if self._checkDirty():
            return
        action = self.sender()
        fn = action.data()
        try:
            self.loadConfig(fn)
        except Exception as e:  # pylint: disable=broad-except
            # catching general exception is wanted here.
            logger.exception("Error while loading configuration %s: %s", fn,
                             str(e))
            QMessageBox.warning(self.mainWidget,
                                "Error while loading configuration", str(e))

    def _checkDirty(self):
        if self._configuration.dirty():
            ans = QMessageBox.question(
                None,
                "Save changes?",
                "There are unsaved changes. Do you want to save them?",
                buttons=QMessageBox.Save | QMessageBox.Discard
                | QMessageBox.Cancel,
                defaultButton=QMessageBox.Save)
            if ans == QMessageBox.Save:
                self.saveConfig()
                return False
            if ans == QMessageBox.Cancel:
                return True
        return False

    def _aboutToClose(self, mainWindow):
        if self._checkDirty():
            mainWindow.ignoreCloseEvent()

    def _execNew(self):
        assertMainThread()
        if self._checkDirty():
            return
        fn, _ = QFileDialog.getSaveFileName(self.mainWidget,
                                            "New configuration",
                                            ".",
                                            filter="*.json")
        if fn is not None and fn != "":
            logger.debug("Creating config file %s", fn)
            self.newConfig(fn)

    def _execSaveConfig(self):
        if self.configuration().filename() is None:
            self._execSaveConfigAs()
        else:
            self.saveConfig()

    def _execSaveConfigWithGuiState(self):
        if self.configuration().filename() is None:
            self._execSaveConfigAs()
        else:
            self.saveConfigWithGuiState()

    def _execSaveConfigAs(self):
        """
        Opens a file dialog to get the save file name and calls saveConfig.

        :return:
        """
        assertMainThread()
        fn, _ = QFileDialog.getSaveFileName(self.mainWidget,
                                            "Save configuration as", ".",
                                            "*.json")
        if fn is not None and fn != "":
            self.saveConfigAs(fn)

    def _addGraphView(self, subConfig):
        g = subConfig.getGraph()
        # remove already deleted graph views from internal list
        valid_graphViews = []
        for gv in self._graphViews:
            if shiboken2.isValid(gv):  # pylint: disable=no-member
                valid_graphViews.append(gv)
        self._graphViews = valid_graphViews
        # check if graph view is already there
        for gv in self._graphViews:
            if gv.widget().scene().graph == g:
                logger.info("Graph view already exists.")
                return
        # create new graph view
        srv = Services.getService("MainWindow")
        graphDw = srv.newDockWidget("Graph (%s)" % (subConfig.getName()),
                                    parent=None,
                                    defaultArea=Qt.RightDockWidgetArea,
                                    allowedArea=Qt.RightDockWidgetArea
                                    | Qt.BottomDockWidgetArea)
        graphDw.setAttribute(Qt.WA_DeleteOnClose, True)
        assert isinstance(graphDw, QDockWidget)
        graphView = GraphEditorView(graphDw)
        graphView.setScene(GraphScene(subConfig.getGraph(), graphDw))
        graphDw.setWidget(graphView)
        self._graphViews.append(graphDw)
        graphDw.visibleChanged.connect(self._removeGraphViewFromList)

    def _subConfigRemoved(self, subConfigName, configType):
        g = self._configuration.subConfigByNameAndTye(subConfigName,
                                                      configType).getGraph()
        for gv in self._graphViews:
            if gv.widget().scene().graph == g:
                logger.debug("deleting graph view for subconfig %s",
                             subConfigName)
                gv.deleteLater()

    def _removeGraphViewFromList(self, visible):
        if visible:
            return
        gv = self.sender()
        try:
            self._graphViews.remove(gv)
            logger.debug("removed graphview from list")
        except ValueError:
            logger.debug("graphview not in list, ignored")

    def _execTreeViewContextMenu(self, point):
        index = self.treeView.indexAt(point)
        item = self.model.data(index, ITEM_ROLE)
        if isinstance(item, ConfigurationModel.SubConfigContent):
            m = QMenu()
            a1 = QAction("Edit graph")
            m.addAction(a1)
            a1.triggered.connect(lambda: self._addGraphView(item.subConfig))
            if self.model.isApplication(index):
                a2 = QAction("Select Application")
                a2.triggered.connect(lambda: self.changeActiveApp(
                    self.model.data(index, Qt.DisplayRole)))
                a3 = QAction("Init Application")
                a3.triggered.connect(lambda: self._changeActiveAppAndInit(
                    self.model.data(index, Qt.DisplayRole)))
                m.addActions([a2, a3])
                pbsrv = Services.getService("PlaybackControl")
                m2 = m.addMenu("Init and load sequence")
                m3 = m.addMenu("Init, load and play")
                s1 = []
                s2 = []
                for a in pbsrv.recentSeqs:
                    assert isinstance(a, QAction)
                    if a.isVisible():
                        # pylint: disable=cell-var-from-loop
                        # the below statements are tested and work
                        aseq = QAction(a.text())
                        aseq.triggered.connect(lambda arg1=a.data(
                        ), seq=a.data(): self._changeActiveAppInitAndLoad(
                            self.model.data(index, Qt.DisplayRole), seq, False)
                                               )
                        s1.append(aseq)
                        aseq = QAction(a.text())
                        aseq.triggered.connect(lambda arg1=a.data(
                        ), seq=a.data(): self._changeActiveAppInitAndLoad(
                            self.model.data(index, Qt.DisplayRole), seq, True))
                        # pylint: enable=cell-var-from-loop
                        s2.append(aseq)
                m2.addActions(s1)
                m3.addActions(s2)
            m.exec_(self.treeView.mapToGlobal(point))
            return
        if self.model.isSubConfigParent(
                index) == Configuration.CONFIG_TYPE_APPLICATION:
            m = QMenu()
            a = QAction("Add application")
            m.addAction(a)
            a = m.exec_(self.treeView.mapToGlobal(point))
            if a is not None:
                self._configuration.addNewApplication()
            return
        if self.model.isSubConfigParent(
                index) == Configuration.CONFIG_TYPE_COMPOSITE:
            m = QMenu()
            a = QAction("Add composite filter")
            m.addAction(a)
            a = m.exec_(self.treeView.mapToGlobal(point))
            if a is not None:
                self._configuration.addNewCompositeFilter()
            return

    def _configNameChanged(self, cfgfile):
        logger.debug("_configNameChanged: %s", cfgfile)
        assertMainThread()
        self.cfgfile = cfgfile
        self._dirtyChanged(self._configuration.dirty())
        foundIdx = None
        for i, a in enumerate(self.recentConfigs):
            if a.data() == cfgfile:
                foundIdx = i
        if foundIdx is None:
            foundIdx = len(self.recentConfigs) - 1
        for i in range(foundIdx, 0, -1):
            self.recentConfigs[i].setText(self.recentConfigs[i - 1].text())
            self.recentConfigs[i].setData(self.recentConfigs[i - 1].data())
            self.recentConfigs[i].setVisible(
                self.recentConfigs[i - 1].data() is not None)
        self.recentConfigs[0].setText(cfgfile)
        self.recentConfigs[0].setData(cfgfile)
        self.recentConfigs[0].setVisible(True)

    def _dirtyChanged(self, dirty):
        srv = Services.getService("MainWindow")
        if self.cfgfile is None:
            title = "nexxT: <unnamed>"
        else:
            title = "nexxT: " + self.cfgfile
        if dirty:
            title += " *"
        srv.setWindowTitle(title)

    def _onItemDoubleClicked(self, index):
        assertMainThread()
        if self.model.isApplication(index):
            app = self.model.data(index, Qt.DisplayRole)
            self.changeActiveApp(app)
        else:
            self.treeView.edit(index)

    def _changeActiveAppAndInit(self, app):
        """
        Call this slot to activate and init an application

        :param app: can be either an Application instance or the name of an application
        :return:
        """
        assertMainThread()
        if isinstance(app, str):
            app = self.configuration().applicationByName(app)
        currentApp = Application.activeApplication
        if currentApp is not None:
            currentApp = currentApp.getApplication()
        self._waitForActivated = app
        self.changeActiveApp(app.getName())

    def _changeActiveAppInitAndLoad(self, app, sequence, startPlay):
        self._waitForOpenState = (app, sequence, startPlay)
        self._changeActiveAppAndInit(app)

    def appActivated(self, name, app):  # pylint: disable=unused-argument
        """
        Called when the application is activated.

        :param name: the application name
        :param app: An ActiveApplication instance.
        :return:
        """
        assertMainThread()
        if app is not None:
            self.activeAppStateChange(app.getState())
            app.stateChanged.connect(self.activeAppStateChange)
            if self._waitForActivated == app.getApplication():
                MethodInvoker(self.activate, Qt.QueuedConnection)
        else:
            self.actActivate.setEnabled(False)
            self.actDeactivate.setEnabled(False)
        self._waitForActivated = None

    def _disconnectSingleShotPlay(self):
        assertMainThread()
        pbsrv = Services.getService("PlaybackControl")
        try:
            pbsrv.playbackPaused.disconnect(self._singleShotPlay)
        except RuntimeError:
            # we are already disconnected.
            pass

    def _singleShotPlay(self):
        assertMainThread()
        pbsrv = Services.getService("PlaybackControl")
        MethodInvoker(pbsrv.startPlayback, Qt.QueuedConnection)
        self._disconnectSingleShotPlay()

    def activeAppStateChange(self, newState):
        """
        Called when the active application changes its state.

        :param newState: the new application's state (see FilterState)
        :return:
        """
        assertMainThread()
        if newState == FilterState.CONSTRUCTED:
            self.actActivate.setEnabled(True)
        else:
            self.actActivate.setEnabled(False)
        if newState == FilterState.ACTIVE:
            if self._waitForOpenState is not None:
                app, pbfile, startPlay = self._waitForOpenState
                self._waitForOpenState = None
                if app == Application.activeApplication.getApplication(
                ).getName():
                    pbsrv = Services.getService("PlaybackControl")
                    if startPlay:
                        pbsrv.playbackPaused.connect(self._singleShotPlay)
                        QTimer.singleShot(2000, self._disconnectSingleShotPlay)
                    MethodInvoker(pbsrv.browser.setActive, Qt.QueuedConnection,
                                  pbfile)
            self.actDeactivate.setEnabled(True)
            self.actSaveWithGuiState.setEnabled(False)
        else:
            self.actDeactivate.setEnabled(False)
            self.actSaveWithGuiState.setEnabled(True)

    def restoreState(self):
        """
        Restore the state of the configuration gui service (namely the recently
        open config files). This is saved in QSettings because it is used
        across config files.

        :return:
        """
        logger.debug("restoring config state ...")
        settings = QSettings()
        v = settings.value("ConfigurationRecentFiles")
        if v is not None and isinstance(v, QByteArray):
            ds = QDataStream(v)
            recentFiles = ds.readQStringList()
            idx = 0
            for f in recentFiles:
                if f != "" and f is not None:
                    self.recentConfigs[idx].setData(f)
                    self.recentConfigs[idx].setText(f)
                    self.recentConfigs[idx].setVisible(True)
                    idx += 1
                    if idx >= len(self.recentConfigs):
                        break
        logger.debug("restoring config state done")

    def saveState(self):
        """
        Save the state of the configuration gui service (namely the recently
        open config files). This is saved in QSettings because it is used
        across config files.

        :return:
        """
        logger.debug("saving config state ...")
        settings = QSettings()
        b = QByteArray()
        ds = QDataStream(b, QIODevice.WriteOnly)
        l = [
            rc.data() for rc in self.recentConfigs
            if rc.isVisible() and rc.data() is not None and rc.data() != ""
        ]
        ds.writeQStringList(l)
        settings.setValue("ConfigurationRecentFiles", b)
        logger.debug("saving config state done (%s)", l)
Exemple #5
0
class ExportDialog(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.model = ExportChangesModel()
        self.error_dialog = None
        self.setWindowIcon(QIcon("paragon.ico"))
        self.setWindowTitle("Export")

        main_layout = QVBoxLayout(self)
        self.export_button = QPushButton()
        self.export_button.setText("Export")
        self.main_view = QTreeView()
        self.main_view.setModel(self.model)
        self.main_view.setHeaderHidden(True)
        self.main_view.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        self.remember_selections_checkbox = QCheckBox()
        self.remember_selections_checkbox.setText("Remember selections.")
        main_layout.addWidget(self.export_button)
        main_layout.addWidget(self.main_view)
        main_layout.addWidget(self.remember_selections_checkbox)
        self.setLayout(main_layout)

        self.main_view.expanded.connect(self._on_item_expanded)
        self.export_button.clicked.connect(self._on_export_triggered)
        self.remember_selections_checkbox.stateChanged.connect(
            self._on_remember_selections_state_changed)

        self._set_remember_checkbox_state_from_settings()

    def _set_remember_checkbox_state_from_settings(self):
        settings_service = locator.get_static("SettingsService")
        if settings_service.get_remember_exports():
            self.remember_selections_checkbox.setCheckState(QtCore.Qt.Checked)

    @staticmethod
    def _on_remember_selections_state_changed(state: int):
        should_remember = state == QtCore.Qt.Checked
        locator.get_static("SettingsService").set_remember_exports(
            should_remember)

    def closeEvent(self, event: QtGui.QCloseEvent):
        self.model.save_selected_items_tree()
        event.accept()

    def _on_export_triggered(self):
        file_name, ok = QFileDialog.getSaveFileName(
            self, caption="Select Changes File Destination", filter="*.json")
        if ok:
            self._try_export_and_write(file_name)

    def _try_export_and_write(self, file_name):
        logging.debug("Exporting selected data to %s" % file_name)
        try:
            export_data = self.model.export_selected_items()
            with open(file_name, "w", encoding="utf-8") as f:
                json.dump(export_data, f, indent=4, ensure_ascii=False)
        except:
            logging.exception("An error occurred while exporting data.")
            self.error_dialog = ErrorDialog(
                "An error occurred while exporting. See the log for details.")
            self.error_dialog.show()

    def _on_item_expanded(self, index: QModelIndex):
        self.model.update_data_for_index(index)
Exemple #6
0
class CatsTreeWindow(PBDialog):
    """Extension of `PBDialog` that shows the categories tree"""
    def __init__(
        self,
        parent=None,
        askCats=False,
        askForBib=None,
        askForExp=None,
        expButton=True,
        previous=[],
        single=False,
        multipleRecords=False,
    ):
        """Initialize instance parameters and call the function that
        creates the layout.

        Parameters:
            parent (default None): the parent widget
            askCats (default False): if True, enable checkboxes for
                selection of categories
            askForBib (default None): the optional key which identifies
                in the database the bibtex entry for which categories
                are being selected
            askForExp (default None): the optional ID which identifies
                in the database the experiment for which categories
                are being selected
            expButton (default True): if True, add a button to accept
                the widget content and later ask for experiments
            previous (default []): the list of categories that
                must be selected at the beginning
            single (default False): if True, only allow the selection
                of a single category (the parent category, typically).
                Multiple checkboxes can be selected,
                but only the first one will be considered
            multipleRecords: used when dealing with categories
                corresponding to multiple records. Activate a tristate
                checkbox for the initial list of categories, which are
                typically not the same for all the elements in the list
        """
        PBDialog.__init__(self, parent)
        self.setWindowTitle(cwstr.cats)
        self.currLayout = QVBoxLayout(self)
        self.setLayout(self.currLayout)
        self.askCats = askCats
        self.askForBib = askForBib
        self.askForExp = askForExp
        self.expButton = expButton
        self.previous = previous
        self.single = single
        self.multipleRecords = multipleRecords
        self.result = False
        self.marked = []
        self.root_model = None
        self.proxyModel = None
        self.tree = None
        self.menu = None
        self.timer = None
        self.expsButton = None
        self.filterInput = None
        self.newCatButton = None
        self.acceptButton = None
        self.cancelButton = None

        self.setMinimumWidth(400)
        self.setMinimumHeight(600)

        self.createForm()

    def populateAskCat(self):
        """If selection of categories is allowed, add some information
        on the bibtex/experiment for which the categories are requested
        and a simple message, then create few required empty lists
        """
        if self.askCats:
            if self.askForBib is not None:
                try:
                    bibitem = pBDB.bibs.getByBibkey(self.askForBib,
                                                    saveQuery=False)[0]
                except IndexError:
                    pBGUILogger.warning(
                        cwstr.entryNotInDb % self.askForBib,
                        exc_info=True,
                    )
                    return
                try:
                    if bibitem["inspire"] != "" and bibitem[
                            "inspire"] is not None:
                        link = "<a href='%s'>%s</a>" % (
                            pBView.getLink(self.askForBib, "inspire"),
                            self.askForBib,
                        )
                    elif bibitem["arxiv"] != "" and bibitem[
                            "arxiv"] is not None:
                        link = "<a href='%s'>%s</a>" % (
                            pBView.getLink(self.askForBib, "arxiv"),
                            self.askForBib,
                        )
                    elif bibitem["doi"] != "" and bibitem["doi"] is not None:
                        link = "<a href='%s'>%s</a>" % (
                            pBView.getLink(self.askForBib, "doi"),
                            self.askForBib,
                        )
                    else:
                        link = self.askForBib
                    bibtext = PBLabel(
                        cwstr.markCatBibKAT %
                        (link, bibitem["author"], bibitem["title"]))
                except KeyError:
                    bibtext = PBLabel(cwstr.markCatBibK % (self.askForBib))
                self.currLayout.addWidget(bibtext)
            elif self.askForExp is not None:
                try:
                    expitem = pBDB.exps.getByID(self.askForExp)[0]
                except IndexError:
                    pBGUILogger.warning(
                        cwstr.expNotInDb % self.askForExp,
                        exc_info=True,
                    )
                    return
                try:
                    exptext = PBLabel(
                        cwstr.markCatExpINC %
                        (self.askForExp, expitem["name"], expitem["comments"]))
                except KeyError:
                    exptext = PBLabel(cwstr.markCatExpI % (self.askForExp))
                self.currLayout.addWidget(exptext)
            else:
                if self.single:
                    comment = PBLabel(cwstr.selectCat)
                else:
                    comment = PBLabel(cwstr.selectCats)
                self.currLayout.addWidget(comment)
            self.marked = []
            self.parent().selectedCats = []
        return True

    def onCancel(self):
        """Reject the dialog content and close the window"""
        self.result = False
        self.close()

    def onOk(self, exps=False):
        """Accept the dialog content
        (update the list of selected categories)
        and close the window.
        May set `self.result` to "Exps"
        for later opening of a new dialog to ask for experiments.

        Parameter:
            exps (default False): if True, set the result to "Exps",
                otherwise to "Ok"
        """
        self.parent().selectedCats = [
            idC for idC in self.root_model.selectedCats.keys()
            if self.root_model.selectedCats[idC] == True
        ]
        self.parent().previousUnchanged = [
            idC for idC in self.root_model.previousSaved.keys()
            if self.root_model.previousSaved[idC] == True
        ]

        if (self.single and len(self.parent().selectedCats) > 1
                and self.parent().selectedCats[0] == 0):
            self.parent().selectedCats.pop(0)
            self.parent().selectedCats = [self.parent().selectedCats[0]]
        self.result = "Exps" if exps else "Ok"
        self.close()

    def changeFilter(self, string):
        """When the filter `QLineEdit` is changed,
        update the `LeafFilterProxyModel` regexp filter

        Parameter:
            string: the new filter string
        """
        self.proxyModel.setFilterRegExp(str(string))
        self.tree.expandAll()

    def onAskExps(self):
        """Action to perform when the selection of categories
        will be folloed by the selection of experiments.
        Call `self.onOk` with `exps = True`.
        """
        self.onOk(exps=True)

    def onNewCat(self):
        """Action to perform when the creation
        of a new category is requested
        """
        editCategory(self, self.parent())

    def keyPressEvent(self, e):
        """Manage the key press events.
        Do nothing unless `Esc` is pressed:
        in this case close the dialog
        """
        if e.key() == Qt.Key_Escape:
            self.close()

    def createForm(self):
        """Create the dialog content, connect the model to the view
        and eventually add the buttons at the end
        """
        self.populateAskCat()

        catsTree = pBDB.cats.getHier()

        self.filterInput = QLineEdit("", self)
        self.filterInput.setPlaceholderText(cwstr.filterCat)
        self.filterInput.textChanged.connect(self.changeFilter)
        self.currLayout.addWidget(self.filterInput)
        self.filterInput.setFocus()

        self.tree = QTreeView(self)
        self.currLayout.addWidget(self.tree)
        self.tree.setMouseTracking(True)
        self.tree.entered.connect(self.handleItemEntered)
        self.tree.doubleClicked.connect(self.cellDoubleClick)
        self.tree.setExpandsOnDoubleClick(False)

        catsNamedTree = self._populateTree(catsTree[0], 0)

        self.root_model = CatsModel(
            pBDB.cats.getAll(),
            [catsNamedTree],
            self,
            self.previous,
            multipleRecords=self.multipleRecords,
        )
        self.proxyModel = LeafFilterProxyModel(self)
        self.proxyModel.setSourceModel(self.root_model)
        self.proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.proxyModel.setSortCaseSensitivity(Qt.CaseInsensitive)
        self.proxyModel.setFilterKeyColumn(-1)
        self.tree.setModel(self.proxyModel)

        self.tree.expandAll()

        self.tree.setHeaderHidden(True)
        # self.tree.doubleClicked.connect(self.askAndPerformAction)

        self.newCatButton = QPushButton(cwstr.addNew, self)
        self.newCatButton.clicked.connect(self.onNewCat)
        self.currLayout.addWidget(self.newCatButton)

        if self.askCats:
            self.acceptButton = QPushButton(cwstr.ok, self)
            self.acceptButton.clicked.connect(self.onOk)
            self.currLayout.addWidget(self.acceptButton)

            if self.expButton:
                self.expsButton = QPushButton(cwstr.askExp, self)
                self.expsButton.clicked.connect(self.onAskExps)
                self.currLayout.addWidget(self.expsButton)

            # cancel button
            self.cancelButton = QPushButton(cwstr.cancel, self)
            self.cancelButton.clicked.connect(self.onCancel)
            self.cancelButton.setAutoDefault(True)
            self.currLayout.addWidget(self.cancelButton)

    def _populateTree(self, children, idCat):
        """Read the list of categories recursively and
        populate the categories tree

        Parameters:
            children: the list of children categories
                of the currently considered one
            idCat: the id of the current category
        """
        name = pBDB.cats.getByID(idCat)[0]["name"]
        children_list = []
        for child in cats_alphabetical(children, pBDB):
            child_item = self._populateTree(children[child], child)
            children_list.append(child_item)
        return NamedElement(idCat, name, children_list)

    def handleItemEntered(self, index):
        """Process event when mouse enters an item and
        create a `QTooltip` which describes the category, with a timer

        Parameter:
            index: a `QModelIndex` instance
        """
        if index.isValid():
            row = index.row()
        else:
            return
        try:
            idString = self.proxyModel.sibling(row, 0, index).data()
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        try:
            idCat, catName = idString.split(": ")
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        idCat = idCat.strip()
        try:
            self.timer.stop()
            QToolTip.showText(QCursor.pos(), "", self.tree.viewport())
        except AttributeError:
            pass
        try:
            catData = pBDB.cats.getByID(idCat)[0]
        except IndexError:
            pBGUILogger.exception(cwstr.failedFind)
            return
        self.timer = QTimer(self)
        self.timer.setSingleShot(True)
        self.timer.timeout.connect(lambda: QToolTip.showText(
            QCursor.pos(),
            cwstr.catId.format(idC=idCat, cat=catData["name"]) + cwstr.
            entriesCorrespondent.format(en=pBDB.catBib.countByCat(idCat)) +
            cwstr.expsAssociated.format(ex=pBDB.catExp.countByCat(idCat)),
            self.tree.viewport(),
            self.tree.visualRect(index),
            3000,
        ))
        self.timer.start(500)

    def contextMenuEvent(self, event):
        """Create a right click menu with few actions
        on the selected category

        Parameter:
            event: a `QEvent`
        """
        indexes = self.tree.selectedIndexes()
        try:
            index = indexes[0]
        except IndexError:
            pBLogger.debug(cwstr.clickMissingIndex)
            return
        if index.isValid():
            row = index.row()
        else:
            return
        try:
            idString = self.proxyModel.sibling(row, 0, index).data()
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        try:
            idCat, catName = idString.split(": ")
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        idCat = idCat.strip()

        menu = PBMenu()
        self.menu = menu
        titAction = QAction(cwstr.catDescr % catName)
        titAction.setDisabled(True)
        bibAction = QAction(cwstr.openEntryList)
        modAction = QAction(cwstr.modify)
        delAction = QAction(cwstr.delete)
        subAction = QAction(cwstr.addSub)
        menu.possibleActions = [
            titAction,
            None,
            bibAction,
            None,
            modAction,
            delAction,
            None,
            subAction,
        ]
        menu.fillMenu()

        action = menu.exec_(event.globalPos())

        if action == bibAction:
            self.parent().reloadMainContent(pBDB.bibs.getByCat(idCat))
        elif action == modAction:
            editCategory(self, self.parent(), idCat)
        elif action == delAction:
            deleteCategory(self, self.parent(), idCat, catName)
        elif action == subAction:
            editCategory(self, self.parent(), useParentCat=idCat)
        return

    def cellDoubleClick(self, index):
        """Process event when mouse double clicks an item.
        Opens a link if some columns

        Parameter:
            index: a `QModelIndex` instance
        """
        if index.isValid():
            row = index.row()
            col = index.column()
        else:
            return
        try:
            idString = self.proxyModel.sibling(row, 0, index).data()
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        try:
            idCat, catName = idString.split(": ")
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        idCat = idCat.strip()
        self.parent().reloadMainContent(pBDB.bibs.getByCat(idCat))
        return

    def recreateTable(self):
        """Delete the previous widgets and recreate them with new data"""
        self.cleanLayout()
        self.createForm()
class Ui_FE14MapEditor(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.toolbar = QToolBar()
        self.toggle_coordinate_type_action = QAction("Toggle Coordinate Type")
        self.refresh_action = QAction("Refresh")
        self.refresh_action.setShortcut(QKeySequence("Ctrl+R"))
        self.copy_spawn_action = QAction("Copy Spawn")
        self.copy_spawn_action.setShortcut(QKeySequence("Ctrl+C"))
        self.paste_spawn_action = QAction("Paste Spawn")
        self.paste_spawn_action.setShortcut(QKeySequence("Ctrl+V"))
        self.add_spawn_action = QAction("Add Spawn")
        self.delete_spawn_action = QAction("Delete Spawn")
        self.add_group_action = QAction("Add Group")
        self.delete_group_action = QAction("Delete Group")
        self.add_tile_action = QAction("Add Tile")
        self.toggle_mode_action = QAction("Toggle Mode")
        self.undo_action = QAction("Undo")
        self.undo_action.setShortcut(QKeySequence("Ctrl+Z"))
        self.redo_action = QAction("Redo")
        self.redo_action.setShortcut(QKeySequence("Ctrl+Shift+Z"))
        self.toolbar.addActions(
            [self.toggle_coordinate_type_action, self.refresh_action])
        self.toolbar.addSeparator()
        self.toolbar.addActions([
            self.copy_spawn_action, self.paste_spawn_action,
            self.add_spawn_action, self.delete_spawn_action,
            self.add_group_action, self.delete_group_action
        ])
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.add_tile_action)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.toggle_mode_action)
        self.toolbar.addSeparator()
        self.toolbar.addActions([self.undo_action, self.redo_action])
        self.addToolBar(self.toolbar)

        self.model_view = QTreeView()
        self.model_view.setHeaderHidden(True)
        self.grid = FE14MapGrid()
        self.grid_scroll = QScrollArea()
        self.grid_scroll.setWidgetResizable(True)
        self.grid_scroll.setWidget(self.grid)
        self.tile_list = QListView()
        self.terrain_pane = FE14TerrainEditorPane()
        self.spawn_pane = FE14SpawnEditorPane()

        self.model_view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.model_view_context_menu = QMenu()
        self.model_view_context_menu.addActions(
            [self.toggle_coordinate_type_action, self.refresh_action])
        self.model_view_context_menu.addSeparator()
        self.model_view_context_menu.addActions([
            self.copy_spawn_action, self.paste_spawn_action,
            self.add_spawn_action, self.delete_spawn_action,
            self.add_group_action, self.delete_group_action
        ])
        self.model_view_context_menu.addSeparator()
        self.model_view_context_menu.addAction(self.add_tile_action)
        self.model_view_context_menu.addSeparator()
        self.model_view_context_menu.addAction(self.toggle_mode_action)
        self.model_view_context_menu.addSeparator()
        self.model_view_context_menu.addActions(
            [self.undo_action, self.redo_action])

        self.status_bar = QStatusBar()
        self.coordinate_type_label = QLabel()
        self.status_bar.addPermanentWidget(self.coordinate_type_label)
        self.setStatusBar(self.status_bar)

        self.main_widget = QSplitter()
        self.main_widget.setOrientation(QtCore.Qt.Horizontal)
        self.main_widget.addWidget(self.model_view)
        self.main_widget.addWidget(self.grid_scroll)
        self.main_widget.addWidget(self.spawn_pane)
        self.main_widget.addWidget(self.terrain_pane)
        self.setCentralWidget(self.main_widget)
Exemple #8
0
class PocetnaStrana(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.lista_putanja = []
        self.lista_baza = []
        self.main_window = QtWidgets.QMainWindow()
        self.main_window.resize(1040, 680)
        self.main_window.setWindowTitle("Rukovalac informacionim resursima")
        icon = QtGui.QIcon("src/ikonice/logo.jpg")
        self.main_window.setWindowIcon(icon)

        self.meni_bar = MenuBar(self.main_window, parent=None)

        self.tool_bar = ToolBar(self.main_window,parent=None)
        self.tool_bar.dodaj.triggered.connect(self.dodavanje_u_datoteku)
        self.tool_bar.izmeni_tabelu.triggered.connect(self.izmena_u_datoteci)
        self.tool_bar.pretrazi.triggered.connect(self.otvori_pretragu)
        self.tool_bar.ponisti_pretragu.triggered.connect(self.ponisti_pretragu)
        self.tool_bar.ukloni_iz_tabele.triggered.connect(self.ukloni_iz_tabele)
        self.tool_bar.spoji_datoteke.triggered.connect(self.spoji_datoteke)
        # self.tool_bar.podeli_datoteku.triggered.connect(self.podeli_datoteku)
        
        status_bar = QtWidgets.QStatusBar()
        #status_bar.showMessage("Prikazan status bar!")
        self.main_window.setStatusBar(status_bar)
        
        self.central_widget = QtWidgets.QTabWidget(self.main_window) 
        self.central_widget.setTabsClosable(True) 
        self.central_widget.tabCloseRequested.connect(self.delete_tab)
        self.main_window.setCentralWidget(self.central_widget)


        self.dock = LeftDock("", parent=None)
        self.main_window.addDockWidget(Qt.LeftDockWidgetArea,self.dock) 
        self.dock.tree.setSelectionMode(QAbstractItemView.SingleSelection) 
        self.dock.tree.clicked.connect(self.read)
        self.multi_selekt = []
        
        self.listener = keyboard.Listener(on_press=self.pritisnuto_dugme, on_release=self.pusteno_dugme) 
        self.listener.start()
        self.main_window.show()

    def ponisti_pretragu(self):
        if self.central_widget.currentWidget() == None:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedna datoteka nije otvorena!")
            poruka.exec_()
            return

        model = self.central_widget.currentWidget().table.model()
        model = pretraga(
            [], [],
            [], 
            self.central_widget.currentWidget().meta_podaci,
            True,
            self.central_widget.currentWidget())

        self.central_widget.currentWidget().table.setModel(model)
        self.central_widget.currentWidget().table.selectRow(0)
        self.central_widget.currentWidget().column_resize()

    def podeli_datoteku(self): # kopirano od metode pretrage
        if len(self.multi_selekt) == 0:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedna datoteka nije selektovana za spajanje!")
            poruka.exec_()
            return
        
        prikaz = PrikazElementa(self.central_widget.currentWidget(),True)
        prikaz.exec_()
        if len(prikaz.lista_atr) != 0 and len(prikaz.lista_kriterijuma) != 0:
            model = self.central_widget.currentWidget().table.model()
            model = pretraga(
                prikaz.lista_atr, prikaz.lista_kriterijuma,
                prikaz.lista_vece_manje, 
                self.central_widget.currentWidget().meta_podaci,
                False)

            if len(model.lista_prikaz) == 0:
                poruka = QMessageBox()
                icon = QtGui.QIcon("src/ikonice/logo.jpg")
                poruka.setWindowIcon(icon)
                poruka.setWindowTitle("Upozorenje!")
                poruka.setText("Zadata pretraga nije pronasla vrednosti koje odgovaraju zadatim kriterijumima.")
                poruka.exec_()
                return

            self.central_widget.currentWidget().table.setModel(model)
        else:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Niste zadali ni jedan kriterijum za pretragu, pretraga je prekinuta.")
            poruka.exec_()
            return

    def spoji_datoteke(self):
        if len(self.multi_selekt) < 2:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nije vise datoteka selektovano za spajanje!")
            poruka.exec_()
            return

        lista = []
        self.multi_selekt.sort()
        
        brojac = 0
        while brojac < len(self.multi_selekt):
            nadjen = False
            for j in range(len(lista)):
                if self.multi_selekt[brojac].row() == lista[j]:
                    nadjen = True
                    break
            if nadjen:
                self.multi_selekt.pop(brojac)
                brojac -= 1
            lista.append(self.multi_selekt[brojac].row())
            brojac += 1

        text, ok = QtWidgets.QInputDialog.getText(None, "Spajanje datoteka", "Unesite ime nove datoteke:", QtWidgets.QLineEdit.Normal, "")
        ime_nove_datoteke = "podaci/podaci/"
        if ok:
            ime_nove_datoteke += str(text) + ".csv"
        else:
            return
            
        for i in range(0, len(self.multi_selekt)-1, 2):
            spoji_dve_sekvencijalne_datoteke(
                self.dock.model.filePath(self.multi_selekt[i]),
                self.dock.model.filePath(self.multi_selekt[i+1]),
                self.central_widget.currentWidget().meta_podaci[11].split(","),
                self.central_widget.currentWidget().meta_podaci[5].split(","),
                True,
                ime_nove_datoteke,
                self)

        self.multi_selekt = []

    def pritisnuto_dugme(self, key):
        if key == Key.ctrl_l:
            self.dock.tree.setSelectionMode(QAbstractItemView.MultiSelection) 

    def pusteno_dugme(self, key):
        if key == Key.ctrl_l:
            self.dock.tree.setSelectionMode(QAbstractItemView.SingleSelection)
            self.multi_selekt = self.dock.tree.selectedIndexes()
            

    def otvori_tabelu_levi_rodjak(self):...
    
    def otvori_tabelu_desni_rodjak(self):...

    def ukloni_iz_tabele(self):
        if self.central_widget.currentWidget() == None:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedna datoteka nije otvorena!")
            poruka.exec_()
            return
        
        elif not hasattr(self.central_widget.currentWidget().table, "selected_elem"):
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje")
            poruka.setText("Trenutno nijedan element nije selektovan!")
            poruka.exec_()
            return
        ime_datoteke = self.central_widget.currentWidget().meta_podaci[0]    
        tip_datoteke = self.central_widget.currentWidget().meta_podaci[1]  
        model = self.central_widget.currentWidget().table.model()
        element_selected = model.get_element(self.central_widget.currentWidget().table.selected_elem)
        putanja = self.central_widget.currentWidget().meta_podaci[4]
        lista_kljuceva = self.central_widget.currentWidget().meta_podaci[11].split(",")
        lista_atributa = self.central_widget.currentWidget().meta_podaci[5].split(",")
        lista_tip_atributa = self.central_widget.currentWidget().meta_podaci[6].split(",")
        veze = []
        veze = self.central_widget.currentWidget().meta_podaci[9].split(",")
        
        #DELETE FROM plan_studijske_grupe WHERE STU_VU_OZNAKA='IR' AND SP_OZNAKA='IT' AND SPB_BLOK=2 AND SPB_POZICIJA=2;
        if tip_datoteke == "sql":
            query= " DELETE FROM " + ime_datoteke + " WHERE "
            brojac = 0 
            for i in range(len(lista_kljuceva)):
                if brojac == 0:
                    query+= lista_kljuceva[i] + "="
                else:
                    query += " AND " + lista_kljuceva[i] + "="
                if lista_tip_atributa[i] == "str":
                    query += "'" + element_selected.__getattribute__(lista_atributa[i]) +"'"
                else:
                    query += element_selected.__getattribute__(lista_atributa[i])
                brojac +=1
            query += ";"

            try:
                self.csor.execute(query)
            except mysql.connector.errors.IntegrityError as e:
                poruka = QtWidgets.QMessageBox() 
                
                icon = QtGui.QIcon("src/ikonice/logo.jpg")
                poruka.setWindowIcon(icon)
                poruka.setWindowTitle("Upozorenje!")
                poruka.setText("Ne mozete izbrisati ovaj element!\n"+e.msg)
                poruka.exec_()
                return

            self.connection.commit()
            query = "SELECT * FROM " + ime_datoteke
            self.csor.execute(query)
            self.central_widget.currentWidget().table.model().lista_prikaz = []
            for result in self.csor.fetchall():
                lista_podataka = []
                for i in result:
                    lista_podataka.append(str(i))
                    
                self.central_widget.currentWidget().table.model().lista_prikaz.append(GenerickaKlasa(lista_atributa, lista_podataka))

        top = QModelIndex()
        top.child(0,0)
        self.central_widget.currentWidget().table.model().beginRemoveRows(top, 0, 0) 
        for i in range(len(veze)): #provjaravamo da li ima djecu, ako ima ne smije se obrisati
            if hasattr(self.central_widget.currentWidget(), "sub_table"+str(i+1)):
                if len(self.central_widget.currentWidget().__getattribute__("sub_table"+str(i+1)).model.lista_prikaz) != 0:
                    poruka = QMessageBox()
                    icon = QtGui.QIcon("src/ikonice/logo.jpg")
                    poruka.setWindowIcon(icon)
                    poruka.setWindowTitle("Upozorenje!")
                    poruka.setText("Selektovani element ne sme da se obrise zato sto se njegovi podaci koriste u podtabelama, njegovoj deci!")
                    poruka.exec_()
                    return
               
        self.central_widget.currentWidget().table.model().lista_prikaz = []
        if tip_datoteke != "sql":
            
            with open(putanja, 'r',newline='') as csvfile:
                spamreader = csv.reader(csvfile, delimiter = "\n")
                counter = 0
                prva_linija = True
                izbrisan = False
                for row in spamreader:
                    if prva_linija:
                        prva_linija = False
                        continue
                    
                    if len(row) == 0:
                        break
                    
                    objekat = GenerickaKlasa(lista_atributa, row[0].split(","))
                    nadjen = True
                    for i in range(len(lista_kljuceva)):
                        if objekat.__getattribute__(lista_kljuceva[i]) != element_selected.__getattribute__(lista_kljuceva[i]):
                            nadjen = False
                
                    if not izbrisan and nadjen:
                        izbrisan = True
                        self.central_widget.currentWidget().table.model().removeRow(counter) #uklanjamo red iz tabele
                    else:
                        self.central_widget.currentWidget().table.model().lista_prikaz.append(objekat)
                    counter += 1
            
            
            
            with open(putanja, 'w', newline='') as f:
                writer = csv.writer(f, delimiter = ",")
                writer.writerow([self.central_widget.currentWidget().putanja_meta])
                for i in range(len(self.central_widget.currentWidget().table.model().lista_prikaz)):
                    tekst = ""
                    for j in range(len(lista_atributa)):
                        tekst += str(self.central_widget.currentWidget().table.model().lista_prikaz[i].__getattribute__(lista_atributa[j]))
                        if j < len(lista_atributa)-1:
                            tekst += ","
                            
                    novi_red = tekst.split(",")
                    writer.writerow(novi_red)
        else:
            query = "SELECT * FROM " + ime_datoteke
            self.csor.execute(query)

            for result in self.csor.fetchall():
                lista_podataka = []
                for i in result:
                    lista_podataka.append(str(i))
                    
                self.central_widget.currentWidget().table.model().lista_prikaz.append(GenerickaKlasa(lista_atributa, lista_podataka))

        self.central_widget.currentWidget().table.model().endRemoveRows()

    def otvori_tabelu_roditelj(self):
        if self.central_widget.currentWidget() == None:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedna datoteka nije otvorena!")
            poruka.exec_()
            return
        elif not hasattr(self.central_widget.currentWidget().table, "selected_elem"):
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedan element nije selektovan!")
            poruka.exec_()
            return

        model = self.central_widget.currentWidget().table.model()
        element_selected = model.get_element(self.central_widget.currentWidget().table.selected_elem)
        veze = []
        veze = self.central_widget.currentWidget().meta_podaci[9].split(",")
        meta_podaci = self.central_widget.currentWidget().meta_podaci
        lista_kljuceva = []
        brojac = len(veze)-1
        lista_roditelja = []

        for i in range(len(veze)):
            if veze[brojac].find("parent_") == -1:
                veze.pop(brojac)
                brojac -= 1
            else:
                lista_roditelja.append(veze[brojac])
                brojac -= 1
        index = -1

        if len(lista_roditelja) == 0:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Selektovani element nema roditelja!")
            poruka.exec_()
            return

        elif len(lista_roditelja) > 1:
            list_tuple = ()
            for i in range(len(lista_roditelja)):
                del1 = lista_roditelja[i].find("_")+1
                del2 = lista_roditelja[i].find("(")
                ime = lista_roditelja[i][del1:del2]

                list_tuple = list_tuple + (ime,)

            input = QtWidgets.QInputDialog.getItem(
                self,
                "Izbor",
                "Trenutna tabela ima vise od 1 roditelja\nIzaberite roditelja:",
                list_tuple,
                0,
                editable=False)
                
            if input[1]:
                for i in range(len(lista_roditelja)):
                    if lista_roditelja[i].find(input[0]) != -1:
                        index = i
                        break
            else:
                return

        elif len(lista_roditelja) == 1:
            index = 0

        if index == -1:
            return
            
        del1 = lista_roditelja[index].find("_")+1
        lista_roditelja[index] = lista_roditelja[index][del1:len(lista_roditelja[index])]
        del1 = lista_roditelja[index].find("(")
        ime_roditelja = lista_roditelja[index][0:del1]
        nova_putanja = ime_roditelja[0].lower()
        
        for s in range(1, len(ime_roditelja)):
            if ime_roditelja[s].isupper():
                nova_putanja += "_" + ime_roditelja[s].lower()
            else:
                nova_putanja += ime_roditelja[s]
                
        
        nova_putanja = meta_podaci[2] + "\\" + nova_putanja
        if meta_podaci[1] == "serijska":
            nova_putanja += "_ser."
            
        elif meta_podaci[1] == "sekvencijalna":
            nova_putanja += "_sek."
            
        elif meta_podaci[1] == "sql":
            nova_putanja += "_meta_podaci_sql."

        nova_putanja += meta_podaci[3]
        
        del1 = lista_roditelja[index].find("(") + 1
        del2 = lista_roditelja[index].find(")")
        lista_kljuceva.append(lista_roditelja[index][del1:del2].split("#"))
        
        if self.central_widget.currentWidget().is_baza:
            tab = Tab(parent=self.central_widget)
            tab.pocetna_strana = self
            tab.naziv = ime_roditelja
            indeks = 0
            for i in range(len(self.imena_tabela)):
                if self.imena_tabela[i] == ime_roditelja:
                    indeks = i
                    break
            for i in range(len(self.lista_baza)):
                if self.lista_baza[i] == self.central_widget.currentWidget().indeks:
                    self.lista_baza.pop(i)
                    break
            tab.indeks = indeks
            tab.read(nova_putanja)
        else:
            tab = Tab(nova_putanja, self.central_widget)
            tab.pocetna_strana = self
            tab.read()

        indeks_roditelja = -1
        for j in range(len(tab.table.model().lista_prikaz)):
            pronadjen = True
            for m in range(len(lista_kljuceva[len(lista_kljuceva)-1])):
                kljucevi = lista_kljuceva[len(lista_kljuceva)-1][m].split("=")
                if len(kljucevi) == 1:
                    if element_selected.__getattribute__(kljucevi[0]) != tab.table.model().lista_prikaz[j].__getattribute__(kljucevi[0]):
                        pronadjen = False
                elif len(kljucevi) == 2:
                    if element_selected.__getattribute__(kljucevi[0]) != tab.table.model().lista_prikaz[j].__getattribute__(kljucevi[1]):
                        pronadjen = False
                else:
                    print("pocetna_strana.py, 124 linija, eror u len(klucevi):", len(kljucevi), "// ", kljucevi)
            if pronadjen:
                indeks_roditelja = j
                break
        
        if indeks_roditelja == -1:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Selektovani element nema roditelja sa istim kljucem kao kod selektovanog!")
            poruka.exec_()
            return

        tab.table.selectRow(indeks_roditelja)
        top = tab.table.currentIndex()
        tab.element_selected(top)

        # tab.table.setModel(tab.table.model())

        tab.btn_down.clicked.connect(self.otvori_tabelu_dete)
        tab.btn_up.clicked.connect(self.otvori_tabelu_roditelj)
        # tab.btn_left.clicked.connect(self.otvori_tabelu_levi_rodjak)
        # tab.btn_right.clicked.connect(self.otvori_tabelu_desni_rodjak)

        self.central_widget.removeTab(self.central_widget.currentIndex())
        self.central_widget.addTab(tab, ime_roditelja)

        meta = ""
        for s in range(len(self.central_widget.currentWidget().meta_podaci[0])):
            if self.central_widget.currentWidget().meta_podaci[0][s].isupper():
                meta += "_" + self.central_widget.currentWidget().meta_podaci[0][s].lower()
            else:
                meta += self.central_widget.currentWidget().meta_podaci[0][s]
                
        meta = meta[1:len(meta)]
        meta = self.central_widget.currentWidget().meta_podaci[2] + "\\" + meta
        if self.central_widget.currentWidget().meta_podaci[1] == "serijska":
            meta += "_ser."
            
        elif self.central_widget.currentWidget().meta_podaci[1] == "sekvencijalna":
            meta += "_sek."
            
        elif self.central_widget.currentWidget().meta_podaci[1] == "sql":
            meta += "_meta_podaci_sql."

        meta += self.central_widget.currentWidget().meta_podaci[3]
        
        self.lista_putanja.append(meta)
        self.lista_putanja.remove(self.lista_putanja[self.central_widget.currentIndex()])

    def otvori_tabelu_dete(self):
        if self.central_widget.currentWidget() == None:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedna datoteka nije otvorena!")
            poruka.exec_()
            return
        elif not hasattr(self.central_widget.currentWidget().table, "selected_elem"):
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedan element nije selektovan!")
            poruka.exec_()
            return
        elif self.central_widget.currentWidget().tab_widget.currentWidget() == None:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Selektovani element nema podtabele!")
            poruka.exec_()
            return
        elif len(self.central_widget.currentWidget().tab_widget.currentWidget().model.lista_prikaz) == 0:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Selektovani element nema decu u selektovanoj podtabeli!")
            poruka.exec_()
            return

        child = self.central_widget.currentWidget().tab_widget.currentWidget()
        if self.central_widget.currentWidget().is_baza:
            tab = Tab(parent=self.central_widget)
            tab.pocetna_strana = self
            tab.naziv = child.naziv
            indeks = 0
            for i in range(len(self.imena_tabela)):
                if self.imena_tabela[i] == child.naziv:
                    indeks = i
                    break
            for i in range(len(self.lista_baza)):
                if self.lista_baza[i] == self.central_widget.currentWidget().indeks:
                    self.lista_baza.pop(i)
                    break
            tab.indeks = indeks
            # self.lista_baza.append(indeks)
            tab.read(child.putanja)
        else:
            tab = Tab(child.putanja, self.central_widget)
            tab.pocetna_strana = self
            tab.read()
        tab.table.model().lista_prikaz = child.model.lista_prikaz
        
        tab.btn_down.clicked.connect(self.otvori_tabelu_dete)
        tab.btn_up.clicked.connect(self.otvori_tabelu_roditelj)

        self.central_widget.removeTab(self.central_widget.currentIndex())
        self.central_widget.addTab(tab, child.meta_podaci[0])

        meta = ""
        for s in range(len(child.meta_podaci[0])):
            if child.meta_podaci[0][s].isupper():
                meta += "_" + child.meta_podaci[0][s].lower()
            else:
                meta += child.meta_podaci[0][s]
                
        meta = meta[1:len(meta)]
        meta = child.meta_podaci[2] + "\\" + meta
        if child.meta_podaci[1] == "serijska":
            meta += "_ser."
            
        elif child.meta_podaci[1] == "sekvencijalna":
            meta += "_sek."
            
        elif child.meta_podaci[1] == "sql":
            meta += "_meta_podaci_sql."

        meta += child.meta_podaci[3]

        self.lista_putanja.append(meta)
        self.lista_putanja.remove(self.lista_putanja[self.central_widget.currentIndex()])

    def izmena_u_datoteci(self):
        if self.central_widget.currentWidget() == None:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedna datoteka nije otvorena!")
            poruka.exec_()
            return
        elif not hasattr(self.central_widget.currentWidget().table, "selected_elem"):
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedan element nije selektovan!")
            poruka.exec_()
            return
            
        model = self.central_widget.currentWidget().table.model()
        selektovani_element = model.get_element(self.central_widget.currentWidget().table.selected_elem)
        prikaz = PrikazElementa(self.central_widget.currentWidget(), False, selektovani_element)
    
        prikaz.exec_()
        self.central_widget.currentWidget().column_resize()

    def dodavanje_u_datoteku(self):
        if self.central_widget.currentWidget() == None:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedna datoteka nije otvorena!")
            poruka.exec_()
            return
            
        prikaz = PrikazElementa(self.central_widget.currentWidget())
    
        prikaz.exec_()
        self.central_widget.currentWidget().column_resize()

    def otvori_pretragu(self):
        if self.central_widget.currentWidget() == None:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Trenutno nijedna datoteka nije otvorena!")
            poruka.exec_()
            return

        prikaz = PrikazElementa(self.central_widget.currentWidget(),True)
        prikaz.exec_()
        if len(prikaz.lista_atr) != 0 and len(prikaz.lista_kriterijuma) != 0:
            model = self.central_widget.currentWidget().table.model()
            model = pretraga(
                prikaz.lista_atr, prikaz.lista_kriterijuma,
                prikaz.lista_vece_manje, 
                self.central_widget.currentWidget().meta_podaci,
                False,
                self.central_widget.currentWidget())

            if len(model.lista_prikaz) == 0:
                poruka = QMessageBox()
                icon = QtGui.QIcon("src/ikonice/logo.jpg")
                poruka.setWindowIcon(icon)
                poruka.setWindowTitle("Upozorenje!")
                poruka.setText("Zadata pretraga nije pronasla vrednosti koje odgovaraju zadatim kriterijumima.")
                poruka.exec_()
                return

            self.central_widget.currentWidget().table.setModel(model)
            self.central_widget.currentWidget().table.selectRow(0)
        else:
            poruka = QMessageBox()
            icon = QtGui.QIcon("src/ikonice/logo.jpg")
            poruka.setWindowIcon(icon)
            poruka.setWindowTitle("Upozorenje!")
            poruka.setText("Niste zadali ni jedan kriterijum za pretragu, pretraga je prekinuta.")
            poruka.exec_()
            return
            
        self.central_widget.currentWidget().column_resize()

    def delete_tab(self, index):
        self.central_widget.setCurrentIndex(index)
        tab = self.central_widget.currentWidget()
        if tab.is_baza:
            for i in range(len(self.lista_baza)):
                if self.lista_baza[i] == tab.indeks:
                    self.lista_baza.pop(i)
                    break
            self.central_widget.removeTab(index)
            return
        if hasattr(tab, "sortirano") and len(tab.table.model().lista_prikaz) > 1:
            if tab.meta_podaci[1] == "serijska": 
                while True:
                    izabrano = -1
                    list_tuple = ()
                    lista = ["Samo stare podatke", "Samo nove podatke", "Ili i stare i nove podatke"]
                    for i in range(len(lista)):
                        list_tuple = list_tuple + (lista[i],)

                    input = QtWidgets.QInputDialog.getItem(
                        tab,
                        "Izbor",
                        "Posto ste sortirali tabelu\nIzaberite da li zelite da sacuvate:",
                        list_tuple,
                        0,
                        editable=False)
                        
                    if input[1]:
                        for i in range(len(lista)):
                            if lista[i].find(input[0]) != -1:
                                izabrano = i
                                break
                        break

                putanja = tab.meta_podaci[4]

                if izabrano == 2:
                    i = 0
                    while True:
                        del1 = tab.meta_podaci[4].rfind(".")
                        deo = tab.meta_podaci[4][0:del1]
                        nastavak = tab.meta_podaci[4][del1:len(tab.meta_podaci[4])]
                        if not os.path.exists(deo + "_new"+str(i+1) + nastavak):
                            putanja = deo + "_new"+str(i+1) + nastavak
                            break
                        i += 1

                if izabrano != 0:
                    with open(putanja, 'w', newline='') as f:
                        writer = csv.writer(f, delimiter = ",")
                        writer.writerow([tab.putanja_meta])
                        for i in range(len(tab.table.model().lista_prikaz)):
                            tekst = ""
                            for j in range(len(tab.table.model().nazivi_atributa)):
                                tekst += str(tab.table.model().lista_prikaz[i].__getattribute__(tab.table.model().nazivi_atributa[j]))
                                if j < len(tab.table.model().nazivi_atributa)-1:
                                    tekst += ","
                                
                            novi_red = tekst.split(",")
                            writer.writerow(novi_red)

        self.central_widget.removeTab(index)
        self.lista_putanja.remove(self.lista_putanja[index])

    def read(self, index):
        putanja = self.dock.model.filePath(index)
        if os.path.isdir(putanja):
            return

        ista_putanja = False
        for i in range(len(self.lista_putanja)):
            if putanja == self.lista_putanja[i]:
                ista_putanja = True
                return
        if not ista_putanja:
            self.lista_putanja.append(putanja)
            if putanja.find(".sql") != -1:
                self.connection = mysql.connector.connect(user="******", password="******", host="127.0.0.1", database="projekat")
                self.csor = self.connection.cursor()
                putanja = "podaci\metaPodaci\projekat_meta_podaci.csv"
                meta_podaci = citanje_meta_podataka(putanja, True)
                self.imena_tabela = meta_podaci[4].split(",")

                self.treeView = QTreeView()
                self.treeView.setContextMenuPolicy(Qt.CustomContextMenu)
                self.treeView.customContextMenuRequested.connect(self.dugme_baza)
                
                model = QStandardItemModel(parent=self.dock.tree.sub_layout)
                item = QStandardItem("zatvori")
                item.setEditable(False)
                model.appendRow(item)
                for text in self.imena_tabela:
                    item = QStandardItem(text)
                    item.setEditable(False)
                    model.appendRow(item)
                
                self.treeView.setModel(model)
                self.treeView.clicked.connect(self.dugme_baza)
                self.treeView.PositionAtBottom

                si = self.dock.tree.sub_layout.sizeHint()
                si.setWidth(self.dock.width())
                si.setHeight(200)
                self.treeView.setFixedSize(si.width(), si.height())

                self.treeView.setHeaderHidden(True)
                self.dock.tree.sub_layout.addWidget(self.treeView)
                self.dock.tree.sub_layout.setAlignment(self.treeView, QtCore.Qt.AlignBottom)
                return

            tab = Tab(putanja, parent=self.central_widget)
            tab.pocetna_strana = self

            if putanja != "":
                tab.read()
            else:
                tab.read(putanja)
            tab.btn_down.clicked.connect(self.otvori_tabelu_dete)
            tab.btn_up.clicked.connect(self.otvori_tabelu_roditelj)
            tab.naziv = tab.meta_podaci[0]
            self.central_widget.addTab(tab, tab.naziv)
            self.central_widget.setCurrentIndex(self.central_widget.currentIndex()+1)
    
    def dugme_baza(self, model_indeks):
        indeks = model_indeks.row()
        if indeks == 0:
            self.treeView.close()
            for i in range(len(self.lista_putanja)):
                if self.lista_putanja[i].find(".sql") != 1:
                    self.lista_putanja.pop(i)
                    break

            self.central_widget.setCurrentIndex(indeks)
            brojac = 0
            while len(self.lista_baza) != 0:
                tab = self.central_widget.currentWidget()
                if tab.is_baza:
                    for i in range(brojac, len(self.lista_baza)):
                        if self.lista_baza[brojac] == tab.indeks:
                            self.lista_baza.pop(brojac)
                            self.central_widget.removeTab(indeks)
                            break
                        else:
                            brojac += 1
                else:
                    indeks += 1
                    self.central_widget.setCurrentIndex(indeks)

            self.csor.close()
            self.connection.close()
            return
        else:
            indeks -= 1
            for i in range(len(self.lista_baza)):
                if self.lista_baza[i] == indeks:
                    return
            self.lista_baza.append(indeks)

        tab = Tab(parent=self.central_widget)
        tab.pocetna_strana = self
        tab.indeks = indeks
        tab.naziv = self.imena_tabela[indeks]
        
        nova_putanja = "podaci\\metaPodaci\\"
        nova_putanja += self.imena_tabela[indeks][0].lower()
        
        for s in range(1, len(self.imena_tabela[indeks])):
            if self.imena_tabela[indeks][s].isupper():
                nova_putanja += "_" + self.imena_tabela[indeks][s].lower()
            else:
                nova_putanja += self.imena_tabela[indeks][s]
        
        nova_putanja += "_meta_podaci_sql.csv"

        tab.read(nova_putanja)
        tab.btn_down.clicked.connect(self.otvori_tabelu_dete)
        tab.btn_up.clicked.connect(self.otvori_tabelu_roditelj)
        self.central_widget.addTab(tab, tab.naziv)
        self.central_widget.setCurrentIndex(self.central_widget.currentIndex()+1)