This commit is contained in:
Kovid Goyal 2010-05-09 10:15:50 -06:00
commit 8ecc6e94ed
6 changed files with 66 additions and 34 deletions

View File

@ -17,11 +17,12 @@ from calibre.utils.config import Config, ConfigProxy, dynamic, JSONConfig
from calibre.utils.localization import set_qt_translator from calibre.utils.localization import set_qt_translator
from calibre.ebooks.metadata.meta import get_metadata, metadata_from_formats from calibre.ebooks.metadata.meta import get_metadata, metadata_from_formats
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation
from calibre.utils.date import UNDEFINED_DATE
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) UNDEFINED_QDATE = QDate(UNDEFINED_DATE)
ALL_COLUMNS = ['title', 'authors', 'size', 'timestamp', 'rating', 'publisher', ALL_COLUMNS = ['title', 'authors', 'size', 'timestamp', 'rating', 'publisher',
'tags', 'series', 'pubdate'] 'tags', 'series', 'pubdate']

View File

@ -14,7 +14,7 @@ from PyQt4.Qt import QComboBox, QLabel, QSpinBox, QDoubleSpinBox, QDateEdit, \
from calibre.utils.date import qt_to_dt from calibre.utils.date import qt_to_dt
from calibre.gui2.widgets import TagsLineEdit, EnComboBox from calibre.gui2.widgets import TagsLineEdit, EnComboBox
from calibre.gui2 import UNDEFINED_DATE from calibre.gui2 import UNDEFINED_QDATE
from calibre.utils.config import tweaks from calibre.utils.config import tweaks
class Base(object): class Base(object):
@ -123,15 +123,23 @@ class Rating(Int):
val *= 2 val *= 2
return val return val
class DateEdit(QDateEdit):
def focusInEvent(self, x):
self.setSpecialValueText('')
def focusOutEvent(self, x):
self.setSpecialValueText(_('Undefined'))
class DateTime(Base): class DateTime(Base):
def setup_ui(self, parent): def setup_ui(self, parent):
self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent), self.widgets = [QLabel('&'+self.col_metadata['name']+':', parent),
QDateEdit(parent)] DateEdit(parent)]
w = self.widgets[1] w = self.widgets[1]
w.setDisplayFormat('dd MMM yyyy') w.setDisplayFormat('dd MMM yyyy')
w.setCalendarPopup(True) w.setCalendarPopup(True)
w.setMinimumDate(UNDEFINED_DATE) w.setMinimumDate(UNDEFINED_QDATE)
w.setSpecialValueText(_('Undefined')) w.setSpecialValueText(_('Undefined'))
def setter(self, val): def setter(self, val):
@ -143,7 +151,7 @@ class DateTime(Base):
def getter(self): def getter(self):
val = self.widgets[1].date() val = self.widgets[1].date()
if val == UNDEFINED_DATE: if val == UNDEFINED_QDATE:
val = None val = None
else: else:
val = qt_to_dt(val) val = qt_to_dt(val)
@ -373,16 +381,15 @@ class BulkText(BulkBase):
def getter(self, original_value = None): def getter(self, original_value = None):
if self.col_metadata['is_multiple']: if self.col_metadata['is_multiple']:
ans = original_value if self.removing_widget.text() == '*':
vals = [v.strip() for v in unicode(self.adding_widget.text()).split(',')] ans = set()
for t in vals: else:
if t not in ans: ans = set(original_value)
ans.append(t) ans -= set([v.strip() for v in
vals = [v.strip() for v in unicode(self.removing_widget.text()).split(',')] unicode(self.removing_widget.text()).split(',')])
for t in vals: ans |= set([v.strip() for v in
if t in ans: unicode(self.adding_widget.text()).split(',')])
ans.remove(t) return ans # returning a set instead of a list works, for now at least.
return ans
val = unicode(self.widgets[1].currentText()).strip() val = unicode(self.widgets[1].currentText()).strip()
if not val: if not val:
val = None val = None

View File

