diff --git a/src/presentation/modules/CppElements/page_view.cpp b/src/presentation/modules/CppElements/page_view.cpp index 4d59f94df..62268ac75 100644 --- a/src/presentation/modules/CppElements/page_view.cpp +++ b/src/presentation/modules/CppElements/page_view.cpp @@ -212,7 +212,7 @@ void PageView::mousePressEvent(QMouseEvent* event) void PageView::handleClickingOnHighlight(const Highlight* highlight) { // Scale the highlight rects (initially zoom of 1) to the current zoom and - // get the center x and top y position of the highlight. + // get the center x and bottom y position of the highlight. auto rects = highlight->getRects(); QList qRects; qRects.reserve(rects.size()); @@ -223,7 +223,7 @@ void PageView::handleClickingOnHighlight(const Highlight* highlight) qRectF, m_pageController->getZoom() / window()->devicePixelRatio()); qRects.append(qRectF); } - auto positions = getCenterXAndTopYFromRects(qRects); + auto positions = getCenterXAndBottomYFromRects(qRects); auto uuidAsString = highlight->getUuid().toString(QUuid::WithoutBraces); m_bookController->highlightSelected(positions.first, positions.second, @@ -270,7 +270,7 @@ void PageView::mouseReleaseEvent(QMouseEvent* event) restoredRects.push_back(rect); } - auto positions = getCenterXAndTopYFromRects(restoredRects); + auto positions = getCenterXAndBottomYFromRects(restoredRects); emit m_bookController->textSelectionFinished(positions.first, positions.second); @@ -279,12 +279,12 @@ void PageView::mouseReleaseEvent(QMouseEvent* event) m_doubleClickHold = false; } -QPair PageView::getCenterXAndTopYFromRects( +QPair PageView::getCenterXAndBottomYFromRects( const QList& rects) { float mostLeftX = std::numeric_limits::max(); float mostRightX = 0; - float topY = std::numeric_limits::max(); + float bottomY = 0; for(auto& rect : rects) { if(rect.x() < mostLeftX) @@ -293,12 +293,12 @@ QPair PageView::getCenterXAndTopYFromRects( if(rect.x() + rect.width() > mostRightX) mostRightX = rect.x() + rect.width(); - if(rect.top() < topY) - topY = rect.top(); + if(rect.bottom() > bottomY) + bottomY = rect.bottom(); } auto centerX = (mostLeftX + mostRightX) / 2; - return { centerX, topY }; + return { centerX, bottomY }; } void PageView::mouseMoveEvent(QMouseEvent* event) diff --git a/src/presentation/modules/CppElements/page_view.hpp b/src/presentation/modules/CppElements/page_view.hpp index eff75a8a3..75d1130ab 100644 --- a/src/presentation/modules/CppElements/page_view.hpp +++ b/src/presentation/modules/CppElements/page_view.hpp @@ -99,7 +99,7 @@ private slots: void setCorrectCursor(int x, int y); bool rectsAreOnSameLine(const QRectF& rect1, const QRectF& rect2); - QPair getCenterXAndTopYFromRects(const QList& rects); + QPair getCenterXAndBottomYFromRects(const QList& rects); std::unique_ptr m_pageController; adapters::IBookController* m_bookController = nullptr; diff --git a/src/presentation/qmlSources.qrc b/src/presentation/qmlSources.qrc index b43d11589..fb14ad156 100644 --- a/src/presentation/qmlSources.qrc +++ b/src/presentation/qmlSources.qrc @@ -93,7 +93,6 @@ modules/CustomComponents/MConfirmAccountDeletionPopup.qml settings/updatesPage/MWindowsUpdatingPopup.qml readingPage/MSelectionOptionsPopup.qml - readingPage/MColorSelectionPopup.qml modules/CustomComponents/MSlider.qml readingPage/MDictionaryPopup.qml readingPage/MBookmarkItem.qml diff --git a/src/presentation/readingPage/MColorSelectionPopup.qml b/src/presentation/readingPage/MColorSelectionPopup.qml deleted file mode 100644 index 51681283c..000000000 --- a/src/presentation/readingPage/MColorSelectionPopup.qml +++ /dev/null @@ -1,121 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import Librum.style -import Librum.icons -import Librum.controllers - -Popup -{ - id: root - property string highlight: "" - signal colorSelected(color color) - - width: selectionOptionsLayout.width - height: 32 - padding: 0 - background: Rectangle - { - color: Style.colorControlBackground - radius: 4 - border.width: 1 - border.color: Style.colorContainerBorder - } - - Image - { - id: triangleDecoration - x: parent.width / 2 - implicitWidth / 2 - y: parent.y + parent.height - 1 - source: Icons.popupDroplet - rotation: 180 - } - - RowLayout - { - id: selectionOptionsLayout - height: parent.height - spacing: 0 - - component ColorItem: Rectangle - { - id: colorItem - property string colorName - - Layout.fillHeight: true - Layout.preferredWidth: 38 - color: "transparent" - - Rectangle - { - width: parent.width / 2.8 - height: width - anchors.centerIn: parent - radius: width - color: SettingsController.appearanceSettings[colorItem.colorName] - } - - MouseArea - { - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onContainsMouseChanged: activeFocusItem.setPointingCursor() - - onClicked: - { - // Change highlight color - activeFocusItem.changeHighlightColor(colorSelectionPopup.highlight, - SettingsController.appearanceSettings[colorItem.colorName], - SettingsController.appearanceSettings.HighlightOpacity); - - // Remember the last color used - SettingsController.setSetting(SettingKeys.DefaultHighlightColorName, - colorItem.colorName, - SettingGroups.Appearance); - root.close(); - } - } - } - - component Separator: Rectangle - { - Layout.fillHeight: true - Layout.preferredWidth: 2 - color: Style.colorSeparator - } - - ColorItem - { - colorName: "HighlightColorA" - } - - Separator {} - - ColorItem - { - colorName: "HighlightColorB" - } - - Separator {} - - ColorItem - { - colorName: "HighlightColorC" - } - - Separator {} - - ColorItem - { - colorName: "HighlightColorD" - } - - Separator {} - - ColorItem - { - colorName: "HighlightColorE" - } - } -} \ No newline at end of file diff --git a/src/presentation/readingPage/MDocumentView.qml b/src/presentation/readingPage/MDocumentView.qml index 5014800a2..69d1a3bb6 100644 --- a/src/presentation/readingPage/MDocumentView.qml +++ b/src/presentation/readingPage/MDocumentView.qml @@ -155,13 +155,9 @@ Pane { onContentYChanged: { NavigationLogic.updateCurrentPageCounter() selectionOptionsPopup.close() - colorSelectionPopup.close() } - onContentXChanged: { - selectionOptionsPopup.close() - colorSelectionPopup.close() - } + onContentXChanged: selectionOptionsPopup.close() Component.onCompleted: root.setPage(root.bookController.currentPage) @@ -238,33 +234,16 @@ Pane { MSelectionOptionsPopup { id: selectionOptionsPopup property real highlightCenterX - property real highlightTopY + property real highlightBottomY onNewWidth: internal.openSelectionOptionsPopup(-1, -1) - onHighlightOptionSelected: uuid => { - if (selectionOptionsPopup.highlight == "") - colorSelectionPopup.highlight = uuid - else - colorSelectionPopup.highlight - = selectionOptionsPopup.highlight - - internal.openPopupAt( - colorSelectionPopup, - selectionOptionsPopup.highlightCenterX, - selectionOptionsPopup.highlightTopY) - } - onExplanationOptionSelected: text => { explanationPopup.question = text explanationPopup.open() } } - MColorSelectionPopup { - id: colorSelectionPopup - } - MDictionaryPopup { id: dictionaryPopup } @@ -319,22 +298,22 @@ Pane { id: internal property string optionNameCursorModeHiddenAfterDelay: "Hidden after delay" - function openSelectionOptionsPopup(centerX, topY) { - if (centerX === -1 && topY === -1) { + function openSelectionOptionsPopup(centerX, bottomY) { + if (centerX === -1 && bottomY === -1) { centerX = selectionOptionsPopup.highlightCenterX - topY = selectionOptionsPopup.highlightTopY + bottomY = selectionOptionsPopup.highlightBottomY } selectionOptionsPopup.highlightCenterX = centerX - selectionOptionsPopup.highlightTopY = topY + selectionOptionsPopup.highlightBottomY = bottomY - internal.openPopupAt(selectionOptionsPopup, centerX, topY) + internal.openPopupAt(selectionOptionsPopup, centerX, bottomY) } - function openPopupAt(popup, centerX, topY) { + function openPopupAt(popup, centerX, bottomY) { let pageYOffset = pageView.contentY - activeFocusItem.y let pageXOffset = pageView.contentX - activeFocusItem.x let posX = centerX + pageView.x - popup.width / 2 - pageXOffset - let posY = topY - popup.height - pageYOffset - 6 + let posY = bottomY + -pageYOffset + 6 let spaceToRight = (pageView.x + pageView.width) - (posX + popup.width) if (spaceToRight < 0) diff --git a/src/presentation/readingPage/MSelectionOptionsPopup.qml b/src/presentation/readingPage/MSelectionOptionsPopup.qml index 94eaf636b..3133090fd 100644 --- a/src/presentation/readingPage/MSelectionOptionsPopup.qml +++ b/src/presentation/readingPage/MSelectionOptionsPopup.qml @@ -11,13 +11,12 @@ Popup { id: root property string highlight: "" signal newWidth - signal highlightOptionSelected(string uuid) signal dictionaryOptionSelected(string word) signal explanationOptionSelected(string word) - width: selectionOptionsListView.width - height: 32 padding: 0 + width: layout.width + height: layout.height background: Rectangle { color: Style.colorControlBackground radius: 4 @@ -25,8 +24,6 @@ Popup { border.color: Style.colorContainerBorder } - onOpened: selectionOptionsListView.model - = (baseRoot.externalBookMode ? externalBookActionPage : firstActionsPage) onClosed: root.highlight = "" Shortcut { @@ -50,278 +47,174 @@ Popup { Image { id: triangleDecoration x: parent.width / 2 - implicitWidth / 2 - y: parent.y + parent.height - 1 + y: -5 - root.verticalPadding source: Icons.popupDroplet - rotation: 180 } - ListView { - id: selectionOptionsListView - property bool firstTimeOpened: true - - width: contentWidth - height: parent.height - orientation: ListView.Horizontal - spacing: 2 - model: baseRoot.externalBookMode ? externalBookActionPage : firstActionsPage - boundsBehavior: Flickable.StopAtBounds - - onModelChanged: { - // Prevent the selection popup being opened on initialization - if (firstTimeOpened) { - firstTimeOpened = false - return - } - - selectionOptionsListView.forceLayout() - root.newWidth() - } - } - - component SelectionOptionsPopupItem: Rectangle { - id: action - property string text - property color textColor: Style.colorText - property var clickedFunction: function () {} - - height: selectionOptionsListView.height - implicitWidth: actionText.implicitWidth - color: "transparent" - opacity: actionArea.pressed ? 0.8 : 1 - - Label { - id: actionText - height: parent.height - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - padding: 10 - text: action.text - color: action.textColor - font.pointSize: Fonts.size12 - } - - MouseArea { - id: actionArea - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - hoverEnabled: true - - onClicked: { - action.clickedFunction() + ColumnLayout { + id: layout + spacing: 6 + + RowLayout { + id: highlightRow + Layout.leftMargin: 10 + Layout.rightMargin: 10 + Layout.topMargin: 8 + spacing: 0 + + component ColorItem: Rectangle { + id: colorItem + property string colorName + Layout.preferredHeight: 26 + Layout.preferredWidth: 26 + color: "transparent" + + Rectangle { + width: 15 + height: width + anchors.centerIn: parent + radius: width + color: SettingsController.appearanceSettings[colorItem.colorName] + } - root.close() + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onContainsMouseChanged: activeFocusItem.setPointingCursor() + + onClicked: { + let uuid = root.highlight + if (root.highlight == "") { + uuid = internal.createHighlight() + } + + // Change highlight color + activeFocusItem.changeHighlightColor( + uuid, + SettingsController.appearanceSettings[colorItem.colorName], + SettingsController.appearanceSettings.HighlightOpacity) + + // Remember the last color used + SettingsController.setSetting( + SettingKeys.DefaultHighlightColorName, + colorItem.colorName, + SettingGroups.Appearance) + + root.close() + } + } } - } - } - component Separator: Rectangle { - y: 1 // Move one down - height: selectionOptionsListView.height - 2 - implicitWidth: 2 - color: Style.colorSeparator - } + ColorItem { + colorName: "HighlightColorA" + } - ObjectModel { - id: firstActionsPage - - SelectionOptionsPopupItem { - id: copyAction - text: qsTr("Copy") - clickedFunction: function () { - if (root.highlight == "") - activeFocusItem.copySelectedText() - else - activeFocusItem.copyHighlightedText(root.highlight) + ColorItem { + colorName: "HighlightColorB" } - } - Separator {} - - SelectionOptionsPopupItem { - id: highlightAction - text: qsTr("Highlight") - visible: !baseRoot.externalBookMode - clickedFunction: function () { - // We do not want to create a new highlight when clicking on - // one and selecting the "Highlight" option to edit it. - let uuid = root.highlight - if (root.highlight == "") { - uuid = internal.createHighlight() - } + ColorItem { + colorName: "HighlightColorC" + } - root.highlightOptionSelected(uuid) + ColorItem { + colorName: "HighlightColorD" } - } - Separator {} - - SelectionOptionsPopupItem { - id: lookUpAction - text: qsTr("Look Up") - clickedFunction: function () { - let text = "" - if (root.highlight == "") - text = activeFocusItem.getSelectedText() - else - text = activeFocusItem.getHighlightedText(root.highlight) - - // Removing any . or , from the start and the end of the word - text = text.replace(/^[,.]+|[,.]+$/g, '') - - // Make the first letter lower case. When the word is at the start of a sentence, - // the first letter will be upper case, which in turn causes the dictionary to fail. - const firstLetter = text.charAt(0).toLowerCase() - const restOfString = text.slice(1) - // Get the rest of the string - text = firstLetter + restOfString - - DictionaryController.getDefinitionForWord(text) - root.dictionaryOptionSelected(text) + ColorItem { + colorName: "HighlightColorE" } } - Separator {} - - Rectangle { - height: selectionOptionsListView.height - width: 26 - color: "transparent" - - RowLayout { - anchors.fill: parent - - Image { - id: goToPage2Button - Layout.alignment: Qt.AlignCenter - Layout.rightMargin: 4 - source: Icons.arrowheadNextIcon - } - } + Label { + id: copyText + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.topMargin: -2 + text: "Copy" + color: Style.colorText + font.weight: Font.Medium + font.pointSize: Fonts.size12dot5 MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor hoverEnabled: true - onClicked: selectionOptionsListView.model = secondActionsPage - } - } - } - - ObjectModel { - id: secondActionsPage - - Rectangle { - height: selectionOptionsListView.height - width: 26 - color: "transparent" + onClicked: { + if (root.highlight == "") + activeFocusItem.copySelectedText() + else + activeFocusItem.copyHighlightedText(root.highlight) - RowLayout { - anchors.fill: parent - - Image { - id: goToPage1Button - Layout.alignment: Qt.AlignCenter - Layout.leftMargin: 2 - rotation: 180 - source: Icons.arrowheadNextIcon + root.close() } } + } + + Label { + id: lookUpText + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + text: "Look Up" + color: Style.colorText + font.weight: Font.Medium + font.pointSize: Fonts.size12dot5 MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor hoverEnabled: true - onClicked: selectionOptionsListView.model = firstActionsPage - } - } - - Separator {} - - SelectionOptionsPopupItem { - id: explainAction - text: qsTr("Explain") - clickedFunction: function () { - let text = "" - if (root.highlight == "") - text = activeFocusItem.getSelectedText() - else - text = activeFocusItem.getHighlightedText(root.highlight) - - root.explanationOptionSelected(text) - } - } - - Separator { - visible: root.highlight != "" - width: visible ? implicitWidth : 0 - } - - SelectionOptionsPopupItem { - id: removeAction - width: visible ? implicitWidth : 0 - text: qsTr("Remove") - textColor: Style.colorErrorText - visible: root.highlight != "" - - clickedFunction: function () { - activeFocusItem.removeHighlight(root.highlight) - } - } - } - - ObjectModel { - id: externalBookActionPage - - SelectionOptionsPopupItem { - text: qsTr("Copy") - clickedFunction: function () { - if (root.highlight == "") - activeFocusItem.copySelectedText() - else - activeFocusItem.copyHighlightedText(root.highlight) - } - } - - Separator {} - - SelectionOptionsPopupItem { - text: qsTr("Look Up") - clickedFunction: function () { - let text = "" - if (root.highlight == "") - text = activeFocusItem.getSelectedText() - else - text = activeFocusItem.getHighlightedText(root.highlight) - - // Removing any . or , from the start and the end of the word - text = text.replace(/^[,.]+|[,.]+$/g, '') - - // Make the first letter lower case. When the word is at the start of a sentence, - // the first letter will be upper case, which in turn causes the dictionary to fail. - const firstLetter = text.charAt(0).toLowerCase() - const restOfString = text.slice(1) - // Get the rest of the string - text = firstLetter + restOfString - - DictionaryController.getDefinitionForWord(text) - root.dictionaryOptionSelected(text) + onClicked: { + let text = "" + if (root.highlight == "") + text = activeFocusItem.getSelectedText() + else + text = activeFocusItem.getHighlightedText( + root.highlight) + // Removing any . or , from the start and the end of the word + text = text.replace(/^[,.]+|[,.]+$/g, '') + // Make the first letter lower case. When the word is at the start of a sentence, + // the first letter will be upper case, which in turn causes the dictionary to fail. + const firstLetter = text.charAt(0).toLowerCase() + const restOfString = text.slice(1) + // Get the rest of the string + text = firstLetter + restOfString + DictionaryController.getDefinitionForWord(text) + root.dictionaryOptionSelected(text) + } } } - Separator {} + Label { + id: explainText + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.bottomMargin: 10 + text: "Ai Explain" + color: Style.colorText + font.pointSize: Fonts.size12dot5 + font.weight: Font.Medium - SelectionOptionsPopupItem { - text: qsTr("Explain") - clickedFunction: function () { - let text = "" - if (root.highlight == "") - text = activeFocusItem.getSelectedText() - else - text = activeFocusItem.getHighlightedText(root.highlight) + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true - root.explanationOptionSelected(text) + onClicked: { + let text = "" + if (root.highlight == "") + text = activeFocusItem.getSelectedText() + else + text = activeFocusItem.getHighlightedText( + root.highlight) + root.explanationOptionSelected(text) + } } } }