Modifying loading mechanism for ui files so that it works in an egg

This commit is contained in:
Kovid Goyal 2006-12-02 02:03:20 +00:00
parent 38273e5b10
commit 95ab3d492d
5 changed files with 367 additions and 310 deletions

View File

@ -14,3 +14,15 @@
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
__docformat__ = "epytext"
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
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"]]

View File

@ -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 "")

View File

@ -19,222 +19,113 @@
<property name="spacing" >
<number>6</number>
</property>
<item row="0" column="1" >
<widget class="QGroupBox" name="groupBox_3" >
<property name="title" >
<string>Available Formats</string>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item row="0" column="1" >
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="add_format" >
<property name="toolTip" >
<string>Add a new format for this book</string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="icon" >
<iconset resource="images.qrc" >:/images/plus.png</iconset>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" >
<size>
<width>26</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="remove_format" >
<property name="toolTip" >
<string>Remove the selected formats for this book from the database.</string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="icon" >
<iconset resource="images.qrc" >:/images/minus.png</iconset>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="0" >
<widget class="QListWidget" name="formats" />
</item>
</layout>
</widget>
</item>
<item row="0" column="0" >
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
<widget class="QSplitter" name="splitter" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Meta information</string>
<widget class="QWidget" name="" >
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item row="3" column="1" colspan="2" >
<widget class="QLineEdit" name="tags" >
<property name="toolTip" >
<string>Tags categorize the book. This is particularly useful while searching. &lt;br>&lt;br>They can be any words or phrases, separated by commas.</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2" >
<widget class="QLineEdit" name="publisher" >
<property name="toolTip" >
<string>Change the publisher of this book</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2" >
<widget class="QLineEdit" name="authors" >
<property name="toolTip" >
<string>Change the author(s) of this book. Multiple authors should be separated by the &amp; character</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2" >
<widget class="QLineEdit" name="title" >
<property name="toolTip" >
<string>Change the title of this book</string>
</property>
</widget>
</item>
<item row="3" column="0" >
<widget class="QLabel" name="label_4" >
<property name="text" >
<string>Ta&amp;gs: </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>tags</cstring>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>&amp;Publisher: </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>publisher</cstring>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>&amp;Author(s): </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>authors</cstring>
</property>
</widget>
</item>
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>&amp;Title: </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>title</cstring>
</property>
</widget>
</item>
<item row="5" column="2" >
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Meta information</string>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<number>0</number>
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_5" >
<property name="text" >
<string>Change &amp;cover image:</string>
</property>
<property name="buddy" >
<cstring>cover_path</cstring>
<item row="3" column="1" colspan="2" >
<widget class="QLineEdit" name="tags" >
<property name="toolTip" >
<string>Tags categorize the book. This is particularly useful while searching. &lt;br>&lt;br>They can be any words or phrases, separated by commas.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<item row="2" column="1" colspan="2" >
<widget class="QLineEdit" name="publisher" >
<property name="toolTip" >
<string>Change the publisher of this book</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2" >
<widget class="QLineEdit" name="authors" >
<property name="toolTip" >
<string>Change the author(s) of this book. Multiple authors should be separated by the &amp; character</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2" >
<widget class="QLineEdit" name="title" >
<property name="toolTip" >
<string>Change the title of this book</string>
</property>
</widget>
</item>
<item row="3" column="0" >
<widget class="QLabel" name="label_4" >
<property name="text" >
<string>Ta&amp;gs: </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>tags</cstring>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>&amp;Publisher: </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>publisher</cstring>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>&amp;Author(s): </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>authors</cstring>
</property>
</widget>
</item>
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>&amp;Title: </string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>title</cstring>
</property>
</widget>
</item>
<item row="5" column="2" >
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
@ -242,106 +133,220 @@
<number>6</number>
</property>
<item>
<widget class="QLineEdit" name="cover_path" >
<property name="readOnly" >
<bool>true</bool>
<widget class="QLabel" name="label_5" >
<property name="text" >
<string>Change &amp;cover image:</string>
</property>
<property name="buddy" >
<cstring>cover_path</cstring>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="cover_button" >
<property name="toolTip" >
<string>Browse for an image to use as the cover of this book.</string>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="text" >
<string>...</string>
<property name="spacing" >
<number>6</number>
</property>
<property name="icon" >
<iconset resource="images.qrc" >:/images/fileopen.png</iconset>
</property>
</widget>
<item>
<widget class="QLineEdit" name="cover_path" >
<property name="readOnly" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="cover_button" >
<property name="toolTip" >
<string>Browse for an image to use as the cover of this book.</string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="icon" >
<iconset resource="images.qrc" >:/images/fileopen.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="6" column="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>21</height>
</size>
</property>
</spacer>
</item>
<item rowspan="3" row="4" column="0" colspan="2" >
<widget class="QLabel" name="cover" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>100</width>
<height>120</height>
</size>
</property>
<property name="text" >
<string/>
</property>
<property name="pixmap" >
<pixmap resource="images.qrc" >:/images/cherubs.jpg</pixmap>
</property>
<property name="scaledContents" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2" >
<property name="title" >
<string>Comments</string>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
<property name="spacing" >
<number>6</number>
</property>
</spacer>
</item>
<item row="4" column="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>21</height>
</size>
</property>
</spacer>
</item>
<item rowspan="3" row="4" column="0" colspan="2" >
<widget class="QLabel" name="cover" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>100</width>
<height>120</height>
</size>
</property>
<property name="text" >
<string/>
</property>
<property name="pixmap" >
<pixmap resource="images.qrc" >:/images/cherubs.jpg</pixmap>
</property>
<property name="scaledContents" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2" >
<property name="title" >
<string>Comments</string>
<item row="0" column="0" >
<widget class="QTextEdit" name="comments" />
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="groupBox_3" >
<property name="title" >
<string>Available Formats</string>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<number>9</number>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item row="0" column="0" >
<widget class="QTextEdit" name="comments" />
</item>
</layout>
</widget>
</item>
</layout>
<property name="spacing" >
<number>6</number>
</property>
<item row="0" column="1" >
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="add_format_button" >
<property name="toolTip" >
<string>Add a new format for this book</string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="icon" >
<iconset resource="images.qrc" >:/images/plus.png</iconset>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" >
<size>
<width>26</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="remove_format_button" >
<property name="toolTip" >
<string>Remove the selected formats for this book from the database.</string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="icon" >
<iconset resource="images.qrc" >:/images/minus.png</iconset>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="0" >
<widget class="QListWidget" name="formats" />
</item>
</layout>
</widget>
</widget>
</item>
<item row="1" column="0" colspan="2" >
<item row="1" column="0" >
<widget class="QDialogButtonBox" name="button_box" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>

View File

@ -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

View File

@ -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',