@ -127,6 +127,8 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
if col_type == 'datetime': if col_type == 'datetime':
if self.date_format_box.text(): if self.date_format_box.text():
date_format = {'date_format':unicode(self.date_format_box.text())} date_format = {'date_format':unicode(self.date_format_box.text())}
else:
date_format = {'date_format': None}
if not self.editing_col: if not self.editing_col:
self.parent.custcols[col] = { self.parent.custcols[col] = {
@ -150,7 +152,7 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
item.setText(col_heading) item.setText(col_heading)
self.parent.custcols[self.orig_column_name]['label'] = col self.parent.custcols[self.orig_column_name]['label'] = col
self.parent.custcols[self.orig_column_name]['name'] = col_heading self.parent.custcols[self.orig_column_name]['name'] = col_heading
self.parent.custcols[self.orig_column_name]['display'] = date_format self.parent.custcols[self.orig_column_name]['display'].update(date_format)
self.parent.custcols[self.orig_column_name]['*edited'] = True self.parent.custcols[self.orig_column_name]['*edited'] = True
self.parent.custcols[self.orig_column_name]['*must_restart'] = True self.parent.custcols[self.orig_column_name]['*must_restart'] = True
QDialog.accept(self) QDialog.accept(self)

View File

@ -19,13 +19,13 @@ from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, pyqtSignal, \
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, UNDEFINED_DATE from calibre.gui2 import NONE, TableView, config, error_dialog, UNDEFINED_QDATE
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
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile
from calibre.utils.config import tweaks from calibre.utils.config import tweaks
from calibre.utils.date import dt_factory, qt_to_dt, isoformat from calibre.utils.date import dt_factory, qt_to_dt, isoformat, now
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
@ -103,7 +103,7 @@ class DateDelegate(QStyledItemDelegate):
def displayText(self, val, locale): def displayText(self, val, locale):
d = val.toDate() d = val.toDate()
if d == UNDEFINED_DATE: if d == UNDEFINED_QDATE:
return '' return ''
return d.toString('dd MMM yyyy') return d.toString('dd MMM yyyy')
@ -113,7 +113,7 @@ 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(UNDEFINED_DATE) qde.setMinimumDate(UNDEFINED_QDATE)
qde.setSpecialValueText(_('Undefined')) qde.setSpecialValueText(_('Undefined'))
qde.setCalendarPopup(True) qde.setCalendarPopup(True)
return qde return qde
@ -122,14 +122,14 @@ class PubDateDelegate(QStyledItemDelegate):
def displayText(self, val, locale): def displayText(self, val, locale):
d = val.toDate() d = val.toDate()
if d == UNDEFINED_DATE: if d == UNDEFINED_QDATE:
return '' return ''
return d.toString('MMM yyyy') 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(UNDEFINED_DATE) qde.setMinimumDate(UNDEFINED_QDATE)
qde.setSpecialValueText(_('Undefined')) qde.setSpecialValueText(_('Undefined'))
qde.setCalendarPopup(True) qde.setCalendarPopup(True)
return qde return qde
@ -192,18 +192,33 @@ class CcDateDelegate(QStyledItemDelegate):
def displayText(self, val, locale): def displayText(self, val, locale):
d = val.toDate() d = val.toDate()
if d == UNDEFINED_DATE: if d == UNDEFINED_QDATE:
return '' return ''
return d.toString(self.format) return d.toString(self.format)
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(self.format) qde.setDisplayFormat(self.format)
qde.setMinimumDate(UNDEFINED_DATE) qde.setMinimumDate(UNDEFINED_QDATE)
qde.setSpecialValueText(_('Undefined')) qde.setSpecialValueText(_('Undefined'))
qde.setCalendarPopup(True) qde.setCalendarPopup(True)
return qde return qde
def setEditorData(self, editor, index):
m = index.model()
# db col is not named for the field, but for the table number. To get it,
# 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']]]
if val is None:
val = now()
editor.setDate(val)
def setModelData(self, editor, model, index):
val = editor.date()
if val == UNDEFINED_QDATE:
val = None
model.setData(index, QVariant(val), Qt.EditRole)
class CcTextDelegate(QStyledItemDelegate): class CcTextDelegate(QStyledItemDelegate):
''' '''
Delegate for text/int/float data. Delegate for text/int/float data.
@ -739,7 +754,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(UNDEFINED_DATE) return QVariant(UNDEFINED_QDATE)
def bool_type(r, idx=-1): def bool_type(r, idx=-1):
return None # displayed using a decorator return None # displayed using a decorator
@ -874,9 +889,12 @@ class BooksModel(QAbstractTableModel):
val = None val = None
elif typ == 'datetime': elif typ == 'datetime':
val = value.toDate() val = value.toDate()
if val.isNull() or not val.isValid(): if val.isNull():
return False val = None
val = qt_to_dt(val, as_utc=False) else:
if not val.isValid():
return False
val = qt_to_dt(val, as_utc=False)
self.db.set_custom(self.db.id(row), val, label=colhead, num=None, append=False, notify=True) self.db.set_custom(self.db.id(row), val, label=colhead, num=None, append=False, notify=True)
return True return True

View File

@ -14,7 +14,7 @@ from PyQt4.QtCore import QThread, QReadWriteLock
from PyQt4.QtGui import QImage from PyQt4.QtGui import QImage
from calibre.utils.config import tweaks from calibre.utils.config import tweaks
from calibre.utils.date import parse_date, now from calibre.utils.date import parse_date, now, UNDEFINED_DATE
from calibre.utils.search_query_parser import SearchQueryParser from calibre.utils.search_query_parser import SearchQueryParser
from calibre.utils.pyparsing import ParseException from calibre.utils.pyparsing import ParseException
@ -573,11 +573,13 @@ class ResultCache(SearchQueryParser):
except AttributeError: # Some entries may be None except AttributeError: # Some entries may be None
ans = cmp(self._data[x][loc], self._data[y][loc]) ans = cmp(self._data[x][loc], self._data[y][loc])
except TypeError: ## raised when a datetime is None except TypeError: ## raised when a datetime is None
if self._data[x][loc] is None: x = self._data[x][loc]
if self._data[y][loc] is None: if x is None:
return 0 # Both None. Return eq x = UNDEFINED_DATE
return 1 # x is None, y not. Return gt y = self._data[y][loc]
return -1 # x is not None and (therefore) y is. return lt if y is None:
y = UNDEFINED_DATE
return cmp(x, y)
if subsort and ans == 0: if subsort and ans == 0:
return cmp(self._data[x][11].lower(), self._data[y][11].lower()) return cmp(self._data[x][11].lower(), self._data[y][11].lower())
return ans return ans

View File

@ -40,6 +40,8 @@ parse_date_day_first = compute_locale_info_for_parse_date()
utc_tz = _utc_tz = tzutc() utc_tz = _utc_tz = tzutc()
local_tz = _local_tz = SafeLocalTimeZone() local_tz = _local_tz = SafeLocalTimeZone()
UNDEFINED_DATE = datetime(101,1,1, tzinfo=utc_tz)
def parse_date(date_string, assume_utc=False, as_utc=True, default=None): def parse_date(date_string, assume_utc=False, as_utc=True, default=None):
''' '''
Parse a date/time string into a timezone aware datetime object. The timezone Parse a date/time string into a timezone aware datetime object. The timezone