mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Merge from custcol trunk
This commit is contained in:
commit
eda505f755
@ -4,6 +4,7 @@ __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from itertools import izip
|
from itertools import izip
|
||||||
|
from xml.sax.saxutils import escape
|
||||||
|
|
||||||
from calibre.customize import Plugin as _Plugin
|
from calibre.customize import Plugin as _Plugin
|
||||||
|
|
||||||
@ -238,7 +239,7 @@ class OutputProfile(Plugin):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tags_to_string(cls, tags):
|
def tags_to_string(cls, tags):
|
||||||
return ', '.join(tags)
|
return escape(', '.join(tags))
|
||||||
|
|
||||||
class iPadOutput(OutputProfile):
|
class iPadOutput(OutputProfile):
|
||||||
|
|
||||||
@ -383,7 +384,8 @@ class KindleOutput(OutputProfile):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tags_to_string(cls, tags):
|
def tags_to_string(cls, tags):
|
||||||
return 'ttt '.join(tags)+'ttt '
|
return u'%s <br/><span style="color: white">%s</span>' % (', '.join(tags),
|
||||||
|
'ttt '.join(tags)+'ttt ')
|
||||||
|
|
||||||
class KindleDXOutput(OutputProfile):
|
class KindleDXOutput(OutputProfile):
|
||||||
|
|
||||||
@ -399,7 +401,8 @@ class KindleDXOutput(OutputProfile):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tags_to_string(cls, tags):
|
def tags_to_string(cls, tags):
|
||||||
return 'ttt '.join(tags)+'ttt '
|
return u'%s <br/><span style="color: white">%s</span>' % (', '.join(tags),
|
||||||
|
'ttt '.join(tags)+'ttt ')
|
||||||
|
|
||||||
class IlliadOutput(OutputProfile):
|
class IlliadOutput(OutputProfile):
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import threading, Queue
|
|||||||
|
|
||||||
|
|
||||||
class DeviceManager(object):
|
class DeviceManager(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.devices = []
|
self.devices = []
|
||||||
self.device_jobs = Queue(0)
|
self.device_jobs = Queue(0)
|
||||||
@ -21,19 +21,19 @@ class Job(object):
|
|||||||
def __init__(self, func, args):
|
def __init__(self, func, args):
|
||||||
self.completed = False
|
self.completed = False
|
||||||
self.exception = None
|
self.exception = None
|
||||||
|
|
||||||
|
|
||||||
class Worker(threading.Thread):
|
class Worker(threading.Thread):
|
||||||
|
|
||||||
def __init__(self, jobs):
|
def __init__(self, jobs):
|
||||||
self.jobs = jobs
|
self.jobs = jobs
|
||||||
self.results = []
|
self.results = []
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.setDaemon(True)
|
self.setDaemon(True)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
'''Thread loops taking jobs from the queue as they become available'''
|
'''Thread loops taking jobs from the queue as they become available'''
|
||||||
while True:
|
while True:
|
||||||
job = self.jobs.get(True, None)
|
self.jobs.get(True, None)
|
||||||
# Do job
|
# Do job
|
||||||
self.jobs.task_done()
|
self.jobs.task_done()
|
||||||
|
@ -99,7 +99,7 @@ class Jacket(object):
|
|||||||
except:
|
except:
|
||||||
tags = []
|
tags = []
|
||||||
if tags:
|
if tags:
|
||||||
tags = '<b>Tags: </b>' + escape(self.opts.dest.tags_to_string(tags))
|
tags = '<b>Tags: </b>' + self.opts.dest.tags_to_string(tags)
|
||||||
else:
|
else:
|
||||||
tags = ''
|
tags = ''
|
||||||
try:
|
try:
|
||||||
|
@ -354,7 +354,6 @@ if another paragraph_def is found, the state changes to collect_tokens.
|
|||||||
def __tab_stop_func(self, line):
|
def __tab_stop_func(self, line):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
type = 'tabs-%s' % self.__tab_type
|
|
||||||
self.__att_val_dict['tabs'] += '%s:' % self.__tab_type
|
self.__att_val_dict['tabs'] += '%s:' % self.__tab_type
|
||||||
self.__att_val_dict['tabs'] += '%s;' % line[20:-1]
|
self.__att_val_dict['tabs'] += '%s;' % line[20:-1]
|
||||||
self.__tab_type = 'left'
|
self.__tab_type = 'left'
|
||||||
@ -373,7 +372,6 @@ if another paragraph_def is found, the state changes to collect_tokens.
|
|||||||
"""
|
"""
|
||||||
leader = self.__tab_type_dict.get(self.__token_info)
|
leader = self.__tab_type_dict.get(self.__token_info)
|
||||||
if leader != None:
|
if leader != None:
|
||||||
type = 'tabs-%s' % self.__tab_type
|
|
||||||
self.__att_val_dict['tabs'] += '%s^' % leader
|
self.__att_val_dict['tabs'] += '%s^' % leader
|
||||||
else:
|
else:
|
||||||
if self.__run_level > 3:
|
if self.__run_level > 3:
|
||||||
|
@ -318,7 +318,6 @@ class Styles:
|
|||||||
Try to add the number to dictionary entry tabs-left, or tabs-right, etc.
|
Try to add the number to dictionary entry tabs-left, or tabs-right, etc.
|
||||||
If the dictionary entry doesn't exist, create one.
|
If the dictionary entry doesn't exist, create one.
|
||||||
"""
|
"""
|
||||||
type = 'tabs-%s' % self.__tab_type
|
|
||||||
try:
|
try:
|
||||||
if self.__leader_found:
|
if self.__leader_found:
|
||||||
self.__styles_dict['par'][self.__styles_num]['tabs']\
|
self.__styles_dict['par'][self.__styles_num]['tabs']\
|
||||||
@ -362,7 +361,6 @@ class Styles:
|
|||||||
leader = self.__tab_type_dict.get(self.__token_info)
|
leader = self.__tab_type_dict.get(self.__token_info)
|
||||||
if leader != None:
|
if leader != None:
|
||||||
leader += '^'
|
leader += '^'
|
||||||
type = 'tabs-%s' % self.__tab_type
|
|
||||||
try:
|
try:
|
||||||
self.__styles_dict['par'][self.__styles_num]['tabs'] += ':%s;' % leader
|
self.__styles_dict['par'][self.__styles_num]['tabs'] += ':%s;' % leader
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
__license__ = 'GPL v3'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__docformat__ = 'restructuredtext en'
|
||||||
__docformat__ = 'restructuredtext en'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
from PyQt4.Qt import QDialog
|
from PyQt4.Qt import QDialog
|
||||||
from calibre.gui2 import ResizableDialog
|
from calibre.gui2.dialogs.comments_dialog_ui import Ui_CommentsDialog
|
||||||
from calibre.gui2.dialogs.comments_dialog_ui import Ui_CommentsDialog
|
|
||||||
|
class CommentsDialog(QDialog, Ui_CommentsDialog):
|
||||||
class CommentsDialog(QDialog, Ui_CommentsDialog):
|
def __init__(self, parent, text):
|
||||||
def __init__(self, parent, text):
|
QDialog.__init__(self, parent)
|
||||||
QDialog.__init__(self, parent)
|
Ui_CommentsDialog.__init__(self)
|
||||||
Ui_CommentsDialog.__init__(self)
|
self.setupUi(self)
|
||||||
self.setupUi(self)
|
if text is not None:
|
||||||
if text is not None:
|
self.textbox.setPlainText(text)
|
||||||
self.textbox.setPlainText(text)
|
self.textbox.setTabChangesFocus(True)
|
||||||
self.textbox.setTabChangesFocus(True)
|
|
||||||
|
@ -1,83 +1,83 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>CommentsDialog</class>
|
<class>CommentsDialog</class>
|
||||||
<widget class="QDialog" name="CommentsDialog">
|
<widget class="QDialog" name="CommentsDialog">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>336</width>
|
<width>336</width>
|
||||||
<height>235</height>
|
<height>235</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Edit Comments</string>
|
<string>Edit Comments</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="verticalLayoutWidget">
|
<widget class="QWidget" name="verticalLayoutWidget">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>10</x>
|
<x>10</x>
|
||||||
<y>10</y>
|
<y>10</y>
|
||||||
<width>311</width>
|
<width>311</width>
|
||||||
<height>211</height>
|
<height>211</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPlainTextEdit" name="textbox"/>
|
<widget class="QPlainTextEdit" name="textbox"/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="standardButtons">
|
<property name="standardButtons">
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>buttonBox</sender>
|
||||||
<signal>accepted()</signal>
|
<signal>accepted()</signal>
|
||||||
<receiver>CommentsDialog</receiver>
|
<receiver>CommentsDialog</receiver>
|
||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>229</x>
|
<x>229</x>
|
||||||
<y>211</y>
|
<y>211</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>157</x>
|
<x>157</x>
|
||||||
<y>234</y>
|
<y>234</y>
|
||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>buttonBox</sender>
|
||||||
<signal>rejected()</signal>
|
<signal>rejected()</signal>
|
||||||
<receiver>CommentsDialog</receiver>
|
<receiver>CommentsDialog</receiver>
|
||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>297</x>
|
<x>297</x>
|
||||||
<y>217</y>
|
<y>217</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>286</x>
|
<x>286</x>
|
||||||
<y>234</y>
|
<y>234</y>
|
||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
</connections>
|
</connections>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
import os, re, time, textwrap, sys, copy
|
import os, re, time, textwrap, copy
|
||||||
|
|
||||||
from PyQt4.Qt import QDialog, QListWidgetItem, QIcon, \
|
from PyQt4.Qt import QDialog, QListWidgetItem, QIcon, \
|
||||||
QDesktopServices, QVBoxLayout, QLabel, QPlainTextEdit, \
|
QDesktopServices, QVBoxLayout, QLabel, QPlainTextEdit, \
|
||||||
@ -17,7 +17,6 @@ from calibre.gui2 import qstring_to_unicode, choose_dir, error_dialog, config, \
|
|||||||
ALL_COLUMNS, NONE, info_dialog, choose_files, \
|
ALL_COLUMNS, NONE, info_dialog, choose_files, \
|
||||||
warning_dialog, ResizableDialog
|
warning_dialog, ResizableDialog
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
from calibre.gui2.library import BooksModel
|
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.ebooks.oeb.iterator import is_supported
|
from calibre.ebooks.oeb.iterator import is_supported
|
||||||
from calibre.library import server_config
|
from calibre.library import server_config
|
||||||
@ -666,10 +665,10 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def add_custcol(self):
|
def add_custcol(self):
|
||||||
d = CreateCustomColumn(self, False, self.model.orig_headers, ALL_COLUMNS)
|
CreateCustomColumn(self, False, self.model.orig_headers, ALL_COLUMNS)
|
||||||
|
|
||||||
def edit_custcol(self):
|
def edit_custcol(self):
|
||||||
d = CreateCustomColumn(self, True, self.model.orig_headers, ALL_COLUMNS)
|
CreateCustomColumn(self, True, self.model.orig_headers, ALL_COLUMNS)
|
||||||
|
|
||||||
def view_server_logs(self):
|
def view_server_logs(self):
|
||||||
from calibre.library.server import log_access_file, log_error_file
|
from calibre.library.server import log_access_file, log_error_file
|
||||||
|
@ -1,123 +1,121 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2010, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2010, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
'''Dialog to create a new custom column'''
|
'''Dialog to create a new custom column'''
|
||||||
|
|
||||||
from PyQt4.QtCore import SIGNAL, QObject
|
from PyQt4.QtCore import SIGNAL
|
||||||
from PyQt4.Qt import QDialog, Qt, QMessageBox, QListWidgetItem, QVariant
|
from PyQt4.Qt import QDialog, Qt, QListWidgetItem, QVariant
|
||||||
from calibre.gui2.dialogs.config.create_custom_column_ui import Ui_QCreateCustomColumn
|
from calibre.gui2.dialogs.config.create_custom_column_ui import Ui_QCreateCustomColumn
|
||||||
from calibre.gui2 import ALL_COLUMNS, qstring_to_unicode
|
|
||||||
|
class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
||||||
class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
column_types = {
|
||||||
column_types = {
|
0:{'datatype':'text', 'text':_('Text, column shown in tags browser'), 'is_multiple':False},
|
||||||
0:{'datatype':'text', 'text':_('Text, column shown in tags browser'), 'is_multiple':False},
|
1:{'datatype':'*text', 'text':_('Comma separated text, shown in tags browser'), 'is_multiple':True},
|
||||||
1:{'datatype':'*text', 'text':_('Comma separated text, shown in tags browser'), 'is_multiple':True},
|
2:{'datatype':'comments', 'text':_('Text, column not shown in tags browser'), 'is_multiple':False},
|
||||||
2:{'datatype':'comments', 'text':_('Text, column not shown in tags browser'), 'is_multiple':False},
|
3:{'datatype':'datetime', 'text':_('Date'), 'is_multiple':False},
|
||||||
3:{'datatype':'datetime', 'text':_('Date'), 'is_multiple':False},
|
4:{'datatype':'float', 'text':_('Float'), 'is_multiple':False},
|
||||||
4:{'datatype':'float', 'text':_('Float'), 'is_multiple':False},
|
5:{'datatype':'int', 'text':_('Integer'), 'is_multiple':False},
|
||||||
5:{'datatype':'int', 'text':_('Integer'), 'is_multiple':False},
|
6:{'datatype':'rating', 'text':_('Rating (stars)'), 'is_multiple':False},
|
||||||
6:{'datatype':'rating', 'text':_('Rating (stars)'), 'is_multiple':False},
|
7:{'datatype':'bool', 'text':_('Yes/No'), 'is_multiple':False},
|
||||||
7:{'datatype':'bool', 'text':_('Yes/No'), 'is_multiple':False},
|
}
|
||||||
}
|
def __init__(self, parent, editing, standard_colheads, standard_colnames):
|
||||||
def __init__(self, parent, editing, standard_colheads, standard_colnames):
|
QDialog.__init__(self, parent)
|
||||||
QDialog.__init__(self, parent)
|
Ui_QCreateCustomColumn.__init__(self)
|
||||||
Ui_QCreateCustomColumn.__init__(self)
|
self.setupUi(self)
|
||||||
self.setupUi(self)
|
self.connect(self.button_box, SIGNAL("accepted()"), self.accept)
|
||||||
self.connect(self.button_box, SIGNAL("accepted()"), self.accept)
|
self.connect(self.button_box, SIGNAL("rejected()"), self.reject)
|
||||||
self.connect(self.button_box, SIGNAL("rejected()"), self.reject)
|
self.parent = parent
|
||||||
self.parent = parent
|
self.editing_col = editing
|
||||||
self.editing_col = editing
|
self.standard_colheads = standard_colheads
|
||||||
self.standard_colheads = standard_colheads
|
self.standard_colnames = standard_colnames
|
||||||
self.standard_colnames = standard_colnames
|
if not self.editing_col:
|
||||||
if not self.editing_col:
|
for t in self.column_types:
|
||||||
for t in self.column_types:
|
self.column_type_box.addItem(self.column_types[t]['text'])
|
||||||
self.column_type_box.addItem(self.column_types[t]['text'])
|
self.exec_()
|
||||||
self.exec_()
|
return
|
||||||
return
|
idx = parent.columns.currentRow()
|
||||||
idx = parent.columns.currentRow()
|
if idx < 0:
|
||||||
if idx < 0:
|
self.parent.messagebox(_('No column has been selected'))
|
||||||
self.parent.messagebox(_('No column has been selected'))
|
return
|
||||||
return
|
col = unicode(parent.columns.item(idx).data(Qt.UserRole).toString())
|
||||||
col = qstring_to_unicode(parent.columns.item(idx).data(Qt.UserRole).toString())
|
if col not in parent.custcols:
|
||||||
if col not in parent.custcols:
|
self.parent.messagebox(_('Selected column is not a user-defined column'))
|
||||||
self.parent.messagebox(_('Selected column is not a user-defined column'))
|
return
|
||||||
return
|
|
||||||
|
c = parent.custcols[col]
|
||||||
c = parent.custcols[col]
|
self.column_name_box.setText(c['label'])
|
||||||
self.column_name_box.setText(c['label'])
|
self.column_heading_box.setText(c['name'])
|
||||||
self.column_heading_box.setText(c['name'])
|
ct = c['datatype'] if not c['is_multiple'] else '*text'
|
||||||
ct = c['datatype'] if not c['is_multiple'] else '*text'
|
self.orig_column_number = c['num']
|
||||||
self.orig_column_number = c['num']
|
self.orig_column_name = col
|
||||||
self.orig_column_name = col
|
column_numbers = dict(map(lambda x:(self.column_types[x]['datatype'], x), self.column_types))
|
||||||
column_numbers = dict(map(lambda x:(self.column_types[x]['datatype'], x), self.column_types))
|
self.column_type_box.addItem(self.column_types[column_numbers[ct]]['text'])
|
||||||
self.column_type_box.addItem(self.column_types[column_numbers[ct]]['text'])
|
self.exec_()
|
||||||
self.exec_()
|
|
||||||
|
def accept(self):
|
||||||
def accept(self):
|
col = unicode(self.column_name_box.text())
|
||||||
col = qstring_to_unicode(self.column_name_box.text())
|
col_heading = unicode(self.column_heading_box.text())
|
||||||
col_heading = qstring_to_unicode(self.column_heading_box.text())
|
col_type = self.column_types[self.column_type_box.currentIndex()]['datatype']
|
||||||
col_type = self.column_types[self.column_type_box.currentIndex()]['datatype']
|
if col_type == '*text':
|
||||||
if col_type == '*text':
|
col_type='text'
|
||||||
col_type='text'
|
is_multiple = True
|
||||||
is_multiple = True
|
else:
|
||||||
else:
|
is_multiple = False
|
||||||
is_multiple = False
|
if not col:
|
||||||
if not col:
|
self.parent.messagebox(_('No lookup name was provided'))
|
||||||
self.parent.messagebox(_('No lookup name was provided'))
|
return
|
||||||
return
|
if not col_heading:
|
||||||
if not col_heading:
|
self.parent.messagebox(_('No column heading was provided'))
|
||||||
self.parent.messagebox(_('No column heading was provided'))
|
return
|
||||||
return
|
bad_col = False
|
||||||
bad_col = False
|
if col in self.parent.custcols:
|
||||||
if col in self.parent.custcols:
|
if not self.editing_col or self.parent.custcols[col]['num'] != self.orig_column_number:
|
||||||
if not self.editing_col or self.parent.custcols[col]['num'] != self.orig_column_number:
|
bad_col = True
|
||||||
bad_col = True
|
if col in self.standard_colnames:
|
||||||
if col in self.standard_colnames:
|
bad_col = True
|
||||||
bad_col = True
|
if bad_col:
|
||||||
if bad_col:
|
self.parent.messagebox(_('The lookup name %s is already used')%col)
|
||||||
self.parent.messagebox(_('The lookup name %s is already used')%col)
|
return
|
||||||
return
|
bad_head = False
|
||||||
bad_head = False
|
for t in self.parent.custcols:
|
||||||
for t in self.parent.custcols:
|
if self.parent.custcols[t]['name'] == col_heading:
|
||||||
if self.parent.custcols[t]['name'] == col_heading:
|
if not self.editing_col or self.parent.custcols[t]['num'] != self.orig_column_number:
|
||||||
if not self.editing_col or self.parent.custcols[t]['num'] != self.orig_column_number:
|
bad_head = True
|
||||||
bad_head = True
|
for t in self.standard_colheads:
|
||||||
for t in self.standard_colheads:
|
if self.standard_colheads[t] == col_heading:
|
||||||
if self.standard_colheads[t] == col_heading:
|
bad_head = True
|
||||||
bad_head = True
|
if bad_head:
|
||||||
if bad_head:
|
self.parent.messagebox(_('The heading %s is already used')%col_heading)
|
||||||
self.parent.messagebox(_('The heading %s is already used')%col_heading)
|
return
|
||||||
return
|
if ':' in col or ' ' in col or col.lower() != col:
|
||||||
if col.find(':') >= 0 or col.find(' ') >= 0 and \
|
self.parent.messagebox(_('The lookup name must be lower case and cannot contain ":"s or spaces'))
|
||||||
(not is_alpha(col) or is_lower(col)):
|
return
|
||||||
self.parent.messagebox(_('The lookup name must be lower case and cannot contain ":"s or spaces'))
|
|
||||||
return
|
if not self.editing_col:
|
||||||
|
self.parent.custcols[col] = {
|
||||||
if not self.editing_col:
|
'label':col,
|
||||||
self.parent.custcols[col] = {
|
'name':col_heading,
|
||||||
'label':col,
|
'datatype':col_type,
|
||||||
'name':col_heading,
|
'editable':True,
|
||||||
'datatype':col_type,
|
'display':None,
|
||||||
'editable':True,
|
'normalized':None,
|
||||||
'display':None,
|
'num':None,
|
||||||
'normalized':None,
|
'is_multiple':is_multiple,
|
||||||
'num':None,
|
}
|
||||||
'is_multiple':is_multiple,
|
item = QListWidgetItem(col_heading, self.parent.columns)
|
||||||
}
|
item.setData(Qt.UserRole, QVariant(col))
|
||||||
item = QListWidgetItem(col_heading, self.parent.columns)
|
item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable|Qt.ItemIsSelectable)
|
||||||
item.setData(Qt.UserRole, QVariant(col))
|
item.setCheckState(Qt.Checked)
|
||||||
item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable|Qt.ItemIsSelectable)
|
else:
|
||||||
item.setCheckState(Qt.Checked)
|
idx = self.parent.columns.currentRow()
|
||||||
else:
|
item = self.parent.columns.item(idx)
|
||||||
idx = self.parent.columns.currentRow()
|
item.setData(Qt.UserRole, QVariant(col))
|
||||||
item = self.parent.columns.item(idx)
|
item.setText(col_heading)
|
||||||
item.setData(Qt.UserRole, QVariant(col))
|
self.parent.custcols[self.orig_column_name]['label'] = col
|
||||||
item.setText(col_heading)
|
self.parent.custcols[self.orig_column_name]['name'] = col_heading
|
||||||
self.parent.custcols[self.orig_column_name]['label'] = col
|
self.parent.custcols[self.orig_column_name]['*edited'] = True
|
||||||
self.parent.custcols[self.orig_column_name]['name'] = col_heading
|
self.parent.custcols[self.orig_column_name]['*must_restart'] = True
|
||||||
self.parent.custcols[self.orig_column_name]['*edited'] = True
|
QDialog.accept(self)
|
||||||
self.parent.custcols[self.orig_column_name]['*must_restart'] = True
|
|
||||||
QDialog.accept(self)
|
def reject(self):
|
||||||
|
QDialog.reject(self)
|
||||||
def reject(self):
|
|
||||||
QDialog.reject(self)
|
|
||||||
|
@ -1,142 +1,142 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>QCreateCustomColumn</class>
|
<class>QCreateCustomColumn</class>
|
||||||
<widget class="QDialog" name="QCreateCustomColumn">
|
<widget class="QDialog" name="QCreateCustomColumn">
|
||||||
<property name="windowModality">
|
<property name="windowModality">
|
||||||
<enum>Qt::ApplicationModal</enum>
|
<enum>Qt::ApplicationModal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>391</width>
|
<width>391</width>
|
||||||
<height>157</height>
|
<height>157</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Create Tag-based Column</string>
|
<string>Create Tag-based Column</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="verticalLayoutWidget">
|
<widget class="QWidget" name="verticalLayoutWidget">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>10</x>
|
<x>10</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>371</width>
|
<width>371</width>
|
||||||
<height>141</height>
|
<height>141</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0">
|
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0">
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetDefaultConstraint</enum>
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="margin">
|
<property name="margin">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Lookup name</string>
|
<string>Lookup name</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Column heading</string>
|
<string>Column heading</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLineEdit" name="column_name_box">
|
<widget class="QLineEdit" name="column_name_box">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>20</width>
|
||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Used for searching the column. Must be lower case and not contain spaces or colons.</string>
|
<string>Used for searching the column. Must be lower case and not contain spaces or colons.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLineEdit" name="column_heading_box">
|
<widget class="QLineEdit" name="column_heading_box">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Column heading in the library view and category name in tags browser</string>
|
<string>Column heading in the library view and category name in tags browser</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Column type</string>
|
<string>Column type</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QComboBox" name="column_type_box">
|
<widget class="QComboBox" name="column_type_box">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>70</width>
|
<width>70</width>
|
||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>What kind of information will be kept in the column.</string>
|
<string>What kind of information will be kept in the column.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QDialogButtonBox" name="button_box">
|
<widget class="QDialogButtonBox" name="button_box">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="standardButtons">
|
<property name="standardButtons">
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="centerButtons">
|
<property name="centerButtons">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<weight>75</weight>
|
<weight>75</weight>
|
||||||
<bold>true</bold>
|
<bold>true</bold>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Create and edit custom columns</string>
|
<string>Create and edit custom columns</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>column_name_box</tabstop>
|
<tabstop>column_name_box</tabstop>
|
||||||
<tabstop>column_heading_box</tabstop>
|
<tabstop>column_heading_box</tabstop>
|
||||||
<tabstop>column_type_box</tabstop>
|
<tabstop>column_type_box</tabstop>
|
||||||
<tabstop>button_box</tabstop>
|
<tabstop>button_box</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -1,186 +1,182 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
from copy import copy
|
|
||||||
|
from PyQt4.QtCore import SIGNAL, Qt
|
||||||
from PyQt4.QtCore import SIGNAL, Qt, QVariant
|
from PyQt4.QtGui import QDialog, QIcon, QListWidgetItem
|
||||||
from PyQt4.QtGui import QDialog, QDialogButtonBox, QLineEdit, QComboBox, \
|
|
||||||
QIcon, QListWidgetItem
|
from calibre.gui2.dialogs.tag_categories_ui import Ui_TagCategories
|
||||||
from PyQt4.Qt import QString
|
from calibre.gui2 import qstring_to_unicode, config
|
||||||
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
from calibre.gui2.dialogs.tag_categories_ui import Ui_TagCategories
|
from calibre.constants import islinux
|
||||||
from calibre.gui2 import qstring_to_unicode, config
|
|
||||||
from calibre.gui2 import question_dialog, error_dialog
|
class Item:
|
||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
def __init__(self, name, label, index, icon, exists):
|
||||||
from calibre.constants import islinux
|
self.name = name
|
||||||
|
self.label = label
|
||||||
class Item:
|
self.index = index
|
||||||
def __init__(self, name, label, index, icon, exists):
|
self.icon = icon
|
||||||
self.name = name
|
self.exists = exists
|
||||||
self.label = label
|
def __str__(self):
|
||||||
self.index = index
|
return 'name=%s, label=%s, index=%s, exists='%(self.name, self.label, self.index, self.exists)
|
||||||
self.icon = icon
|
|
||||||
self.exists = exists
|
class TagCategories(QDialog, Ui_TagCategories):
|
||||||
def __str__(self):
|
category_labels = ['', 'author', 'series', 'publisher', 'tag']
|
||||||
return 'name=%s, label=%s, index=%s, exists='%(self.name, self.label, self.index, self.exists)
|
|
||||||
|
def __init__(self, window, db, index=None):
|
||||||
class TagCategories(QDialog, Ui_TagCategories):
|
QDialog.__init__(self, window)
|
||||||
category_labels = ['', 'author', 'series', 'publisher', 'tag']
|
Ui_TagCategories.__init__(self)
|
||||||
|
self.setupUi(self)
|
||||||
def __init__(self, window, db, index=None):
|
|
||||||
QDialog.__init__(self, window)
|
self.db = db
|
||||||
Ui_TagCategories.__init__(self)
|
self.index = index
|
||||||
self.setupUi(self)
|
self.applied_items = []
|
||||||
|
|
||||||
self.db = db
|
category_icons = [None, QIcon(I('user_profile.svg')), QIcon(I('series.svg')),
|
||||||
self.index = index
|
QIcon(I('publisher.png')), QIcon(I('tags.svg'))]
|
||||||
self.applied_items = []
|
category_values = [None,
|
||||||
|
lambda: [n for (id, n) in self.db.all_authors()],
|
||||||
category_icons = [None, QIcon(I('user_profile.svg')), QIcon(I('series.svg')),
|
lambda: [n for (id, n) in self.db.all_series()],
|
||||||
QIcon(I('publisher.png')), QIcon(I('tags.svg'))]
|
lambda: [n for (id, n) in self.db.all_publishers()],
|
||||||
category_values = [None,
|
lambda: self.db.all_tags()
|
||||||
lambda: [n for (id, n) in self.db.all_authors()],
|
]
|
||||||
lambda: [n for (id, n) in self.db.all_series()],
|
category_names = ['', _('Authors'), _('Series'), _('Publishers'), _('Tags')]
|
||||||
lambda: [n for (id, n) in self.db.all_publishers()],
|
|
||||||
lambda: self.db.all_tags()
|
self.all_items = []
|
||||||
]
|
self.all_items_dict = {}
|
||||||
category_names = ['', _('Authors'), _('Series'), _('Publishers'), _('Tags')]
|
for idx,label in enumerate(self.category_labels):
|
||||||
|
if idx == 0:
|
||||||
self.all_items = []
|
continue
|
||||||
self.all_items_dict = {}
|
for n in category_values[idx]():
|
||||||
for idx,label in enumerate(self.category_labels):
|
t = Item(name=n, label=label, index=len(self.all_items),icon=category_icons[idx], exists=True)
|
||||||
if idx == 0:
|
self.all_items.append(t)
|
||||||
continue
|
self.all_items_dict[label+':'+n] = t
|
||||||
for n in category_values[idx]():
|
|
||||||
t = Item(name=n, label=label, index=len(self.all_items),icon=category_icons[idx], exists=True)
|
self.categories = dict.copy(config['user_categories'])
|
||||||
self.all_items.append(t)
|
if self.categories is None:
|
||||||
self.all_items_dict[label+':'+n] = t
|
self.categories = {}
|
||||||
|
for cat in self.categories:
|
||||||
self.categories = dict.copy(config['user_categories'])
|
for item,l in enumerate(self.categories[cat]):
|
||||||
if self.categories is None:
|
key = ':'.join([l[1], l[0]])
|
||||||
self.categories = {}
|
t = self.all_items_dict.get(key, None)
|
||||||
for cat in self.categories:
|
if t is None:
|
||||||
for item,l in enumerate(self.categories[cat]):
|
t = Item(name=l[0], label=l[1], index=len(self.all_items),
|
||||||
key = ':'.join([l[1], l[0]])
|
icon=category_icons[self.category_labels.index(l[1])], exists=False)
|
||||||
t = self.all_items_dict.get(key, None)
|
self.all_items.append(t)
|
||||||
if t is None:
|
self.all_items_dict[key] = t
|
||||||
t = Item(name=l[0], label=l[1], index=len(self.all_items),
|
l[2] = t.index
|
||||||
icon=category_icons[self.category_labels.index(l[1])], exists=False)
|
|
||||||
self.all_items.append(t)
|
self.all_items_sorted = sorted(self.all_items, cmp=lambda x,y: cmp(x.name.lower(), y.name.lower()))
|
||||||
self.all_items_dict[key] = t
|
self.display_filtered_categories(0)
|
||||||
l[2] = t.index
|
|
||||||
|
for v in category_names:
|
||||||
self.all_items_sorted = sorted(self.all_items, cmp=lambda x,y: cmp(x.name.lower(), y.name.lower()))
|
self.category_filter_box.addItem(v)
|
||||||
self.display_filtered_categories(0)
|
self.current_cat_name = None
|
||||||
|
|
||||||
for v in category_names:
|
self.connect(self.apply_button, SIGNAL('clicked()'), self.apply_tags)
|
||||||
self.category_filter_box.addItem(v)
|
self.connect(self.unapply_button, SIGNAL('clicked()'), self.unapply_tags)
|
||||||
self.current_cat_name = None
|
self.connect(self.add_category_button, SIGNAL('clicked()'), self.add_category)
|
||||||
|
self.connect(self.category_box, SIGNAL('currentIndexChanged(int)'), self.select_category)
|
||||||
self.connect(self.apply_button, SIGNAL('clicked()'), self.apply_tags)
|
self.connect(self.category_filter_box, SIGNAL('currentIndexChanged(int)'), self.display_filtered_categories)
|
||||||
self.connect(self.unapply_button, SIGNAL('clicked()'), self.unapply_tags)
|
self.connect(self.delete_category_button, SIGNAL('clicked()'), self.del_category)
|
||||||
self.connect(self.add_category_button, SIGNAL('clicked()'), self.add_category)
|
if islinux:
|
||||||
self.connect(self.category_box, SIGNAL('currentIndexChanged(int)'), self.select_category)
|
self.available_items_box.itemDoubleClicked.connect(self.apply_tags)
|
||||||
self.connect(self.category_filter_box, SIGNAL('currentIndexChanged(int)'), self.display_filtered_categories)
|
else:
|
||||||
self.connect(self.delete_category_button, SIGNAL('clicked()'), self.del_category)
|
self.connect(self.available_items_box, SIGNAL('itemActivated(QListWidgetItem*)'), self.apply_tags)
|
||||||
if islinux:
|
self.connect(self.applied_items_box, SIGNAL('itemActivated(QListWidgetItem*)'), self.unapply_tags)
|
||||||
self.available_items_box.itemDoubleClicked.connect(self.apply_tags)
|
|
||||||
else:
|
self.populate_category_list()
|
||||||
self.connect(self.available_items_box, SIGNAL('itemActivated(QListWidgetItem*)'), self.apply_tags)
|
return
|
||||||
self.connect(self.applied_items_box, SIGNAL('itemActivated(QListWidgetItem*)'), self.unapply_tags)
|
self.select_category(0)
|
||||||
|
|
||||||
self.populate_category_list()
|
def make_list_widget(self, item):
|
||||||
return
|
n = item.name if item.exists else item.name + _(' (not on any book)')
|
||||||
self.select_category(0)
|
w = QListWidgetItem(item.icon, n)
|
||||||
|
w.setData(Qt.UserRole, item.index)
|
||||||
def make_list_widget(self, item):
|
return w
|
||||||
n = item.name if item.exists else item.name + _(' (not on any book)')
|
|
||||||
w = QListWidgetItem(item.icon, n)
|
def display_filtered_categories(self, idx):
|
||||||
w.setData(Qt.UserRole, item.index)
|
idx = idx if idx is not None else self.category_filter_box.currentIndex()
|
||||||
return w
|
self.available_items_box.clear()
|
||||||
|
self.applied_items_box.clear()
|
||||||
def display_filtered_categories(self, idx):
|
for item in self.all_items_sorted:
|
||||||
idx = idx if idx is not None else self.category_filter_box.currentIndex()
|
if idx == 0 or item.label == self.category_labels[idx]:
|
||||||
self.available_items_box.clear()
|
if item.index not in self.applied_items and item.exists:
|
||||||
self.applied_items_box.clear()
|
self.available_items_box.addItem(self.make_list_widget(item))
|
||||||
for item in self.all_items_sorted:
|
for index in self.applied_items:
|
||||||
if idx == 0 or item.label == self.category_labels[idx]:
|
self.applied_items_box.addItem(self.make_list_widget(self.all_items[index]))
|
||||||
if item.index not in self.applied_items and item.exists:
|
|
||||||
self.available_items_box.addItem(self.make_list_widget(item))
|
def apply_tags(self, node=None):
|
||||||
for index in self.applied_items:
|
if self.current_cat_name is None:
|
||||||
self.applied_items_box.addItem(self.make_list_widget(self.all_items[index]))
|
return
|
||||||
|
nodes = self.available_items_box.selectedItems() if node is None else [node]
|
||||||
def apply_tags(self, node=None):
|
for node in nodes:
|
||||||
if self.current_cat_name is None:
|
index = self.all_items[node.data(Qt.UserRole).toPyObject()].index
|
||||||
return
|
if index not in self.applied_items:
|
||||||
nodes = self.available_items_box.selectedItems() if node is None else [node]
|
self.applied_items.append(index)
|
||||||
for node in nodes:
|
self.applied_items.sort(cmp=lambda x, y:cmp(self.all_items[x].name.lower(), self.all_items[y].name.lower()))
|
||||||
index = self.all_items[node.data(Qt.UserRole).toPyObject()].index
|
self.display_filtered_categories(None)
|
||||||
if index not in self.applied_items:
|
|
||||||
self.applied_items.append(index)
|
def unapply_tags(self, node=None):
|
||||||
self.applied_items.sort(cmp=lambda x, y:cmp(self.all_items[x].name.lower(), self.all_items[y].name.lower()))
|
nodes = self.applied_items_box.selectedItems() if node is None else [node]
|
||||||
self.display_filtered_categories(None)
|
for node in nodes:
|
||||||
|
index = self.all_items[node.data(Qt.UserRole).toPyObject()].index
|
||||||
def unapply_tags(self, node=None):
|
self.applied_items.remove(index)
|
||||||
nodes = self.applied_items_box.selectedItems() if node is None else [node]
|
self.display_filtered_categories(None)
|
||||||
for node in nodes:
|
|
||||||
index = self.all_items[node.data(Qt.UserRole).toPyObject()].index
|
def add_category(self):
|
||||||
self.applied_items.remove(index)
|
self.save_category()
|
||||||
self.display_filtered_categories(None)
|
cat_name = qstring_to_unicode(self.input_box.text()).strip()
|
||||||
|
if cat_name == '':
|
||||||
def add_category(self):
|
return False
|
||||||
self.save_category()
|
if cat_name not in self.categories:
|
||||||
cat_name = qstring_to_unicode(self.input_box.text()).strip()
|
self.category_box.clear()
|
||||||
if cat_name == '':
|
self.current_cat_name = cat_name
|
||||||
return False
|
self.categories[cat_name] = []
|
||||||
if cat_name not in self.categories:
|
self.applied_items = []
|
||||||
self.category_box.clear()
|
self.populate_category_list()
|
||||||
self.current_cat_name = cat_name
|
self.category_box.setCurrentIndex(self.category_box.findText(cat_name))
|
||||||
self.categories[cat_name] = []
|
else:
|
||||||
self.applied_items = []
|
self.select_category(self.category_box.findText(cat_name))
|
||||||
self.populate_category_list()
|
return True
|
||||||
self.category_box.setCurrentIndex(self.category_box.findText(cat_name))
|
|
||||||
else:
|
def del_category(self):
|
||||||
self.select_category(self.category_box.findText(cat_name))
|
if self.current_cat_name is not None:
|
||||||
return True
|
if not confirm('<p>'+_('The current tag category will be '
|
||||||
|
'<b>permanently deleted</b>. Are you sure?')
|
||||||
def del_category(self):
|
+'</p>', 'tag_category_delete', self):
|
||||||
if self.current_cat_name is not None:
|
return
|
||||||
if not confirm('<p>'+_('The current tag category will be '
|
del self.categories[self.current_cat_name]
|
||||||
'<b>permanently deleted</b>. Are you sure?')
|
self.current_cat_name = None
|
||||||
+'</p>', 'tag_category_delete', self):
|
self.category_box.removeItem(self.category_box.currentIndex())
|
||||||
return
|
|
||||||
del self.categories[self.current_cat_name]
|
def select_category(self, idx):
|
||||||
self.current_cat_name = None
|
self.save_category()
|
||||||
self.category_box.removeItem(self.category_box.currentIndex())
|
s = self.category_box.itemText(idx)
|
||||||
|
if s:
|
||||||
def select_category(self, idx):
|
self.current_cat_name = unicode(s)
|
||||||
self.save_category()
|
else:
|
||||||
s = self.category_box.itemText(idx)
|
self.current_cat_name = None
|
||||||
if s:
|
if self.current_cat_name:
|
||||||
self.current_cat_name = unicode(s)
|
self.applied_items = [cat[2] for cat in self.categories.get(self.current_cat_name, [])]
|
||||||
else:
|
else:
|
||||||
self.current_cat_name = None
|
self.applied_items = []
|
||||||
if self.current_cat_name:
|
self.display_filtered_categories(None)
|
||||||
self.applied_items = [cat[2] for cat in self.categories.get(self.current_cat_name, [])]
|
|
||||||
else:
|
def accept(self):
|
||||||
self.applied_items = []
|
self.save_category()
|
||||||
self.display_filtered_categories(None)
|
config['user_categories'] = self.categories
|
||||||
|
QDialog.accept(self)
|
||||||
def accept(self):
|
|
||||||
self.save_category()
|
def save_category(self):
|
||||||
config['user_categories'] = self.categories
|
if self.current_cat_name is not None:
|
||||||
QDialog.accept(self)
|
l = []
|
||||||
|
for index in self.applied_items:
|
||||||
def save_category(self):
|
item = self.all_items[index]
|
||||||
if self.current_cat_name is not None:
|
l.append([item.name, item.label, item.index])
|
||||||
l = []
|
self.categories[self.current_cat_name] = l
|
||||||
for index in self.applied_items:
|
|
||||||
item = self.all_items[index]
|
def populate_category_list(self):
|
||||||
l.append([item.name, item.label, item.index])
|
for n in sorted(self.categories.keys(), cmp=lambda x,y: cmp(x.lower(), y.lower())):
|
||||||
self.categories[self.current_cat_name] = l
|
self.category_box.addItem(n)
|
||||||
|
|
||||||
def populate_category_list(self):
|
|
||||||
for n in sorted(self.categories.keys(), cmp=lambda x,y: cmp(x.lower(), y.lower())):
|
|
||||||
self.category_box.addItem(n)
|
|
||||||
|
@ -6,16 +6,15 @@ import os, textwrap, traceback, re, shutil, functools
|
|||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from math import cos, sin, pi
|
from math import cos, sin, pi
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
from datetime import date
|
|
||||||
|
|
||||||
from PyQt4.QtGui import QTableView, QAbstractItemView, QColor, \
|
from PyQt4.QtGui import QTableView, QAbstractItemView, QColor, \
|
||||||
QPainterPath, QLinearGradient, QBrush, \
|
QPainterPath, QLinearGradient, QBrush, \
|
||||||
QPen, QStyle, QPainter, QStyleOptionViewItemV4, \
|
QPen, QStyle, QPainter, QStyleOptionViewItemV4, \
|
||||||
QIcon, QImage, QMenu, \
|
QIcon, QImage, QMenu, \
|
||||||
QStyledItemDelegate, QCompleter, QIntValidator, \
|
QStyledItemDelegate, QCompleter, QIntValidator, \
|
||||||
QPlainTextEdit, QDoubleValidator, QCheckBox, QMessageBox
|
QDoubleValidator, QCheckBox
|
||||||
from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, pyqtSignal, \
|
from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, pyqtSignal, \
|
||||||
SIGNAL, QObject, QSize, QModelIndex, QDate, QRect
|
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
|
||||||
@ -25,7 +24,7 @@ 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, prefs
|
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
|
||||||
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
|
||||||
@ -222,10 +221,7 @@ class CcBoolDelegate(QStyledItemDelegate):
|
|||||||
QStyledItemDelegate.__init__(self, parent)
|
QStyledItemDelegate.__init__(self, parent)
|
||||||
|
|
||||||
def createEditor(self, parent, option, index):
|
def createEditor(self, parent, option, index):
|
||||||
m = index.model()
|
|
||||||
col = m.column_map[index.column()]
|
|
||||||
editor = QCheckBox(parent)
|
editor = QCheckBox(parent)
|
||||||
val = m.db.data[index.row()][m.db.FIELD_MAP[m.custom_columns[col]['num']]]
|
|
||||||
if tweaks['bool_custom_columns_are_tristate'] == 'no':
|
if tweaks['bool_custom_columns_are_tristate'] == 'no':
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -8,7 +8,6 @@ Browsing book collection by tags.
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from itertools import izip
|
from itertools import izip
|
||||||
from copy import copy
|
|
||||||
|
|
||||||
from PyQt4.Qt import Qt, QTreeView, QApplication, pyqtSignal, \
|
from PyQt4.Qt import Qt, QTreeView, QApplication, pyqtSignal, \
|
||||||
QFont, SIGNAL, QSize, QIcon, QPoint, \
|
QFont, SIGNAL, QSize, QIcon, QPoint, \
|
||||||
@ -435,4 +434,4 @@ class TagsModel(QAbstractItemModel):
|
|||||||
continue
|
continue
|
||||||
tags_seen.append(tag.name)
|
tags_seen.append(tag.name)
|
||||||
ans.append('%s%s:"=%s"'%(prefix, category, tag.name))
|
ans.append('%s%s:"=%s"'%(prefix, category, tag.name))
|
||||||
return ans
|
return ans
|
||||||
|
@ -62,8 +62,6 @@ from calibre.library.caches import CoverCache
|
|||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
from calibre.gui2.dialogs.tag_categories import TagCategories
|
from calibre.gui2.dialogs.tag_categories import TagCategories
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
class SaveMenu(QMenu):
|
class SaveMenu(QMenu):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
@ -129,7 +127,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
pixmap_to_data(pixmap))
|
pixmap_to_data(pixmap))
|
||||||
|
|
||||||
def __init__(self, listener, opts, actions, parent=None):
|
def __init__(self, listener, opts, actions, parent=None):
|
||||||
self.last_time = datetime.now()
|
self.last_time = datetime.datetime.now()
|
||||||
self.preferences_action, self.quit_action = actions
|
self.preferences_action, self.quit_action = actions
|
||||||
self.spare_servers = []
|
self.spare_servers = []
|
||||||
self.must_restart_before_config = False
|
self.must_restart_before_config = False
|
||||||
@ -2167,7 +2165,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
return
|
return
|
||||||
for row in rows:
|
for row in rows:
|
||||||
path = self.library_view.model().db.abspath(row.row())
|
path = self.library_view.model().db.abspath(row.row())
|
||||||
QDesktopServices.openUrl(QUrl('file:'+path))
|
QDesktopServices.openUrl(QUrl.fromLocalFile(path))
|
||||||
|
|
||||||
|
|
||||||
def view_book(self, triggered):
|
def view_book(self, triggered):
|
||||||
|
@ -13,7 +13,7 @@ from datetime import timedelta
|
|||||||
from PyQt4.QtCore import QThread, QReadWriteLock
|
from PyQt4.QtCore import QThread, QReadWriteLock
|
||||||
from PyQt4.QtGui import QImage
|
from PyQt4.QtGui import QImage
|
||||||
|
|
||||||
from calibre.utils.config import tweaks, prefs
|
from calibre.utils.config import tweaks
|
||||||
from calibre.utils.date import parse_date, now
|
from calibre.utils.date import parse_date, now
|
||||||
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
|
||||||
@ -541,4 +541,4 @@ class ResultCache(SearchQueryParser):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
def set_search_restriction(self, s):
|
def set_search_restriction(self, s):
|
||||||
self.search_restriction = '' if not s else 'search:"%s"' % (s.strip())
|
self.search_restriction = '' if not s else 'search:"%s"' % (s.strip())
|
||||||
|
@ -54,7 +54,7 @@ def set_metadata(stream, mi):
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
ret = p.wait()
|
p.wait()
|
||||||
break
|
break
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
if e.errno == errno.EINTR:
|
if e.errno == errno.EINTR:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user