Fri, 11 Mar 2011 16:51:57 +0100
Made code mostly PEP 8 compliant (except all whitespace and line length).
# -*- coding: utf-8 -*- # Copyright (c) 2008 - 2011 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the mdi area viewmanager class. """ from PyQt4.QtCore import * from PyQt4.QtGui import * from ViewManager.ViewManager import ViewManager import QScintilla.Editor from QScintilla.Editor import Editor import UI.PixmapCache from E5Gui.E5Action import E5Action, addActions import Utilities class MdiArea(QMdiArea, ViewManager): """ Class implementing the mdi area viewmanager class. @signal changeCaption(str) emitted if a change of the caption is necessary @signal editorChanged(str) emitted when the current editor has changed @signal lastEditorClosed() emitted after the last editor window was closed @signal editorOpened(str) emitted after an editor window was opened @signal editorOpenedEd(Editor) emitted after an editor window was opened @signal editorClosed(str) emitted just before an editor window gets closed @signal editorClosedEd(Editor) emitted just before an editor window gets closed @signal editorSaved(str) emitted after an editor window was saved @signal checkActions(Editor) emitted when some actions should be checked for their status @signal cursorChanged(Editor) emitted after the cursor position of the active window has changed @signal breakpointToggled(Editor) emitted when a breakpoint is toggled. @signal bookmarkToggled(Editor) emitted when a bookmark is toggled. """ changeCaption = pyqtSignal(str) editorChanged = pyqtSignal(str) lastEditorClosed = pyqtSignal() editorOpened = pyqtSignal(str) editorOpenedEd = pyqtSignal(Editor) editorClosed = pyqtSignal(str) editorClosedEd = pyqtSignal(Editor) editorSaved = pyqtSignal(str) checkActions = pyqtSignal(Editor) cursorChanged = pyqtSignal(Editor) breakpointToggled = pyqtSignal(Editor) bookmarkToggled = pyqtSignal(Editor) syntaxerrorToggled = pyqtSignal(Editor) def __init__(self, parent): """ Constructor @param parent parent widget (QWidget) @param ui reference to the main user interface @param dbs reference to the debug server object """ QMdiArea.__init__(self, parent) ViewManager.__init__(self) self.lastFN = '' self.__removingView = False self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.__windowMapper = QSignalMapper(self) self.__windowMapper.mapped[QWidget].connect(self.__mapped) self.subWindowActivated.connect(self.__subWindowActivated) def __mapped(self, subWindow): """ Private slot to handle the activation of a sub window. @param subWindow sub window to be activated (QMdiSubWindow) """ self.setActiveSubWindow(subWindow) def canCascade(self): """ Public method to signal if cascading of managed windows is available. @return flag indicating cascading of windows is available """ return True def canTile(self): """ Public method to signal if tiling of managed windows is available. @return flag indicating tiling of windows is available """ return True def canSplit(self): """ public method to signal if splitting of the view is available. @return flag indicating splitting of the view is available. """ return False def tile(self): """ Public method to tile the managed windows. """ self.tileSubWindows() def cascade(self): """ Public method to cascade the managed windows. """ self.cascadeSubWindows() def _removeAllViews(self): """ Protected method to remove all views (i.e. windows) """ for win in self.editors: self._removeView(win) def _removeView(self, win): """ Protected method to remove a view (i.e. window) @param win editor window to be removed """ self.__removingView = True self.lastFN = '' win.removeEventFilter(self) self.closeActiveSubWindow() win.closeIt() self.__removingView = False def _addView(self, win, fn=None, noName=""): """ Protected method to add a view (i.e. window) @param win editor window to be added @param fn filename of this editor @param noName name to be used for an unnamed editor (string) """ self.addSubWindow(win) if fn is None: if not noName: self.untitledCount += 1 noName = self.trUtf8("Untitled {0}").format(self.untitledCount) win.setWindowTitle(noName) win.setNoName(noName) else: if self.lastFN != fn: self.lastFN = fn win.show() if win.hasSyntaxErrors(): self.__setSubWindowIcon(win, UI.PixmapCache.getIcon("syntaxError.png")) elif win.hasFlakesWarnings(): self.__setSubWindowIcon(win, UI.PixmapCache.getIcon("warning.png")) else: self.__setSubWindowIcon(win, UI.PixmapCache.getIcon("empty.png")) # Make the editor window a little bit smaller to make the whole # window with all decorations visible. This is not the most elegant # solution but more of a workaround for another QWorkspace strangeness. # 25 points are subtracted to give space for the scrollbars pw = win.parentWidget() sz = QSize(self.width() - 25, self.height() - 25) pw.resize(sz) win.setFocus() win.installEventFilter(self) def _showView(self, win, fn=None): """ Private method to show a view (i.e. window) @param win editor window to be shown @param fn filename of this editor (string) """ if fn is not None and self.lastFN != fn: self.lastFN = fn win.show() win.setFocus() def activeWindow(self): """ Private method to return the active (i.e. current) window. @return reference to the active editor """ subWindow = self.activeSubWindow() if subWindow is None: return None else: return subWindow.widget() def showWindowMenu(self, windowMenu): """ Public method to set up the viewmanager part of the Window menu. @param windowMenu reference to the window menu """ self.windowsMenu = QMenu(self.trUtf8('&Windows')) menu = self.windowsMenu idx = 1 for subWindow in self.subWindowList(): sv = subWindow.widget() if idx == 10: menu.addSeparator() menu = menu.addMenu(self.trUtf8("&More")) fn = sv.fileName if fn: txt = Utilities.compactPath(fn, self.ui.maxMenuFilePathLen) else: txt = sv.windowTitle() accel = "" if idx < 10: accel = "&{0:d}. ".format(idx) elif idx < 36: accel = "&{0}. ".format(chr(idx - 9 + ord("@"))) act = menu.addAction("{0}{1}".format(accel, txt)) act.triggered[()].connect(self.__windowMapper.map) self.__windowMapper.setMapping(act, subWindow) idx += 1 addActions(windowMenu, [None, self.nextChildAct, self.prevChildAct, self.tileAct, self.cascadeAct, self.restoreAllAct, self.iconizeAllAct, None]) for act in [self.restoreAllAct, self.iconizeAllAct]: act.setEnabled(len(self.editors) != 0) for act in [self.nextChildAct, self.prevChildAct, self.tileAct, self.cascadeAct]: act.setEnabled(len(self.editors) > 1) act = windowMenu.addMenu(self.windowsMenu) if len(self.editors) == 0: act.setEnabled(False) def _initWindowActions(self): """ Protected method to define the user interface actions for window handling. """ self.tileAct = E5Action(self.trUtf8('Tile'), self.trUtf8('&Tile'), 0, 0, self, 'vm_window_tile') self.tileAct.setStatusTip(self.trUtf8('Tile the windows')) self.tileAct.setWhatsThis(self.trUtf8( """<b>Tile the windows</b>""" """<p>Rearrange and resize the windows so that they are tiled.</p>""" )) self.tileAct.triggered[()].connect(self.tile) self.windowActions.append(self.tileAct) self.cascadeAct = E5Action(self.trUtf8('Cascade'), self.trUtf8('&Cascade'), 0, 0, self, 'vm_window_cascade') self.cascadeAct.setStatusTip(self.trUtf8('Cascade the windows')) self.cascadeAct.setWhatsThis(self.trUtf8( """<b>Cascade the windows</b>""" """<p>Rearrange and resize the windows so that they are cascaded.</p>""" )) self.cascadeAct.triggered[()].connect(self.cascade) self.windowActions.append(self.cascadeAct) self.nextChildAct = E5Action(self.trUtf8('Next'), self.trUtf8('&Next'), 0, 0, self, 'vm_window_next') self.nextChildAct.setStatusTip(self.trUtf8('Activate next window')) self.nextChildAct.setWhatsThis(self.trUtf8( """<b>Next</b>""" """<p>Activate the next window of the list of open windows.</p>""" )) self.nextChildAct.triggered[()].connect(self.activateNextSubWindow) self.windowActions.append(self.nextChildAct) self.prevChildAct = E5Action(self.trUtf8('Previous'), self.trUtf8('&Previous'), 0, 0, self, 'vm_window_previous') self.prevChildAct.setStatusTip(self.trUtf8('Activate previous window')) self.prevChildAct.setWhatsThis(self.trUtf8( """<b>Previous</b>""" """<p>Activate the previous window of the list of open windows.</p>""" )) self.prevChildAct.triggered[()].connect(self.activatePreviousSubWindow) self.windowActions.append(self.prevChildAct) self.restoreAllAct = E5Action(self.trUtf8('Restore All'), self.trUtf8('&Restore All'), 0, 0, self, 'vm_window_restore_all') self.restoreAllAct.setStatusTip(self.trUtf8('Restore all windows')) self.restoreAllAct.setWhatsThis(self.trUtf8( """<b>Restore All</b>""" """<p>Restores all windows to their original size.</p>""" )) self.restoreAllAct.triggered[()].connect(self.__restoreAllWindows) self.windowActions.append(self.restoreAllAct) self.iconizeAllAct = E5Action(self.trUtf8('Iconize All'), self.trUtf8('&Iconize All'), 0, 0, self, 'vm_window_iconize_all') self.iconizeAllAct.setStatusTip(self.trUtf8('Iconize all windows')) self.iconizeAllAct.setWhatsThis(self.trUtf8( """<b>Iconize All</b>""" """<p>Iconizes all windows.</p>""" )) self.iconizeAllAct.triggered[()].connect(self.__iconizeAllWindows) self.windowActions.append(self.iconizeAllAct) def setEditorName(self, editor, newName): """ Public method to change the displayed name of the editor. @param editor editor window to be changed @param newName new name to be shown (string) """ pass def __setSubWindowIcon(self, widget, icon): """ Private method to set the icon of a subwindow given it's internal widget. @param widget reference to the internal widget (QWidget) @param icon reference to the icon (QIcon) """ for subWindow in self.subWindowList(): if subWindow.widget() == widget: subWindow.setWindowIcon(icon) return def _modificationStatusChanged(self, m, editor): """ Protected slot to handle the modificationStatusChanged signal. @param m flag indicating the modification status (boolean) @param editor editor window changed """ if m: self.__setSubWindowIcon(editor, UI.PixmapCache.getIcon("fileModified.png")) elif editor.hasSyntaxErrors(): self.__setSubWindowIcon(editor, UI.PixmapCache.getIcon("syntaxError.png")) elif editor.hasFlakesWarnings(): self.__setSubWindowIcon(editor, UI.PixmapCache.getIcon("warning.png")) else: self.__setSubWindowIcon(editor, UI.PixmapCache.getIcon("empty.png")) self._checkActions(editor) def _syntaxErrorToggled(self, editor): """ Protected slot to handle the syntaxerrorToggled signal. @param editor editor that sent the signal """ if editor.hasSyntaxErrors(): self.__setSubWindowIcon(editor, UI.PixmapCache.getIcon("syntaxError.png")) elif editor.hasFlakesWarnings(): self.__setSubWindowIcon(editor, UI.PixmapCache.getIcon("warning.png")) else: self.__setSubWindowIcon(editor, UI.PixmapCache.getIcon("empty.png")) ViewManager._syntaxErrorToggled(self, editor) def __subWindowActivated(self, subWindow): """ Private slot to handle the windowActivated signal. @param subWindow the activated subwindow (QMdiSubWindow) """ if subWindow is not None: editor = subWindow.widget() self._checkActions(editor) if editor is not None: fn = editor.getFileName() self.editorChanged.emit(fn) def eventFilter(self, watched, event): """ Public method called to filter the event queue. @param watched the QObject being watched @param event the event that occurred @return flag indicating, whether the event was handled (boolean) """ if event.type() == QEvent.Close and \ not self.__removingView and \ isinstance(watched, QScintilla.Editor.Editor): watched.close() return True return QMdiArea.eventFilter(self, watched, event) def __restoreAllWindows(self): """ Private slot to restore all windows. """ for win in self.subWindowList(): win.showNormal() def __iconizeAllWindows(self): """ Private slot to iconize all windows. """ for win in self.subWindowList(): win.showMinimized()