From 43dd6a34d980131c0a99f7ec783e9aa289889af8 Mon Sep 17 00:00:00 2001 From: BasioMeusPuga Date: Fri, 30 Mar 2018 20:48:13 +0530 Subject: [PATCH] Implement basic annotation editor / preview --- lector/resources/raw/settings.ui | 228 +++++++++++++++++++++++++++++ lector/resources/settingswindow.py | 105 ++++++++++++- lector/settingsdialog.py | 135 +++++++++++++++++ 3 files changed, 466 insertions(+), 2 deletions(-) diff --git a/lector/resources/raw/settings.ui b/lector/resources/raw/settings.ui index 6ade5ef..a79a80b 100644 --- a/lector/resources/raw/settings.ui +++ b/lector/resources/raw/settings.ui @@ -265,6 +265,234 @@ Reopen book to see changes Text + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 30 + 0 + + + + + 45 + 16777215 + + + + + + + + + + + + + 0 + 0 + + + + + 30 + 0 + + + + + 45 + 16777215 + + + + - + + + + + + + + 0 + 0 + + + + + 30 + 0 + + + + + 45 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + + 30 + 0 + + + + + 45 + 16777215 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Foreground + + + + + + + Highlight + + + + + + + Bold + + + + + + + Italic + + + + + + + Underline + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 100 + + + + + + + diff --git a/lector/resources/settingswindow.py b/lector/resources/settingswindow.py index aac8845..947f670 100644 --- a/lector/resources/settingswindow.py +++ b/lector/resources/settingswindow.py @@ -153,6 +153,98 @@ class Ui_Dialog(object): self.tabWidget.setObjectName("tabWidget") self.textTab = QtWidgets.QWidget() self.textTab.setObjectName("textTab") + self.gridLayout_8 = QtWidgets.QGridLayout(self.textTab) + self.gridLayout_8.setObjectName("gridLayout_8") + self.verticalLayout_5 = QtWidgets.QVBoxLayout() + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.horizontalLayout_11 = QtWidgets.QHBoxLayout() + self.horizontalLayout_11.setObjectName("horizontalLayout_11") + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_6.addItem(spacerItem1) + self.newAnnotation = QtWidgets.QPushButton(self.textTab) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.newAnnotation.sizePolicy().hasHeightForWidth()) + self.newAnnotation.setSizePolicy(sizePolicy) + self.newAnnotation.setMinimumSize(QtCore.QSize(30, 0)) + self.newAnnotation.setMaximumSize(QtCore.QSize(45, 16777215)) + self.newAnnotation.setObjectName("newAnnotation") + self.verticalLayout_6.addWidget(self.newAnnotation) + self.deleteAnnotation = QtWidgets.QPushButton(self.textTab) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.deleteAnnotation.sizePolicy().hasHeightForWidth()) + self.deleteAnnotation.setSizePolicy(sizePolicy) + self.deleteAnnotation.setMinimumSize(QtCore.QSize(30, 0)) + self.deleteAnnotation.setMaximumSize(QtCore.QSize(45, 16777215)) + self.deleteAnnotation.setObjectName("deleteAnnotation") + self.verticalLayout_6.addWidget(self.deleteAnnotation) + self.moveUp = QtWidgets.QPushButton(self.textTab) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.moveUp.sizePolicy().hasHeightForWidth()) + self.moveUp.setSizePolicy(sizePolicy) + self.moveUp.setMinimumSize(QtCore.QSize(30, 0)) + self.moveUp.setMaximumSize(QtCore.QSize(45, 16777215)) + self.moveUp.setObjectName("moveUp") + self.verticalLayout_6.addWidget(self.moveUp) + self.moveDown = QtWidgets.QPushButton(self.textTab) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.moveDown.sizePolicy().hasHeightForWidth()) + self.moveDown.setSizePolicy(sizePolicy) + self.moveDown.setMinimumSize(QtCore.QSize(30, 0)) + self.moveDown.setMaximumSize(QtCore.QSize(45, 16777215)) + self.moveDown.setObjectName("moveDown") + self.verticalLayout_6.addWidget(self.moveDown) + spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_6.addItem(spacerItem2) + self.horizontalLayout_11.addLayout(self.verticalLayout_6) + self.annotationsList = QtWidgets.QListView(self.textTab) + self.annotationsList.setObjectName("annotationsList") + self.horizontalLayout_11.addWidget(self.annotationsList) + self.verticalLayout_8 = QtWidgets.QVBoxLayout() + self.verticalLayout_8.setObjectName("verticalLayout_8") + spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_8.addItem(spacerItem3) + self.foregroundCheck = QtWidgets.QCheckBox(self.textTab) + self.foregroundCheck.setObjectName("foregroundCheck") + self.verticalLayout_8.addWidget(self.foregroundCheck) + self.highlightCheck = QtWidgets.QCheckBox(self.textTab) + self.highlightCheck.setObjectName("highlightCheck") + self.verticalLayout_8.addWidget(self.highlightCheck) + self.boldCheck = QtWidgets.QCheckBox(self.textTab) + self.boldCheck.setObjectName("boldCheck") + self.verticalLayout_8.addWidget(self.boldCheck) + self.italicCheck = QtWidgets.QCheckBox(self.textTab) + self.italicCheck.setObjectName("italicCheck") + self.verticalLayout_8.addWidget(self.italicCheck) + self.underlineCheck = QtWidgets.QCheckBox(self.textTab) + self.underlineCheck.setObjectName("underlineCheck") + self.verticalLayout_8.addWidget(self.underlineCheck) + spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_8.addItem(spacerItem4) + self.horizontalLayout_11.addLayout(self.verticalLayout_8) + self.verticalLayout_5.addLayout(self.horizontalLayout_11) + self.gridLayout_8.addLayout(self.verticalLayout_5, 0, 0, 1, 1) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.previewView = QtWidgets.QTextBrowser(self.textTab) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.previewView.sizePolicy().hasHeightForWidth()) + self.previewView.setSizePolicy(sizePolicy) + self.previewView.setMaximumSize(QtCore.QSize(16777215, 100)) + self.previewView.setObjectName("previewView") + self.horizontalLayout_2.addWidget(self.previewView) + self.gridLayout_8.addLayout(self.horizontalLayout_2, 1, 0, 1, 1) self.tabWidget.addTab(self.textTab, "") self.imageTab = QtWidgets.QWidget() self.imageTab.setObjectName("imageTab") @@ -172,8 +264,8 @@ class Ui_Dialog(object): self.verticalLayout_4.addWidget(self.stackedWidget) self.horizontalLayout_10 = QtWidgets.QHBoxLayout() self.horizontalLayout_10.setObjectName("horizontalLayout_10") - spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_10.addItem(spacerItem1) + spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_10.addItem(spacerItem5) self.okButton = QtWidgets.QPushButton(Dialog) self.okButton.setObjectName("okButton") self.horizontalLayout_10.addWidget(self.okButton) @@ -211,6 +303,15 @@ class Ui_Dialog(object): self.cachingEnabled.setText(_translate("Dialog", "Cache comic / pdf pages")) self.languageLabel.setText(_translate("Dialog", "Dictionary language")) self.scrollSpeedLabel.setText(_translate("Dialog", "Scroll speed")) + self.newAnnotation.setText(_translate("Dialog", "+")) + self.deleteAnnotation.setText(_translate("Dialog", "-")) + self.moveUp.setText(_translate("Dialog", "⬆")) + self.moveDown.setText(_translate("Dialog", "⬇")) + self.foregroundCheck.setText(_translate("Dialog", "Foreground")) + self.highlightCheck.setText(_translate("Dialog", "Highlight")) + self.boldCheck.setText(_translate("Dialog", "Bold")) + self.italicCheck.setText(_translate("Dialog", "Italic")) + self.underlineCheck.setText(_translate("Dialog", "Underline")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.textTab), _translate("Dialog", "Text")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.imageTab), _translate("Dialog", "Comic/PDF")) self.okButton.setText(_translate("Dialog", "Scan Library")) diff --git a/lector/settingsdialog.py b/lector/settingsdialog.py index 7c3b6eb..15b9293 100644 --- a/lector/settingsdialog.py +++ b/lector/settingsdialog.py @@ -119,6 +119,22 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog): self.listView.setModel(self.listModel) self.listView.clicked.connect(self.page_switch) + # Generate annotation settings + self.annotations_list = [] + self.generate_annotations() + + # Init colors + self.default_stylesheet = self.foregroundCheck.styleSheet() + self.foreground = QtGui.QColor.fromRgb(0, 0, 0) + self.highlight = QtGui.QColor.fromRgb(255, 255, 255) + + # Connect annotation related checkboxes + self.foregroundCheck.clicked.connect(self.format_checkboxes) + self.highlightCheck.clicked.connect(self.format_checkboxes) + self.boldCheck.clicked.connect(self.format_checkboxes) + self.italicCheck.clicked.connect(self.format_checkboxes) + self.underlineCheck.clicked.connect(self.format_checkboxes) + # Generate the filesystem treeView self.generate_tree() @@ -273,6 +289,7 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog): event.accept() def showEvent(self, event): + self.format_preview() self.tag_data_copy = copy.deepcopy(self.filesystem_model.tag_data) event.accept() @@ -320,3 +337,121 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog): if not self.performCulling.isChecked(): self.parent.cover_functions.load_all_covers() + + def generate_annotations(self): + annotations_model = QtGui.QStandardItemModel() + items_list = ['Sample annotation'] + + for i in items_list: + # TODO + # Set annotation types to user roles + + item = QtGui.QStandardItem() + item.setText(i) + annotations_model.appendRow(item) + + self.annotationsList.setModel(annotations_model) + + def format_preview(self): + self.previewView.setText('Vidistine nuper imagines moventes bonas?') + profile_index = self.parent.bookToolBar.profileBox.currentIndex() + current_profile = self.parent.bookToolBar.profileBox.itemData( + profile_index, QtCore.Qt.UserRole) + + if not current_profile: + return + + font = current_profile['font'] + self.foreground = current_profile['foreground'] + background = current_profile['background'] + font_size = current_profile['font_size'] + + self.previewView.setStyleSheet( + "QTextEdit {{font-family: {0}; font-size: {1}px; color: {2}; background-color: {3}}}".format( + font, font_size, self.foreground.name(), background.name())) + + block_format = QtGui.QTextBlockFormat() + block_format.setAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter) + + cursor = self.previewView.textCursor() + while True: + old_position = cursor.position() + cursor.mergeBlockFormat(block_format) + cursor.movePosition(QtGui.QTextCursor.NextBlock, 0, 1) + new_position = cursor.position() + if old_position == new_position: + break + + def update_preview(self): + cursor = self.previewView.textCursor() + cursor.setPosition(0) + cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.KeepAnchor) + + # TODO + # Other kinds of text markup + previewCharFormat = QtGui.QTextCharFormat() + + if self.foregroundCheck.isChecked(): + previewCharFormat.setForeground(self.foreground) + + highlight = QtCore.Qt.transparent + if self.highlightCheck.isChecked(): + highlight = self.highlight + previewCharFormat.setBackground(highlight) + + font_weight = QtGui.QFont.Normal + if self.boldCheck.isChecked(): + font_weight = QtGui.QFont.Bold + previewCharFormat.setFontWeight(font_weight) + + font_italic = False + if self.italicCheck.isChecked(): + font_italic = True + previewCharFormat.setFontItalic(font_italic) + + font_underline = False + if self.underlineCheck.isChecked(): + font_underline = True + previewCharFormat.setFontUnderline(font_underline) + + previewCharFormat.setFontStyleStrategy( + QtGui.QFont.PreferAntialias) + + cursor.setCharFormat(previewCharFormat) + cursor.clearSelection() + self.previewView.setTextCursor(cursor) + + def format_checkboxes(self): + sender = self.sender() + if not sender.isChecked(): + sender.setStyleSheet(self.default_stylesheet) + self.update_preview() + return + + if sender == self.foregroundCheck: + new_color = self.get_color(self.foreground) + self.foregroundCheck.setStyleSheet( + "QCheckBox {{color: {0}; border: none;}}".format(new_color.name())) + self.foreground = new_color + + if sender == self.highlightCheck: + new_color = self.get_color(self.highlight) + self.highlightCheck.setStyleSheet( + "QCheckBox {{background-color: {0}}}".format(new_color.name())) + self.highlight = new_color + + # TODO + # See if QCheckboxes support this + if sender == self.boldCheck: + self.boldCheck.setStyleSheet( + "QCheckBox {{font-weight: bold;}}") + + self.update_preview() + + def get_color(self, current_color): + color_dialog = QtWidgets.QColorDialog() + new_color = color_dialog.getColor(current_color) + if new_color.isValid(): # Returned in case cancel is pressed + return new_color + else: + return current_color