コード例 #1
0
ファイル: mainframe.py プロジェクト: yattom/snakefire
    def getSettings(self, group, asString=True, reload=False):
        defaults = {
            "connection": {
                "subdomain": None,
                "user": None,
                "password": None,
                "ssl": False,
                "connect": False,
                "join": False,
                "rooms": []
            },
            "program": {
                "minimize": False,
                "spell_language": SpellTextEditor.defaultLanguage(),
                "away": True,
                "away_time": 10,
                "away_time_between_messages": 5,
                "away_message": self._("I am currently away from {name}").format(name=self.NAME)
            },
            "display": {
                "theme": "default",
                "size": 100,
                "show_join_message": True,
                "show_part_message": True,
                "show_message_timestamps": True
            },
            "alerts": {
                "notify_ping": True,
                "notify_inactive_tab": False,
                "notify_blink": True,
                "notify_notify": True
            },
            "matches": []
        }

        if reload or not group in self._settings:
            settings = defaults[group] if group in defaults else {}

            if group == "matches":
                settings = []
                size = self._qsettings.beginReadArray("matches")
                for i in range(size):
                    self._qsettings.setArrayIndex(i)
                    isRegex = False
                    try:
                        isRegex = True if ["true", "1"].index(str(self._qsettings.value("regex").toPyObject()).lower()) >= 0 else False
                    except:
                        pass

                    settings.append({
                        'regex': isRegex,
                        'match': self._qsettings.value("match").toPyObject()
                    })
                self._qsettings.endArray()
            else:
                self._qsettings.beginGroup(group);
                for setting in self._qsettings.childKeys():
                    settings[str(setting)] = self._qsettings.value(setting).toPyObject()
                self._qsettings.endGroup();

                boolSettings = []
                if group == "connection":
                    boolSettings += ["ssl", "connect", "join"]
                elif group == "program":
                    boolSettings += ["away", "minimize"]
                elif group == "display":
                    boolSettings += ["show_join_message", "show_part_message", "show_message_timestamps"]
                elif group == "alerts":
                    boolSettings += ["notify_ping", "notify_inactive_tab", "notify_blink", "notify_notify"]

                for boolSetting in boolSettings:
                    try:
                        settings[boolSetting] = True if ["true", "1"].index(str(settings[boolSetting]).lower()) >= 0 else False
                    except:
                        settings[boolSetting] = False

                if group == "connection" and settings["subdomain"] and settings["user"]:
                    settings["password"] = keyring.get_password(self.NAME, str(settings["subdomain"])+"_"+str(settings["user"]))

            self._settings[group] = settings

        settings = self._settings[group]
        if asString:
            if isinstance(settings, list):
                for i, row in enumerate(settings):
                    for setting in row:
                        if not isinstance(row[setting], bool):
                            settings[i][setting] = str(row[setting]) if row[setting] else ""
            else:
                for setting in settings:
                    if not isinstance(settings[setting], bool):
                        settings[setting] = str(settings[setting]) if settings[setting] else ""

        return settings
