mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-10-31 02:27:01 -04:00 
			
		
		
		
	You can now change the cover or add formats to the currently selected book by Drag and Drop onto the book information display panel at the bottom. Fixes #3601 (Drag and Drop cover editing in main GUI)
This commit is contained in:
		
							parent
							
								
									e505743a25
								
							
						
					
					
						commit
						dc58e890bf
					
				| @ -124,17 +124,22 @@ class CopyButton(QPushButton): | ||||
| 
 | ||||
| 
 | ||||
|     def keyPressEvent(self, ev): | ||||
|         if ev.key() in self.ACTION_KEYS: | ||||
|             self.copied() | ||||
|         else: | ||||
|             QPushButton.event(self, ev) | ||||
|         try: | ||||
|             if ev.key() in self.ACTION_KEYS: | ||||
|                 self.copied() | ||||
|                 return | ||||
|         except: | ||||
|             pass | ||||
|         return QPushButton.event(self, ev) | ||||
| 
 | ||||
| 
 | ||||
|     def keyReleaseEvent(self, ev): | ||||
|         if ev.key() in self.ACTION_KEYS: | ||||
|         try: | ||||
|             if ev.key() in self.ACTION_KEYS: | ||||
|                 return | ||||
|         except: | ||||
|             pass | ||||
|         else: | ||||
|             QPushButton.event(self, ev) | ||||
|         return QPushButton.event(self, ev) | ||||
| 
 | ||||
|     def mouseReleaseEvent(self, ev): | ||||
|         ev.accept() | ||||
|  | ||||
| @ -30,7 +30,7 @@ from calibre.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \ | ||||
|                            max_available_height, config, info_dialog, \ | ||||
|                            available_width, GetMetadata | ||||
| from calibre.gui2.cover_flow import CoverFlow, DatabaseImages, pictureflowerror | ||||
| from calibre.gui2.widgets import ProgressIndicator | ||||
| from calibre.gui2.widgets import ProgressIndicator, IMAGE_EXTENSIONS | ||||
| from calibre.gui2.wizard import move_library | ||||
| from calibre.gui2.dialogs.scheduler import Scheduler | ||||
| from calibre.gui2.update import CheckForUpdates | ||||
| @ -220,6 +220,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): | ||||
|                 self.status_bar.job_done, Qt.QueuedConnection) | ||||
|         QObject.connect(self.status_bar, SIGNAL('show_book_info()'), | ||||
|                 self.show_book_info) | ||||
|         QObject.connect(self.status_bar, SIGNAL('files_dropped(PyQt_PyObject,PyQt_PyObject)'), | ||||
|                 self.files_dropped_on_book) | ||||
|         ####################### Setup Toolbar ##################### | ||||
|         md = QMenu() | ||||
|         md.addAction(_('Edit metadata individually')) | ||||
| @ -826,6 +828,31 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): | ||||
|         to_device = self.stack.currentIndex() != 0 | ||||
|         self._add_books(paths, to_device) | ||||
| 
 | ||||
|     def files_dropped_on_book(self, event, paths): | ||||
|         accept = False | ||||
|         if self.current_view() is not self.library_view: | ||||
|             return | ||||
|         db = self.library_view.model().db | ||||
|         current_idx = self.library_view.currentIndex() | ||||
|         if not current_idx.isValid(): return | ||||
|         cid = db.id(current_idx.row()) | ||||
|         for path in paths: | ||||
|             ext = os.path.splitext(path)[1].lower() | ||||
|             if ext: | ||||
|                 ext = ext[1:] | ||||
|             if ext in IMAGE_EXTENSIONS: | ||||
|                 pmap = QPixmap() | ||||
|                 pmap.load(path) | ||||
|                 if not pmap.isNull(): | ||||
|                     accept = True | ||||
|                     db.set_cover(cid, pmap) | ||||
|             elif ext in BOOK_EXTENSIONS: | ||||
|                 db.add_format_with_hooks(cid, ext, path, index_is_id=True) | ||||
|                 accept = True | ||||
|         if accept: | ||||
|             event.accept() | ||||
|             self.cover_cache.refresh([cid]) | ||||
|             self.library_view.model().current_changed(current_idx, current_idx) | ||||
| 
 | ||||
|     def add_filesystem_book(self, path): | ||||
|         if os.access(path, os.R_OK): | ||||
|  | ||||
| @ -1,14 +1,48 @@ | ||||
| __license__   = 'GPL v3' | ||||
| __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>' | ||||
| import re, collections | ||||
| import os, re, collections | ||||
| 
 | ||||
