A more complex view management solution
In the previous section I suggested that
it might be nice to code up a view manager where the list of
open views was shown in a listbox on the left side. I could have
have left this for you to do, but I couldn't resist.
"""
listspace.py - stacked view manager with a list for the mdi framework
copyright: (C) 2001, Boudewijn Rempt
email: boud@rempt.xs4all.nl
"""
from qt import *
from resources import TRUE, FALSE
class ListSpace(QSplitter):
The ListSpace is
based on QSplitter — that way the
user can decide how wide he wants to have his list of window
titles.
def __init__(self, *args):
apply(QSplitter.__init__,(self, ) + args)
self.viewlist=QListBox(self)
self.setResizeMode(self.viewlist,
QSplitter.KeepSize)
self.stack=QWidgetStack(self)
self.views=[]
self.connect(self.viewlist,
SIGNAL("highlighted(int)"),
self.__activateViewByIndex)
First the QListBox
is added to the splitter, and then to the widget stack (which is
used in the same way as in the previous section). Here, I chose
to use a QListBox, because it offers a
more comfortable interface for the adding, changing and removing
of entries than a QListView. As soon as
we need the treeview, column header or multi-column capabilities
of QListView, the change to
QListView will be simple enough.
Because the
highlighted(int) signal of
QListBox passed the index of the selected
entry in the listbox, not the actual view object, we have to
pass it through an internal function,
__activateViewByIndex, which maps the index
to the view object that should be activated.
def addView(self, view):
self.views.append(view)
self.viewlist.insertItem(view.caption(), len(self.views) - 1)
self.stack.addWidget(view, len(self.views) - 1)
self.stack.raiseWidget(view)
self.connect(view,
PYSIGNAL("sigCaptionChanged"),
self.setListText)
def setListText(self, view, caption):
i = self.views.index(view)
self.viewlist.changeItem(caption, i)
Of course, adding a view is now slightly
more complicated, because the caption of the view must also be
inserted into the listbox. Note that we have changed the code of
MDIView slightly: when its caption
changes, it now emits a signal, which we use here to keep the
title text in the listview synchronized with the title of the
document. Synchronization is done using the
setListText function, which uses the view
to determine the right entry in the listbox. Of course, the
mapping between the view object and the entry in the listbox
should be encapsulated in a subclass of
QListBox.
def removeView(self, view):
if view in self.views:
self.viewlist.removeItem(self.views.index(view))
self.stack.removeWidget(view)
self.views.remove(view)
Removing an item from a
QListView is rather difficult to do
without clearing the entire listview and building the contents
anew.
[1] Fortunately, the QListBox
class offers a handy remove()
function.
def activeWindow(self):
return self.stack.visibleWidget()
def cascade(self): pass
def tile(self): pass
def canCascade(self):
return FALSE
def canTile(self):
return FALSE
def windowList(self):
return self.views
def activateView(self, view):
self.stack.raiseWidget(view)
def __activateViewByIndex(self, index):
self.activateView(self.views[index])
Apart from
__activateViewByIndex(), which we discussed
above, the rest of the code is a plain reflection of our view
manager API — in other words, nothing spectacular.