############################################################################
##
## 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_())