From f573d07e819fe6f557465dd94712492774520ba9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 20 Jan 2011 11:16:03 -0700 Subject: [PATCH] And we have tags --- src/calibre/gui2/dialogs/metadata_single.py | 2 +- src/calibre/gui2/dialogs/tag_editor.py | 4 +- src/calibre/gui2/metadata/single.py | 135 +++++++++++++++++++- src/calibre/manual/faq.rst | 2 +- 4 files changed, 133 insertions(+), 10 deletions(-) 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 `_. If the installer still doesn't work, then something on your computer is preventing it from running. Best place to ask for more help is in the `forums `_. +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 `_. If the installer still doesn't work, then something on your computer is preventing it from running. Try rebooting your computer and running a registry cleaner like `Wise registry cleaner `_. Best place to ask for more help is in the `forums `_. My antivirus program claims |app| is a virus/trojan? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~