mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
When deleting books from the library if a device is connected and the books are also present on the device ask the user if the books should be deleted from the device, the library, or both.
This commit is contained in:
commit
023a97a4b5
@ -12,6 +12,7 @@ from PyQt4.Qt import QMenu, QObject, QTimer
|
||||
from calibre.gui2 import error_dialog
|
||||
from calibre.gui2.dialogs.delete_matching_from_device import DeleteMatchingFromDeviceDialog
|
||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||
from calibre.gui2.dialogs.confirm_delete_location import confirm_location
|
||||
from calibre.gui2.actions import InterfaceAction
|
||||
|
||||
single_shot = partial(QTimer.singleShot, 10)
|
||||
@ -223,7 +224,31 @@ class DeleteAction(InterfaceAction):
|
||||
rows = view.selectionModel().selectedRows()
|
||||
if not rows or len(rows) == 0:
|
||||
return
|
||||
# Library view is visible.
|
||||
if self.gui.stack.currentIndex() == 0:
|
||||
# Ask the user if they want to delete the book from the library or device if it is in both.
|
||||
if self.gui.device_manager.is_device_connected:
|
||||
on_device = False
|
||||
on_device_ids = self._get_selected_ids()
|
||||
for id in on_device_ids:
|
||||
res = self.gui.book_on_device(id)
|
||||
if res[0] or res[1] or res[2]:
|
||||
on_device = True
|
||||
if on_device:
|
||||
break
|
||||
if on_device:
|
||||
loc = confirm_location('<p>' + _('Some of the selected books are on the attached device. '
|
||||
'<b>Where</b> do you want the selected files deleted from?'),
|
||||
self.gui)
|
||||
if not loc:
|
||||
return
|
||||
elif loc == 'dev':
|
||||
self.remove_matching_books_from_device()
|
||||
return
|
||||
elif loc == 'both':
|
||||
self.remove_matching_books_from_device()
|
||||
# The following will run if the selected books are not on a connected device.
|
||||
# The user has selected to delete from the library or the device and library.
|
||||
if not confirm('<p>'+_('The selected books will be '
|
||||
'<b>permanently deleted</b> and the files '
|
||||
'removed from your calibre library. Are you sure?')
|
||||
@ -239,7 +264,7 @@ class DeleteAction(InterfaceAction):
|
||||
else:
|
||||
self.__md = MultiDeleter(self.gui, rows,
|
||||
partial(self.library_ids_deleted, current_row=row))
|
||||
|
||||
# Device view is visible.
|
||||
else:
|
||||
if not confirm('<p>'+_('The selected books will be '
|
||||
'<b>permanently deleted</b> '
|
||||
|
51
src/calibre/gui2/dialogs/confirm_delete_location.py
Normal file
51
src/calibre/gui2/dialogs/confirm_delete_location.py
Normal file
@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' \
|
||||
'2010, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from functools import partial
|
||||
|
||||
from calibre.gui2.dialogs.confirm_delete_location_ui import Ui_Dialog
|
||||
from PyQt4.Qt import QDialog, Qt, QPixmap, QIcon
|
||||
|
||||
class Dialog(QDialog, Ui_Dialog):
|
||||
|
||||
def __init__(self, msg, name, parent):
|
||||
QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.loc = None
|
||||
self.msg.setText(msg)
|
||||
self.name = name
|
||||
self.buttonBox.setFocus(Qt.OtherFocusReason)
|
||||
self.button_lib.clicked.connect(partial(self.set_loc, 'lib'))
|
||||
self.button_device.clicked.connect(partial(self.set_loc, 'dev'))
|
||||
self.button_both.clicked.connect(partial(self.set_loc, 'both'))
|
||||
|
||||
def set_loc(self, loc):
|
||||
self.loc = loc
|
||||
self.accept()
|
||||
|
||||
def choice(self):
|
||||
return self.loc
|
||||
|
||||
def break_cycles(self):
|
||||
for x in ('lib', 'device', 'both'):
|
||||
b = getattr(self, 'button_'+x)
|
||||
try:
|
||||
b.clicked.disconnect()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def confirm_location(msg, name, parent=None, pixmap='dialog_warning.png'):
|
||||
d = Dialog(msg, name, parent)
|
||||
d.label.setPixmap(QPixmap(I(pixmap)))
|
||||
d.setWindowIcon(QIcon(I(pixmap)))
|
||||
d.resize(d.sizeHint())
|
||||
ret = d.exec_()
|
||||
d.break_cycles()
|
||||
if ret == d.Accepted:
|
||||
return d.choice()
|
||||
return None
|
116
src/calibre/gui2/dialogs/confirm_delete_location.ui
Normal file
116
src/calibre/gui2/dialogs/confirm_delete_location.ui
Normal file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>459</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Where do you want to delete from?</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../../../resources/images.qrc">
|
||||
<normaloff>:/images/dialog_warning.png</normaloff>:/images/dialog_warning.png</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../../../../resources/images.qrc">:/images/dialog_warning.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="msg">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_lib">
|
||||
<property name="text">
|
||||
<string>Library</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_device">
|
||||
<property name="text">
|
||||
<string>Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_both">
|
||||
<property name="text">
|
||||
<string>Library and Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../../resources/images.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -123,8 +123,8 @@ class BooksView(QTableView): # {{{
|
||||
elif action == 'show':
|
||||
h.setSectionHidden(idx, False)
|
||||
if h.sectionSize(idx) < 3:
|
||||
sz = h.sectionSizeHint(idx)
|
||||
h.resizeSection(idx, sz)
|
||||
sz = h.sectionSizeHint(idx)
|
||||
h.resizeSection(idx, sz)
|
||||
elif action == 'ascending':
|
||||
self.sortByColumn(idx, Qt.AscendingOrder)
|
||||
elif action == 'descending':
|
||||
|
Loading…
x
Reference in New Issue
Block a user