Plugins/ViewManagerPlugins/Tabview/Tabview.py

changeset 0
de9c2efb9d02
child 7
c679fb30c8f3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/ViewManagerPlugins/Tabview/Tabview.py	Mon Dec 28 16:03:33 2009 +0000
@@ -0,0 +1,1098 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2002 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a tabbed viewmanager class.
+"""
+
+import os
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from E4Gui.E4Application import e4App
+
+from ViewManager.ViewManager import ViewManager
+
+import QScintilla.Editor
+
+import UI.PixmapCache
+
+from E4Gui.E4TabWidget import E4TabWidget, E4WheelTabBar
+from E4Gui.E4Led import E4Led
+
+import Preferences
+
+from eric4config import getConfig
+
+class TabBar(E4WheelTabBar):
+    """
+    Class implementing a customized tab bar supporting drag & drop.
+    
+    @signal tabMoveRequested(int, int) emitted to signal a tab move request giving
+        the old and new index position
+    @signal tabRelocateRequested(long, int, int) emitted to signal a tab relocation
+        request giving the id of the old tab widget, the index in the old tab widget
+        and the new index position
+    @signal tabCopyRequested(long, int, int) emitted to signal a clone request
+        giving the id of the source tab widget, the index in the source tab widget
+        and the new index position
+    @signal tabCopyRequested(int, int) emitted to signal a clone request giving
+        the old and new index position
+    """
+    def __init__(self, parent = None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        E4WheelTabBar.__init__(self, parent)
+        self.setAcceptDrops(True)
+        
+        self.__dragStartPos = QPoint()
+    
+    def mousePressEvent(self, event):
+        """
+        Protected method to handle mouse press events.
+        
+        @param event reference to the mouse press event (QMouseEvent)
+        """
+        if event.button() == Qt.LeftButton:
+            self.__dragStartPos = QPoint(event.pos())
+        E4WheelTabBar.mousePressEvent(self, event)
+    
+    def mouseMoveEvent(self, event):
+        """
+        Protected method to handle mouse move events.
+        
+        @param event reference to the mouse move event (QMouseEvent)
+        """
+        if event.buttons() == Qt.MouseButtons(Qt.LeftButton) and \
+           (event.pos() - self.__dragStartPos).manhattanLength() > \
+                QApplication.startDragDistance():
+            drag = QDrag(self)
+            mimeData = QMimeData()
+            index = self.tabAt(event.pos())
+            mimeData.setText(self.tabText(index))
+            mimeData.setData("action", "tab-reordering")
+            mimeData.setData("tabbar-id", QByteArray.number(id(self)))
+            mimeData.setData("source-index", 
+                             QByteArray.number(self.tabAt(self.__dragStartPos)))
+            mimeData.setData("tabwidget-id", QByteArray.number(id(self.parentWidget())))
+            drag.setMimeData(mimeData)
+            if event.modifiers() == Qt.KeyboardModifiers(Qt.ShiftModifier):
+                drag.exec_(Qt.DropActions(Qt.CopyAction))
+            elif event.modifiers() == Qt.KeyboardModifiers(Qt.NoModifier):
+                drag.exec_(Qt.DropActions(Qt.MoveAction))
+        E4WheelTabBar.mouseMoveEvent(self, event)
+    
+    def dragEnterEvent(self, event):
+        """
+        Protected method to handle drag enter events.
+        
+        @param event reference to the drag enter event (QDragEnterEvent)
+        """
+        mimeData = event.mimeData()
+        formats = mimeData.formats()
+        if formats.contains("action") and \
+           mimeData.data("action") == "tab-reordering" and \
+           formats.contains("tabbar-id") and \
+           formats.contains("source-index") and \
+           formats.contains("tabwidget-id"):
+            event.acceptProposedAction()
+        E4WheelTabBar.dragEnterEvent(self, event)
+    
+    def dropEvent(self, event):
+        """
+        Protected method to handle drop events.
+        
+        @param event reference to the drop event (QDropEvent)
+        """
+        mimeData = event.mimeData()
+        oldID = mimeData.data("tabbar-id").toLong()[0]
+        fromIndex = mimeData.data("source-index").toInt()[0]
+        toIndex = self.tabAt(event.pos())
+        if oldID != id(self):
+            parentID = mimeData.data("tabwidget-id").toLong()[0]
+            if event.proposedAction() == Qt.MoveAction:
+                self.emit(SIGNAL("tabRelocateRequested(long, int, int)"), 
+                          parentID, fromIndex, toIndex)
+                event.acceptProposedAction()
+            elif event.proposedAction() == Qt.CopyAction:
+                self.emit(SIGNAL("tabCopyRequested(long, int, int)"), 
+                          parentID, fromIndex, toIndex)
+                event.acceptProposedAction()
+        else:
+            if fromIndex != toIndex:
+                if event.proposedAction() == Qt.MoveAction:
+                    self.emit(SIGNAL("tabMoveRequested(int, int)"), fromIndex, toIndex)
+                    event.acceptProposedAction()
+                elif event.proposedAction() == Qt.CopyAction:
+                    self.emit(SIGNAL("tabCopyRequested(int, int)"), fromIndex, toIndex)
+                    event.acceptProposedAction()
+        E4WheelTabBar.dropEvent(self, event)
+
+class TabWidget(E4TabWidget):
+    """
+    Class implementing a custimized tab widget.
+    """
+    def __init__(self, vm):
+        """
+        Constructor
+        
+        @param vm view manager widget (Tabview)
+        """
+        E4TabWidget.__init__(self)
+        self.setAttribute(Qt.WA_DeleteOnClose, True)
+        
+        self.__tabBar = TabBar(self)
+        self.setTabBar(self.__tabBar)
+        
+        self.connect(self.__tabBar, SIGNAL("tabMoveRequested(int, int)"), 
+                     self.moveTab)
+        self.connect(self.__tabBar, SIGNAL("tabRelocateRequested(long, int, int)"), 
+                     self.relocateTab)
+        self.connect(self.__tabBar, SIGNAL("tabCopyRequested(long, int, int)"), 
+                     self.copyTabOther)
+        self.connect(self.__tabBar, SIGNAL("tabCopyRequested(int, int)"), 
+                     self.copyTab)
+        
+        self.vm = vm
+        self.editors = []
+        
+        self.indicator = E4Led(self)
+        self.setCornerWidget(self.indicator, Qt.TopLeftCorner)
+        
+        self.rightCornerWidget = QWidget(self)
+        self.rightCornerWidgetLayout = QHBoxLayout(self.rightCornerWidget)
+        self.rightCornerWidgetLayout.setMargin(0)
+        self.rightCornerWidgetLayout.setSpacing(0)
+        
+        self.__navigationMenu = QMenu(self)
+        self.connect(self.__navigationMenu, SIGNAL("aboutToShow()"), 
+                     self.__showNavigationMenu)
+        self.connect(self.__navigationMenu, SIGNAL("triggered(QAction*)"), 
+                     self.__navigationMenuTriggered)
+        
+        self.navigationButton = QToolButton(self)
+        self.navigationButton.setIcon(UI.PixmapCache.getIcon("1downarrow.png"))
+        self.navigationButton.setToolTip(self.trUtf8("Show a navigation menu"))
+        self.navigationButton.setPopupMode(QToolButton.InstantPopup)
+        self.navigationButton.setMenu(self.__navigationMenu)
+        self.navigationButton.setEnabled(False)
+        self.rightCornerWidgetLayout.addWidget(self.navigationButton)
+        
+        if Preferences.getUI("SingleCloseButton") or \
+           not hasattr(self, 'setTabsClosable'):
+            self.closeButton = QToolButton(self)
+            self.closeButton.setIcon(UI.PixmapCache.getIcon("close.png"))
+            self.closeButton.setToolTip(self.trUtf8("Close the current editor"))
+            self.closeButton.setEnabled(False)
+            self.connect(self.closeButton, SIGNAL("clicked(bool)"),
+                self.__closeButtonClicked)
+            self.rightCornerWidgetLayout.addWidget(self.closeButton)
+        else:
+            self.connect(self, SIGNAL("tabCloseRequested(int)"), 
+                self.__closeRequested)
+            self.closeButton = None
+        
+        self.setCornerWidget(self.rightCornerWidget, Qt.TopRightCorner)
+        
+        self.__initMenu()
+        self.contextMenuEditor = None
+        self.contextMenuIndex = -1
+        
+        self.setTabContextMenuPolicy(Qt.CustomContextMenu)
+        self.connect(self, SIGNAL('customTabContextMenuRequested(const QPoint &, int)'),
+                     self.__showContextMenu)
+        
+        ericPic = QPixmap(os.path.join(getConfig('ericPixDir'), 'eric_small.png'))
+        self.emptyLabel = QLabel()
+        self.emptyLabel.setPixmap(ericPic)
+        self.emptyLabel.setAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
+        E4TabWidget.addTab(self, self.emptyLabel, UI.PixmapCache.getIcon("empty.png"), "")
+        
+    def __initMenu(self):
+        """
+        Private method to initialize the tab context menu.
+        """
+        self.__menu = QMenu(self)
+        self.leftMenuAct = \
+            self.__menu.addAction(UI.PixmapCache.getIcon("1leftarrow.png"),
+            self.trUtf8('Move Left'), self.__contextMenuMoveLeft)
+        self.rightMenuAct = \
+            self.__menu.addAction(UI.PixmapCache.getIcon("1rightarrow.png"),
+            self.trUtf8('Move Right'), self.__contextMenuMoveRight)
+        self.firstMenuAct = \
+            self.__menu.addAction(UI.PixmapCache.getIcon("2leftarrow.png"),
+            self.trUtf8('Move First'), self.__contextMenuMoveFirst)
+        self.lastMenuAct = \
+            self.__menu.addAction(UI.PixmapCache.getIcon("2rightarrow.png"),
+            self.trUtf8('Move Last'), self.__contextMenuMoveLast)
+        self.__menu.addSeparator()
+        self.__menu.addAction(UI.PixmapCache.getIcon("close.png"),
+            self.trUtf8('Close'), self.__contextMenuClose)
+        self.closeOthersMenuAct = self.__menu.addAction(self.trUtf8("Close Others"), 
+            self.__contextMenuCloseOthers)
+        self.__menu.addAction(self.trUtf8('Close All'), self.__contextMenuCloseAll)
+        self.__menu.addSeparator()
+        self.saveMenuAct = \
+            self.__menu.addAction(UI.PixmapCache.getIcon("fileSave.png"),
+            self.trUtf8('Save'), self.__contextMenuSave)
+        self.__menu.addAction(UI.PixmapCache.getIcon("fileSaveAs.png"),
+            self.trUtf8('Save As...'), self.__contextMenuSaveAs)
+        self.__menu.addAction(UI.PixmapCache.getIcon("fileSaveAll.png"),
+            self.trUtf8('Save All'), self.__contextMenuSaveAll)
+        self.projectMenuAct = \
+            self.__menu.addAction(UI.PixmapCache.getIcon("fileSaveProject.png"),
+                self.trUtf8('Save to Project'), self.__contextMenuSaveToProject)
+        self.__menu.addSeparator()
+        self.__menu.addAction(UI.PixmapCache.getIcon("print.png"),
+            self.trUtf8('Print'), self.__contextMenuPrintFile)
+        
+    def __showContextMenu(self, coord, index):
+        """
+        Private slot to show the tab context menu.
+        
+        @param coord the position of the mouse pointer (QPoint)
+        @param index index of the tab the menu is requested for (integer)
+        """
+        if self.editors:
+            self.contextMenuEditor = self.widget(index)
+            if self.contextMenuEditor:
+                self.saveMenuAct.setEnabled(self.contextMenuEditor.isModified())
+            self.projectMenuAct.setEnabled(e4App().getObject("Project").isOpen())
+            
+            self.contextMenuIndex = index
+            self.leftMenuAct.setEnabled(index > 0)
+            self.rightMenuAct.setEnabled(index < self.count() - 1)
+            self.firstMenuAct.setEnabled(index > 0)
+            self.lastMenuAct.setEnabled(index < self.count() - 1)
+            
+            self.closeOthersMenuAct.setEnabled(self.count() > 1)
+            
+            coord = self.mapToGlobal(coord)
+            self.__menu.popup(coord)
+        
+    def __showNavigationMenu(self):
+        """
+        Private slot to show the navigation button menu.
+        """
+        self.__navigationMenu.clear()
+        for index in range(self.count()):
+            act = self.__navigationMenu.addAction(self.tabIcon(index), 
+                                                  self.tabText(index))
+            act.setData(QVariant(index))
+        
+    def __navigationMenuTriggered(self, act):
+        """
+        Private slot called to handle the navigation button menu selection.
+        
+        @param act reference to the selected action (QAction)
+        """
+        index, ok = act.data().toInt()
+        if ok:
+            self.setCurrentIndex(index)
+        
+    def showIndicator(self, on):
+        """
+        Public slot to set the indicator on or off.
+        
+        @param on flag indicating the dtate of the indicator (boolean)
+        """
+        if on:
+            self.indicator.setColor(QColor("green"))
+        else:
+            self.indicator.setColor(QColor("red"))
+        
+    def addTab(self, editor, title):
+        """
+        Overwritten method to add a new tab.
+        
+        @param editor the editor object to be added (QScintilla.Editor.Editor)
+        @param title title for the new tab (string)
+        """
+        E4TabWidget.addTab(self, editor, UI.PixmapCache.getIcon("empty.png"), title)
+        if self.closeButton:
+            self.closeButton.setEnabled(True)
+        else:
+            self.setTabsClosable(True)
+        self.navigationButton.setEnabled(True)
+        
+        if not editor in self.editors:
+            self.editors.append(editor)
+            self.connect(editor, SIGNAL('captionChanged'),
+                self.__captionChange)
+        
+        emptyIndex = self.indexOf(self.emptyLabel)
+        if emptyIndex > -1:
+            self.removeTab(emptyIndex)
+        
+    def insertWidget(self, index, editor, title):
+        """
+        Overwritten method to insert a new tab.
+        
+        @param index index position for the new tab (integer)
+        @param editor the editor object to be added (QScintilla.Editor.Editor)
+        @param title title for the new tab (string)
+        @return index of the inserted tab (integer)
+        """
+        newIndex = E4TabWidget.insertTab(self, index, editor, 
+                                         UI.PixmapCache.getIcon("empty.png"), 
+                                         title)
+        if self.closeButton:
+            self.closeButton.setEnabled(True)
+        else:
+            self.setTabsClosable(True)
+        self.navigationButton.setEnabled(True)
+        
+        if not editor in self.editors:
+            self.editors.append(editor)
+            self.connect(editor, SIGNAL('captionChanged'),
+                self.__captionChange)
+        
+        emptyIndex = self.indexOf(self.emptyLabel)
+        if emptyIndex > -1:
+            self.removeTab(emptyIndex)
+        
+        return newIndex
+        
+    def __captionChange(self, cap, editor):
+        """
+        Private method to handle Caption change signals from the editor. 
+        
+        Updates the tab text and tooltip text to reflect the new caption information.
+        
+        @param cap Caption for the editor
+        @param editor Editor to update the caption for
+        """
+        fn = editor.getFileName()
+        if fn:
+            if Preferences.getUI("TabViewManagerFilenameOnly"):
+                txt = os.path.basename(fn)
+            else:
+                txt = fn
+                ppath = e4App().getObject("Project").getProjectPath()
+                if ppath:
+                    txt = txt.replace(ppath + os.sep, "")
+            
+            maxFileNameChars = Preferences.getUI("TabViewManagerFilenameLength")
+            if len(txt) > maxFileNameChars:
+                txt = "...%s" % txt[-maxFileNameChars:]
+            if editor.isReadOnly():
+                txt = self.trUtf8("{0} (ro)").format(txt)
+            
+            index = self.indexOf(editor)
+            if index > -1:
+                self.setTabText(index, txt)
+                self.setTabToolTip(index, fn)
+        
+    def removeWidget(self, object):
+        """
+        Public method to remove a widget.
+        
+        @param object object to be removed (QWidget)
+        """
+        index = self.indexOf(object)
+        if index > -1:
+            self.removeTab(index)
+        
+        if isinstance(object, QScintilla.Editor.Editor):
+            self.disconnect(object, SIGNAL('captionChanged'),
+                self.__captionChange)
+            self.editors.remove(object)
+        
+        if not self.editors:
+            E4TabWidget.addTab(self, self.emptyLabel, 
+                UI.PixmapCache.getIcon("empty.png"), "")
+            self.emptyLabel.show()
+            if self.closeButton:
+                self.closeButton.setEnabled(False)
+            else:
+                self.setTabsClosable(False)
+            self.navigationButton.setEnabled(False)
+        
+    def relocateTab(self, sourceId, sourceIndex, targetIndex):
+        """
+        Public method to relocate an editor from another TabWidget.
+        
+        @param sourceId id of the TabWidget to get the editor from (long)
+        @param sourceIndex index of the tab in the old tab widget (integer)
+        @param targetIndex index position to place it to (integer)
+        """
+        tw = self.vm.getTabWidgetById(sourceId)
+        if tw is not None:
+            # step 1: get data of the tab of the source
+            toolTip = tw.tabToolTip(sourceIndex)
+            text = tw.tabText(sourceIndex)
+            icon = tw.tabIcon(sourceIndex)
+            whatsThis = tw.tabWhatsThis(sourceIndex)
+            editor = tw.widget(sourceIndex)
+            
+            # step 2: relocate the tab
+            tw.removeWidget(editor)
+            self.insertWidget(targetIndex, editor, text)
+            
+            # step 3: set the tab data again
+            self.setTabIcon(targetIndex, icon)
+            self.setTabToolTip(targetIndex, toolTip)
+            self.setTabWhatsThis(targetIndex, whatsThis)
+            
+            # step 4: set current widget
+            self.setCurrentIndex(targetIndex)
+        
+    def copyTabOther(self, sourceId, sourceIndex, targetIndex):
+        """
+        Public method to copy an editor from another TabWidget.
+        
+        @param sourceId id of the TabWidget to get the editor from (long)
+        @param sourceIndex index of the tab in the old tab widget (integer)
+        @param targetIndex index position to place it to (integer)
+        """
+        tw = self.vm.getTabWidgetById(sourceId)
+        if tw is not None:
+            editor = tw.widget(sourceIndex)
+            newEditor = self.vm.cloneEditor(editor, editor.getFileType(), 
+                                            editor.getFileName())
+            self.vm.insertView(newEditor, self, targetIndex, 
+                               editor.getFileName(), editor.getNoName())
+        
+    def copyTab(self, sourceIndex, targetIndex):
+        """
+        Public method to copy an editor.
+        
+        @param sourceIndex index of the tab (integer)
+        @param targetIndex index position to place it to (integer)
+        """
+        editor = self.widget(sourceIndex)
+        newEditor = self.vm.cloneEditor(editor, editor.getFileType(), 
+                                        editor.getFileName())
+        self.vm.insertView(newEditor, self, targetIndex, 
+                           editor.getFileName(), editor.getNoName())
+        
+    def currentWidget(self):
+        """
+        Overridden method to return a reference to the current page.
+        
+        @return reference to the current page (QWidget)
+        """
+        if not self.editors:
+            return None
+        else:
+            return E4TabWidget.currentWidget(self)
+        
+    def hasEditor(self, editor):
+        """
+        Public method to check for an editor.
+        
+        @param editor editor object to check for
+        @return flag indicating, whether the editor to be checked belongs
+            to the list of editors managed by this tab widget.
+        """
+        return editor in self.editors
+        
+    def hasEditors(self):
+        """
+        Public method to test, if any editor is managed.
+        
+        @return flag indicating editors are managed
+        """
+        return len(self.editors) > 0
+        
+    def __contextMenuClose(self):
+        """
+        Private method to close the selected tab.
+        """
+        if self.contextMenuEditor:
+            self.vm.closeEditorWindow(self.contextMenuEditor)
+        
+    def __contextMenuCloseOthers(self):
+        """
+        Private method to close the other tabs.
+        """
+        index = self.contextMenuIndex
+        for i in range(self.count() - 1, index, -1) + range(index - 1, -1, -1):
+            editor = self.widget(i)
+            self.vm.closeEditorWindow(editor)
+        
+    def __contextMenuCloseAll(self):
+        """
+        Private method to close all tabs.
+        """
+        savedEditors = self.editors[:]
+        for editor in savedEditors:
+            self.vm.closeEditorWindow(editor)
+        
+    def __contextMenuSave(self):
+        """
+        Private method to save the selected tab.
+        """
+        if self.contextMenuEditor:
+            self.vm.saveEditorEd(self.contextMenuEditor)
+        
+    def __contextMenuSaveAs(self):
+        """
+        Private method to save the selected tab to a new file.
+        """
+        if self.contextMenuEditor:
+            self.vm.saveAsEditorEd(self.contextMenuEditor)
+        
+    def __contextMenuSaveAll(self):
+        """
+        Private method to save all tabs.
+        """
+        self.vm.saveEditorsList(self.editors)
+        
+    def __contextMenuSaveToProject(self):
+        """
+        Private method to save the selected tab to the current project.
+        """
+        if self.contextMenuEditor:
+            self.vm.saveEditorToProjectEd(self.contextMenuEditor)
+        
+    def __contextMenuPrintFile(self):
+        """
+        Private method to print the selected tab.
+        """
+        if self.contextMenuEditor:
+            self.vm.printEditor(self.contextMenuEditor)
+        
+    def __contextMenuMoveLeft(self):
+        """
+        Private method to move a tab one position to the left.
+        """
+        self.moveTab(self.contextMenuIndex, self.contextMenuIndex - 1)
+        
+    def __contextMenuMoveRight(self):
+        """
+        Private method to move a tab one position to the right.
+        """
+        self.moveTab(self.contextMenuIndex, self.contextMenuIndex + 1)
+        
+    def __contextMenuMoveFirst(self):
+        """
+        Private method to move a tab to the first position.
+        """
+        self.moveTab(self.contextMenuIndex, 0)
+        
+    def __contextMenuMoveLast(self):
+        """
+        Private method to move a tab to the last position.
+        """
+        self.moveTab(self.contextMenuIndex, self.count() - 1)
+        
+    def __closeButtonClicked(self):
+        """
+        Private method to handle the press of the close button.
+        """
+        self.vm.closeEditorWindow(self.currentWidget())
+        
+    def __closeRequested(self, index):
+        """
+        Private method to handle the press of the individual tab close button.
+        
+        @param index index of the tab (integer)
+        """
+        if index >= 0:
+            self.vm.closeEditorWindow(self.widget(index))
+        
+    def mouseDoubleClickEvent(self, event):
+        """
+        Protected method handling double click events.
+        
+        @param event reference to the event object (QMouseEvent)
+        """
+        self.vm.newEditor()
+
+class Tabview(QSplitter, ViewManager):
+    """
+    Class implementing a tabbed viewmanager class embedded in a splitter.
+    
+    @signal changeCaption(string) emitted if a change of the caption is necessary
+    @signal editorChanged(string) emitted when the current editor has changed
+    """
+    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
+        """
+        self.tabWidgets = []
+        
+        QSplitter.__init__(self, parent)
+        ViewManager.__init__(self)
+        tw = TabWidget(self)
+        self.addWidget(tw)
+        self.tabWidgets.append(tw)
+        self.currentTabWidget = tw
+        self.currentTabWidget.showIndicator(True)
+        self.connect(tw, SIGNAL('currentChanged(int)'),
+            self.__currentChanged)
+        tw.installEventFilter(self)
+        tw.tabBar().installEventFilter(self)
+        self.setOrientation(Qt.Vertical)
+        self.__inRemoveView = False
+        
+        self.maxFileNameChars = Preferences.getUI("TabViewManagerFilenameLength")
+        self.filenameOnly = Preferences.getUI("TabViewManagerFilenameOnly")
+        
+    def canCascade(self):
+        """
+        Public method to signal if cascading of managed windows is available.
+        
+        @return flag indicating cascading of windows is available
+        """
+        return False
+        
+    def canTile(self):
+        """
+        Public method to signal if tiling of managed windows is available.
+        
+        @return flag indicating tiling of windows is available
+        """
+        return False
+        
+    def canSplit(self):
+        """
+        public method to signal if splitting of the view is available.
+        
+        @return flag indicating splitting of the view is available.
+        """
+        return True
+        
+    def tile(self):
+        """
+        Public method to tile the managed windows.
+        """
+        pass
+        
+    def cascade(self):
+        """
+        Public method to cascade the managed windows.
+        """
+        pass
+        
+    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.__inRemoveView = True
+        for tw in self.tabWidgets:
+            if tw.hasEditor(win):
+                tw.removeWidget(win)
+                break
+        win.closeIt()
+        self.__inRemoveView = False
+        
+        # if this was the last editor in this view, switch to the next, that
+        # still has open editors
+        for i in range(self.tabWidgets.index(tw), -1, -1) + \
+                 range(self.tabWidgets.index(tw) + 1, len(self.tabWidgets)):
+            if self.tabWidgets[i].hasEditors():
+                self.currentTabWidget.showIndicator(False)
+                self.currentTabWidget = self.tabWidgets[i]
+                self.currentTabWidget.showIndicator(True)
+                self.activeWindow().setFocus()
+                break
+        
+        aw = self.activeWindow()
+        fn = aw and aw.getFileName() or None
+        if fn:
+            self.emit(SIGNAL('changeCaption'), fn)
+            self.emit(SIGNAL('editorChanged'), fn)
+        else:
+            self.emit(SIGNAL('changeCaption'), "")
+        
+    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 (string)
+        @param noName name to be used for an unnamed editor (string)
+        """
+        if fn is None:
+            if not noName:
+                self.untitledCount += 1
+                noName = self.trUtf8("Untitled {0}").format(self.untitledCount)
+            self.currentTabWidget.addTab(win, noName)
+            win.setNoName(noName)
+        else:
+            if self.filenameOnly:
+                txt = os.path.basename(fn)
+            else:
+                txt = fn
+                ppath = e4App().getObject("Project").getProjectPath()
+                if ppath:
+                    txt = txt.replace(ppath + os.sep, "")
+            if len(txt) > self.maxFileNameChars:
+                txt = "...%s" % txt[-self.maxFileNameChars:]
+            if not QFileInfo(fn).isWritable():
+                txt = self.trUtf8("{0} (ro)").format(txt)
+            self.currentTabWidget.addTab(win, txt)
+            index = self.currentTabWidget.indexOf(win)
+            self.currentTabWidget.setTabToolTip(index, fn)
+        self.currentTabWidget.setCurrentWidget(win)
+        win.show()
+        win.setFocus()
+        if fn:
+            self.emit(SIGNAL('changeCaption'), fn)
+            self.emit(SIGNAL('editorChanged'), fn)
+        else:
+            self.emit(SIGNAL('changeCaption'), "")
+        
+    def insertView(self, win, tabWidget, index, fn = None, noName = ""):
+        """
+        Protected method to add a view (i.e. window)
+        
+        @param win editor window to be added
+        @param tabWidget reference to the tab widget to insert the editor into (TabWidget)
+        @param index index position to insert at (integer)
+        @param fn filename of this editor (string)
+        @param noName name to be used for an unnamed editor (string)
+        """
+        if fn is None:
+            if not noName:
+                self.untitledCount += 1
+                noName = self.trUtf8("Untitled {0}").format(self.untitledCount)
+            tabWidget.insertWidget(index, win, noName)
+            win.setNoName(noName)
+        else:
+            if self.filenameOnly:
+                txt = os.path.basename(fn)
+            else:
+                txt = fn
+                ppath = e4App().getObject("Project").getProjectPath()
+                if ppath:
+                    txt = txt.replace(ppath + os.sep, "")
+            if len(txt) > self.maxFileNameChars:
+                txt = "...%s" % txt[-self.maxFileNameChars:]
+            if not QFileInfo(fn).isWritable():
+                txt = self.trUtf8("{0} (ro)").format(txt)
+            nindex = tabWidget.insertWidget(index, win, txt)
+            tabWidget.setTabToolTip(nindex, fn)
+        tabWidget.setCurrentWidget(win)
+        win.show()
+        win.setFocus()
+        if fn:
+            self.emit(SIGNAL('changeCaption'), fn)
+            self.emit(SIGNAL('editorChanged'), fn)
+        else:
+            self.emit(SIGNAL('changeCaption'), "")
+        
+        self._modificationStatusChanged(win.isModified(), win)
+        self._checkActions(win)
+        
+    def _showView(self, win, fn = None):
+        """
+        Protected method to show a view (i.e. window)
+        
+        @param win editor window to be shown
+        @param fn filename of this editor (string)
+        """
+        win.show()
+        for tw in self.tabWidgets:
+            if tw.hasEditor(win):
+                tw.setCurrentWidget(win)
+                self.currentTabWidget.showIndicator(False)
+                self.currentTabWidget = tw
+                self.currentTabWidget.showIndicator(True)
+                break
+        win.setFocus()
+        
+    def activeWindow(self):
+        """
+        Public method to return the active (i.e. current) window.
+        
+        @return reference to the active editor
+        """
+        return self.currentTabWidget.currentWidget()
+        
+    def showWindowMenu(self, windowMenu):
+        """
+        Public method to set up the viewmanager part of the Window menu.
+        
+        @param windowMenu reference to the window menu
+        """
+        pass
+        
+    def _initWindowActions(self):
+        """
+        Protected method to define the user interface actions for window handling.
+        """
+        pass
+        
+    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)
+        """
+        if self.filenameOnly:
+            tabName = os.path.basename(newName)
+        else:
+            tabName = newName
+            ppath = e4App().getObject("Project").getProjectPath()
+            if ppath:
+                tabName = tabName.replace(ppath + os.sep, "")
+        if len(tabName) > self.maxFileNameChars:
+            tabName = "...%s" % tabName[-self.maxFileNameChars:]
+        index = self.currentTabWidget.indexOf(editor)
+        self.currentTabWidget.setTabText(index, tabName)
+        self.currentTabWidget.setTabToolTip(index, newName)
+        self.emit(SIGNAL('changeCaption'), newName)
+
+    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
+        """
+        for tw in self.tabWidgets:
+            if tw.hasEditor(editor):
+                break
+        index = tw.indexOf(editor)
+        if m:
+            tw.setTabIcon(index, UI.PixmapCache.getIcon("fileModified.png"))
+        elif editor.hasSyntaxErrors():
+            tw.setTabIcon(index, UI.PixmapCache.getIcon("syntaxError.png"))
+        else:
+            tw.setTabIcon(index, 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
+        """
+        for tw in self.tabWidgets:
+            if tw.hasEditor(editor):
+                break
+        index = tw.indexOf(editor)
+        if editor.hasSyntaxErrors():
+            tw.setTabIcon(index, UI.PixmapCache.getIcon("syntaxError.png"))
+        else:
+            tw.setTabIcon(index, UI.PixmapCache.getIcon("empty.png"))
+        
+        ViewManager._syntaxErrorToggled(self, editor)
+        
+    def addSplit(self):
+        """
+        Public method used to split the current view.
+        """
+        tw = TabWidget(self)
+        tw.show()
+        self.addWidget(tw)
+        self.tabWidgets.append(tw)
+        self.currentTabWidget.showIndicator(False)
+        self.currentTabWidget = self.tabWidgets[-1]
+        self.currentTabWidget.showIndicator(True)
+        self.connect(tw, SIGNAL('currentChanged(int)'),
+            self.__currentChanged)
+        tw.installEventFilter(self)
+        tw.tabBar().installEventFilter(self)
+        if self.orientation() == Qt.Horizontal:
+            size = self.width()
+        else:
+            size = self.height()
+        self.setSizes([int(size/len(self.tabWidgets))] * len(self.tabWidgets))
+        self.splitRemoveAct.setEnabled(True)
+        self.nextSplitAct.setEnabled(True)
+        self.prevSplitAct.setEnabled(True)
+        
+    def removeSplit(self):
+        """
+        Public method used to remove the current split view.
+        
+        @return flag indicating successfull removal
+        """
+        if len(self.tabWidgets) > 1:
+            tw = self.currentTabWidget
+            res = True
+            savedEditors = tw.editors[:]
+            for editor in savedEditors:
+                res &= self.closeEditor(editor)
+            if res:
+                try:
+                    i = self.tabWidgets.index(tw)
+                except ValueError:
+                    return True
+                if i == len(self.tabWidgets) - 1:
+                    i -= 1
+                self.tabWidgets.remove(tw)
+                tw.close()
+                self.currentTabWidget = self.tabWidgets[i]
+                self.currentTabWidget.showIndicator(True)
+                if len(self.tabWidgets) == 1:
+                    self.splitRemoveAct.setEnabled(False)
+                    self.nextSplitAct.setEnabled(False)
+                    self.prevSplitAct.setEnabled(False)
+                return True
+        
+        return False
+        
+    def setSplitOrientation(self, orientation):
+        """
+        Public method used to set the orientation of the split view.
+        
+        @param orientation orientation of the split
+                (Qt.Horizontal or Qt.Vertical)
+        """
+        self.setOrientation(orientation)
+        
+    def nextSplit(self):
+        """
+        Public slot used to move to the next split.
+        """
+        aw = self.activeWindow()
+        _hasFocus = aw and aw.hasFocus()
+        ind = self.tabWidgets.index(self.currentTabWidget) + 1
+        if ind == len(self.tabWidgets):
+            ind = 0
+        
+        self.currentTabWidget.showIndicator(False)
+        self.currentTabWidget = self.tabWidgets[ind]
+        self.currentTabWidget.showIndicator(True)
+        if _hasFocus:
+            aw = self.activeWindow()
+            if aw:
+                aw.setFocus()
+        
+    def prevSplit(self):
+        """
+        Public slot used to move to the previous split.
+        """
+        aw = self.activeWindow()
+        _hasFocus = aw and aw.hasFocus()
+        ind = self.tabWidgets.index(self.currentTabWidget) - 1
+        if ind == -1:
+            ind = len(self.tabWidgets) - 1
+        
+        self.currentTabWidget.showIndicator(False)
+        self.currentTabWidget = self.tabWidgets[ind]
+        self.currentTabWidget.showIndicator(True)
+        if _hasFocus:
+            aw = self.activeWindow()
+            if aw:
+                aw.setFocus()
+        
+    def __currentChanged(self, index):
+        """
+        Private slot to handle the currentChanged signal.
+        
+        @param index index of the current tab (integer)
+        """
+        if index == -1 or not self.editors:
+            return
+        
+        editor = self.activeWindow()
+        if editor is None:
+            return
+        
+        self._checkActions(editor)
+        editor.setFocus()
+        fn = editor.getFileName()
+        if fn:
+            self.emit(SIGNAL('changeCaption'), fn)
+            if not self.__inRemoveView:
+                self.emit(SIGNAL('editorChanged'), fn)
+        else:
+            self.emit(SIGNAL('changeCaption'), "")
+        
+    def eventFilter(self, watched, event):
+        """
+        Public method called to filter the event queue.
+        
+        @param watched the QObject being watched (QObject)
+        @param event the event that occurred (QEvent)
+        @return always False
+        """
+        if event.type() == QEvent.MouseButtonPress and \
+           not event.button() == Qt.RightButton:
+            self.currentTabWidget.showIndicator(False)
+            if isinstance(watched, E4TabWidget):
+                switched = watched is not self.currentTabWidget
+                self.currentTabWidget = watched
+            elif isinstance(watched, QTabBar):
+                switched = watched.parent() is not self.currentTabWidget
+                self.currentTabWidget = watched.parent()
+                if switched:
+                    index = self.currentTabWidget.selectTab(event.pos())
+                    switched = self.currentTabWidget.widget(index) is self.activeWindow()
+            elif isinstance(watched, QScintilla.Editor.Editor):
+                for tw in self.tabWidgets:
+                    if tw.hasEditor(watched):
+                        switched = tw is not self.currentTabWidget
+                        self.currentTabWidget = tw
+                        break
+            self.currentTabWidget.showIndicator(True)
+            
+            aw = self.activeWindow()
+            if aw is not None:
+                self._checkActions(aw)
+                aw.setFocus()
+                fn = aw.getFileName()
+                if fn:
+                    self.emit(SIGNAL('changeCaption'), fn)
+                    if switched:
+                        self.emit(SIGNAL('editorChanged'), fn)
+                else:
+                    self.emit(SIGNAL('changeCaption'), "")
+        
+        return False
+        
+    def preferencesChanged(self):
+        """
+        Public slot to handle the preferencesChanged signal.
+        """
+        ViewManager.preferencesChanged(self)
+        
+        self.maxFileNameChars = Preferences.getUI("TabViewManagerFilenameLength")
+        self.filenameOnly = Preferences.getUI("TabViewManagerFilenameOnly")
+        
+        for tabWidget in self.tabWidgets:
+            for index in range(tabWidget.count()):
+                editor = tabWidget.widget(index)
+                if isinstance(editor, QScintilla.Editor.Editor):
+                    fn = editor.getFileName()
+                    if fn:
+                        if self.filenameOnly:
+                            txt = os.path.basename(fn)
+                        else:
+                            txt = fn
+                            ppath = e4App().getObject("Project").getProjectPath()
+                            if ppath:
+                                txt = txt.replace(ppath + os.sep, "")
+                        if len(txt) > self.maxFileNameChars:
+                            txt = "...%s" % txt[-self.maxFileNameChars:]
+                        if not QFileInfo(fn).isWritable():
+                            txt = self.trUtf8("{0} (ro)").format(txt)
+                        tabWidget.setTabText(index, txt)
+        
+    def getTabWidgetById(self, id_):
+        """
+        Public method to get a reference to a tab widget knowing it's ID.
+        
+        @param id_ id of the tab widget (long)
+        @return reference to the tab widget (TabWidget)
+        """
+        for tw in self.tabWidgets:
+            if id(tw) == id_:
+                return tw
+        return None

eric ide

mercurial