#!/usr/bin/env python #**************************************************************************** # recentfiles.py, class to handle recent file lists in menus # # Copyright (C) 2005, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, Version 2. This program is # distributed in the hope that it will be useful, but WITTHOUT ANY WARRANTY. #***************************************************************************** import os.path from qt import Qt, PYSIGNAL, SIGNAL, SLOT, QObject class RecentFiles(QObject): """Tracks & loads menus with recently opened files""" def __init__(self, options, numEntries, maxEntryLen, parent=None, \ name=None): QObject.__init__(self, parent, name) self.options = options self.numEntries = numEntries self.maxEntryLen = maxEntryLen self.menu = None self.firstId = 0 self.separatorId = 0 def initMenu(self, menu, firstId): """load the entries into the menu""" self.menu = menu self.firstId = firstId self.separatorId = self.menu.idAt(self.menu.count() - 1) for text, i in zip(self.menuTextList(), range(self.numEntries)): self.menu.insertItem(text, self.firstId + i) self.connect(self.menu, SIGNAL('activated(int)'), self.openItem) def addEntry(self, fileName): """Add a new filename to the start of the list""" newPath = os.path.abspath(fileName) curPath = newPath for i in range(self.numEntries): tmpPath = self.recentFileName(i) self.options.changeData(self.optionTitle(i), curPath, 1) curPath = tmpPath if curPath == newPath: break # eliminate duplicates self.options.writeChanges() self.updateMenu() self.emit(PYSIGNAL('listChanged'), (self.fileList(),)) def removeEntry(self, filePath): """Remove a filename from the list""" allPaths = [self.recentFileName(i) for i in range(self.numEntries)] try: allPaths.remove(filePath) except ValueError: return allPaths = filter(None, allPaths) for i, path in map(None, range(self.numEntries), allPaths): self.options.changeData(self.optionTitle(i), path or '', 1) self.options.writeChanges() self.updateMenu() self.emit(PYSIGNAL('listChanged'), (self.fileList(),)) def openItem(self, id): """Signal to main window to open an item""" if self.firstId <= id < self.firstId + self.numEntries: self.emit(PYSIGNAL('askOpen'), \ (self.recentFileName(id - self.firstId),)) def firstPath(self): """Return the first valid path from the recent file list""" for num in range(self.numEntries): path = os.path.dirname(self.recentFileName(num)) if os.path.exists(path): return path return '' def updateMenu(self): """Refresh menu items""" firstIndex = self.menu.indexOf(self.separatorId) + 1 for text, i in map(None, self.menuTextList(), range(self.numEntries)): num = self.menu.indexOf(self.firstId + i) if text: if num >= 0: self.menu.changeItem(self.firstId + i, text) else: self.menu.insertItem(text, self.firstId + i, \ firstIndex + i) elif num >= 0: self.menu.removeItem(self.firstId + i) def changeNumEntries(self, numEntries): """Modify number of available entries""" for i in range(numEntries, self.numEntries): num = self.menu.indexOf(self.firstId + i) if num >= 0: self.menu.removeItem(self.firstId + i) self.options.changeData(self.optionTitle(i), '', 1) self.options.changeData('TreeState%d' % (i + 1), '0:0:0:0', 1) for i in range(self.numEntries, numEntries): self.options.dfltDict[self.optionTitle(i)] = '' self.options.dfltDict['TreeState%d' % (i + 1)] = '0:0:0:0' self.numEntries = numEntries self.options.writeChanges() self.updateMenu() def optionTitle(self, num): """Return option key""" return 'RecentFile%d' % (num + 1) def recentFileName(self, num): """Return file name at num (0-max)""" return self.options.strData(self.optionTitle(num), 1) def menuTextList(self): """Return list of abbreviated path names""" return [self.abbreviatePath(path, i) for path, i in \ zip(self.fileList(), range(self.numEntries)) if path] def abbreviatePath(self, path, num): """Return abbreviated and numbered path for menu use""" if len(path) > self.maxEntryLen: pos = path.find('/', len(path) - (self.maxEntryLen - 3)) if pos < 0: pos = len(path) - (self.maxEntryLen - 3) path = '...' + path[pos:] return '&%d %s' % (num + 1, path) def fileList(self): """Return the recent files as a list of full paths""" return [self.recentFileName(i) for i in range(self.numEntries)]