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)
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()
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)
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)
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)
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)
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)