mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from custcol trunk
This commit is contained in:
commit
301b78564d
@ -6,6 +6,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from PyQt4.Qt import QComboBox, QLabel, QSpinBox, QDoubleSpinBox, QDateEdit, \
|
from PyQt4.Qt import QComboBox, QLabel, QSpinBox, QDoubleSpinBox, QDateEdit, \
|
||||||
QDate, QGroupBox, QVBoxLayout, QPlainTextEdit, QSizePolicy, \
|
QDate, QGroupBox, QVBoxLayout, QPlainTextEdit, QSizePolicy, \
|
||||||
@ -18,10 +19,11 @@ from calibre.utils.config import tweaks
|
|||||||
|
|
||||||
class Base(object):
|
class Base(object):
|
||||||
|
|
||||||
def __init__(self, db, col_id):
|
def __init__(self, db, col_id, parent=None):
|
||||||
self.db, self.col_id = db, col_id
|
self.db, self.col_id = db, col_id
|
||||||
self.col_metadata = db.custom_column_num_map[col_id]
|
self.col_metadata = db.custom_column_num_map[col_id]
|
||||||
self.initial_val = None
|
self.initial_val = None
|
||||||
|
self.setup_ui(parent)
|
||||||
|
|
||||||
def initialize(self, book_id):
|
def initialize(self, book_id):
|
||||||
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
||||||
@ -43,8 +45,7 @@ class Base(object):
|
|||||||
|
|
||||||
class Bool(Base):
|
class Bool(Base):
|
||||||
|
|
||||||
def __init__(self, db, col_id, parent=None):
|
def setup_ui(self, parent):
|
||||||
Base.__init__(self, db, col_id)
|
|
||||||
self.widgets = [QLabel('&'+self.col_metadata['name'], parent),
|
self.widgets = [QLabel('&'+self.col_metadata['name'], parent),
|
||||||
QComboBox(parent)]
|
QComboBox(parent)]
|
||||||
w = self.widgets[1]
|
w = self.widgets[1]
|
||||||
@ -69,8 +70,7 @@ class Bool(Base):
|
|||||||
|
|
||||||
class Int(Base):
|
class Int(Base):
|
||||||
|
|
||||||
def __init__(self, db, col_id, parent=None):
|
def setup_ui(self, parent):
|
||||||
Base.__init__(self, db, col_id)
|
|
||||||
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
||||||
QSpinBox(parent)]
|
QSpinBox(parent)]
|
||||||
w = self.widgets[1]
|
w = self.widgets[1]
|
||||||
@ -93,8 +93,7 @@ class Int(Base):
|
|||||||
|
|
||||||
class Float(Int):
|
class Float(Int):
|
||||||
|
|
||||||
def __init__(self, db, col_id, parent=None):
|
def setup_ui(self, parent):
|
||||||
Base.__init__(self, db, col_id)
|
|
||||||
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
||||||
QDoubleSpinBox(parent)]
|
QDoubleSpinBox(parent)]
|
||||||
w = self.widgets[1]
|
w = self.widgets[1]
|
||||||
@ -103,8 +102,8 @@ class Float(Int):
|
|||||||
|
|
||||||
class Rating(Int):
|
class Rating(Int):
|
||||||
|
|
||||||
def __init__(self, db, col_id, parent=None):
|
def setup_ui(self, parent):
|
||||||
Int.__init__(self, db, col_id)
|
Int.setup_ui(self, parent)
|
||||||
w = self.widgets[1]
|
w = self.widgets[1]
|
||||||
w.setRange(0, 5)
|
w.setRange(0, 5)
|
||||||
w.setSuffix(' '+_('stars'))
|
w.setSuffix(' '+_('stars'))
|
||||||
@ -125,8 +124,7 @@ class Rating(Int):
|
|||||||
|
|
||||||
class DateTime(Base):
|
class DateTime(Base):
|
||||||
|
|
||||||
def __init__(self, db, col_id, parent=None):
|
def setup_ui(self, parent):
|
||||||
Base.__init__(self, db, col_id)
|
|
||||||
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
||||||
QDateEdit(parent)]
|
QDateEdit(parent)]
|
||||||
w = self.widgets[1]
|
w = self.widgets[1]
|
||||||
@ -153,8 +151,7 @@ class DateTime(Base):
|
|||||||
|
|
||||||
class Comments(Base):
|
class Comments(Base):
|
||||||
|
|
||||||
def __init__(self, db, col_id, parent=None):
|
def setup_ui(self, parent):
|
||||||
Base.__init__(self, db, col_id)
|
|
||||||
self._box = QGroupBox(parent)
|
self._box = QGroupBox(parent)
|
||||||
self._box.setTitle('&'+self.col_metadata['name'])
|
self._box.setTitle('&'+self.col_metadata['name'])
|
||||||
self._layout = QVBoxLayout()
|
self._layout = QVBoxLayout()
|
||||||
@ -178,9 +175,8 @@ class Comments(Base):
|
|||||||
|
|
||||||
class Text(Base):
|
class Text(Base):
|
||||||
|
|
||||||
def __init__(self, db, col_id, parent=None):
|
def setup_ui(self, parent):
|
||||||
Base.__init__(self, db, col_id)
|
values = self.all_values = list(self.db.all_custom(num=self.col_id))
|
||||||
values = self.all_values = list(self.db.all_custom(num=col_id))
|
|
||||||
values.sort(cmp = lambda x,y: cmp(x.lower(), y.lower()))
|
values.sort(cmp = lambda x,y: cmp(x.lower(), y.lower()))
|
||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
w = TagsLineEdit(parent, values)
|
w = TagsLineEdit(parent, values)
|
||||||
@ -238,16 +234,16 @@ widgets = {
|
|||||||
'comments': Comments,
|
'comments': Comments,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def field_sort(y, z, x=None):
|
||||||
|
m1, m2 = x[y], x[z]
|
||||||
|
n1 = 'zzzzz' if m1['datatype'] == 'comments' else m1['name']
|
||||||
|
n2 = 'zzzzz' if m2['datatype'] == 'comments' else m2['name']
|
||||||
|
return cmp(n1.lower(), n2.lower())
|
||||||
|
|
||||||
def populate_single_metadata_page(left, right, db, book_id, parent=None):
|
def populate_single_metadata_page(left, right, db, book_id, parent=None):
|
||||||
x = db.custom_column_num_map
|
x = db.custom_column_num_map
|
||||||
cols = list(x)
|
cols = list(x)
|
||||||
def field_sort(y, z):
|
cols.sort(cmp=partial(field_sort, x=x))
|
||||||
m1, m2 = x[y], x[z]
|
|
||||||
n1 = 'zzzzz' if m1['datatype'] == 'comments' else m1['name']
|
|
||||||
n2 = 'zzzzz' if m2['datatype'] == 'comments' else m2['name']
|
|
||||||
return cmp(n1.lower(), n2.lower())
|
|
||||||
|
|
||||||
cols.sort(cmp=field_sort)
|
|
||||||
ans = []
|
ans = []
|
||||||
for i, col in enumerate(cols):
|
for i, col in enumerate(cols):
|
||||||
w = widgets[x[col]['datatype']](db, col, parent)
|
w = widgets[x[col]['datatype']](db, col, parent)
|
||||||
@ -275,6 +271,107 @@ def populate_single_metadata_page(left, right, db, book_id, parent=None):
|
|||||||
|
|
||||||
return ans, items
|
return ans, items
|
||||||
|
|
||||||
def populate_bulk_metadata_page(left, right, db, book_id, parent=None):
|
class BulkBase(Base):
|
||||||
|
|
||||||
|
def get_initial_value(self, book_ids):
|
||||||
|
values = set([])
|
||||||
|
for book_id in book_ids:
|
||||||
|
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
||||||
|
if isinstance(val, list):
|
||||||
|
val = frozenset(val)
|
||||||
|
values.add(val)
|
||||||
|
if len(values) > 1:
|
||||||
|
break
|
||||||
|
ans = None
|
||||||
|
if len(values) == 1:
|
||||||
|
ans = iter(values).next()
|
||||||
|
if isinstance(ans, frozenset):
|
||||||
|
ans = list(ans)
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def initialize(self, book_ids):
|
||||||
|
self.initial_val = val = self.get_initial_value(book_ids)
|
||||||
|
val = self.normalize_db_val(val)
|
||||||
|
self.setter(val)
|
||||||
|
|
||||||
|
def commit(self, book_ids, notify=False):
|
||||||
|
val = self.getter()
|
||||||
|
val = self.normalize_ui_val(val)
|
||||||
|
if val != self.initial_val:
|
||||||
|
for book_id in book_ids:
|
||||||
|
self.db.set_custom(book_id, val, num=self.col_id, notify=notify)
|
||||||
|
|
||||||
|
class BulkBool(BulkBase, Bool):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class BulkRating(BulkBase, Rating):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class BulkInt(BulkBase, Int):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class BulkFloat(BulkBase, Float):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class BulkRating(BulkBase, Rating):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class BulkDateTime(BulkBase, DateTime):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class BulkText(BulkBase, Text):
|
||||||
|
|
||||||
|
def initialize(self, book_ids):
|
||||||
|
val = self.get_initial_value(book_ids)
|
||||||
|
self.initial_val = val = self.normalize_db_val(val)
|
||||||
|
if self.col_metadata['is_multiple']:
|
||||||
|
self.setter(val)
|
||||||
|
self.widgets[1].update_tags_cache(self.all_values)
|
||||||
|
else:
|
||||||
|
idx = None
|
||||||
|
for i, c in enumerate(self.all_values):
|
||||||
|
if c == val:
|
||||||
|
idx = i
|
||||||
|
self.widgets[1].addItem(c)
|
||||||
|
self.widgets[1].setEditText('')
|
||||||
|
if idx is not None:
|
||||||
|
self.widgets[1].setCurrentIndex(idx)
|
||||||
|
|
||||||
|
|
||||||
|
bulk_widgets = {
|
||||||
|
'bool' : BulkBool,
|
||||||
|
'rating' : BulkRating,
|
||||||
|
'int': BulkInt,
|
||||||
|
'float': BulkFloat,
|
||||||
|
'datetime': BulkDateTime,
|
||||||
|
'text' : BulkText,
|
||||||
|
}
|
||||||
|
|
||||||
|
def populate_bulk_metadata_page(layout, db, book_ids, parent=None):
|
||||||
|
x = db.custom_column_num_map
|
||||||
|
cols = list(x)
|
||||||
|
cols.sort(cmp=partial(field_sort, x=x))
|
||||||
|
ans = []
|
||||||
|
for i, col in enumerate(cols):
|
||||||
|
dt = x[col]['datatype']
|
||||||
|
if dt == 'comments':
|
||||||
|
continue
|
||||||
|
w = bulk_widgets[dt](db, col, parent)
|
||||||
|
ans.append(w)
|
||||||
|
w.initialize(book_ids)
|
||||||
|
row = layout.rowCount()
|
||||||
|
if len(w.widgets) == 1:
|
||||||
|
layout.addWidget(w.widgets[0], row, 0, 1, -1)
|
||||||
|
else:
|
||||||
|
w.widgets[0].setBuddy(w.widgets[1])
|
||||||
|
for c, widget in enumerate(w.widgets):
|
||||||
|
layout.addWidget(widget, row, c)
|
||||||
|
items = []
|
||||||
|
if len(ans) > 0:
|
||||||
|
items.append(QSpacerItem(10, 10, QSizePolicy.Minimum,
|
||||||
|
QSizePolicy.Expanding))
|
||||||
|
layout.addItem(items[-1], layout.rowCount(), 0, 1, 1)
|
||||||
|
layout.setRowStretch(layout.rowCount()-1, 100)
|
||||||
|
|
||||||
|
return ans, items
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
'''Dialog to edit metadata in bulk'''
|
'''Dialog to edit metadata in bulk'''
|
||||||
|
|
||||||
from PyQt4.QtCore import SIGNAL, QObject
|
from PyQt4.QtCore import SIGNAL, QObject
|
||||||
from PyQt4.QtGui import QDialog
|
from PyQt4.QtGui import QDialog, QGridLayout
|
||||||
|
|
||||||
from calibre.gui2.dialogs.metadata_bulk_ui import Ui_MetadataBulkDialog
|
from calibre.gui2.dialogs.metadata_bulk_ui import Ui_MetadataBulkDialog
|
||||||
from calibre.gui2.dialogs.tag_editor import TagEditor
|
from calibre.gui2.dialogs.tag_editor import TagEditor
|
||||||
@ -48,7 +48,16 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
|||||||
self.exec_()
|
self.exec_()
|
||||||
|
|
||||||
def create_custom_column_editors(self):
|
def create_custom_column_editors(self):
|
||||||
pass
|
w = self.central_widget.widget(1)
|
||||||
|
layout = QGridLayout()
|
||||||
|
|
||||||
|
self.custom_column_widgets, self.__cc_spacers = populate_bulk_metadata_page(
|
||||||
|
layout, self.db, self.ids, w)
|
||||||
|
w.setLayout(layout)
|
||||||
|
self.__custom_col_layouts = [layout]
|
||||||
|
ans = self.custom_column_widgets
|
||||||
|
for i in range(len(ans)-1):
|
||||||
|
w.setTabOrder(ans[i].widgets[-1], ans[i+1].widgets[-1])
|
||||||
|
|
||||||
def initialize_combos(self):
|
def initialize_combos(self):
|
||||||
self.initalize_authors()
|
self.initalize_authors()
|
||||||
@ -143,6 +152,9 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
|||||||
self.db.set_authors(id, new_authors, notify=False)
|
self.db.set_authors(id, new_authors, notify=False)
|
||||||
|
|
||||||
self.changed = True
|
self.changed = True
|
||||||
|
for w in getattr(self, 'custom_column_widgets', []):
|
||||||
|
w.commit(self.ids)
|
||||||
|
|
||||||
|
|
||||||
def series_changed(self):
|
def series_changed(self):
|
||||||
self.write_series = True
|
self.write_series = True
|
||||||
|
@ -258,9 +258,9 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
self.device_info = ' '
|
self.device_info = ' '
|
||||||
if not opts.no_update_check:
|
if not opts.no_update_check:
|
||||||
self.update_checker = CheckForUpdates(self)
|
self.update_checker = CheckForUpdates(self)
|
||||||
QObject.connect(self.update_checker,
|
self.update_checker.update_found.connect(self.update_found,
|
||||||
SIGNAL('update_found(PyQt_PyObject)'), self.update_found)
|
type=Qt.QueuedConnection)
|
||||||
self.update_checker.start(2000)
|
self.update_checker.start()
|
||||||
####################### Status Bar #####################
|
####################### Status Bar #####################
|
||||||
self.status_bar.initialize(self.system_tray_icon)
|
self.status_bar.initialize(self.system_tray_icon)
|
||||||
self.status_bar.show_book_info.connect(self.show_book_info)
|
self.status_bar.show_book_info.connect(self.show_book_info)
|
||||||
@ -2493,7 +2493,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
if write_settings:
|
if write_settings:
|
||||||
self.write_settings()
|
self.write_settings()
|
||||||
self.check_messages_timer.stop()
|
self.check_messages_timer.stop()
|
||||||
self.update_checker.stop()
|
self.update_checker.terminate()
|
||||||
self.listener.close()
|
self.listener.close()
|
||||||
self.job_manager.server.close()
|
self.job_manager.server.close()
|
||||||
while self.spare_servers:
|
while self.spare_servers:
|
||||||
|
@ -3,7 +3,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from PyQt4.QtCore import QObject, SIGNAL, QTimer
|
from PyQt4.QtCore import QThread, pyqtSignal
|
||||||
import mechanize
|
import mechanize
|
||||||
|
|
||||||
from calibre.constants import __version__, iswindows, isosx
|
from calibre.constants import __version__, iswindows, isosx
|
||||||
@ -12,31 +12,27 @@ from calibre.utils.config import prefs
|
|||||||
|
|
||||||
URL = 'http://status.calibre-ebook.com/latest'
|
URL = 'http://status.calibre-ebook.com/latest'
|
||||||
|
|
||||||
class CheckForUpdates(QObject):
|
class CheckForUpdates(QThread):
|
||||||
|
|
||||||
|
update_found = pyqtSignal(object)
|
||||||
|
INTERVAL = 24*60*60
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QObject.__init__(self, parent)
|
QThread.__init__(self, parent)
|
||||||
self.timer = QTimer(self)
|
|
||||||
self.first = True
|
|
||||||
self.connect(self.timer, SIGNAL('timeout()'), self)
|
|
||||||
self.start = self.timer.start
|
|
||||||
self.stop = self.timer.stop
|
|
||||||
|
|
||||||
def __call__(self):
|
def run(self):
|
||||||
if self.first:
|
while True:
|
||||||
self.timer.setInterval(1000*24*60*60)
|
try:
|
||||||
self.first = False
|
br = browser()
|
||||||
|
req = mechanize.Request(URL)
|
||||||
try:
|
req.add_header('CALIBRE_VERSION', __version__)
|
||||||
br = browser()
|
req.add_header('CALIBRE_OS',
|
||||||
req = mechanize.Request(URL)
|
'win' if iswindows else 'osx' if isosx else 'oth')
|
||||||
req.add_header('CALIBRE_VERSION', __version__)
|
req.add_header('CALIBRE_INSTALL_UUID', prefs['installation_uuid'])
|
||||||
req.add_header('CALIBRE_OS',
|
version = br.open(req).read().strip()
|
||||||
'win' if iswindows else 'osx' if isosx else 'oth')
|
if version and version != __version__:
|
||||||
req.add_header('CALIBRE_INSTALL_UUID', prefs['installation_uuid'])
|
self.update_found.emit(version)
|
||||||
version = br.open(req).read().strip()
|
except:
|
||||||
if version and version != __version__:
|
traceback.print_exc()
|
||||||
self.emit(SIGNAL('update_found(PyQt_PyObject)'), version)
|
self.sleep(self.INTERVAL)
|
||||||
except:
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user