class MainWindow(KXmlGuiWindow): CHOOSER_PLUGINS = [ # TODO reenable (radicalpage.RadicalPage, ki18n('&Radicals')), (componentpage.ComponentPage, ki18n('&Components')), (handwritingpage.HandwritingPage, ki18n('Hand&writing')), (vocabularypage.VocabularyPage, ki18n('&Vocabulary')), ] """Plugins loaded into the side panel.""" def __init__(self): QMainWindow.__init__(self) self.miniMode = False self.initialised = False # set i18n language for libeclectus setTranslationLanguage(unicode(KGlobal.locale().language())) # start rendering thread self.renderThread = renderthread.SQLRenderThread(g_app) self.connect(g_app, SIGNAL("aboutToQuit()"), self.renderThread.quit) self.renderThread.start() self.connect(self.renderThread, SIGNAL("queueEmpty"), self.queueEmpty) self.connect(self.renderThread, SIGNAL("jobEnqueued"), self.jobEnqueued) self.connect(self.renderThread, SIGNAL("jobErrorneous"), lambda jobId, classObject, method, args, param, e, stacktrace: \ showDebug(stacktrace.decode('utf8'))) self.updateDialog = update.UpdateDialog(self, self.renderThread) #self.updateDialog = None # set to None to disable updating if self.updateDialog: self.connect(self.updateDialog, SIGNAL("databaseChanged()"), lambda: self.emit(SIGNAL("databaseChanged()"))) # set up UI self.setupUi() self.setupActions() # finally build gui xmlFile = os.path.join(os.getcwd(), 'eclectusqt', 'eclectusui.rc') if os.path.exists(xmlFile): self.setupGUI(KXmlGuiWindow.StandardWindowOption( KXmlGuiWindow.Default ^ KXmlGuiWindow.StatusBar), xmlFile) else: self.setupGUI(KXmlGuiWindow.StandardWindowOption( KXmlGuiWindow.Default ^ KXmlGuiWindow.StatusBar)) self.restoreWindowState() self.setCentralWidget(self.splitterFrame) self.splitterFrame.setVisible(True) self.initialised = True if (GeneralConfig.readEntry("Show installer on startup", 'True') == 'True') and self.updateAction: self.updateAction.trigger() def setupUi(self): self.setWindowIcon(QIcon(util.getIcon('eclectus.png'))) self.splitterFrame = QtGui.QSplitter(self) self.splitterFrame.setOrientation(QtCore.Qt.Horizontal) self.characterChooser = QtGui.QToolBox(self.splitterFrame) self.characterChooser.setFrameShape(QtGui.QFrame.StyledPanel) self.dictionaryPage = dictionarypage.DictionaryPage(self, self.renderThread, PluginConfig) self.connect(self.dictionaryPage, SIGNAL('pageChanged(const QString &)'), self.slotPageChanged) # forward settingsChanged self.connect(self.dictionaryPage, SIGNAL("settingsChanged()"), lambda: self.emit(SIGNAL("settingsChanged()"))) # TODO make this modular self.connect(self.dictionaryPage, SIGNAL("vocabularyAdded(const QString &, const QString &, const QString &, const QString &)"), self.slotVocabularyAdded) self.connect(self.dictionaryPage, SIGNAL("modeChanged(bool)"), self.slotMiniMode) self.splitterFrame.addWidget(self.characterChooser) self.splitterFrame.addWidget(self.dictionaryPage) # load sidebar plugins self.plugins = [] self.vocabularyPlugin = None for classObj, heading in self.CHOOSER_PLUGINS: page = classObj(self, self.renderThread, PluginConfig) if not self.vocabularyPlugin \ and isinstance(page, vocabularypage.VocabularyPage): self.vocabularyPlugin = len(self.plugins) self.characterChooser.addItem(page, heading.toString()) self.connect(page, SIGNAL('inputReceived(const QString &)'), self.dictionaryPage.load) self.plugins.append(page) self.splitterFrame.setVisible(False) self.setCentralWidget(QLabel(i18n('Installing basic tables...'))) def setupActions(self): """Sets up all actions (signal/slot combinations).""" # standard action KStandardAction.quit(g_app.quit, self.actionCollection()) # dictionary actions self.dictionaryPage.registerGlobalActions(self.actionCollection()) # update dictionaries if self.updateDialog: self.updateAction = self.updateDialog.updateAction( self.actionCollection()) # optimise database self.updateDialog.optimiseAction(self.actionCollection()) else: self.updateAction = None # search bar self.characterCombo = KHistoryComboBox() self.characterCombo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) font = QFont() font.setPointSize(13) self.characterCombo.setFont(font) self.characterCombo.setObjectName("characterCombo") self.connect(self.characterCombo, SIGNAL("activated(const QString &)"), self.slotCharacterComboActivated) comboAction = KAction(self) comboAction.setText(i18n("Search bar")) comboAction.setShortcut(Qt.Key_F6) self.connect(comboAction, SIGNAL("triggered()"), self.slotSearchComboActivated) comboAction.setDefaultWidget(self.characterCombo) comboAction.setWhatsThis( i18n("<html>Search bar<br/><br/>Enter character of search string</html>")) self.actionCollection().addAction("searchbar", comboAction) goUrl = self.actionCollection().addAction("go_search") goUrl.setIcon(KIcon("go-jump-locationbar")) goUrl.setText(i18n("Go")) self.connect(goUrl, SIGNAL("triggered()"), lambda: self.slotCharacterComboActivated( self.characterCombo.currentText())) goUrl.setWhatsThis( i18n("<html>Go<br /><br />Searches for the string given in the search bar.</html>")) # clear search bar action clearLocationAction = KAction(KIcon("edit-clear-locationbar-ltr"), i18n("Clear &Location Bar"), self) clearLocationAction.setShortcut(Qt.CTRL + Qt.Key_L) clearLocationAction.setWhatsThis( i18n("Clears the location bar and places the cursor inside")) self.actionCollection().addAction("clearlocationbar", clearLocationAction) self.connect(clearLocationAction, SIGNAL("triggered(bool)"), self.characterCombo.clearEditText) self.connect(clearLocationAction, SIGNAL("triggered(bool)"), self.characterCombo.setFocus) # show/hide character page self.toggleToolboxAction = KToggleAction(KIcon("view-sidetree"), i18n("Show Character Toolbox"), self) self.toggleToolboxAction.setShortcut(Qt.Key_F9) self.toggleToolboxAction.setWhatsThis( i18n("Shows and Hides the character choosing toolbox")) self.actionCollection().addAction("showtoolbox", self.toggleToolboxAction) self.connect(self.toggleToolboxAction, SIGNAL("triggered(bool)"), self.slotToggleToolbox) # auto-lookup clipboard self.autoLookupAction = KToggleAction(i18n("&Auto-Lookup"), self) self.autoLookupAction.setToolTip( i18n("Automatically look up text selected by the mouse cursor.")) self.autoLookupAction.setWhatsThis( i18n("Automatically look up text selected by the mouse cursor.")) self.actionCollection().addAction("autolookup", self.autoLookupAction) self.connect(self.autoLookupAction, SIGNAL("triggered(bool)"), self.setAutoLookup) self.autoLookupAction.setIcon( QIcon(util.getIcon('auto-lookup-selection.png'))) self.connect(QApplication.clipboard(), SIGNAL("selectionChanged()"), self.slotSelectionChanged) def restoreWindowState(self): # GUI settings history = util.readConfigString(GeneralConfig, "Url History", '')\ .split(',') self.characterCombo.insertItems(history) self.historyLength = util.readConfigInt(GeneralConfig, "History Length", 20) self.autoLookup = util.readConfigString(GeneralConfig, "Auto-Lookup clipboard", str(False)) != "False" self.autoLookupAction.setChecked(self.autoLookup) self.onlyAutoLookupCJKCharacters = util.readConfigString(GeneralConfig, "Auto-Lookup only Chinese characters", str(False)) != "False" self.splitterFrame.restoreState(QByteArray.fromBase64( str(util.readConfigString(GeneralConfig, "Splitter", "")))) self.splitterSizes = [int(i) for i \ in util.readConfigString(GeneralConfig, "Splitter sizes", "220,426").split(',')] self.toolbarOriginalState = QByteArray.fromBase64( str(util.readConfigString(GeneralConfig, "Toolbar original state", ""))) self.restoreState(self.toolbarOriginalState) self.menuBar().setVisible(True) self.characterChooser.setCurrentIndex(util.readConfigInt(GeneralConfig, "Toolbox current", 0)) visible = GeneralConfig.readEntry("Toolbox visibile", str(True)) if visible == "False": self.characterChooserOriginalVisibility = False else: self.splitterFrame.setSizes(self.splitterSizes) self.characterChooserOriginalVisibility = True self.characterChooser.setVisible( self.characterChooserOriginalVisibility) self.toggleToolboxAction.setChecked( self.characterChooserOriginalVisibility) w = util.readConfigInt(GeneralConfig, "Width", 640) h = util.readConfigInt(GeneralConfig, "Height", 420) self.defaultWindowSize = QSize(w, h) x = util.readConfigInt(GeneralConfig, "LastX", 0) y = util.readConfigInt(GeneralConfig, "LastY", 0) mini_w = util.readConfigInt(GeneralConfig, "Mini-mode Width", 400) mini_h = util.readConfigInt(GeneralConfig, "Mini-mode Height", 200) self.miniModeWindowSize = QSize(mini_w, mini_h) self.setGeometry(x, y, w, h) def queryExit(self): """ save config data before exiting """ self.emit(SIGNAL("writeSettings()")) if self.miniMode: self.miniModeWindowSize = self.size() else: self.defaultWindowSize = self.size() GeneralConfig.writeEntry("Width", str(self.defaultWindowSize.width())) GeneralConfig.writeEntry("Height", str(self.defaultWindowSize.height())) GeneralConfig.writeEntry("LastX", str(self.x())) GeneralConfig.writeEntry("LastY", str(self.y())) GeneralConfig.writeEntry("Mini-mode Width", str(self.miniModeWindowSize.width())) GeneralConfig.writeEntry("Mini-mode Height", str(self.miniModeWindowSize.height())) GeneralConfig.writeEntry("Show installer on startup", 'False') GeneralConfig.writeEntry("Url History", self.characterCombo.historyItems()[:self.historyLength]) GeneralConfig.writeEntry("Splitter", QByteArray.toBase64(self.splitterFrame.saveState())) GeneralConfig.writeEntry("Auto-Lookup clipboard", str(self.autoLookup)) GeneralConfig.writeEntry("Auto-Lookup only Chinese characters", str(self.onlyAutoLookupCJKCharacters)) # toolbox if self.characterChooser.isVisible(): self.splitterSizes = self.splitterFrame.sizes() GeneralConfig.writeEntry("Splitter sizes", ",".join( [str(i) for i in self.splitterSizes])) if not self.miniMode: self.toolbarOriginalState = self.saveState(0) GeneralConfig.writeEntry("Toolbar original state", QByteArray.toBase64(self.toolbarOriginalState)) GeneralConfig.writeEntry("Toolbox current", str(self.characterChooser.currentIndex())) GeneralConfig.writeEntry("Toolbox visibile", str(self.characterChooserOriginalVisibility)) return True def settings(self): return self.dictionaryPage.settings() def slotToggleToolbox(self, show): if not self.miniMode: self.showToolbox(show) self.characterChooserOriginalVisibility = show def showToolbox(self, show): # save / restore size as hiding makes Qt forget if self.characterChooser.isVisible(): self.splitterSizes = self.splitterFrame.sizes() else: self.splitterFrame.setSizes(self.splitterSizes) self.characterChooser.setVisible(show) def slotMiniMode(self, miniMode): self.miniMode = miniMode if not self.miniMode: # restore original state if given if self.toolbarOriginalState: self.restoreState(self.toolbarOriginalState, 0) self.menuBar().setVisible(True) self.showToolbox(self.characterChooserOriginalVisibility) self.miniModeWindowSize = self.size() self.resize(self.defaultWindowSize) else: # save original state of toolbars self.toolbarOriginalState = self.saveState(0) for toolbar in self.toolBars(): toolbar.setVisible(False) self.menuBar().setVisible(False) self.characterChooserOriginalVisibility \ = self.characterChooser.isVisible() self.showToolbox(False) self.defaultWindowSize = self.size() self.resize(self.miniModeWindowSize) # tell user what to do # TODO renable #miniModeShortcut = unicode(i18n( #self.miniModeAction.shortcut().toString())) #text = unicode(i18n("Mini-mode hides your menubar and toolbars. Press %1 again to get back to normal mode.", miniModeShortcut)) #lookupShortcut = self.lookupClipboardAction.globalShortcut()\ #.toString(QtGui.QKeySequence.NativeText) #if lookupShortcut: #text = text + "\n\n" \ #+ unicode(i18n("You may look up entries by selecting a word and pressing %1. Alternatively you can turn on auto-lookup or paste from the clipboard by pressing the middle mouse button.", #i18n(lookupShortcut))) #KMessageBox.information(self, text, i18n("Mini-mode"), #"show_mini-mode_notice") def slotCharacterComboActivated(self, inputString): self.characterCombo.addToHistory(inputString) self.dictionaryPage.load(inputString) self.dictionaryPage.setFocus() def slotSearchComboActivated(self): self.characterCombo.setFocus() self.characterCombo.lineEdit().selectAll() def setAutoLookup(self, selected): self.autoLookup = selected def slotSelectionChanged(self): if self.autoLookup: # don't auto lookup when user is editing one of our edit widgets focusWidget = QApplication.focusWidget() if focusWidget: for editWidgetCls in [kdeui.KHistoryComboBox, kdeui.KLineEdit]: if isinstance(focusWidget, editWidgetCls): return clipboardText = unicode(QApplication.clipboard().text( QClipboard.Selection).simplified()).strip() if not clipboardText or len(clipboardText) >= 20: return if (self.onlyAutoLookupCJKCharacters and not MainWindow.hasCJKCharacter(clipboardText)): return self.dictionaryPage.load(clipboardText) # make window flash in taskbar self.activateWindow() @staticmethod def hasCJKCharacter(string): """ Simple function for telling if a Chinese character or other CJK script is present. """ for char in string: if getCJKScriptClass(char) != None: return True return False def slotPageChanged(self, pageName): # dictionary page changed self.emit(SIGNAL("pageRequested(const QString &)"), pageName) # Temporarily hide default internal pageTypes if unicode(pageName).count(':'): pageType, page = unicode(pageName).split(':') if pageType in ['character', 'word']: pageName = page self.characterCombo.setEditText(pageName) # TODO mask page type def slotVocabularyAdded(self, headword, reading, translation, audio): self.emit(SIGNAL("vocabularyAdded(const QString &, const QString &, const QString &, const QString &)"), headword, reading, translation, audio) if self.vocabularyPlugin != None: self.characterChooser.setCurrentIndex(self.vocabularyPlugin) def queueEmpty(self): QApplication.restoreOverrideCursor() def jobEnqueued(self, jobId): if not QApplication.overrideCursor(): QApplication.setOverrideCursor(QCursor(Qt.BusyCursor))