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
7f32c89948
@ -6,7 +6,7 @@ from threading import RLock
|
|||||||
|
|
||||||
from PyQt4.QtCore import QVariant, QFileInfo, QObject, SIGNAL, QBuffer, Qt, QSize, \
|
from PyQt4.QtCore import QVariant, QFileInfo, QObject, SIGNAL, QBuffer, Qt, QSize, \
|
||||||
QByteArray, QTranslator, QCoreApplication, QThread, \
|
QByteArray, QTranslator, QCoreApplication, QThread, \
|
||||||
QEvent, QTimer, pyqtSignal
|
QEvent, QTimer, pyqtSignal, QDate
|
||||||
from PyQt4.QtGui import QFileDialog, QMessageBox, QPixmap, QFileIconProvider, \
|
from PyQt4.QtGui import QFileDialog, QMessageBox, QPixmap, QFileIconProvider, \
|
||||||
QIcon, QTableView, QApplication, QDialog, QPushButton
|
QIcon, QTableView, QApplication, QDialog, QPushButton
|
||||||
|
|
||||||
@ -21,6 +21,7 @@ from calibre.ebooks.metadata import MetaInformation
|
|||||||
gprefs = JSONConfig('gui')
|
gprefs = JSONConfig('gui')
|
||||||
|
|
||||||
NONE = QVariant() #: Null value to return from the data function of item models
|
NONE = QVariant() #: Null value to return from the data function of item models
|
||||||
|
UNDEFINED_DATE = QDate(101,1,1)
|
||||||
|
|
||||||
ALL_COLUMNS = ['title', 'authors', 'size', 'timestamp', 'rating', 'publisher',
|
ALL_COLUMNS = ['title', 'authors', 'size', 'timestamp', 'rating', 'publisher',
|
||||||
'tags', 'series', 'pubdate']
|
'tags', 'series', 'pubdate']
|
||||||
|
270
src/calibre/gui2/custom_column_widgets.py
Normal file
270
src/calibre/gui2/custom_column_widgets.py
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from PyQt4.Qt import QComboBox, QLabel, QSpinBox, QDoubleSpinBox, QDateEdit, \
|
||||||
|
QDate, QGroupBox, QVBoxLayout, QPlainTextEdit, QSizePolicy, \
|
||||||
|
QSpacerItem, QIcon
|
||||||
|
|
||||||
|
from calibre.utils.date import qt_to_dt
|
||||||
|
from calibre.gui2.widgets import TagsLineEdit, EnComboBox
|
||||||
|
from calibre.gui2 import UNDEFINED_DATE
|
||||||
|
from calibre.utils.config import tweaks
|
||||||
|
|
||||||
|
class Base(object):
|
||||||
|
|
||||||
|
def __init__(self, db, col_id):
|
||||||
|
self.db, self.col_id = db, col_id
|
||||||
|
self.col_metadata = db.custom_column_num_map[col_id]
|
||||||
|
self.initial_val = None
|
||||||
|
|
||||||
|
def initialize(self, book_id):
|
||||||
|
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
||||||
|
self.initial_val = val
|
||||||
|
val = self.normalize_db_val(val)
|
||||||
|
self.setter(val)
|
||||||
|
|
||||||
|
def commit(self, book_id, notify=False):
|
||||||
|
val = self.getter()
|
||||||
|
val = self.normalize_ui_val(val)
|
||||||
|
if val != self.initial_val:
|
||||||
|
self.db.set_custom(book_id, val, num=self.col_id, notify=notify)
|
||||||
|
|
||||||
|
def normalize_db_val(self, val):
|
||||||
|
return val
|
||||||
|
|
||||||
|
def normalize_ui_val(self, val):
|
||||||
|
return val
|
||||||
|
|
||||||
|
class Bool(Base):
|
||||||
|
|
||||||
|
def __init__(self, db, col_id, parent=None):
|
||||||
|
Base.__init__(self, db, col_id)
|
||||||
|
self.widgets = [QLabel('&'+self.col_metadata['name'], parent),
|
||||||
|
QComboBox(parent)]
|
||||||
|
w = self.widgets[1]
|
||||||
|
items = [_('Yes'), _('No'), _('Undefined')]
|
||||||
|
icons = [I('ok.svg'), I('list_remove.svg'), I('blank.svg')]
|
||||||
|
if tweaks['bool_custom_columns_are_tristate'] == 'no':
|
||||||
|
items = items[:-1]
|
||||||
|
icons = icons[:-1]
|
||||||
|
for icon, text in zip(icons, items):
|
||||||
|
w.addItem(QIcon(icon), text)
|
||||||
|
|
||||||
|
|
||||||
|
def setter(self, val):
|
||||||
|
val = {None: 2, False: 1, True: 0}[val]
|
||||||
|
if tweaks['bool_custom_columns_are_tristate'] == 'no' and val == 2:
|
||||||
|
val = 1
|
||||||
|
self.widgets[1].setCurrentIndex(val)
|
||||||
|
|
||||||
|
def getter(self):
|
||||||
|
val = self.widgets[1].currentIndex()
|
||||||
|
return {2: None, 1: False, 0: True}[val]
|
||||||
|
|
||||||
|
class Int(Base):
|
||||||
|
|
||||||
|
def __init__(self, db, col_id, parent=None):
|
||||||
|
Base.__init__(self, db, col_id)
|
||||||
|
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
||||||
|
QSpinBox(parent)]
|
||||||
|
w = self.widgets[1]
|
||||||
|
w.setRange(-100, sys.maxint)
|
||||||
|
w.setSpecialValueText(_('Undefined'))
|
||||||
|
w.setSingleStep(1)
|
||||||
|
|
||||||
|
def setter(self, val):
|
||||||
|
if val is None:
|
||||||
|
val = self.widgets[1].minimum()
|
||||||
|
else:
|
||||||
|
val = int(val)
|
||||||
|
self.widgets[1].setValue(val)
|
||||||
|
|
||||||
|
def getter(self):
|
||||||
|
val = self.widgets[1].value()
|
||||||
|
if val == self.widgets[1].minimum():
|
||||||
|
val = None
|
||||||
|
return val
|
||||||
|
|
||||||
|
class Float(Int):
|
||||||
|
|
||||||
|
def __init__(self, db, col_id, parent=None):
|
||||||
|
Base.__init__(self, db, col_id)
|
||||||
|
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
||||||
|
QDoubleSpinBox(parent)]
|
||||||
|
w = self.widgets[1]
|
||||||
|
self.setRange(-100., float(sys.maxint))
|
||||||
|
w.setDecimals(2)
|
||||||
|
|
||||||
|
class Rating(Int):
|
||||||
|
|
||||||
|
def __init__(self, db, col_id, parent=None):
|
||||||
|
Int.__init__(self, db, col_id)
|
||||||
|
w = self.widgets[1]
|
||||||
|
w.setRange(0, 5)
|
||||||
|
w.setSuffix(' '+_('stars'))
|
||||||
|
w.setSpecialValueText(_('Unrated'))
|
||||||
|
|
||||||
|
def setter(self, val):
|
||||||
|
if val is None:
|
||||||
|
val = 0
|
||||||
|
self.widgets[1].setValue(int(round(val/2.)))
|
||||||
|
|
||||||
|
def getter(self):
|
||||||
|
val = self.widgets[1].value()
|
||||||
|
if val == 0:
|
||||||
|
val = None
|
||||||
|
else:
|
||||||
|
val *= 2
|
||||||
|
return val
|
||||||
|
|
||||||
|
class DateTime(Base):
|
||||||
|
|
||||||
|
def __init__(self, db, col_id, parent=None):
|
||||||
|
Base.__init__(self, db, col_id)
|
||||||
|
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
||||||
|
QDateEdit(parent)]
|
||||||
|
w = self.widgets[1]
|
||||||
|
w.setDisplayFormat('dd MMM yyyy')
|
||||||
|
w.setCalendarPopup(True)
|
||||||
|
w.setMinimumDate(UNDEFINED_DATE)
|
||||||
|
w.setSpecialValueText(_('Undefined'))
|
||||||
|
|
||||||
|
def setter(self, val):
|
||||||
|
if val is None:
|
||||||
|
val = self.widgets[1].minimumDate()
|
||||||
|
else:
|
||||||
|
val = QDate(val.year, val.month, val.day)
|
||||||
|
self.widgets[1].setDate(val)
|
||||||
|
|
||||||
|
def getter(self):
|
||||||
|
val = self.widgets[1].date()
|
||||||
|
if val == UNDEFINED_DATE:
|
||||||
|
val = None
|
||||||
|
else:
|
||||||
|
val = qt_to_dt(val)
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
class Comments(Base):
|
||||||
|
|
||||||
|
def __init__(self, db, col_id, parent=None):
|
||||||
|
Base.__init__(self, db, col_id)
|
||||||
|
self._box = QGroupBox(parent)
|
||||||
|
self._box.setTitle('&'+self.col_metadata['name'])
|
||||||
|
self._layout = QVBoxLayout()
|
||||||
|
self._tb = QPlainTextEdit(self._box)
|
||||||
|
self._tb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||||
|
self._layout.addWidget(self._tb)
|
||||||
|
self._box.setLayout(self._layout)
|
||||||
|
self.widgets = [self._box]
|
||||||
|
|
||||||
|
def setter(self, val):
|
||||||
|
if val is None:
|
||||||
|
val = ''
|
||||||
|
self._tb.setPlainText(val)
|
||||||
|
|
||||||
|
def getter(self):
|
||||||
|
val = unicode(self._tb.toPlainText()).strip()
|
||||||
|
if not val:
|
||||||
|
val = None
|
||||||
|
return val
|
||||||
|
|
||||||
|
class Text(Base):
|
||||||
|
|
||||||
|
def __init__(self, db, col_id, parent=None):
|
||||||
|
Base.__init__(self, db, 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()))
|
||||||
|
if self.col_metadata['is_multiple']:
|
||||||
|
w = TagsLineEdit(parent, values)
|
||||||
|
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
||||||
|
else:
|
||||||
|
w = EnComboBox(parent)
|
||||||
|
w.setSizeAdjustPolicy(w.AdjustToMinimumContentsLengthWithIcon)
|
||||||
|
w.setMinimumContentsLength(25)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
|
||||||
|
w]
|
||||||
|
|
||||||
|
def initialize(self, book_id):
|
||||||
|
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
||||||
|
self.initial_val = 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)
|
||||||
|
|
||||||
|
|
||||||
|
def setter(self, val):
|
||||||
|
if self.col_metadata['is_multiple']:
|
||||||
|
if not val:
|
||||||
|
val = []
|
||||||
|
self.widgets[1].setText(u', '.join(val))
|
||||||
|
|
||||||
|
def getter(self):
|
||||||
|
if self.col_metadata['is_multiple']:
|
||||||
|
val = unicode(self.widgets[1].text()).strip()
|
||||||
|
return [x.strip() for x in val.split(',')]
|
||||||
|
val = unicode(self.widgets[1].currentText()).strip()
|
||||||
|
if not val:
|
||||||
|
val = None
|
||||||
|
return val
|
||||||
|
|
||||||
|
widgets = {
|
||||||
|
'bool' : Bool,
|
||||||
|
'rating' : Rating,
|
||||||
|
'int': Int,
|
||||||
|
'float': Float,
|
||||||
|
'datetime': DateTime,
|
||||||
|
'text' : Text,
|
||||||
|
'comments': Comments,
|
||||||
|
}
|
||||||
|
|
||||||
|
def populate_single_metadata_page(left, right, db, book_id, parent=None):
|
||||||
|
x = db.custom_column_num_map
|
||||||
|
cols = list(x)
|
||||||
|
cols.sort(cmp=lambda z,y: cmp(x[z]['name'].lower(), x[y]['name'].lower()))
|
||||||
|
ans = []
|
||||||
|
for i, col in enumerate(cols):
|
||||||
|
w = widgets[x[col]['datatype']](db, col, parent)
|
||||||
|
ans.append(w)
|
||||||
|
w.initialize(book_id)
|
||||||
|
layout = left if i%2 == 0 else right
|
||||||
|
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))
|
||||||
|
left.addItem(items[-1], left.rowCount(), 0, 1, 1)
|
||||||
|
left.setRowStretch(left.rowCount()-1, 100)
|
||||||
|
if len(ans) > 1:
|
||||||
|
items.append(QSpacerItem(10, 100, QSizePolicy.Minimum,
|
||||||
|
QSizePolicy.Expanding))
|
||||||
|
right.addItem(items[-1], left.rowCount(), 0, 1, 1)
|
||||||
|
right.setRowStretch(right.rowCount()-1, 100)
|
||||||
|
|
||||||
|
return ans, items
|
||||||
|
|
@ -11,8 +11,9 @@ import re
|
|||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
import sip
|
||||||
from PyQt4.Qt import SIGNAL, QObject, QCoreApplication, Qt, QTimer, QThread, QDate, \
|
from PyQt4.Qt import SIGNAL, QObject, QCoreApplication, Qt, QTimer, QThread, QDate, \
|
||||||
QPixmap, QListWidgetItem, QDialog
|
QPixmap, QListWidgetItem, QDialog, QHBoxLayout, QGridLayout
|
||||||
|
|
||||||
from calibre.gui2 import error_dialog, file_icon_provider, \
|
from calibre.gui2 import error_dialog, file_icon_provider, \
|
||||||
choose_files, choose_images, ResizableDialog, \
|
choose_files, choose_images, ResizableDialog, \
|
||||||
@ -31,6 +32,7 @@ from calibre.utils.config import prefs, tweaks
|
|||||||
from calibre.utils.date import qt_to_dt
|
from calibre.utils.date import qt_to_dt
|
||||||
from calibre.customize.ui import run_plugins_on_import, get_isbndb_key
|
from calibre.customize.ui import run_plugins_on_import, get_isbndb_key
|
||||||
from calibre.gui2.dialogs.config.social import SocialMetadata
|
from calibre.gui2.dialogs.config.social import SocialMetadata
|
||||||
|
from calibre.gui2.custom_column_widgets import populate_single_metadata_page
|
||||||
|
|
||||||
class CoverFetcher(QThread):
|
class CoverFetcher(QThread):
|
||||||
|
|
||||||
@ -405,6 +407,26 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
self.cover.setPixmap(pm)
|
self.cover.setPixmap(pm)
|
||||||
self.cover_data = cover
|
self.cover_data = cover
|
||||||
self.original_series_name = unicode(self.series.text()).strip()
|
self.original_series_name = unicode(self.series.text()).strip()
|
||||||
|
if len(db.custom_column_label_map) == 0:
|
||||||
|
self.central_widget.tabBar().setVisible(False)
|
||||||
|
else:
|
||||||
|
self.create_custom_column_editors()
|
||||||
|
|
||||||
|
def create_custom_column_editors(self):
|
||||||
|
w = self.central_widget.widget(1)
|
||||||
|
top_layout = QHBoxLayout()
|
||||||
|
top_layout.setSpacing(20)
|
||||||
|
left_layout = QGridLayout()
|
||||||
|
right_layout = QGridLayout()
|
||||||
|
top_layout.addLayout(left_layout)
|
||||||
|
|
||||||
|
self.custom_column_widgets, self.__cc_spacers = populate_single_metadata_page(
|
||||||
|
left_layout, right_layout, self.db, self.id, w)
|
||||||
|
top_layout.addLayout(right_layout)
|
||||||
|
sip.delete(w.layout())
|
||||||
|
w.setLayout(top_layout)
|
||||||
|
self.__custom_col_layouts = [top_layout, left_layout, right_layout]
|
||||||
|
|
||||||
|
|
||||||
def validate_isbn(self, isbn):
|
def validate_isbn(self, isbn):
|
||||||
isbn = unicode(isbn).strip()
|
isbn = unicode(isbn).strip()
|
||||||
@ -675,6 +697,8 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
self.db.set_cover(self.id, self.cover_data)
|
self.db.set_cover(self.id, self.cover_data)
|
||||||
else:
|
else:
|
||||||
self.db.remove_cover(self.id)
|
self.db.remove_cover(self.id)
|
||||||
|
for w in getattr(self, 'custom_column_widgets', []):
|
||||||
|
w.commit(self.id)
|
||||||
except IOError, err:
|
except IOError, err:
|
||||||
if err.errno == 13: # Permission denied
|
if err.errno == 13: # Permission denied
|
||||||
fname = err.filename if err.filename else 'file'
|
fname = err.filename if err.filename else 'file'
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,14 +12,14 @@ from PyQt4.QtGui import QTableView, QAbstractItemView, QColor, \
|
|||||||
QPen, QStyle, QPainter, QStyleOptionViewItemV4, \
|
QPen, QStyle, QPainter, QStyleOptionViewItemV4, \
|
||||||
QIcon, QImage, QMenu, \
|
QIcon, QImage, QMenu, \
|
||||||
QStyledItemDelegate, QCompleter, QIntValidator, \
|
QStyledItemDelegate, QCompleter, QIntValidator, \
|
||||||
QDoubleValidator, QCheckBox
|
QDoubleValidator, QComboBox
|
||||||
from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, pyqtSignal, \
|
from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, pyqtSignal, \
|
||||||
SIGNAL, QObject, QSize, QModelIndex, QDate
|
SIGNAL, QObject, QSize, QModelIndex, QDate
|
||||||
|
|
||||||
from calibre import strftime
|
from calibre import strftime
|
||||||
from calibre.ebooks.metadata import string_to_authors, fmt_sidx, authors_to_string
|
from calibre.ebooks.metadata import string_to_authors, fmt_sidx, authors_to_string
|
||||||
from calibre.ebooks.metadata.meta import set_metadata as _set_metadata
|
from calibre.ebooks.metadata.meta import set_metadata as _set_metadata
|
||||||
from calibre.gui2 import NONE, TableView, config, error_dialog
|
from calibre.gui2 import NONE, TableView, config, error_dialog, UNDEFINED_DATE
|
||||||
from calibre.gui2.dialogs.comments_dialog import CommentsDialog
|
from calibre.gui2.dialogs.comments_dialog import CommentsDialog
|
||||||
from calibre.gui2.widgets import EnLineEdit, TagsLineEdit
|
from calibre.gui2.widgets import EnLineEdit, TagsLineEdit
|
||||||
from calibre.library.caches import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH
|
from calibre.library.caches import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH
|
||||||
@ -29,6 +29,7 @@ from calibre.utils.date import dt_factory, qt_to_dt, isoformat
|
|||||||
from calibre.utils.pyparsing import ParseException
|
from calibre.utils.pyparsing import ParseException
|
||||||
from calibre.utils.search_query_parser import SearchQueryParser
|
from calibre.utils.search_query_parser import SearchQueryParser
|
||||||
|
|
||||||
|
|
||||||
class RatingDelegate(QStyledItemDelegate):
|
class RatingDelegate(QStyledItemDelegate):
|
||||||
COLOR = QColor("blue")
|
COLOR = QColor("blue")
|
||||||
SIZE = 16
|
SIZE = 16
|
||||||
@ -79,14 +80,14 @@ class RatingDelegate(QStyledItemDelegate):
|
|||||||
painter.setRenderHint(QPainter.Antialiasing)
|
painter.setRenderHint(QPainter.Antialiasing)
|
||||||
painter.setClipRect(option.rect)
|
painter.setClipRect(option.rect)
|
||||||
y = option.rect.center().y()-self.SIZE/2.
|
y = option.rect.center().y()-self.SIZE/2.
|
||||||
x = option.rect.right() - self.SIZE
|
x = option.rect.left()
|
||||||
painter.setPen(self.PEN)
|
painter.setPen(self.PEN)
|
||||||
painter.setBrush(self.brush)
|
painter.setBrush(self.brush)
|
||||||
painter.translate(x, y)
|
painter.translate(x, y)
|
||||||
i = 0
|
i = 0
|
||||||
while i < num:
|
while i < num:
|
||||||
draw_star()
|
draw_star()
|
||||||
painter.translate(-self.SIZE, 0)
|
painter.translate(self.SIZE, 0)
|
||||||
i += 1
|
i += 1
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
@ -99,8 +100,11 @@ class RatingDelegate(QStyledItemDelegate):
|
|||||||
return sb
|
return sb
|
||||||
|
|
||||||
class DateDelegate(QStyledItemDelegate):
|
class DateDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
def displayText(self, val, locale):
|
def displayText(self, val, locale):
|
||||||
d = val.toDate()
|
d = val.toDate()
|
||||||
|
if d == UNDEFINED_DATE:
|
||||||
|
return ''
|
||||||
return d.toString('dd MMM yyyy')
|
return d.toString('dd MMM yyyy')
|
||||||
|
|
||||||
def createEditor(self, parent, option, index):
|
def createEditor(self, parent, option, index):
|
||||||
@ -109,18 +113,24 @@ class DateDelegate(QStyledItemDelegate):
|
|||||||
if 'yyyy' not in stdformat:
|
if 'yyyy' not in stdformat:
|
||||||
stdformat = stdformat.replace('yy', 'yyyy')
|
stdformat = stdformat.replace('yy', 'yyyy')
|
||||||
qde.setDisplayFormat(stdformat)
|
qde.setDisplayFormat(stdformat)
|
||||||
qde.setMinimumDate(QDate(101,1,1))
|
qde.setMinimumDate(UNDEFINED_DATE)
|
||||||
|
qde.setSpecialValueText(_('Undefined'))
|
||||||
qde.setCalendarPopup(True)
|
qde.setCalendarPopup(True)
|
||||||
return qde
|
return qde
|
||||||
|
|
||||||
class PubDateDelegate(QStyledItemDelegate):
|
class PubDateDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
def displayText(self, val, locale):
|
def displayText(self, val, locale):
|
||||||
return val.toDate().toString('MMM yyyy')
|
d = val.toDate()
|
||||||
|
if d == UNDEFINED_DATE:
|
||||||
|
return ''
|
||||||
|
return d.toString('MMM yyyy')
|
||||||
|
|
||||||
def createEditor(self, parent, option, index):
|
def createEditor(self, parent, option, index):
|
||||||
qde = QStyledItemDelegate.createEditor(self, parent, option, index)
|
qde = QStyledItemDelegate.createEditor(self, parent, option, index)
|
||||||
qde.setDisplayFormat('MM yyyy')
|
qde.setDisplayFormat('MM yyyy')
|
||||||
qde.setMinimumDate(QDate(101,1,1))
|
qde.setMinimumDate(UNDEFINED_DATE)
|
||||||
|
qde.setSpecialValueText(_('Undefined'))
|
||||||
qde.setCalendarPopup(True)
|
qde.setCalendarPopup(True)
|
||||||
return qde
|
return qde
|
||||||
|
|
||||||
@ -217,16 +227,19 @@ class CcBoolDelegate(QStyledItemDelegate):
|
|||||||
QStyledItemDelegate.__init__(self, parent)
|
QStyledItemDelegate.__init__(self, parent)
|
||||||
|
|
||||||
def createEditor(self, parent, option, index):
|
def createEditor(self, parent, option, index):
|
||||||
editor = QCheckBox(parent)
|
editor = QComboBox(parent)
|
||||||
|
items = [_('Y'), _('N'), ' ']
|
||||||
|
icons = [I('ok.svg'), I('list_remove.svg'), I('blank.svg')]
|
||||||
if tweaks['bool_custom_columns_are_tristate'] == 'no':
|
if tweaks['bool_custom_columns_are_tristate'] == 'no':
|
||||||
pass
|
items = items[:-1]
|
||||||
else:
|
icons = icons[:-1]
|
||||||
if tweaks['bool_custom_columns_are_tristate'] == 'yes':
|
for icon, text in zip(icons, items):
|
||||||
editor.setTristate(True)
|
editor.addItem(QIcon(icon), text)
|
||||||
return editor
|
return editor
|
||||||
|
|
||||||
def setModelData(self, editor, model, index):
|
def setModelData(self, editor, model, index):
|
||||||
model.setData(index, QVariant(editor.checkState()), Qt.EditRole)
|
val = {0:True, 1:False, 2:None}[editor.currentIndex()]
|
||||||
|
model.setData(index, QVariant(val), Qt.EditRole)
|
||||||
|
|
||||||
def setEditorData(self, editor, index):
|
def setEditorData(self, editor, index):
|
||||||
m = index.model()
|
m = index.model()
|
||||||
@ -234,10 +247,10 @@ class CcBoolDelegate(QStyledItemDelegate):
|
|||||||
# gui column -> column label -> table number -> db column
|
# gui column -> column label -> table number -> db column
|
||||||
val = m.db.data[index.row()][m.db.FIELD_MAP[m.custom_columns[m.column_map[index.column()]]['num']]]
|
val = m.db.data[index.row()][m.db.FIELD_MAP[m.custom_columns[m.column_map[index.column()]]['num']]]
|
||||||
if tweaks['bool_custom_columns_are_tristate'] == 'no':
|
if tweaks['bool_custom_columns_are_tristate'] == 'no':
|
||||||
val = Qt.Unchecked if val is None or not val else Qt.Checked
|
val = 1 if not val else 0
|
||||||
else:
|
else:
|
||||||
val = Qt.PartiallyChecked if val is None else Qt.Unchecked if not val else Qt.Checked
|
val = 2 if val is None else 1 if not val else 0
|
||||||
editor.setCheckState(val)
|
editor.setCurrentIndex(val)
|
||||||
|
|
||||||
class BooksModel(QAbstractTableModel):
|
class BooksModel(QAbstractTableModel):
|
||||||
|
|
||||||
@ -693,7 +706,7 @@ class BooksModel(QAbstractTableModel):
|
|||||||
if val is not None:
|
if val is not None:
|
||||||
return QVariant(QDate(val))
|
return QVariant(QDate(val))
|
||||||
else:
|
else:
|
||||||
return QVariant(QDate())
|
return QVariant(UNDEFINED_DATE)
|
||||||
|
|
||||||
def bool_type(r, idx=-1):
|
def bool_type(r, idx=-1):
|
||||||
return None # displayed using a decorator
|
return None # displayed using a decorator
|
||||||
@ -817,8 +830,7 @@ class BooksModel(QAbstractTableModel):
|
|||||||
val = unicode(value.toString()).strip()
|
val = unicode(value.toString()).strip()
|
||||||
val = val if val else None
|
val = val if val else None
|
||||||
if typ == 'bool':
|
if typ == 'bool':
|
||||||
val = value.toInt()[0] # tristate checkboxes put unknown in the middle
|
val = value.toPyObject()
|
||||||
val = None if val == 1 else False if val == 0 else True
|
|
||||||
elif typ == 'rating':
|
elif typ == 'rating':
|
||||||
val = value.toInt()[0]
|
val = value.toInt()[0]
|
||||||
val = 0 if val < 0 else 5 if val > 5 else val
|
val = 0 if val < 0 else 5 if val > 5 else val
|
||||||
|
@ -160,7 +160,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="restriction_label">
|
<widget class="QLabel" name="restriction_label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Restrict display to:</string>
|
<string>&Restrict to:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>search_restriction</cstring>
|
<cstring>search_restriction</cstring>
|
||||||
@ -353,13 +353,11 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="popularity">
|
<widget class="QCheckBox" name="popularity">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Sort by &popularity</string>
|
<string>Sort by &popularity</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="tag_match">
|
<widget class="QComboBox" name="tag_match">
|
||||||
@ -379,7 +377,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="edit_categories">
|
<widget class="QPushButton" name="edit_categories">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Create, edit, and delete user categories</string>
|
<string>Create, edit, and delete user categories</string>
|
||||||
@ -388,7 +385,6 @@
|
|||||||
<string>Manage &user categories</string>
|
<string>Manage &user categories</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -73,7 +73,7 @@ class SearchBox2(QComboBox):
|
|||||||
self.setInsertPolicy(self.NoInsert)
|
self.setInsertPolicy(self.NoInsert)
|
||||||
self.setMaxCount(self.MAX_COUNT)
|
self.setMaxCount(self.MAX_COUNT)
|
||||||
self.setSizeAdjustPolicy(self.AdjustToMinimumContentsLengthWithIcon)
|
self.setSizeAdjustPolicy(self.AdjustToMinimumContentsLengthWithIcon)
|
||||||
self.setMinimumContentsLength(50)
|
self.setMinimumContentsLength(25)
|
||||||
|
|
||||||
def initialize(self, opt_name, colorize=False,
|
def initialize(self, opt_name, colorize=False,
|
||||||
help_text=_('Search')):
|
help_text=_('Search')):
|
||||||
@ -306,4 +306,4 @@ class SavedSearchBox(QComboBox):
|
|||||||
idx = self.currentIndex();
|
idx = self.currentIndex();
|
||||||
if idx < 0:
|
if idx < 0:
|
||||||
return
|
return
|
||||||
self.search_box.set_search_string(self.saved_searches.lookup(unicode(self.currentText())))
|
self.search_box.set_search_string(self.saved_searches.lookup(unicode(self.currentText())))
|
||||||
|
@ -530,7 +530,7 @@ class BasicList(QListWidget):
|
|||||||
class LineEditECM(object):
|
class LineEditECM(object):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Extend the contenxt menu of a QLineEdit to include more actions.
|
Extend the context menu of a QLineEdit to include more actions.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def contextMenuEvent(self, event):
|
def contextMenuEvent(self, event):
|
||||||
@ -659,7 +659,7 @@ class EnComboBox(QComboBox):
|
|||||||
'''
|
'''
|
||||||
Enhanced QComboBox.
|
Enhanced QComboBox.
|
||||||
|
|
||||||
Includes an extended content menu.
|
Includes an extended context menu.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user