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))
class MainWindow(KMainWindow, Ui_MainWindow, MjpegStreamingConsumerInterface): def __init__(self, args, parent=None): self.args = args #super(MainWindow, self).__init__() #PsyQtClientBase.__init__(self) KMainWindow.__init__(self, parent) self.is_streaming = False self.live_center_action = None self.preview_center_action = None self.live_size_action = None self.preview_font_action = None self.live_font_action = None self.preview_size_action = None self.default_size = 28 self.default_align_text = "format_align_center" self.preview_actions = list() self.live_actions = list() self.current = 0 self.model = TextModel(self) self.animation = TextAnimation(self) self.db_dirty = False self.is_animate = False self.fade_animation = None self.dialog = None self.current_object = None self.current_index = -1 self.is_auto_publish = False self.setupUi(self) self.win_id = self.live_text.winId() self.fps = 12.5 self.http_server = MjpegStreamingServer( (args.http_host, args.http_port), self, self.fps) self.live_text.setLineWrapMode( QtGui.QTextEdit.LineWrapMode(QtGui.QTextEdit.FixedPixelWidth)) self.live_text.setLineWrapColumnOrWidth(768) self.font = QtGui.QFont("monospace", self.default_size) self.font.setStyleHint(QtGui.QFont.TypeWriter) self.previous_action = None self.next_action = None self.publish_action = None self.auto_publish_action = None self.save_live_action = None self.save_preview_action = None self.save_action = None self.dialog_widget = None self.action_collection = None self.streaming_action = None self.text_combo = None self.clear_live_action = None self.clear_preview_action = None self.toolbar = None self.typer_animation_action = None self.text_editor_action = None self.preview_text.setFont(self.font) self.preview_text.setRichTextSupport( KRichTextWidget.RichTextSupport(0xffffffff)) self.preview_editor_collection = KActionCollection(self) self.preview_text.createActions(self.preview_editor_collection) self.live_text.setRichTextSupport( KRichTextWidget.RichTextSupport(0xffffffff)) self.live_text.setFont(self.font) self.live_editor_collection = KActionCollection(self) self.live_text.createActions(self.live_editor_collection) self.filter_editor_actions() self.create_toolbar() self.slot_load() qtapp.focusChanged.connect(self.focusChanged) self.start_streaming() self.show() timer = QtCore.QTimer() timer.start(2000) timer.timeout.connect(lambda: None) def pubdir(self): return os.path.dirname(os.path.abspath(__file__)) def getPreviewCoords(self): public_rect = self.preview_text.geometry() global_rect = QtCore.QRect(self.mapToGlobal(public_rect.topLeft()), self.mapToGlobal(public_rect.bottomRight())) return global_rect.x(), global_rect.y() def render_image(self): public_rect = self.live_text_rect() #global_rect = QtCore.QRect(self.mapToGlobal(public_rect.topLeft()), self.mapToGlobal(public_rect.bottomRight())) pixmap = QPixmap.grabWindow(self.win_id, public_rect.x() + 1, public_rect.y() + 1, 768, 576) buf = QBuffer() buf.open(QIODevice.WriteOnly) pixmap.save(buf, "JPG", 75) return buf.data() def filter_editor_actions(self): disabled_action_names = [ "action_to_plain_text", "format_painter", "direction_ltr", "direction_rtl", "format_font_family", "format_text_background_color", "format_list_style", "format_list_indent_more", "format_list_indent_less", "format_text_bold", "format_text_underline", "format_text_strikeout", "format_text_italic", "format_align_right", "manage_link", "format_text_subscript", "format_text_superscript", "insert_horizontal_rule" ] for action in self.live_editor_collection.actions(): text = str(action.objectName()) if text in disabled_action_names: action.setVisible(False) if text == self.default_align_text: self.live_center_action = action elif text == "format_font_size": self.live_size_action = action elif text == "format_font_family": self.live_font_action = action for action in self.preview_editor_collection.actions(): text = str(action.objectName()) if text in disabled_action_names: action.setVisible(False) if text == self.default_align_text: self.preview_center_action = action elif text == "format_font_size": self.preview_size_action = action elif text == "format_font_family": self.preview_font_action = action self.slot_set_preview_defaults() self.slot_set_live_defaults() def create_toolbar(self): self.toolbar = KToolBar(self, True, True) self.toolbar.setIconDimensions(16) self.toolbar.setAllowedAreas(QtCore.Qt.BottomToolBarArea) self.toolbar.setMovable(False) self.toolbar.setFloatable(False) self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) self.addToolBar(QtCore.Qt.BottomToolBarArea, self.toolbar) self.toolbar.show() self.action_collection = KActionCollection(self) self.action_collection.addAssociatedWidget(self.toolbar) self.clear_live_action = self.action_collection.addAction( "clear_live_action") icon = QtGui.QIcon(":texter/images/edit-clear.png") self.clear_live_action.setIcon(icon) self.clear_live_action.setIconText("clear live") self.clear_live_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Q)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.save_live_action = self.action_collection.addAction( "save_live_action") icon = QtGui.QIcon(":texter/images/document-new.png") self.save_live_action.setIcon(icon) self.save_live_action.setIconText("save live") self.save_live_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_W)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.clear_preview_action = self.action_collection.addAction( "clear_preview_action") icon = QtGui.QIcon(":texter/images/edit-clear.png") self.clear_preview_action.setIcon(icon) self.clear_preview_action.setIconText("clear preview") self.clear_preview_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_A)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.save_preview_action = self.action_collection.addAction( "save_preview_action") icon = QtGui.QIcon(":texter/images/document-new.png") self.save_preview_action.setIcon(icon) self.save_preview_action.setIconText("save preview") self.save_preview_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_S)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.publish_action = self.action_collection.addAction( "publish_action") icon = QtGui.QIcon(":texter/images/edit-copy.png") self.publish_action.setIcon(icon) self.publish_action.setIconText("publish") self.publish_action.setShortcutConfigurable(True) self.publish_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Return)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.toolbar.insertSeparator(self.publish_action) self.auto_publish_action = KToggleAction(self.action_collection) self.action_collection.addAction("auto publish", self.auto_publish_action) icon = QtGui.QIcon(":texter/images/view-refresh.png") self.auto_publish_action.setIcon(icon) self.auto_publish_action.setObjectName("auto_publish_action") self.auto_publish_action.setIconText("auto publish") self.auto_publish_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_P)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.typer_animation_action = KToggleAction(self.action_collection) icon = QtGui.QIcon(":texter/images/media-playback-stop.png") self.typer_animation_action.setIcon(icon) self.typer_animation_action.setIconText("animate") self.typer_animation_action.setObjectName("typer_animation_action") self.typer_animation_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_M)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.action_collection.addAction("typer_animation_action", self.typer_animation_action) self.text_editor_action = self.action_collection.addAction( "text_editor_action") icon = QtGui.QIcon(":texter/images/document-open-data.png") self.text_editor_action.setIcon(icon) self.text_editor_action.setIconText("edit") self.text_editor_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_O)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.toolbar.insertSeparator(self.text_editor_action) self.save_action = self.action_collection.addAction("save_action") icon = QtGui.QIcon(":texter/images/document-save.png") self.save_action.setIcon(icon) self.save_action.setIconText("save") self.save_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_S)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.streaming_action = KToggleAction(self.action_collection) icon = QtGui.QIcon(":texter/images/media-record.png") self.streaming_action.setIcon(icon) self.streaming_action.setIconText("stream") self.streaming_action.setObjectName("stream") self.streaming_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_1)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.action_collection.addAction("stream", self.streaming_action) spacer = KToolBarSpacerAction(self.action_collection) self.action_collection.addAction("1_spacer", spacer) self.previous_action = self.action_collection.addAction( "previous_action") icon = QtGui.QIcon(":texter/images/go-previous-view-page.png") self.previous_action.setIcon(icon) self.previous_action.setIconText("previous") self.previous_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Left)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.text_combo = KSelectAction(self.action_collection) self.text_combo.setEditable(False) icon = QtGui.QIcon(":texter/images/document-open-recent.png") self.text_combo.setIcon(icon) self.text_combo.setIconText("saved texts") self.text_combo.setObjectName("text_combo") self.action_collection.addAction("saved texts", self.text_combo) self.next_action = self.action_collection.addAction("next_action") icon = QtGui.QIcon(":texter/images/go-next-view-page.png") self.next_action.setIcon(icon) self.next_action.setIconText("next") self.next_action.setShortcut( KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Right)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut)) self.toolbar.addSeparator() self.save_action.triggered.connect(self.slot_save) self.publish_action.triggered.connect(self.slot_publish) self.clear_live_action.triggered.connect(self.slot_clear_live) self.clear_preview_action.triggered.connect(self.slot_clear_preview) self.text_combo.triggered[int].connect(self.slot_load_preview_text) self.text_editor_action.triggered.connect(self.slot_open_dialog) self.save_live_action.triggered.connect(self.slot_save_live_text) self.save_preview_action.triggered.connect(self.slot_save_preview_text) self.streaming_action.triggered.connect(self.slot_toggle_streaming) self.auto_publish_action.toggled.connect(self.slot_auto_publish) self.typer_animation_action.toggled.connect(self.slot_toggle_animation) self.preview_size_action.triggered[QtGui.QAction].connect( self.slot_preview_font_size) self.live_size_action.triggered[QtGui.QAction].connect( self.slot_live_font_size) self.next_action.triggered.connect(self.slot_next_item) self.previous_action.triggered.connect(self.slot_previous_item) self.streaming_action.setChecked(True) def closeEvent(self, event): logger.info("closeEvent") if self.db_dirty: self.dialog = KDialog(self) self.dialog.setCaption("4.48 texter - text db not saved") label = QtGui.QLabel( "The Text database is not saved. Do you want to save before exit?", self.dialog) self.dialog.setMainWidget(label) self.dialog.setButtons( KDialog.ButtonCodes(KDialog.Ok | KDialog.Cancel)) self.dialog.okClicked.connect(self.slot_save) self.dialog.exec_() event.accept() def live_text_rect(self): return self.live_text.geometry() def stop_streaming(self): self.is_streaming = False self.http_server.stop() def start_streaming(self): self.http_server.listen(port=self.args.http_port) self.is_streaming = True def fill_combo_box(self): if self.dialog is not None: self.dialog.deleteLater() self.dialog = None self.text_combo.clear() current_row = -1 for index, list_obj in enumerate(self.model.text_db): preview, text = list_obj self.text_combo.addAction(preview) if list_obj == self.current_object: current_row = index if current_row == -1: current_row = self.current_index self.slot_load_preview_text(current_row) self.text_combo.setCurrentItem(current_row) def focusChanged(self, old, new): if new == self.preview_text: self.live_editor_collection.clearAssociatedWidgets() self.preview_editor_collection.addAssociatedWidget(self.toolbar) elif new == self.live_text: self.preview_editor_collection.clearAssociatedWidgets() self.live_editor_collection.addAssociatedWidget(self.toolbar) def slot_auto_publish(self, state): self.is_auto_publish = bool(state) def slot_toggle_animation(self, state): self.is_animate = bool(state) def slot_toggle_streaming(self): if self.is_streaming: self.stop_streaming() else: self.start_streaming() def slot_next_item(self): try: self.current = (self.text_combo.currentItem() + 1) % len( self.model.text_db) self.text_combo.setCurrentItem(self.current) self.slot_load_preview_text(self.current) except ZeroDivisionError: pass def slot_previous_item(self): try: self.current = (self.text_combo.currentItem() - 1) % len( self.model.text_db) self.text_combo.setCurrentItem(self.current) self.slot_load_preview_text(self.current) except ZeroDivisionError: pass def slot_publish(self): if self.is_animate: self.animation.start_animation(self.preview_text, self.live_text, 0) else: self.live_text.setTextOrHtml(self.preview_text.textOrHtml()) def slot_live_font_size(self, action): self.default_size = self.live_size_action.fontSize() self.slot_set_preview_defaults() self.slot_set_live_defaults() def slot_preview_font_size(self, action): self.default_size = self.preview_size_action.fontSize() self.slot_set_live_defaults() self.slot_set_preview_defaults() def slot_toggle_publish(self, state=None): if state: self.slot_publish() else: self.slot_clear_live() def slot_set_preview_defaults(self): self.preview_center_action.setChecked(True) self.preview_text.alignCenter() self.font.setPointSize(self.default_size) self.preview_text.setFontSize(self.default_size) self.preview_text.setFont(self.font) self.preview_size_action.setFontSize(self.default_size) self.preview_text.document().setDefaultFont(self.font) def slot_set_live_defaults(self): self.live_center_action.setChecked(True) self.live_text.alignCenter() self.live_text.setFontSize(self.default_size) self.live_size_action.setFontSize(self.default_size) self.live_text.document().setDefaultFont(self.font) def slot_clear_live(self): self.live_text.clear() self.slot_set_live_defaults() def slot_clear_preview(self): self.preview_text.clear() self.slot_set_preview_defaults() def slot_fade(self): if self.fade_animation.timer is None: self.fade_animation.start_animation() def slot_load_preview_text(self, index): try: preview, text = self.model.text_db[index] except IndexError: return self.preview_text.setTextOrHtml(text) if self.is_auto_publish: self.slot_publish() def slot_save_live_text(self): text = self.live_text.toHtml() preview = get_preview_text(unicode(self.live_text.toPlainText())) if not preview: return old_item = self.model.text_by_preview(preview) if old_item is not None: suffix = 1 while 1: tmp_preview = "%s_%d" % (preview, suffix) tmp = self.model.text_by_preview(tmp_preview) if tmp is None: preview = tmp_preview break else: suffix += 1 self.model.text_db.append([preview, text]) self.model.modelReset.emit() action = self.text_combo.addAction(preview) self.text_combo.setCurrentAction(action) self.db_dirty = True def slot_save_preview_text(self): text = self.preview_text.toHtml() preview = get_preview_text(unicode(self.preview_text.toPlainText())) if not preview: return old_item = self.model.text_by_preview(preview) if old_item is not None: ix, old_preview, old_text = old_item self.model.text_db[ix][1] = text else: self.model.text_db.append([preview, text]) action = self.text_combo.addAction(preview) self.model.modelReset.emit() self.text_combo.setCurrentAction(action) self.db_dirty = True def slot_save(self): path = os.path.expanduser("~/.texter") if not os.path.isdir(path): os.mkdir(path) try: f = open(os.path.join(path, "texter.db"), "w") except IOError: return else: cPickle.dump(self.model.text_db, f, cPickle.HIGHEST_PROTOCOL) self.db_dirty = False def slot_open_dialog(self): self.current_index = self.text_combo.currentItem() self.current_object = self.model.text_db[self.current_index] if self.dialog is not None: self.dialog.deleteLater() self.dialog = None self.dialog = KDialog(self) self.dialog.setButtons(KDialog.Close) self.dialog_widget = EditDialog(self.dialog) self.dialog.setMainWidget(self.dialog_widget) pos_x, pos_y = self.getPreviewCoords() self.dialog.move(pos_x, self.pos().y()) self.dialog.exec_() self.fill_combo_box() def slot_load(self): path = os.path.expanduser("~/.texter") if not os.path.isdir(path): os.mkdir(path) try: db_file = open(os.path.join(path, "texter.db")) except IOError: return try: self.model.text_db = [list(i) for i in cPickle.load(db_file)] except ValueError, error: logger.exception(error) self.fill_combo_box() self.text_combo.setCurrentItem(0) self.slot_load_preview_text(0)