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 ¬ifications 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):