class Cart_Pay(QWidget): #Initialiaze the first page for class View_Menu_First_Page() def __init__(self,parent=None): super(Cart_Pay,self).__init__(parent) self.resize(800,600) self.stackedwidget = QStackedWidget(self) self.stackedwidget.setGeometry(QtCore.QRect(0,0 , 800, 600)) self.stackedwidget.setObjectName("stackwidget") self.add_first_page() #function to show first page def add_first_page(self): self.first_page = Pay_First_Page() self.stackedwidget.addWidget(self.first_page) self.stackedwidget.setCurrentIndex(0) print(self.first_page.tableWidget.rowCount()) self.first_page.BlueButton.clicked.connect(self.add_second_page) #only can use lambda: to make use of return value form functions #function to show second page def add_second_page(self): self.second_page = See_Waiting_Time() self.stackedwidget.addWidget(self.second_page) self.stackedwidget.setCurrentIndex(1)
def init_main_stacked_widget(self): """ create and return the main stackedWidget object """ stacked_widget = QStackedWidget(self) stacked_widget.setObjectName(u"stacked_widget") stacked_widget.setGeometry(QRect(0, 0, WINDOW_HEIGHT, WINDOW_WIDTH)) return stacked_widget
def _initUI(self): self.toolbar = None w = QStackedWidget() w.setObjectName('block-principal') self.setCentralWidget(w) style = PARAMETERS["MAIN_STYLE"] + PARAMETERS["WIDGETS_STYLE"] self.setStyleSheet(style) self.setWindowTitle(self.WINDOW_TITLE) self.setWindowIcon(AppIcon()) self.move(200, 200)
class View_Menu(QWidget): #Initialiaze the first page for class View_Menu_First_Page() def __init__(self,parent=None): super(View_Menu,self).__init__(parent) self.resize(800,600) self.stackedwidget = QStackedWidget(self) self.stackedwidget.setGeometry(QtCore.QRect(0,0 , 800, 600)) self.stackedwidget.setObjectName("stackwidget") self.add_first_page() #function to show first page def add_first_page(self): self.first_page = View_Menu_First_Page() self.stackedwidget.addWidget(self.first_page) self.stackedwidget.setCurrentIndex(0) self.first_page.label_malay.clicked.connect(lambda:self.add_second_page(self.first_page.MY_link_click())) #only can use lambda: to make use of return value form functions self.first_page.label_mcdonalds.clicked.connect(lambda:self.add_second_page(self.first_page.MC_link_click())) #only can use lambda: to make use of return value form functions self.first_page.label_kfc.clicked.connect(lambda:self.add_second_page(self.first_page.KFC_link_click())) #only can use lambda: to make use of return value form functions self.first_page.label_subway.clicked.connect(lambda:self.add_second_page(self.first_page.Subway_link_click())) #only can use lambda: to make use of return value form functions #function to show second page def add_second_page(self,store): self.second_page = View_Menu_Second_Page(store) self.stackedwidget.addWidget(self.second_page) self.stackedwidget.setCurrentIndex(1) if 'Subway' in self.second_page.Logo.text(): print('Logo') self.second_page.BlueButton.clicked.connect(lambda:self.add_third_page(self.first_page.Subway_link_click(),self.second_page.SearchMenu())) elif 'Malay' in self.second_page.Logo.text(): print('Malay logo') self.second_page.BlueButton.clicked.connect(lambda:self.add_third_page(self.first_page.MY_link_click(),self.second_page.SearchMenu())) elif 'Mcdonalds' in self.second_page.Logo.text(): print('Mcdonalds Logo') self.second_page.BlueButton.clicked.connect(lambda:self.add_third_page(self.first_page.Mc_link_click(),self.second_page.SearchMenu())) elif 'KFC' in self.second_page.Logo.text(): print('KFC Logo') self.second_page.BlueButton.clicked.connect(lambda:self.add_third_page(self.first_page.KFC_link_click(),self.second_page.SearchMenu())) #function to show third page def add_third_page(self,store,date_and_time): self.third_page = View_Menu_Third_Page(store,date_and_time) self.stackedwidget.addWidget(self.third_page) self.stackedwidget.setCurrentIndex(2) #kfcCombine.KFC_breakfast_window.BlueButton_2.clicked.connect(self.go_back) self.third_page.BlueButton_2.clicked.connect(self.go_back) def go_back(self): self.stackedwidget.setCurrentIndex(0) self.stackedwidget.removeWidget(self.second_page) self.stackedwidget.removeWidget(self.third_page)
class salUI(object): def __init__(self): super(salUI).__init__() def setupUI(self, MainWindow): MainWindow.setWindowIcon(QIcon("icons/saldb_red")) MainWindow.setWindowTitle("Simple Anime Library | ヽ( ´ー`)ノ") # setup menubar menubar = MainWindow.menuBar() self.mb_file = menubar.addMenu("File") self.mb_edit = menubar.addMenu("Edit") self.mb_view = menubar.addMenu("View") self.mb_help = menubar.addMenu("Help") # menubar file menu self.mb_newAction = QAction("New Entry", MainWindow) self.mb_file.addAction(self.mb_newAction) # menubar edit menu self.mb_editEntryAction = QAction("Edit Entry", MainWindow) self.mb_edit.addAction(self.mb_editEntryAction) # menubar view menu # TODO # menubar help menu # TODO # Toolbar self.toolbar = QToolBar(MainWindow) self.toolbar.setIconSize(QSize(40, 40)) MainWindow.addToolBar(self.toolbar) self.addnewAction = QAction(QIcon("icons/add_1.png"), "Create New Entry", MainWindow) self.addnewAction.setShortcut('Ctrl+N') self.toolbar.addAction(self.addnewAction) self.deleteAction = QAction(QIcon("icons/delete_1.png"), "Delete Entry", MainWindow) self.deleteAction.setShortcut("Ctrl+D") self.toolbar.addAction(self.deleteAction) self.editAction = QAction(QIcon("icons/edit.png"), "Edit Entry", MainWindow) self.editAction.setShortcut("Ctrl+E") self.toolbar.addAction(self.editAction) self.toolbar.addSeparator() self.findAction = QAction(QIcon("icons/find.png"), "Search", MainWindow) self.findAction.setShortcut("Ctrl+F") self.toolbar.addAction(self.findAction) self.queryAction = QAction(QIcon("icons/filter.png"), "Filter/Sort", MainWindow) self.queryAction.setShortcut("Ctrl+Alt+Q") self.toolbar.addAction(self.queryAction) self.toolbar.addSeparator() self.settingsAction = QAction(QIcon("icons/settings.png"), "App Settings", MainWindow) self.settingsAction.setShortcut("Ctrl+Shift+S") self.toolbar.addAction(self.settingsAction) self.infoAction = QAction(QIcon("icons/info.png"), "App Info", MainWindow) self.toolbar.addAction(self.infoAction) ############################################################################################################# self.centralWidget = QWidget(MainWindow) self.centralWidget.setObjectName('central') self.splitter = QSplitter(self.centralWidget) self.splitter.setOrientation(Qt.Horizontal) self.splitter.setStretchFactor(0, 25) self.splitter.setStretchFactor(1, 75) # sidebar (QListWidget) self.sidebar = QListWidget(self.splitter) self.sidebar.setObjectName('sidebar') self.sidebar.addItem('Fin.') self.sidebar.addItem('Planned') self.sidebar.addItem('Ongoing') self.sidebar.addItem('Current') self.sidebar.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) # [nevermind lol] pretty sure i dont need this here, it should be created in the backend and added to the stack. self.watchListTable = QTableWidget() self.watchListTable.setObjectName('watchListTable') self.watchListTable.setSelectionBehavior(QAbstractItemView.SelectRows) self.watchListTable.setSelectionMode(QAbstractItemView.SingleSelection) self.watchListTable.setContextMenuPolicy(Qt.CustomContextMenu) self.watchListTable.customContextMenuRequested.connect( self.tableContextMenu) self.watchListTable.setEditTriggers(QAbstractItemView.NoEditTriggers) self.watchListTable.setFont(QFont('Arial', 14)) self.watchListTable.setWordWrap(False) #self.watchListTable.setTextAlignment(Qt.AlignCenter) self.watchListTable.setColumnCount(7) self.watchListTable.setHorizontalHeaderLabels([ "Art", "Title", "English Title", "SUB/DUB", "Start Date", "Completion Date", "Series Type" ]) self.watchListTable.verticalHeader().setDefaultSectionSize(140) self.watchListTable.horizontalHeader().setDefaultSectionSize(120) # stackwidget to switch contents of list catagories self.tableStack = QStackedWidget(self.splitter) self.tableStack.setObjectName('tablestack') self.tableStack.addWidget(self.watchListTable) # add widgets to splitter self.splitter.addWidget(self.sidebar) self.splitter.addWidget(self.tableStack) self.splitter.setSizes([50, 650]) ######################################################################################################## ######################################################################################################## self.boxLayout = QHBoxLayout() self.centralWidget.setLayout(self.boxLayout) MainWindow.setCentralWidget(self.centralWidget) self.boxLayout.addWidget(self.splitter) MainWindow.show()
class ExperimentActionsWidget(QtWidgets.QWidget): def __init__(self, parent=None, statusBar=None): logging.debug("ExperimentActionsWidget instantiated") QtWidgets.QWidget.__init__(self, parent=None) self.statusBar = statusBar self.experimentItemNames = {} self.experimentActionsBaseWidgets = {} self.eco = ExperimentConfigIO.getInstance() self.rolledoutjson = None self.setObjectName("ExperimentActionsWidget") self.windowWidget = QtWidgets.QWidget() self.windowWidget.setObjectName("windowWidget") self.windowBoxHLayout = QtWidgets.QHBoxLayout() #self.windowBoxHLayout.setContentsMargins(0, 0, 0, 0) self.windowBoxHLayout.setObjectName("windowBoxHLayout") self.windowWidget.setLayout(self.windowBoxHLayout) self.experimentTree = QtWidgets.QTreeWidget(parent) self.experimentTree.setObjectName("experimentTree") self.experimentTree.header().resizeSection(0, 150) self.experimentTree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.experimentTree.customContextMenuRequested.connect( self.showContextMenu) self.experimentTree.itemSelectionChanged.connect(self.onItemSelected) self.experimentTree.setEnabled(True) self.experimentTree.setMinimumSize(200, 521) self.experimentTree.setMaximumWidth(350) self.experimentTree.setObjectName("experimentTree") self.experimentTree.headerItem().setText(0, "Experiments New") self.experimentTree.setSortingEnabled(False) self.windowBoxHLayout.addWidget(self.experimentTree) self.windowBoxVLayout = QtWidgets.QVBoxLayout() #self.windowBoxHLayout.setContentsMargins(0, 0, 0, 0) self.windowBoxVLayout.setObjectName("windowBoxVLayout") self.basedataStackedWidget = QStackedWidget() self.basedataStackedWidget.setObjectName("basedataStackedWidget") self.basedataStackedWidget.setEnabled(False) self.windowBoxVLayout.addWidget(self.basedataStackedWidget) self.refreshVMsButton = QtWidgets.QPushButton("Refresh Status") self.refreshVMsButton.clicked.connect(self.refreshVMStatus) self.refreshVMsButton.setEnabled(False) self.windowBoxVLayout.addWidget(self.refreshVMsButton) self.windowBoxHLayout.addLayout(self.windowBoxVLayout) # Context menus self.experimentMenu = QtWidgets.QMenu() self.startupContextMenu = QtWidgets.QMenu("Startup") self.shutdownContextMenu = QtWidgets.QMenu("Shutdown") self.stateContextMenu = QtWidgets.QMenu("State") self.experimentMenu.addMenu(self.startupContextMenu) self.experimentMenu.addMenu(self.shutdownContextMenu) self.experimentMenu.addMenu(self.stateContextMenu) self.cloneExperiment = self.startupContextMenu.addAction( "Signal - Create Clones") self.cloneExperiment.triggered.connect(self.menuItemSelected) self.startVMs = self.startupContextMenu.addAction( "Signal - Start VMs (headless)") self.startVMs.triggered.connect(self.menuItemSelected) self.restoreSnapshots = self.startupContextMenu.addAction( "Signal - Restore Snapshots") self.restoreSnapshots.triggered.connect(self.menuItemSelected) self.pauseVMs = self.shutdownContextMenu.addAction( "Signal - Pause VMs") self.pauseVMs.triggered.connect(self.menuItemSelected) self.suspendVMs = self.shutdownContextMenu.addAction( "Signal - Suspend & Save States") self.suspendVMs.triggered.connect(self.menuItemSelected) self.poweroffVMs = self.shutdownContextMenu.addAction( "Signal - Power Off VMs") self.poweroffVMs.triggered.connect(self.menuItemSelected) self.deleteClones = self.shutdownContextMenu.addAction( "Signal - Delete Clones") self.deleteClones.triggered.connect(self.menuItemSelected) self.shutdownContextMenu.addAction(self.deleteClones) self.snapshotVMs = self.stateContextMenu.addAction( "Signal - Snapshot VMs") self.snapshotVMs.triggered.connect(self.menuItemSelected) self.setLayout(self.windowBoxHLayout) self.retranslateUi() def retranslateUi(self): logging.debug("ExperimentActionsWidget: retranslateUi(): instantiated") self.setWindowTitle("ExperimentActionsWidget") self.experimentTree.headerItem().setText(0, "Experiments") self.experimentTree.setSortingEnabled(False) def onItemSelected(self): logging.debug("MainApp:onItemSelected instantiated") self.basedataStackedWidget.setEnabled(True) self.refreshVMsButton.setEnabled(True) # Get the selected item selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:onItemSelected no configurations left") self.statusBar.showMessage( "No configuration items selected or available.") return #Check if it's the case that an experiment name was selected parentparentSelectedItem = None parentSelectedItem = selectedItem.parent() if parentSelectedItem != None: parentparentSelectedItem = selectedItem.parent().parent() if parentSelectedItem == None: #A base widget was selected self.basedataStackedWidget.setCurrentWidget( self.experimentActionsBaseWidgets[selectedItem.text( 0)]["ExperimentActionsBaseWidget"]) self.experimentTree.resizeColumnToContents(0) elif parentparentSelectedItem == None: #A base widget was selected self.basedataStackedWidget.setCurrentWidget( self.experimentActionsBaseWidgets[parentSelectedItem.text( 0)]["ExperimentActionsBaseWidget"]) self.experimentTree.resizeColumnToContents(0) else: #Check if it's the case that a VM Name was selected if (selectedItem.text(0)[0] == "V"): logging.debug( "Setting right widget: " + str(self.experimentActionsBaseWidgets[ parentparentSelectedItem.text(0)] ["ExperimentActionsVMWidgets"][selectedItem.text(0)])) self.basedataStackedWidget.setCurrentWidget( self.experimentActionsBaseWidgets[ parentparentSelectedItem.text(0)] ["ExperimentActionsVMWidgets"][selectedItem.text(0)]) if (selectedItem.text(0)[0] == "S"): logging.debug( "Setting right widget: " + str(self.experimentActionsBaseWidgets[ parentparentSelectedItem.text(0)] ["ExperimentActionsSetWidgets"][selectedItem.text(0)])) self.basedataStackedWidget.setCurrentWidget( self.experimentActionsBaseWidgets[ parentparentSelectedItem.text(0)] ["ExperimentActionsSetWidgets"][selectedItem.text(0)]) if (selectedItem.text(0)[0] == "T"): logging.debug("Setting right widget: " + str(self.experimentActionsBaseWidgets[ parentparentSelectedItem.text(0)] ["ExperimentActionsTemplateWidgets"][ selectedItem.text(0)])) self.basedataStackedWidget.setCurrentWidget( self.experimentActionsBaseWidgets[ parentparentSelectedItem.text(0)] ["ExperimentActionsTemplateWidgets"][selectedItem.text(0)]) if (selectedItem.text(0)[0] == "U"): logging.debug("Setting right widget: " + str( self.experimentActionsBaseWidgets[ parentparentSelectedItem.text(0)] ["ExperimentActionsUserWidgets"][selectedItem.text(0)])) self.basedataStackedWidget.setCurrentWidget( self.experimentActionsBaseWidgets[ parentparentSelectedItem.text(0)] ["ExperimentActionsUserWidgets"][selectedItem.text(0)]) def getExperimentVMRolledOut(self, configname, config_json): logging.debug( "ExperimentActionsWidget(): getExperimentVMRolledOut(): retranslateUi(): instantiated" ) self.rolledoutjson = self.eco.getExperimentVMRolledOut( configname, config_json) def addExperimentItem(self, configname, config_jsondata=None): logging.debug("addExperimentItem(): retranslateUi(): instantiated") if configname in self.experimentItemNames: logging.error( "addExperimentItem(): Item already exists in tree: " + str(configname)) return userpool = UserPool() ##Now add the item to the tree widget and create the baseWidget experimentTreeWidgetItem = QtWidgets.QTreeWidgetItem( self.experimentTree) experimentTreeWidgetItem.setText(0, configname) experimentSetTreeItem = QtWidgets.QTreeWidgetItem( experimentTreeWidgetItem) experimentSetTreeItem.setText(0, "Sets") experimentCloneTreeItem = QtWidgets.QTreeWidgetItem( experimentTreeWidgetItem) experimentCloneTreeItem.setText(0, "Templates") experimentVMTreeItem = QtWidgets.QTreeWidgetItem( experimentTreeWidgetItem) experimentVMTreeItem.setText(0, "VMs") experimentUserTreeItem = QtWidgets.QTreeWidgetItem( experimentTreeWidgetItem) experimentUserTreeItem.setText(0, "Users") self.experimentItemNames[configname] = experimentTreeWidgetItem #get all rolled out and then get them by VM funcs = [] funcs.append( (self.getExperimentVMRolledOut, configname, config_jsondata)) GUIFunctionExecutingDialog(None, "Processing VMs for " + str(configname), funcs).exec_() rolledoutjson = self.rolledoutjson if rolledoutjson != None: # if file was specified, but it doesn't exist, prepend usernames invalid_userfile = False users_filename = config_jsondata["xml"]["testbed-setup"]["vm-set"][ "users-filename"] if users_filename != None and users_filename.strip() != "": if os.path.exists(users_filename) == False: invalid_userfile = True #get the usersConn associations first: usersConns = userpool.generateUsersConns( configname, creds_file=users_filename, rolledout_json=rolledoutjson) vmuser_mapping = {} for (username, password) in usersConns: for conn in usersConns[(username, password)]: cloneVMName = conn[0] if invalid_userfile == False: vmuser_mapping[cloneVMName] = (username, password) else: vmuser_mapping[cloneVMName] = "userfile_not_found" #create the status widgets (tables) self.experimentActionsBaseWidget = ExperimentActionsVMStatusWidget( self, configname, rolledoutjson=rolledoutjson, interest_vmnames=[], vmuser_mapping=vmuser_mapping, status_bar=self.statusBar) self.experimentActionsBaseWidgets[configname] = { "ExperimentActionsBaseWidget": {}, "ExperimentActionsSetWidgets": {}, "ExperimentActionsTemplateWidgets": {}, "ExperimentActionsVMWidgets": {}, "ExperimentActionsUserWidgets": {} } self.experimentActionsBaseWidgets[configname][ "ExperimentActionsBaseWidget"] = self.experimentActionsBaseWidget self.basedataStackedWidget.addWidget( self.experimentActionsBaseWidget) #Set-based view (template_vms, num_clones) = rolledoutjson #First create the sets from the rolled out data sets = self.eco.getExperimentSetDictFromRolledOut( configname, rolledoutjson) for set in sets: set_item = QtWidgets.QTreeWidgetItem(experimentSetTreeItem) setlabel = "S: Set " + set set_item.setText(0, setlabel) # Set Widget experimentActionsSetStatusWidget = ExperimentActionsVMStatusWidget( self, configname, rolledoutjson=rolledoutjson, interest_vmnames=sets[set], vmuser_mapping=vmuser_mapping, status_bar=self.statusBar) self.experimentActionsBaseWidgets[configname][ "ExperimentActionsSetWidgets"][ setlabel] = experimentActionsSetStatusWidget self.basedataStackedWidget.addWidget( experimentActionsSetStatusWidget) templates = self.eco.getExperimentVMNamesFromTemplateFromRolledOut( configname, rolledoutjson) for templatename in templates: template_item = QtWidgets.QTreeWidgetItem( experimentCloneTreeItem) templatelabel = "T: " + templatename template_item.setText(0, templatelabel) # Set Widget experimentActionsTemplateStatusWidget = ExperimentActionsVMStatusWidget( self, configname, rolledoutjson=rolledoutjson, interest_vmnames=templates[templatename], vmuser_mapping=vmuser_mapping, status_bar=self.statusBar) self.experimentActionsBaseWidgets[configname][ "ExperimentActionsTemplateWidgets"][ templatelabel] = experimentActionsTemplateStatusWidget self.basedataStackedWidget.addWidget( experimentActionsTemplateStatusWidget) #Individual VM-based view vms_list = self.eco.getExperimentVMListsFromRolledOut( configname, rolledoutjson) for vm in vms_list: vmname = vm["name"] vm_item = QtWidgets.QTreeWidgetItem(experimentVMTreeItem) vmlabel = "V: " + vmname vm_item.setText(0, vmlabel) # VM Config Widget experimentActionsVMStatusWidget = ExperimentActionsVMStatusWidget( self, configname, rolledoutjson=rolledoutjson, interest_vmnames=[vmname], vmuser_mapping=vmuser_mapping, status_bar=self.statusBar) self.experimentActionsBaseWidgets[configname][ "ExperimentActionsVMWidgets"][ vmlabel] = experimentActionsVMStatusWidget self.basedataStackedWidget.addWidget( experimentActionsVMStatusWidget) #Individual Users-based view num = 1 for (username, password) in usersConns: vmnames = [ tuple[0] for tuple in usersConns[(username, password)] ] user_item = QtWidgets.QTreeWidgetItem(experimentUserTreeItem) user_label = "U: " + username + " (Set " + str(num) + ")" num += 1 user_item.setText(0, user_label) # VM Config Widget experimentActionsUserStatusWidget = ExperimentActionsVMStatusWidget( self, configname, rolledoutjson=rolledoutjson, interest_vmnames=vmnames, vmuser_mapping=vmuser_mapping, status_bar=self.statusBar) self.experimentActionsBaseWidgets[configname][ "ExperimentActionsUserWidgets"][ user_label] = experimentActionsUserStatusWidget self.basedataStackedWidget.addWidget( experimentActionsUserStatusWidget) self.statusBar.showMessage("Added new experiment: " + str(configname)) logging.debug("addExperimentItem(): retranslateUi(): Completed") def resetExperiment(self, configname, config_jsondata): logging.debug("updateExperimentItem(): retranslateUi(): instantiated") if configname not in self.experimentItemNames: logging.error( "removeExperimentItem(): Item does not exist in tree: " + str(configname)) return self.removeExperimentItem(configname) self.addExperimentItem(configname, config_jsondata) def removeExperimentItem(self, configname): logging.debug("removeExperimentItem(): retranslateUi(): instantiated") if configname not in self.experimentItemNames: logging.error( "removeExperimentItem(): Item does not exist in tree: " + str(configname)) return experimentTreeWidgetItem = self.experimentItemNames[configname] self.experimentTree.invisibleRootItem().removeChild( experimentTreeWidgetItem) del self.experimentItemNames[configname] logging.debug("removeExperimentItem(): Completed") def showContextMenu(self, position): logging.debug( "ExperimentActionsWidget(): showContextMenu(): instantiated") self.experimentMenu.popup(self.experimentTree.mapToGlobal(position)) def getTypeNameFromSelection(self): configname = "" itype = "" name = "" #configname selected if self.experimentTree.currentItem().parent() == None: configname = self.experimentTree.currentItem().text(0) itype = "set" name = "all" #sets, clones, or VMs label selected elif self.experimentTree.currentItem().parent().parent() == None: configname = self.experimentTree.currentItem().parent().text(0) itype = "set" name = "all" #specific item selected elif self.experimentTree.currentItem().parent().parent().parent( ) == None: configname = self.experimentTree.currentItem().parent().parent( ).text(0) currItemText = self.experimentTree.currentItem().text(0) if currItemText.startswith("S: Set "): itype = "set" name = currItemText.split("S: Set ")[1:] name = " ".join(name) elif currItemText.startswith("V: "): itype = "vm" name = currItemText.split("V: ")[1:] name = "\"" + " ".join(name) + "\"" elif currItemText.startswith("T: "): itype = "template" name = currItemText.split("T: ")[1:] name = "\"" + " ".join(name) + "\"" elif currItemText.startswith("U: "): itype = "set" name = currItemText.split("(Set ")[1].split(")")[0:-1] name = " ".join(name) return configname, itype, name def menuItemSelected(self): logging.debug("menuItemSelected(): instantiated") actionlabelname = self.sender().text() configname, itype, name = self.getTypeNameFromSelection() ExperimentActions().experimentActionEvent(configname, actionlabelname, itype, name) self.statusBar.showMessage("Executed " + str(actionlabelname) + " on " + configname) def refreshVMStatus(self): logging.debug("refreshVMStatus(): instantiated") #Get the configname based on selected item: selectedItem = self.experimentTree.currentItem() #Check if an experiment name is selected if selectedItem == None: logging.error("No experiment label was selected.") return #If so, get the configname associated with it while selectedItem.parent() != None: selectedItem = selectedItem.parent() configname = selectedItem.text(0) s = VMRetrievingDialog(self).exec_() self.vms = s["vmstatus"] #Update all vm status in the subtrees #First the "all" view for widget in self.experimentActionsBaseWidgets[configname].values(): if isinstance(widget, ExperimentActionsVMStatusWidget): widget.updateVMStatus(self.vms) #The Sets: for widget in self.experimentActionsBaseWidgets[configname][ "ExperimentActionsSetWidgets"].values(): if isinstance(widget, ExperimentActionsVMStatusWidget): widget.updateVMStatus(self.vms) #The Templates: for widget in self.experimentActionsBaseWidgets[configname][ "ExperimentActionsTemplateWidgets"].values(): if isinstance(widget, ExperimentActionsVMStatusWidget): widget.updateVMStatus(self.vms) #The VMs for widget in self.experimentActionsBaseWidgets[configname][ "ExperimentActionsVMWidgets"].values(): if isinstance(widget, ExperimentActionsVMStatusWidget): widget.updateVMStatus(self.vms) #The Users for widget in self.experimentActionsBaseWidgets[configname][ "ExperimentActionsUserWidgets"].values(): if isinstance(widget, ExperimentActionsVMStatusWidget): widget.updateVMStatus(self.vms)
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.patient_id = '' self.result_list = [] self.title_lb = QPushButton() self.exit_bt = QPushButton() self.logo_bt = QPushButton() self.main_widget = QWidget() self.main_layout = QVBoxLayout() self.left_widget = QWidget() self.left_layout = QGridLayout() self.right_widget = QStackedWidget() self.mid_widget = QWidget() self.mid_layout = QHBoxLayout() self.bottom_layout = QHBoxLayout() self.bottom_widget = QWidget() # self.status_bar = QPushButton() # self.status_bar.set # self.stack1 = QWidget() self.stack_system_intro = SystemIntro() self.stack_border_map_intro = BorderMapIntro() self.stack_datapreprocessUI = DataPreprocessUI() self.stack_clusterUI = ClusterUI() self.stack_load_electrode_picUI = LoadElectrodePic() self.stack_generate_border_mapUI = GenerateBorderMap() self.stack_property_map_intro = PropertyMapIntro() self.stack_load_cortex_pic = LoadCortexPic() self.stack_generate_property_map = GeneratePropertyMap() self.stack_function_map_intro = FunctionMapIntro() self.stack_generate_function_map = GenerateFunctionMap() self.left_close = QPushButton("") # 关闭按钮 self.left_visit = QPushButton("") # 空白按钮 self.left_mini = QPushButton("") # 最小化按钮 self.left_close.setFixedSize(15, 15) # 设置关闭按钮的大小 self.left_visit.setFixedSize(15, 15) # 设置按钮大小 self.left_mini.setFixedSize(15, 15) # 设置最小化按钮大小 self.left_close.setStyleSheet( '''QPushButton{background:#F76677;border-radius:5px;}QPushButton:hover{background:red;}''' ) self.left_visit.setStyleSheet( '''QPushButton{background:#F7D674;border-radius:5px;}QPushButton:hover{background:yellow;}''' ) self.left_mini.setStyleSheet( '''QPushButton{background:#6DDF6D;border-radius:5px;}QPushButton:hover{background:green;}''' ) self.left_label_1 = QPushButton("功能区边界聚类算法") self.left_label_1.clicked.connect(self.show_click_meg) self.left_label_1.clicked.connect(self.on_border_map_bt_clicked) self.left_label_1.setObjectName('left_label') self.left_label_2 = QPushButton("功能区属性分类算法") self.left_label_2.clicked.connect(self.show_click_meg) self.left_label_2.clicked.connect(self.on_property_map_bt_clicked) self.left_label_2.setObjectName('left_label') self.left_label_3 = QPushButton("基于聚类和分类的定位算法") self.left_label_3.clicked.connect(self.show_click_meg) self.left_label_3.clicked.connect(self.on_function_map_bt_clicked) self.left_label_3.setObjectName('left_label') self.left_button_1 = QPushButton( qtawesome.icon('fa.music', color='white'), "导入数据") self.left_button_1.clicked.connect(self.on_load_data_bt_clicked) self.left_button_1.clicked.connect(self.show_click_meg) self.left_button_1.setObjectName('left_button') self.left_button_2 = QPushButton( qtawesome.icon('fa.sellsy', color='white'), "预处理及特征提取") self.left_button_2.clicked.connect(self.on_preprocessing_bt_clicked) self.left_button_2.setObjectName('left_button') self.left_button_2.clicked.connect(self.show_click_meg) self.left_button_3 = QPushButton( qtawesome.icon('fa.film', color='white'), "模型加载与识别") self.left_button_3.clicked.connect(self.on_load_model_bt_clicked) self.left_button_3.setObjectName('left_button') self.left_button_3.clicked.connect(self.show_click_meg) self.left_button_4 = QPushButton( qtawesome.icon('fa.home', color='white '), "导入电极分布图") self.left_button_4.clicked.connect(self.on_load_pic_bt_clicked) self.left_button_4.setObjectName('left_button') self.left_button_4.clicked.connect(self.show_click_meg) self.left_button_5 = QPushButton( qtawesome.icon('fa.download', color='white'), "边界定位图") self.left_button_5.clicked.connect( self.on_generate_border_map_bt_clicked) self.left_button_5.setObjectName('left_button') self.left_button_5.clicked.connect(self.show_click_meg) self.left_button_6 = QPushButton( qtawesome.icon('fa.heart', color='white'), "加载皮质图片") self.left_button_6.clicked.connect(self.on_load_cortex_bt_clicked) self.left_button_6.setObjectName('left_button') self.left_button_6.clicked.connect(self.show_click_meg) self.left_button_7 = QPushButton( qtawesome.icon('fa.comment', color='white'), "属性定位图") self.left_button_7.clicked.connect( self.on_generate_property_map_bt_clicked) self.left_button_7.setObjectName('left_button') self.left_button_7.clicked.connect(self.show_click_meg) self.left_button_8 = QPushButton( qtawesome.icon('fa.star', color='white'), "功能区地形图") self.left_button_8.clicked.connect( self.on_generate_function_map_bt_clicked) self.left_button_8.setObjectName('left_button') self.left_button_8.clicked.connect(self.show_click_meg) self.statusBar = QStatusBar() self.setupUI() self.raw_data = 0 self.data_path = '' self.pic_path = '' self.border_pic_path = None self.feature_sample = None def setupUI(self): self.resize(1000, 800) self.setWindowTitle('基于静息态ECoG聚类和分类的术中脑功能定位系统') self.title_lb.setText('基于静息态ECoG聚类和分类的术中脑功能定位系统') # self.title_lb.setStyleSheet("QLabel{background-color:black; font-size:20px}") self.setStatusBar(self.statusBar) self.statusBar.setStyleSheet("QStatusBar{font-size:15px}") # 调大状态栏的字体 # self.statusBar.setStyleSheet("QStatusBar{background-color:gray; font-size:20px}") # 改状态栏的颜色与背景颜色一致 # self.statusBar.setVisible(True) # 最下面额外增加一栏状态栏 self.statusBar.showMessage('就绪!') self.title_lb.clicked.connect(self.on_title_bt_clicked) self.title_lb.clicked.connect(self.show_click_meg) self.title_lb.setFixedSize(750, 70) self.title_lb.setStyleSheet( 'QPushButton{color:rgb(0, 0, 0, 255);border:none;font-size:30px;font-family: \ "Helvetica Neue", Helvetica, Arial, sans-serif;}\ QPushButton:hover{border-left:4px solid red;font-weight:700;}') self.exit_bt.setText('退出') self.exit_bt.setFixedSize(100, 50) self.exit_bt.setStyleSheet( 'QPushButton{color:rgb(0, 0, 0, 255);border:none;font-size:25px;font-family: \ "Helvetica Neue", Helvetica, Arial, sans-serif;}\ QPushButton:hover{border-left:4px solid red;font-weight:700;}') self.exit_bt.clicked.connect(self.exit_bt_clicked) self.logo_bt.setText('copyright@SCUT-BME-504') self.logo_bt.setFixedSize(300, 30) self.logo_bt.clicked.connect(self.show_click_meg) self.logo_bt.setStyleSheet( 'QPushButton{color:rgb(0, 0, 0, 255);border:none;font-size:15px;font-family: \ "Helvetica Neue", Helvetica, Arial, sans-serif;}\ QPushButton:hover{border-left:4px solid red;font-weight:700;}') # self.bottom_layout.addWidget(self.status_bar, alignment=Qt.AlignLeft) self.bottom_layout.addStretch(2) self.bottom_layout.addWidget(self.logo_bt, alignment=Qt.AlignLeft) self.bottom_layout.addStretch(1) self.bottom_layout.addWidget(self.exit_bt, alignment=Qt.AlignRight) self.bottom_widget.setLayout(self.bottom_layout) self.stack_datapreprocessUI.setStyleSheet( 'QLabel{color:black;font-size:20px;font-family:Arial; \ header:None}') self.main_widget.setLayout(self.main_layout) self.left_widget.setObjectName('left_widget') self.left_widget.setLayout(self.left_layout) self.right_widget.setObjectName('right_widget') self.left_layout.addWidget(self.left_mini, 0, 0, 1, 1) self.left_layout.addWidget(self.left_close, 0, 2, 1, 1) self.left_layout.addWidget(self.left_visit, 0, 1, 1, 1) self.left_layout.addWidget(self.left_label_1, 1, 0, 1, 3) self.left_layout.addWidget(self.left_button_1, 2, 0, 1, 3) self.left_layout.addWidget(self.left_button_2, 3, 0, 1, 3) self.left_layout.addWidget(self.left_button_3, 4, 0, 1, 3) self.left_layout.addWidget(self.left_button_4, 5, 0, 1, 3) self.left_layout.addWidget(self.left_button_5, 6, 0, 1, 3) self.left_layout.addWidget(self.left_label_2, 7, 0, 1, 3) self.left_layout.addWidget(self.left_button_6, 8, 0, 1, 3) self.left_layout.addWidget(self.left_button_7, 9, 0, 1, 3) self.left_layout.addWidget(self.left_label_3, 10, 0, 1, 3) self.left_layout.addWidget(self.left_button_8, 11, 0, 1, 3) # self.left_layout.setSpacing(0) # self.stack = QStackedWidget() self.right_widget.addWidget(self.stack_system_intro) self.right_widget.addWidget(self.stack_border_map_intro) self.right_widget.addWidget(self.stack_datapreprocessUI) self.right_widget.addWidget(self.stack_clusterUI) self.right_widget.addWidget(self.stack_load_electrode_picUI) self.right_widget.addWidget(self.stack_generate_border_mapUI) self.right_widget.addWidget(self.stack_property_map_intro) self.right_widget.addWidget(self.stack_load_cortex_pic) self.right_widget.addWidget(self.stack_generate_property_map) self.right_widget.addWidget(self.stack_function_map_intro) self.right_widget.addWidget(self.stack_generate_function_map) self.mid_layout.addWidget(self.left_widget, stretch=1) self.mid_layout.addWidget(self.right_widget, stretch=3) self.mid_widget.setFixedSize(1000, 650) self.mid_layout.setSpacing(0) self.mid_widget.setLayout(self.mid_layout) self.main_widget.setObjectName('main_widget') self.main_layout.addWidget(self.title_lb, alignment=Qt.AlignCenter, stretch=1) self.main_layout.addWidget(self.mid_widget, stretch=7) self.main_layout.addWidget(self.bottom_widget, stretch=1) self.main_layout.setSpacing(0) # 设置窗口的样式 main_widget_stylesheet = ''' QWidget#main_widget{ background:gray; } QPushButton#left_button{border:none;color:white;} QPushButton#left_label{ border:none; border-bottom:1px solid white; font-size:18px; font-weight:700; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } QWidget#left_widget{ background:grey; border-top:1px solid white; border-bottom:1px solid white; border-left:1px solid white; border-top-left-radius:10px; border-bottom-left-radius:10px; } QWidget#right_widget{ color:#232C51; background:white; border-top:1px solid darkGray; border-bottom:1px solid darkGray; border-right:1px solid darkGray; border-top-right-radius:10px; border-bottom-right-radius:10px; } QPushButton#left_button:hover{border-left:4px solid red;font-weight:700;} QPushButton#left_label:hover{border-left:4px solid red;font-weight:700;} ''' self.main_widget.setStyleSheet(main_widget_stylesheet) self.setCentralWidget(self.main_widget) # 一定要有要句代码,要不然主窗口不显示 self.setWindowOpacity(1) # 设置窗口透明度 # self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口背景透明 加上的话状态栏不显示。 self.right_widget.setCurrentWidget(self.stack_system_intro) # self.setWindowFlag(Qt.FramelessWindowHint) # 隐藏边框 def on_title_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_system_intro) def on_border_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_border_map_intro) def on_load_data_bt_clicked(self): self.stack_datapreprocessUI.status_signal.connect( self.show_process_msg) self.right_widget.setCurrentWidget(self.stack_datapreprocessUI) def on_preprocessing_bt_clicked(self): self.feature_sample = self.stack_datapreprocessUI.feature_extract() self.stack_datapreprocessUI.status_signal.connect( self.show_process_msg) if self.feature_sample: self.right_widget.setCurrentWidget(self.stack_datapreprocessUI) else: if not self.raw_data: QMessageBox.information(self, '消息', '请先加载数据', QMessageBox.Ok) else: self.feature_sample = self.stack_datapreprocessUI.feature_extract( ) def on_load_model_bt_clicked(self): self.stack_clusterUI.get_feature_sample(self.feature_sample) self.stack_clusterUI.status_signal.connect(self.show_process_msg) self.right_widget.setCurrentWidget(self.stack_clusterUI) def on_load_pic_bt_clicked(self): self.pic_path = self.stack_datapreprocessUI.trans_pic_path() self.stack_load_electrode_picUI.get_pic_path(self.pic_path) self.right_widget.setCurrentWidget(self.stack_load_electrode_picUI) def on_generate_border_map_bt_clicked(self): self.stack_generate_border_mapUI.get_pic_path(self.pic_path) self.result_list = self.stack_clusterUI.trans_result_list() self.stack_generate_border_mapUI.get_result_list(self.result_list) self.stack_generate_border_mapUI.status_signal.connect( self.show_process_msg) self.right_widget.setCurrentWidget(self.stack_generate_border_mapUI) def on_property_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_property_map_intro) def on_load_cortex_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_load_cortex_pic) def on_generate_property_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_generate_property_map) def on_function_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_function_map_intro) def on_generate_function_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_generate_function_map) def exit_bt_clicked(self): # sender是发送信号的对象,这里获得的是按钮的名称 sender = self.sender() # 以文本的形式输出按钮的名称 print(sender.text() + ' 被按下了') # 获取QApplication类的对象 q_app = QApplication.instance() # 退出 q_app.quit() def show_click_meg(self): sender = self.sender() self.statusBar.showMessage(sender.text(), 3000) def show_process_msg(self, msg): self.statusBar.showMessage(msg)
class ConfigurationWidget(QWidget): """ Class implementing a dialog for the configuration of eric6. @signal preferencesChanged() emitted after settings have been changed @signal masterPasswordChanged(str, str) emitted after the master password has been changed with the old and the new password @signal accepted() emitted to indicate acceptance of the changes @signal rejected() emitted to indicate rejection of the changes """ preferencesChanged = pyqtSignal() masterPasswordChanged = pyqtSignal(str, str) accepted = pyqtSignal() rejected = pyqtSignal() DefaultMode = 0 HelpBrowserMode = 1 TrayStarterMode = 2 def __init__(self, parent=None, fromEric=True, displayMode=DefaultMode): """ Constructor @param parent The parent widget of this dialog. (QWidget) @keyparam fromEric flag indicating a dialog generation from within the eric6 ide (boolean) @keyparam displayMode mode of the configuration dialog (DefaultMode, HelpBrowserMode, TrayStarterMode) @exception RuntimeError raised to indicate an invalid dialog mode """ assert displayMode in (ConfigurationWidget.DefaultMode, ConfigurationWidget.HelpBrowserMode, ConfigurationWidget.TrayStarterMode) super(ConfigurationWidget, self).__init__(parent) self.fromEric = fromEric self.displayMode = displayMode self.__setupUi() self.itmDict = {} if not fromEric: from PluginManager.PluginManager import PluginManager try: self.pluginManager = e5App().getObject("PluginManager") except KeyError: self.pluginManager = PluginManager(self) e5App().registerObject("PluginManager", self.pluginManager) if displayMode == ConfigurationWidget.DefaultMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function create to # create the configuration page. This must have the method # save to save the settings. "applicationPage": [ self.tr("Application"), "preferences-application.png", "ApplicationPage", None, None ], "cooperationPage": [ self.tr("Cooperation"), "preferences-cooperation.png", "CooperationPage", None, None ], "corbaPage": [ self.tr("CORBA"), "preferences-orbit.png", "CorbaPage", None, None ], "emailPage": [ self.tr("Email"), "preferences-mail_generic.png", "EmailPage", None, None ], "graphicsPage": [ self.tr("Graphics"), "preferences-graphics.png", "GraphicsPage", None, None ], "iconsPage": [ self.tr("Icons"), "preferences-icons.png", "IconsPage", None, None ], "ircPage": [self.tr("IRC"), "irc.png", "IrcPage", None, None], "networkPage": [ self.tr("Network"), "preferences-network.png", "NetworkPage", None, None ], "notificationsPage": [ self.tr("Notifications"), "preferences-notifications.png", "NotificationsPage", None, None ], "pluginManagerPage": [ self.tr("Plugin Manager"), "preferences-pluginmanager.png", "PluginManagerPage", None, None ], "printerPage": [ self.tr("Printer"), "preferences-printer.png", "PrinterPage", None, None ], "pythonPage": [ self.tr("Python"), "preferences-python.png", "PythonPage", None, None ], "qtPage": [ self.tr("Qt"), "preferences-qtlogo.png", "QtPage", None, None ], "securityPage": [ self.tr("Security"), "preferences-security.png", "SecurityPage", None, None ], "shellPage": [ self.tr("Shell"), "preferences-shell.png", "ShellPage", None, None ], "tasksPage": [self.tr("Tasks"), "task.png", "TasksPage", None, None], "templatesPage": [ self.tr("Templates"), "preferences-template.png", "TemplatesPage", None, None ], "trayStarterPage": [ self.tr("Tray Starter"), "erict.png", "TrayStarterPage", None, None ], "vcsPage": [ self.tr("Version Control Systems"), "preferences-vcs.png", "VcsPage", None, None ], "0debuggerPage": [ self.tr("Debugger"), "preferences-debugger.png", None, None, None ], "debuggerGeneralPage": [ self.tr("General"), "preferences-debugger.png", "DebuggerGeneralPage", "0debuggerPage", None ], "debuggerPythonPage": [ self.tr("Python"), "preferences-pyDebugger.png", "DebuggerPythonPage", "0debuggerPage", None ], "debuggerPython3Page": [ self.tr("Python3"), "preferences-pyDebugger.png", "DebuggerPython3Page", "0debuggerPage", None ], "debuggerRubyPage": [ self.tr("Ruby"), "preferences-rbDebugger.png", "DebuggerRubyPage", "0debuggerPage", None ], "0editorPage": [ self.tr("Editor"), "preferences-editor.png", None, None, None ], "editorAPIsPage": [ self.tr("APIs"), "preferences-api.png", "EditorAPIsPage", "0editorPage", None ], "editorAutocompletionPage": [ self.tr("Autocompletion"), "preferences-autocompletion.png", "EditorAutocompletionPage", "0editorPage", None ], "editorAutocompletionQScintillaPage": [ self.tr("QScintilla"), "qscintilla.png", "EditorAutocompletionQScintillaPage", "editorAutocompletionPage", None ], "editorCalltipsPage": [ self.tr("Calltips"), "preferences-calltips.png", "EditorCalltipsPage", "0editorPage", None ], "editorCalltipsQScintillaPage": [ self.tr("QScintilla"), "qscintilla.png", "EditorCalltipsQScintillaPage", "editorCalltipsPage", None ], "editorGeneralPage": [ self.tr("General"), "preferences-general.png", "EditorGeneralPage", "0editorPage", None ], "editorFilePage": [ self.tr("Filehandling"), "preferences-filehandling.png", "EditorFilePage", "0editorPage", None ], "editorSearchPage": [ self.tr("Searching"), "preferences-search.png", "EditorSearchPage", "0editorPage", None ], "editorSpellCheckingPage": [ self.tr("Spell checking"), "preferences-spellchecking.png", "EditorSpellCheckingPage", "0editorPage", None ], "editorStylesPage": [ self.tr("Style"), "preferences-styles.png", "EditorStylesPage", "0editorPage", None ], "editorSyntaxPage": [ self.tr("Code Checkers"), "preferences-debugger.png", "EditorSyntaxPage", "0editorPage", None ], "editorTypingPage": [ self.tr("Typing"), "preferences-typing.png", "EditorTypingPage", "0editorPage", None ], "editorExportersPage": [ self.tr("Exporters"), "preferences-exporters.png", "EditorExportersPage", "0editorPage", None ], "1editorLexerPage": [ self.tr("Highlighters"), "preferences-highlighting-styles.png", None, "0editorPage", None ], "editorHighlightersPage": [ self.tr("Filetype Associations"), "preferences-highlighter-association.png", "EditorHighlightersPage", "1editorLexerPage", None ], "editorHighlightingStylesPage": [ self.tr("Styles"), "preferences-highlighting-styles.png", "EditorHighlightingStylesPage", "1editorLexerPage", None ], "editorKeywordsPage": [ self.tr("Keywords"), "preferences-keywords.png", "EditorKeywordsPage", "1editorLexerPage", None ], "editorPropertiesPage": [ self.tr("Properties"), "preferences-properties.png", "EditorPropertiesPage", "1editorLexerPage", None ], "0helpPage": [self.tr("Help"), "preferences-help.png", None, None, None], "helpAppearancePage": [ self.tr("Appearance"), "preferences-styles.png", "HelpAppearancePage", "0helpPage", None ], "helpDocumentationPage": [ self.tr("Help Documentation"), "preferences-helpdocumentation.png", "HelpDocumentationPage", "0helpPage", None ], "helpViewersPage": [ self.tr("Help Viewers"), "preferences-helpviewers.png", "HelpViewersPage", "0helpPage", None ], "helpWebBrowserPage": [ self.tr("eric6 Web Browser"), "ericWeb.png", "HelpWebBrowserPage", "0helpPage", None ], "0projectPage": [ self.tr("Project"), "preferences-project.png", None, None, None ], "projectBrowserPage": [ self.tr("Project Viewer"), "preferences-project.png", "ProjectBrowserPage", "0projectPage", None ], "projectPage": [ self.tr("Project"), "preferences-project.png", "ProjectPage", "0projectPage", None ], "multiProjectPage": [ self.tr("Multiproject"), "preferences-multiproject.png", "MultiProjectPage", "0projectPage", None ], "0interfacePage": [ self.tr("Interface"), "preferences-interface.png", None, None, None ], "interfacePage": [ self.tr("Interface"), "preferences-interface.png", "InterfacePage", "0interfacePage", None ], "viewmanagerPage": [ self.tr("Viewmanager"), "preferences-viewmanager.png", "ViewmanagerPage", "0interfacePage", None ], } self.configItems.update( e5App().getObject("PluginManager").getPluginConfigData()) elif displayMode == ConfigurationWidget.HelpBrowserMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function create to # create the configuration page. This must have the method # save to save the settings. "interfacePage": [ self.tr("Interface"), "preferences-interface.png", "HelpInterfacePage", None, None ], "networkPage": [ self.tr("Network"), "preferences-network.png", "NetworkPage", None, None ], "printerPage": [ self.tr("Printer"), "preferences-printer.png", "PrinterPage", None, None ], "securityPage": [ self.tr("Security"), "preferences-security.png", "SecurityPage", None, None ], "0helpPage": [self.tr("Help"), "preferences-help.png", None, None, None], "helpAppearancePage": [ self.tr("Appearance"), "preferences-styles.png", "HelpAppearancePage", "0helpPage", None ], "helpDocumentationPage": [ self.tr("Help Documentation"), "preferences-helpdocumentation.png", "HelpDocumentationPage", "0helpPage", None ], "helpWebBrowserPage": [ self.tr("eric6 Web Browser"), "ericWeb.png", "HelpWebBrowserPage", "0helpPage", None ], } elif displayMode == ConfigurationWidget.TrayStarterMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function create to # create the configuration page. This must have the method # save to save the settings. "trayStarterPage": [ self.tr("Tray Starter"), "erict.png", "TrayStarterPage", None, None ], } else: raise RuntimeError("Illegal mode value: {0}".format(displayMode)) # generate the list entries for key in sorted(self.configItems.keys()): pageData = self.configItems[key] if pageData[3]: pitm = self.itmDict[pageData[3]] # get the parent item else: pitm = self.configList self.itmDict[key] = ConfigurationPageItem(pitm, pageData[0], key, pageData[1]) self.itmDict[key].setData(0, Qt.UserRole, key) self.itmDict[key].setExpanded(True) self.configList.sortByColumn(0, Qt.AscendingOrder) # set the initial size of the splitter self.configSplitter.setSizes([200, 600]) self.configList.itemActivated.connect(self.__showConfigurationPage) self.configList.itemClicked.connect(self.__showConfigurationPage) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.rejected) if displayMode != ConfigurationWidget.TrayStarterMode: self.__initLexers() def accept(self): """ Public slot to accept the buttonBox accept signal. """ if not isMacPlatform(): wdg = self.focusWidget() if wdg == self.configList: return self.accepted.emit() def __setupUi(self): """ Private method to perform the general setup of the configuration widget. """ self.setObjectName("ConfigurationDialog") self.resize(900, 650) self.verticalLayout_2 = QVBoxLayout(self) self.verticalLayout_2.setSpacing(6) self.verticalLayout_2.setContentsMargins(6, 6, 6, 6) self.verticalLayout_2.setObjectName("verticalLayout_2") self.configSplitter = QSplitter(self) self.configSplitter.setOrientation(Qt.Horizontal) self.configSplitter.setObjectName("configSplitter") self.configListWidget = QWidget(self.configSplitter) self.leftVBoxLayout = QVBoxLayout(self.configListWidget) self.leftVBoxLayout.setContentsMargins(0, 0, 0, 0) self.leftVBoxLayout.setSpacing(0) self.leftVBoxLayout.setObjectName("leftVBoxLayout") self.configListFilter = E5ClearableLineEdit( self, self.tr("Enter filter text...")) self.configListFilter.setObjectName("configListFilter") self.leftVBoxLayout.addWidget(self.configListFilter) self.configList = QTreeWidget() self.configList.setObjectName("configList") self.leftVBoxLayout.addWidget(self.configList) self.configListFilter.textChanged.connect(self.__filterTextChanged) self.scrollArea = QScrollArea(self.configSplitter) self.scrollArea.setFrameShape(QFrame.NoFrame) self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scrollArea.setWidgetResizable(False) self.scrollArea.setObjectName("scrollArea") self.configStack = QStackedWidget() self.configStack.setFrameShape(QFrame.Box) self.configStack.setFrameShadow(QFrame.Sunken) self.configStack.setObjectName("configStack") self.scrollArea.setWidget(self.configStack) self.emptyPage = QWidget() self.emptyPage.setGeometry(QRect(0, 0, 372, 591)) self.emptyPage.setObjectName("emptyPage") self.vboxlayout = QVBoxLayout(self.emptyPage) self.vboxlayout.setSpacing(6) self.vboxlayout.setContentsMargins(6, 6, 6, 6) self.vboxlayout.setObjectName("vboxlayout") spacerItem = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.vboxlayout.addItem(spacerItem) self.emptyPagePixmap = QLabel(self.emptyPage) self.emptyPagePixmap.setAlignment(Qt.AlignCenter) self.emptyPagePixmap.setObjectName("emptyPagePixmap") self.emptyPagePixmap.setPixmap( QPixmap(os.path.join(getConfig('ericPixDir'), 'eric.png'))) self.vboxlayout.addWidget(self.emptyPagePixmap) self.textLabel1 = QLabel(self.emptyPage) self.textLabel1.setAlignment(Qt.AlignCenter) self.textLabel1.setObjectName("textLabel1") self.vboxlayout.addWidget(self.textLabel1) spacerItem1 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.vboxlayout.addItem(spacerItem1) self.configStack.addWidget(self.emptyPage) self.verticalLayout_2.addWidget(self.configSplitter) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Apply | QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.Reset) self.buttonBox.setObjectName("buttonBox") if not self.fromEric and \ self.displayMode == ConfigurationWidget.DefaultMode: self.buttonBox.button(QDialogButtonBox.Apply).hide() self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False) self.verticalLayout_2.addWidget(self.buttonBox) self.setWindowTitle(self.tr("Preferences")) self.configList.header().hide() self.configList.header().setSortIndicator(0, Qt.AscendingOrder) self.configList.setSortingEnabled(True) self.textLabel1.setText( self.tr("Please select an entry of the list \n" "to display the configuration page.")) QMetaObject.connectSlotsByName(self) self.setTabOrder(self.configList, self.configStack) self.configStack.setCurrentWidget(self.emptyPage) self.configList.setFocus() def __filterTextChanged(self, filter): """ Private slot to handle a change of the filter. @param filter text of the filter line edit (string) """ self.__filterChildItems(self.configList.invisibleRootItem(), filter) def __filterChildItems(self, parent, filter): """ Private method to filter child items based on a filter string. @param parent reference to the parent item (QTreeWidgetItem) @param filter filter string (string) @return flag indicating a visible child item (boolean) """ childVisible = False filter = filter.lower() for index in range(parent.childCount()): itm = parent.child(index) if itm.childCount() > 0: visible = self.__filterChildItems(itm, filter) or \ filter == "" or filter in itm.text(0).lower() else: visible = filter == "" or filter in itm.text(0).lower() if visible: childVisible = True itm.setHidden(not visible) return childVisible def __initLexers(self): """ Private method to initialize the dictionary of preferences lexers. """ import QScintilla.Lexers from .PreferencesLexer import PreferencesLexer, \ PreferencesLexerLanguageError self.lexers = {} for language in QScintilla.Lexers.getSupportedLanguages(): if language not in self.lexers: try: self.lexers[language] = PreferencesLexer(language, self) except PreferencesLexerLanguageError: pass def __importConfigurationPage(self, name): """ Private method to import a configuration page module. @param name name of the configuration page module (string) @return reference to the configuration page module """ modName = "Preferences.ConfigurationPages.{0}".format(name) try: mod = __import__(modName) components = modName.split('.') for comp in components[1:]: mod = getattr(mod, comp) return mod except ImportError: E5MessageBox.critical( self, self.tr("Configuration Page Error"), self.tr("""<p>The configuration page <b>{0}</b>""" """ could not be loaded.</p>""").format(name)) return None def __showConfigurationPage(self, itm, column): """ Private slot to show a selected configuration page. @param itm reference to the selected item (QTreeWidgetItem) @param column column that was selected (integer) (ignored) """ pageName = itm.getPageName() self.showConfigurationPageByName(pageName, setCurrent=False) def __initPage(self, pageData): """ Private method to initialize a configuration page. @param pageData data structure for the page to initialize @return reference to the initialized page """ page = None if isinstance(pageData[2], types.FunctionType): page = pageData[2](self) else: mod = self.__importConfigurationPage(pageData[2]) if mod: page = mod.create(self) if page is not None: self.configStack.addWidget(page) pageData[-1] = page try: page.setMode(self.displayMode) except AttributeError: pass return page def showConfigurationPageByName(self, pageName, setCurrent=True): """ Public slot to show a named configuration page. @param pageName name of the configuration page to show (string) @param setCurrent flag indicating to set the current item (boolean) """ if pageName == "empty" or pageName not in self.configItems: page = self.emptyPage else: pageData = self.configItems[pageName] if pageData[-1] is None and pageData[2] is not None: # the page was not loaded yet, create it page = self.__initPage(pageData) else: page = pageData[-1] if page is None: page = self.emptyPage elif setCurrent: items = self.configList.findItems( pageData[0], Qt.MatchFixedString | Qt.MatchRecursive) for item in items: if item.data(0, Qt.UserRole) == pageName: self.configList.setCurrentItem(item) self.configStack.setCurrentWidget(page) ssize = self.scrollArea.size() if self.scrollArea.horizontalScrollBar(): ssize.setHeight(ssize.height() - self.scrollArea.horizontalScrollBar().height() - 2) if self.scrollArea.verticalScrollBar(): ssize.setWidth(ssize.width() - self.scrollArea.verticalScrollBar().width() - 2) psize = page.minimumSizeHint() self.configStack.resize(max(ssize.width(), psize.width()), max(ssize.height(), psize.height())) if page != self.emptyPage: page.polishPage() self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(True) else: self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False) # reset scrollbars for sb in [ self.scrollArea.horizontalScrollBar(), self.scrollArea.verticalScrollBar() ]: if sb: sb.setValue(0) self.__currentConfigurationPageName = pageName def getConfigurationPageName(self): """ Public method to get the page name of the current page. @return page name of the current page (string) """ return self.__currentConfigurationPageName def calledFromEric(self): """ Public method to check, if invoked from within eric. @return flag indicating invocation from within eric (boolean) """ return self.fromEric def getPage(self, pageName): """ Public method to get a reference to the named page. @param pageName name of the configuration page (string) @return reference to the page or None, indicating page was not loaded yet """ return self.configItems[pageName][-1] def getLexers(self): """ Public method to get a reference to the lexers dictionary. @return reference to the lexers dictionary """ return self.lexers def setPreferences(self): """ Public method called to store the selected values into the preferences storage. """ for key, pageData in list(self.configItems.items()): if pageData[-1]: pageData[-1].save() # page was loaded (and possibly modified) QApplication.processEvents() # ensure HMI is responsive def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. @param button button that was clicked (QAbstractButton) """ if button == self.buttonBox.button(QDialogButtonBox.Apply): self.on_applyButton_clicked() elif button == self.buttonBox.button(QDialogButtonBox.Reset): self.on_resetButton_clicked() @pyqtSlot() def on_applyButton_clicked(self): """ Private slot called to apply the settings of the current page. """ if self.configStack.currentWidget() != self.emptyPage: page = self.configStack.currentWidget() savedState = page.saveState() page.save() self.preferencesChanged.emit() if savedState is not None: page.setState(savedState) @pyqtSlot() def on_resetButton_clicked(self): """ Private slot called to reset the settings of the current page. """ if self.configStack.currentWidget() != self.emptyPage: currentPage = self.configStack.currentWidget() savedState = currentPage.saveState() pageName = self.configList.currentItem().getPageName() self.configStack.removeWidget(currentPage) if pageName == "editorHighlightingStylesPage": self.__initLexers() self.configItems[pageName][-1] = None self.showConfigurationPageByName(pageName) if savedState is not None: self.configStack.currentWidget().setState(savedState)
class AppManager(metaclass=Singleton): APP_NAME = 'Lang tutor' WIDGETS = [ main_widget, scenario_widget, editor_widget ] MSB_TYPE = { MsgType.INFO: QMessageBox.information, MsgType.WARN: QMessageBox.warning, } def __init__(self): init_locale() self.translator = Translator.get_translator('main') self.__init_main_window() self.__init_widgets() self.__init_event_handlers() def __init_main_window(self): self.main_window = QMainWindow() self.main_window.resize(1024, 768) self.main_window.setWindowTitle(self.APP_NAME) font = QFont() font.setFamily("Calibri") font.setPointSize(12) font.setBold(False) font.setWeight(50) self.main_window.setFont(font) self.centralwidget = QWidget(self.main_window) self.centralwidget.setMinimumSize(QSize(1024, 768)) grid = QGridLayout(self.centralwidget) self.mainStackWidget = QStackedWidget(self.centralwidget) self.mainStackWidget.setObjectName("mainStackWidget") grid.addWidget(self.mainStackWidget, 0, 0, 1, 1) grid.setColumnMinimumWidth(0, 200) self.main_window.setCentralWidget(self.centralwidget) def __init_widgets(self): for wid in self.WIDGETS: self.mainStackWidget.addWidget(wid.init()) def __init_event_handlers(self): CrossWidgetEvents.change_screen_event += self.select_active_widget CrossWidgetEvents.show_message_event += self.show_info_msb CrossWidgetEvents.show_question_event += self.show_question_msb CrossWidgetEvents.clsoe_main_window_event += self.main_window.close def get_main_window(self): return self.main_window def select_active_widget(self, wid_id): self.mainStackWidget.setCurrentIndex(wid_id) def show_info_msb(self, t, title, message): if t not in self.MSB_TYPE.keys(): t = MsgType.INFO self.MSB_TYPE[t](self.main_window, title, message) def __init_quest_msb(self): quest_msb = QMessageBox() quest_msb.setIcon(QMessageBox.Question) quest_msb.setStandardButtons(QMessageBox.Yes | QMessageBox.No) yes_btn = quest_msb.button(QMessageBox.Yes) yes_btn.setText(self.translator.translate('YES_ANSWER')) no_btn = quest_msb.button(QMessageBox.No) no_btn.setText(self.translator.translate('NO_ANSWER')) return quest_msb def show_question_msb(self, title, message, yes_action): quest_msb = self.__init_quest_msb() quest_msb.setWindowTitle(title) quest_msb.setText(message) answer = quest_msb.exec() if answer == QMessageBox.Yes: yes_action()
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) # window = QMainWindow() # window.resize(800, 600) # self.centralwidget = QtWidgets.QWidget(MainWindow) # self.centralwidget = QtWidgets.QWidget(MainWindow) self.stack = QStackedWidget(parent=MainWindow) self.centralwidget = QStackedWidget(parent=MainWindow) self.centralwidget.setObjectName("centralwidget") # self.matplotlibwidget_static = MatplotlibWidget(self.centralwidget) matplotlibwidget_static = MatplotlibWidget() matplotlibwidget_static.setGeometry(QtCore.QRect(10, 0, 611, 271)) matplotlibwidget_static.setObjectName("matplotlibwidget_static") self.stack.addWidget(matplotlibwidget_static) self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(670, 80, 75, 23)) self.pushButton.setObjectName("pushButton") # self.matplotlibwidget_dynamic = MatplotlibWidget() # self.matplotlibwidget_dynamic.setEnabled(True) # self.matplotlibwidget_dynamic.setGeometry(QtCore.QRect(10, 270, 611, 291)) # self.matplotlibwidget_dynamic.setObjectName("matplotlibwidget_dynamic") matplotlibwidget_dynamic = MatplotlibWidget() matplotlibwidget_dynamic.setEnabled(True) matplotlibwidget_dynamic.setGeometry(QtCore.QRect(10, 0, 611, 271)) matplotlibwidget_dynamic.setObjectName("matplotlibwidget_dynamic") self.stack.addWidget(matplotlibwidget_dynamic) self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_2.setGeometry(QtCore.QRect(670, 370, 75, 23)) self.pushButton_2.setObjectName("pushButton_2") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.stack.show() # window.show() def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushButton.setText(_translate("MainWindow", "显示静态图")) self.pushButton_2.setText(_translate("MainWindow", "显示动态图")) def next(self): self.stack.setCurrentIndex(self.stack.currentIndex() + 1) print('current', self.stack.currentIndex())
class FraudFrame(QDialog): version = 'Fraud Detect Tool 1.0.0' def __init__(self, parent=None): super(FraudFrame, self).__init__(parent) self.contentsWidget = QListWidget() self.contentsWidget.setViewMode(QListView.IconMode) self.contentsWidget.setIconSize(QSize(120, 110)) self.contentsWidget.setMovement(QListView.Static) self.contentsWidget.setMaximumWidth(130) self.contentsWidget.setSpacing(10) self.contentsWidget.setObjectName('left_widget') self.pagesWidget = QStackedWidget() self.pagesWidget.addWidget(NPoPage()) self.pagesWidget.addWidget(NPoPage()) self.pagesWidget.addWidget(NPoPage()) self.pagesWidget.addWidget(SettingPage()) self.pagesWidget.addWidget(InformationPage()) self.pagesWidget.setObjectName('left_widget') self.logoLabel() vLayout = QVBoxLayout() vWidget = QWidget() vWidget.setObjectName('vWidget') vLayout.addWidget(self.left_label_1) vLayout.addWidget(self.contentsWidget) vWidget.setLayout(vLayout) horizontalLayout = QHBoxLayout() horizontalLayout.addWidget(vWidget) horizontalLayout.addWidget(self.pagesWidget, 1) mainLayout = QVBoxLayout() mainLayout.addLayout(horizontalLayout) mainLayout.addStretch(1) mainLayout.addSpacing(1) self.setStyleBetter() self.setLayout(mainLayout) self.createIcons() self.setWindowTitle(self.version) self.setWindowFlags(Qt.WindowMinimizeButtonHint) def changePage(self, current, previous): if not current: current = previous self.pagesWidget.setCurrentIndex(self.contentsWidget.row(current)) def logoLabel(self): # # LOGO logo_jpg = QPixmap("logo.png") self.left_label_1 = QLabel(self) self.left_label_1.setObjectName('logo') self.left_label_1.setPixmap(logo_jpg) self.left_label_1.setAlignment(Qt.AlignCenter) def createIcons(self): poButton = QListWidgetItem(self.contentsWidget) # poButton.setIcon(QIcon('PO.jpg')) poButton.setIcon(QIcon('PO.png')) poButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) nPoButton = QListWidgetItem(self.contentsWidget) nPoButton.setIcon(QIcon('NPO.png')) nPoButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) moreButton = QListWidgetItem(self.contentsWidget) moreButton.setIcon(QIcon('MORE.png')) moreButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) moreButton.setToolTip('这是MORE按钮') settingButton = QListWidgetItem(self.contentsWidget) settingButton.setIcon(QIcon('Setting.png')) settingButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) settingButton.setToolTip('这是设定按钮') informationButton = QListWidgetItem(self.contentsWidget) informationButton.setIcon(QIcon('information.png')) informationButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) informationButton.setToolTip('这是工具信息按钮') # 为contentsWidget界面切换添加changePage响应 self.contentsWidget.currentItemChanged.connect(self.changePage) def setStyleBetter(self): """ @todo border: 2px outset red :return: """ # set style self.setStyleSheet(""" QWidget{ background:#15191C; } """)
class MainApp(QWidget): def __init__(self, parent=None): logging.debug("MainApp:init() instantiated") super().__init__() self.baseWidgets = {} self.vmWidgets = {} self.materialWidgets = {} self.cf = SystemConfigIO() self.ec = ExperimentConfigIO.getInstance() self.statusBar = QStatusBar() self.setMinimumSize(670, 565) quit = QAction("Quit", self) quit.triggered.connect(self.closeEvent) self.setWindowTitle("ARL South RES v0.1") self.tabWidget = QtWidgets.QTabWidget() self.tabWidget.setGeometry(QtCore.QRect(0, 15, 668, 565)) self.tabWidget.setObjectName("tabWidget") # Configuration Window (windowBox) contains: ## windowBoxHLayout contains: ###experimentTree (Left) ###basedataStackedWidget (Right) self.windowWidget = QtWidgets.QWidget() self.windowWidget.setObjectName("windowWidget") self.windowBoxHLayout = QtWidgets.QHBoxLayout() #self.windowBoxHLayout.setContentsMargins(0, 0, 0, 0) self.windowBoxHLayout.setObjectName("windowBoxHLayout") self.windowWidget.setLayout(self.windowBoxHLayout) self.experimentTree = QtWidgets.QTreeWidget() self.experimentTree.itemSelectionChanged.connect(self.onItemSelected) self.experimentTree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.experimentTree.customContextMenuRequested.connect( self.showContextMenu) self.experimentTree.setEnabled(True) self.experimentTree.setMinimumSize(200, 521) self.experimentTree.setMaximumWidth(350) self.experimentTree.setObjectName("experimentTree") self.experimentTree.headerItem().setText(0, "Experiments") self.experimentTree.setSortingEnabled(False) self.windowBoxHLayout.addWidget(self.experimentTree) self.basedataStackedWidget = QStackedWidget() self.basedataStackedWidget.setObjectName("basedataStackedWidget") self.basedataStackedWidget.setEnabled(False) self.windowBoxHLayout.addWidget(self.basedataStackedWidget) self.tabWidget.addTab(self.windowWidget, "Configuration") # VBox Actions Tab self.experimentActionsWidget = ExperimentActionsWidget( statusBar=self.statusBar) self.experimentActionsWidget.setObjectName("experimentActionsWidget") self.tabWidget.addTab(self.experimentActionsWidget, "Experiment Actions") # Remote Connections Tab self.connectionWidget = ConnectionWidget(statusBar=self.statusBar) self.connectionWidget.setObjectName("connectionsWidget") self.tabWidget.addTab(self.connectionWidget, "Remote Connections") #Create the bottom layout so that we can access the status bar self.bottomLayout = QHBoxLayout() self.statusBar.showMessage("Loading GUI...") self.bottomLayout.addWidget(self.statusBar) self.saveButton = QtWidgets.QPushButton("Save Current") self.saveButton.clicked.connect(self.saveExperimentButton) self.saveButton.setEnabled(False) self.bottomLayout.addWidget(self.saveButton) self.populateUi() self.setupContextMenus() self.initMenu() self.mainLayout = QVBoxLayout() self.mainLayout.addWidget(self.mainMenu) self.mainLayout.addWidget(self.tabWidget) self.mainLayout.addLayout(self.bottomLayout) self.setLayout(self.mainLayout) #self.setCentralWidget(self.outerBox) self.tabWidget.setCurrentIndex(0) #self.statusBar.showMessage("Finished Loading GUI Components") # Plugin Section self.tabWidget.addTab(CTFi2GUI(), "CTFi2") def readSystemConfig(self): logging.debug("MainApp:readSystemConfig() instantiated") self.vboxPath = self.cf.getConfig()['VBOX']['VMANAGE_PATH'] self.experimentPath = self.cf.getConfig( )['EXPERIMENTS']['EXPERIMENTS_PATH'] self.statusBar.showMessage("Finished reading system config") def setupContextMenus(self): logging.debug("MainApp:setupContextMenus() instantiated") # Context menu for blank space self.blankTreeContextMenu = QtWidgets.QMenu() self.addExperiment = self.blankTreeContextMenu.addAction( "New Experiment") self.addExperiment.triggered.connect(self.addExperimentActionEvent) self.importExperiment = self.blankTreeContextMenu.addAction( "Import Experiment from RES archive") self.importExperiment.triggered.connect(self.importActionEvent) # Experiment context menu self.experimentContextMenu = QtWidgets.QMenu() self.addVMContextSubMenu = QtWidgets.QMenu() self.experimentContextMenu.addMenu(self.addVMContextSubMenu) self.addVMContextSubMenu.setTitle("Add") self.addVM = self.addVMContextSubMenu.addAction("Virtual Machines") self.addVM.triggered.connect(self.addVMActionEvent) self.addMaterial = self.addVMContextSubMenu.addAction("Material Files") self.addMaterial.triggered.connect(self.addMaterialActionEvent) # Add line separator here self.removeExperiment = self.experimentContextMenu.addAction( "Remove Experiment") self.removeExperiment.triggered.connect( self.removeExperimentItemActionEvent) self.exportExperiment = self.experimentContextMenu.addAction( "Export Experiment") self.exportExperiment.triggered.connect(self.exportActionEvent) # VM/Material context menu self.itemContextMenu = QtWidgets.QMenu() self.removeItem = self.itemContextMenu.addAction( "Remove Experiment Item") self.removeItem.triggered.connect(self.removeExperimentItemActionEvent) def populateUi(self): logging.debug("MainApp:populateUi() instantiated") self.statusBar.showMessage("Populating UI") self.readSystemConfig() #####Create the following based on the config file result = self.ec.getExperimentXMLFilenames() if result == None: return [xmlExperimentFilenames, xmlExperimentNames] = result if xmlExperimentFilenames == [] or xmlExperimentNames == []: self.statusBar.showMessage("No configs found") return #For all experiment files found for configname in xmlExperimentNames: ####Read Experiment Config Data and Populate Tree self.loadConfigname(configname) self.statusBar.showMessage( "Completed populating the User Interface from " + str(len(xmlExperimentNames)) + " config files read", 6000) ############################### def loadConfigname(self, configname): logging.debug("MainApp(): loadConfigname instantiated") logging.info("Reading XML data for " + str(configname)) jsondata = self.ec.getExperimentXMLFileData(configname) self.statusBar.showMessage("Finished reading experiment config") ##########testbed-setup data###### if jsondata == None: jsondata = {} if "xml" not in jsondata or jsondata["xml"] == None or str( jsondata["xml"]).strip() == "": jsondata["xml"] = {} if "testbed-setup" not in jsondata["xml"]: jsondata["xml"]["testbed-setup"] = {} if "vm-set" not in jsondata["xml"]["testbed-setup"]: jsondata["xml"]["testbed-setup"]["vm-set"] = {} #Temporary fix for older xml/json files. if "users-filename" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["users-filename"] = "" if "rdp-broker-ip" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["rdp-broker-ip"] = "" if "chat-server-ip" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["chat-server-ip"] = "" configTreeWidgetItem = QtWidgets.QTreeWidgetItem(self.experimentTree) configTreeWidgetItem.setText(0, configname) self.experimentActionsWidget.addExperimentItem( configname, config_jsondata=jsondata) self.connectionWidget.addExperimentItem(configname, config_jsondata=jsondata) basejsondata = jsondata["xml"] # Base Config Widget self.baseWidget = BaseWidget(self, configname, configname, basejsondata) self.baseWidgets[configname] = { "BaseWidget": {}, "VMWidgets": {}, "MaterialWidgets": {} } self.baseWidgets[configname]["BaseWidget"] = self.baseWidget self.basedataStackedWidget.addWidget(self.baseWidget) ##########vm data###### if "vm" in jsondata["xml"]["testbed-setup"]["vm-set"]: vmsjsondata = jsondata["xml"]["testbed-setup"]["vm-set"]["vm"] if isinstance(vmsjsondata, list): for vm in vmsjsondata: vm_item = QtWidgets.QTreeWidgetItem(configTreeWidgetItem) vmlabel = "V: " + vm["name"] vm_item.setText(0, vmlabel) # VM Config Widget vmWidget = VMWidget(None, configname, vm["name"], vm) self.baseWidgets[configname]["VMWidgets"][ vmlabel] = vmWidget self.basedataStackedWidget.addWidget(vmWidget) else: vm_item = QtWidgets.QTreeWidgetItem(configTreeWidgetItem) vmlabel = "V: " + vmsjsondata["name"] vm_item.setText(0, vmlabel) # VM Config Widget vmWidget = VMWidget(None, configname, vmsjsondata["name"], vmsjsondata) self.baseWidgets[configname]["VMWidgets"][vmlabel] = vmWidget self.basedataStackedWidget.addWidget(vmWidget) ##########material data###### if "material" in jsondata["xml"]["testbed-setup"]["vm-set"]: materialsjsondata = jsondata["xml"]["testbed-setup"]["vm-set"][ "material"] if isinstance(materialsjsondata, list): for material in materialsjsondata: material_item = QtWidgets.QTreeWidgetItem( configTreeWidgetItem) materiallabel = "M: " + material["name"] material_item.setText(0, materiallabel) # Material Config Widget materialWidget = MaterialWidget(None, configname, material["name"], material) self.baseWidgets[configname]["MaterialWidgets"][ materiallabel] = materialWidget self.basedataStackedWidget.addWidget(materialWidget) else: material_item = QtWidgets.QTreeWidgetItem(configTreeWidgetItem) materiallabel = "M: " + materialsjsondata["name"] material_item.setText(0, materiallabel) # Material Config Widget materialWidget = MaterialWidget(None, configname, materialsjsondata["name"], materialsjsondata) self.baseWidgets[configname]["MaterialWidgets"][ materiallabel] = materialWidget self.basedataStackedWidget.addWidget(materialWidget) logging.debug("MainApp(): Finished loading configname: " + str(configname)) def onItemSelected(self): logging.debug("MainApp:onItemSelected instantiated") # Get the selected item selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:onItemSelected no configurations left") self.statusBar.showMessage( "No configuration items selected or available.") return self.basedataStackedWidget.setEnabled(True) # Now enable the save button self.saveButton.setEnabled(True) self.saveExperimentMenuButton.setEnabled(True) #Check if it's the case that an experiment name was selected parentSelectedItem = selectedItem.parent() if (parentSelectedItem == None): #A base widget was selected self.basedataStackedWidget.setCurrentWidget( self.baseWidgets[selectedItem.text(0)]["BaseWidget"]) else: #Check if it's the case that a VM Name was selected if (selectedItem.text(0)[0] == "V"): logging.debug("Setting right widget: " + str(self.baseWidgets[parentSelectedItem.text(0)] ["VMWidgets"][selectedItem.text(0)])) self.basedataStackedWidget.setCurrentWidget( self.baseWidgets[parentSelectedItem.text(0)]["VMWidgets"][ selectedItem.text(0)]) #Check if it's the case that a Material Name was selected elif (selectedItem.text(0)[0] == "M"): logging.debug("Setting right widget: " + str(self.baseWidgets[parentSelectedItem.text(0)] ["MaterialWidgets"][selectedItem.text(0)])) self.basedataStackedWidget.setCurrentWidget( self.baseWidgets[parentSelectedItem.text( 0)]["MaterialWidgets"][selectedItem.text(0)]) def showContextMenu(self, position): logging.debug("MainApp:showContextMenu() instantiated: " + str(position)) if (self.experimentTree.itemAt(position) == None): self.blankTreeContextMenu.popup( self.experimentTree.mapToGlobal(position)) elif (self.experimentTree.itemAt(position).parent() == None): self.experimentContextMenu.popup( self.experimentTree.mapToGlobal(position)) else: self.itemContextMenu.popup( self.experimentTree.mapToGlobal(position)) def addExperimentActionEvent(self): logging.debug("MainApp:addExperimentActionEvent() instantiated") configname = ExperimentAddDialog().experimentAddDialog( self, self.baseWidgets.keys()) if configname != None: logging.debug( "configureVM(): OK pressed and valid configname entered: " + str(configname)) else: logging.debug("configureVM(): Cancel pressed or no VM selected") return ##Now add the item to the tree widget and create the baseWidget configTreeWidgetItem = QtWidgets.QTreeWidgetItem(self.experimentTree) configTreeWidgetItem.setText(0, configname) self.experimentActionsWidget.addExperimentItem(configname) self.connectionWidget.addExperimentItem(configname) # Base Config Widget self.baseWidget = BaseWidget(self, configname, configname) self.baseWidgets[configname] = { "BaseWidget": {}, "VMWidgets": {}, "MaterialWidgets": {} } self.baseWidgets[configname]["BaseWidget"] = self.baseWidget self.basedataStackedWidget.addWidget(self.baseWidget) self.statusBar.showMessage("Added new experiment: " + str(configname)) def importActionEvent(self): logging.debug("MainApp:importActionEvent() instantiated") #Check if it's the case that an experiment name was selected confignamesChosen = PackageImportDialog().packageImportDialog( self, self.baseWidgets.keys()) if confignamesChosen == []: logging.debug( "importActionEvent(): Canceled or a file could not be imported. make sure file exists." ) return #for fileChosen in filesChosen: logging.debug( "MainApp: importActionEvent(): Files choosen (getting only first): " + confignamesChosen) firstConfignameChosen = confignamesChosen self.loadConfigname(firstConfignameChosen) #Add the items to the tree self.statusBar.showMessage("Imported " + firstConfignameChosen) def addVMActionEvent(self): logging.debug("MainApp:addVMActionEvent() instantiated") selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:addVMActionEvent no configurations left") self.statusBar.showMessage( "Could not add VM. No configuration items selected or available." ) return selectedItemName = selectedItem.text(0) #Now allow the user to choose the VM: (response, vmsChosen) = VMRetrieveDialog(self).exec_() if response == QMessageBox.Ok and vmsChosen != None: logging.debug("configureVM(): OK pressed and VMs selected " + str(vmsChosen)) else: logging.debug("configureVM(): Cancel pressed or no VM selected") return if vmsChosen == []: logging.debug( "configureVM(): Canceled or a file could not be added. Try again later or check permissions" ) return for vmChosen in vmsChosen: logging.debug("MainApp: addVMActionEvent(): File choosen: " + str(vmChosen)) #Add the item to the tree vmItem = QtWidgets.QTreeWidgetItem(selectedItem) vmlabel = "V: " + vmChosen vmItem.setText(0, vmlabel) # VM Config Widget #Now add the item to the stack and list of baseWidgets vmjsondata = {"name": vmChosen} vmWidget = VMWidget(self, selectedItemName, vmChosen, vmjsondata) self.baseWidgets[selectedItemName]["VMWidgets"][vmlabel] = vmWidget self.basedataStackedWidget.addWidget(vmWidget) #Now add data to the experimentActionWidget associated with the current config #Check if it's the case that an experiment name was selected parentSelectedItem = selectedItem.parent() if parentSelectedItem != None: selectedItem = parentSelectedItem configname = selectedItem.text(0) config_jsondata = self.getWritableData(configname) self.experimentActionsWidget.resetExperiment( configname, config_jsondata=config_jsondata) self.connectionWidget.resetExperiment(configname, config_jsondata=config_jsondata) self.statusBar.showMessage("Added " + str(len(vmsChosen)) + " VM files to experiment: " + str(selectedItemName)) def startHypervisorActionEvent(self): logging.debug("MainApp:startHypervisorActionEvent() instantiated") logging.debug( "MainApp:startHypervisorActionEvent no configurations left") # Try to open the hypervisor and check if it worked or not result = HypervisorOpenDialog().hypervisorOpenDialog(self) if result != "success": logging.debug( "startHypervisorActionEvent(): Could not start the hypervisor") self.statusBar.showMessage("Hypervisor could not be started.") return self.statusBar.showMessage("Started hypervisor.") def addMaterialActionEvent(self): logging.debug("MainApp:addMaterialActionEvent() instantiated") selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug( "MainApp:addMaterialActionEvent no configurations left") self.statusBar.showMessage( "Could not add item. No configuration items selected or available." ) return selectedItemName = selectedItem.text(0) #Check if it's the case that an experiment name was selected filesChosen = MaterialAddFileDialog().materialAddFileDialog( selectedItemName) if filesChosen == []: logging.debug( "addMaterialActionEvent(): Canceled or a file could not be added. Try again later or check permissions" ) return for fileChosen in filesChosen: fileChosen = os.path.basename(fileChosen) logging.debug("MainApp: addMaterialActionEvent(): File choosen: " + fileChosen) #Add the item to the tree material_item = QtWidgets.QTreeWidgetItem(selectedItem) materiallabel = "M: " + fileChosen material_item.setText(0, materiallabel) # Material Config Widget #Now add the item to the stack and list of baseWidgets materialsjsondata = {"name": fileChosen} materialWidget = MaterialWidget(self, selectedItemName, fileChosen, materialsjsondata) self.baseWidgets[selectedItem.text( 0)]["MaterialWidgets"][materiallabel] = materialWidget self.basedataStackedWidget.addWidget(materialWidget) self.statusBar.showMessage("Added " + str(len(filesChosen)) + " material files to experiment: " + str(selectedItemName)) def removeExperimentItemActionEvent(self): logging.debug("MainApp:removeExperimentItemActionEvent() instantiated") selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:onItemSelected no configurations left") self.statusBar.showMessage( "Could not remove. No configuration items selected or available." ) return selectedItemName = selectedItem.text(0) #Check if it's the case that an experiment name was selected parentSelectedItem = selectedItem.parent() if (parentSelectedItem == None): #A base widget was selected successfilenames = ExperimentRemoveFileDialog( ).experimentRemoveFileDialog(selectedItemName) if successfilenames == [] or successfilenames == "": logging.debug( "removeExperimentItemActionEvent(): Canceled or a file could not be removed. Try again later or check permissions" ) return self.experimentTree.invisibleRootItem().removeChild(selectedItem) self.basedataStackedWidget.removeWidget( self.baseWidgets[selectedItemName]["BaseWidget"]) del self.baseWidgets[selectedItemName] self.experimentActionsWidget.removeExperimentItem(selectedItemName) self.experimentActionsWidget.removeExperimentItem(selectedItemName) self.statusBar.showMessage("Removed experiment: " + str(selectedItemName)) else: #Check if it's the case that a VM Name was selected if (selectedItem.text(0)[0] == "V"): parentSelectedItem.removeChild(selectedItem) configname = parentSelectedItem.text(0) self.basedataStackedWidget.removeWidget( self.baseWidgets[configname]["VMWidgets"][ selectedItem.text(0)]) del self.baseWidgets[configname]["VMWidgets"][ selectedItem.text(0)] self.statusBar.showMessage("Removed VM: " + str(selectedItemName) + " from experiment: " + str(parentSelectedItem.text(0))) #Also remove from the experiment action widget: config_jsondata = self.getWritableData(configname) self.experimentActionsWidget.resetExperiment( configname, config_jsondata=config_jsondata) self.connectionWidget.resetExperiment( configname, config_jsondata=config_jsondata) #Check if it's the case that a Material Name was selected elif (selectedItem.text(0)[0] == "M"): materialName = selectedItemName.split("M: ")[1] successfilenames = MaterialRemoveFileDialog( ).materialRemoveFileDialog(parentSelectedItem.text(0), materialName) if successfilenames == []: logging.debug( "Canceled or a file could not be removed. Try again later or check permissions" ) return parentSelectedItem.removeChild(selectedItem) self.basedataStackedWidget.removeWidget( self.baseWidgets[parentSelectedItem.text( 0)]["MaterialWidgets"][selectedItem.text(0)]) del self.baseWidgets[parentSelectedItem.text( 0)]["MaterialWidgets"][selectedItem.text(0)] self.statusBar.showMessage("Removed Material: " + str(materialName) + " from experiment: " + str(parentSelectedItem.text(0))) def exportActionEvent(self): logging.debug("MainApp:exportActionEvent() instantiated") #Check if it's the case that an experiment name was selected selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:exportActionEvent no configurations left") self.statusBar.showMessage( "Could not export experiment. No configuration items selected or available." ) return selectedItemName = selectedItem.text(0) folderChosen = PackageExportDialog().packageExportDialog( self, selectedItemName) if folderChosen == []: logging.debug( "exportActionEvent(): Canceled or the experiment could not be exported. Check folder permissions." ) return folderChosen = os.path.basename(folderChosen[0]) logging.debug("MainApp: exportActionEvent(): File choosen: " + folderChosen) #Add the items to the tree self.statusBar.showMessage("Exported to " + folderChosen) def editPathActionEvent(self): logging.debug("MainApp:editPathActionEvent() instantiated") result = ConfigurationDialog(self).exec_() def closeEvent(self, event): logging.debug("MainApp:closeEvent(): instantiated") logging.debug("closeEvent(): returning accept") event.accept() qApp.quit() return def initMenu(self): self.mainMenu = QMenuBar() self.fileMenu = self.mainMenu.addMenu("File") self.editMenu = self.mainMenu.addMenu("Edit") self.hypervisorMenu = self.mainMenu.addMenu("Hypervisor") self.newExperimentMenuButton = QAction(QIcon(), "New Experiment", self) self.newExperimentMenuButton.setShortcut("Ctrl+N") self.newExperimentMenuButton.setStatusTip("Create New Experiment") self.newExperimentMenuButton.triggered.connect( self.addExperimentActionEvent) self.fileMenu.addAction(self.newExperimentMenuButton) self.importExperimentMenuButton = QAction(QIcon(), "Import Experiment", self) self.importExperimentMenuButton.setShortcut("Ctrl+I") self.importExperimentMenuButton.setStatusTip( "Import Experiment from RES File") self.importExperimentMenuButton.triggered.connect( self.importActionEvent) self.fileMenu.addAction(self.importExperimentMenuButton) self.saveExperimentMenuButton = QAction(QIcon(), "Save Experiment", self) self.saveExperimentMenuButton.setShortcut("Ctrl+I") self.saveExperimentMenuButton.setStatusTip( "Save currently selected experiment") self.saveExperimentMenuButton.triggered.connect( self.saveExperimentButton) self.saveExperimentMenuButton.setEnabled(False) self.fileMenu.addAction(self.saveExperimentMenuButton) self.exitMenuButton = QAction(QIcon("exit24.png"), "Exit", self) self.exitMenuButton.setShortcut("Ctrl+Q") self.exitMenuButton.setStatusTip("Exit application") self.exitMenuButton.triggered.connect(self.close) self.fileMenu.addAction(self.exitMenuButton) self.pathMenuButton = QAction(QIcon(), "Edit Paths", self) self.pathMenuButton.setShortcut("Ctrl+E") self.pathMenuButton.setStatusTip("Edit Paths") self.pathMenuButton.triggered.connect(self.editPathActionEvent) self.editMenu.addAction(self.pathMenuButton) self.startHypervisorMenuButton = QAction(QIcon(), "Instantiate Hypervisor", self) self.startHypervisorMenuButton.setShortcut("Ctrl+O") self.startHypervisorMenuButton.setStatusTip( "Start the hypervisor that is currently configured") self.startHypervisorMenuButton.triggered.connect( self.startHypervisorActionEvent) self.hypervisorMenu.addAction(self.startHypervisorMenuButton) def getWritableData(self, configname): logging.debug("MainApp: getWritableData() instantiated") jsondata = {} jsondata["xml"] = {} #get baseWidget data baseWidget = self.baseWidgets[configname]["BaseWidget"] ###TODO: make this work for multiple experiments (current testing assumes only one) if isinstance(baseWidget, BaseWidget): jsondata["xml"] = baseWidget.getWritableData() ###Setup the dictionary if "testbed-setup" not in jsondata["xml"]: jsondata["xml"]["testbed-setup"] = {} if "vm-set" not in jsondata["xml"]["testbed-setup"]: jsondata["xml"]["testbed-setup"]["vm-set"] = {} if "vm" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["vm"] = [] if "material" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["material"] = [] for vmData in self.baseWidgets[configname]["VMWidgets"].values(): jsondata["xml"]["testbed-setup"]["vm-set"]["vm"].append( vmData.getWritableData()) for materialData in self.baseWidgets[configname][ "MaterialWidgets"].values(): jsondata["xml"]["testbed-setup"]["vm-set"]["material"].append( materialData.getWritableData()) return jsondata def saveExperimentButton(self): logging.debug("MainApp: saveExperiment() instantiated") self.saveExperiment() def saveExperiment(self, configname=None): logging.debug("MainApp: saveExperiment() instantiated") selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:onItemSelected no configurations left") self.statusBar.showMessage( "Could not save. No configuration items selected or available." ) return #Check if it's the case that an experiment name was selected parentSelectedItem = selectedItem.parent() if parentSelectedItem != None: selectedItem = parentSelectedItem configname = selectedItem.text(0) jsondata = self.getWritableData(configname) self.ec.writeExperimentXMLFileData(jsondata, configname) self.ec.writeExperimentJSONFileData(jsondata, configname) self.ec.getExperimentVMRolledOut(configname, jsondata, force_refresh=True) res = self.ec.getExperimentServerInfo(configname) #Now reset the experimentActions view self.experimentActionsWidget.resetExperiment(configname, jsondata) self.connectionWidget.resetExperiment(configname, jsondata) self.statusBar.showMessage( "Succesfully saved experiment file for " + str(configname), 2000)
class MainWindow(QMainWindow): """ 主窗口界面 """ def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) # 初始化 self.init() # ui设计 self.setup_ui() # 创建右键菜单 self.create_context_menu() # 主框体设计 self.set_main_form() # 加载qss样式 self.load_qss() def init(self): self.setGeometry(Const.WIN_X, Const.WIN_Y, Const.WIN_WIDTH, Const.WIN_HEIGHT) self.setObjectName('mainWindow') self.setWindowIcon(QIcon("./image/Logo/logo.png")) self.setWindowTitle('IFR智能公式识别系统') # 加载图片缩放公共类 self.imageScale = ImageScale() def setup_ui(self): """ 创建状态栏、菜单栏、工具栏 """ # 状态栏 self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.statusBar.showMessage('准备就绪', 5000) # self.statusBar().setStyleSheet('background-color:lightGray;') # 菜单栏 self.menubar = QMenuBar() self.setMenuBar(self.menubar) # self.menuBar().setStyleSheet('background-color:lightGray;') # 文件 self.fileMenu = self.menubar.addMenu('&文件(F)') # 调用自定义action self.openPimax = Action.action_b_2(self, 'openPimax', '&打开图片文件', 'Ctrl+P', '打开图片文件') self.openPimax.setIcon(QIcon('./image/openQpixmap.jpg')) self.openText = Action.action_b_2(self, 'openText', '&打开文本文件', 'Ctrl+T', '打开文本文件') self.openText.setIcon(QIcon('./image/openText.ico')) self.openFile = Action.action_b_3(self, 'openFile', '打开文件', '打开文件', self.fileMenu) self.openFile.addAction(self.openPimax) self.openFile.addAction(self.openText) self.openPimax.triggered.connect(lambda: self.get_image()) self.openText.triggered.connect(lambda: self.get_text()) self.openRecentFile = Action.action_a_2(self, 'openRecentFile', '&最近打开的文件', 'Ctrl+O', '最近打开的文件', self.fileMenu) # self.openRecentFile.triggered.connect(self.) self.save = Action.action_a_2(self, 'save', '&保存分析结果', 'Ctrl+S', '保存数据分析结果', self.fileMenu) # self.save.triggered.connect(self.) self.saveAs = Action.action_a_2(self, 'saveAs', '&另保存分析结果', 'Ctrl+Shift+S', '另保存数据分析结果', self.fileMenu) # self.saveAs.triggered.connect(self.) self.printf = Action.action_a_2(self, 'printef', '&打印分析结果', 'Ctrl+P', '打印数据分析结果', self.fileMenu) # self.printf.triggered.connect(self.) self.exitAction = Action.action_a_1(self, 'exitAction', './image/mainWindowIcon/toolBarIcon/exit.png', '&退出', 'Ctrl+Q', '退出应用程序', self.fileMenu) self.exitAction.triggered.connect(self.close) # 编辑 self.exitMenu = self.menubar.addMenu('&编辑(E)') # # ####################查找与替换####################开始 self.search = Action.action_b_2(self, 'search', '&快速查找', 'Ctrl+F', '快速查找') self.replace = Action.action_b_2(self, 'replace', '&快速替换', 'Ctrl+H', '快速替换') # 新增二级菜单 self.searchAndReplaceMenu = Action.action_b_3(self, 'searchAndReplaceMenu', '查找与替换', '查找与替换', self.exitMenu) self.searchAndReplaceMenu.addAction(self.search) self.searchAndReplaceMenu.addAction(self.replace) # self.search.triggered.connect(self.) # self.replace.triggered.connect(self.) # ####################查找与替换####################结束 self.cut = Action.action_a_2(self, 'cut', '&剪切', 'Ctrl+X', '剪切', self.exitMenu) # self.cut.triggered.connect(self.) self.copy = Action.action_a_2(self, 'copy', '&复制', 'Ctrl+C', '复制', self.exitMenu) # self.copy.triggered.connect(self.) self.paste = Action.action_a_2(self, 'paste', '&粘贴', 'Ctrl+V', '粘贴', self.exitMenu) # self.paste.triggered.connect(self.) self.delete = Action.action_a_2(self, 'delect', '&删除', 'Del', '删除', self.exitMenu) # self.delect.triggered.connect(self.) self.selectAll = Action.action_a_2(self, 'selectAll', '&全选', 'Ctrl+Alt', '全选', self.exitMenu) # self.selectAll.triggered.connect(self.) # 视图 self.viewMenu = self.menubar.addMenu('&视图(V)') self.notice = Action.action_a_2(self, 'notice', '&通知', 'Ctrl+Alt+X', '信息通知提醒', self.viewMenu) # self.notice.triggered.connect(self.) # ####################窗口管理####################开始 self.window = Action.action_b_3(self, 'window', '&窗口', '展示一些基本窗口', self.viewMenu) # ####################窗口管理####################结束 # # # # ####################工具栏####################开始 self.tool = Action.action_b_3(self, 'tool', '&工具栏', '基本工具', self.viewMenu) self.calculator = Action.action_a_1(self, 'calculator', './image/calculator.jpg', '&计算器', 'C', '计算器', self.viewMenu) self.calculator.triggered.connect(lambda: self.calculator_win()) # ####################工具####################结束 self.fullScreen = Action.action_a_2(self, 'fullScreen', '&全屏幕', 'Shift+Alt+Enter', '全屏', self.viewMenu) # self.fullScreen.triggered.connect(self.) self.propertyWindow = Action.action_a_2(self, 'propertyWindow', '&属性窗口', 'F4', '属性窗口', self.viewMenu) # self.propertyWindow.triggered.connect(self.) # # 分析 self.navigateMenu = self.menubar.addMenu('&分析(N)') # # 工具 self.toolMenu = self.menubar.addMenu('&工具(T)') # # 扩展 self.extendMenu = self.menubar.addMenu('&扩展(X)') # # 窗口 self.windowMenu = self.menubar.addMenu('&窗口(W)') # # 帮助 self.helpMenu = self.menubar.addMenu('&帮助(H)') self.help = Action.action_a_2(self, 'help ', '&查看帮助', 'Ctrl+F1', '查看帮助', self.helpMenu) # self.help.triggered.connect(self.) # ####################菜单####################结束 ################################################################################################################ # ####################工具栏####################开始 # 工具 self.pixmapToolbar = self.addToolBar('打开图形文件') self.textToolbar = self.addToolBar('打开文本文件') self.pixmapToolbar.addAction(self.openPimax) self.textToolbar.addAction(self.openText) self.exitToolbar = self.addToolBar('退出') self.exitToolbar.addAction(self.exitAction) self.calculatorTooolbar = self.addToolBar('计算器') self.calculatorTooolbar.addAction(self.calculator) # ####################工具栏####################结束 # 槽函数线程 # 创建右键菜单 def create_context_menu(self): """ 创建右键菜单 :return: """ self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.show_context_menu) # 创建QMenu self.contextMenu = QMenu(self) # ####################工具栏管理####################开始 self.toolBarManagementMenu = Action.action_b_4(self, 'toolBarManagementMenu', '&工具栏管理', self.contextMenu) # 未完成 # ####################工具栏管理####################结束 self.minAtion = Action.action_a_1(self, 'minAction', './image/min.png', '&最小化', 'Ctrl+M', '最小化窗口', self.contextMenu) self.contextMenu.addSeparator() # 添加分隔线 self.cutAction = Action.action_a_2(self, 'cutAction', '&剪切', 'Ctrl+X', '剪切', self.contextMenu) self.copyAction = Action.action_a_2(self, 'copyAction', '&复制', 'Ctrl+C', '复制', self.contextMenu) self.pasteAction = Action.action_a_2(self, 'pasteAction', '&粘贴', 'Ctrl+V', '粘贴', self.contextMenu) self.deleteAction = Action.action_a_2(self, 'delectAction', '&删除', 'Del', '删除', self.contextMenu) self.selectAllAction = Action.action_a_2(self, 'selectAllAction', '&全选', 'Ctrl+Alt', '全选', self.contextMenu) self.contextMenu.addSeparator() # 添加分隔线 self.closeAction = Action.action_a_1(self, 'closeAction', './image/Exit.png', '&退出', 'Ctrl+W', '退出', self.contextMenu) self.minAtion.triggered.connect(self.show_mininized_window) self.closeAction.triggered.connect(self.quit_window) # self.selectAllAction.triggered.connect(self.) # self.cutAction.triggered.connect(self.) # self.copyAction.triggered.connect(self.) # self.pasteAction.triggered.connect(self.) # self.delectAction.triggered.connect(self.) # ****************************** 业务逻辑 ********************************* def load_qss(self): """ 加载Qss样式表 :return: """ style_file = './Window/mainWindow/Qss/mainWindow.qss' qss_style = CommonhelperQss.read_qss(style_file) self.setStyleSheet(qss_style) def set_action_connect(self): """ 菜单栏、工具栏槽函数连接 :return: """ pass def calculator_win(self): """ 加载计算器窗口 :return: """ self.calculator_Win = Calculatormainwindow() self.calculator_Win.show() def set_main_form(self): """ 窗体布局以及主框体设计 :return: """ # 主框体 self.mainSpiltter = QSplitter(Qt.Vertical) self.mainSpiltter.setObjectName('mainSpiltter') self.mainSpiltterLayout = QVBoxLayout() # 设置主窗口中心窗体 self.setCentralWidget(self.mainSpiltter) # *******工作区间******* self.workWidget = QSplitter() self.workWidget.setObjectName('workWidget') self.mainSpiltter.addWidget(self.workWidget) self.workWidgetLayout = QHBoxLayout() self.workWidget.setLayout(self.workWidgetLayout) self.leftWidget = QFrame() self.leftWidget.setObjectName('leftWidget') self.leftWidget.setFrameShape(QFrame.StyledPanel) self.leftWidget.setMaximumWidth(230) self.leftWidgetLayout = QVBoxLayout() self.leftWidgetLayout.setContentsMargins(0, 0, 0, 0) self.leftWidget.setLayout(self.leftWidgetLayout) # self.hideBtn = QLabel() # self.hideBtn.setObjectName('hideBtn') # self.hideBtn.setPixmap(QPixmap('./image/mainWindowIcon/showAndHideIcon/hide0.ico')) # # self.showBtn = QLabel() # self.showBtn.setObjectName('showBtn') # self.showBtn.setPixmap(QPixmap('./image/mainWindowIcon/showAndHideIcon/show0.ico')) # 存放按钮 self.widget = QWidget() self.widget.setObjectName('widget') self.leftWidgetLayout.addWidget(self.widget) pixmap = self.imageScale.pixmap_scale('./image/Logo/logo0.png', 204, 80) self.logoIamgeLabel = QLabel(self.widget) self.logoIamgeLabel.setObjectName('logoImageLabel') self.logoIamgeLabel.setPixmap(pixmap) self.widgetLayout = QGridLayout() self.widget.setLayout(self.widgetLayout) self.widgetLayout.addWidget(self.logoIamgeLabel, 0, 1) # 多界面 # QListWidget + QStackedWidget实现 self.leftListWidget = QListWidget() # 左侧选项列表 self.leftListWidget.setObjectName('leftListWidget') self.rightWidget = QStackedWidget() # 右侧框体 self.rightWidget.setObjectName('rightWidget') self.leftWidgetLayout.addWidget(self.leftListWidget) self.workWidgetLayout.addWidget(self.leftWidget) self.workWidgetLayout.addWidget(self.rightWidget) # ********左侧选项列表布局以及设置****************************** # 设置左侧选项列表大小 self.leftListWidget.setMinimumWidth(Const.LEFTWIDGET_WIDTH) # 左侧选项列表与右侧框体的index对应绑定 self.leftListWidget.currentRowChanged.connect(self.rightWidget.setCurrentIndex) # 去掉边框 self.leftListWidget.setFrameShape(QListWidget.NoFrame) # 隐藏滚动条 self.leftListWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.leftListWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) list_str = ['智能识别', '公式生成器', '学习资源区', '设置', '关于'] # 左侧选项添加 for i in range(5): self.item = QListWidgetItem(list_str[i], self.leftListWidget) self.item.setSizeHint(QSize(Const.ITEM_WIDTH, Const.ITEM_HEIGHT)) # 居中显示 self.item.setTextAlignment(Qt.AlignCenter) # 设置默认选中item[1] self.leftListWidget.setCurrentRow(0) # ********右侧主框体布局以及设置********************************** self.rightForm1 = RightForm1() self.rightForm2 = RightForm2() self.rightForm3 = RightForm3() self.rightForm4 = RightForm4() self.rightForm5 = RightForm5() self.rightWidget.addWidget(self.rightForm1) self.rightWidget.addWidget(self.rightForm2) self.rightWidget.addWidget(self.rightForm3) self.rightWidget.addWidget(self.rightForm4) self.rightWidget.addWidget(self.rightForm5) # ############################################################# # 消息通知框 self.messageInform = MesageFrame() self.messageInform.setObjectName('messageInform') # 消息通知框默认隐藏 self.messageInform.hide() self.mainSpiltter.addWidget(self.messageInform) # *****侧边栏***** # 右侧边栏 self.rightBar = QFrame() self.rightBar.setObjectName('rightBar') self.rightBar.setFixedWidth(35) self.rightBar.setFrameShape(QFrame.StyledPanel) self.rightBarLayout = QVBoxLayout() self.rightBar.setLayout(self.rightBarLayout) self.workWidgetLayout.addWidget(self.rightBar) # 右侧边栏控件 # 右侧边栏添加控件 # 下侧边栏 self.bottomBar = QFrame() self.bottomBar.setObjectName('bottomBar') self.bottomBar.setMaximumHeight(35) self.bottomBar.setFrameShape(QFrame.StyledPanel) self.bottomBarLayout = QHBoxLayout() self.bottomBarLayout.setAlignment(Qt.AlignRight) # 右对齐 self.bottomBar.setLayout(self.bottomBarLayout) self.mainSpiltter.addWidget(self.bottomBar) # 下侧边栏控件 # 留白控件 blank = QLabel(self.bottomBar) blank.setObjectName('blank') self.informText = QLabel(self.bottomBar) self.informText.setObjectName('informText') self.informText.setText('通知') self.informBtn = QPushButton(self.bottomBar) self.informBtn.setObjectName('informBtn') self.informBtn.resize(QSize(35, 35)) self.informBtn.setIcon(QIcon('./image/mainWindowIcon/messageBarBtnIcon/inform0.png')) self.informBtn.clicked.connect(lambda: self.open_inform_frame()) # 下侧边栏添加控件 self.bottomBarLayout.addWidget(self.informBtn) self.bottomBarLayout.addWidget(self.informText) self.bottomBarLayout.addWidget(blank) # ****************************业务逻辑****************************** # 右键菜单 def show_context_menu(self): """ 右键点击时调用的函数 :return: """ # 显示菜单前,将它移动到鼠标点击的位置 self.contextMenu.exec_(QCursor.pos()) # 最小化窗口 def show_mininized_window(self): """ :return: """ self.showMinimized() # 最大化窗口 def show_maximized_window(self): """ :return: """ self.showMaximized() # 复原窗口 def show_restore_window(self): """ :return: """ if self.isMaximized(): self.showNormal() else: self.showMaximized() # 关闭窗口 def quit_window(self): """ :return: """ self.close() # 打开文件 def get_image(self): """ getOpenFileName():返回用户所选择文件的名称,并打开该文件 第一个参数用于指定父组件 第二个参数指定对话框标题 第三个参数指定目录 第四个参数是文件扩展名过滤器 """ pass # fname, _ = QFileDialog.getOpenFileName(self, '选择图形文件', 'C:\\', "*.jpg *.gif *.png") # self.pixmapLabel.setPixmap(QPixmap(fname)) def get_text(self): """ :return: """ pass # # 初始化实例,并设置一些参数 # # textDialog = QFileDialog() # # textDialog.setFileMode(QFileDialog.AnyFile) # # textDialog.setFilter(QDir.Files) # textDialog = QFileDialog.getOpenFileName(self, '选择文本文件', 'C:\\', "*.txt *.doc *.docx") # # 当选择器关闭的时候 # if textDialog.exec_(): # # 拿到所选择的文本 # filenames = textDialog.selectedFiles() # # 读取文本内容设置到textEdit中 # f = open(filenames[0], 'r') # with f: # data = f.read() # self.textEdit.setText(data) def open_inform_frame(self): self.messageInform.show()
class SettingsDialog(QDialog): ''' Dialog object for application settings. ''' def __init__(self): super().__init__() self.settings = QSettings() self.modified_settings = [] self.initUi() def initUi(self): self.setObjectName('dialogSettings') self.resize(725, 475) self.horizontalLayout = QHBoxLayout(self) self.horizontalLayout.setObjectName('horizontalLayoutSettings') self.listWidget = QListWidget(self) self.listWidget.setObjectName('listWidgetSettings') sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.listWidget.sizePolicy().hasHeightForWidth()) self.listWidget.setSizePolicy(sizePolicy) font = QFont() font.setPointSize(12) self.listWidget.setFont(font) self.listWidget.setSortingEnabled(False) self.horizontalLayout.addWidget(self.listWidget) self.verticalWidget = QWidget(self) self.verticalWidget.setObjectName('verticalWidgetSettings') sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(2) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.verticalWidget.sizePolicy().hasHeightForWidth()) self.verticalWidget.setSizePolicy(sizePolicy) self.horizontalLayout.addWidget(self.verticalWidget) self.verticalLayout = QVBoxLayout(self.verticalWidget) self.verticalLayout.setObjectName('verticalLayoutSettings') self.stackedWidget = QStackedWidget(self.verticalWidget) self.stackedWidget.setObjectName('stackedWidgetSettings') self.verticalLayout.addWidget(self.stackedWidget) self.buttonBox = QDialogButtonBox(self.verticalWidget) self.buttonBox.setObjectName('buttonBoxSettings') sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.buttonBox.sizePolicy().hasHeightForWidth()) self.buttonBox.setSizePolicy(sizePolicy) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Apply | QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) apply = self.buttonBox.button(QDialogButtonBox.Apply) apply.clicked.connect(self.saveSettings) apply.setEnabled(False) self.verticalLayout.addWidget(self.buttonBox) self.initSettingGroups() self.retranslateUi() self.listWidget.setCurrentRow(0) self.stackedWidget.setCurrentIndex(0) def initSettingGroups(self): ''' Adds setting groups as ListItems and connects them to their specific widgets. ''' # Server settings - Index 0 item = QListWidgetItem() icon = QIcon() icon.addPixmap(QPixmap(':/icons/network.svg'), QIcon.Normal, QIcon.On) item.setIcon(icon) self.listWidget.addItem(item) self.widgetServerSettings = ServerSettingsWidget(self) self.stackedWidget.addWidget(self.widgetServerSettings) def saveSettings(self): for setting in self.modified_settings: widget = self.findChild(QObject, setting) if setting == 'lineEditApiUrl': self.settings.setValue('server/api_base_url', widget.text()) if setting == 'lineEditApiToken': if widget.text().strip() == '': keyring.delete_password(qApp.applicationName(), 'Token') else: keyring.set_password(qApp.applicationName(), 'Token', widget.text()) self.settings.sync() self.modified_settings = [] self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) def accept(self): self.saveSettings() self.done(QDialog.Accepted) def reject(self): self.done(QDialog.Rejected) def retranslateUi(self): '''Translate labels into native language and assign them to widgets.''' _ = QCoreApplication.translate # Dialog title self.setWindowTitle(_('Client', 'Settings')) # Server settings item = self.listWidget.item(0) item.setText(_('Client', ' Server')) self.widgetServerSettings.labelApiUrl.setText( _('Client', 'API Base URL:')) self.widgetServerSettings.labelApiToken.setText( _('Client', 'API Token:'))
class QUnFrameWindow(QWidget): """ 无边框窗口类 """ def __init__(self): super(QUnFrameWindow, self).__init__(None, Qt.FramelessWindowHint) # 设置为顶级窗口,无边框 self._padding = 5 # 设置边界宽度为5 self.initTitleLabel() # 安放标题栏标签 self.setWindowTitle = self._setTitleText(self.setWindowTitle) # 用装饰器将设置WindowTitle名字函数共享到标题栏标签上 self.setWindowTitle(" The LC. Technology Refined Operation Console") self.initLayout() # 设置框架布局 self.setMinimumWidth(250) self.setMouseTracking(True) # 设置widget鼠标跟踪 self.initDrag() # 设置鼠标跟踪判断默认值 #-------------------------------------------------------- with open(setting.STATIC_PATH+'\\main.qss', 'r',encoding='UTF-8') as f: # 导入QListWidget的qss样式 self.list_style = f.read() self.main_layout = QHBoxLayout(self, spacing=0) # 窗口的整体布局 self.addLayout(self.main_layout) self.main_layout.setContentsMargins(0, 50, 0, 0) self.left_widget = QListWidget() # 左侧选项列表 self.left_widget.setStyleSheet(self.list_style) self.main_layout.addWidget(self.left_widget) self.right_widget = QStackedWidget() self.main_layout.addWidget(self.right_widget) self._setup_ui() #------------------------------------------------------------------------------------------------------ def _setup_ui(self): '''加载界面ui''' self.left_widget.currentRowChanged.connect(self.right_widget.setCurrentIndex) #list和右侧窗口的index对应绑定 self.left_widget.setFrameShape(QListWidget.NoFrame) #去掉边框 self.left_widget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) #隐藏滚动条 self.left_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) for item in router.ROUTER: self.item = QListWidgetItem(item, self.left_widget) self.item.setSizeHint(QSize(20, 60)) self.item.setTextAlignment(Qt.AlignCenter) self.right_widget.addWidget(router.ROUTER[item]()) self.right_widget.setObjectName('content') def initDrag(self): # 设置鼠标跟踪判断扳机默认值 self._move_drag = False self._corner_drag = False self._bottom_drag = False self._right_drag = False def initTitleLabel(self): # 安放标题栏标签 self._TitleLabel = QTitleLabel(self) self._TitleLabel.setMouseTracking(True) # 设置标题栏标签鼠标跟踪(如不设,则标题栏内在widget上层,无法实现跟踪) self._TitleLabel.setIndent(10) # 设置标题栏文本缩进 self._TitleLabel.move(0, 0) # 标题栏安放到左上角 self._Ico = QLabel(self._TitleLabel) self.setObjectName('title_ico') png = QPixmap(setting.STATIC_PATH+'\\main_ico.png') self._Ico.setPixmap(png) self._Ico.move(10,7) def initLayout(self): # 设置框架布局 self._MainLayout = QVBoxLayout() self._MainLayout.setSpacing(0) # self._MainLayout.addWidget(QLabel(), Qt.AlignLeft) # 顶一个QLabel在竖放框架第一行,以免正常内容挤占到标题范围里 # self._MainLayout.addStretch() self.setLayout(self._MainLayout) def addLayout(self, QLayout): # 给widget定义一个addLayout函数,以实现往竖放框架的正确内容区内嵌套Layout框架 self._MainLayout.addLayout(QLayout) def _setTitleText(self, func): # 设置标题栏标签的装饰器函数 def wrapper(*args): self._TitleLabel.setText(*args) return func(*args) return wrapper def setTitleAlignment(self, alignment): # 给widget定义一个setTitleAlignment函数,以实现标题栏标签的对齐方式设定 self._TitleLabel.setAlignment(alignment | Qt.AlignVCenter) def setCloseButton(self, bool): # 给widget定义一个setCloseButton函数,为True时设置一个关闭按钮 if bool == True: self._CloseButton = QTitleButton(b'x'.decode("utf-8"), self) self._CloseButton.setObjectName("CloseButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式 self._CloseButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪) self._CloseButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度 self._CloseButton.clicked.connect(self.close) # 按钮信号连接到关闭窗口的槽函数 def setMinMaxButtons(self, bool): # 给widget定义一个setMinMaxButtons函数,为True时设置一组最小化最大化按钮 if bool == True: self._MinimumButton = QTitleButton(b'-'.decode("utf-8"), self) self._MinimumButton.setObjectName("MinMaxButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式 self._MinimumButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪) self._MinimumButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度 self._MinimumButton.clicked.connect(self.showMinimized) # 按钮信号连接到最小化窗口的槽函数 def resizeEvent(self, QResizeEvent): # 自定义窗口调整大小事件 self._TitleLabel.setFixedWidth(self.width()) # 将标题标签始终设为窗口宽度 # 分别移动三个按钮到正确的位置 try: self._CloseButton.move(self.width() - self._CloseButton.width(), 0) except: pass try: self._MinimumButton.move(self.width() - (self._CloseButton.width() + 1) * 2 + 1, 0) except: pass # 重新调整边界范围以备实现鼠标拖放缩放窗口大小,采用三个列表生成式生成三个列表 self._right_rect = [QPoint(x, y) for x in range(self.width() - self._padding, self.width() + 1) for y in range(1, self.height() - self._padding)] self._bottom_rect = [QPoint(x, y) for x in range(1, self.width() - self._padding) for y in range(self.height() - self._padding, self.height() + 1)] self._corner_rect = [QPoint(x, y) for x in range(self.width() - self._padding, self.width() + 1) for y in range(self.height() - self._padding, self.height() + 1)] def mousePressEvent(self, event): # 重写鼠标点击的事件 if (event.button() == Qt.LeftButton) and (event.pos() in self._corner_rect): # 鼠标左键点击右下角边界区域 self._corner_drag = True event.accept() elif (event.button() == Qt.LeftButton) and (event.pos() in self._right_rect): # 鼠标左键点击右侧边界区域 self._right_drag = True event.accept() elif (event.button() == Qt.LeftButton) and (event.pos() in self._bottom_rect): # 鼠标左键点击下侧边界区域 self._bottom_drag = True event.accept() elif (event.button() == Qt.LeftButton) and (event.y() < self._TitleLabel.height()): # 鼠标左键点击标题栏区域 self._move_drag = True self.move_DragPosition = event.globalPos() - self.pos() event.accept() def mouseMoveEvent(self, QMouseEvent): # 判断鼠标位置切换鼠标手势 if QMouseEvent.pos() in self._corner_rect: self.setCursor(Qt.SizeFDiagCursor) elif QMouseEvent.pos() in self._bottom_rect: self.setCursor(Qt.SizeVerCursor) elif QMouseEvent.pos() in self._right_rect: self.setCursor(Qt.SizeHorCursor) else: self.setCursor(Qt.ArrowCursor) # 当鼠标左键点击不放及满足点击区域的要求后,分别实现不同的窗口调整 # 没有定义左方和上方相关的5个方向,主要是因为实现起来不难,但是效果很差,拖放的时候窗口闪烁,再研究研究是否有更好的实现 if Qt.LeftButton and self._right_drag: # 右侧调整窗口宽度 self.resize(QMouseEvent.pos().x(), self.height()) QMouseEvent.accept() elif Qt.LeftButton and self._bottom_drag: # 下侧调整窗口高度 self.resize(self.width(), QMouseEvent.pos().y()) QMouseEvent.accept() elif Qt.LeftButton and self._corner_drag: # 右下角同时调整高度和宽度 self.resize(QMouseEvent.pos().x(), QMouseEvent.pos().y()) QMouseEvent.accept() elif Qt.LeftButton and self._move_drag: # 标题栏拖放窗口位置 self.move(QMouseEvent.globalPos() - self.move_DragPosition) QMouseEvent.accept() def mouseReleaseEvent(self, QMouseEvent): # 鼠标释放后,各扳机复位 self._move_drag = False self._corner_drag = False self._bottom_drag = False self._right_drag = False
class DnmrGui(QMainWindow): """ Create the GUI for the application. Currently the app features a single simulation model (two uncoupled spins), and so a single main window. TODO: as views are added, create a toggle between GUI windows tailored to each simulation (e.g. appropriate widgets for data entry) """ def __init__(self, parent=None): print('ititializing gui class') super(DnmrGui, self).__init__(parent) print('creating views list') self.views = [] self.models = [dnmrplot_2spin, dnmrplot_AB] self.setObjectName('toplevel') self.setupUi() class MainView(QWidget): """A QWidget that has the following properties: - A top row of labeled QDoubleSpinBox es for data entry - Beneath them, a pqtgraph PlotWidget for the simulated plot - the ability to detect changes to the data entries, store their current values, call the appropriate model and pass the simulation results to the pyqtgraph widget """ def __init__(self, name, *args): super().__init__() self.setObjectName(name + 'widget') self.setAutoFillBackground(True) self.setStyleSheet("background-color: rgb(60, 63, 65);") self.simulation_vars = {} layout = QGridLayout() layout.setObjectName(name + 'layout') for i, widget in enumerate(args): # make a label for the widget wlabel = QLabel(widget.string) wlabel.setObjectName(widget.key + '_label') wlabel.setStyleSheet('color: white') wlabel.setAlignment(Qt.AlignCenter) # Make a QDoubleSpinBox widget wbox = QDoubleSpinBox() wbox.setObjectName(widget.key) wbox.setStyleSheet('color: white') wbox.setRange(*widget.range) # SET RANGE BEFORE VALUE wbox.setValue(widget.value) wbox.setAlignment(Qt.AlignCenter) wbox.setAccelerated(True) # Add label (above) and spinbox (below) to layout layout.addWidget(wlabel, 0, i) layout.addWidget(wbox, 1, i) # Store the default simulation value self.simulation_vars[widget.key] = widget.value # update the view if this widget's value is changed # Using the lambda expression below allows extra information to # be passed to the self.update slot, allowing the delegator to # see who sent the signal, update the dictionary of model # inputs, call the model for a simulation result, and plot # it. See: # https://mfitzp.io/article/transmit-extra-data-with-signals-in-pyqt/ wbox.valueChanged.connect( lambda val, key=widget.key: self.parent().parent().updateView(key, val)) # Add pyqtgraph widget setConfigOption('background', (43, 43, 43)) setConfigOption('foreground', (187, 187, 187)) graphicsView = PlotWidget() layout.addWidget(graphicsView, 2, 0, 1, len(twosinglets_vars)) plots.append(graphicsView.plot()) # lets the graph span the entire width of the window, no matter how # many input widgets appear above self.setLayout(layout) def setupUi(self): """ Set up the GUI with the default moded, default variables, and simulated lineshape. """ self.setupCentral() self.setupModelBar() self.initializeGui() def setupCentral(self): self.stackedWidget = QStackedWidget() self.stackedWidget.setObjectName('stackedwidget') self.stackedWidget.setStyleSheet("background-color: rgb(60, 63, 65);") for view in mainviews: widget = self.MainView(view[0], *view[1]) self.stackedWidget.addWidget(widget) self.setCentralWidget(self.stackedWidget) def setupModelBar(self): """ Add a tool bar to the GUI for selecting which model to display """ leftToolBar = QToolBar() leftToolBar.setStyleSheet("background-color: rgb(60, 63, 65);") leftToolBar.setObjectName('lefttoolbar') leftToolBar.addWidget(self.modelButtonGroup()) self.addToolBar(Qt.LeftToolBarArea, leftToolBar) def modelButtonGroup(self): """ A widget of radio buttons that will determine which QStackedWidget is displayed. """ # It seems that in order for the buttonClicked signal to work, # self.ButtonGroup and not ButtonGroup is necessary. Does not work # with out 'self.' prefix!!! modelsWidget = QWidget() modelsWidget.setObjectName('modelswidget') modelsLayout = QVBoxLayout() modelsLayout.setObjectName('modelslayout') self.ButtonGroup = QButtonGroup() selectModelLabel = QLabel('Select Model:') selectModelLabel.setAlignment(Qt.AlignCenter) selectModelLabel.setStyleSheet('color: white') twosingletbutton = QRadioButton('Two uncoupled spin-1/2 nuclei') twosingletbutton.setObjectName('twosingletbutton') twosingletbutton.setStyleSheet('color: white') twosingletbutton.setChecked(True) self.ButtonGroup.addButton(twosingletbutton, 0) abbutton = QRadioButton('Two coupled spin-1/2 nuclei\n ("AB quartet)') abbutton.setObjectName('abbutton') abbutton.setStyleSheet('color: white') self.ButtonGroup.addButton(abbutton, 1) self.ButtonGroup.buttonClicked[int].connect(self.switchView) modelsLayout.addStretch() modelsLayout.addWidget(selectModelLabel) modelsLayout.addWidget(twosingletbutton) modelsLayout.addWidget(abbutton) modelsLayout.addStretch() modelsWidget.setLayout(modelsLayout) modelsWidget.setStyleSheet("background-color: rgb(60, 63, 65);") return modelsWidget def switchView(self, index): self.stackedWidget.setCurrentIndex(index) self.call_model() def initializeGui(self): # Note order of models in stackedWidget and plots must be same for i in range(len(plots)): self.stackedWidget.setCurrentIndex(i) plot = plots[i] plot.getViewBox().invertX(True) # Reverse x axis "NMR style" plot.setData(*self.call_model()) self.stackedWidget.setCurrentIndex(0) self.setGeometry(50, 50, 800, 600) self.setWindowTitle('pyDNMR') self.statusBar().showMessage('Ready') def call_model(self): """ Send the dictionary as **kwargs to the model :return: a spectrum, consisting of a tuple of x and y coordinate arrays """ model = self.models[self.stackedWidget.currentIndex()] x, y = model( **self.stackedWidget.currentWidget().simulation_vars) return x, y def updateView(self, key, val): """ Detect a change in numerical input; record the change in the dictionary of widget values; call the model to get an updated spectrum; and plot the spectrum. :param key: the dictionary key for the variable associated with the signalling widget :param val: the current value of the signalling widget """ self.stackedWidget.currentWidget().simulation_vars[key] = val self.plot_graph() def plot_graph(self): activePlot = plots[self.stackedWidget.currentIndex()] activePlot.setData(*self.call_model())
class Notes(object): def __init__(self): super(Notes).__init__() def setupUi(self, MainWindow): menubar = MainWindow.menuBar() self.menu_file = menubar.addMenu("File") self.menu_edit = menubar.addMenu("Edit") self.menu_format = menubar.addMenu("Format") self.menu_help = menubar.addMenu("Help") #self.menu_view = menubar.addMenu("Export") # menubar file menu self.menu_file_action = QAction("New File", MainWindow) self.menu_file.addAction(self.menu_file_action) self.new_notebook_action = QAction("New Notebook", MainWindow) self.menu_file.addAction(self.new_notebook_action) self.open_file_action = QAction("Open an existing file", MainWindow) self.menu_file.addAction(self.open_file_action) self.save_file_action = QAction("Save File", MainWindow) self.menu_file.addAction(self.save_file_action) # menubar edit menu self.undo_edit_action = QAction("Undo", MainWindow) self.menu_edit.addAction(self.undo_edit_action) self.redo_edit_action = QAction("Redo", MainWindow) self.menu_edit.addAction(self.redo_edit_action) self.copy_edit_action = QAction("Copy", MainWindow) self.menu_edit.addAction(self.copy_edit_action) self.cut_edit_action = QAction("Cut", MainWindow) self.menu_edit.addAction(self.cut_edit_action) self.paste_edit_action = QAction("Paste", MainWindow) self.menu_edit.addAction(self.paste_edit_action) self.image_edit_action = QAction("Insert an Image", MainWindow) self.menu_edit.addAction(self.image_edit_action) self.table_edit_action = QAction("Insert a Table", MainWindow) self.menu_edit.addAction(self.table_edit_action) self.time_edit_action = QAction("Insert the current Time", MainWindow) self.menu_edit.addAction(self.time_edit_action) self.date_edit_action = QAction("Insert the current Date", MainWindow) self.menu_edit.addAction(self.date_edit_action) # menubar format menu self.fontcolor_format_action = QAction("Choose font color", MainWindow) self.menu_format.addAction(self.fontcolor_format_action) self.fontbgcolor_format_action = QAction( "Choose font Background Color", MainWindow) self.menu_format.addAction(self.fontbgcolor_format_action) self.font_format_action = QAction("Choose font", MainWindow) self.menu_format.addAction(self.font_format_action) self.leftalign_format_action = QAction("Align Text Left", MainWindow) self.menu_format.addAction(self.leftalign_format_action) self.centeralign_format_action = QAction("Align Text Center", MainWindow) self.menu_format.addAction(self.centeralign_format_action) self.rightalign_format_action = QAction("Align Text Right", MainWindow) self.menu_format.addAction(self.rightalign_format_action) self.alignjustify_format_action = QAction("Align Text Justify", MainWindow) self.menu_format.addAction(self.alignjustify_format_action) # menubar export menu self.toolbar = QToolBar(MainWindow) MainWindow.addToolBar(self.toolbar) self.addnew = QAction(QIcon("icons/notebookgrey.png"), "Add New Nobebook", MainWindow) self.addnew.setShortcut('Ctrl+N') self.toolbar.addAction(self.addnew) self.addtab = QAction(QIcon("icons/tabtest"), "Add New Tab", MainWindow) self.addtab.setShortcut('Ctrl+T') self.toolbar.addAction(self.addtab) self.toolbar.addSeparator() self.saveAction = QAction(QIcon("icons/save.png"), "Save Current Note File", MainWindow) self.saveAction.setShortcut('Ctrl+S') self.toolbar.addAction(self.saveAction) self.newFile = QAction(QIcon("icons/new.png"), "Create New Note File", MainWindow) self.newFile.setShortcut('Ctrl+Shift+N') self.toolbar.addAction(self.newFile) self.openAction = QAction(QIcon("icons/open.png"), "open notes file", MainWindow) self.openAction.setShortcut('Ctrl+O') self.toolbar.addAction(self.openAction) self.toolbar.addSeparator() self.undoAction = QAction(QIcon("icons/undo.png"), "undo", MainWindow) self.undoAction.setShortcut('Ctrl+Z') self.toolbar.addAction(self.undoAction) self.redoAction = QAction(QIcon("icons/redo.png"), "redo", MainWindow) self.redoAction.setShortcut('Ctrl+Alt+Z') self.toolbar.addAction(self.redoAction) self.printcfg = QAction(QIcon("icons/pdf.png"), "print", MainWindow) self.toolbar.addAction(self.printcfg) self.toolbar.addSeparator() self.copyAction = QAction(QIcon("icons/copy.png"), "copy text", MainWindow) self.copyAction.setShortcut('Ctrl+C') self.toolbar.addAction(self.copyAction) self.pasteAction = QAction(QIcon("icons/paste.png"), "paste text", MainWindow) self.pasteAction.setShortcut('Ctrl+V') self.toolbar.addAction(self.pasteAction) self.cutAction = QAction(QIcon("icons/cut.png"), "cut text", MainWindow) self.cutAction.setShortcut('Ctrl+X') self.toolbar.addAction(self.cutAction) self.toolbar.addSeparator() self.leftAlign = QAction(QIcon("icons/alignleft.png"), "align left", MainWindow) self.toolbar.addAction(self.leftAlign) self.rightAlign = QAction(QIcon("icons/alignright.png"), "align right", MainWindow) self.toolbar.addAction(self.rightAlign) self.centerAlign = QAction(QIcon("icons/center.png"), "align center", MainWindow) self.toolbar.addAction(self.centerAlign) self.justifyAlign = QAction(QIcon("icons/justify.png"), "align justify", MainWindow) self.toolbar.addAction(self.justifyAlign) self.toolbar.addSeparator() self.dateAction = QAction(QIcon("icons/calendar.png"), "insert date", MainWindow) self.dateAction.setShortcut('Ctrl+Alt+D') self.toolbar.addAction(self.dateAction) self.timeAction = QAction(QIcon("icons/clock.png"), "insert time", MainWindow) self.timeAction.setShortcut('Ctrl+Alt+T') self.toolbar.addAction(self.timeAction) self.toolbar.addSeparator() self.bulletAction = QAction(QIcon("icons/bullets.png"), "insert bulleted list", MainWindow) self.bulletAction.setShortcut('Ctrl+B') self.toolbar.addAction(self.bulletAction) self.numberAction = QAction(QIcon("icons/numbers.png"), "insert numbered list", MainWindow) self.numberAction.setShortcut('Alt+N') self.toolbar.addAction(self.numberAction) self.toolbar.addSeparator() self.tableAction = QAction(QIcon("icons/table.png"), "insert table", MainWindow) self.tableAction.setShortcut('Ctrl+Shift+T') self.toolbar.addAction(self.tableAction) self.imageAction = QAction(QIcon("icons/image.png"), "insert image", MainWindow) self.imageAction.setShortcut('Ctrl+Alt+I') self.toolbar.addAction(self.imageAction) self.toolbar.addSeparator() self.fontcolorAction = QAction(QIcon("icons/fontcolor.png"), "Select font color", MainWindow) self.fontcolorAction.setShortcut('Ctrl+Shift+C') self.toolbar.addAction(self.fontcolorAction) self.fontBackgroundAction = QAction(QIcon("icons/highlight.png"), "Select font background color", MainWindow) self.fontBackgroundAction.setShortcut('Ctrl+Alt+C') self.toolbar.addAction(self.fontBackgroundAction) self.fontAction = QAction(QIcon("icons/text.png"), "Choose Font", MainWindow) self.fontAction.setShortcut('Ctrl+F') self.toolbar.addAction(self.fontAction) self.HRAction = QAction(QIcon("icons/hr.png"), "Insert Horizontal Rule", MainWindow) self.HRAction.setShortcut('Ctrl+L') self.toolbar.addAction(self.HRAction) self.central_widget = QWidget(MainWindow) self.central_widget.setObjectName('central') self.splitter = QSplitter(self.central_widget) self.splitter.setOrientation(Qt.Horizontal) self.splitter.setStretchFactor(0, 25) self.splitter.setStretchFactor(1, 75) self.list = QListWidget(self.splitter) self.list.setObjectName("List") self.list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) #self.list.setAlternatingRowColors(True) self.list.setAcceptDrops(True) self.list.setDragDropMode(QAbstractItemView.InternalMove) self.list.setDragEnabled(True) self.stack = QStackedWidget(self.splitter) self.stack.setObjectName("Stack") self.stack.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.listFrame = QFrame() self.stackFrame = QFrame() #maybe delete this self.splitter.addWidget(self.list) self.splitter.addWidget(self.stack) self.splitter.setSizes([50, 650]) #################################################################################################################### self.boxlayout = QHBoxLayout() self.central_widget.setLayout(self.boxlayout) MainWindow.setCentralWidget(self.central_widget) self.boxlayout.addWidget(self.splitter) MainWindow.show()
class MainGUI(QMainWindow): def __init__(self, logman, comment_mgr, val): logging.debug("MainGUI(): Instantiated") super(MainGUI, self).__init__() self.setWindowTitle('Traffic Annotation Workflow') self.setFixedSize(670,565) self.logman = logman self.comment_mgr = comment_mgr self.val = val self.project_sessions = ProjectSessions() self.cm = ConfigurationManager.get_instance() #shared data between widgets self.existingconfignames = {} self.logEnabled = '' self.closeConfirmed = '' self.newProject_pressed = False self.newPro = None #get project folder self.project_data_folder = self.cm.read_config_value("PROJECTS", "PROJECTS_BASE_PATH") self.createRequiredSubDirectories() self.at_start = True self.mainWidget = QWidget() self.setCentralWidget(self.mainWidget) mainlayout = QVBoxLayout() self.baseWidget = QWidget() #BaseWidget() self.annotateWidget = QWidget() self.resultsWidget = QWidget() self.projectTree = QtWidgets.QTreeWidget() self.baseWidgets = {} self.blankTreeContextMenu = {} quit = QAction("Quit", self) quit.triggered.connect(self.closeEvent) #Add tab widget - RES tabWidget = QtWidgets.QTabWidget() tabWidget.setGeometry(QtCore.QRect(0, 15, 668, 565)) tabWidget.setObjectName("tabWidget") #BaseWidget self.baseWidget.setWindowTitle("BaseWidget") self.baseWidget.setObjectName("BaseWidget") baseLayoutWidget = QtWidgets.QWidget() baseLayoutWidget.setObjectName("layoutWidget") self.baseOuterVertBox = QtWidgets.QVBoxLayout() self.baseOuterVertBox.setObjectName("outerVertBox") baseLayoutWidget.setLayout(self.baseOuterVertBox) self.baseWidget.setLayout(self.baseOuterVertBox) #Configuration window - RES ## windowBoxHLayout contains: ###projectTree (Left) ###basedataStackedWidget (Right) windowWidget = QtWidgets.QWidget() windowWidget.setObjectName("windowWidget") windowBoxHLayout = QtWidgets.QHBoxLayout() windowBoxHLayout.setObjectName("windowBoxHLayout") windowWidget.setLayout(windowBoxHLayout) self.projectTree.itemSelectionChanged.connect(self.onItemSelected) self.projectTree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.projectTree.customContextMenuRequested.connect(self.showContextMenu) self.projectTree.setEnabled(True) self.projectTree.setMaximumSize(200,521) self.projectTree.setObjectName("projectTree") self.projectTree.headerItem().setText(0, "Projects") self.projectTree.setSortingEnabled(False) windowBoxHLayout.addWidget(self.projectTree) self.basedataStackedWidget = QStackedWidget() self.basedataStackedWidget.setObjectName("basedataStackedWidget") windowBoxHLayout.addWidget(self.basedataStackedWidget) tabWidget.addTab(windowWidget, "Configuration") #ADD TAB WIDGET - RES self.initMenu() mainlayout = QVBoxLayout() mainlayout.addWidget(self.mainMenu) mainlayout.addWidget(tabWidget) self.mainWidget.setLayout(mainlayout) #load any saved projects self.load_saved() self.load_sessions() self.at_start = False logging.debug("MainWindow(): Complete") def createRequiredSubDirectories(self): logging.debug("MainApp:createRequiredSubDirectories() instantiated") if os.path.exists(self.project_data_folder) == False: try: os.makedirs(self.project_data_folder) except: logging.error("MainApp:createRequiredSubDirectories(): An error occured when trying to create project directories: ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) QMessageBox.error(self, "Create Error", "Could not create project subdirectories, quitting...", QMessageBox.Ok) exit() #RES Method def onItemSelected(self): logging.debug("MainApp:onItemSelected instantiated") # Get the selected item self.selectedItem = self.projectTree.currentItem() if self.selectedItem == None: logging.debug("MainApp:onItemSelected no configurations left") self.statusBar.showMessage("No configuration items selected or available.") return #Check if it's the case that an project name was selected parentSelectedItem = self.selectedItem.parent() if(parentSelectedItem == None): #A base widget was selected #logging.debug"PROJECT_WIDGET: " + str((self.baseWidgets[self.selectedItem.text(0)]["ProjectWidget"]))) self.basedataStackedWidget.setCurrentWidget(self.baseWidgets[self.selectedItem.text(0)]["ProjectWidget"]) else: #for children parentOfParent = parentSelectedItem.parent() #Check if it's the case that a Session Name was selected if(self.selectedItem.text(0)[0] == "S"): #logging.debug"SESSION_WIDGET: " + str(self.baseWidgets[parentSelectedItem.text(0)][self.selectedItem.text(0)]["SessionWidget"])) logging.debug("Setting right widget: " + str(self.baseWidgets[parentSelectedItem.text(0)][self.selectedItem.text(0)]["SessionWidget"])) self.basedataStackedWidget.setCurrentWidget(self.baseWidgets[parentSelectedItem.text(0)][self.selectedItem.text(0)]["SessionWidget"]) #Check if it's the case that a Annotate was selected elif(self.selectedItem.text(0)[0] == "A"): #logging.debug"ANNOTATE " + str(self.baseWidgets[parentOfParent.text(0)][parentSelectedItem.text(0)]["AnnotateWidget"])) logging.debug("Setting right widget: " + str(self.baseWidgets[parentOfParent.text(0)][parentSelectedItem.text(0)]["AnnotateWidget"])) self.basedataStackedWidget.setCurrentWidget(self.baseWidgets[parentOfParent.text(0)][parentSelectedItem.text(0)]["AnnotateWidget"]) #Check if it's the case that a Rules was selected elif(self.selectedItem.text(0)[0] == "R"): #logging.debug"RULES " + str(self.baseWidgets[parentOfParent.text(0)][parentSelectedItem.text(0)]["RulesWidget"])) logging.debug("Setting right widget: " + str(self.baseWidgets[parentOfParent.text(0)][parentSelectedItem.text(0)]["RulesWidget"])) self.basedataStackedWidget.setCurrentWidget(self.baseWidgets[parentOfParent.text(0)][parentSelectedItem.text(0)]["RulesWidget"]) #Check if it's the case that a Results was selected elif(self.selectedItem.text(0)[0] == "X"): #logging.debug"RESULTS " + str(self.baseWidgets[parentOfParent.text(0)][parentSelectedItem.text(0)]["ResultsWidget"])) logging.debug("Setting right widget: " + str(self.baseWidgets[parentOfParent.text(0)][parentSelectedItem.text(0)]["ResultsWidget"])) self.basedataStackedWidget.setCurrentWidget(self.baseWidgets[parentOfParent.text(0)][parentSelectedItem.text(0)]["ResultsWidget"]) def on_add_curation_clicked(self): logging.debug("on_add_curation_clicked(): Instantiated") selectedItem = self.projectTree.currentItem() self.nsd = NewSessionDialog(selectedItem.text(0)) projectSessions = [] for pot_session in self.baseWidgets[selectedItem.text(0)]: if pot_session.startswith("S:"): projectSessions.append(pot_session) if len(projectSessions) > 0: self.nsd.templateNameComboBox.addItems(projectSessions) self.nsd.templateNameComboBox.setEnabled(True) self.nsd.created.connect(self.session_created) self.nsd.setWindowModality(QtCore.Qt.ApplicationModal) self.nsd.show() def addSession(self, projectItem, sessionName): logging.debug("addSession(): Instantiated") projectName = projectItem.text(0) add_session_result = self.add_session_list(projectName, sessionName) if add_session_result == False: logging.error("An error occured when trying to add session to GUI: " + str(sessionName)) return else: sessionLabel = "S: " + sessionName #create tree widget item sessionItem = QtWidgets.QTreeWidgetItem(projectItem) sessionItem.setText(0,sessionLabel) sessionWidget = SessionWidget(sessionName) self.baseWidgets[projectName][sessionLabel] = {} #project name (Parent of Parent) + session name (parent of children) self.baseWidgets[projectName][sessionLabel]["SessionWidget"] = sessionWidget self.basedataStackedWidget.addWidget(sessionWidget) #create other widget items ##ANNOTATE annItem = QtWidgets.QTreeWidgetItem() annLabel = "A: " + "Annotate" annItem.setText(0, annLabel) sessionItem.addChild(annItem) self.annotateWidget = AnnotateWidget(self.project_data_folder, projectName, os.path.basename(self.existingconfignames[projectName]), sessionName, self.comment_mgr) #send project name for the corresponding directory self.baseWidgets[projectName][sessionLabel]["AnnotateWidget"] = self.annotateWidget #child self.basedataStackedWidget.addWidget(self.annotateWidget) ##RULES rulesItem = QtWidgets.QTreeWidgetItem() rulesLabel = "R: " + "Rules" rulesItem.setText(0, rulesLabel) sessionItem.addChild(rulesItem) #add the corresponding directory -- if it is already created, skip rulesDir = os.path.join(self.project_data_folder, projectName) rulesDir = os.path.join(rulesDir, ConfigurationManager.STRUCTURE_RULES_GEN_PATH) if os.path.exists(rulesDir) == False: os.mkdir(rulesDir) rulesWidget = RulesWidget(self.project_data_folder, projectName, os.path.basename(self.existingconfignames[projectName]), sessionName, rulesDir, self.comment_mgr, self.val) self.baseWidgets[projectName][sessionLabel]["RulesWidget"] = rulesWidget self.basedataStackedWidget.addWidget(rulesWidget) ##RESULTS resultsItem = QtWidgets.QTreeWidgetItem() resultsLabel = "X: " + "Results" resultsItem.setText(0, resultsLabel) sessionItem.addChild(resultsItem) #add the corresponding directory -- if it is already created, skip resultsDir = os.path.join(self.project_data_folder, projectName) resultsDir = os.path.join(resultsDir, "IDS-ALERTS") if os.path.exists(resultsDir) == False: os.mkdir(resultsDir) self.resultsWidget = ResultsWidget(self.project_data_folder, projectName, sessionName, resultsDir, self.val) self.baseWidgets[projectName][sessionLabel]["ResultsWidget"] = self.resultsWidget self.basedataStackedWidget.addWidget(self.resultsWidget) logging.debug("on_add_curation_clicked(): Completed") def on_export_clicked(self): #get project dir selectedItem = self.projectTree.currentItem() selectedItemName = selectedItem.text(0) project_folder = os.path.join(self.project_data_folder, selectedItemName) project_folder = os.path.abspath(project_folder) self.exportPro = ExportDialog(self, selectedItemName, project_folder).exec_() #self.exportPro.setWindowModality(QtCore.Qt.ApplicationModal) #self.exportPro.show() #RES METHOD def showContextMenu(self, position): logging.debug("MainApp:showContextMenu() instantiated: " + str(position)) if(self.projectTree.itemAt(position) == None): self.blankTreeContextMenu.popup(self.projectTree.mapToGlobal(position)) elif(self.projectTree.itemAt(position).parent() == None): self.projectContextMenu.popup(self.projectTree.mapToGlobal(position)) #RES METHOD def initMenu(self): logging.debug("MainApp:initMenu() instantiated") self.mainMenu = QMenuBar() self.fileMenu = self.mainMenu.addMenu("File") self.blankTreeContextMenu = QtWidgets.QMenu() self.newProjectContextMenu = QtWidgets.QMenu("New Project") self.blankTreeContextMenu.addMenu(self.newProjectContextMenu) self.fromCapture = self.newProjectContextMenu.addAction("Create Capture") self.fromCapture.triggered.connect(self.newFromCapture) self.fromPCAP = self.newProjectContextMenu.addAction("From PCAP") self.fromPCAP.triggered.connect(self.newFromPCAP) # Experiment context menu self.importContextMenu = QtWidgets.QMenu("Import Project") self.blankTreeContextMenu.addMenu(self.importContextMenu) self.fromFolderContextSubMenu = self.importContextMenu.addAction("From Folder") self.fromFolderContextSubMenu.triggered.connect(self.importFromFolder) self.fromZipContextSubMenu = self.importContextMenu.addAction("From Zip") self.fromZipContextSubMenu.triggered.connect(self.importFromZip) #Context menu project self.projectContextMenu = QtWidgets.QMenu() self.addCuration = self.projectContextMenu.addAction("Create curation session") self.addCuration.triggered.connect(self.on_add_curation_clicked) self.exportProject = self.projectContextMenu.addAction("Export project") self.exportProject.triggered.connect(self.on_export_clicked) self.quitAppMenuButton = QAction(QIcon(), "Quit", self) self.quitAppMenuButton.setShortcut("Ctrl+Q") self.quitAppMenuButton.setStatusTip("Quit App") self.quitAppMenuButton.triggered.connect(self.closeEvent) self.fileMenu.addAction(self.quitAppMenuButton) #Used to create a new project, this is where the prompt to write a name for the project is taken. def newFromCapture(self): logging.debug("MainApp:newFromCapture() instantiated") #Creating a custom widget to display what is needed for creating a new project: self.newPro = NewFromCollectDataDialog(self.logman, self.existingconfignames) #slots to receive data from the custom widget self.newPro.logEnabled.connect(self.log_enabled) self.newPro.created.connect(self.project_created) self.newPro.closeConfirmed.connect(self.close_confirmed) self.newProject_pressed = True self.newPro.setWindowModality(QtCore.Qt.ApplicationModal) self.newPro.show() def newFromPCAP(self): logging.debug("MainApp:newFromPCAP() instantiated") #Creating a custom widget to display what is needed for creating a new project: self.newCap = NewFromPCAPDialog(self.existingconfignames) #slot to receive data from the custom widget self.newCap.created.connect(self.project_created) self.newProject_pressed = True self.newCap.setWindowModality(QtCore.Qt.ApplicationModal) self.newCap.show() #Slot for when the user created the new project, path and configname @QtCore.pyqtSlot(str, dict, str) def project_created(self, configname, existingconfignames, path): #update project info with new info selected from widget self.existingconfignames = existingconfignames #create the new project with the updated information self.addProject(configname, self.existingconfignames[configname], path) @QtCore.pyqtSlot(str) def session_created(self, newsessionname): #call the function to add session to gui selectedProject = self.projectTree.currentItem() self.addSession(selectedProject, newsessionname) #Slot to let us know if the logging has started @QtCore.pyqtSlot(str) def log_enabled(self, status): self.logEnabled = status #Slot to let us know if the close has been confirmed or canceled @QtCore.pyqtSlot(str) def close_confirmed(self, status): self.closeConfirmed = status #Used to create a new project, and this is where the project will actually be populated def addProject(self, configname, projectPCAP, path): if configname in self.baseWidgets: logging.debug("Project already in tree: " + str(configname + "; skipping")) return #create the folders and files for new project if it's not already there: self.projectWidget = ProjectWidget(configname, projectPCAP, path) configTreeWidgetItem = QtWidgets.QTreeWidgetItem(self.projectTree) configTreeWidgetItem.setText(0,configname) self.projectWidget.addProjectItem(configname) #Add base info self.baseWidgets[configname] = {"BaseWidget": {}, "ProjectWidget": {}, "SessionWidget": {}, "AnnotateWidget": {}, "RulesWidget": {}, "ResultsWidget": {}} self.baseWidgets[configname]["BaseWidget"] = self.baseWidget self.basedataStackedWidget.addWidget(self.baseWidget) self.baseWidgets[configname]["ProjectWidget"] = self.projectWidget self.basedataStackedWidget.addWidget(self.projectWidget) self.basedataStackedWidget.addWidget(self.baseWidget) #add to list self.project_sessions.add_project(configname) def importFromZip(self): logging.debug("MainApp:importFromZip() instantiated") zip_file = QFileDialog() zip_file.setWindowTitle("Select File") zip_file.setFileMode(QtWidgets.QFileDialog.ExistingFile) zip_file.setNameFilter("Zip Files (*.zip)") filenames = zip_file.getOpenFileName() filename = filenames[0] if filename == "": logging.debug("File choose cancelled") return else: configname = os.path.basename(filename) configname = os.path.splitext(configname)[0] if configname in self.existingconfignames: QMessageBox.warning(self, "Name Exists", "A project with the same name already exists.", QMessageBox.Ok) return None else: #instance of package manage pack_mgr = PackageManager() self.populate_import(pack_mgr, configname, os.path.abspath(filename)) def importFromFolder(self, configname): logging.debug("MainApp:importFromFolder() instantiated") folder_chosen = str(QFileDialog.getExistingDirectory(self, "Select Directory to Store Data")) if folder_chosen == "": logging.debug("File choose cancelled") return if len(folder_chosen) > 0: baseNoExt = os.path.basename(folder_chosen) baseNoExt = os.path.splitext(baseNoExt)[0] configname = ''.join(e for e in baseNoExt if e.isalnum) if configname in self.existingconfignames: QMessageBox.warning(self, "Name Exists", "A project with the same name already exists.", QMessageBox.Ok) return None else: self.populate_import("dir", configname, folder_chosen) def populate_import(self, function, configname, from_file): importedProjectPath = os.path.join(self.project_data_folder, configname) #copy selected dir to new dir self.batch_thread = BatchThread() self.batch_thread.progress_signal.connect(self.update_progress_bar) self.batch_thread.completion_signal.connect(self.copy_dir_complete) if function == "dir": self.batch_thread.add_function(self.copy_dir, from_file, importedProjectPath) else: self.batch_thread.add_function(function.unzip, from_file, configname, self.project_data_folder) self.progress_dialog_overall = ProgressBarDialog(self, self.batch_thread.get_load_count()) self.batch_thread.start() self.progress_dialog_overall.show() def load_project_widgets(self): logging.debug("load_project_widgets(): instantiated") for name in self.existingconfignames: path = os.path.join(self.project_data_folder, name) projectPCAP = os.path.join(path, self.existingconfignames[name]) configname = name self.addProject(configname, projectPCAP, path) logging.debug("load_project_widgets(): Complete") def copy_dir(self, from_dir, to_dir): logging.debug("copy_dir(): copying selected directory") copy_tree(from_dir, to_dir) logging.debug("copy_dir(): copying complete") def copy_dir_complete(self): logging.debug("copy_dir_complete(): Instantiated") self.progress_dialog_overall.update_progress() self.progress_dialog_overall.hide() #Need to load projects (add to existing...) ##GET Project PCAP Name Here and also add to existingprojectnames self.load_saved() self.load_sessions() logging.debug("copy_dir_complete(): Complete") def load_saved(self): i = 0 #for each subdir, import the saved projects for (dirName, subdirlist, filelist) in os.walk(self.project_data_folder): for projectFolder in subdirlist: pcapSubdir = os.path.join(self.project_data_folder, projectFolder, ConfigurationManager.STRUCTURE_PCAP_SUBDIR) abspcapSubdir = os.path.abspath(pcapSubdir) if os.path.exists(abspcapSubdir): #go one level down #if this is the pcap directory, then check if a pcap exists #if so, this is a good project; create an entry in existingconfignames for (subdirName, subsubdirlist, subfilelist) in os.walk(abspcapSubdir): if len(subfilelist) == 1: filename = subfilelist[0] spt = os.path.splitext(filename) if spt[1] == ".pcap" or spt[1] == ".pcapng": self.existingconfignames[projectFolder] = filename break #once everything has been added, populate widget self.load_project_widgets() def load_sessions(self): for name in self.existingconfignames: #for already saved project project_path = os.path.join(self.project_data_folder, name) project_pcap_session = os.path.join(project_path, ConfigurationManager.STRUCTURE_PCAP_SUBDIR) if os.path.exists(project_pcap_session): paths, dirs, files = next(os.walk(project_pcap_session)) if len(dirs) > 0: self.traverse_sessions(name, project_pcap_session) def traverse_sessions(self, project_name, path): #if RULES dir exists in project folder, then sessions exists i = 0 for (dirName, subdirlist, filelist) in os.walk(path): for sessionName in subdirlist: if os.path.isfile(sessionName): #skip break elif self.add_session_list(project_name, sessionName) == True: self.add_session_widgets(project_name, self.existingconfignames[project_name], sessionName) def add_session_widgets(self, project_name, project_pcap_filename, sessionName): sessionLabel = "S: " + sessionName #create tree widget item selectedItem = self.projectTree.findItems(project_name, Qt.Qt.MatchContains) sessionItem = QtWidgets.QTreeWidgetItem(selectedItem[0]) sessionItem.setText(0,sessionLabel) sessionWidget = SessionWidget(sessionName) self.baseWidgets[project_name][sessionLabel] = {} #project name (Parent of Parent) + session name (parent of children) self.baseWidgets[project_name][sessionLabel]["SessionWidget"] = sessionWidget self.basedataStackedWidget.addWidget(sessionWidget) #create other widget items ##ANNOTATE annItem = QtWidgets.QTreeWidgetItem() annLabel = "A: " + "Annotate" annItem.setText(0, annLabel) sessionItem.addChild(annItem) self.annotateWidget = AnnotateWidget(self.project_data_folder, project_name, project_pcap_filename, sessionName, self.comment_mgr) #send project name for the corresponding directory self.baseWidgets[project_name][sessionLabel]["AnnotateWidget"] = self.annotateWidget #child self.basedataStackedWidget.addWidget(self.annotateWidget) ##RULES rulesItem = QtWidgets.QTreeWidgetItem() rulesLabel = "R: " + "Rules" rulesItem.setText(0, rulesLabel) sessionItem.addChild(rulesItem) #add the corresponding directory -- if it is already created, skip rulesDir = os.path.join(self.project_data_folder, project_name) rulesDir = os.path.join(rulesDir, ConfigurationManager.STRUCTURE_RULES_GEN_PATH) if os.path.exists(rulesDir) == False: os.mkdir(rulesDir) self.rulesWidget = RulesWidget(self.project_data_folder, project_name, project_pcap_filename, sessionName, rulesDir, self.comment_mgr, self.val) self.baseWidgets[project_name][sessionLabel]["RulesWidget"] = self.rulesWidget self.basedataStackedWidget.addWidget(self.rulesWidget) ##RESULTS resultsItem = QtWidgets.QTreeWidgetItem() resultsLabel = "X: " + "Results" resultsItem.setText(0, resultsLabel) sessionItem.addChild(resultsItem) #add the corresponding directory -- if it is already created, skip resultsDir = os.path.join(self.project_data_folder, project_name) resultsDir = os.path.join(resultsDir, "IDS-ALERTS") if os.path.exists(resultsDir) == False: os.mkdir(resultsDir) self.resultsWidget = ResultsWidget(self.project_data_folder, project_name, sessionName, resultsDir, self.val) self.baseWidgets[project_name][sessionLabel]["ResultsWidget"] = self.resultsWidget self.basedataStackedWidget.addWidget(self.resultsWidget) def add_session_list(self, project_name, project_session): #method returns true if session was successfully added success = self.project_sessions.add_project_session(project_name, project_session) if success == False: #self.project_sessions.print_d() return False else: #self.project_sessions.print_d() return True def update_progress_bar(self): logging.debug('update_progress_bar(): Instantiated') self.progress_dialog_overall.update_progress() logging.debug('update_progress_bar(): Complete') def closeEvent(self, event): logging.debug("closeEvent(): instantiated") self.quit_event = event if self.logEnabled == "TRUE": #This means that the new project widget is still running so call the close event #for that widget first to stop logger self.newPro.closeEvent(event) #Check if the close was confirmed or not if self.closeConfirmed == "TRUE": #after that's done, make sure to quit the app self.quit_event.accept() #self.close() qApp.quit() else: return else: close = QMessageBox.question(self, "QUIT", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No) if close == QMessageBox.Yes: #call the delete data function from new project, just to make sure #everything has been cleared out if self.newProject_pressed == True: if self.newPro != None: self.newPro.delete_data() qApp.quit() return elif close == QMessageBox.No and not type(self.quit_event) == bool: self.quit_event.ignore() pass return def quit_app(self): self.quit_event.accept() qApp.quit() return
class SettingsWindow(QDialog): def __init__(self): super().__init__() self.setWindowTitle('nParse Settings') layout = QVBoxLayout() top_layout = QHBoxLayout() self._list_widget = QListWidget() self._list_widget.setObjectName('SettingsList') self._list_widget.setSelectionMode(QListWidget.SingleSelection) self._list_widget.currentItemChanged.connect(self._switch_stack) self._widget_stack = QStackedWidget() self._widget_stack.setObjectName('SettingsStack') top_layout.addWidget(self._list_widget, 0) top_layout.addWidget(self._widget_stack, 1) settings = self._create_settings() if settings: for setting_name, stacked_widget in settings: self._list_widget.addItem(QListWidgetItem(setting_name)) self._widget_stack.addWidget(stacked_widget) self._list_widget.setCurrentRow(0) self._list_widget.setMaximumWidth( self._list_widget.minimumSizeHint().width()) self._list_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) buttons = QWidget() buttons.setObjectName('SettingsButtons') buttons_layout = QHBoxLayout() buttons_layout.setContentsMargins(0, 0, 0, 0) save_button = QPushButton('Save') save_button.setAutoDefault(False) save_button.clicked.connect(self._save) buttons_layout.addWidget(save_button) cancel_button = QPushButton('Cancel') cancel_button.setAutoDefault(False) cancel_button.clicked.connect(self._cancelled) buttons_layout.addWidget(cancel_button) buttons_layout.insertStretch(0) buttons.setLayout(buttons_layout) layout.addLayout(top_layout, 1) layout.addWidget(buttons, 0) self.setLayout(layout) self._set_values() def _save(self): for stacked_widget in self._widget_stack.findChildren(QFrame): for widget in stacked_widget.children(): wt = type(widget) if wt == QCheckBox: key1, key2 = widget.objectName().split(':') config.data[key1][key2] = widget.isChecked() elif wt == QSpinBox: key1, key2 = widget.objectName().split(':') config.data[key1][key2] = widget.value() elif wt == QLineEdit: key1, key2 = widget.objectName().split(':') config.data[key1][key2] = widget.text() config.save() self.accept() def _cancelled(self): self._set_values() self.reject() def showEvent(self, _): self._set_values() def closeEvent(self, _): self._set_values() self.reject() def _switch_stack(self): if self._list_widget.selectedIndexes(): self._widget_stack.setCurrentIndex(self._list_widget.currentRow()) def _set_values(self): for stacked_widget in self._widget_stack.findChildren(QFrame): for widget in stacked_widget.children(): wt = type(widget) if wt == QCheckBox: key1, key2 = widget.objectName().split(':') widget.setChecked(config.data[key1][key2]) elif wt == QSpinBox: key1, key2 = widget.objectName().split(':') widget.setValue(config.data[key1][key2]) elif wt == QLineEdit: key1, key2 = widget.objectName().split(':') widget.setText(config.data[key1][key2]) def _create_settings(self): stacked_widgets = [] # General Settings general_settings = QFrame() gsl = QFormLayout() gsl.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) gsl.addRow(SettingsHeader('general')) gsl_update_check = QCheckBox() gsl_update_check.setObjectName('general:update_check') gsl.addRow('Check for Updates', gsl_update_check) gsl.addRow(SettingsHeader('parsers')) gsl_opacity = QSpinBox() gsl_opacity.setRange(1, 100) gsl_opacity.setSingleStep(5) gsl_opacity.setSuffix('%') gsl_opacity.setObjectName('general:parser_opacity') gsl.addRow('Parser Window Opacity (% 1-100)', gsl_opacity) gsl_scaling = QSpinBox() gsl_scaling.setRange(100, 300) gsl_scaling.setSingleStep(5) gsl_scaling.setSuffix('%') gsl_scaling.setObjectName('general:qt_scale_factor') gsl.addRow('Window Scaling Factor', gsl_scaling) gsl.addRow(SettingsHeader('experimental')) gsl_enable_plugins = QCheckBox() gsl_enable_plugins.setObjectName('general:enable_plugins') gsl.addRow('Enable Plugins', gsl_enable_plugins) gsl_safe_mode = QCheckBox() gsl_safe_mode.setObjectName('general:safe_mode') gsl.addRow('Safe Mode', gsl_safe_mode) general_settings.setLayout(gsl) stacked_widgets.append(('General', general_settings)) # Spell Settings spells_settings = QFrame() ssl = QFormLayout() ssl.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) ssl.addRow(SettingsHeader('general')) ssl_casting_window = QCheckBox() ssl_casting_window.setWhatsThis(WHATS_THIS_CASTING_WINDOW) ssl_casting_window.setObjectName('spells:use_casting_window') ssl.addRow('Use Casting Window', ssl_casting_window) ssl_casting_window_buffer = QSpinBox() ssl_casting_window_buffer.setWhatsThis(WHATS_THIS_CASTING_BUFFER) ssl_casting_window_buffer.setRange(1, 4000) ssl_casting_window_buffer.setSingleStep(100) ssl_casting_window_buffer.setObjectName('spells:casting_window_buffer') ssl.addRow( 'Casting Window Buffer (msec 1-4000)', ssl_casting_window_buffer ) ssl_open_custom = QPushButton("Edit") ssl_open_custom.clicked.connect(self._get_custom_timers) row = ssl.addRow('Custom Timers', ssl_open_custom) ssl.addRow(SettingsHeader('experimental')) ssl_secondary_duration = QCheckBox() ssl_secondary_duration.setWhatsThis(WHATS_THIS_PVP_DURATION) ssl_secondary_duration.setObjectName('spells:use_secondary_all') ssl.addRow('Use PvP Durations', ssl_secondary_duration) ssl_save_spells = QCheckBox() ssl_save_spells.setObjectName('spells:save_spells') ssl.addRow('Save Spells Between Sessions', ssl_save_spells) spells_settings.setLayout(ssl) stacked_widgets.append(('Spells', spells_settings)) # caoilainn fork # log streaming push_settings = QFrame() push = QFormLayout() push.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) push.addRow(SettingsHeader('push notifications (experimental)')) push_enable = QCheckBox() push_enable.setWhatsThis(WHATS_THIS_PUSH_NOTIFICATIONS) push_enable.setObjectName('push:push_enabled') push.addRow('Use Push Notifications', push_enable) push_timer_expiry = QCheckBox() push_timer_expiry.setObjectName('push:timer_expiry') push.addRow('Push When Timer Expires', push_timer_expiry) push_afk_only = QCheckBox() push_afk_only.setObjectName('push:afk_only') push.addRow('Triggers Only When AFK', push_afk_only) push_timer_afk_only = QCheckBox() push_timer_afk_only.setObjectName('push:timer_expiry_afk_only') push.addRow('Timers Only When AFK', push_timer_afk_only) push_afk_idle_time = QSpinBox() push_afk_idle_time.setRange(0, 600) push_afk_idle_time.setSingleStep(1) push_afk_idle_time.setSuffix('s') push_afk_idle_time.setObjectName('push:idle_time_to_afk') push.addRow('Idle time to be AFK', push_afk_idle_time) push.addWidget(QLabel("You are always afk when using /afk.\n(0 to disable idle timer)")) push_api_key = QLineEdit() push_api_key.setMaxLength(512) push_api_key.setObjectName('push:prowl_api_key') push.addRow('Prowl API Key', push_api_key) push_edit_triggers = QPushButton("Edit") push_edit_triggers.clicked.connect(self._get_push_triggers) push.addRow('Push Triggers', push_edit_triggers) push_settings.setLayout(push) stacked_widgets.append(('Push', push_settings)) # Map Settings map_settings = QFrame() msl = QFormLayout() msl.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) msl.addRow(SettingsHeader('general')) msl_line_width = QSpinBox() msl_line_width.setObjectName('maps:line_width') msl_line_width.setRange(1, 10) msl_line_width.setSingleStep(1) msl.addRow('Map Line Width', msl_line_width) msl_grid_line_width = QSpinBox() msl_grid_line_width.setObjectName('maps:grid_line_width') msl_grid_line_width.setRange(1, 10) msl_grid_line_width.setSingleStep(1) msl.addRow('Grid Line Width', msl_grid_line_width) msl.addRow(SettingsHeader('z levels')) msl_current_z_alpha = QSpinBox() msl_current_z_alpha.setRange(1, 100) msl_current_z_alpha.setSingleStep(1) msl_current_z_alpha.setSuffix('%') msl_current_z_alpha.setObjectName('maps:current_z_alpha') msl.addRow('Current Z Opacity', msl_current_z_alpha) msl_closest_z_alpha = QSpinBox() msl_closest_z_alpha.setRange(1, 100) msl_closest_z_alpha.setSingleStep(1) msl_closest_z_alpha.setSuffix('%') msl_closest_z_alpha.setObjectName('maps:closest_z_alpha') msl.addRow('Closest Z Opacity', msl_closest_z_alpha) msl_other_z_alpha = QSpinBox() msl_other_z_alpha.setRange(1, 100) msl_other_z_alpha.setSingleStep(1) msl_other_z_alpha.setSuffix('%') msl_other_z_alpha.setObjectName('maps:other_z_alpha') msl.addRow('Other Z Opacity', msl_other_z_alpha) map_settings.setLayout(msl) stacked_widgets.append(('Maps', map_settings)) return stacked_widgets def _get_custom_timers(self): dialog = CustomTriggerSettings() dialog.exec() def _get_push_triggers(self): dialog = PushTriggerSettings() dialog.exec()
class MinWindow(Winform): def __init__(self, parent=None): super(MinWindow, self).__init__(parent) self.setWindowTitle('主窗口') self.resize(900, 600) self.center() # 创建主窗口 self.create_main_frame() self.add_button() # 创建菜单 self.create_menu() # 画出图像 self.on_draw() # 绑定所有事件 self.events_all_siganl_connect() def save_plot(self): # 保存当前matplotlib图像 file_choices = "PNG (*.png)|*.png" # path = QFileDialog.getSaveFileName(self, # 'Save file', '', # file_choices) # path = self.get_current_path() self.stack_tabWidget.currentWidget().mpl_nav_toolbar.save_figure() # if path: # print('保存啊') # # self.stack_tabWidget.currentWidget() # self.stack_tabWidget.currentWidget().mpl_nav_toolbar.save_figure() # print('保存了啊') # self.statusBar().showMessage('Saved to %s' % path, 2000) pass def create_menu(self): # 添加菜单栏 self.setCentralWidget(self.centralwidget) # 添加菜单栏 self.main_menubar = QtWidgets.QMenuBar() self.main_menubar.setGeometry(QtCore.QRect(0, 0, 800, 23)) self.main_menubar.setObjectName("main_menubar") self.menu = QtWidgets.QMenu(self.main_menubar) self.menu.setObjectName("menu") self.file_menu = QtWidgets.QMenu(self.main_menubar) self.file_menu.setObjectName("file_menu") self.save_menu = QtWidgets.QMenu(self.main_menubar) self.save_menu.setObjectName("save_menu") self.setMenuBar(self.main_menubar) self.statusbar = QtWidgets.QStatusBar() self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) # 添加状态栏 self.show_status_bar() # self.statusbar.showMessage("这是状态栏") self.plot_save_action = QAction(self) self.plot_save_action.setObjectName("plot_save_action") _translate = QtCore.QCoreApplication.translate self.menu.setTitle(_translate("MainWindow", "菜单")) self.file_menu.setTitle(_translate("MainWindow", "保存")) self.save_menu.setTitle(_translate("MainWindow", "保存图片")) self.plot_save_action.setText(_translate("MainWindow", "保存图片")) self.file_menu.addAction(self.plot_save_action) self.main_menubar.addAction(self.menu.menuAction()) self.main_menubar.addAction(self.file_menu.menuAction()) self.main_menubar.addAction(self.save_menu.menuAction()) self.retranslateUi() # 给菜单按钮添加绑定事件 # QtCore.QMetaObject.connectSlotsByName(self) save_file_action = self.create_action("&保存图像", shortcut="Ctrl+S", slot=self.save_plot, tip="Save the plot") quit_action = self.create_action("&Quit", slot=self.close, shortcut="Ctrl+Q", tip="Close the application") self.add_actions(self.file_menu, (save_file_action, None, quit_action)) pass def create_main_frame(self): # 窗口布局 # 添加主窗口 self.setObjectName("MainWindow") # self.layout = self.layout = QVBoxLayout(self) self.centralwidget = QtWidgets.QWidget() self.centralwidget.setObjectName("centralwidget") self.setCentralWidget(self.centralwidget) self.main_widget = QtWidgets.QWidget(self.centralwidget) self.main_widget.setGeometry(QtCore.QRect(10, 20, 761, 481)) self.main_widget.setObjectName("main_widget") # 此区域存放图像 self.stack_tabWidget = QtWidgets.QTabWidget(self.main_widget) self.stack_tabWidget.setGeometry(QtCore.QRect(30, 60, 721, 401)) self.stack_tabWidget.setObjectName("stack_tabWidget") # 此区域存放图像的工具栏 self.toolbar_stackedWidget = QStackedWidget(self.main_widget) self.toolbar_stackedWidget.setGeometry(QtCore.QRect(20, 0, 791, 71)) self.toolbar_stackedWidget.setObjectName("toolbar_stackedWidget") self.layout.addWidget(self.centralwidget) def on_draw(self): # 添加图像 self.draw_all_stack_tab() # 添加工具栏 self.set_all_stack_tab_toolbar() pass def create_status_bar(self): pass def create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: # action.setIcon(QIcon(":/%s.png" % button_icon)) pass if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) return action def add_actions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def add_button(self): self.save_pushButton = QtWidgets.QPushButton(self.centralwidget) self.save_pushButton.setGeometry(QtCore.QRect(800, 160, 75, 23)) self.save_pushButton.setObjectName("save_pushButton") pass def on_about(self): # 弹出关于此软件的信息 msg = """ A demo of using PyQt with matplotlib: * Use the matplotlib navigation bar * Add values to the text box and press Enter (or click "Draw") * Show or hide the grid * Drag the slider to modify the width of the bars * Save the plot to a file using the File menu * Click on a bar to receive an informative message """ QMessageBox.about(self, "About the demo", msg.strip()) def retranslateUi(self): # 设置各个菜单的名字 _translate = QtCore.QCoreApplication.translate self.setWindowTitle(_translate("MainWindow", "曲线翻页")) # self.stack_tabWidget.setTabText(self.stack_tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1")) # self.stack_tabWidget.setTabText(self.stack_tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2")) self.menu.setTitle(_translate("MainWindow", "菜单")) self.file_menu.setTitle(_translate("MainWindow", "保存")) self.save_menu.setTitle(_translate("MainWindow", "状态")) self.plot_save_action.setText(_translate("MainWindow", "保存图片")) self.save_pushButton.setText(_translate("MainWindow", "点击保存")) def draw_all_stack_tab(self): # 绘制所有图像 # 添加到stack_tabWidget上 # 创建matplot画布 self.tab1 = PlotCanvas(self, width=9, height=6, dpi=100) self.tab2 = PlotCanvas(self, width=9, height=6, dpi=100) self.tab3 = PlotCanvas(self, width=9, height=6, dpi=100) # mpl.draw_one_line() # 加载数据 # 在不同的画布上画出来 # 将所有f分页加入到tabWidget上 lines = load_all_lines() self.tab1.draw_one_line(lines[0]) self.tab2.draw_one_line(lines[1]) self.tab3.draw_one_line(lines[2]) # 将所有的tab添加到stack_tabWidget上 self.stack_tabWidget.addTab(self.tab1, 'td=0.12') self.stack_tabWidget.addTab(self.tab2, 'td=0.144') self.stack_tabWidget.addTab(self.tab3, 'td=0.176') pass def set_all_stack_tab_toolbar(self): # 添加图像的工具栏 所有的工具栏用容器toolbar_stackedWidget保存 self.add_stack_toolbar() self.tab1_ntb = NavigationToolbar(self.tab1, self.toolbar_page1) # 添加完整的 toolbar self.tab2_ntb = NavigationToolbar(self.tab2, self.toolbar_page2) # 添加完整的 toolbar self.tab3_ntb = NavigationToolbar(self.tab3, self.toolbar_page3) # 添加完整的 toolbar self.tab1.mpl_nav_toolbar = self.tab1_ntb self.tab2.mpl_nav_toolbar = self.tab2_ntb self.tab3.mpl_nav_toolbar = self.tab3_ntb # log('设置了的') pass def show_status_bar(self): # 添加状态栏 self.status_text = QLabel(" demo 状态栏") self.statusbar.addWidget(self.status_text, 1) def add_stack_toolbar(self): # 添加matplotlib的工具栏 # toolbar_stackedWidget # 创建QStackedWidget容器 将matplotlib所有图像的工具栏叠加放在一起 # self.toolbar_stackedWidget = QStackedWidget() # 创建不同的 QWidget保存单个matplotlib图像的工具栏 self.toolbar_page1 = QtWidgets.QWidget() self.toolbar_page1.setObjectName("toolbar_page1") self.toolbar_page2 = QtWidgets.QWidget() self.toolbar_page2.setObjectName("toolbar_page2") self.toolbar_page3 = QtWidgets.QWidget() self.toolbar_page3.setObjectName("toolbar_page3") # 初始化空白toolbar区域 # 添加三个空页 self.toolbar_stackedWidget.addWidget(self.toolbar_page1) self.toolbar_stackedWidget.addWidget(self.toolbar_page2) self.toolbar_stackedWidget.addWidget(self.toolbar_page3) pass def events_all_siganl_connect(self): # 连接所有的事件 # 切换tabWidget图像 显示 当前图像的toolbar self.stack_tabWidget.currentChanged.connect( self.event_change_toolbar_page) # 点击按钮 保存当前图像 self.save_pushButton.clicked.connect(self.save_plot) pass def event_change_toolbar_page(self): # 切换当前td图像触发 # 在toolbar_stackedWidget区域显示当前图像的matplotlib工具栏 # 获取当前的tab # log('点击了当前的widget') c = self.stack_tabWidget.currentIndex() # 设置当前stackWidget的当前 self.toolbar_stackedWidget.setCurrentIndex(c) # log("toolbar_stackedWidget 当前页面是({})".format(c)) # 设置当前的tool stackWidget的page pass def get_current_path(self): # 获取当前文件目录 paths = sys.path current_file = os.path.basename(__file__) for path in paths: try: if current_file in os.listdir(path): self.current_path = path break except (FileExistsError, FileNotFoundError) as e: print(e)
class Ui_MainWindow(object): def setupUi(self, MainWindow): self.MainWindow = MainWindow self.setupMainWindow() self.setupMenuBar() self.setupAjdustmentOptionBar() self.setupMainStack() self.shiftUi = Ui_ShiftWindow(self.shift_page) self.shiftUi.setupUi() self.perpetualUi = Ui_PerpetualWindow(self.perpetual_page) self.perpetualUi.setupUi() self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def setupMainWindow(self): self.MainWindow.setObjectName("MainWindow") self.MainWindow.resize(1500, 800) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth( self.MainWindow.sizePolicy().hasHeightForWidth()) self.MainWindow.setSizePolicy(sizePolicy) self.MainWindow.setMinimumSize(QtCore.QSize(1500, 800)) self.centralWidget = QWidget(self.MainWindow) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth( self.centralWidget.sizePolicy().hasHeightForWidth()) self.centralWidget.setSizePolicy(sizePolicy) self.centralWidget.setMinimumSize(QtCore.QSize(1500, 800)) self.centralWidget.setSizeIncrement(QtCore.QSize(5, 5)) self.centralWidget.setBaseSize(QtCore.QSize(5, 5)) self.centralWidget.setObjectName("centralWidget") self.MainWindow.setCentralWidget(self.centralWidget) self.statusBar = QStatusBar(self.MainWindow) self.statusBar.setObjectName("statusBar") self.MainWindow.setStatusBar(self.statusBar) self.toolBar = QToolBar(self.MainWindow) self.toolBar.setObjectName("toolBar") self.MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.outer_gridLayout = QGridLayout(self.centralWidget) self.outer_gridLayout.setSizeConstraint(QLayout.SetMinimumSize) self.outer_gridLayout.setContentsMargins(11, 6, 11, 0) self.outer_gridLayout.setSpacing(6) self.outer_gridLayout.setObjectName("outer_gridLayout") def setupMenuBar(self): self.menuBar = QMenuBar(self.MainWindow) self.menuBar.setGeometry(QtCore.QRect(0, 0, 942, 21)) self.menuBar.setObjectName("menuBar") self.MainWindow.setMenuBar(self.menuBar) self.menuLog = QMenu(self.menuBar) self.menuLog.setObjectName("menuLog") self.actionLog = QAction(self.MainWindow) self.actionLog.setObjectName("actionLog") self.menuLog.addAction(self.actionLog) self.menuBar.addAction(self.menuLog.menuAction()) _translate = QtCore.QCoreApplication.translate self.menuLog.setTitle(_translate("MainWindow", "Log")) self.actionLog.setText(_translate("MainWindow", "Show Log")) self.menuAbout = QMenu(self.menuBar) self.menuAbout.setObjectName("menuAbout") self.actionHelp = QAction(self.MainWindow) self.actionHelp.setObjectName("actionHelp") self.menuAbout.addAction(self.actionHelp) self.menuBar.addAction(self.menuAbout.menuAction()) _translate = QtCore.QCoreApplication.translate self.menuAbout.setTitle(_translate("MainWindow", "About")) self.actionHelp.setText(_translate("MainWindow", "Help")) def setupAjdustmentOptionBar(self): self.verticalWidget = QWidget(self.centralWidget) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth( self.verticalWidget.sizePolicy().hasHeightForWidth()) self.verticalWidget.setSizePolicy(sizePolicy) self.verticalWidget.setMinimumSize(QtCore.QSize(120, 0)) self.verticalWidget.setMaximumSize(QtCore.QSize(120, 16777215)) self.verticalWidget.setStyleSheet("background-color:darkgray") self.verticalWidget.setObjectName("verticalWidget") self.verticalLayout = QVBoxLayout(self.verticalWidget) self.verticalLayout.setContentsMargins(5, 65, 5, 11) self.verticalLayout.setSpacing(20) self.verticalLayout.setObjectName("verticalLayout") self.shift_button = QPushButton(self.verticalWidget) self.shift_button.setMinimumSize(QtCore.QSize(0, 100)) font = QtGui.QFont() font.setPointSize(11) font.setBold(True) font.setWeight(75) self.shift_button.setFont(font) self.shift_button.setObjectName("shift_button") self.shift_button.setCheckable(True) self.perpetual_button = QPushButton(self.verticalWidget) self.perpetual_button.setMinimumSize(QtCore.QSize(0, 100)) font = QtGui.QFont() font.setPointSize(11) font.setBold(True) font.setWeight(75) self.perpetual_button.setFont(font) self.perpetual_button.setCheckable(True) self.perpetual_button.setObjectName("perpetual_button") self.verticalLayout.addWidget(self.shift_button) self.verticalLayout.addWidget(self.perpetual_button) self.buttonGroup = QButtonGroup(self.verticalWidget) self.buttonGroup.addButton(self.shift_button) self.buttonGroup.addButton(self.perpetual_button) self.buttonGroup.setExclusive(True) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.verticalLayout.addItem(spacerItem) self.outer_gridLayout.addWidget(self.verticalWidget, 0, 0, 1, 1) def setupMainStack(self): self.shift_main_stacked = QStackedWidget(self.centralWidget) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth( self.shift_main_stacked.sizePolicy().hasHeightForWidth()) self.shift_main_stacked.setSizePolicy(sizePolicy) self.shift_main_stacked.setObjectName("shift_main_stacked") self.shift_page = QWidget() sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth( self.shift_page.sizePolicy().hasHeightForWidth()) self.shift_page.setSizePolicy(sizePolicy) self.shift_page.setObjectName("shift_page") self.shift_main_stacked.addWidget(self.shift_page) self.perpetual_page = QWidget() sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth( self.perpetual_page.sizePolicy().hasHeightForWidth()) self.perpetual_page.setSizePolicy(sizePolicy) self.perpetual_page.setObjectName("perpetual_page") self.shift_main_stacked.addWidget(self.perpetual_page) self.outer_gridLayout.addWidget(self.shift_main_stacked, 0, 1, 1, 1) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate self.MainWindow.setWindowTitle( _translate("MainWindow", "Continuous Contract Maker")) self.shift_button.setText( _translate("MainWindow", "Forward\n" "Backward")) self.perpetual_button.setText( _translate("MainWindow", "Perputual\n" " Series")) self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
class ConfigurationWidget(QWidget): """ Class implementing a dialog for the configuration of eric6. @signal preferencesChanged() emitted after settings have been changed @signal masterPasswordChanged(str, str) emitted after the master password has been changed with the old and the new password @signal accepted() emitted to indicate acceptance of the changes @signal rejected() emitted to indicate rejection of the changes """ preferencesChanged = pyqtSignal() masterPasswordChanged = pyqtSignal(str, str) accepted = pyqtSignal() rejected = pyqtSignal() DefaultMode = 0 HelpBrowserMode = 1 TrayStarterMode = 2 HexEditorMode = 3 def __init__(self, parent=None, fromEric=True, displayMode=DefaultMode, expandedEntries=[]): """ Constructor @param parent The parent widget of this dialog. (QWidget) @keyparam fromEric flag indicating a dialog generation from within the eric6 ide (boolean) @keyparam displayMode mode of the configuration dialog (DefaultMode, HelpBrowserMode, TrayStarterMode, HexEditorMode) @exception RuntimeError raised to indicate an invalid dialog mode @keyparam expandedEntries list of entries to be shown expanded (list of strings) """ assert displayMode in ( ConfigurationWidget.DefaultMode, ConfigurationWidget.HelpBrowserMode, ConfigurationWidget.TrayStarterMode, ConfigurationWidget.HexEditorMode, ) super(ConfigurationWidget, self).__init__(parent) self.fromEric = fromEric self.displayMode = displayMode self.__setupUi() self.itmDict = {} if not fromEric: from PluginManager.PluginManager import PluginManager try: self.pluginManager = e5App().getObject("PluginManager") except KeyError: self.pluginManager = PluginManager(self) e5App().registerObject("PluginManager", self.pluginManager) if displayMode == ConfigurationWidget.DefaultMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function 'create' to # create the configuration page. This must have the method # 'save' to save the settings. "applicationPage": [self.tr("Application"), "preferences-application.png", "ApplicationPage", None, None], "cooperationPage": [self.tr("Cooperation"), "preferences-cooperation.png", "CooperationPage", None, None], "corbaPage": [self.tr("CORBA"), "preferences-orbit.png", "CorbaPage", None, None], "emailPage": [self.tr("Email"), "preferences-mail_generic.png", "EmailPage", None, None], "graphicsPage": [self.tr("Graphics"), "preferences-graphics.png", "GraphicsPage", None, None], "hexEditorPage": [self.tr("Hex Editor"), "hexEditor.png", "HexEditorPage", None, None], "iconsPage": [self.tr("Icons"), "preferences-icons.png", "IconsPage", None, None], "ircPage": [self.tr("IRC"), "irc.png", "IrcPage", None, None], "logViewerPage": [self.tr("Log-Viewer"), "preferences-logviewer.png", "LogViewerPage", None, None], "mimeTypesPage": [self.tr("Mimetypes"), "preferences-mimetypes.png", "MimeTypesPage", None, None], "networkPage": [self.tr("Network"), "preferences-network.png", "NetworkPage", None, None], "notificationsPage": [self.tr("Notifications"), "preferences-notifications.png", "NotificationsPage", None, None], "pluginManagerPage": [self.tr("Plugin Manager"), "preferences-pluginmanager.png", "PluginManagerPage", None, None], "printerPage": [self.tr("Printer"), "preferences-printer.png", "PrinterPage", None, None], "pythonPage": [self.tr("Python"), "preferences-python.png", "PythonPage", None, None], "qtPage": [self.tr("Qt"), "preferences-qtlogo.png", "QtPage", None, None], "securityPage": [self.tr("Security"), "preferences-security.png", "SecurityPage", None, None], "shellPage": [self.tr("Shell"), "preferences-shell.png", "ShellPage", None, None], "tasksPage": [self.tr("Tasks"), "task.png", "TasksPage", None, None], "templatesPage": [self.tr("Templates"), "preferences-template.png", "TemplatesPage", None, None], "trayStarterPage": [self.tr("Tray Starter"), "erict.png", "TrayStarterPage", None, None], "vcsPage": [self.tr("Version Control Systems"), "preferences-vcs.png", "VcsPage", None, None], "0debuggerPage": [self.tr("Debugger"), "preferences-debugger.png", None, None, None], "debuggerGeneralPage": [self.tr("General"), "preferences-debugger.png", "DebuggerGeneralPage", "0debuggerPage", None], "debuggerPythonPage": [self.tr("Python"), "preferences-pyDebugger.png", "DebuggerPythonPage", "0debuggerPage", None], "debuggerPython3Page": [self.tr("Python3"), "preferences-pyDebugger.png", "DebuggerPython3Page", "0debuggerPage", None], "0editorPage": [self.tr("Editor"), "preferences-editor.png", None, None, None], "editorAPIsPage": [self.tr("APIs"), "preferences-api.png", "EditorAPIsPage", "0editorPage", None], "editorAutocompletionPage": [self.tr("Autocompletion"), "preferences-autocompletion.png", "EditorAutocompletionPage", "0editorPage", None], "editorAutocompletionQScintillaPage": [self.tr("QScintilla"), "qscintilla.png", "EditorAutocompletionQScintillaPage", "editorAutocompletionPage", None], "editorCalltipsPage": [self.tr("Calltips"), "preferences-calltips.png", "EditorCalltipsPage", "0editorPage", None], "editorCalltipsQScintillaPage": [self.tr("QScintilla"), "qscintilla.png", "EditorCalltipsQScintillaPage", "editorCalltipsPage", None], "editorGeneralPage": [self.tr("General"), "preferences-general.png", "EditorGeneralPage", "0editorPage", None], "editorFilePage": [self.tr("Filehandling"), "preferences-filehandling.png", "EditorFilePage", "0editorPage", None], "editorSearchPage": [self.tr("Searching"), "preferences-search.png", "EditorSearchPage", "0editorPage", None], "editorSpellCheckingPage": [self.tr("Spell checking"), "preferences-spellchecking.png", "EditorSpellCheckingPage", "0editorPage", None], "editorStylesPage": [self.tr("Style"), "preferences-styles.png", "EditorStylesPage", "0editorPage", None], "editorSyntaxPage": [self.tr("Code Checkers"), "preferences-debugger.png", "EditorSyntaxPage", "0editorPage", None], "editorTypingPage": [self.tr("Typing"), "preferences-typing.png", "EditorTypingPage", "0editorPage", None], "editorExportersPage": [self.tr("Exporters"), "preferences-exporters.png", "EditorExportersPage", "0editorPage", None], "1editorLexerPage": [self.tr("Highlighters"), "preferences-highlighting-styles.png", None, "0editorPage", None], "editorHighlightersPage": [self.tr("Filetype Associations"), "preferences-highlighter-association.png", "EditorHighlightersPage", "1editorLexerPage", None], "editorHighlightingStylesPage": [self.tr("Styles"), "preferences-highlighting-styles.png", "EditorHighlightingStylesPage", "1editorLexerPage", None], "editorKeywordsPage": [self.tr("Keywords"), "preferences-keywords.png", "EditorKeywordsPage", "1editorLexerPage", None], "editorPropertiesPage": [self.tr("Properties"), "preferences-properties.png", "EditorPropertiesPage", "1editorLexerPage", None], "1editorMouseClickHandlers": [self.tr("Mouse Click Handlers"), "preferences-mouse-click-handler.png", "EditorMouseClickHandlerPage", "0editorPage", None], "0helpPage": [self.tr("Help"), "preferences-help.png", None, None, None], "helpDocumentationPage": [self.tr("Help Documentation"), "preferences-helpdocumentation.png", "HelpDocumentationPage", "0helpPage", None], "helpViewersPage": [self.tr("Help Viewers"), "preferences-helpviewers.png", "HelpViewersPage", "0helpPage", None], "0projectPage": [self.tr("Project"), "preferences-project.png", None, None, None], "projectBrowserPage": [self.tr("Project Viewer"), "preferences-project.png", "ProjectBrowserPage", "0projectPage", None], "projectPage": [self.tr("Project"), "preferences-project.png", "ProjectPage", "0projectPage", None], "multiProjectPage": [self.tr("Multiproject"), "preferences-multiproject.png", "MultiProjectPage", "0projectPage", None], "0interfacePage": [self.tr("Interface"), "preferences-interface.png", None, None, None], "interfacePage": [self.tr("Interface"), "preferences-interface.png", "InterfacePage", "0interfacePage", None], "viewmanagerPage": [self.tr("Viewmanager"), "preferences-viewmanager.png", "ViewmanagerPage", "0interfacePage", None], } try: from PyQt5 import QtWebKit # __IGNORE_WARNING__ self.configItems.update({ "helpAppearancePage": [self.tr("Appearance"), "preferences-styles.png", "HelpAppearancePage", "0helpPage", None], "helpFlashCookieManagerPage": [self.tr("Flash Cookie Manager"), "flashCookie16.png", "HelpFlashCookieManagerPage", "0helpPage", None], "helpVirusTotalPage": [self.tr("VirusTotal Interface"), "virustotal.png", "HelpVirusTotalPage", "0helpPage", None], "helpWebBrowserPage": [self.tr("eric6 Web Browser"), "ericWeb.png", "HelpWebBrowserPage", "0helpPage", None], }) except ImportError: pass self.configItems.update( e5App().getObject("PluginManager").getPluginConfigData()) elif displayMode == ConfigurationWidget.HelpBrowserMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function 'create' to # create the configuration page. This must have the method # 'save' to save the settings. "interfacePage": [self.tr("Interface"), "preferences-interface.png", "HelpInterfacePage", None, None], "networkPage": [self.tr("Network"), "preferences-network.png", "NetworkPage", None, None], "printerPage": [self.tr("Printer"), "preferences-printer.png", "PrinterPage", None, None], "securityPage": [self.tr("Security"), "preferences-security.png", "SecurityPage", None, None], "0helpPage": [self.tr("Help"), "preferences-help.png", None, None, None], "helpDocumentationPage": [self.tr("Help Documentation"), "preferences-helpdocumentation.png", "HelpDocumentationPage", "0helpPage", None], } try: from PyQt5 import QtWebKit # __IGNORE_WARNING__ self.configItems.update({ "helpAppearancePage": [self.tr("Appearance"), "preferences-styles.png", "HelpAppearancePage", "0helpPage", None], "helpFlashCookieManagerPage": [self.tr("Flash Cookie Manager"), "flashCookie16.png", "HelpFlashCookieManagerPage", "0helpPage", None], "helpVirusTotalPage": [self.tr("VirusTotal Interface"), "virustotal.png", "HelpVirusTotalPage", "0helpPage", None], "helpWebBrowserPage": [self.tr("eric6 Web Browser"), "ericWeb.png", "HelpWebBrowserPage", "0helpPage", None], }) except ImportError: pass elif displayMode == ConfigurationWidget.TrayStarterMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function 'create' to # create the configuration page. This must have the method # 'save' to save the settings. "trayStarterPage": [self.tr("Tray Starter"), "erict.png", "TrayStarterPage", None, None], } elif displayMode == ConfigurationWidget.HexEditorMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function 'create' to # create the configuration page. This must have the method # 'save' to save the settings. "hexEditorPage": [self.tr("Hex Editor"), "hexEditor.png", "HexEditorPage", None, None], } else: raise RuntimeError("Illegal mode value: {0}".format(displayMode)) # generate the list entries self.__expandedEntries = [] for key in sorted(self.configItems.keys()): pageData = self.configItems[key] if pageData[3]: if pageData[3] in self.itmDict: pitm = self.itmDict[pageData[3]] # get the parent item else: continue else: pitm = self.configList self.itmDict[key] = ConfigurationPageItem(pitm, pageData[0], key, pageData[1]) self.itmDict[key].setData(0, Qt.UserRole, key) if (not self.fromEric or displayMode != ConfigurationWidget.DefaultMode or key in expandedEntries): self.itmDict[key].setExpanded(True) self.configList.sortByColumn(0, Qt.AscendingOrder) # set the initial size of the splitter self.configSplitter.setSizes([200, 600]) self.configList.itemActivated.connect(self.__showConfigurationPage) self.configList.itemClicked.connect(self.__showConfigurationPage) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.rejected) if displayMode in [ConfigurationWidget.HelpBrowserMode, ConfigurationWidget.TrayStarterMode, ConfigurationWidget.HexEditorMode]: self.configListSearch.hide() if displayMode not in [ConfigurationWidget.TrayStarterMode, ConfigurationWidget.HexEditorMode]: self.__initLexers() def accept(self): """ Public slot to accept the buttonBox accept signal. """ if not isMacPlatform(): wdg = self.focusWidget() if wdg == self.configList: return self.accepted.emit() def __setupUi(self): """ Private method to perform the general setup of the configuration widget. """ self.setObjectName("ConfigurationDialog") self.resize(900, 650) self.verticalLayout_2 = QVBoxLayout(self) self.verticalLayout_2.setSpacing(6) self.verticalLayout_2.setContentsMargins(6, 6, 6, 6) self.verticalLayout_2.setObjectName("verticalLayout_2") self.configSplitter = QSplitter(self) self.configSplitter.setOrientation(Qt.Horizontal) self.configSplitter.setObjectName("configSplitter") self.configListWidget = QWidget(self.configSplitter) self.leftVBoxLayout = QVBoxLayout(self.configListWidget) self.leftVBoxLayout.setContentsMargins(0, 0, 0, 0) self.leftVBoxLayout.setSpacing(0) self.leftVBoxLayout.setObjectName("leftVBoxLayout") self.configListSearch = E5ClearableLineEdit( self, self.tr("Enter search text...")) self.configListSearch.setObjectName("configListSearch") self.leftVBoxLayout.addWidget(self.configListSearch) self.configList = QTreeWidget() self.configList.setObjectName("configList") self.leftVBoxLayout.addWidget(self.configList) self.configListSearch.textChanged.connect(self.__searchTextChanged) self.scrollArea = QScrollArea(self.configSplitter) self.scrollArea.setFrameShape(QFrame.NoFrame) self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scrollArea.setWidgetResizable(False) self.scrollArea.setObjectName("scrollArea") self.configStack = QStackedWidget() self.configStack.setFrameShape(QFrame.Box) self.configStack.setFrameShadow(QFrame.Sunken) self.configStack.setObjectName("configStack") self.scrollArea.setWidget(self.configStack) self.emptyPage = QWidget() self.emptyPage.setGeometry(QRect(0, 0, 372, 591)) self.emptyPage.setObjectName("emptyPage") self.vboxlayout = QVBoxLayout(self.emptyPage) self.vboxlayout.setSpacing(6) self.vboxlayout.setContentsMargins(6, 6, 6, 6) self.vboxlayout.setObjectName("vboxlayout") spacerItem = QSpacerItem( 20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.vboxlayout.addItem(spacerItem) self.emptyPagePixmap = QLabel(self.emptyPage) self.emptyPagePixmap.setAlignment(Qt.AlignCenter) self.emptyPagePixmap.setObjectName("emptyPagePixmap") self.emptyPagePixmap.setPixmap( QPixmap(os.path.join(getConfig('ericPixDir'), 'eric.png'))) self.vboxlayout.addWidget(self.emptyPagePixmap) self.textLabel1 = QLabel(self.emptyPage) self.textLabel1.setAlignment(Qt.AlignCenter) self.textLabel1.setObjectName("textLabel1") self.vboxlayout.addWidget(self.textLabel1) spacerItem1 = QSpacerItem( 20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.vboxlayout.addItem(spacerItem1) self.configStack.addWidget(self.emptyPage) self.verticalLayout_2.addWidget(self.configSplitter) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.Apply | QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.Reset) self.buttonBox.setObjectName("buttonBox") if not self.fromEric and \ self.displayMode == ConfigurationWidget.DefaultMode: self.buttonBox.button(QDialogButtonBox.Apply).hide() self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False) self.verticalLayout_2.addWidget(self.buttonBox) self.setWindowTitle(self.tr("Preferences")) self.configList.header().hide() self.configList.header().setSortIndicator(0, Qt.AscendingOrder) self.configList.setSortingEnabled(True) self.textLabel1.setText( self.tr("Please select an entry of the list \n" "to display the configuration page.")) QMetaObject.connectSlotsByName(self) self.setTabOrder(self.configList, self.configStack) self.configStack.setCurrentWidget(self.emptyPage) self.configList.setFocus() def __searchTextChanged(self, text): """ Private slot to handle a change of the search text. @param text text to search for (string) """ self.__searchChildItems(self.configList.invisibleRootItem(), text) def __searchChildItems(self, parent, text): """ Private method to enable child items based on a search string. @param parent reference to the parent item (QTreeWidgetItem) @param text text to search for (string) @return flag indicating an enabled child item (boolean) """ childEnabled = False text = text.lower() for index in range(parent.childCount()): itm = parent.child(index) if itm.childCount() > 0: enable = self.__searchChildItems(itm, text) or \ text == "" or text in itm.text(0).lower() else: enable = text == "" or text in itm.text(0).lower() if enable: childEnabled = True itm.setDisabled(not enable) return childEnabled def __initLexers(self): """ Private method to initialize the dictionary of preferences lexers. """ import QScintilla.Lexers from .PreferencesLexer import PreferencesLexer, \ PreferencesLexerLanguageError self.lexers = {} for language in QScintilla.Lexers.getSupportedLanguages(): if language not in self.lexers: try: self.lexers[language] = PreferencesLexer(language, self) except PreferencesLexerLanguageError: pass def __importConfigurationPage(self, name): """ Private method to import a configuration page module. @param name name of the configuration page module (string) @return reference to the configuration page module """ modName = "Preferences.ConfigurationPages.{0}".format(name) try: mod = __import__(modName) components = modName.split('.') for comp in components[1:]: mod = getattr(mod, comp) return mod except ImportError: E5MessageBox.critical( self, self.tr("Configuration Page Error"), self.tr("""<p>The configuration page <b>{0}</b>""" """ could not be loaded.</p>""").format(name)) return None def __showConfigurationPage(self, itm, column): """ Private slot to show a selected configuration page. @param itm reference to the selected item (QTreeWidgetItem) @param column column that was selected (integer) (ignored) """ pageName = itm.getPageName() self.showConfigurationPageByName(pageName, setCurrent=False) def __initPage(self, pageData): """ Private method to initialize a configuration page. @param pageData data structure for the page to initialize @return reference to the initialized page """ page = None if isinstance(pageData[2], types.FunctionType): page = pageData[2](self) else: mod = self.__importConfigurationPage(pageData[2]) if mod: page = mod.create(self) if page is not None: self.configStack.addWidget(page) pageData[-1] = page try: page.setMode(self.displayMode) except AttributeError: pass return page def showConfigurationPageByName(self, pageName, setCurrent=True): """ Public slot to show a named configuration page. @param pageName name of the configuration page to show (string) @param setCurrent flag indicating to set the current item (boolean) """ if pageName == "empty" or pageName not in self.configItems: page = self.emptyPage else: pageData = self.configItems[pageName] if pageData[-1] is None and pageData[2] is not None: # the page was not loaded yet, create it page = self.__initPage(pageData) else: page = pageData[-1] if page is None: page = self.emptyPage elif setCurrent: items = self.configList.findItems( pageData[0], Qt.MatchFixedString | Qt.MatchRecursive) for item in items: if item.data(0, Qt.UserRole) == pageName: self.configList.setCurrentItem(item) self.configStack.setCurrentWidget(page) ssize = self.scrollArea.size() if self.scrollArea.horizontalScrollBar(): ssize.setHeight( ssize.height() - self.scrollArea.horizontalScrollBar().height() - 2) if self.scrollArea.verticalScrollBar(): ssize.setWidth( ssize.width() - self.scrollArea.verticalScrollBar().width() - 2) psize = page.minimumSizeHint() self.configStack.resize(max(ssize.width(), psize.width()), max(ssize.height(), psize.height())) if page != self.emptyPage: page.polishPage() self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(True) else: self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False) # reset scrollbars for sb in [self.scrollArea.horizontalScrollBar(), self.scrollArea.verticalScrollBar()]: if sb: sb.setValue(0) self.__currentConfigurationPageName = pageName def getConfigurationPageName(self): """ Public method to get the page name of the current page. @return page name of the current page (string) """ return self.__currentConfigurationPageName def calledFromEric(self): """ Public method to check, if invoked from within eric. @return flag indicating invocation from within eric (boolean) """ return self.fromEric def getPage(self, pageName): """ Public method to get a reference to the named page. @param pageName name of the configuration page (string) @return reference to the page or None, indicating page was not loaded yet """ return self.configItems[pageName][-1] def getLexers(self): """ Public method to get a reference to the lexers dictionary. @return reference to the lexers dictionary """ return self.lexers def setPreferences(self): """ Public method called to store the selected values into the preferences storage. """ for key, pageData in list(self.configItems.items()): if pageData[-1]: pageData[-1].save() # page was loaded (and possibly modified) QApplication.processEvents() # ensure HMI is responsive def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. @param button button that was clicked (QAbstractButton) """ if button == self.buttonBox.button(QDialogButtonBox.Apply): self.on_applyButton_clicked() elif button == self.buttonBox.button(QDialogButtonBox.Reset): self.on_resetButton_clicked() @pyqtSlot() def on_applyButton_clicked(self): """ Private slot called to apply the settings of the current page. """ if self.configStack.currentWidget() != self.emptyPage: page = self.configStack.currentWidget() savedState = page.saveState() page.save() self.preferencesChanged.emit() if savedState is not None: page.setState(savedState) page.polishPage() @pyqtSlot() def on_resetButton_clicked(self): """ Private slot called to reset the settings of the current page. """ if self.configStack.currentWidget() != self.emptyPage: currentPage = self.configStack.currentWidget() savedState = currentPage.saveState() pageName = self.configList.currentItem().getPageName() self.configStack.removeWidget(currentPage) if pageName == "editorHighlightingStylesPage": self.__initLexers() self.configItems[pageName][-1] = None self.showConfigurationPageByName(pageName) if savedState is not None: self.configStack.currentWidget().setState(savedState) def getExpandedEntries(self): """ Public method to get a list of expanded entries. @return list of expanded entries (list of string) """ return self.__expandedEntries @pyqtSlot(QTreeWidgetItem) def on_configList_itemCollapsed(self, item): """ Private slot handling a list entry being collapsed. @param item reference to the collapsed item (QTreeWidgetItem) """ pageName = item.data(0, Qt.UserRole) if pageName in self.__expandedEntries: self.__expandedEntries.remove(pageName) @pyqtSlot(QTreeWidgetItem) def on_configList_itemExpanded(self, item): """ Private slot handling a list entry being expanded. @param item reference to the expanded item (QTreeWidgetItem) """ pageName = item.data(0, Qt.UserRole) if pageName not in self.__expandedEntries: self.__expandedEntries.append(pageName)