# -*- coding: utf-8 -*-

# Copyright (c) 2002 - 2007 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the workspace viewmanager class.
"""

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from ViewManager import ViewManager

import QScintilla.Editor

import UI.PixmapCache

from E4Gui.E4Action import E4Action

from ThirdParty.compactpath import compactpath

class Workspace(QWorkspace, ViewManager):
    """
    Class implementing the workspace viewmanager class.
    
    @signal editorChanged(string) emitted when the current editor has changed
    """
    def __init__(self, parent, ui, dbs):
        """
        Constructor
        
        @param parent parent widget (QWidget)
        @param ui reference to the main user interface
        @param dbs reference to the debug server object
        """
        QWorkspace.__init__(self,parent)
        ViewManager.__init__(self, ui, dbs)
        self.setScrollBarsEnabled(True)
        self.lastFN = ''
        self.connect(self, SIGNAL('windowActivated(QWidget*)'),
            self.__windowActivated)
        
    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.
        """
        QWorkspace.tile(self)
        
    def cascade(self):
        """
        Public method to cascade the managed windows.
        """
        QWorkspace.cascade(self)
        
    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.lastFN = ''
        win.removeEventFilter(self)
        win.closeIt()
        
    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 or QString)
        """
        self.addWindow(win)
        if fn is None:
            if not unicode(noName):
                self.untitledCount += 1
                noName = self.trUtf8("Untitled %1").arg(self.untitledCount)
            win.setWindowTitle(noName)
            win.setNoName(noName)
        else:
            if self.lastFN != fn:
                self.lastFN = fn
                # QWorkspace is a little bit tricky
                win.hide()
        win.show()
        
        # 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
        """
        if fn is not None and self.lastFN != fn:
            self.lastFN = fn
            # QWorkspace is a little bit tricky
            win.hide()
        win.show()
        win.setFocus()
        
    def activeWindow(self):
        """
        Private method to return the active (i.e. current) window.
        
        @return reference to the active editor
        """
        return QWorkspace.activeWindow(self)
        
    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'))
        self.connect(self.windowsMenu, SIGNAL('triggered(QAction *)'),
            self.__windowsMenuTriggered)
        
        idx = 0
        for sv in self.editors:
            fn = sv.fileName
            if fn:
                txt = compactpath.compactPath(unicode(fn), self.ui.maxMenuFilePathLen)
            else:
                txt = sv.windowTitle()
            act = self.windowsMenu.addAction(txt)
            act.setData(QVariant(idx))
            act.setCheckable(True)
            act.setChecked(not sv.isHidden())
            idx += 1
        
        windowMenu.addSeparator()
        self.tileAct.addTo(windowMenu)
        self.cascadeAct.addTo(windowMenu)
        windowMenu.addSeparator()
        act = windowMenu.addMenu(self.windowsMenu)
        if len(self.editors) == 0:
            act.setEnabled(False)
        
    def __windowsMenuTriggered(self, act):
        """
        Private method to handle the toggle of an editor window.
        
        @param act reference to the action that triggered (QAction)
        """
        idx, ok = act.data().toInt()
        if ok:
            self.__toggleWindow(self.editors[idx])
        
    def __toggleWindow(self,w):
        """
        Protected method to toggle a workspace window.
        
        @param w editor window to be toggled
        """
        if w.isHidden():
            w.show()
        else:
            w.hide()
        
    def _initWindowActions(self):
        """
        Protected method to define the user interface actions for window handling.
        """
        self.tileAct = E4Action(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.connectIt(SIGNAL('triggered()'), self.tile)
        self.windowActions.append(self.tileAct)
        
        self.cascadeAct = E4Action(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.connectIt(SIGNAL('triggered()'), self.cascade)
        self.windowActions.append(self.cascadeAct)
        
    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 or QString)
        """
        pass
        
    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:
            editor.setWindowIcon(UI.PixmapCache.getIcon("fileModified.png"))
        elif editor.hasSyntaxErrors():
            editor.setWindowIcon(UI.PixmapCache.getIcon("syntaxError.png"))
        else:
            editor.setWindowIcon(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():
            editor.setWindowIcon(UI.PixmapCache.getIcon("syntaxError.png"))
        else:
            editor.setWindowIcon(UI.PixmapCache.getIcon("empty.png"))
                
        ViewManager._syntaxErrorToggled(self, editor)
        
    def __windowActivated(self, editor):
        """
        Private slot to handle the windowActivated signal.
        
        @param editor the activated editor window
        """
        self._checkActions(editor)
        if editor is not None:
            fn = editor.getFileName()
            self.emit(SIGNAL('editorChanged'), unicode(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 always False
        """
        if event.type() == QEvent.Close and isinstance(watched, QScintilla.Editor.Editor):
            watched.close()
        
        return False