| from PyQt4.QtGui import QStatusBar, QMovie, QLabel, QWidget, QHBoxLayout, QPixmap, \ | ||||
|                         QVBoxLayout, QSizePolicy, QToolButton, QIcon, QScrollArea, QFrame | ||||
| from PyQt4.QtCore import Qt, QSize, SIGNAL, QCoreApplication | ||||
| from calibre import fit_image, preferred_encoding, isosx | ||||
| from calibre.gui2 import qstring_to_unicode, config | ||||
| from calibre.gui2.widgets import IMAGE_EXTENSIONS | ||||
| from calibre.ebooks import BOOK_EXTENSIONS | ||||
| 
 | ||||
| class BookInfoDisplay(QWidget): | ||||
| 
 | ||||
|     DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS+BOOK_EXTENSIONS | ||||
| 
 | ||||
|     @classmethod | ||||
|     def paths_from_event(cls, event): | ||||
|         ''' | ||||
|         Accept a drop event and return a list of paths that can be read from | ||||
|         and represent files with extensions. | ||||
|         ''' | ||||
|         if event.mimeData().hasFormat('text/uri-list'): | ||||
|             urls = [unicode(u.toLocalFile()) for u in event.mimeData().urls()] | ||||
|             urls = [u for u in urls if os.path.splitext(u)[1] and os.access(u, os.R_OK)] | ||||
|             return [u for u in urls if os.path.splitext(u)[1][1:].lower() in cls.DROPABBLE_EXTENSIONS] | ||||
| 
 | ||||
|     def dragEnterEvent(self, event): | ||||
|         if int(event.possibleActions() & Qt.CopyAction) + \ | ||||
|            int(event.possibleActions() & Qt.MoveAction) == 0: | ||||
|             return | ||||
|         paths = self.paths_from_event(event) | ||||
|         if paths: | ||||
|             event.acceptProposedAction() | ||||
| 
 | ||||
|     def dropEvent(self, event): | ||||
|         paths = self.paths_from_event(event) | ||||
|         event.setDropAction(Qt.CopyAction) | ||||
|         self.emit(SIGNAL('files_dropped(PyQt_PyObject, PyQt_PyObject)'), event, | ||||
|             paths) | ||||
| 
 | ||||
|     def dragMoveEvent(self, event): | ||||
|         event.acceptProposedAction() | ||||
| 
 | ||||
| 
 | ||||
|     class BookCoverDisplay(QLabel): | ||||
| 
 | ||||
|         WIDTH = 81 | ||||
| @ -184,15 +218,22 @@ class StatusBar(QStatusBar): | ||||
|         self.addPermanentWidget(self.tag_view_button) | ||||
|         self.addPermanentWidget(self.movie_button) | ||||
|         self.book_info = BookInfoDisplay(self.clearMessage) | ||||
|         self.book_info.setAcceptDrops(True) | ||||
|         self.scroll_area = QScrollArea() | ||||
|         self.scroll_area.setWidget(self.book_info) | ||||
|         self.scroll_area.setMaximumHeight(120) | ||||
|         self.scroll_area.setWidgetResizable(True) | ||||
|         self.connect(self.book_info, SIGNAL('show_book_info()'), self.show_book_info) | ||||
|         self.connect(self.book_info, | ||||
|                 SIGNAL('files_dropped(PyQt_PyObject,PyQt_PyObject)'), | ||||
|                     self.files_dropped, Qt.QueuedConnection) | ||||
|         self.addWidget(self.scroll_area, 100) | ||||
|         self.setMinimumHeight(120) | ||||
|         self.setMaximumHeight(120) | ||||
| 
 | ||||
|     def files_dropped(self, event, paths): | ||||
|         self.emit(SIGNAL('files_dropped(PyQt_PyObject, PyQt_PyObject)'), event, | ||||
|             paths) | ||||
| 
 | ||||
|     def reset_info(self): | ||||
|         self.book_info.show_data({}) | ||||
| @ -243,7 +284,6 @@ if __name__ == '__main__': | ||||
|     # Used to create the animated status icon | ||||
|     from PyQt4.Qt import QApplication, QPainter, QSvgRenderer, QColor | ||||
|     from subprocess import check_call | ||||
|     import os | ||||
|     app = QApplication([]) | ||||
| 
 | ||||
|     def create_pixmaps(path, size=16, delta=20): | ||||
|  | ||||
| @ -105,13 +105,13 @@ class FilenamePattern(QWidget, Ui_Form): | ||||
|         return pat | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'gif', 'png', 'bmp'] | ||||
| 
 | ||||
| class ImageView(QLabel): | ||||
| 
 | ||||
|     MAX_WIDTH  = 400 | ||||
|     MAX_HEIGHT = 300 | ||||
|     DROPABBLE_EXTENSIONS = ('jpg', 'jpeg', 'gif', 'png', 'bmp') | ||||
|     DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS | ||||
| 
 | ||||
|     @classmethod | ||||
|     def paths_from_event(cls, event): | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user