%s | %s |
'+_('All checked books will be ' + 'permanently deleted from your ' + 'device. Please verify the list.'+'
')) + self.buttonBox.accepted.connect(self.accepted) + self.table.cellClicked.connect(self.cell_clicked) + self.table.setSelectionMode(QAbstractItemView.NoSelection) + self.table.setColumnCount(5) + self.table.setHorizontalHeaderLabels( + ['', _('Location'), _('Title'), + _('Author'), _('Date'), _('Format')]) + rows = 0 + for card in items: + rows += len(items[card][1]) + self.table.setRowCount(rows) + row = 0 + for card in items: + (model,books) = items[card] + for (id,book) in books: + item = QTableWidgetItem() + item.setFlags(Qt.ItemIsUserCheckable|Qt.ItemIsEnabled) + item.setCheckState(Qt.Checked) + item.setData(Qt.UserRole, (model, id, book.path)) + self.table.setItem(row, 0, item) + self.table.setItem(row, 1, tableItem(card)) + self.table.setItem(row, 2, titleTableItem(book.title)) + self.table.setItem(row, 3, authorTableItem(book)) + self.table.setItem(row, 4, dateTableItem(book.datetime)) + self.table.setItem(row, 5, tableItem(book.path.rpartition('.')[2])) + row += 1 + self.table.setCurrentCell(0, 1) + self.table.resizeColumnsToContents() + self.table.setSortingEnabled(True) + self.table.sortByColumn(2, Qt.AscendingOrder) + self.table.setCurrentCell(0, 1) + + def cell_clicked(self, row, col): + if col == 0: + self.table.setCurrentCell(row, 1) + + def accepted(self): + self.result = [] + for row in range(self.table.rowCount()): + if self.table.item(row, 0).checkState() == Qt.Unchecked: + continue + (model, id, path) = self.table.item(row, 0).data(Qt.UserRole).toPyObject() + path = unicode(path) + self.result.append((model, id, path)) + return + diff --git a/src/calibre/gui2/dialogs/delete_matching_from_device.ui b/src/calibre/gui2/dialogs/delete_matching_from_device.ui new file mode 100644 index 0000000000..fec08e5b00 --- /dev/null +++ b/src/calibre/gui2/dialogs/delete_matching_from_device.ui @@ -0,0 +1,90 @@ + +%s | %s |
'+_('Click to open Book Details window') +
- '
' + _('Path') + ': ' + data.get(_('Path'), ''))
-
-
-
-class StatusBarInterface(object):
-
- def initialize(self, systray=None):
- self.systray = systray
- self.notifier = get_notifier(systray)
-
- def show_message(self, msg, timeout=0):
- QStatusBar.showMessage(self, msg, timeout)
- if self.notifier is not None and not config['disable_tray_notification']:
- if isosx and isinstance(msg, unicode):
- try:
- msg = msg.encode(preferred_encoding)
- except UnicodeEncodeError:
- msg = msg.encode('utf-8')
- self.notifier(msg)
-
- def clear_message(self):
- QStatusBar.clearMessage(self)
-
-class BookDetailsInterface(object):
-
- # These signals must be defined in the class implementing this interface
- files_dropped = None
- show_book_info = None
- open_containing_folder = None
- view_specific_format = None
-
- def reset_info(self):
- raise NotImplementedError()
-
- def show_data(self, data):
- raise NotImplementedError()
-
-class HStatusBar(QStatusBar, StatusBarInterface):
- pass
-
-class StatusBar(QStatusBar, StatusBarInterface, BookDetailsInterface):
-
- files_dropped = pyqtSignal(object, object)
- show_book_info = pyqtSignal()
- open_containing_folder = pyqtSignal(int)
- view_specific_format = pyqtSignal(int, object)
-
- resized = pyqtSignal(object)
-
- def initialize(self, systray=None):
- StatusBarInterface.initialize(self, systray=systray)
- self.book_info = BookInfoDisplay(self.clear_message)
- self.book_info.setAcceptDrops(True)
- self.scroll_area = QScrollArea()
- self.scroll_area.setWidget(self.book_info)
- self.scroll_area.setWidgetResizable(True)
- self.book_info.show_book_info.connect(self.show_book_info.emit,
- type=Qt.QueuedConnection)
- self.book_info.files_dropped.connect(self.files_dropped.emit,
- type=Qt.QueuedConnection)
- self.book_info.book_data.link_clicked.connect(self._link_clicked)
- self.addWidget(self.scroll_area, 100)
- self.setMinimumHeight(120)
- self.resized.connect(self.book_info.cover_display.relayout)
- self.book_info.cover_display.relayout(self.size())
-
-
- def _link_clicked(self, link):
- typ, _, val = link.partition(':')
- if typ == 'path':
- self.open_containing_folder.emit(int(val))
- elif typ == 'format':
- id_, fmt = val.split(':')
- self.view_specific_format.emit(int(id_), fmt)
- elif typ == 'devpath':
- QDesktopServices.openUrl(QUrl.fromLocalFile(val))
-
-
- def resizeEvent(self, ev):
- self.resized.emit(self.size())
-
- def reset_info(self):
- self.book_info.show_data({})
-
- def show_data(self, data):
- self.book_info.show_data(data)
-
diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py
index 2226520cf2..6452890883 100644
--- a/src/calibre/gui2/ui.py
+++ b/src/calibre/gui2/ui.py
@@ -126,8 +126,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
# Jobs Button {{{
self.job_manager = JobManager()
self.jobs_dialog = JobsDialog(self, self.job_manager)
- self.jobs_button = JobsButton(horizontal=config['gui_layout'] !=
- 'narrow')
+ self.jobs_button = JobsButton(horizontal=True)
self.jobs_button.initialize(self.jobs_dialog, self.job_manager)
# }}}
@@ -216,12 +215,6 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
self.vanity.setText(self.vanity_template%dict(version=' ', device=' '))
self.device_info = ' '
UpdateMixin.__init__(self, opts)
- ####################### Status Bar #####################
- self.status_bar.initialize(self.system_tray_icon)
- self.book_details.show_book_info.connect(self.show_book_info)
- self.book_details.files_dropped.connect(self.files_dropped_on_book)
- self.book_details.open_containing_folder.connect(self.view_folder_for_id)
- self.book_details.view_specific_format.connect(self.view_format_by_id)
####################### Setup Toolbar #####################
ToolbarMixin.__init__(self)
@@ -417,6 +410,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
self.tags_view.set_new_model() # in case columns changed
self.tags_view.recount()
self.create_device_menu()
+ self.set_device_menu_items_state(bool(self.device_connected),
+ self.device_connected == 'folder')
if not patheq(self.library_path, d.database_location):
newloc = d.database_location
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index c7830187df..fe4aac12b5 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -136,6 +136,23 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.initialize_dynamic()
def initialize_dynamic(self):
+ self.conn.executescript('''
+ DROP TRIGGER IF EXISTS author_insert_trg;
+ CREATE TEMP TRIGGER author_insert_trg
+ AFTER INSERT ON authors
+ BEGIN
+ UPDATE authors SET sort=author_to_author_sort(NEW.name) WHERE id=NEW.id;
+ END;
+ DROP TRIGGER IF EXISTS author_update_trg;
+ CREATE TEMP TRIGGER author_update_trg
+ BEFORE UPDATE ON authors
+ BEGIN
+ UPDATE authors SET sort=author_to_author_sort(NEW.name)
+ WHERE id=NEW.id AND name <> NEW.name;
+ END;
+ ''')
+ self.conn.execute(
+ 'UPDATE authors SET sort=author_to_author_sort(name) WHERE sort IS NULL')
self.conn.executescript(u'''
CREATE TEMP VIEW IF NOT EXISTS tag_browser_news AS SELECT DISTINCT
id,
diff --git a/src/calibre/library/schema_upgrades.py b/src/calibre/library/schema_upgrades.py
index a8ffd9cde4..1ba650f6fd 100644
--- a/src/calibre/library/schema_upgrades.py
+++ b/src/calibre/library/schema_upgrades.py
@@ -385,28 +385,5 @@ class SchemaUpgrade(object):
if table.startswith('custom_column_') and link_table in tables:
create_cust_tag_browser_view(table, link_table)
- from calibre.ebooks.metadata import author_to_author_sort
+ self.conn.execute('UPDATE authors SET sort=author_to_author_sort(name)')
- aut = self.conn.get('SELECT id, name FROM authors');
- records = []
- for (id, author) in aut:
- records.append((id, author.replace('|', ',')))
- for id,author in records:
- self.conn.execute('UPDATE authors SET sort=? WHERE id=?',
- (author_to_author_sort(author.replace('|', ',')).strip(), id))
- self.conn.commit()
- self.conn.executescript('''
- DROP TRIGGER IF EXISTS author_insert_trg;
- CREATE TRIGGER author_insert_trg
- AFTER INSERT ON authors
- BEGIN
- UPDATE authors SET sort=author_to_author_sort(NEW.name) WHERE id=NEW.id;
- END;
- DROP TRIGGER IF EXISTS author_update_trg;
- CREATE TRIGGER author_update_trg
- BEFORE UPDATE ON authors
- BEGIN
- UPDATE authors SET sort=author_to_author_sort(NEW.name)
- WHERE id=NEW.id AND name <> NEW.name;
- END;
- ''')
diff --git a/src/calibre/library/sqlite.py b/src/calibre/library/sqlite.py
index 7e0458fba4..85954f6e0f 100644
--- a/src/calibre/library/sqlite.py
+++ b/src/calibre/library/sqlite.py
@@ -94,6 +94,9 @@ class Connection(sqlite.Connection):
return ans[0]
return ans.fetchall()
+def _author_to_author_sort(x):
+ if not x: return ''
+ return author_to_author_sort(x.replace('|', ','))
class DBThread(Thread):
@@ -121,7 +124,7 @@ class DBThread(Thread):
else:
self.conn.create_function('title_sort', 1, title_sort)
self.conn.create_function('author_to_author_sort', 1,
- lambda x: author_to_author_sort(x.replace('|', ',')))
+ _author_to_author_sort)
self.conn.create_function('uuid4', 0, lambda : str(uuid.uuid4()))
# Dummy functions for dynamically created filters
self.conn.create_function('books_list_filter', 1, lambda x: 1)
diff --git a/src/calibre/utils/Zeroconf.py b/src/calibre/utils/Zeroconf.py
index 8a1e13c23f..f4a7119d16 100755
--- a/src/calibre/utils/Zeroconf.py
+++ b/src/calibre/utils/Zeroconf.py
@@ -596,10 +596,11 @@ class DNSIncoming(object):
next = off + 1
off = ((len & 0x3F) << 8) | ord(self.data[off])
if off >= first:
- raise 'Bad domain name (circular) at ' + str(off)
+ raise ValueError('Bad domain name (circular) at ' +
+ str(off))
first = off
else:
- raise 'Bad domain name at ' + str(off)
+ raise ValueError('Bad domain name at ' + str(off))
if next >= 0:
self.offset = next
diff --git a/src/calibre/web/feeds/news.py b/src/calibre/web/feeds/news.py
index 9e05babecc..73e0fae8e8 100644
--- a/src/calibre/web/feeds/news.py
+++ b/src/calibre/web/feeds/news.py
@@ -788,6 +788,7 @@ class BasicNewsRecipe(Recipe):
}
.summary_byline {
+ text-align:left;
font-family:monospace;
}
@@ -1139,12 +1140,6 @@ class BasicNewsRecipe(Recipe):
mi = MetaInformation(self.short_title() + strftime(self.timefmt), [__appname__])
mi.publisher = __appname__
mi.author_sort = __appname__
- if self.output_profile.name == 'iPad':
- date_as_author = '%s, %s %s, %s' % (strftime('%A'), strftime('%B'), strftime('%d').lstrip('0'), strftime('%Y'))
- mi = MetaInformation(self.short_title(), [date_as_author])
- mi.publisher = __appname__
- sort_author = re.sub('^\s*A\s+|^\s*The\s+|^\s*An\s+', '', self.title).rstrip()
- mi.author_sort = '%s %s' % (sort_author, strftime('%Y-%m-%d'))
mi.publication_type = 'periodical:'+self.publication_type
mi.timestamp = nowf()
mi.comments = self.description