From 95ab3d492d2dfa9807e0c75f18db3737a91cc514 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 2 Dec 2006 02:03:20 +0000 Subject: [PATCH] Modifying loading mechanism for ui files so that it works in an egg --- libprs500/gui/__init__.py | 12 + libprs500/gui/editbook.py | 57 +++- libprs500/gui/editbook.ui | 587 +++++++++++++++++++------------------- libprs500/gui/main.py | 12 +- setup.py | 9 +- 5 files changed, 367 insertions(+), 310 deletions(-) diff --git a/libprs500/gui/__init__.py b/libprs500/gui/__init__.py index 82d22e958b..12653c6e7e 100644 --- a/libprs500/gui/__init__.py +++ b/libprs500/gui/__init__.py @@ -14,3 +14,15 @@ ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. __docformat__ = "epytext" __author__ = "Kovid Goyal " + +import pkg_resources, sys, os, StringIO +from PyQt4 import QtCore, QtGui # Needed for classes imported with import_ui +from PyQt4.uic.Compiler import compiler + +def import_ui(name): + uifile = pkg_resources.resource_stream(__name__, name) + code_string = StringIO.StringIO() + winfo = compiler.UICompiler().compileUi(uifile, code_string) + ui = pkg_resources.resource_filename(__name__, name) + exec code_string.getvalue() + return locals()[winfo["uiclass"]] diff --git a/libprs500/gui/editbook.py b/libprs500/gui/editbook.py index d22a53d9bd..6d526086b8 100644 --- a/libprs500/gui/editbook.py +++ b/libprs500/gui/editbook.py @@ -12,27 +12,32 @@ ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import sys, os, pkg_resources, StringIO +import sys, os, StringIO from PyQt4 import uic from PyQt4.QtCore import Qt, SIGNAL -from PyQt4.Qt import QObject, QDialog, QPixmap -from libprs500.lrf.meta import LRFMeta +from PyQt4.Qt import QObject, QDialog, QPixmap, QListWidgetItem +from libprs500.lrf.meta import LRFMetaFile +from libprs500.gui import import_ui -ui = pkg_resources.resource_stream(__name__, "editbook.ui") -sys.path.append(os.path.dirname(ui.name)) -Ui_BookEditDialog, bclass = uic.loadUiType(pkg_resources.resource_stream(__name__, "editbook.ui")) +class Format(QListWidgetItem): + def __init__(self, parent, ext, data): + self.data = data + self.ext = ext + QListWidgetItem.__init__(self, ext.upper(), parent, QListWidgetItem.UserType) +Ui_BookEditDialog = import_ui("editbook.ui") class EditBookDialog(Ui_BookEditDialog): def select_cover(self, checked): settings = QSettings() dir = settings.value("change cover dir", QVariant(os.path.expanduser("~"))).toString() - file = QFileDialog.getOpenFileName(self.window, "Choose cover for " + str(self.title.text(), dir, "Images (*.png *.gif *.jpeg *.jpg);;All files (*)")) + file = QFileDialog.getOpenFileName(self.window, "Choose cover for " + str(self.title.text()), dir, "Images (*.png *.gif *.jpeg *.jpg);;All files (*)") if len(str(file)): file = os.path.abspath(file) settings.setValue("change cover dir", QVariant(os.path.dirname(file))) if not os.access(file, os.R_OK): QErrorMessage(self.parent).showMessage("You do not have permission to read the file: " + file) + return cf, cover = None, None try: cf = open(file, "rb") @@ -55,10 +60,14 @@ class EditBookDialog(Ui_BookEditDialog): publisher = str(self.publisher.text()).strip() comments = str(self.comments.toPlainText()).strip() self.db.set_metadata(self.id, title=title, authors=authors, tags=tags, publisher=publisher, comments=comments, cover=self.cover_data) + if self.formats_changed: + for r in range(self.formats.count()): + format = self.formats.item(r) + self.db.add_format(self.id, format.ext, format.data) lrf = self.db.get_format(self.id, "lrf") if lrf: lrf = StringIO.StringIO(lrf) - lf = LRFMeta(lrf) + lf = LRFMetaFile(lrf) if title: lf.title = title if authors: lf.title = authors if publisher: lf.publisher = publisher @@ -66,15 +75,47 @@ class EditBookDialog(Ui_BookEditDialog): self.db.add_format(self.id, "lrf", lrf.getvalue()) + def add_format(self, x): + dir = settings.value("add formats dialog dir", QVariant(os.path.expanduser("~"))).toString() + files = QFileDialog.getOpenFileNames(self.window, "Choose formats for " + str(self.title.text()), dir, "Books (*.lrf *.lrx *.rtf *.txt *.html *.xhtml *.htm *.rar);;All files (*)") + if not files.isEmpty(): + x = str(files[0]) + settings.setValue("add formats dialog dir", QVariant(os.path.dirname(x))) + files = str(files.join("|||")).split("|||") + for file in files: + file = os.path.abspath(file) + if not os.access(file, os.R_OK): + QErrorMessage(self.parent).showMessage("You do not have permission to read the file: " + file) + continue + f, data = None, None + try: + f = open(file, "rb") + data = f.read() + except IOError, e: QErrorMessage(self.parent).showMessage("There was an error reading from file: " + file + "\n"+str(e)) + if data: + ext = file[file.rfind(".")+1:].lower() if file.find(".") > -1 else None + Format(self.formats, ext, data) + self.formats_changed = True + + def remove_format(self, x): + rows = self.formats.selectionModel().selectedRows(0) + for row in rows: + item = self.formats.takeItem(row.row()) + self.formats_changed = True + def __init__(self, dialog, id, db): Ui_BookEditDialog.__init__(self) self.parent = dialog self.setupUi(dialog) + self.splitter.setStretchFactor(100,1) self.db = db self.id = id self.cover_data = None + self.formats_changed = False QObject.connect(self.cover_button, SIGNAL("clicked(bool)"), self.select_cover) QObject.connect(self.button_box, SIGNAL("accepted()"), self.write_data) + QObject.connect(self.add_format_button, SIGNAL("clicked(bool)"), self.add_format) + QObject.connect(self.remove_format_button, SIGNAL("clicked(bool)"), self.remove_format) data = self.db.get_row_by_id(self.id, ["title","authors","publisher","tags","comments"]) self.title.setText(data["title"]) self.authors.setText(data["authors"] if data["authors"] else "") diff --git a/libprs500/gui/editbook.ui b/libprs500/gui/editbook.ui index b65f4b3542..bdb4f871ce 100644 --- a/libprs500/gui/editbook.ui +++ b/libprs500/gui/editbook.ui @@ -19,222 +19,113 @@ 6 - - - - Available Formats - - - - 9 - - - 6 - - - - - 0 - - - 6 - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Add a new format for this book - - - ... - - - :/images/plus.png - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 26 - 10 - - - - - - - - Remove the selected formats for this book from the database. - - - ... - - - :/images/minus.png - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - 0 + + + Qt::Horizontal - - 6 - - - - - Meta information + + + + 0 - - - 9 - - - 6 - - - - - Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas. - - - - - - - Change the publisher of this book - - - - - - - Change the author(s) of this book. Multiple authors should be separated by the & character - - - - - - - Change the title of this book - - - - - - - Ta&gs: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - tags - - - - - - - &Publisher: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - publisher - - - - - - - &Author(s): - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - authors - - - - - - - &Title: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - title - - - - - + + 6 + + + + + Meta information + + - 0 + 9 6 - - - - Change &cover image: - - - cover_path + + + + Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas. - - + + + + Change the publisher of this book + + + + + + + Change the author(s) of this book. Multiple authors should be separated by the & character + + + + + + + Change the title of this book + + + + + + + Ta&gs: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + tags + + + + + + + &Publisher: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + publisher + + + + + + + &Author(s): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + authors + + + + + + + &Title: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + title + + + + + 0 @@ -242,106 +133,220 @@ 6 - - - true + + + Change &cover image: + + + cover_path - - - Browse for an image to use as the cover of this book. + + + 0 - - ... + + 6 - - :/images/fileopen.png - - + + + + true + + + + + + + Browse for an image to use as the cover of this book. + + + ... + + + :/images/fileopen.png + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 21 + + + + + + + + + 0 + 0 + 0 + 0 + + + + + 100 + 120 + + + + + + + :/images/cherubs.jpg + + + true + + + - - - - - Qt::Vertical + + + + + + Comments + + + + 9 - - - 20 - 40 - + + 6 - - - - - - Qt::Vertical - - - - 20 - 21 - - - - - - - - - 0 - 0 - 0 - 0 - - - - - 100 - 120 - - - - - - - :/images/cherubs.jpg - - - true - - - - - - - - - - Comments + + + + + + + + + + + Available Formats + + + + 9 - - - 9 - - - 6 - - - - - - - - + + 6 + + + + + 0 + + + 6 + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Add a new format for this book + + + ... + + + :/images/plus.png + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 26 + 10 + + + + + + + + Remove the selected formats for this book from the database. + + + ... + + + :/images/minus.png + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + - + Qt::Horizontal diff --git a/libprs500/gui/main.py b/libprs500/gui/main.py index 67f4dfcaa3..86c4efa84f 100644 --- a/libprs500/gui/main.py +++ b/libprs500/gui/main.py @@ -15,6 +15,7 @@ from libprs500.communicate import PRS500Device as device from libprs500.errors import * from libprs500.lrf.meta import LRFMetaFile, LRFException +from libprs500.gui import import_ui from database import LibraryDatabase from editbook import EditBookDialog @@ -22,7 +23,7 @@ from PyQt4.QtCore import Qt, SIGNAL from PyQt4.Qt import QObject, QThread, QCoreApplication, QEventLoop, QString, QStandardItem, QStandardItemModel, QStatusBar, QVariant, QAbstractTableModel, \ QAbstractItemView, QImage, QPixmap, QIcon, QSize, QMessageBox, QSettings, QFileDialog, QErrorMessage, QDialog from PyQt4 import uic -import sys, pkg_resources, re, string, time, os, os.path, traceback, textwrap, zlib +import sys, re, string, time, os, os.path, traceback, textwrap, zlib from stat import ST_SIZE from tempfile import TemporaryFile, NamedTemporaryFile from exceptions import Exception as Exception @@ -264,9 +265,7 @@ class DeviceBooksModel(QAbstractTableModel): -ui = pkg_resources.resource_stream(__name__, "main.ui") -sys.path.append(os.path.dirname(ui.name)) -Ui_MainWindow, bclass = uic.loadUiType(pkg_resources.resource_stream(__name__, "main.ui")) +Ui_MainWindow = import_ui("main.ui") class MainWindow(QObject, Ui_MainWindow): def show_device(self, yes): @@ -418,7 +417,7 @@ class MainWindow(QObject, Ui_MainWindow): except LRFException: pass self.library_model.add(file, title, author, publisher, cover) - def edit(self, action): + def edit(self, action): if self.library_view.isVisible(): rows = self.library_view.selectionModel().selectedRows() for row in rows: @@ -519,7 +518,6 @@ class MainWindow(QObject, Ui_MainWindow): QObject.connect(self.action_edit, SIGNAL("triggered(bool)"), self.edit) self.device_detector = self.startTimer(1000) - self.splitter.setStretchFactor(0,0) self.splitter.setStretchFactor(1,100) self.search.setFocus(Qt.OtherFocusReason) window.show() @@ -565,7 +563,7 @@ class MainWindow(QObject, Ui_MainWindow): self.status("Connecting to device") try: space = self.dev.available_space() - except ProtocolError: + except TimeoutError: c = 0 self.status("Waiting for device to initialize") while c < 100: # Delay for 10s while device is initializing diff --git a/setup.py b/setup.py index 57b72ced9e..96317e7b42 100644 --- a/setup.py +++ b/setup.py @@ -24,11 +24,12 @@ setup(name='libprs500', 'console_scripts': [ 'prs500 = libprs500.cli.main:main', 'lrf-meta = libprs500.lrf.meta:main' ], 'gui_scripts' : [ 'prs500-gui = libprs500.gui.main:main'] }, - include_package_data = True, + package_data = {'libprs500.gui' : ['*.ui']}, + zip_safe = True, version=VERSION, install_requires=["pyusb>=0.3.5","pyxml>=0.8.4"], dependency_links=["http://sourceforge.net/project/showfiles.php?group_id=145185","http://sourceforge.net/project/showfiles.php?group_id=6473"], - description='Library to interface with the Sony Portable Reader 500 over USB.', + description='Library to interface with the Sony Portable Reader 500 over USB. Also has a GUI with library management features.', long_description = """ libprs500 is library to interface with the `SONY Portable Reader`_ over USB_. @@ -39,7 +40,7 @@ setup(name='libprs500', In addition libprs500 has a utility to read/write the metadata from LRF files (unencrypted books in the SONY BBeB format). A command line interface to this is provided via the command lrf-meta. - For SVN access: svn co https://kovidgoyal.net/svn/code/prs-500 + For SVN access: svn co https://svn.kovidgoyal.net/code/prs-500 .. _SONY Portable Reader: http://Sony.com/reader .. _USB: http://www.usb.org @@ -49,7 +50,7 @@ setup(name='libprs500', provides=['libprs500'], packages = find_packages(), license = 'GPL', - url = 'http://www.python.org/pypi/libprs500/', + url = 'http://libprs500.kovidgoyal.net', classifiers = [ 'Development Status :: 2 - Pre-Alpha', 'Environment :: Console',