コード例 #2
0
ファイル: dialogs.py プロジェクト: benjaminws/snakefire
    def _setupUI(self):
        # Connection group

        self._subdomainField = QtGui.QLineEdit(self)
        self._usernameField = QtGui.QLineEdit(self)
        self._passwordField = QtGui.QLineEdit(self)
        self._passwordField.setEchoMode(QtGui.QLineEdit.Password)
        self._sslField = QtGui.QCheckBox(self._mainFrame._("Use &secure connection (SSL)"), self)

        self.connect(self._subdomainField, QtCore.SIGNAL('textChanged(QString)'), self.validate)
        self.connect(self._usernameField, QtCore.SIGNAL('textChanged(QString)'), self.validate)
        self.connect(self._passwordField, QtCore.SIGNAL('textChanged(QString)'), self.validate)

        connectionGrid = QtGui.QGridLayout()
        connectionGrid.addWidget(QtGui.QLabel(self._mainFrame._("Subdomain:"), self), 1, 0)
        connectionGrid.addWidget(self._subdomainField, 1, 1)
        connectionGrid.addWidget(QtGui.QLabel(self._mainFrame._("Username:"******"Password:"******"Campfire connection"))
        connectionGroupBox.setLayout(connectionGrid)

        # Program group

        spellLanguages = {
            "": self._mainFrame._("No spell check")
        }

        if SpellTextEditor.canSpell():
            for language in SpellTextEditor.languages():
                spellLanguages[language] = language;

        self._connectField = QtGui.QCheckBox(self._mainFrame._("Automatically &connect when program starts"), self)
        self._joinField = QtGui.QCheckBox(self._mainFrame._("&Join last opened channels once connected"), self)
        self._minimizeField = QtGui.QCheckBox(self._mainFrame._("&Minimize to system tray if window is minimized, or closed"), self)
        self._spellLanguageField = QtGui.QComboBox(self)

        spellLanguageBox = QtGui.QHBoxLayout()
        spellLanguageBox.addWidget(QtGui.QLabel(self._mainFrame._("Spell checking:"), self))
        spellLanguageBox.addWidget(self._spellLanguageField)
        spellLanguageBox.addStretch(1)

        programGrid = QtGui.QGridLayout()
        programGrid.addWidget(self._connectField, 1, 0)
        programGrid.addWidget(self._joinField, 2, 0)
        programGrid.addWidget(self._minimizeField, 3, 0)
        programGrid.addLayout(spellLanguageBox, 4, 0)

        programGroupBox = QtGui.QGroupBox(self._mainFrame._("Program settings"))
        programGroupBox.setLayout(programGrid)

        if not SpellTextEditor.canSpell():
            self._spellLanguageField.setEnabled(False)

        # Away group

        awayTimes = {
            5: self._mainFrame._("5 minutes"),
            10: self._mainFrame._("10 minutes"),
            15: self._mainFrame._("15 minutes"),
            30: self._mainFrame._("30 minutes"),
            45: self._mainFrame._("45 minutes"),
            60: self._mainFrame._("1 hour"),
            90: self._mainFrame._("1 and a half hours"),
            120: self._mainFrame._("2 hours")
        }

        awayBetweenTimes = {
            2: self._mainFrame._("2 minutes"),
            5: self._mainFrame._("5 minutes"),
            10: self._mainFrame._("10 minutes"),
            15: self._mainFrame._("15 minutes"),
            30: self._mainFrame._("30 minutes"),
            45: self._mainFrame._("45 minutes"),
            60: self._mainFrame._("1 hour")
        }

        self._awayField = QtGui.QCheckBox(self._mainFrame._("Set me as &away after idle time"), self)
        self._awayTimeField = QtGui.QComboBox(self)
        self._awayMessageField = QtGui.QLineEdit(self)
        self._awayTimeBetweenMessagesField = QtGui.QComboBox(self)

        if IdleTimer.supported():
            self.connect(self._awayField, QtCore.SIGNAL('stateChanged(int)'), self.validate)
            self.connect(self._awayMessageField, QtCore.SIGNAL('textChanged(QString)'), self.validate)
        else:
            self._awayField.setEnabled(False)

        awayTimeBox = QtGui.QHBoxLayout()
        awayTimeBox.addWidget(QtGui.QLabel(self._mainFrame._("Idle Time:"), self))
        awayTimeBox.addWidget(self._awayTimeField)
        awayTimeBox.addWidget(QtGui.QLabel(self._mainFrame._("Wait"), self))
        awayTimeBox.addWidget(self._awayTimeBetweenMessagesField)
        awayTimeBox.addWidget(QtGui.QLabel(self._mainFrame._("before sending consecutive messages"), self))
        awayTimeBox.addStretch(1)

        awayMessageBox = QtGui.QHBoxLayout()
        awayMessageBox.addWidget(QtGui.QLabel(self._mainFrame._("Message:"), self))
        awayMessageBox.addWidget(self._awayMessageField)

        awayBox = QtGui.QVBoxLayout()
        awayBox.addWidget(self._awayField)
        awayBox.addLayout(awayTimeBox)
        awayBox.addLayout(awayMessageBox)

        awayGroupBox = QtGui.QGroupBox(self._mainFrame._("Away mode"))
        awayGroupBox.setLayout(awayBox)

        # Theme group

        self._themeField = QtGui.QComboBox(self)
        self._themeSizeField = QtGui.QComboBox(self)
        self._themePreview = QtWebKit.QWebView(self)
        self._themePreview.setMaximumHeight(300)

        themeSelectorBox = QtGui.QHBoxLayout()
        themeSelectorBox.addWidget(QtGui.QLabel(self._mainFrame._("Theme:")))
        themeSelectorBox.addWidget(self._themeField)
        themeSelectorBox.addWidget(QtGui.QLabel(self._mainFrame._("Text size:")))
        themeSelectorBox.addWidget(self._themeSizeField)
        themeSelectorBox.addStretch(1)

        themeSelectorBox.setContentsMargins(0, 0, 0, 0)
        themeSelectorBox.setSpacing(5)

        themeSelectorFrame = QtGui.QWidget()
        themeSelectorFrame.setLayout(themeSelectorBox)

        themeGrid = QtGui.QGridLayout()
        themeGrid.addWidget(themeSelectorFrame, 1, 0)
        themeGrid.addWidget(self._themePreview, 2, 0)

        themeGroupBox = QtGui.QGroupBox(self._mainFrame._("Theme"))
        themeGroupBox.setLayout(themeGrid)

        # Events group

        self._showJoinMessageField = QtGui.QCheckBox(self._mainFrame._("Show &join messages"), self)
        self._showPartMessageField = QtGui.QCheckBox(self._mainFrame._("Show p&art messages"), self)
        self._showMessageTimestampsField = QtGui.QCheckBox(self._mainFrame._("Show message &timestamps"), self)
        self._showAvatarsField = QtGui.QCheckBox(self._mainFrame._("Show user a&vatars (only supported by certain themes)"), self)

        eventsGrid = QtGui.QGridLayout()
        eventsGrid.addWidget(self._showJoinMessageField, 1, 0)
        eventsGrid.addWidget(self._showPartMessageField, 2, 0)
        eventsGrid.addWidget(self._showMessageTimestampsField, 3, 0)
        eventsGrid.addWidget(self._showAvatarsField, 4, 0)

        eventsGroupBox = QtGui.QGroupBox(self._mainFrame._("Display events"))
        eventsGroupBox.setLayout(eventsGrid)

        # Options tab

        optionsBox = QtGui.QVBoxLayout()
        optionsBox.addWidget(connectionGroupBox)
        optionsBox.addWidget(programGroupBox)
        optionsBox.addWidget(awayGroupBox)
        optionsBox.addStretch(1)

        optionsFrame = QtGui.QWidget()
        optionsFrame.setLayout(optionsBox)

        # Display tab

        displayBox = QtGui.QVBoxLayout()
        displayBox.addWidget(themeGroupBox)
        displayBox.addWidget(eventsGroupBox)
        displayBox.addStretch(1)

        displayFrame = QtGui.QWidget()
        displayFrame.setLayout(displayBox)

        # Tabs

        tabs = QtGui.QTabWidget()
        tabs.setTabsClosable(False)

        tabs.addTab(optionsFrame, self._mainFrame._("&Program options"))
        tabs.addTab(displayFrame, self._mainFrame._("&Display options"))

        # Buttons

        self._okButton = QtGui.QPushButton(self._mainFrame._("&OK"), self)
        self._cancelButton = QtGui.QPushButton(self._mainFrame._("&Cancel"), self)

        self.connect(self._okButton, QtCore.SIGNAL('clicked()'), self.ok)
        self.connect(self._cancelButton, QtCore.SIGNAL('clicked()'), self.cancel)

        # Main layout

        hbox = QtGui.QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(self._okButton)
        hbox.addWidget(self._cancelButton)

        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(tabs)
        vbox.addLayout(hbox)

        self.setLayout(vbox)

        # Load settings

        connectionSettings = self._mainFrame.getSettings("connection")
        programSettings = self._mainFrame.getSettings("program")
        displaySettings = self._mainFrame.getSettings("display")

        self._subdomainField.setText(connectionSettings["subdomain"])
        self._usernameField.setText(connectionSettings["user"])
        if connectionSettings["password"]:
            self._passwordField.setText(connectionSettings["password"])
        self._sslField.setChecked(connectionSettings["ssl"])
        self._connectField.setChecked(connectionSettings["connect"])
        self._joinField.setChecked(connectionSettings["join"])
        self._minimizeField.setChecked(programSettings["minimize"])
        self._awayField.setChecked(programSettings["away"])
        self._awayMessageField.setText(programSettings["away_message"])

        self._showJoinMessageField.setChecked(displaySettings["show_join_message"])
        self._showPartMessageField.setChecked(displaySettings["show_part_message"])
        self._showMessageTimestampsField.setChecked(displaySettings["show_message_timestamps"])
        self._showAvatarsField.setChecked(displaySettings["show_avatars"])

        self._setupThemesUI(displaySettings)

        currentIndex = None
        index = 0
        spellLanguageKeys = spellLanguages.keys()
        spellLanguageKeys.sort()
        for value in spellLanguageKeys:
            self._spellLanguageField.addItem(spellLanguages[value], value)
            if value == programSettings["spell_language"]:
                currentIndex = index
            index += 1

        if currentIndex is not None:
            self._spellLanguageField.setCurrentIndex(currentIndex)

        currentIndex = None
        index = 0
        awayTimeKeys = awayTimes.keys()
        awayTimeKeys.sort()
        for value in awayTimeKeys:
            self._awayTimeField.addItem(awayTimes[value], value)
            if value == int(programSettings["away_time"]):
                currentIndex = index
            index += 1

        if currentIndex is not None:
            self._awayTimeField.setCurrentIndex(currentIndex)

        currentIndex = None
        index = 0
        awayBetweenTimeKeys = awayBetweenTimes.keys()
        awayBetweenTimeKeys.sort()
        for value in awayBetweenTimeKeys:
            self._awayTimeBetweenMessagesField.addItem(awayBetweenTimes[value], value)
            if value == int(programSettings["away_time_between_messages"]):
                currentIndex = index
            index += 1

        if currentIndex is not None:
            self._awayTimeBetweenMessagesField.setCurrentIndex(currentIndex)

        self.validate()
コード例 #3
0
ファイル: mainframe.py プロジェクト: fabiokung/snakefire
    def _setupUI(self):
        self.setWindowTitle(self.NAME)

        self._addMenu()
        self._addToolbar()

        self._tabs = QtGui.QTabWidget()
        self._tabs.setTabsClosable(True)
        self.connect(self._tabs, QtCore.SIGNAL("currentChanged(int)"),
                     self._roomTabFocused)
        self.connect(self._tabs, QtCore.SIGNAL("tabCloseRequested(int)"),
                     self._roomTabClose)

        self._editor = SpellTextEditor(lang=self.getSetting(
            "program", "spell_language"),
                                       mainFrame=self)

        speakButton = QtGui.QPushButton(self._("&Send"))
        self.connect(speakButton, QtCore.SIGNAL('clicked()'), self.speak)

        grid = QtGui.QGridLayout()
        grid.setRowStretch(0, 1)
        grid.addWidget(self._tabs, 0, 0, 1, -1)
        grid.addWidget(self._editor, 2, 0)
        grid.addWidget(speakButton, 2, 1)

        widget = QtGui.QWidget()
        widget.setLayout(grid)
        self.setCentralWidget(widget)

        tabWidgetFocusEventFilter = TabWidgetFocusEventFilter(self)
        self.connect(tabWidgetFocusEventFilter, QtCore.SIGNAL("tabFocused()"),
                     self._roomTabFocused)
        widget.installEventFilter(tabWidgetFocusEventFilter)

        self.centralWidget().hide()

        size = self.getSetting("window", "size")

        if not size:
            size = QtCore.QSize(640, 480)

        self.resize(size)

        position = self.getSetting("window", "position")
        if not position:
            screen = QtGui.QDesktopWidget().screenGeometry()
            position = QtCore.QPoint((screen.width() - size.width()) / 2,
                                     (screen.height() - size.height()) / 2)

        self.move(position)

        self._updateLayout()

        menu = QtGui.QMenu(self)
        menu.addAction(self._menus["file"]["connect"])
        menu.addAction(self._menus["file"]["disconnect"])
        menu.addSeparator()
        menu.addAction(self._menus["file"]["exit"])

        self._trayIcon = Systray(self._trayIconIcon, self)
        self._trayIcon.setContextMenu(menu)
        self._trayIcon.setToolTip(self.DESCRIPTION)
コード例 #4
0
ファイル: mainframe.py プロジェクト: fabiokung/snakefire
    def getSettings(self, group, asString=True, reload=False):
        try:
            spell_language = SpellTextEditor.defaultLanguage()
        except enchant.errors.Error:
            spell_language = None
        defaults = {
            "connection": {
                "subdomain": None,
                "user": None,
                "password": None,
                "ssl": False,
                "connect": False,
                "join": False,
                "rooms": []
            },
            "program": {
                "minimize":
                False,
                "spell_language":
                spell_language,
                "away":
                True,
                "away_time":
                10,
                "away_time_between_messages":
                5,
                "away_message":
                self._("I am currently away from {name}").format(
                    name=self.NAME)
            },
            "display": {
                "theme": "default",
                "size": 100,
                "show_join_message": True,
                "show_part_message": True,
                "show_message_timestamps": True
            },
            "alerts": {
                "notify_ping": True,
                "notify_inactive_tab": False,
                "notify_blink": True,
                "notify_notify": True
            },
            "matches": []
        }

        if reload or not group in self._settings:
            settings = defaults[group] if group in defaults else {}

            if group == "matches":
                settings = []
                size = self._qsettings.beginReadArray("matches")
                for i in range(size):
                    self._qsettings.setArrayIndex(i)
                    isRegex = False
                    try:
                        isRegex = True if ["true", "1"].index(
                            str(self._qsettings.value(
                                "regex").toPyObject()).lower()) >= 0 else False
                    except:
                        pass

                    settings.append({
                        'regex':
                        isRegex,
                        'match':
                        self._qsettings.value("match").toPyObject()
                    })
                self._qsettings.endArray()
            else:
                self._qsettings.beginGroup(group)
                for setting in self._qsettings.childKeys():
                    settings[str(setting)] = self._qsettings.value(
                        setting).toPyObject()
                self._qsettings.endGroup()

                boolSettings = []
                if group == "connection":
                    boolSettings += ["ssl", "connect", "join"]
                elif group == "program":
                    boolSettings += ["away", "minimize"]
                elif group == "display":
                    boolSettings += [
                        "show_join_message", "show_part_message",
                        "show_message_timestamps"
                    ]
                elif group == "alerts":
                    boolSettings += [
                        "notify_ping", "notify_inactive_tab", "notify_blink",
                        "notify_notify"
                    ]

                for boolSetting in boolSettings:
                    try:
                        settings[boolSetting] = True if ["true", "1"].index(
                            str(settings[boolSetting]).lower()) >= 0 else False
                    except:
                        settings[boolSetting] = False

                if group == "connection" and settings[
                        "subdomain"] and settings["user"]:
                    settings["password"] = keyring.get_password(
                        self.NAME,
                        str(settings["subdomain"]) + "_" +
                        str(settings["user"]))

            self._settings[group] = settings

        settings = self._settings[group]
        if asString:
            if isinstance(settings, list):
                for i, row in enumerate(settings):
                    for setting in row:
                        if not isinstance(row[setting], bool):
                            settings[i][setting] = str(
                                row[setting]) if row[setting] else ""
            else:
                for setting in settings:
                    if not isinstance(settings[setting], bool):
                        settings[setting] = str(
                            settings[setting]) if settings[setting] else ""

        return settings
コード例 #5
0
    def _setupUI(self):
        # Connection group

        self._subdomainField = QtGui.QLineEdit(self)
        self._usernameField = QtGui.QLineEdit(self)
        self._passwordField = QtGui.QLineEdit(self)
        self._passwordField.setEchoMode(QtGui.QLineEdit.Password)
        self._sslField = QtGui.QCheckBox(
            self._mainFrame._("Use &secure connection (SSL)"), self)

        self.connect(self._subdomainField,
                     QtCore.SIGNAL('textChanged(QString)'), self.validate)
        self.connect(self._usernameField,
                     QtCore.SIGNAL('textChanged(QString)'), self.validate)
        self.connect(self._passwordField,
                     QtCore.SIGNAL('textChanged(QString)'), self.validate)

        connectionGrid = QtGui.QGridLayout()
        connectionGrid.addWidget(
            QtGui.QLabel(self._mainFrame._("Subdomain:"), self), 1, 0)
        connectionGrid.addWidget(self._subdomainField, 1, 1)
        connectionGrid.addWidget(
            QtGui.QLabel(self._mainFrame._("Username:"******"Password:"******"Campfire connection"))
        connectionGroupBox.setLayout(connectionGrid)

        # Program group

        spellLanguages = {"": self._mainFrame._("No spell check")}

        if SpellTextEditor.canSpell():
            for language in SpellTextEditor.languages():
                spellLanguages[language] = language

        self._connectField = QtGui.QCheckBox(
            self._mainFrame._("Automatically &connect when program starts"),
            self)
        self._joinField = QtGui.QCheckBox(
            self._mainFrame._("&Join last opened channels once connected"),
            self)
        self._minimizeField = QtGui.QCheckBox(
            self._mainFrame._(
                "&Minimize to system tray if window is minimized, or closed"),
            self)
        self._spellLanguageField = QtGui.QComboBox(self)

        spellLanguageBox = QtGui.QHBoxLayout()
        spellLanguageBox.addWidget(
            QtGui.QLabel(self._mainFrame._("Spell checking:"), self))
        spellLanguageBox.addWidget(self._spellLanguageField)
        spellLanguageBox.addStretch(1)

        programGrid = QtGui.QGridLayout()
        programGrid.addWidget(self._connectField, 1, 0)
        programGrid.addWidget(self._joinField, 2, 0)
        programGrid.addWidget(self._minimizeField, 3, 0)
        programGrid.addLayout(spellLanguageBox, 4, 0)

        programGroupBox = QtGui.QGroupBox(
            self._mainFrame._("Program settings"))
        programGroupBox.setLayout(programGrid)

        if not SpellTextEditor.canSpell():
            self._spellLanguageField.setEnabled(False)

        # Away group

        awayTimes = {
            5: self._mainFrame._("5 minutes"),
            10: self._mainFrame._("10 minutes"),
            15: self._mainFrame._("15 minutes"),
            30: self._mainFrame._("30 minutes"),
            45: self._mainFrame._("45 minutes"),
            60: self._mainFrame._("1 hour"),
            90: self._mainFrame._("1 and a half hours"),
            120: self._mainFrame._("2 hours")
        }

        awayBetweenTimes = {
            2: self._mainFrame._("2 minutes"),
            5: self._mainFrame._("5 minutes"),
            10: self._mainFrame._("10 minutes"),
            15: self._mainFrame._("15 minutes"),
            30: self._mainFrame._("30 minutes"),
            45: self._mainFrame._("45 minutes"),
            60: self._mainFrame._("1 hour")
        }

        self._awayField = QtGui.QCheckBox(
            self._mainFrame._("Set me as &away after idle time"), self)
        self._awayTimeField = QtGui.QComboBox(self)
        self._awayMessageField = QtGui.QLineEdit(self)
        self._awayTimeBetweenMessagesField = QtGui.QComboBox(self)

        if IdleTimer.supported():
            self.connect(self._awayField, QtCore.SIGNAL('stateChanged(int)'),
                         self.validate)
            self.connect(self._awayMessageField,
                         QtCore.SIGNAL('textChanged(QString)'), self.validate)
        else:
            self._awayField.setEnabled(False)

        awayTimeBox = QtGui.QHBoxLayout()
        awayTimeBox.addWidget(
            QtGui.QLabel(self._mainFrame._("Idle Time:"), self))
        awayTimeBox.addWidget(self._awayTimeField)
        awayTimeBox.addWidget(QtGui.QLabel(self._mainFrame._("Wait"), self))
        awayTimeBox.addWidget(self._awayTimeBetweenMessagesField)
        awayTimeBox.addWidget(
            QtGui.QLabel(
                self._mainFrame._("before sending consecutive messages"),
                self))
        awayTimeBox.addStretch(1)

        awayMessageBox = QtGui.QHBoxLayout()
        awayMessageBox.addWidget(
            QtGui.QLabel(self._mainFrame._("Message:"), self))
        awayMessageBox.addWidget(self._awayMessageField)

        awayBox = QtGui.QVBoxLayout()
        awayBox.addWidget(self._awayField)
        awayBox.addLayout(awayTimeBox)
        awayBox.addLayout(awayMessageBox)

        awayGroupBox = QtGui.QGroupBox(self._mainFrame._("Away mode"))
        awayGroupBox.setLayout(awayBox)

        # Theme group

        self._themeField = QtGui.QComboBox(self)
        self._themeSizeField = QtGui.QComboBox(self)
        self._themePreview = QtWebKit.QWebView(self)
        self._themePreview.setMaximumHeight(300)

        themeSelectorBox = QtGui.QHBoxLayout()
        themeSelectorBox.addWidget(QtGui.QLabel(self._mainFrame._("Theme:")))
        themeSelectorBox.addWidget(self._themeField)
        themeSelectorBox.addWidget(
            QtGui.QLabel(self._mainFrame._("Text size:")))
        themeSelectorBox.addWidget(self._themeSizeField)
        themeSelectorBox.addStretch(1)

        themeSelectorBox.setContentsMargins(0, 0, 0, 0)
        themeSelectorBox.setSpacing(5)

        themeSelectorFrame = QtGui.QWidget()
        themeSelectorFrame.setLayout(themeSelectorBox)

        themeGrid = QtGui.QGridLayout()
        themeGrid.addWidget(themeSelectorFrame, 1, 0)
        themeGrid.addWidget(self._themePreview, 2, 0)

        themeGroupBox = QtGui.QGroupBox(self._mainFrame._("Theme"))
        themeGroupBox.setLayout(themeGrid)

        # Events group

        self._showJoinMessageField = QtGui.QCheckBox(
            self._mainFrame._("Show &join messages"), self)
        self._showPartMessageField = QtGui.QCheckBox(
            self._mainFrame._("Show p&art messages"), self)
        self._showMessageTimestampsField = QtGui.QCheckBox(
            self._mainFrame._("Show message &timestamps"), self)

        eventsGrid = QtGui.QGridLayout()
        eventsGrid.addWidget(self._showJoinMessageField, 1, 0)
        eventsGrid.addWidget(self._showPartMessageField, 2, 0)
        eventsGrid.addWidget(self._showMessageTimestampsField, 3, 0)

        eventsGroupBox = QtGui.QGroupBox(self._mainFrame._("Display events"))
        eventsGroupBox.setLayout(eventsGrid)

        # Options tab

        optionsBox = QtGui.QVBoxLayout()
        optionsBox.addWidget(connectionGroupBox)
        optionsBox.addWidget(programGroupBox)
        optionsBox.addWidget(awayGroupBox)
        optionsBox.addStretch(1)

        optionsFrame = QtGui.QWidget()
        optionsFrame.setLayout(optionsBox)

        # Display tab

        displayBox = QtGui.QVBoxLayout()
        displayBox.addWidget(themeGroupBox)
        displayBox.addWidget(eventsGroupBox)
        displayBox.addStretch(1)

        displayFrame = QtGui.QWidget()
        displayFrame.setLayout(displayBox)

        # Tabs

        tabs = QtGui.QTabWidget()
        tabs.setTabsClosable(False)

        tabs.addTab(optionsFrame, self._mainFrame._("&Program options"))
        tabs.addTab(displayFrame, self._mainFrame._("&Display options"))

        # Buttons

        self._okButton = QtGui.QPushButton(self._mainFrame._("&OK"), self)
        self._cancelButton = QtGui.QPushButton(self._mainFrame._("&Cancel"),
                                               self)

        self.connect(self._okButton, QtCore.SIGNAL('clicked()'), self.ok)
        self.connect(self._cancelButton, QtCore.SIGNAL('clicked()'),
                     self.cancel)

        # Main layout

        hbox = QtGui.QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(self._okButton)
        hbox.addWidget(self._cancelButton)

        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(tabs)
        vbox.addLayout(hbox)

        self.setLayout(vbox)

        # Load settings

        connectionSettings = self._mainFrame.getSettings("connection")
        programSettings = self._mainFrame.getSettings("program")
        displaySettings = self._mainFrame.getSettings("display")

        self._subdomainField.setText(connectionSettings["subdomain"])
        self._usernameField.setText(connectionSettings["user"])
        if connectionSettings["password"]:
            self._passwordField.setText(connectionSettings["password"])
        self._sslField.setChecked(connectionSettings["ssl"])
        self._connectField.setChecked(connectionSettings["connect"])
        self._joinField.setChecked(connectionSettings["join"])
        self._minimizeField.setChecked(programSettings["minimize"])
        self._awayField.setChecked(programSettings["away"])
        self._awayMessageField.setText(programSettings["away_message"])

        self._showJoinMessageField.setChecked(
            displaySettings["show_join_message"])
        self._showPartMessageField.setChecked(
            displaySettings["show_part_message"])
        self._showMessageTimestampsField.setChecked(
            displaySettings["show_message_timestamps"])

        self._setupThemesUI(displaySettings)

        currentIndex = None
        index = 0
        spellLanguageKeys = spellLanguages.keys()
        spellLanguageKeys.sort()
        for value in spellLanguageKeys:
            self._spellLanguageField.addItem(spellLanguages[value], value)
            if value == programSettings["spell_language"]:
                currentIndex = index
            index += 1

        if currentIndex is not None:
            self._spellLanguageField.setCurrentIndex(currentIndex)

        currentIndex = None
        index = 0
        awayTimeKeys = awayTimes.keys()
        awayTimeKeys.sort()
        for value in awayTimeKeys:
            self._awayTimeField.addItem(awayTimes[value], value)
            if value == int(programSettings["away_time"]):
                currentIndex = index
            index += 1

        if currentIndex is not None:
            self._awayTimeField.setCurrentIndex(currentIndex)

        currentIndex = None
        index = 0
        awayBetweenTimeKeys = awayBetweenTimes.keys()
        awayBetweenTimeKeys.sort()
        for value in awayBetweenTimeKeys:
            self._awayTimeBetweenMessagesField.addItem(awayBetweenTimes[value],
                                                       value)
            if value == int(programSettings["away_time_between_messages"]):
                currentIndex = index
            index += 1

        if currentIndex is not None:
            self._awayTimeBetweenMessagesField.setCurrentIndex(currentIndex)

        self.validate()