mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
commit
8ecc6e94ed
@ -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']
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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,7 +889,10 @@ 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():
|
||||||
|
val = None
|
||||||
|
else:
|
||||||
|
if not val.isValid():
|
||||||
return False
|
return False
|
||||||
val = qt_to_dt(val, as_utc=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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user