From cdc69fcfc1c418359dff62a065de913fbf606db2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 12 Apr 2013 12:52:54 +0530 Subject: [PATCH 1/3] Fix #1168231 (enhancement Choose Library by Path would be so much easier to work with if...) --- src/calibre/gui2/actions/copy_to_library.py | 36 +++++++++++++-------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/calibre/gui2/actions/copy_to_library.py b/src/calibre/gui2/actions/copy_to_library.py index 15155990a0..8465cb98f0 100644 --- a/src/calibre/gui2/actions/copy_to_library.py +++ b/src/calibre/gui2/actions/copy_to_library.py @@ -10,8 +10,7 @@ from functools import partial from threading import Thread from contextlib import closing -from PyQt4.Qt import (QToolButton, QDialog, QGridLayout, QIcon, QLabel, - QCheckBox, QDialogButtonBox) +from PyQt4.Qt import (QToolButton, QDialog, QGridLayout, QIcon, QLabel, QDialogButtonBox) from calibre.gui2.actions import InterfaceAction from calibre.gui2 import (error_dialog, Dispatcher, warning_dialog, gprefs, @@ -21,7 +20,7 @@ from calibre.gui2.widgets import HistoryLineEdit from calibre.utils.config import prefs, tweaks from calibre.utils.date import now -class Worker(Thread): # {{{ +class Worker(Thread): # {{{ def __init__(self, ids, db, loc, progress, done, delete_after): Thread.__init__(self) @@ -71,8 +70,10 @@ class Worker(Thread): # {{{ mi.timestamp = now() self.progress(i, mi.title) fmts = self.db.formats(x, index_is_id=True) - if not fmts: fmts = [] - else: fmts = fmts.split(',') + if not fmts: + fmts = [] + else: + fmts = fmts.split(',') paths = [] for fmt in fmts: p = self.db.format(x, fmt, index_is_id=True, @@ -82,7 +83,7 @@ class Worker(Thread): # {{{ automerged = False if prefs['add_formats_to_existing']: identical_book_list = newdb.find_identical_books(mi) - if identical_book_list: # books with same author and nearly same title exist in newdb + if identical_book_list: # books with same author and nearly same title exist in newdb self.auto_merged_ids[x] = _('%(title)s by %(author)s')%\ dict(title=mi.title, author=mi.format_field('authors')[1]) automerged = True @@ -127,7 +128,7 @@ class Worker(Thread): # {{{ # }}} -class ChooseLibrary(QDialog): # {{{ +class ChooseLibrary(QDialog): # {{{ def __init__(self, parent): super(ChooseLibrary, self).__init__(parent) @@ -146,12 +147,19 @@ class ChooseLibrary(QDialog): # {{{ b.setToolTip(_('Browse for library')) b.clicked.connect(self.browse) l.addWidget(b, 0, 2) - self.c = c = QCheckBox(_('&Delete after copy')) - l.addWidget(c, 1, 0, 1, 3) - self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) + self.bb = bb = QDialogButtonBox(QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) - l.addWidget(bb, 2, 0, 1, 3) + self.delete_after_copy = False + b = bb.addButton(_('&Copy'), bb.AcceptRole) + b.setIcon(QIcon(I('edit-copy.png'))) + b.setToolTip(_('Copy to the specified library')) + b2 = bb.addButton(_('&Move'), bb.AcceptRole) + b2.clicked.connect(lambda: setattr(self, 'delete_after_copy', True)) + b2.setIcon(QIcon(I('edit-cut.png'))) + b2.setToolTip(_('Copy to the specified library and delete from the current library')) + b.setDefault(True) + l.addWidget(bb, 1, 0, 1, 3) le.setMinimumWidth(350) self.resize(self.sizeHint()) @@ -163,7 +171,7 @@ class ChooseLibrary(QDialog): # {{{ @property def args(self): - return (unicode(self.le.text()), self.c.isChecked()) + return (unicode(self.le.text()), self.delete_after_copy) # }}} class CopyToLibraryAction(InterfaceAction): @@ -204,7 +212,7 @@ class CopyToLibraryAction(InterfaceAction): self.menu.addAction(name, partial(self.copy_to_library, loc)) self.menu.addAction(name + ' ' + _('(delete after copy)'), - partial(self.copy_to_library, loc, delete_after=True)) + partial(self.copy_to_library, loc, delete_after=True)) self.menu.addSeparator() self.menu.addAction(_('Choose library by path...'), self.choose_library) @@ -214,6 +222,8 @@ class CopyToLibraryAction(InterfaceAction): d = ChooseLibrary(self.gui) if d.exec_() == d.Accepted: path, delete_after = d.args + if not path: + return db = self.gui.library_view.model().db current = os.path.normcase(os.path.abspath(db.library_path)) if current == os.path.normcase(os.path.abspath(path)): From 1096eaaadf19635905b95996d89d8b4f68cf1a5c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 12 Apr 2013 13:13:30 +0530 Subject: [PATCH 2/3] ... --- Changelog.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.yaml b/Changelog.yaml index 9c1514bab2..808662ba9e 100644 --- a/Changelog.yaml +++ b/Changelog.yaml @@ -28,7 +28,7 @@ description: "To enable them go to Preferences->Metadata download and enable the 'Google Image' and 'Big Book Search' sources. Google Images is useful for finding larger covers as well as alternate versions of the cover. Big Book Search searches for alternate covers from amazon.com. It can occasionally find nicer covers than the direct Amazon source. Note that both these sources download multiple covers for a single book. Some of these covers can be wrong (i.e. they may be of a different book or not covers at all, so you should inspect the results and manually pick the best match). When bulk downloading, these sources are only used if the other sources find no covers." type: major - - title: "Content server: Allow specifying a reestriction to use for the server when embedding it as a WSGI app." + - title: "Content server: Allow specifying a restriction to use for the server when embedding it as a WSGI app." tickets: [1167951] - title: "Get Books: Add a plugin for the Koobe Polish book store" From 311d2cc8944c9925d1eeb03c4f7582f33e4b35b3 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 12 Apr 2013 16:05:37 +0530 Subject: [PATCH 3/3] Add a checkbox to create and instead of or based VLs --- src/calibre/gui2/search_restriction_mixin.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/search_restriction_mixin.py b/src/calibre/gui2/search_restriction_mixin.py index 702f67f69d..8338baf6c4 100644 --- a/src/calibre/gui2/search_restriction_mixin.py +++ b/src/calibre/gui2/search_restriction_mixin.py @@ -8,7 +8,7 @@ from functools import partial from PyQt4.Qt import ( Qt, QMenu, QPoint, QIcon, QDialog, QGridLayout, QLabel, QLineEdit, - QDialogButtonBox, QSize, QVBoxLayout, QListWidget, QStringList) + QDialogButtonBox, QSize, QVBoxLayout, QListWidget, QStringList, QCheckBox) from calibre.gui2 import error_dialog, question_dialog from calibre.gui2.widgets import ComboBoxWithHelp @@ -31,6 +31,9 @@ class SelectNames(QDialog): # {{{ self._names.setSelectionMode(self._names.ExtendedSelection) l.addWidget(self._names) + self._and = QCheckBox(_('Match all selected %s names')%txt) + l.addWidget(self._and) + self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) @@ -42,6 +45,11 @@ class SelectNames(QDialog): # {{{ def names(self): for item in self._names.selectedItems(): yield unicode(item.data(Qt.DisplayRole).toString()) + + @property + def match_type(self): + return ' and ' if self._and.isChecked() else ' or ' + # }}} MAX_VIRTUAL_LIBRARY_NAME_LENGTH = 40 @@ -154,7 +162,9 @@ class CreateVirtualLibrary(QDialog): # {{{ search = ['%s:"=%s"'%(prefix, x.replace('"', '\\"')) for x in d.names] if search: self.vl_name.setText(d.names.next()) - self.vl_text.setText(' or '.join(search)) + self.vl_text.setText(d.match_type.join(search)) + self.vl_text.setCursorPosition(0) + self.vl_name.setCursorPosition(0) def accept(self): n = unicode(self.vl_name.text()).strip()