home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_1218 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  24.4 KB  |  669 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __license__ = 'GPL v3'
  5. __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
  6. __docformat__ = 'restructuredtext en'
  7. import sys
  8. from functools import partial
  9. from PyQt4.Qt import QComboBox, QLabel, QSpinBox, QDoubleSpinBox, QDateEdit, QDate, QGroupBox, QVBoxLayout, QPlainTextEdit, QSizePolicy, QSpacerItem, QIcon, QCheckBox, QWidget, QHBoxLayout, SIGNAL, QPushButton
  10. from calibre.utils.date import qt_to_dt, now
  11. from calibre.gui2.widgets import TagsLineEdit, EnComboBox
  12. from calibre.gui2 import UNDEFINED_QDATE
  13. from calibre.utils.config import tweaks
  14.  
  15. class Base(object):
  16.     
  17.     def __init__(self, db, col_id, parent = None):
  18.         self.db = db
  19.         self.col_id = col_id
  20.         self.col_metadata = db.custom_column_num_map[col_id]
  21.         self.initial_val = None
  22.         self.setup_ui(parent)
  23.  
  24.     
  25.     def initialize(self, book_id):
  26.         val = self.db.get_custom(book_id, num = self.col_id, index_is_id = True)
  27.         self.initial_val = val
  28.         val = self.normalize_db_val(val)
  29.         self.setter(val)
  30.  
  31.     
  32.     def commit(self, book_id, notify = False):
  33.         val = self.getter()
  34.         val = self.normalize_ui_val(val)
  35.         if val != self.initial_val:
  36.             self.db.set_custom(book_id, val, num = self.col_id, notify = notify)
  37.         
  38.  
  39.     
  40.     def normalize_db_val(self, val):
  41.         return val
  42.  
  43.     
  44.     def normalize_ui_val(self, val):
  45.         return val
  46.  
  47.  
  48.  
  49. class Bool(Base):
  50.     
  51.     def setup_ui(self, parent):
  52.         self.widgets = [
  53.             QLabel('&' + self.col_metadata['name'] + ':', parent),
  54.             QComboBox(parent)]
  55.         w = self.widgets[1]
  56.         items = [
  57.             _('Yes'),
  58.             _('No'),
  59.             _('Undefined')]
  60.         icons = [
  61.             I('ok.svg'),
  62.             I('list_remove.svg'),
  63.             I('blank.svg')]
  64.         if tweaks['bool_custom_columns_are_tristate'] == 'no':
  65.             items = items[:-1]
  66.             icons = icons[:-1]
  67.         
  68.         for icon, text in zip(icons, items):
  69.             w.addItem(QIcon(icon), text)
  70.         
  71.  
  72.     
  73.     def setter(self, val):
  74.         val = {
  75.             None: 2,
  76.             False: 1,
  77.             True: 0 }[val]
  78.         if tweaks['bool_custom_columns_are_tristate'] == 'no' and val == 2:
  79.             val = 1
  80.         
  81.         self.widgets[1].setCurrentIndex(val)
  82.  
  83.     
  84.     def getter(self):
  85.         val = self.widgets[1].currentIndex()
  86.         return {
  87.             2: None,
  88.             1: False,
  89.             0: True }[val]
  90.  
  91.  
  92.  
  93. class Int(Base):
  94.     
  95.     def setup_ui(self, parent):
  96.         self.widgets = [
  97.             QLabel('&' + self.col_metadata['name'] + ':', parent),
  98.             QSpinBox(parent)]
  99.         w = self.widgets[1]
  100.         w.setRange(-100, sys.maxint)
  101.         w.setSpecialValueText(_('Undefined'))
  102.         w.setSingleStep(1)
  103.  
  104.     
  105.     def setter(self, val):
  106.         if val is None:
  107.             val = self.widgets[1].minimum()
  108.         else:
  109.             val = int(val)
  110.         self.widgets[1].setValue(val)
  111.  
  112.     
  113.     def getter(self):
  114.         val = self.widgets[1].value()
  115.         if val == self.widgets[1].minimum():
  116.             val = None
  117.         
  118.         return val
  119.  
  120.  
  121.  
  122. class Float(Int):
  123.     
  124.     def setup_ui(self, parent):
  125.         self.widgets = [
  126.             QLabel('&' + self.col_metadata['name'] + ':', parent),
  127.             QDoubleSpinBox(parent)]
  128.         w = self.widgets[1]
  129.         w.setRange(-100, float(sys.maxint))
  130.         w.setDecimals(2)
  131.         w.setSpecialValueText(_('Undefined'))
  132.         w.setSingleStep(1)
  133.  
  134.     
  135.     def setter(self, val):
  136.         if val is None:
  137.             val = self.widgets[1].minimum()
  138.         
  139.         self.widgets[1].setValue(val)
  140.  
  141.  
  142.  
  143. class Rating(Int):
  144.     
  145.     def setup_ui(self, parent):
  146.         Int.setup_ui(self, parent)
  147.         w = self.widgets[1]
  148.         w.setRange(0, 5)
  149.         w.setSuffix(' ' + _('star(s)'))
  150.         w.setSpecialValueText(_('Unrated'))
  151.  
  152.     
  153.     def setter(self, val):
  154.         if val is None:
  155.             val = 0
  156.         
  157.         self.widgets[1].setValue(int(round(val / 2)))
  158.  
  159.     
  160.     def getter(self):
  161.         val = self.widgets[1].value()
  162.         if val == 0:
  163.             val = None
  164.         else:
  165.             val *= 2
  166.         return val
  167.  
  168.  
  169.  
  170. class DateEdit(QDateEdit):
  171.     
  172.     def focusInEvent(self, x):
  173.         self.setSpecialValueText('')
  174.         QDateEdit.focusInEvent(self, x)
  175.  
  176.     
  177.     def focusOutEvent(self, x):
  178.         self.setSpecialValueText(_('Undefined'))
  179.         QDateEdit.focusOutEvent(self, x)
  180.  
  181.     
  182.     def set_to_today(self):
  183.         self.setDate(now())
  184.  
  185.  
  186.  
  187. class DateTime(Base):
  188.     
  189.     def setup_ui(self, parent):
  190.         cm = self.col_metadata
  191.         self.widgets = [
  192.             QLabel('&' + cm['name'] + ':', parent),
  193.             DateEdit(parent),
  194.             QLabel(''),
  195.             QPushButton(_("Set '%s' to today") % cm['name'], parent)]
  196.         w = self.widgets[1]
  197.         format = cm['display'].get('date_format', '')
  198.         if not format:
  199.             format = 'dd MMM yyyy'
  200.         
  201.         w.setDisplayFormat(format)
  202.         w.setCalendarPopup(True)
  203.         w.setMinimumDate(UNDEFINED_QDATE)
  204.         w.setSpecialValueText(_('Undefined'))
  205.         self.widgets[3].clicked.connect(w.set_to_today)
  206.  
  207.     
  208.     def setter(self, val):
  209.         if val is None:
  210.             val = self.widgets[1].minimumDate()
  211.         else:
  212.             val = QDate(val.year, val.month, val.day)
  213.         self.widgets[1].setDate(val)
  214.  
  215.     
  216.     def getter(self):
  217.         val = self.widgets[1].date()
  218.         if val == UNDEFINED_QDATE:
  219.             val = None
  220.         else:
  221.             val = qt_to_dt(val)
  222.         return val
  223.  
  224.  
  225.  
  226. class Comments(Base):
  227.     
  228.     def setup_ui(self, parent):
  229.         self._box = QGroupBox(parent)
  230.         self._box.setTitle('&' + self.col_metadata['name'])
  231.         self._layout = QVBoxLayout()
  232.         self._tb = QPlainTextEdit(self._box)
  233.         self._tb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
  234.         self._tb.setTabChangesFocus(True)
  235.         self._layout.addWidget(self._tb)
  236.         self._box.setLayout(self._layout)
  237.         self.widgets = [
  238.             self._box]
  239.  
  240.     
  241.     def setter(self, val):
  242.         if val is None:
  243.             val = ''
  244.         
  245.         self._tb.setPlainText(val)
  246.  
  247.     
  248.     def getter(self):
  249.         val = unicode(self._tb.toPlainText()).strip()
  250.         if not val:
  251.             val = None
  252.         
  253.         return val
  254.  
  255.  
  256.  
  257. class Text(Base):
  258.     
  259.     def setup_ui(self, parent):
  260.         values = self.all_values = list(self.db.all_custom(num = self.col_id))
  261.         values.sort(cmp = (lambda x, y: cmp(x.lower(), y.lower())))
  262.         if self.col_metadata['is_multiple']:
  263.             w = TagsLineEdit(parent, values)
  264.             w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
  265.         else:
  266.             w = EnComboBox(parent)
  267.             w.setSizeAdjustPolicy(w.AdjustToMinimumContentsLengthWithIcon)
  268.             w.setMinimumContentsLength(25)
  269.         self.widgets = [
  270.             QLabel('&' + self.col_metadata['name'] + ':', parent),
  271.             w]
  272.  
  273.     
  274.     def initialize(self, book_id):
  275.         val = self.db.get_custom(book_id, num = self.col_id, index_is_id = True)
  276.         self.initial_val = val
  277.         val = self.normalize_db_val(val)
  278.         if self.col_metadata['is_multiple']:
  279.             self.setter(val)
  280.             self.widgets[1].update_tags_cache(self.all_values)
  281.         else:
  282.             idx = None
  283.             for i, c in enumerate(self.all_values):
  284.                 if c == val:
  285.                     idx = i
  286.                 
  287.                 self.widgets[1].addItem(c)
  288.             
  289.             self.widgets[1].setEditText('')
  290.             if idx is not None:
  291.                 self.widgets[1].setCurrentIndex(idx)
  292.             
  293.  
  294.     
  295.     def setter(self, val):
  296.         if self.col_metadata['is_multiple']:
  297.             if not val:
  298.                 val = []
  299.             
  300.             self.widgets[1].setText(u', '.join(val))
  301.         
  302.  
  303.     
  304.     def getter(self):
  305.         if self.col_metadata['is_multiple']:
  306.             val = unicode(self.widgets[1].text()).strip()
  307.             ans = _[1]
  308.             return ans
  309.         val = unicode(self.widgets[1].currentText()).strip()
  310.         if not val:
  311.             val = None
  312.         
  313.         return val
  314.  
  315.  
  316.  
  317. class Series(Base):
  318.     
  319.     def setup_ui(self, parent):
  320.         values = self.all_values = list(self.db.all_custom(num = self.col_id))
  321.         values.sort(cmp = (lambda x, y: cmp(x.lower(), y.lower())))
  322.         w = EnComboBox(parent)
  323.         w.setSizeAdjustPolicy(w.AdjustToMinimumContentsLengthWithIcon)
  324.         w.setMinimumContentsLength(25)
  325.         self.name_widget = w
  326.         self.widgets = [
  327.             QLabel('&' + self.col_metadata['name'] + ':', parent),
  328.             w]
  329.         self.widgets.append(QLabel('&' + self.col_metadata['name'] + _(' index:'), parent))
  330.         w = QDoubleSpinBox(parent)
  331.         w.setRange(-100, float(sys.maxint))
  332.         w.setDecimals(2)
  333.         w.setSpecialValueText(_('Undefined'))
  334.         w.setSingleStep(1)
  335.         self.idx_widget = w
  336.         self.widgets.append(w)
  337.  
  338.     
  339.     def initialize(self, book_id):
  340.         val = self.db.get_custom(book_id, num = self.col_id, index_is_id = True)
  341.         s_index = self.db.get_custom_extra(book_id, num = self.col_id, index_is_id = True)
  342.         if s_index is None:
  343.             s_index = 0
  344.         
  345.         self.idx_widget.setValue(s_index)
  346.         self.initial_index = s_index
  347.         self.initial_val = val
  348.         val = self.normalize_db_val(val)
  349.         idx = None
  350.         for i, c in enumerate(self.all_values):
  351.             if c == val:
  352.                 idx = i
  353.             
  354.             self.name_widget.addItem(c)
  355.         
  356.         self.name_widget.setEditText('')
  357.         if idx is not None:
  358.             self.widgets[1].setCurrentIndex(idx)
  359.         
  360.  
  361.     
  362.     def commit(self, book_id, notify = False):
  363.         val = unicode(self.name_widget.currentText()).strip()
  364.         val = self.normalize_ui_val(val)
  365.         s_index = self.idx_widget.value()
  366.         if val != self.initial_val or s_index != self.initial_index:
  367.             if s_index == 0:
  368.                 if tweaks['series_index_auto_increment'] == 'next':
  369.                     s_index = self.db.get_next_cc_series_num_for(val, num = self.col_id)
  370.                 else:
  371.                     s_index = None
  372.             
  373.             self.db.set_custom(book_id, val, extra = s_index, num = self.col_id, notify = notify)
  374.         
  375.  
  376.  
  377. widgets = {
  378.     'bool': Bool,
  379.     'rating': Rating,
  380.     'int': Int,
  381.     'float': Float,
  382.     'datetime': DateTime,
  383.     'text': Text,
  384.     'comments': Comments,
  385.     'series': Series }
  386.  
  387. def field_sort(y, z, x = None):
  388.     m1 = x[y]
  389.     m2 = x[z]
  390.     n1 = None if m1['datatype'] == 'comments' else m1['name']
  391.     n2 = None if m2['datatype'] == 'comments' else m2['name']
  392.     return cmp(n1.lower(), n2.lower())
  393.  
  394.  
  395. def populate_metadata_page(layout, db, book_id, bulk = False, two_column = False, parent = None):
  396.     
  397.     def widget_factory(type, col):
  398.         if bulk:
  399.             w = bulk_widgets[type](db, col, parent)
  400.         else:
  401.             w = widgets[type](db, col, parent)
  402.         w.initialize(book_id)
  403.         return w
  404.  
  405.     x = db.custom_column_num_map
  406.     cols = list(x)
  407.     cols.sort(cmp = partial(field_sort, x = x))
  408.     count_non_comment = [](_[1])
  409.     layout.setColumnStretch(1, 10)
  410.     ans = []
  411.     for col in cols:
  412.         dt = x[col]['datatype']
  413.         w = widget_factory(dt, col)
  414.         ans.append(w)
  415.         for c in range(0, len(w.widgets), 2):
  416.             w.widgets[c].setBuddy(w.widgets[c + 1])
  417.             layout.addWidget(w.widgets[c], row, column)
  418.             layout.addWidget(w.widgets[c + 1], row, column + 1)
  419.             row += 1
  420.         
  421.         comments_row = max(comments_row, row)
  422.         if row >= turnover_point:
  423.             column += 2
  424.             turnover_point = count_non_comment + 1000
  425.             row = 0
  426.             continue
  427.         None if dt == 'comments' else (None, None, None, None) if two_column else len
  428.     
  429.     if not bulk:
  430.         row = comments_row
  431.         column = 0
  432.         for col in cols:
  433.             dt = x[col]['datatype']
  434.             if dt != 'comments':
  435.                 continue
  436.             
  437.             w = widget_factory(dt, col)
  438.             ans.append(w)
  439.             layout.addWidget(w.widgets[0], row, column, 1, 2)
  440.             if two_column and column == 0:
  441.                 column = 2
  442.                 continue
  443.             
  444.             column = 0
  445.             row += 1
  446.         
  447.     
  448.     items = []
  449.     if len(ans) > 0:
  450.         items.append(QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding))
  451.         layout.addItem(items[-1], layout.rowCount(), 0, 1, 1)
  452.         layout.setRowStretch(layout.rowCount() - 1, 100)
  453.     
  454.     return (ans, items)
  455.  
  456.  
  457. class BulkBase(Base):
  458.     
  459.     def get_initial_value(self, book_ids):
  460.         values = set([])
  461.         for book_id in book_ids:
  462.             val = self.db.get_custom(book_id, num = self.col_id, index_is_id = True)
  463.             if isinstance(val, list):
  464.                 val = frozenset(val)
  465.             
  466.             values.add(val)
  467.             if len(values) > 1:
  468.                 break
  469.                 continue
  470.         
  471.         ans = None
  472.         if len(values) == 1:
  473.             ans = iter(values).next()
  474.         
  475.         if isinstance(ans, frozenset):
  476.             ans = list(ans)
  477.         
  478.         return ans
  479.  
  480.     
  481.     def process_each_book(self):
  482.         return False
  483.  
  484.     
  485.     def initialize(self, book_ids):
  486.         if not self.process_each_book():
  487.             self.initial_val = val = self.get_initial_value(book_ids)
  488.             val = self.normalize_db_val(val)
  489.             self.setter(val)
  490.         
  491.  
  492.     
  493.     def commit(self, book_ids, notify = False):
  494.         if self.process_each_book():
  495.             for book_id in book_ids:
  496.                 val = self.db.get_custom(book_id, num = self.col_id, index_is_id = True)
  497.                 self.db.set_custom(book_id, self.getter(val), num = self.col_id, notify = notify)
  498.             
  499.         else:
  500.             val = self.getter()
  501.             val = self.normalize_ui_val(val)
  502.             if val != self.initial_val:
  503.                 for book_id in book_ids:
  504.                     self.db.set_custom(book_id, val, num = self.col_id, notify = notify)
  505.                 
  506.             
  507.  
  508.  
  509.  
  510. class BulkBool(BulkBase, Bool):
  511.     pass
  512.  
  513.  
  514. class BulkInt(BulkBase, Int):
  515.     pass
  516.  
  517.  
  518. class BulkFloat(BulkBase, Float):
  519.     pass
  520.  
  521.  
  522. class BulkRating(BulkBase, Rating):
  523.     pass
  524.  
  525.  
  526. class BulkDateTime(BulkBase, DateTime):
  527.     pass
  528.  
  529.  
  530. class BulkSeries(BulkBase):
  531.     
  532.     def setup_ui(self, parent):
  533.         values = self.all_values = list(self.db.all_custom(num = self.col_id))
  534.         values.sort(cmp = (lambda x, y: cmp(x.lower(), y.lower())))
  535.         w = EnComboBox(parent)
  536.         w.setSizeAdjustPolicy(w.AdjustToMinimumContentsLengthWithIcon)
  537.         w.setMinimumContentsLength(25)
  538.         self.name_widget = w
  539.         self.widgets = [
  540.             QLabel('&' + self.col_metadata['name'] + ':', parent),
  541.             w]
  542.         self.widgets.append(QLabel(_('Automatically number books in this series'), parent))
  543.         self.idx_widget = QCheckBox(parent)
  544.         self.widgets.append(self.idx_widget)
  545.  
  546.     
  547.     def initialize(self, book_id):
  548.         self.idx_widget.setChecked(False)
  549.         for c in self.all_values:
  550.             self.name_widget.addItem(c)
  551.         
  552.         self.name_widget.setEditText('')
  553.  
  554.     
  555.     def commit(self, book_ids, notify = False):
  556.         val = unicode(self.name_widget.currentText()).strip()
  557.         val = self.normalize_ui_val(val)
  558.         update_indices = self.idx_widget.checkState()
  559.         if val != '':
  560.             for book_id in book_ids:
  561.                 if update_indices:
  562.                     if tweaks['series_index_auto_increment'] == 'next':
  563.                         s_index = self.db.get_next_cc_series_num_for(val, num = self.col_id)
  564.                     else:
  565.                         s_index = 1
  566.                 else:
  567.                     s_index = self.db.get_custom_extra(book_id, num = self.col_id, index_is_id = True)
  568.                 self.db.set_custom(book_id, val, extra = s_index, num = self.col_id, notify = notify)
  569.             
  570.         
  571.  
  572.     
  573.     def process_each_book(self):
  574.         return True
  575.  
  576.  
  577.  
  578. class RemoveTags(QWidget):
  579.     
  580.     def __init__(self, parent, values):
  581.         QWidget.__init__(self, parent)
  582.         layout = QHBoxLayout()
  583.         layout.setSpacing(5)
  584.         layout.setContentsMargins(0, 0, 0, 0)
  585.         self.tags_box = TagsLineEdit(parent, values)
  586.         layout.addWidget(self.tags_box, stretch = 1)
  587.         self.checkbox = QCheckBox(_('Remove all tags'), parent)
  588.         layout.addWidget(self.checkbox)
  589.         self.setLayout(layout)
  590.         self.connect(self.checkbox, SIGNAL('stateChanged(int)'), self.box_touched)
  591.  
  592.     
  593.     def box_touched(self, state):
  594.         if state:
  595.             self.tags_box.setText('')
  596.             self.tags_box.setEnabled(False)
  597.         else:
  598.             self.tags_box.setEnabled(True)
  599.  
  600.  
  601.  
  602. class BulkText(BulkBase):
  603.     
  604.     def setup_ui(self, parent):
  605.         values = self.all_values = list(self.db.all_custom(num = self.col_id))
  606.         values.sort(cmp = (lambda x, y: cmp(x.lower(), y.lower())))
  607.         if self.col_metadata['is_multiple']:
  608.             w = TagsLineEdit(parent, values)
  609.             w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
  610.             self.widgets = [
  611.                 QLabel('&' + self.col_metadata['name'] + ': ' + _('tags to add'), parent),
  612.                 w]
  613.             self.adding_widget = w
  614.             w = RemoveTags(parent, values)
  615.             self.widgets.append(QLabel('&' + self.col_metadata['name'] + ': ' + _('tags to remove'), parent))
  616.             self.widgets.append(w)
  617.             self.removing_widget = w
  618.         else:
  619.             w = EnComboBox(parent)
  620.             w.setSizeAdjustPolicy(w.AdjustToMinimumContentsLengthWithIcon)
  621.             w.setMinimumContentsLength(25)
  622.             self.widgets = [
  623.                 QLabel('&' + self.col_metadata['name'] + ':', parent),
  624.                 w]
  625.  
  626.     
  627.     def initialize(self, book_ids):
  628.         if self.col_metadata['is_multiple']:
  629.             self.widgets[1].update_tags_cache(self.all_values)
  630.         else:
  631.             val = self.get_initial_value(book_ids)
  632.             self.initial_val = val = self.normalize_db_val(val)
  633.             idx = None
  634.             for i, c in enumerate(self.all_values):
  635.                 if c == val:
  636.                     idx = i
  637.                 
  638.                 self.widgets[1].addItem(c)
  639.             
  640.             self.widgets[1].setEditText('')
  641.             if idx is not None:
  642.                 self.widgets[1].setCurrentIndex(idx)
  643.             
  644.  
  645.     
  646.     def process_each_book(self):
  647.         return self.col_metadata['is_multiple']
  648.  
  649.     
  650.     def getter(self, original_value = None):
  651.         if self.col_metadata['is_multiple']:
  652.             [] |= []([ v.strip() for v in unicode(self.adding_widget.text()).split(',') ])
  653.             return ans
  654.         val = unicode(self.widgets[1].currentText()).strip()
  655.         if not val:
  656.             val = None
  657.         
  658.         return val
  659.  
  660.  
  661. bulk_widgets = {
  662.     'bool': BulkBool,
  663.     'rating': BulkRating,
  664.     'int': BulkInt,
  665.     'float': BulkFloat,
  666.     'datetime': BulkDateTime,
  667.     'text': BulkText,
  668.     'series': BulkSeries }
  669.