From ab242cc96d3037ca064845f3ac657038cdb6ae28 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 5 Dec 2007 21:45:43 +0000 Subject: [PATCH] Implement #111 --- src/libprs500/gui2/dialogs/config.py | 53 ++++++++++++ src/libprs500/gui2/dialogs/config.ui | 121 +++++++++++++++++++++++++++ src/libprs500/gui2/library.py | 9 +- src/libprs500/gui2/main.py | 57 +++++++------ src/libprs500/library/database.py | 13 ++- 5 files changed, 224 insertions(+), 29 deletions(-) create mode 100644 src/libprs500/gui2/dialogs/config.py create mode 100644 src/libprs500/gui2/dialogs/config.ui diff --git a/src/libprs500/gui2/dialogs/config.py b/src/libprs500/gui2/dialogs/config.py new file mode 100644 index 0000000000..e204cc89ea --- /dev/null +++ b/src/libprs500/gui2/dialogs/config.py @@ -0,0 +1,53 @@ +## Copyright (C) 2007 Kovid Goyal kovid@kovidgoyal.net +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## 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. +from libprs500.gui2 import error_dialog +import os + +from PyQt4.QtGui import QDialog +from PyQt4.QtCore import QSettings, QVariant, SIGNAL + +from libprs500.gui2.dialogs.config_ui import Ui_Dialog +from libprs500.gui2 import qstring_to_unicode, choose_dir + +class ConfigDialog(QDialog, Ui_Dialog): + + def __init__(self, window): + QDialog.__init__(self, window) + Ui_Dialog.__init__(self) + self.setupUi(self) + + settings = QSettings() + path = qstring_to_unicode(\ + settings.value("database path", + QVariant(os.path.join(os.path.expanduser('~'),'library1.db'))).toString()) + + self.location.setText(os.path.dirname(path)) + self.connect(self.browse_button, SIGNAL('clicked(bool)'), self.browse) + + def browse(self): + dir = choose_dir(self, 'database location dialog', 'Select database location') + self.location.setText(dir) + + def accept(self): + path = qstring_to_unicode(self.location.text()) + if not path or not os.path.exists(path) or not os.path.isdir(path): + d = error_dialog(self, 'Invalid database location', 'Invalid database location '+path+'
Must be a directory.') + d.exec_() + elif not os.access(path, os.W_OK): + d = error_dialog(self, 'Invalid database location', 'Invalid database location.
Cannot write to '+path) + d.exec_() + else: + self.database_location = os.path.abspath(path) + QDialog.accept(self) diff --git a/src/libprs500/gui2/dialogs/config.ui b/src/libprs500/gui2/dialogs/config.ui new file mode 100644 index 0000000000..b2a8ddee7b --- /dev/null +++ b/src/libprs500/gui2/dialogs/config.ui @@ -0,0 +1,121 @@ + + Dialog + + + + 0 + 0 + 400 + 300 + + + + Configuration + + + :/images/config.svg + + + + + + + + + + + + &Location of books database (library1.db) + + + location + + + + + + + + + + + + ... + + + :/images/mimetypes/dir.svg + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/libprs500/gui2/library.py b/src/libprs500/gui2/library.py index decea95704..387b28f4c4 100644 --- a/src/libprs500/gui2/library.py +++ b/src/libprs500/gui2/library.py @@ -115,9 +115,14 @@ class BooksModel(QAbstractTableModel): if isinstance(db, (QString, basestring)): if isinstance(db, QString): db = qstring_to_unicode(db) - db = LibraryDatabase(os.path.expanduser(qstring_to_unicode(db))) + db = LibraryDatabase(os.path.expanduser(db)) self.db = db + def close(self): + self.db.close() + self.db = None + self.reset() + def add_books(self, paths, formats, metadata, uris=[]): self.db.add_books(paths, formats, metadata, uris) @@ -392,6 +397,8 @@ class BooksView(TableView): def set_database(self, db): self._model.set_database(db) + def close(self): + self._model.close() def migrate_database(self): if self.model().database_needs_migration(): diff --git a/src/libprs500/gui2/main.py b/src/libprs500/gui2/main.py index ac11f6c1a8..e94fe9aa4d 100644 --- a/src/libprs500/gui2/main.py +++ b/src/libprs500/gui2/main.py @@ -12,12 +12,11 @@ ## 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.Warning -from libprs500.ebooks.BeautifulSoup import BeautifulSoup -from libprs500.gui2 import qstring_to_unicode -import re -import urllib -import shutil -import os, sys, textwrap, cStringIO, collections, traceback +from libprs500.gui2.update import CheckForUpdates +from libprs500 import iswindows +from libprs500 import isosx + +import os, sys, textwrap, cStringIO, collections, traceback, shutil from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \ QSettings, QVariant, QSize, QThread, QTimer @@ -34,7 +33,7 @@ from libprs500.devices.errors import FreeSpaceError from libprs500.devices.interface import Device from libprs500.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \ initialize_file_icon_provider, BOOK_EXTENSIONS, \ - pixmap_to_data, choose_dir, ORG_NAME + pixmap_to_data, choose_dir, ORG_NAME, qstring_to_unicode from libprs500.gui2.main_window import MainWindow from libprs500.gui2.main_ui import Ui_MainWindow from libprs500.gui2.device import DeviceDetector, DeviceManager @@ -95,7 +94,10 @@ class Main(MainWindow, Ui_MainWindow): self.latest_version = ' ' self.vanity.setText(self.vanity_template%dict(version=' ', device=' ')) self.device_info = ' ' - QTimer.singleShot(1000, self.check_for_updates) + self.update_checker = CheckForUpdates() + QObject.connect(self.update_checker, SIGNAL('update_found(PyQt_PyObject)'), + self.update_found) + self.update_checker.start() ####################### Status Bar ##################### self.status_bar = StatusBar(self.jobs_dialog) self.setStatusBar(self.status_bar) @@ -674,19 +676,27 @@ class Main(MainWindow, Ui_MainWindow): if d.result() == d.Accepted: if os.path.dirname(self.database_path) != d.database_location: try: - self.db.close() - src = open(self.database_path, 'rb') newloc = os.path.join(d.database_location, os.path.basename(self.database_path)) dest = open(newloc, 'wb') self.status_bar.showMessage('Copying database to '+newloc) - shutil.copy(src, dest) + self.setCursor(Qt.BusyCursor) + self.library_view.setEnabled(False) + self.library_view.close() + src = open(self.database_path, 'rb') + shutil.copyfileobj(src, dest) src.close() dest.close() self.database_path = newloc + settings = QSettings() + settings.setValue("database path", QVariant(self.database_path)) + os.unlink(src.name) except Exception, err: + traceback.print_exc() d = error_dialog(self, 'Could not move database', unicode(err)) d.exec_() finally: + self.unsetCursor() + self.library_view.setEnabled(True) self.status_bar.clearMessage() self.search.clear_to_help() self.status_bar.reset_info() @@ -764,8 +774,8 @@ class Main(MainWindow, Ui_MainWindow): settings.beginGroup("Main Window") self.resize(settings.value("size", QVariant(QSize(800, 600))).toSize()) settings.endGroup() - self.database_path = settings.value("database path", - QVariant(os.path.join(os.path.expanduser('~'),'library1.db'))).toString() + self.database_path = qstring_to_unicode(settings.value("database path", + QVariant(os.path.join(os.path.expanduser('~'),'library1.db'))).toString()) def write_settings(self): settings = QSettings() @@ -795,19 +805,14 @@ class Main(MainWindow, Ui_MainWindow): self.write_settings() e.accept() - def check_for_updates(self): - src = urllib.urlopen('http://pypi.python.org/pypi/libprs500').read() - soup = BeautifulSoup(src) - meta = soup.find('link', rel='meta', title='DOAP') - if meta: - src = meta['href'] - match = re.search(r'version=(\S+)', src) - if match: - version = match.group(1) - if version != __version__: - self.latest_version = '%s'%('Latest version: '+version,) - self.vanity.setText(self.vanity_template%(dict(version=self.latest_version, device=self.device_info))) - self.vanity.update() + def update_found(self, version): + os = 'windows' if iswindows else 'osx' if isosx else 'linux' + url = 'https://libprs500.kovidgoyal.net/download_'+os + self.latest_version = 'Latest version: %s'%(url, version) + self.vanity.setText(self.vanity_template%(dict(version=self.latest_version, + device=self.device_info))) + self.vanity.update() + def main(args=sys.argv): from PyQt4.Qt import QApplication diff --git a/src/libprs500/library/database.py b/src/libprs500/library/database.py index 7c1e4e4a04..a44f68cac1 100644 --- a/src/libprs500/library/database.py +++ b/src/libprs500/library/database.py @@ -697,8 +697,10 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; def __del__(self): global _lock_file import os - if _lock_file is not None and os.path.exists(_lock_file): - os.unlink(_lock_file) + if _lock_file is not None: + _lock_file.close() + if os.path.exists(_lock_file.name): + os.unlink(_lock_file.name) def __init__(self, dbpath): self.dbpath = dbpath @@ -714,6 +716,13 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; if self.user_version == 3: # Upgrade to 4 LibraryDatabase.upgrade_version3(self.conn) + def close(self): + global _lock_file + _lock_file.close() + os.unlink(_lock_file.name) + _lock_file = None + self.conn.close() + @apply def user_version(): doc = 'The user version of this database'