############################################################################ ## ## Copyright (C) 2004-2005 Trolltech AS. All rights reserved. ## ## This file is part of the example classes of the Qt Toolkit. ## ## This file may be used under the terms of the GNU General Public ## License version 2.0 as published by the Free Software Foundation ## and appearing in the file LICENSE.GPL included in the packaging of ## this file. Please review the following information to ensure GNU ## General Public Licensing requirements will be met: ## http://www.trolltech.com/products/qt/opensource.html ## ## If you are unsure which license is appropriate for your use, please ## review the following information: ## http://www.trolltech.com/products/qt/licensing.html or contact the ## sales department at sales@trolltech.com. ## ## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ## ############################################################################ import sys from PyQt4 import QtCore, QtGui, QtXml class XbelGenerator: def __init__(self, treeWidget): self.treeWidget = treeWidget self.out = QtCore.QTextStream() def write(self, device): self.out.setDevice(device) self.out.setCodec("UTF-8") self.out << "\n" \ << "\n" \ << "\n" for i in range(self.treeWidget.topLevelItemCount()): self.generateItem(self.treeWidget.topLevelItem(i), 1) self.out << "\n" return True def indent(self, depth): IndentSize = 4 return QtCore.QString(IndentSize * depth, QtCore.QChar(' ')) def escapedText(self, txt): result = txt result.replace("&", "&") result.replace("<", "<") result.replace(">", ">") return result def escapedAttribute(self, txt): result = self.escapedText(txt) result.replace("\"", """) result.prepend("\"") result.append("\"") return result def generateItem(self, item, depth): tagName = item.data(0, QtCore.Qt.UserRole).toString() if tagName == "folder": folded = (not self.treeWidget.isItemExpanded(item)) self.out << self.indent(depth) << "\n"\ << self.indent(depth + 1) << "" \ << self.escapedText(item.text(0)) \ << "\n" for i in range(item.childCount()): self.generateItem(item.child(i), depth + 1) self.out << self.indent(depth) << "\n" elif tagName == "bookmark": self.out << self.indent(depth) << "\n" \ << self.indent(depth + 1) << "" \ << self.escapedText(item.text(0)) \ << "\n" \ << self.indent(depth) << "\n" elif tagName == "separator": self.out << self.indent(depth) << "\n" class XbelHandler(QtXml.QXmlDefaultHandler): def __init__(self, treeWidget): QtXml.QXmlDefaultHandler.__init__(self) self.treeWidget = treeWidget self.folderIcon = QtGui.QIcon() self.bookmarkIcon = QtGui.QIcon() self.currentText = QtCore.QString() self.errorStr = QtCore.QString() self.item = None self.metXbelTag = False style = self.treeWidget.style() self.folderIcon.addPixmap(style.standardPixmap( QtGui.QStyle.SP_DirClosedIcon), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.folderIcon.addPixmap(style.standardPixmap( QtGui.QStyle.SP_DirOpenIcon), QtGui.QIcon.Normal, QtGui.QIcon.On) self.bookmarkIcon.addPixmap(style.standardPixmap(QtGui.QStyle.SP_FileIcon)) def startElement(self, namespaceURI, localName, qName, attributes): if not self.metXbelTag and qName != "xbel": self.errorStr = QtGui.qApp.tr("The file is not an XBEL file.") return False if qName == "xbel": version = attributes.value("version") if not version.isEmpty() and version != "1.0": self.errorStr = QtGui.qApp.tr("The File is not an XBEL version 1.0 file.") return False self.metXbelTag = True elif qName == "folder": self.item = self.createChildItem(qName) self.item.setFlags(self.item.flags() | QtCore.Qt.ItemIsEditable) self.item.setIcon(0, self.folderIcon) self.item.setText(0, QtGui.qApp.tr("Folder")) folded = (attributes.value("folded") != "no") self.treeWidget.setItemExpanded(self.item, (not folded)) elif qName == "bookmark": self.item = self.createChildItem(qName) self.item.setFlags(self.item.flags() | QtCore.Qt.ItemIsEditable) self.item.setIcon(0, self.bookmarkIcon) self.item.setText(0, QtGui.qApp.tr("Unkown title")) self.item.setText(1, attributes.value("href")) elif qName == "separator": self.item = self.createChildItem(qName) self.item.setFlags(self.item.flags() & ~QtCore.Qt.ItemIsSelectable) self.item.setText(0, QtCore.QString(30, QtCore.QChar(0xB7))) self.currentText.clear() return True def endElement(self, namespaceURI, localName, qName): if qName == "title": if self.item: self.item.setText(0, self.currentText) elif qName == "folder" or qName == "bookmark" or qName == "separator": self.item = self.item.parent() return True def characters(self, txt): self.currentText += txt return True def fatalError(self, exception): QtGui.QMessageBox.information(self.treeWidget.window(), QtGui.qApp.tr("SAX Bookmarks"), QtGui.qApp.tr("Parse error at"\ "line %1, column %2"\ ":\n%3") .arg(exception.lineNumber()) .arg(exception.columnNumber()) .arg(exception.message())) return False def errorString(self): return self.errorStr def createChildItem(self, tagName): if self.item: childItem = QtGui.QTreeWidgetItem(self.item) else: childItem = QtGui.QTreeWidgetItem(self.treeWidget) childItem.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(tagName)) return childItem class MainWindow(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) labels = QtCore.QStringList() labels << self.tr("Title") << self.tr("Location") self.treeWidget = QtGui.QTreeWidget() self.treeWidget.header().setResizeMode(QtGui.QHeaderView.Stretch) self.treeWidget.setHeaderLabels(labels) self.setCentralWidget(self.treeWidget) self.createActions() self.createMenus() self.statusBar().showMessage(self.tr("Ready")) self.setWindowTitle(self.tr("SAX Bookmarks")) self.resize( 480, 320 ) def open(self): fileName = QtGui.QFileDialog.getOpenFileName(self, self.tr("Open Bookmark File"), QtCore.QDir.currentPath(), self.tr("XBEL Files (*.xbel *.xml)")) if fileName.isEmpty(): return self.treeWidget.clear() handler = XbelHandler(self.treeWidget) reader = QtXml.QXmlSimpleReader() reader.setContentHandler(handler) reader.setErrorHandler(handler) file = QtCore.QFile(fileName) if not file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text): QtGui.QMessageBox.warning(self, self.tr("SAX Bookmarks"), self.tr("Cannot read file %1:\n%2.") .arg(fileName) .arg(file.errorString())) return xmlInputSource = QtXml.QXmlInputSource(file) if reader.parse(xmlInputSource): self.statusBar().showMessage(self.tr("File loaded"), 2000) def saveAs(self): fileName = QtGui.QFileDialog.getSaveFileName(self, self.tr("Save Bookmark File"), QtCore.QDir.currentPath(), self.tr("XBEL Files (*.xbel *.xml)")) if fileName.isEmpty(): return file = QtCore.QFile(fileName) if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text): QtGui.QMessageBox.warning(self, self.tr("SAX Bookmarks"), self.tr("Cannot write file %1:\n%2.") .arg(fileName) .arg(file.errorString())) return generator = XbelGenerator(self.treeWidget) if generator.write(file): self.statusBar().showMessage(self.tr("File saved"), 2000) def about(self): QtGui.QMessageBox.about(self, self.tr("About SAX Bookmarks"), self.tr("The SAX Bookmarks example demonstrates how to use Qt's " "SAX classes to read XML documents and how to generate XML by " "hand.")) def createActions(self): self.openAct = QtGui.QAction(self.tr("&Open..."), self) self.openAct.setShortcut(self.tr("Ctrl+O")) self.connect(self.openAct, QtCore.SIGNAL("triggered()"), self.open) self.saveAsAct = QtGui.QAction(self.tr("&Save As..."), self) self.saveAsAct.setShortcut(self.tr("Ctrl+S")) self.connect(self.saveAsAct, QtCore.SIGNAL("triggered()"), self.saveAs) self.exitAct = QtGui.QAction(self.tr("E&xit"), self) self.exitAct.setShortcut(self.tr("Ctrl+Q")) self.connect(self.exitAct, QtCore.SIGNAL("triggered()"), self, QtCore.SLOT("close()")) self.aboutAct = QtGui.QAction(self.tr("&About"), self) self.connect(self.aboutAct, QtCore.SIGNAL("triggered()"), self.about) self.aboutQtAct = QtGui.QAction(self.tr("About &Qt"), self) self.connect(self.aboutQtAct, QtCore.SIGNAL("triggered()"), QtGui.qApp, QtCore.SLOT("aboutQt()")) def createMenus(self): self.fileMenu = self.menuBar().addMenu(self.tr("&File")) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addAction(self.exitAct) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu(self.tr("&Help")) self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) if __name__ == "__main__": app = QtGui.QApplication(sys.argv) mainWin = MainWindow() mainWin.show() sys.exit(app.exec_())