Esempio n. 1
0
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)                  #居中显示
Esempio n. 3
0
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)
Esempio n. 4
0
                            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())
Esempio n. 5
0
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)
Esempio n. 6
0
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)
Esempio n. 8
0
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)
Esempio n. 9
0
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()
Esempio n. 10
0
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
Esempio n. 11
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)
Esempio n. 12
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)
Esempio n. 14
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)
Esempio n. 15
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()
Esempio n. 16
-1
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)