From e26df3b5298fd6e333a84e33f5c15039a1e2cfe8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 6 Sep 2023 08:39:05 +0530 Subject: [PATCH] Allow right click to adjust image alignment --- src/calibre/gui2/comments_editor.py | 33 +++++++++++++++++-- .../gui2/dialogs/edit_category_notes.py | 10 +++--- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/calibre/gui2/comments_editor.py b/src/calibre/gui2/comments_editor.py index de29ace1a8..be3b320022 100644 --- a/src/calibre/gui2/comments_editor.py +++ b/src/calibre/gui2/comments_editor.py @@ -7,6 +7,7 @@ import re import weakref from collections import defaultdict from contextlib import contextmanager +from functools import partial from html5_parser import parse from lxml import html from qt.core import ( @@ -14,8 +15,8 @@ from qt.core import ( QDialogButtonBox, QFont, QFontInfo, QFontMetrics, QFormLayout, QHBoxLayout, QIcon, QKeySequence, QLabel, QLineEdit, QMenu, QPalette, QPlainTextEdit, QPushButton, QSize, QSyntaxHighlighter, Qt, QTabWidget, QTextBlockFormat, QTextCharFormat, - QTextCursor, QTextEdit, QTextFormat, QTextListFormat, QTimer, QToolButton, QUrl, - QVBoxLayout, QWidget, pyqtSignal, pyqtSlot, + QTextCursor, QTextEdit, QTextFormat, QTextFrameFormat, QTextListFormat, QTimer, + QToolButton, QUrl, QVBoxLayout, QWidget, pyqtSignal, pyqtSlot, ) from calibre import xml_replace_entities @@ -892,8 +893,36 @@ class EditorWidget(QTextEdit, LineEditECM): # {{{ ans.setHtml(html) return ans + def align_image_at(self, cursor_pos, alignment): + c = self.textCursor() + c.setPosition(cursor_pos) + fmt = c.charFormat() + if fmt.isImageFormat() and c.currentFrame(): + cf = c.currentFrame().childFrames() + if len(cf) == 1: + ff = cf[0].frameFormat() + ff.setPosition(alignment) + cf[0].setFrameFormat(ff) + self.document().markContentsDirty(cursor_pos-2, 5) + def contextMenuEvent(self, ev): menu = QMenu(self) + c = self.cursorForPosition(ev.pos()) + fmt = c.charFormat() + if fmt.isImageFormat() and c.currentFrame(): + cf = c.currentFrame().childFrames() + if len(cf) == 1: + pos = cf[0].frameFormat().position() + align_menu = menu.addMenu(QIcon.ic('view-image.png'), _('Change image alignment...')) + def a(text, epos): + ac = align_menu.addAction(text) + ac.setCheckable(True) + ac.triggered.connect(partial(self.align_image_at, c.position(), epos)) + if pos == epos: + ac.setChecked(True) + a(_('Float to the left'), QTextFrameFormat.Position.FloatLeft) + a(_('Inline with text'), QTextFrameFormat.Position.InFlow) + a(_('Float to the right'), QTextFrameFormat.Position.FloatRight) for ac in 'undo redo -- cut copy paste paste_and_match_style -- select_all'.split(): if ac == '--': menu.addSeparator() diff --git a/src/calibre/gui2/dialogs/edit_category_notes.py b/src/calibre/gui2/dialogs/edit_category_notes.py index 3556cc196d..3866ff1273 100644 --- a/src/calibre/gui2/dialogs/edit_category_notes.py +++ b/src/calibre/gui2/dialogs/edit_category_notes.py @@ -118,6 +118,7 @@ class AskImage(Dialog): hb.addWidget(b) vr.addStretch(10) + self.add_file_button.setFocus(Qt.FocusReason.OtherFocusReason) def image_pasted_or_dropped(self, cover_data): digest = hash_data(cover_data) @@ -146,6 +147,7 @@ class AskImage(Dialog): self.image_preview.set_pixmap(p) self.name_edit.setText(ir.name) self.current_digest = digest + self.bb.setFocus(Qt.FocusReason.OtherFocusReason) def paste_image(self): if not self.image_preview.paste_from_clipboard(): @@ -202,10 +204,10 @@ class NoteEditorWidget(EditorWidget): if d.exec() == QDialog.DialogCode.Accepted and d.current_digest: ir = self.images[d.current_digest] self.focus_self() - with self.editing_cursor() as c: - fmt = QTextImageFormat() - fmt.setName(RESOURCE_URL_SCHEME + ':///' + ir.digest) - c.insertImage(fmt, d.image_layout) + c = self.textCursor() + fmt = QTextImageFormat() + fmt.setName(RESOURCE_URL_SCHEME + ':///' + ir.digest) + c.insertImage(fmt, d.image_layout) class NoteEditor(Editor):