mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Drag 'n drop re-ordering of spine items
This commit is contained in:
parent
26c1fd0689
commit
7f2a1f99da
@ -355,6 +355,28 @@ class Container(object): # {{{
|
||||
for name in nixed:
|
||||
self.remove_item(name)
|
||||
|
||||
def set_spine(self, spine_items):
|
||||
''' Set the spine to be spine_items where spine_items is an iterable of
|
||||
the form (name, linear). Will raise an error if one of the names is not
|
||||
present in the manifest. '''
|
||||
imap = self.manifest_id_map
|
||||
imap = {name:item_id for item_id, name in imap.iteritems()}
|
||||
items = [item for item, name, linear in self.spine_iter]
|
||||
tail, last_tail = (items[0].tail, items[-1].tail) if items else ('\n ', '\n ')
|
||||
map(self.remove_from_xml, items)
|
||||
spine = self.opf_xpath('//opf:spine')[0]
|
||||
spine.text = tail
|
||||
for name, linear in spine_items:
|
||||
i = spine.makeelement('{%s}itemref' % OPF_NAMESPACES['opf'], nsmap={'opf':OPF_NAMESPACES['opf']})
|
||||
i.tail = tail
|
||||
i.set('idref', imap[name])
|
||||
spine.append(i)
|
||||
if not linear:
|
||||
i.set('linear', 'no')
|
||||
if len(spine) > 0:
|
||||
spine[-1].tail = last_tail
|
||||
self.dirty(self.opf_name)
|
||||
|
||||
def remove_item(self, name):
|
||||
'''
|
||||
Remove the item identified by name from this container. This removes all
|
||||
|
@ -35,6 +35,7 @@ class Boss(QObject):
|
||||
def __call__(self, gui):
|
||||
self.gui = gui
|
||||
gui.file_list.delete_requested.connect(self.delete_requested)
|
||||
gui.file_list.reorder_spine.connect(self.reorder_spine)
|
||||
|
||||
def mkdtemp(self):
|
||||
self.container_count += 1
|
||||
@ -130,6 +131,16 @@ class Boss(QObject):
|
||||
self.gui.file_list.delete_done(spine_items, other_items)
|
||||
# TODO: Update other GUI elements
|
||||
|
||||
def reorder_spine(self, items):
|
||||
# TODO: If content.opf is dirty in an editor, abort, calling
|
||||
# file_list.build(current_container) to undo drag and drop
|
||||
self.add_savepoint(_('Re-order text'))
|
||||
c = current_container()
|
||||
c.set_spine(items)
|
||||
self.gui.action_save.setEnabled(True)
|
||||
self.gui.file_list.build(current_container()) # needed as the linear flag may have changed on some items
|
||||
# TODO: If content.opf is open in an editor, reload it
|
||||
|
||||
def save_book(self):
|
||||
self.gui.action_save.setEnabled(False)
|
||||
tdir = tempfile.mkdtemp(prefix='save-%05d-' % self.container_count, dir=self.tdir)
|
||||
|
@ -22,6 +22,7 @@ from calibre.utils.icu import sort_key
|
||||
TOP_ICON_SIZE = 24
|
||||
NAME_ROLE = Qt.UserRole
|
||||
CATEGORY_ROLE = NAME_ROLE + 1
|
||||
LINEAR_ROLE = CATEGORY_ROLE + 1
|
||||
NBSP = '\xa0'
|
||||
|
||||
class ItemDelegate(QStyledItemDelegate): # {{{
|
||||
@ -56,6 +57,7 @@ class ItemDelegate(QStyledItemDelegate): # {{{
|
||||
class FileList(QTreeWidget):
|
||||
|
||||
delete_requested = pyqtSignal(object, object)
|
||||
reorder_spine = pyqtSignal(object)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QTreeWidget.__init__(self, parent)
|
||||
@ -211,6 +213,7 @@ class FileList(QTreeWidget):
|
||||
item.setStatusTip(0, _('Full path: ') + name)
|
||||
item.setData(0, NAME_ROLE, name)
|
||||
item.setData(0, CATEGORY_ROLE, category)
|
||||
item.setData(0, LINEAR_ROLE, bool(linear))
|
||||
set_display_name(name, item)
|
||||
# TODO: Add appropriate tooltips based on the emblems
|
||||
emblems = []
|
||||
@ -294,11 +297,22 @@ class FileList(QTreeWidget):
|
||||
super(FileList, self).dropEvent(event)
|
||||
current_order = {text.child(i):i for i in xrange(text.childCount())}
|
||||
if current_order != pre_drop_order:
|
||||
pass # TODO: Implement this
|
||||
order = []
|
||||
for child in (text.child(i) for i in xrange(text.childCount())):
|
||||
name = unicode(child.data(0, NAME_ROLE).toString())
|
||||
linear = child.data(0, LINEAR_ROLE).toBool()
|
||||
order.append([name, linear])
|
||||
# Ensure that all non-linear items are at the end, any non-linear
|
||||
# items not at the end will be made linear
|
||||
for i, (name, linear) in tuple(enumerate(order)):
|
||||
if not linear and i < len(order) - 1 and order[i+1][1]:
|
||||
order[i][1] = True
|
||||
self.reorder_spine.emit(order)
|
||||
|
||||
class FileListWidget(QWidget):
|
||||
|
||||
delete_requested = pyqtSignal(object, object)
|
||||
reorder_spine = pyqtSignal(object)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
@ -306,7 +320,7 @@ class FileListWidget(QWidget):
|
||||
self.file_list = FileList(self)
|
||||
self.layout().addWidget(self.file_list)
|
||||
self.layout().setContentsMargins(0, 0, 0, 0)
|
||||
for x in ('delete_requested',):
|
||||
for x in ('delete_requested', 'reorder_spine'):
|
||||
getattr(self.file_list, x).connect(getattr(self, x))
|
||||
for x in ('delete_done',):
|
||||
setattr(self, x, getattr(self.file_list, x))
|
||||
|
Loading…
x
Reference in New Issue
Block a user