diff --git a/src/calibre/gui2/dialogs/config/__init__.py b/src/calibre/gui2/dialogs/config/__init__.py index 5e10ea1621..5d855b5263 100644 --- a/src/calibre/gui2/dialogs/config/__init__.py +++ b/src/calibre/gui2/dialogs/config/__init__.py @@ -14,7 +14,7 @@ from PyQt4.Qt import QDialog, QListWidgetItem, QIcon, \ from calibre.constants import iswindows, isosx from calibre.gui2.dialogs.config.config_ui import Ui_Dialog from calibre.gui2.dialogs.config.create_custom_column import CreateCustomColumn -from calibre.gui2 import choose_dir, error_dialog, config, \ +from calibre.gui2 import choose_dir, error_dialog, config, gprefs, \ ALL_COLUMNS, NONE, info_dialog, choose_files, \ warning_dialog, ResizableDialog, question_dialog from calibre.utils.config import prefs @@ -480,6 +480,8 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): self.opt_enforce_cpu_limit.setChecked(config['enforce_cpu_limit']) self.device_detection_button.clicked.connect(self.debug_device_detection) self.port.editingFinished.connect(self.check_port_value) + self.show_splash_screen.setChecked(gprefs.get('show_splash_screen', + True)) def check_port_value(self, *args): port = self.port.value() @@ -852,6 +854,7 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): config['get_social_metadata'] = self.opt_get_social_metadata.isChecked() config['overwrite_author_title_metadata'] = self.opt_overwrite_author_title_metadata.isChecked() config['enforce_cpu_limit'] = bool(self.opt_enforce_cpu_limit.isChecked()) + gprefs['show_splash_screen'] = bool(self.show_splash_screen.isChecked()) fmts = [] for i in range(self.viewer.count()): if self.viewer.item(i).checkState() == Qt.Checked: diff --git a/src/calibre/gui2/dialogs/config/config.ui b/src/calibre/gui2/dialogs/config/config.ui index 5d84e2e2af..db748dae7e 100644 --- a/src/calibre/gui2/dialogs/config/config.ui +++ b/src/calibre/gui2/dialogs/config/config.ui @@ -331,8 +331,8 @@ - - + + Use &Roman numerals for series number @@ -342,28 +342,35 @@ - + Enable system &tray icon (needs restart) - + Show &notifications in system tray - + + + + Show &splash screen at startup + + + + Show cover &browser in a separate window (needs restart) - + Search as you type @@ -373,21 +380,21 @@ - + Automatically send downloaded &news to ebook reader - + &Delete news from library when it is automatically sent to reader - + @@ -404,7 +411,7 @@ - + Toolbar @@ -452,7 +459,7 @@ - + @@ -527,12 +534,12 @@ - - ... - Add a user-defined column + + ... + :/images/plus.svg:/images/plus.svg diff --git a/src/calibre/gui2/dialogs/saved_search_editor.ui b/src/calibre/gui2/dialogs/saved_search_editor.ui index 3fffff7abf..6d98d25667 100644 --- a/src/calibre/gui2/dialogs/saved_search_editor.ui +++ b/src/calibre/gui2/dialogs/saved_search_editor.ui @@ -11,7 +11,7 @@ - Tag Editor + Saved Search Editor @@ -137,7 +137,11 @@ - + + + Change the contents of the saved search + + diff --git a/src/calibre/gui2/dialogs/tag_categories.ui b/src/calibre/gui2/dialogs/tag_categories.ui index 2904b2464e..d280d5061a 100644 --- a/src/calibre/gui2/dialogs/tag_categories.ui +++ b/src/calibre/gui2/dialogs/tag_categories.ui @@ -11,7 +11,7 @@ - Tag Editor + User Categories Editor diff --git a/src/calibre/gui2/dialogs/tag_list_editor.py b/src/calibre/gui2/dialogs/tag_list_editor.py index d5fe3b6181..c2cc1d7116 100644 --- a/src/calibre/gui2/dialogs/tag_list_editor.py +++ b/src/calibre/gui2/dialogs/tag_list_editor.py @@ -9,7 +9,7 @@ from calibre.gui2 import question_dialog, error_dialog class TagListEditor(QDialog, Ui_TagListEditor): def tag_cmp(self, x, y): - return cmp(x.text().lower(), y.text().lower()) + return cmp(x.lower(), y.lower()) def __init__(self, window, db, tag_to_match): QDialog.__init__(self, window) @@ -19,10 +19,12 @@ class TagListEditor(QDialog, Ui_TagListEditor): self.to_rename = {} self.to_delete = [] self.db = db - all_tags = db.get_tags_and_ids() - for tag in sorted(all_tags.keys()): + self.all_tags = {} + for k,v in db.get_tags_with_ids(): + self.all_tags[v] = k + for tag in sorted(self.all_tags.keys(), cmp=self.tag_cmp): item = QListWidgetItem(tag) - item.setData(all_tags[tag]) + item.setData(Qt.UserRole, self.all_tags[tag]) self.available_tags.addItem(item) items = self.available_tags.findItems(tag_to_match, Qt.MatchExactly) @@ -35,8 +37,14 @@ class TagListEditor(QDialog, Ui_TagListEditor): self.connect(self.available_tags, SIGNAL('itemChanged(QListWidgetItem *)'), self.finish_editing) def finish_editing(self, item): - if item.text() != self.item_before_editing: - self.to_rename[self.item_before_editing] = item.text() + if item.text() != self.item_before_editing.text(): + if item.text() in self.all_tags.keys() or item.text() in self.to_rename.keys(): + error_dialog(self, 'Tag already used', + 'The tag %s is already used.'%(item.text())).exec_() + item.setText(self.item_before_editing.text()) + return + id,ign = self.item_before_editing.data(Qt.UserRole).toInt() + self.to_rename[item.text()] = id def rename_tag(self): item = self.available_tags.currentItem() @@ -46,7 +54,7 @@ class TagListEditor(QDialog, Ui_TagListEditor): if item is None: error_dialog(self, 'No tag selected', 'You must select one tag from the list of Available tags.').exec_() return - self.item_before_editing = item.text() + self.item_before_editing = item.clone() item.setFlags (item.flags() | Qt.ItemIsEditable); self.available_tags.editItem(item) @@ -73,8 +81,8 @@ class TagListEditor(QDialog, Ui_TagListEditor): self.available_tags.takeItem(self.available_tags.row(item)) def accept(self): - for item in self.to_rename: - self.db.rename_tag(old=unicode(item), new=unicode(self.to_rename[item])) + for text in self.to_rename: + self.db.rename_tag(self.to_rename[text], unicode(text)) for item in self.to_delete: self.db.delete_tag(unicode(item.text())) QDialog.accept(self) diff --git a/src/calibre/gui2/dialogs/tag_list_editor.ui b/src/calibre/gui2/dialogs/tag_list_editor.ui index 5d7c95db1f..383dc875ac 100644 --- a/src/calibre/gui2/dialogs/tag_list_editor.ui +++ b/src/calibre/gui2/dialogs/tag_list_editor.ui @@ -63,6 +63,12 @@ :/images/trash.svg:/images/trash.svg + + + 32 + 32 + + @@ -77,6 +83,15 @@ :/images/edit_input.svg:/images/edit_input.svg + + + 32 + 32 + + + + Ctrl+S + diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 73f7f3839d..29ae1875c8 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -5,13 +5,15 @@ import sys, os, time, socket, traceback from functools import partial from PyQt4.Qt import QCoreApplication, QIcon, QMessageBox, QObject, QTimer, \ - QThread, pyqtSignal, Qt, QProgressDialog, QString + QThread, pyqtSignal, Qt, QProgressDialog, QString, QPixmap, \ + QSplashScreen, QApplication from calibre import prints, plugins -from calibre.constants import iswindows, __appname__, isosx, filesystem_encoding +from calibre.constants import iswindows, __appname__, isosx, DEBUG, \ + filesystem_encoding from calibre.utils.ipc import ADDRESS, RC from calibre.gui2 import ORG_NAME, APP_UID, initialize_file_icon_provider, \ - Application, choose_dir, error_dialog, question_dialog + Application, choose_dir, error_dialog, question_dialog, gprefs from calibre.gui2.main_window import option_parser as _option_parser from calibre.utils.config import prefs, dynamic from calibre.library.database2 import LibraryDatabase2 @@ -113,16 +115,25 @@ class GuiRunner(QObject): initialization''' def __init__(self, opts, args, actions, listener, app): + self.startup_time = time.time() self.opts, self.args, self.listener, self.app = opts, args, listener, app self.actions = actions self.main = None QObject.__init__(self) + self.splash_screen = None self.timer = QTimer.singleShot(1, self.initialize) + if DEBUG: + prints('Starting up...') def start_gui(self): from calibre.gui2.ui import Main main = Main(self.opts) + if self.splash_screen is not None: + self.splash_screen.showMessage(_('Initializing user interface...')) + self.splash_screen.finish(main) main.initialize(self.library_path, self.db, self.listener, self.actions) + if DEBUG: + prints('Started up in', time.time() - self.startup_time) add_filesystem_book = partial(main.add_filesystem_book, allow_device=False) sys.excepthook = main.unhandled_exception if len(self.args) > 1: @@ -143,7 +154,7 @@ class GuiRunner(QObject): if db is None and tb is not None: # DB Repair failed - error_dialog(None, _('Repairing failed'), + error_dialog(self.splash_screen, _('Repairing failed'), _('The database repair failed. Starting with ' 'a new empty library.'), det_msg=tb, show=True) @@ -160,7 +171,7 @@ class GuiRunner(QObject): os.makedirs(x) except: x = os.path.expanduser('~') - candidate = choose_dir(None, 'choose calibre library', + candidate = choose_dir(self.splash_screen, 'choose calibre library', _('Choose a location for your new calibre e-book library'), default_dir=x) @@ -171,7 +182,7 @@ class GuiRunner(QObject): self.library_path = candidate db = LibraryDatabase2(candidate) except: - error_dialog(None, _('Bad database location'), + error_dialog(self.splash_screen, _('Bad database location'), _('Bad database location %r. calibre will now quit.' )%self.library_path, det_msg=traceback.format_exc(), show=True) @@ -185,7 +196,7 @@ class GuiRunner(QObject): try: db = LibraryDatabase2(self.library_path) except (sqlite.Error, DatabaseException): - repair = question_dialog(None, _('Corrupted database'), + repair = question_dialog(self.splash_screen, _('Corrupted database'), _('Your calibre database appears to be corrupted. Do ' 'you want calibre to try and repair it automatically? ' 'If you say No, a new empty calibre library will be created.'), @@ -204,14 +215,27 @@ class GuiRunner(QObject): self.repair.start() return except: - error_dialog(None, _('Bad database location'), + error_dialog(self.splash_screen, _('Bad database location'), _('Bad database location %r. Will start with ' ' a new, empty calibre library')%self.library_path, det_msg=traceback.format_exc(), show=True) self.initialize_db_stage2(db, None) + def show_splash_screen(self): + self.splash_pixmap = QPixmap() + self.splash_pixmap.load(I('library.png')) + self.splash_screen = QSplashScreen(self.splash_pixmap, + Qt.SplashScreen|Qt.WindowStaysOnTopHint) + self.splash_screen.showMessage(_('Starting %s: Loading books...') % + __appname__) + self.splash_screen.show() + QApplication.instance().processEvents() + def initialize(self, *args): + if gprefs.get('show_splash_screen', True): + self.show_splash_screen() + self.library_path = get_library_path() if self.library_path is None: self.initialization_failed() diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 1eae6866a4..0544293095 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -985,17 +985,18 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): if notify: self.notify('metadata', [id]) - def get_tags_and_ids(self): + # Convenience method for tags_list_editor + def get_tags_with_ids(self): result = self.conn.get('SELECT * FROM tags') if not result: return {} - r = {} + r = [] for k,v in result: - r[v] = k + r.append((k,v)) return r - def rename_tag(self, old, new): - self.conn.execute('UPDATE tags SET name=? WHERE name=?', (new, old)) + def rename_tag(self, id, new): + self.conn.execute('UPDATE tags SET name=? WHERE id=?', (new, id)) self.conn.commit() def get_tags(self, id):