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