class MainApp(QMainWindow): def __init__(self): super(MainApp, self).__init__() # App metadata self.setWindowTitle('Alice Installer') self.setWindowIcon(QIcon(PATH + '/images/icon.png')) self.setWindowFlags(Qt.WindowCloseButtonHint) self.setFixedSize(800, 400) self.load_fonts() # Set central widget and init ui self.central_widget = QWidget(self) self.central_widget.resize(self.frameSize()) self.initUI() def initUI(self): self.stacked_widget = QStackedWidget(self.central_widget) self.stacked_widget.resize(self.frameSize()) self.stacked_widget.setAutoFillBackground(False) self.stacked_widget.setStyleSheet('background-color: #111118;') # Import activities and add to stack self.start_app = StartApp(self) self.install_window = InstallWindow(self) self.install_complete = InstallComplete(self) self.stacked_widget.addWidget(self.start_app) self.stacked_widget.addWidget(self.install_window) self.stacked_widget.addWidget(self.install_complete) # Activities Triggers self.start_app.install.clicked.connect(lambda: self.switch_layout(1)) def load_fonts(self, path=PATH + '/fonts/'): fonts = [f for f in listdir(path) if isfile(join(path, f))] self.font_db = {} # For each font finded in /fonts add to Application and create a directory of fonts for font in fonts: self.font_id = QFontDatabase.addApplicationFont(path + font) self.font_db[font.replace("-", " ")[:-4]] = self.font_id def set_font(self, font_name, font_size): selected_font = QFontDatabase.applicationFontFamilies( self.font_db[font_name]) font = QFont() font.setFamily(selected_font[0]) font.setPointSize(int(font_size)) return font def switch_layout(self, index): self.stacked_widget.setCurrentIndex(index)
class LeftTabWidget(QWidget): '''左侧选项栏''' def __init__(self): super(LeftTabWidget, self).__init__() self.setObjectName('LeftTabWidget') self.resize(800,600) self.setWindowTitle('LeftTabWidget') #with open('D:/python/code/qt/test/QSS/QListWidgetQSS.qss', 'r') as f: #导入QListWidget的qss样式 # self.list_style = f.read() self.main_layout = QHBoxLayout(self, spacing=0) #窗口的整体布局 self.main_layout.setContentsMargins(0,0,0,0) self.left_widget = QListWidget() #左侧选项列表 self.right_widget = QStackedWidget() #右侧 #self.left_widget.setStyleSheet(self.list_style) self.left_widget.setGeometry(0,0,0,0) self.main_layout.addWidget(self.left_widget) self.main_layout.addWidget(self.right_widget) self.left_widget.setFixedWidth(180) self.right_widget.resize(620,600) 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) self.left_widget list_str = ['热点分析','关键词提醒','群发助手','单项好友删除'] #url_list = ['job_num_wordcloud.html', 'edu_need.html', 'salary_bar.html', 'edu_salary_bar.html'] self.func1Page = QWidget() self.func2Page = QWidget() self.func3Page = QWidget() self.func4Page = QWidget() label1 = QLabel('热点分析') label2 = QLabel('关键词提醒') label3 = QLabel('群发助手') label4 = QLabel('单项好友删除') for i in range(4): self.item = QListWidgetItem(list_str[i],self.left_widget) #左侧选项的添加 self.item.setSizeHint(QSize(180,80)) self.item.setTextAlignment(Qt.AlignCenter) #居中显示
class LeftTabWidget(QWidget): '''左侧选项栏''' def __init__(self): super(LeftTabWidget, self).__init__() self.setObjectName('LeftTabWidget') self.resize(800, 600) #self.setWindowTitle('LeftTabWidget') self.main_layout = QHBoxLayout(self, spacing=0) #窗口的整体布局 self.main_layout.setContentsMargins(0, 0, 0, 0) self.left_widget = QListWidget() #左侧选项列表 self.left_widget.setMaximumWidth(180) self.main_layout.addWidget(self.left_widget) self.right_widget = QStackedWidget() self.right_widget.resize(620, 600) 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) list_str = ['创建', '发布', '开奖'] for i in range(3): self.item = QListWidgetItem(list_str[i], self.left_widget) #左侧选项的添加 self.item.setSizeHint(QSize(30, 60)) self.item.setTextAlignment(Qt.AlignCenter) #居中显示 #self.browser = QWebView() #右侧用QWebView来显示html网页 #self.browser.setUrl(QUrl.fromLocalFile('D://python//code//vision//%s' % url_list[i])) button = QPushButton() button.setFixedSize(100, 60) button.setText("创建\n新的抽奖") button.setGeometry(400, 100, 100, 60) self.right_widget.addWidget(button)
if 0 <= v < 10 and 0 <= u < 10: if str(self.map.item(v, u).text()) == '.': self.map.setItem(v, u, new_cell_mul()) if __name__ == '__main__': # Дописать app = QApplication(sys.argv) loading_window = LoadingMain() startmenu_window = StartMenuMain() settings_window = SettingsMain() rules_window = RulesMain() ready_window = ReadyMain() pvp_window = PVPMain() win_window = WinMain() windows = QStackedWidget() windows.addWidget(loading_window) # 0 windows.addWidget(startmenu_window) # 1 windows.addWidget(settings_window) # 2 windows.addWidget(rules_window) # 3 windows.addWidget(ready_window) # 4 windows.addWidget(pvp_window) # 5 windows.addWidget(win_window) # 6 windows.setWindowTitle("SEA BATTLE") windows.setWindowIcon(QIcon("images/icon.svg")) windows.resize(*SCREEN_SIZE[0]) windows.show() sys.exit(app.exec())
class AppWindow(QMainWindow): # uses the init method to setup the window GUI, with the passed in width and height def __init__(self, width, height, reddit, *args, **kwargs): self.reddit = reddit super(AppWindow, self).__init__(*args, **kwargs) self.setMouseTracking(True) self.window_width = width self.window_height = height self.submenus = [] # sets the title to the application window self.setWindowTitle("Subreddit Scanner") # add the vertical layout vlayout = QVBoxLayout() # adds the necessary buttons for each functionality of the application self.add_buttons(vlayout) # adds a dummy widget so it can be added as the central widget to the QMainWindow menu_widget = QWidget() menu_widget.setLayout(vlayout) central_widget = QWidget(self) self.widget_stack = QStackedWidget(central_widget) self.widget_stack.resize(self.window_width, self.window_height) self.widget_stack.addWidget(menu_widget) self.add_widgets() self.setCentralWidget(central_widget) # adds all of the widgets to the app that correspond to the buttons def add_widgets(self): widget_control = WidgetCreator(self.reddit, self.back_clicked) self.widget_stack.addWidget(widget_control.make_create_menu()) self.widget_stack.addWidget(widget_control.make_backup_menu()) self.widget_stack.addWidget(widget_control.make_mimic_menu()) self.widget_stack.addWidget(widget_control.make_save_menu()) self.widget_stack.addWidget(widget_control.make_unsave_menu()) # method that switches the top widget to the main menu def back_clicked(self): self.widget_stack.setCurrentIndex(0) # method that switches the top widget to that of create def create_clicked(self): self.widget_stack.setCurrentIndex(1) # method that switches the top widget to that of backup def backup_clicked(self): self.widget_stack.setCurrentIndex(2) # method that switches the top widget to that of mimic def mimic_clicked(self): self.widget_stack.setCurrentIndex(3) # method that switches the top widget to that of save def save_clicked(self): self.widget_stack.setCurrentIndex(4) # method that switches the top widget to that of unsave def unsave_clicked(self): self.widget_stack.setCurrentIndex(5) # method that exits the application when clicked def quit_clicked(self): sys.exit(0) # method that adds all the buttons on the main menu def add_buttons(self, vlayout): # first creates a list of buttons to add button_names = [ "Create", "Backup", "Mimic", "Save Hot Items", "Unsave", "Quit" ] button_methods = [ self.create_clicked, self.backup_clicked, self.mimic_clicked, self.save_clicked, self.unsave_clicked, self.quit_clicked ] button_spacing = 20 # then calculates the theoretical maximum button height button_height = ( self.window_height - (len(button_names) * button_spacing)) / len(button_names) button_width = 150 current_hlayout = QHBoxLayout() current_hlayout.setAlignment(QtCore.Qt.AlignCenter) current_line_buttons = 0 # and then a button for each button name in the list is created, aligned to the center of the layout for i in range(0, len(button_names)): button = QPushButton(button_names[i]) button.setFixedSize(button_width, min(button_height, 80)) button.clicked.connect(button_methods[i]) if (current_line_buttons * button_spacing) + ( (current_line_buttons + 1) * button_width) > self.window_width: vlayout.addLayout(current_hlayout) current_hlayout = QHBoxLayout() current_hlayout.setAlignment(QtCore.Qt.AlignCenter) current_line_buttons = 0 current_hlayout.addWidget(button, alignment=QtCore.Qt.AlignCenter) current_line_buttons += 1 vlayout.addLayout(current_hlayout) vlayout.setAlignment(QtCore.Qt.AlignCenter) vlayout.setSpacing(button_spacing)
class NavigationInterface(QWidget): """ 导航界面 """ def __init__(self, contactInfo_list: List[Dict[str, str]], parent=None): super().__init__(parent=parent) # 读取用户信息 self.userInfo = getUserInfo() # 实例化小部件 self.searchLineEdit = SearchLineEdit(self) self.__createButtons() self.userNameLabel = QLabel(self) self.personalSignatureLabel = QLabel(self) self.headPortraitWidget = HeadPortrait( self.userInfo['headPortraitPath'], (45, 45), self) self.stackedWidget = QStackedWidget(self) self.chatListWidget = ChatListWidget(self) self.contactInterface = ContactInterface(contactInfo_list, self) self.stateWidget = StateWidget(parent=self) # 界面字典 self.__interface_dict = { 0: self.chatListWidget, 1: self.contactInterface } # 初始化界面 self.__initWidget() def __initWidget(self): """ 初始化界面 """ self.setFixedWidth(402) self.resize(402, 917) self.stateWidget.move(40, 40) self.dialsButton.move(351, 70) self.searchButton.move(22, 83) self.stackedWidget.move(0, 183) self.userNameLabel.move(67, 13) self.searchLineEdit.move(10, 70) self.headPortraitWidget.move(10, 10) self.moreActionsButton.move(351, 11) self.personalSignatureLabel.move(67, 33) self.chatButton.move(38, 127) self.noticeButton.move(340, 127) self.contactButton.move(233, 127) self.conversationButton.move(138, 127) # 将子窗口添加到层叠窗口中 self.stackedWidget.addWidget(self.chatListWidget) self.stackedWidget.addWidget(self.contactInterface) self.chatButton.setSelected(True) # 设置层叠样式 self.setAttribute(Qt.WA_StyledBackground) self.setObjectName('navigationInterface') self.userNameLabel.setObjectName('userNameLabel') self.personalSignatureLabel.setObjectName('personalSignatureLabel') self.__setQss() # 调整个新签名和用户名长度 self.__setLabelText() # 信号连接到槽函数 self.__connectSignalToSlot() def __createButtons(self): """ 创建按钮 """ opacity_dict = {'normal': 1, 'hover': 0.72, 'pressed': 0.2} chatButtonIconPath_dict = { 'normal': r'app\resource\Image\navigation_interface\聊天_normal.png', 'hover': r'app\resource\Image\navigation_interface\聊天_hover.png', 'selected': r'app\resource\Image\navigation_interface\聊天_selected.png', } conversationButtonIconPath_dict = { 'normal': r'app\resource\Image\navigation_interface\通话_normal.png', 'hover': r'app\resource\Image\navigation_interface\通话_hover.png', 'selected': r'app\resource\Image\navigation_interface\通话_selected.png', } contactsButtonIconPath_dict = { 'normal': r'app\resource\Image\navigation_interface\联系人_normal.png', 'hover': r'app\resource\Image\navigation_interface\联系人_hover.png', 'selected': r'app\resource\Image\navigation_interface\联系人_selected.png', } noticeButtonIconPath_dict = { 'normal': r'app\resource\Image\navigation_interface\通知_normal.png', 'hover': r'app\resource\Image\navigation_interface\通知_hover.png', 'selected': r'app\resource\Image\navigation_interface\通知_selected.png', } self.moreActionsButton = OpacityThreeStateToolButton( r'app\resource\Image\navigation_interface\更多操作.png', opacity_dict, parent=self) self.searchButton = OpacityThreeStateToolButton( r'app\resource\Image\navigation_interface\搜索.png', opacity_dict, (18, 18), self) self.dialsButton = OpacityThreeStateToolButton( r'app\resource\Image\navigation_interface\拨号盘.png', opacity_dict, (40, 40), self) self.chatButton = NavigationButton(chatButtonIconPath_dict, '聊天', parent=self) self.conversationButton = NavigationButton( conversationButtonIconPath_dict, '通话', parent=self) self.contactButton = NavigationButton(contactsButtonIconPath_dict, '联系人', (38, 42), parent=self) self.noticeButton = NavigationButton(noticeButtonIconPath_dict, '通知', parent=self) self.navigationButton_list = [ self.chatButton, self.contactButton, self.conversationButton, self.noticeButton ] def __setQss(self): """ 设置层叠样式 """ with open(r'app\resource\qss\navigation_interface.qss', encoding='utf-8') as f: self.setStyleSheet(f.read()) def paintEvent(self, e): """ 绘制背景 """ super().paintEvent(e) painter = QPainter(self) painter.setPen(QPen(QColor(213, 217, 222))) painter.drawLine(0, 182, self.width(), 183) def resizeEvent(self, e): """ 调整窗口大小 """ super().resizeEvent(e) self.stackedWidget.resize(self.width(), self.height() - 183) self.contactInterface.resize(self.stackedWidget.size()) self.chatListWidget.resize(self.stackedWidget.size()) def __setLabelText(self): """设置用户名和个新签名标签的文字并根据字符串长短来添加省略号 """ # 调整个新签名 fontMetrics = QFontMetrics(QFont('Microsoft YaHei', 8)) newText = fontMetrics.elidedText(self.userInfo['personalSignature'], Qt.ElideRight, 250) self.personalSignatureLabel.setText(newText) self.personalSignatureLabel.adjustSize() # 调整用户名 newText = fontMetrics.elidedText(self.userInfo['userName'], Qt.ElideRight, 260) self.userNameLabel.setText(newText) self.userNameLabel.adjustSize() def updateUserInfo(self, userInfo: dict): """ 更新用户信息 """ self.userInfo = userInfo.copy() self.__setLabelText() self.headPortraitWidget.setHeadPortrait(userInfo['headPortraitPath']) def switchToContactInterface(self): """ 切换到联系人界面 """ self.__switchInterface(1) def switchToChatInterface(self): """ 切换到联系人界面 """ self.__switchInterface(0) def __switchInterface(self, index: int): """ 切换界面 """ currentIndex = self.stackedWidget.currentIndex() if index not in self.__interface_dict.keys(): self.navigationButton_list[index].setSelected(False) return elif index == currentIndex: return self.navigationButton_list[currentIndex].setSelected(False) self.navigationButton_list[index].setSelected(True) self.stackedWidget.setCurrentWidget(self.__interface_dict[index]) def __connectSignalToSlot(self): """ 信号连接到槽函数 """ # 切换界面 for i, button in enumerate(self.navigationButton_list): button.clicked.connect(lambda x, i=i: self.__switchInterface(i))
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 WireSharp(FramelessWindow): """ WireSharp 聊天界面 """ BORDER_WIDTH = 5 def __init__(self): super().__init__() self.__getContactInfo() self.userInfo = getUserInfo() # 实例化小部件 t1 = time() print('🤖 正在初始化界面...') self.stackedWidget = QStackedWidget(self) self.dialogInterface = DialogInterface(self) self.welcomeInterface = WelcomeInterface(self) self.navigationInterface = NavigationInterface(self.contactInfo_list, self) print(f'✅ 完成界面的初始化,耗时{time()-t1:.2f}s') # 创建线程 self.publishThread = PublishThread(self) self.wiresharkThread = WiresharkThread(self) self.arpAttackThread = ArpAttackThread(self) # 引用子窗口 self.chatListWidget = self.navigationInterface.chatListWidget self.contactInterface = self.navigationInterface.contactInterface # 初始化界面 self.__initWidget() def __initWidget(self): """ 初始化界面 """ self.setWindowTitle('Wiresharp') self.setWindowFlags(Qt.FramelessWindowHint) self.setWindowIcon(QIcon(r'app\resource\Image\icon\icon.png')) self.setAttribute(Qt.WA_TranslucentBackground | Qt.WA_StyledBackground) # 调整窗口大小和小部件位置 self.navigationInterface.move(0, 40) self.stackedWidget.move(403, 40) self.resize(1279, 957) # 将窗口添加到层叠窗口中 self.stackedWidget.addWidget(self.welcomeInterface) self.stackedWidget.addWidget(self.dialogInterface) # 在去除任务栏的显示区域居中显示 desktop = QApplication.desktop().availableGeometry() self.move(int(desktop.width() / 2 - self.width() / 2), int(desktop.height() / 2 - self.height() / 2)) # 信号连接到槽函数 self.__connectSignalToSlot() def __getContactInfo(self) -> list: """ 获取联系人信息 """ print('🌍 正在获取局域网内的主机...') t1 = time() host_list = getHost() print(f'✅ 完成局域网内主机的获取,耗时{time()-t1:.2f}s') self.contactInfo_list = [] self.headPortraitPath_list = [ r'app\resource\Image\head_portrait\硝子(1).png', r'app\resource\Image\head_portrait\硝子(2).png', r'app\resource\Image\head_portrait\硝子(3).jpg', ] for i, (hostName, IP) in enumerate(host_list): self.contactInfo_list.append({ 'IP': IP, 'contactName': hostName, 'headPortraitPath': self.headPortraitPath_list[i % len(self.headPortraitPath_list)] }) def resizeEvent(self, e): """ 调整窗口大小 """ super().resizeEvent(e) self.stackedWidget.resize(self.width() - 402, self.height() - 40) if hasattr(self, 'navigationInterface'): self.navigationInterface.resize(self.navigationInterface.width(), self.height() - 40) def __connectSignalToSlot(self): """ 将信号连接到槽函数 """ # 欢迎界面信号连接到槽函数 self.welcomeInterface.changeUserInfoSignal.connect( self.__changeUserInfoSlot) self.welcomeInterface.startConvButton.clicked.connect( self.navigationInterface.switchToContactInterface) # todo:联系人界面信号连接到槽函数 self.contactInterface.selectContactSignal.connect( self.__selectContactSlot) self.chatListWidget.currentChatChanged.connect( self.__currentChatChangedSlot) self.chatListWidget.deleteChatSignal.connect(self.__deleteChatSlot) # todo:会话界面信号连接到槽函数 self.dialogInterface.sendMessageSignal.connect(self.__newMessageSlot) self.dialogInterface.recvMessageSignal.connect(self.__newMessageSlot) self.dialogInterface.publishSignal.connect(self.__publishSlot) self.dialogInterface.startWiresharkSignal.connect( self.__startWiresharpSlot) self.dialogInterface.stopWiresharkSignal.connect( self.__stopWiresharpSlot) self.dialogInterface.startArpAttackSignal.connect( self.__startArpAttackSlot) self.dialogInterface.stopArpAttackSignal.connect( self.__stopArpAttackSlot) # todo:线程信号连接到槽函数 self.wiresharkThread.catchPacketSignal.connect(self.__catchPacketSlot) self.wiresharkThread.wiresharkStateChangedSignal.connect( self.__wiresharpStateChangedSlot) self.arpAttackThread.arpAttackStateChangedSignal.connect( self.__arpAttackStateChangedSlot) self.publishThread.publishStateChangedSignal.connect( self.__publishStateChangedSlot) def __changeUserInfoSlot(self): """ 更新用户信息 """ self.userInfo = getUserInfo() self.navigationInterface.updateUserInfo(self.userInfo) def __selectContactSlot(self, contactInfo: dict): """ 选中联系人时显示对话窗口 """ # 如果选中的IP不在聊天列表已有的聊天用户中,就新建一个对话窗口 IP = contactInfo['IP'] if IP not in list(self.chatListWidget.IPContactName_dict.keys()) \ + list(self.dialogInterface.IPIndex_dict.keys()): self.dialogInterface.addDialog(contactInfo) else: self.dialogInterface.setCurrentDialogByIP(IP) # 将当前窗口设置为对话界面 self.stackedWidget.setCurrentWidget(self.dialogInterface) def __currentChatChangedSlot(self, IP: str): """ 当前选中的聊天框改变对应的槽函数 """ self.dialogInterface.setCurrentDialogByIP(IP) self.stackedWidget.setCurrentWidget(self.dialogInterface) def __newMessageSlot(self, messageInfo: dict): """ 发送/接收 对话消息的槽函数 """ IP = messageInfo['IP'] # 如果对话框中没有当前的联系人对话记录,就创建一个新的聊天框,否则更新聊天框 if IP not in self.chatListWidget.IPContactName_dict.keys(): self.chatListWidget.addChatWidget(messageInfo) else: chatWidget, i = self.chatListWidget.findChatListWidgetByIP( IP, True) self.chatListWidget.setCurrentItem( self.chatListWidget.item_list[i]) chatWidget.updateWindow(messageInfo) def __deleteChatSlot(self, IP: str): """ 删除对话框槽函数 """ self.stackedWidget.setCurrentWidget(self.welcomeInterface) self.dialogInterface.removeDialog(IP) def __startWiresharpSlot(self, IP: str): """ 开始抓包 """ self.arpAttackThread.stopArpAttack() self.arpAttackThread.startArpAttack(IP) self.wiresharkThread.startWireshark() def __stopWiresharpSlot(self): """ 停止抓包 """ self.wiresharkThread.stopWireshark() self.arpAttackThread.stopArpAttack() def __catchPacketSlot(self, packetInfo: dict): """ 抓到包的槽函数 """ self.arpAttackThread.stopArpAttack() self.dialogInterface.isArpAttack = False self.dialogInterface.isCatchingPacket = False # 将数据包保存到本地 writeCatchPacket(packetInfo, 'app\\data\\catch_packet.json') with open(r'app\resource\html\send_file.html', encoding='utf-8') as f: self.__sendMessage(f.read()) def __startArpAttackSlot(self, IP: str): """ 开始 ARP 欺骗槽函数(发送错误 MAC 地址) """ self.arpAttackThread.startArpAttack(IP, False) def __stopArpAttackSlot(self): """ 开始 ARP 欺骗槽函数 """ self.arpAttackThread.stopArpAttack() def __publishSlot(self): """ 发布消息槽函数 """ packetInfo = readCatchPacket('app\\data\\catch_packet.json') if packetInfo: self.publishThread.publish(packetInfo['dst host'], packetInfo['topic'], packetInfo['msg']) else: self.__sendMessage('😋 当前没有抓到的包可供发布哦~') def __publishStateChangedSlot(self, message: str): """ 发布状态改变对应的槽函数 """ self.__sendMessage(message) def __wiresharpStateChangedSlot(self, message: str): """ 显示 Wiresharp 线程发来的消息 """ self.__sendMessage(message) def __arpAttackStateChangedSlot(self, message: str): """ 显示 ARP 攻击线程发来的消息 """ self.__sendMessage(message) def __sendMessage(self, message: str): """ 作为contact发送消息 """ messageInfo = deepcopy(self.dialogInterface.currentContactInfo) messageInfo['message'] = message messageInfo['time'] = QTime.currentTime().toString('H:mm') self.dialogInterface.receiveMessageSlot(messageInfo)
class Widgets(QWidget): def __init__(self, dispositivoCamara, parent=None): super(Widgets, self).__init__(parent) self.parent = parent self.estadoFoto = False self.byteArrayFoto = QByteArray() # ========================================================== frame = QFrame(self) frame.setFrameShape(QFrame.Box) frame.setFrameShadow(QFrame.Sunken) frame.setFixedWidth(505) frame.setFixedHeight(380) frame.move(10, 10) # Instancias self.paginaVisor = QVideoWidget() self.paginaVisor.resize(500, 375) self.visor = QCameraViewfinder(self.paginaVisor) self.visor.resize(500, 375) self.labelFoto = QLabel() self.labelFoto.setAlignment(Qt.AlignCenter) self.labelFoto.resize(500, 375) # QStackedWidget self.stackedWidget = QStackedWidget(frame) self.stackedWidget.addWidget(self.paginaVisor) self.stackedWidget.addWidget(self.labelFoto) self.stackedWidget.resize(500, 375) self.stackedWidget.move(2, 2) # ======================== BOTONES ========================= self.buttonTomarFoto = QPushButton("Tomar foto", self) self.buttonTomarFoto.resize(110, 26) self.buttonTomarFoto.move(525, 10) self.buttonEliminarFoto = QPushButton("Eliminar foto", self) self.buttonEliminarFoto.resize(110, 26) self.buttonEliminarFoto.move(525, 50) self.buttonGuardarFoto = QPushButton("Guardar foto", self) self.buttonGuardarFoto.resize(110, 26) self.buttonGuardarFoto.move(525, 82) # ======================== EVENTOS ========================= self.buttonTomarFoto.clicked.connect(self.tomarFoto) self.buttonEliminarFoto.clicked.connect(self.eliminarFoto) self.buttonGuardarFoto.clicked.connect(self.guardarFoto) # ================== FUNCIONES AUTOMÁTICAS ================= self.setCamara(dispositivoCamara) # ======================= FUNCIONES ============================ def setCamara(self, dispositivoCamara): if dispositivoCamara.isEmpty(): self.camara = QCamera() else: self.camara = QCamera(dispositivoCamara) self.camara.stateChanged.connect(self.actualizarEstadoCamara) self.capturaImagen = QCameraImageCapture(self.camara) self.camara.setViewfinder(self.visor) self.actualizarEstadoCamara(self.camara.state()) self.capturaImagen.imageCaptured.connect(self.procesarImagenCapturada) self.capturaImagen.imageSaved.connect(self.imagenGuardada) self.camara.isCaptureModeSupported(QCamera.CaptureStillImage) self.camara.start() self.paginaVisor.update() def actualizarDispositivoCamara(self, action): self.setCamara(action.data()) def actualizarEstadoCamara(self, estado): if estado == QCamera.ActiveState: self.parent.accionIniciarCamara.setEnabled(False) self.parent.accionDetenerCamara.setEnabled(True) if not self.estadoFoto: self.buttonTomarFoto.setEnabled(True) self.buttonEliminarFoto.setEnabled(False) self.buttonGuardarFoto.setEnabled(False) elif estado in (QCamera.UnloadedState, QCamera.LoadedState): self.parent.accionIniciarCamara.setEnabled(True) self.parent.accionDetenerCamara.setEnabled(False) if not self.estadoFoto: self.buttonTomarFoto.setEnabled(False) self.buttonEliminarFoto.setEnabled(False) self.buttonGuardarFoto.setEnabled(False) def iniciarCamara(self): self.camara.start() def detenerCamara(self): self.camara.stop() def tomarFoto(self): rutaFoto = "{}/fotoTemporal.jpg".format(getcwd()) self.capturaImagen.capture(rutaFoto) self.estadoFoto = True def procesarImagenCapturada(self, requestId, imagen): foto = QPixmap.fromImage(imagen) buffer = QBuffer(self.byteArrayFoto) buffer.open(QIODevice.WriteOnly) buffer.close() foto.save(buffer, "PNG") fotoEscalada = foto.scaled(self.labelFoto.size()) self.labelFoto.setPixmap(fotoEscalada) self.mostrarImagenCapturada() def visualizarVisor(self): self.stackedWidget.setCurrentIndex(0) def mostrarImagenCapturada(self): self.stackedWidget.setCurrentIndex(1) self.buttonTomarFoto.setEnabled(False) self.buttonEliminarFoto.setEnabled(True) self.buttonGuardarFoto.setEnabled(True) def imagenGuardada(self, id, nombreFoto): if QFile.exists(nombreFoto): remove(nombreFoto) def eliminarFoto(self): self.estadoFoto = False self.byteArrayFoto.clear() self.labelFoto.clear() self.actualizarEstadoCamara(self.camara.state()) self.visualizarVisor() def guardarFoto(self): guardarComo, extension = QFileDialog.getSaveFileName( self, "Guardar como", "Foto", "JPG (*.jpg);;PNG (*.png);;ICO (*.ico);;BMP (*.bmp)", options=QFileDialog.Options()) if guardarComo: foto = QPixmap() foto.loadFromData(self.byteArrayFoto, "PNG", Qt.AutoColor) foto.save(guardarComo, quality=100) QMessageBox.information( self, "Guardar foto", "Foto guardada con éxito ") self.eliminarFoto()
class LabelNavigationInterface(QWidget): """ 标签导航界面 """ labelClicked = pyqtSignal(str) def __init__(self, parent=None, label_list: list = None): super().__init__(parent) self.scrollWidget = QWidget() self.scrollArea = ScrollArea(self) self.stackWidget = QStackedWidget(self) self.vBox = VBoxLayout(self.scrollWidget) self.letterNavigationWidget = QWidget(self) self.gridLayout = QGridLayout(self.letterNavigationWidget) self.__clickableLabel_list = [] # type:List[ClickableLabel] self.__clickableLetterLabel_list = [ ClickableLabel(chr(i)) for i in range(65, 91) ] # type:List[ClickableLabel] self.__clickableLetterLabel_list.append(ClickableLabel("...")) # 初始化界面 self.setLabels(label_list) self.__initWidget() def __initWidget(self): """ 初始化界面 """ self.resize(800, 800) self.vBox.setSpacing(40) self.gridLayout.setSpacing(60) self.vBox.setAlignment(Qt.AlignLeft) self.vBox.setContentsMargins(25, 25, 0, 140) self.gridLayout.setContentsMargins(0, 0, 0, 140) self.gridLayout.setAlignment(Qt.AlignCenter) self.scrollArea.setWidget(self.scrollWidget) self.scrollWidget.setObjectName("scrollWidget") self.stackWidget.addWidget(self.scrollWidget) self.stackWidget.addWidget(self.letterNavigationWidget) # 设置层叠样式 self.__setQss() # 调整字母标签尺寸并将字母添加到网格布局中 for i, label in enumerate(self.__clickableLetterLabel_list): row = i // 8 col = i - row * 8 label.setFixedHeight(50) text = label.text() label.clicked.connect( lambda text=text: self.labelClicked.emit(text)) self.gridLayout.addWidget(label, row, col, 1, 1, Qt.AlignCenter) def setLabels(self, label_list: List[str] = None, layout="letterGridLayout"): """ 设置导航标签 Parameters ---------- label_list : List[str] 需要显示的标签列表 layout : str 显示的标签的布局,有字母网格布局`letterGridLayout`和列表布局`listLayout`两种 """ self.vBox.removeAllWidget() # 删除旧标签 for label in self.__clickableLabel_list: label.deleteLater() self.__clickableLabel_list = [] self.__label_list = label_list if label_list else [] if self.__label_list: # 不使用棋盘布局直接显示所有标签 if layout != "letterGridLayout": self.__clickableLabel_list = [ ClickableLabel(label) for label in label_list ] self.__connectLabelSigToSlot() # 将新的标签添加到布局中 self.__adjustLabelSize() for label in self.__clickableLabel_list: label.setCursor(Qt.PointingHandCursor) self.vBox.addWidget(label) else: # 生成首字母集合 _ = set(pinyin.get_initial(i)[0].upper() for i in label_list) letter_set = set(i if 65 <= ord(i) <= 90 else "..." for i in _) # 启用在字母结合中的标签 for label in self.__clickableLetterLabel_list: label.setCursor(Qt.PointingHandCursor if label.text() in letter_set else Qt.ArrowCursor) label.setEnabled(label.text() in letter_set) # 切换布局 self.stackWidget.setCurrentIndex(layout == "letterGridLayout") def __adjustLabelSize(self): """ 调整标签尺寸 """ for label in self.__clickableLabel_list: label.setFixedHeight(50) labelNum = len(self.__clickableLabel_list) self.scrollWidget.resize( self.width(), 50 * labelNum + 40 * (labelNum - 1) + 140 + 25) def resizeEvent(self, e): """ 调整部件尺寸 """ self.stackWidget.resize(self.size()) self.scrollWidget.resize(self.width(), self.scrollWidget.height()) self.scrollArea.verticalScrollBar().move(-1, 40) self.scrollArea.verticalScrollBar().resize( self.scrollArea.verticalScrollBar().width(), self.height() - 156) def __setQss(self): """ 设置层叠样式 """ with open(r"app\resource\css\labelNavigationInterface.qss", encoding="utf-8") as f: self.setStyleSheet(f.read()) def __connectLabelSigToSlot(self): """ 标签点击信号的槽函数 """ for label in self.__clickableLabel_list: text = label.text() label.clicked.connect( lambda text=text: self.labelClicked.emit(text)) @property def label_list(self): return self.__label_list
class Window(QMainWindow): BOARD_HEIGHT = 621 BOARD_WIDTH = 1000 def __init__(self): super(Window, self).__init__() self.widgMain = MainForm() self.widgTeam = TeamSelectionUI() self.widgBoard = Board() print("AFTER BOARD CREATED") self.server = Server() # Set up signal to allow state change self.server.updateActiveWidget.connect(self.updateActiveWidget) # Set up signal to allow data to be sent to MAIN_SCREEN self.server.updateConnectedUsersSig.connect(self.widgMain.updateConnectedUsers) self.server.appendConnectedHistorySig.connect(self.widgMain.appendConnectedHistory) self.server.updateConnectedUsersSig.connect(self.widgMain.updateConnectedHistory) self.server.updateGameInfoSig.connect(self.widgMain.updateGameInfo) """ Set up signal to allow data to be received by the TEAM_SCREEN (self.widgTeam), data sent is used to sort clients into teams of two """ self.server.setupTeamSig.connect(self.widgTeam.setupTeam) # Set up signal to allow data to be sent to GAME_SCREEN self.server.updateGameSig.connect(self.widgBoard.updateGame) # Set up signal to allow updated teams to be sent to server self.widgTeam.updateTeamsSig.connect(self.server.updateTeams) self.stack = QStackedWidget(self) self.stack.resize(self.BOARD_WIDTH, self.BOARD_HEIGHT) self.stack.addWidget(self.widgMain) self.stack.addWidget(self.widgTeam) self.stack.addWidget(self.widgBoard) self.resize(self.BOARD_WIDTH, self.BOARD_HEIGHT) layout = QGridLayout() layout.addWidget(self.stack) self.setLayout(layout) self.setWindowTitle("Blobbageddon") self.stack.setCurrentIndex(0) self.server.start() self.show() def updateActiveWidget(self, adrs): if (self.server.state.currState == State.GAME_SCREEN): self.stack.setCurrentIndex(2) print(len(adrs)) self.widgBoard.start(adrs) elif self.server.state.currState == State.TEAM_SCREEN: self.widgTeam.setupUi(adrs) self.stack.setCurrentIndex(1) elif (self.server.state.currState == State.MAIN_SCREEN): self.stack.setCurrentIndex(0)
class centralWidget(QStackedWidget): def __init__(self, parent= None): QStackedWidget.__init__(self , parent) self.central_widget = QStackedWidget() self.central_widget.resize(1100,600)
class MovesetDatEditor(QWidget): def __init__(self, fname, save_directory='', owner=None): super().__init__() # reference to the main window because parent is overwritten by addTab self.owner = owner self.grid = QGridLayout(self) self.fname = fname self.editors_list = QListWidget(self) self.editors_list.setSizeAdjustPolicy(QListWidget.AdjustToContents) self.editors_list.setFixedWidth(150) self.frame = QStackedWidget(self) self.frame.setFrameStyle(QFrame.Panel | QFrame.Raised) self.frame.sizeHint = lambda: QSize( max( self.frame.widget(i).sizeHint().width() for i in range(self.frame.count())), max( self.frame.widget(i).sizeHint().height() for i in range(self.frame.count()))) self.initialize() self.grid.addWidget(QLabel(self.f.title(), self), 0, 0) self.grid.addWidget(self.editors_list, 1, 0) self.grid.addWidget(self.frame, 1, 1) self.grid.setColumnStretch(1, 1) def save(self): """Save the opened file (over itself)""" self.f.save(self.fname) self.last_save_directory = os.path.dirname(self.fname) def saveas(self): """Spawn a save file dialog and save as the selected file name""" self.fname = QFileDialog.getSaveFileName( self, 'Save Moveset File As', self.last_save_directory, 'Moveset dat files (*.dat)')[0] if self.fname: self.save() # Retitle the tab to reflect the new filename. # QTabWidget uses a QStackedWidget internally, and that is the # parent of each tab, so we need parent() twice. tabs = self.parent().parent() tabs.setTabText(tabs.indexOf(self), os.path.basename(self.fname)) def close(self): self.f.close() self.deleteLater() def reload(self): """Reload same file from disk""" while self.editors_list.count() > 0: w = self.editors_list.takeItem(0) del w while self.frame.count() > 0: w = self.frame.currentWidget() self.frame.removeWidget(w) w.deleteLater() self.f.close() self.initialize() def initialize(self): self.f = moveset_datfile(self.fname) self.setup_stacked_frame() @property def last_save_directory(self): return self.owner.last_save_directory @last_save_directory.setter def last_save_directory(self, val): self.owner.last_save_directory = val def setup_stacked_frame(self): self.script_widget = ScriptEditor(self.f) self.frame.addWidget(self.script_widget) self.common_attributes_widget = AttributeEditor( 'Common Attributes', self.f.common_attributes_table) self.frame.addWidget(self.common_attributes_widget) self.unique_attributes_widget = AttributeEditor( 'Unique Attributes', self.f.unique_attributes_table) self.frame.addWidget(self.unique_attributes_widget) self.hurtboxes_widget = HurtboxEditor(self.f.hurtbox_header, self.f.hurtbox_table) self.frame.addWidget(self.hurtboxes_widget) self.ledgegrab_editor = AttributeEditor('Ledge Grab Box', self.f.ledge_grab_data) self.frame.addWidget(self.ledgegrab_editor) for i in range(self.frame.count()): new = QListWidgetItem(self.frame.widget(i).display_name) self.editors_list.addItem(new) self.editors_list.currentRowChanged.connect( self.frame.setCurrentIndex) self.frame.sizeHint = lambda: QSize( max( self.frame.widget(i).sizeHint().width() for i in range(self.frame.count())), max( self.frame.widget(i).sizeHint().height() for i in range(self.frame.count()))) self.frame.resize(self.frame.sizeHint()) self.editors_list.setCurrentRow(0)
class Window(QMainWindow): BOARD_HEIGHT = 621 BOARD_WIDTH = 1000 def __init__(self): super(Window, self).__init__() self.widgMain = MainForm() self.widgTeam = TeamSelectionUI() self.widgBoard = Board() print("AFTER BOARD CREATED") self.server = Server() # Set up signal to allow state change self.server.updateActiveWidget.connect(self.updateActiveWidget) # Set up signal to allow data to be sent to MAIN_SCREEN self.server.updateConnectedUsersSig.connect( self.widgMain.updateConnectedUsers) self.server.appendConnectedHistorySig.connect( self.widgMain.appendConnectedHistory) self.server.updateConnectedUsersSig.connect( self.widgMain.updateConnectedHistory) self.server.updateGameInfoSig.connect(self.widgMain.updateGameInfo) """ Set up signal to allow data to be received by the TEAM_SCREEN (self.widgTeam), data sent is used to sort clients into teams of two """ self.server.setupTeamSig.connect(self.widgTeam.setupTeam) # Set up signal to allow data to be sent to GAME_SCREEN self.server.updateGameSig.connect(self.widgBoard.updateGame) # Set up signal to allow updated teams to be sent to server self.widgTeam.updateTeamsSig.connect(self.server.updateTeams) self.stack = QStackedWidget(self) self.stack.resize(self.BOARD_WIDTH, self.BOARD_HEIGHT) self.stack.addWidget(self.widgMain) self.stack.addWidget(self.widgTeam) self.stack.addWidget(self.widgBoard) self.resize(self.BOARD_WIDTH, self.BOARD_HEIGHT) layout = QGridLayout() layout.addWidget(self.stack) self.setLayout(layout) self.setWindowTitle("Blobbageddon") self.stack.setCurrentIndex(0) self.server.start() self.show() def updateActiveWidget(self, adrs): if (self.server.state.currState == State.GAME_SCREEN): self.stack.setCurrentIndex(2) print(len(adrs)) self.widgBoard.start(adrs) elif self.server.state.currState == State.TEAM_SCREEN: self.widgTeam.setupUi(adrs) self.stack.setCurrentIndex(1) elif (self.server.state.currState == State.MAIN_SCREEN): self.stack.setCurrentIndex(0)
self.index_to_sqlIndex_first_list.clear() self.index_to_sqlIndex_second_listes.clear() self.indexTuple_to_webAddress_listWidetIndex.clear() self.indexTuple_to_webAddressIDLIST.clear() self.indexTuple_to_webAddress_list.clear() # 重新加载 self.load_Database() self.load_stackWidget1() self.load_stackWidget2() if __name__ == "__main__": app = QApplication(sys.argv) stackedWidget = QStackedWidget() stackedWidget.resize(1200, 900) stackedWidget.setWindowTitle('多网页搜索工具') web = Web() mainWindow = MainWindow() stackedWidget.addWidget(mainWindow) stackedWidget.addWidget(web) mainWindow.signal_change_stackedWidget.connect( lambda: stackedWidget.setCurrentIndex(1)) mainWindow.signal.connect(web.add_new_tab) web.signal_change_stackedWidget.connect( lambda: stackedWidget.setCurrentIndex(0)) stackedWidget.show()
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)