diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index a2ced18e0f..00bc98cb17 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -775,7 +775,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): self.original_tags = unicode(self.tags.text()) else: self.tags.setText(self.original_tags) - d = TagEditor(self, self.db, self.row) + d = TagEditor(self, self.db, self.id) d.exec_() if d.result() == QDialog.Accepted: tag_string = ', '.join(d.tags) diff --git a/src/calibre/gui2/dialogs/tag_editor.py b/src/calibre/gui2/dialogs/tag_editor.py index 6c5aa6de66..c12b7357f1 100644 --- a/src/calibre/gui2/dialogs/tag_editor.py +++ b/src/calibre/gui2/dialogs/tag_editor.py @@ -10,13 +10,13 @@ from calibre.utils.icu import sort_key class TagEditor(QDialog, Ui_TagEditor): - def __init__(self, window, db, index=None): + def __init__(self, window, db, id_=None): QDialog.__init__(self, window) Ui_TagEditor.__init__(self) self.setupUi(self) self.db = db - self.index = index + self.index = db.row(id_) if self.index is not None: tags = self.db.tags(self.index) else: diff --git a/src/calibre/gui2/metadata/single.py b/src/calibre/gui2/metadata/single.py index 9cffe2ee55..f531e62fde 100644 --- a/src/calibre/gui2/metadata/single.py +++ b/src/calibre/gui2/metadata/single.py @@ -10,14 +10,15 @@ import textwrap, re, os from PyQt4.Qt import QDialogButtonBox, Qt, QTabWidget, QScrollArea, \ QVBoxLayout, QIcon, QToolButton, QWidget, QLabel, QGridLayout, \ QDoubleSpinBox, QListWidgetItem, QSize, pyqtSignal, QPixmap, \ - QSplitter, QPushButton, QGroupBox, QHBoxLayout + QSplitter, QPushButton, QGroupBox, QHBoxLayout, QSpinBox, \ + QMessageBox from calibre.gui2 import ResizableDialog, file_icon_provider, \ - choose_files, error_dialog, choose_images + choose_files, error_dialog, choose_images, question_dialog from calibre.utils.icu import sort_key from calibre.utils.config import tweaks from calibre.gui2.widgets import EnLineEdit, CompleteComboBox, \ - EnComboBox, FormatList, ImageView + EnComboBox, FormatList, ImageView, CompleteLineEdit from calibre.ebooks.metadata import title_sort, authors_to_string, \ string_to_authors from calibre.utils.date import local_tz @@ -27,6 +28,7 @@ from calibre.customize.ui import run_plugins_on_import from calibre.utils.date import utcfromtimestamp from calibre.gui2.comments_editor import Editor from calibre.library.comments import comments_to_html +from calibre.gui2.dialogs.tag_editor import TagEditor ''' The interface common to all widgets used to set basic metadata @@ -739,6 +741,104 @@ class CommentsEdit(Editor): # {{{ return True # }}} +class RatingEdit(QSpinBox): # {{{ + LABEL = _('&Rating:') + TOOLTIP = _('Rating of this book. 0-5 stars') + + def __init__(self, parent): + QSpinBox.__init__(self, parent) + self.setToolTip(self.TOOLTIP) + self.setWhatsThis(self.TOOLTIP) + self.setMaximum(5) + self.setSuffix(' ' + _('stars')) + + @dynamic_property + def current_val(self): + def fget(self): + return self.value() + def fset(self, val): + if val is None: + val = 0 + val = int(val) + if val < 0: + val = 0 + if val > 5: + val = 5 + self.setValue(val) + return property(fget=fget, fset=fset) + + def initialize(self, db, id_): + val = db.rating(id_, index_is_id=True) + if val > 0: + val = int(val/2.) + else: + val = 0 + self.current_val = val + self.original_val = self.current_val + + def commit(self, db, id_): + db.set_rating(id_, 2*self.current_val, notify=False, commit=False) + return True + +# }}} + +class TagsEdit(CompleteLineEdit): # {{{ + LABEL = _('Ta&gs:') + TOOLTIP = '
'+_('Tags categorize the book. This is particularly '
+ 'useful while searching.
They can be any words'
+ 'or phrases, separated by commas.')
+
+ def __init__(self, parent):
+ CompleteLineEdit.__init__(self, parent)
+ self.setToolTip(self.TOOLTIP)
+ self.setWhatsThis(self.TOOLTIP)
+
+ @dynamic_property
+ def current_val(self):
+ def fget(self):
+ return [x.strip() for x in unicode(self.text()).split(',')]
+ def fset(self, val):
+ if not val:
+ val = []
+ self.setText(', '.join([x.strip() for x in val]))
+ return property(fget=fget, fset=fset)
+
+ def initialize(self, db, id_):
+ tags = db.tags(id_, index_is_id=True)
+ tags = tags.split(',') if tags else []
+ self.current_val = tags
+ self.update_items_cache(db.all_tags())
+ self.original_val = self.current_val
+
+ @property
+ def changed(self):
+ return self.current_val != self.original_val
+
+ def edit(self, db, id_):
+ if self.changed:
+ if question_dialog(self, _('Tags changed'),
+ _('You have changed the tags. In order to use the tags'
+ ' editor, you must either discard or apply these '
+ 'changes'), show_copy_button=False,
+ buttons=QMessageBox.Apply|QMessageBox.Discard,
+ yes_button=QMessageBox.Apply):
+ self.commit(db, id_)
+ db.commit()
+ self.original_val = self.current_val
+ else:
+ self.current_val = self.original_val
+ d = TagEditor(self, db, id_)
+ if d.exec_() == TagEditor.Accepted:
+ self.current_val = d.tags
+ self.update_items_cache(db.all_tags())
+
+
+ def commit(self, db, id_):
+ db.set_tags(id_, self.current_val, notify=False, commit=False)
+ return True
+
+# }}}
+
class MetadataSingleDialog(ResizableDialog):
view_format = pyqtSignal(object)
@@ -778,7 +878,7 @@ class MetadataSingleDialog(ResizableDialog):
def create_basic_metadata_widgets(self): # {{{
self.basic_metadata_widgets = []
- # Title
+
self.title = TitleEdit(self)
self.deduce_title_sort_button = QToolButton(self)
self.deduce_title_sort_button.setToolTip(
@@ -791,7 +891,6 @@ class MetadataSingleDialog(ResizableDialog):
self.deduce_title_sort_button)
self.basic_metadata_widgets.extend([self.title, self.title_sort])
- # Authors
self.authors = AuthorsEdit(self)
self.deduce_author_sort_button = QToolButton(self)
self.deduce_author_sort_button.setToolTip(_(
@@ -826,6 +925,17 @@ class MetadataSingleDialog(ResizableDialog):
self.comments = CommentsEdit(self)
self.basic_metadata_widgets.append(self.comments)
+ self.rating = RatingEdit(self)
+ self.basic_metadata_widgets.append(self.rating)
+
+ self.tags = TagsEdit(self)
+ self.tags_editor_button = QToolButton(self)
+ self.tags_editor_button.setToolTip(_('Open Tag Editor'))
+ self.tags_editor_button.setIcon(QIcon(I('chapters.png')))
+ self.tags_editor_button.clicked.connect(self.tags_editor)
+ self.basic_metadata_widgets.append(self.tags)
+
+
# }}}
def do_layout(self): # {{{
@@ -876,8 +986,18 @@ class MetadataSingleDialog(ResizableDialog):
self.tabs[0].middle = w = QWidget(self)
w.l = l = QGridLayout()
w.setLayout(w.l)
- l.addWidget(gb, 0, 0, 1, 3)
+ l.setMargin(0)
self.splitter.addWidget(w)
+ def create_row2(row, widget, button=None):
+ ql = BuddyLabel(widget)
+ l.addWidget(ql, row, 0, 1, 1)
+ l.addWidget(widget, row, 1, 1, 2 if button is None else 1)
+ if button is not None:
+ l.addWidget(button, row, 2, 1, 1)
+
+ l.addWidget(gb, 0, 0, 1, 3)
+ create_row2(1, self.rating)
+ create_row2(2, self.tags, self.tags_editor_button)
self.tabs[0].gb2 = gb = QGroupBox(_('&Comments'), self)
gb.l = l = QVBoxLayout()
@@ -911,6 +1031,9 @@ class MetadataSingleDialog(ResizableDialog):
self.series.setCurrentIndex(i)
break
+ def tags_editor(self, *args):
+ self.tags.edit(self.db, self.book_id)
+
if __name__ == '__main__':
from PyQt4.Qt import QApplication
diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst
index 3e382c8f10..5ebe91bc76 100644
--- a/src/calibre/manual/faq.rst
+++ b/src/calibre/manual/faq.rst
@@ -441,7 +441,7 @@ menu, choose "Validate fonts".
I downloaded the installer, but it is not working?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Downloading from the internet can sometimes result in a corrupted download. If the |app| installer you downloaded is not opening, try downloading it again. If re-downloading it does not work, download it from `an alternate location