From a35cb979e4d35f89ff6b6d2f2b5a60f7946a11bd Mon Sep 17 00:00:00 2001 From: Felix Kauselmann Date: Mon, 31 Oct 2022 13:19:50 +0100 Subject: [PATCH 01/21] Unix: Fix regression in translation install target The introduction of CONFIG+= lrelease introduced a regression in the installation of translation files on systems using make install targets. This is fixed by replacing the old translation targets with the target supplied by lrelease. Fixes #349 --- YACReader/YACReader.pro | 19 ++----------------- YACReaderLibrary/YACReaderLibrary.pro | 19 ++----------------- .../YACReaderLibraryServer.pro | 12 +----------- config.pri | 16 ++++++++++++++++ 4 files changed, 21 insertions(+), 45 deletions(-) diff --git a/YACReader/YACReader.pro b/YACReader/YACReader.pro index 855de657..49684d37 100644 --- a/YACReader/YACReader.pro +++ b/YACReader/YACReader.pro @@ -214,28 +214,16 @@ win32 { $(COPY) $$shell_path($${SOURCE_QM_DIR}) $$shell_path($${DEPLOYMENT_OUT_QM_DIR}) } else { LRELEASE_DIR = ../release/languages/ + QM_FILES_INSTALL_PATH = $$DATADIR/yacreader/languages } unix:!macx { -# set install prefix if it's empty -isEmpty(PREFIX) { - PREFIX = /usr -} -isEmpty(BINDIR) { - BINDIR = $$PREFIX/bin -} -isEmpty(LIBDIR) { - LIBDIR = $$PREFIX/lib -} -isEmpty(DATADIR) { - DATADIR = $$PREFIX/share -} DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" #MAKE INSTALL -INSTALLS += bin docs icon desktop translation manpage +INSTALLS += bin docs icon desktop manpage bin.path = $$BINDIR isEmpty(DESTDIR) { @@ -256,9 +244,6 @@ icon.files = ../YACReader.svg desktop.path = $$DATADIR/applications desktop.files = ../YACReader.desktop -translation.path = $$DATADIR/yacreader/languages -translation.files = ../release/languages/yacreader_* - manpage.path = $$DATADIR/man/man1 manpage.files = ../YACReader.1 diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro index b66127bf..41edbde5 100644 --- a/YACReaderLibrary/YACReaderLibrary.pro +++ b/YACReaderLibrary/YACReaderLibrary.pro @@ -307,6 +307,7 @@ win32 { $(COPY) $$shell_path($${SOURCE_QM_DIR}) $$shell_path($${DEPLOYMENT_OUT_QM_DIR}) } else { LRELEASE_DIR = ../release/languages/ + QM_FILES_INSTALL_PATH = $$DATADIR/yacreader/languages } #QML/GridView @@ -328,24 +329,11 @@ unix:!macx:RESOURCES += qml_win.qrc macx:RESOURCES += qml_osx.qrc unix:!macx { -#set install prefix if it's empty -isEmpty(PREFIX) { - PREFIX = /usr -} -isEmpty(BINDIR) { - BINDIR = $$PREFIX/bin -} -isEmpty(LIBDIR) { - LIBDIR = $$PREFIX/lib -} -isEmpty(DATADIR) { - DATADIR = $$PREFIX/share -} DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" "BINDIR=\\\"$$BINDIR\\\"" #MAKE INSTALL -INSTALLS += bin icon desktop server translation manpage +INSTALLS += bin icon desktop server manpage bin.path = $$BINDIR isEmpty(DESTDIR) { @@ -363,9 +351,6 @@ icon.files = ../YACReaderLibrary.svg desktop.path = $$DATADIR/applications desktop.files = ../YACReaderLibrary.desktop -translation.path = $$DATADIR/yacreader/languages -translation.files = ../release/languages/yacreaderlibrary_* - manpage.path = $$DATADIR/man/man1 manpage.files = ../YACReaderLibrary.1 } diff --git a/YACReaderLibraryServer/YACReaderLibraryServer.pro b/YACReaderLibraryServer/YACReaderLibraryServer.pro index 311c1764..b84c2057 100644 --- a/YACReaderLibraryServer/YACReaderLibraryServer.pro +++ b/YACReaderLibraryServer/YACReaderLibraryServer.pro @@ -130,13 +130,6 @@ contains(QMAKE_TARGET.arch, x86_64) { unix:!macx { #set install prefix if it's empty -isEmpty(PREFIX) { - PREFIX = /usr -} - -BINDIR = $$PREFIX/bin -LIBDIR = $$PREFIX/lib -DATADIR = $$PREFIX/share DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" "BINDIR=\\\"$$BINDIR\\\"" @@ -150,7 +143,7 @@ DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" "BINDIR=\\\"$$ } CONFIG(server_standalone) { - INSTALLS += bin server translation systemd + INSTALLS += bin server systemd } else:CONFIG(server_bundled) { INSTALLS += bin systemd @@ -169,9 +162,6 @@ server.files = ../release/server systemd.path = $$LIBDIR/systemd/user systemd.files = yacreaderlibraryserver.service -translation.path = $$DATADIR/yacreader/languages -translation.files = ../release/languages/yacreaderlibrary_* - # TODO: We need a manpage for yaclibserver #manpage.path = $$DATADIR/man/man1 #manpage.files = ../YACReaderLibrary.1 diff --git a/config.pri b/config.pri index 033c486d..a5d82f03 100644 --- a/config.pri +++ b/config.pri @@ -93,4 +93,20 @@ macx:!CONFIG(pdfkit):!CONFIG(pdfium):!CONFIG(no_pdf) { DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050900 } +unix:!macx { +# set install prefix if it's empty +isEmpty(PREFIX) { + PREFIX = /usr +} +isEmpty(BINDIR) { + BINDIR = $$PREFIX/bin +} +isEmpty(LIBDIR) { + LIBDIR = $$PREFIX/lib +} +isEmpty(DATADIR) { + DATADIR = $$PREFIX/share +} +} + DEFINES += QT_DEPRECATED_WARNINGS From a7ff96b9ce6943290ffc95b27cd15e4f9dc11312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 6 Nov 2022 10:15:00 +0100 Subject: [PATCH 02/21] Fix indentation --- YACReaderLibrary/qml/GridComicsView.qml | 1448 +++++++++++----------- YACReaderLibrary/qml/GridComicsView6.qml | 894 ++++++------- 2 files changed, 1171 insertions(+), 1171 deletions(-) diff --git a/YACReaderLibrary/qml/GridComicsView.qml b/YACReaderLibrary/qml/GridComicsView.qml index d5366df5..eb8915b6 100644 --- a/YACReaderLibrary/qml/GridComicsView.qml +++ b/YACReaderLibrary/qml/GridComicsView.qml @@ -18,640 +18,640 @@ SplitView { color: info_container.color } -Rectangle { - id: main - clip: true + Rectangle { + id: main + clip: true - Image { - id: backgroundImg - anchors.fill: parent - source: backgroundImage - fillMode: Image.PreserveAspectCrop - smooth: true - mipmap: true - asynchronous : true - cache: false //TODO clear cache only when it is needed - opacity: 0 - visible: false - } + Image { + id: backgroundImg + anchors.fill: parent + source: backgroundImage + fillMode: Image.PreserveAspectCrop + smooth: true + mipmap: true + asynchronous : true + cache: false //TODO clear cache only when it is needed + opacity: 0 + visible: false + } - FastBlur { - anchors.fill: backgroundImg - source: backgroundImg - radius: backgroundBlurRadius - opacity: backgroundBlurOpacity - visible: backgroundBlurVisible - } + FastBlur { + anchors.fill: backgroundImg + source: backgroundImg + radius: backgroundBlurRadius + opacity: backgroundBlurOpacity + visible: backgroundBlurVisible + } - color: backgroundColor - width: parent.width - (info_container.visible ? info_container.width : 0) - SplitView.fillWidth: true - SplitView.minimumWidth: coverWidth + 100 - height: parent.height - anchors.margins: 0 + color: backgroundColor + width: parent.width - (info_container.visible ? info_container.width : 0) + SplitView.fillWidth: true + SplitView.minimumWidth: coverWidth + 100 + height: parent.height + anchors.margins: 0 - Component { - id: appDelegate - Rectangle - { - id: cell - width: grid.cellWidth - height: grid.cellHeight - color: "#00000000" + Component { + id: appDelegate + Rectangle + { + id: cell + width: grid.cellWidth + height: grid.cellHeight + color: "#00000000" - scale: mouseArea.containsMouse ? 1.025 : 1 + scale: mouseArea.containsMouse ? 1.025 : 1 - Behavior on scale { - NumberAnimation { duration: 90 } - } - - DropShadow { - anchors.fill: realCell - horizontalOffset: 0 - verticalOffset: 0 - radius: 8.0 - samples: 17 - color: "#FF000000" - source: realCell - visible: (Qt.platform.os === "osx") ? false : true; - } - - Rectangle { - id: realCell - - property int position : 0 - property bool dragging: false; - Drag.active: mouseArea.drag.active - Drag.hotSpot.x: 32 - Drag.hotSpot.y: 32 - Drag.dragType: Drag.Automatic - //Drag.mimeData: { "x": 1 } - Drag.proposedAction: Qt.CopyAction - Drag.onActiveChanged: { - if(!dragging) - { - dragManager.startDrag(); - dragging = true; - }else - dragging = false; + Behavior on scale { + NumberAnimation { duration: 90 } } - width: itemWidth - height: itemHeight - - color: ((dummyValue || !dummyValue) && comicsSelectionHelper.isSelectedIndex(index))?selectedColor:cellColor; - //border.color: ((dummyValue || !dummyValue) && comicsSelectionHelper.isSelectedIndex(index))?selectedBorderColor:borderColor; - //border.width: ?1:0; - anchors.horizontalCenter: parent.horizontalCenter - - Rectangle - { - id: mouseOverBorder - - property bool commonBorder : false - - property int lBorderwidth : 2 - property int rBorderwidth : 2 - property int tBorderwidth : 2 - property int bBorderwidth : 2 - - property int commonBorderWidth : 1 - - z : -1 - - color: "#00000000" - - anchors - { - left: parent.left - right: parent.right - top: parent.top - bottom: parent.bottom - - topMargin : commonBorder ? -commonBorderWidth : -tBorderwidth - bottomMargin : commonBorder ? -commonBorderWidth : -bBorderwidth - leftMargin : commonBorder ? -commonBorderWidth : -lBorderwidth - rightMargin : commonBorder ? -commonBorderWidth : -rBorderwidth - } - - border.color: (Qt.platform.os === "osx") ? selectedBorderColor : "#ffcc00" - border.width: 3 - - opacity: (dummyValue || !dummyValue) && comicsSelectionHelper.isSelectedIndex(index) ? 1 : 0 - - Behavior on opacity { - NumberAnimation { duration: 300 } - } - - radius : 2 + DropShadow { + anchors.fill: realCell + horizontalOffset: 0 + verticalOffset: 0 + radius: 8.0 + samples: 17 + color: "#FF000000" + source: realCell + visible: (Qt.platform.os === "osx") ? false : true; } + Rectangle { + id: realCell - MouseArea { - id: mouseArea - drag.target: realCell - - drag.minimumX: 0 - drag.maximumX: 0 - drag.minimumY: 0 - drag.maximumY: 0 - - anchors.fill: parent - acceptedButtons: Qt.LeftButton | Qt.RightButton - - hoverEnabled: true - - onDoubleClicked: { - comicsSelectionHelper.clear(); - - comicsSelectionHelper.selectIndex(index); - grid.currentIndex = index; - currentIndexHelper.selectedItem(index); - } - - function selectAll(from,to) - { - for(var i = from;i<=to;i++) + property int position : 0 + property bool dragging: false; + Drag.active: mouseArea.drag.active + Drag.hotSpot.x: 32 + Drag.hotSpot.y: 32 + Drag.dragType: Drag.Automatic + //Drag.mimeData: { "x": 1 } + Drag.proposedAction: Qt.CopyAction + Drag.onActiveChanged: { + if(!dragging) { - comicsSelectionHelper.selectIndex(i); - } + dragManager.startDrag(); + dragging = true; + }else + dragging = false; } - onPressed: mouse => { - var ci = grid.currentIndex; //save current index + width: itemWidth + height: itemHeight - /*if(mouse.button != Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) + color: ((dummyValue || !dummyValue) && comicsSelectionHelper.isSelectedIndex(index))?selectedColor:cellColor; + //border.color: ((dummyValue || !dummyValue) && comicsSelectionHelper.isSelectedIndex(index))?selectedBorderColor:borderColor; + //border.width: ?1:0; + anchors.horizontalCenter: parent.horizontalCenter + + Rectangle + { + id: mouseOverBorder + + property bool commonBorder : false + + property int lBorderwidth : 2 + property int rBorderwidth : 2 + property int tBorderwidth : 2 + property int bBorderwidth : 2 + + property int commonBorderWidth : 1 + + z : -1 + + color: "#00000000" + + anchors + { + left: parent.left + right: parent.right + top: parent.top + bottom: parent.bottom + + topMargin : commonBorder ? -commonBorderWidth : -tBorderwidth + bottomMargin : commonBorder ? -commonBorderWidth : -bBorderwidth + leftMargin : commonBorder ? -commonBorderWidth : -lBorderwidth + rightMargin : commonBorder ? -commonBorderWidth : -rBorderwidth + } + + border.color: (Qt.platform.os === "osx") ? selectedBorderColor : "#ffcc00" + border.width: 3 + + opacity: (dummyValue || !dummyValue) && comicsSelectionHelper.isSelectedIndex(index) ? 1 : 0 + + Behavior on opacity { + NumberAnimation { duration: 300 } + } + + radius : 2 + } + + + MouseArea { + id: mouseArea + drag.target: realCell + + drag.minimumX: 0 + drag.maximumX: 0 + drag.minimumY: 0 + drag.maximumY: 0 + + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + + hoverEnabled: true + + onDoubleClicked: { + comicsSelectionHelper.clear(); + + comicsSelectionHelper.selectIndex(index); + grid.currentIndex = index; + currentIndexHelper.selectedItem(index); + } + + function selectAll(from,to) + { + for(var i = from;i<=to;i++) + { + comicsSelectionHelper.selectIndex(i); + } + } + + onPressed: mouse => { + var ci = grid.currentIndex; //save current index + + /*if(mouse.button != Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) { if(!comicsSelectionHelper.isSelectedIndex(index)) comicsSelectionHelper.clear(); }*/ - if(mouse.modifiers & Qt.ShiftModifier) - if(index < ci) - { - selectAll(index,ci); - grid.currentIndex = index; - } - else if (index > ci) - { - selectAll(ci,index); - grid.currentIndex = index; - } + if(mouse.modifiers & Qt.ShiftModifier) + if(index < ci) + { + selectAll(index,ci); + grid.currentIndex = index; + } + else if (index > ci) + { + selectAll(ci,index); + grid.currentIndex = index; + } - mouse.accepted = true; + mouse.accepted = true; - if(mouse.button === Qt.RightButton) // context menu is requested - { - if(!comicsSelectionHelper.isSelectedIndex(index)) //the context menu is requested outside the current selection, the selection will be - { - currentIndexHelper.setCurrentIndex(index) - grid.currentIndex = index; - } + if(mouse.button === Qt.RightButton) // context menu is requested + { + if(!comicsSelectionHelper.isSelectedIndex(index)) //the context menu is requested outside the current selection, the selection will be + { + currentIndexHelper.setCurrentIndex(index) + grid.currentIndex = index; + } - var coordinates = main.mapFromItem(realCell,mouseX,mouseY) - contextMenuHelper.requestedContextMenu(Qt.point(coordinates.x,coordinates.y)); - mouse.accepted = false; + var coordinates = main.mapFromItem(realCell,mouseX,mouseY) + contextMenuHelper.requestedContextMenu(Qt.point(coordinates.x,coordinates.y)); + mouse.accepted = false; - } else //left button - { + } else //left button + { - if(mouse.modifiers & Qt.ControlModifier) - { - if(comicsSelectionHelper.isSelectedIndex(index)) - { - if(comicsSelectionHelper.numItemsSelected()>1) - { - comicsSelectionHelper.deselectIndex(index); - if(grid.currentIndex === index) - grid.currentIndex = comicsSelectionHelper.lastSelectedIndex(); + if(mouse.modifiers & Qt.ControlModifier) + { + if(comicsSelectionHelper.isSelectedIndex(index)) + { + if(comicsSelectionHelper.numItemsSelected()>1) + { + comicsSelectionHelper.deselectIndex(index); + if(grid.currentIndex === index) + grid.currentIndex = comicsSelectionHelper.lastSelectedIndex(); + } + } + else + { + comicsSelectionHelper.selectIndex(index); + grid.currentIndex = index; + } + } + + if(mouse.button !== Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) //just left button click + { + if(comicsSelectionHelper.isSelectedIndex(index)) //the context menu is requested outside the current selection, the selection will be + { + + } + else + { + currentIndexHelper.setCurrentIndex(index) + } + + grid.currentIndex = index; + } + } + + } + + onReleased: mouse => { + if(mouse.button === Qt.LeftButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) + { + if(comicsSelectionHelper.isSelectedIndex(index)) + { + currentIndexHelper.setCurrentIndex(index) + grid.currentIndex = index; + } + } } - } - else - { - comicsSelectionHelper.selectIndex(index); - grid.currentIndex = index; - } - } + } + } - if(mouse.button !== Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) //just left button click - { - if(comicsSelectionHelper.isSelectedIndex(index)) //the context menu is requested outside the current selection, the selection will be - { + /**/ - } - else - { - currentIndexHelper.setCurrentIndex(index) - } + //cover + Image { + id: coverElement + width: coverWidth + height: coverHeight + anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0} + source: cover_path + fillMode: Image.PreserveAspectCrop + smooth: true + mipmap: true + asynchronous : true + cache: false //TODO clear cache only when it is needed - grid.currentIndex = index; - } + } + + //border + Rectangle { + width: coverElement.width + height: coverElement.height + anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0} + color: "transparent" + border { + color: "#20FFFFFF" + width: 1 + } + } + + //mark + Image { + id: mark + width: 23 + height: 23 + source: read_column&&show_marks?"tick.png":has_been_opened&&show_marks?"reading.png":"" + anchors {right: coverElement.right; top: coverElement.top; topMargin: 9; rightMargin: 9} + asynchronous : true + } + + //title + Text { + id : titleText + anchors { top: coverElement.bottom; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 4; } + width: itemWidth - 8 + maximumLineCount: 2 + wrapMode: Text.WordWrap + text: title + elide: Text.ElideRight + color: titleColor + clip: true + font.letterSpacing: fontSpacing + font.pointSize: fontSize + font.family: fontFamily + } + + //number + Text { + anchors {bottom: realCell.bottom; left: realCell.left; margins: 4} + text: number?"#"+number:"" + color: textColor + font.letterSpacing: fontSpacing + font.pointSize: fontSize + font.family: fontFamily + } + + //page icon + Image { + id: pageImage + anchors {bottom: realCell.bottom; right: realCell.right; bottomMargin: 5; rightMargin: 4; leftMargin: 4} + source: "page.png" + width: 8 + height: 10 + } + + //numPages + Text { + id: pages + anchors {bottom: realCell.bottom; right: pageImage.left; margins: 4} + text: has_been_opened?current_page+"/"+num_pages:num_pages + color: textColor + font.letterSpacing: fontSpacing + font.pointSize: fontSize + font.family: fontFamily + } + + //rating icon + Image { + id: ratingImage + anchors {bottom: realCell.bottom; right: pageImage.left; bottomMargin: 5; rightMargin: Math.floor(pages.width)+12} + source: "star.png" + width: 13 + height: 11 + + MouseArea { + anchors.fill: parent + onPressed: { + console.log("rating"); + comicsSelectionHelper.clear(); + comicsSelectionHelper.selectIndex(index); + grid.currentIndex = index; + ratingConextMenu.popup(); } - } - onReleased: mouse => { - if(mouse.button === Qt.LeftButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) - { - if(comicsSelectionHelper.isSelectedIndex(index)) - { - currentIndexHelper.setCurrentIndex(index) - grid.currentIndex = index; - } + Menu { + background: Rectangle { + implicitWidth: 42 + implicitHeight: 100 + //border.color: "#222" + //color: "#444" + } + + id: ratingConextMenu + + Action { text: "1"; enabled: true; onTriggered: comicRatingHelper.rate(index,1) } + Action { text: "2"; enabled: true; onTriggered: comicRatingHelper.rate(index,2) } + Action { text: "3"; enabled: true; onTriggered: comicRatingHelper.rate(index,3) } + Action { text: "4"; enabled: true; onTriggered: comicRatingHelper.rate(index,4) } + Action { text: "5"; enabled: true; onTriggered: comicRatingHelper.rate(index,5) } + + delegate: MenuItem { + implicitHeight: 30 } } } - } - /**/ - - //cover - Image { - id: coverElement - width: coverWidth - height: coverHeight - anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0} - source: cover_path - fillMode: Image.PreserveAspectCrop - smooth: true - mipmap: true - asynchronous : true - cache: false //TODO clear cache only when it is needed - - } - - //border - Rectangle { - width: coverElement.width - height: coverElement.height - anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0} - color: "transparent" - border { - color: "#20FFFFFF" - width: 1 + //comic rating + Text { + id: comicRating + anchors {bottom: realCell.bottom; right: ratingImage.left; margins: 4} + text: rating>0?rating:"-" + color: textColor } } - - //mark - Image { - id: mark - width: 23 - height: 23 - source: read_column&&show_marks?"tick.png":has_been_opened&&show_marks?"reading.png":"" - anchors {right: coverElement.right; top: coverElement.top; topMargin: 9; rightMargin: 9} - asynchronous : true - } - - //title - Text { - id : titleText - anchors { top: coverElement.bottom; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 4; } - width: itemWidth - 8 - maximumLineCount: 2 - wrapMode: Text.WordWrap - text: title - elide: Text.ElideRight - color: titleColor - clip: true - font.letterSpacing: fontSpacing - font.pointSize: fontSize - font.family: fontFamily - } - - //number - Text { - anchors {bottom: realCell.bottom; left: realCell.left; margins: 4} - text: number?"#"+number:"" - color: textColor - font.letterSpacing: fontSpacing - font.pointSize: fontSize - font.family: fontFamily - } - - //page icon - Image { - id: pageImage - anchors {bottom: realCell.bottom; right: realCell.right; bottomMargin: 5; rightMargin: 4; leftMargin: 4} - source: "page.png" - width: 8 - height: 10 - } - - //numPages - Text { - id: pages - anchors {bottom: realCell.bottom; right: pageImage.left; margins: 4} - text: has_been_opened?current_page+"/"+num_pages:num_pages - color: textColor - font.letterSpacing: fontSpacing - font.pointSize: fontSize - font.family: fontFamily - } - - //rating icon - Image { - id: ratingImage - anchors {bottom: realCell.bottom; right: pageImage.left; bottomMargin: 5; rightMargin: Math.floor(pages.width)+12} - source: "star.png" - width: 13 - height: 11 - - MouseArea { - anchors.fill: parent - onPressed: { - console.log("rating"); - comicsSelectionHelper.clear(); - comicsSelectionHelper.selectIndex(index); - grid.currentIndex = index; - ratingConextMenu.popup(); - } - } - - Menu { - background: Rectangle { - implicitWidth: 42 - implicitHeight: 100 - //border.color: "#222" - //color: "#444" - } - - id: ratingConextMenu - - Action { text: "1"; enabled: true; onTriggered: comicRatingHelper.rate(index,1) } - Action { text: "2"; enabled: true; onTriggered: comicRatingHelper.rate(index,2) } - Action { text: "3"; enabled: true; onTriggered: comicRatingHelper.rate(index,3) } - Action { text: "4"; enabled: true; onTriggered: comicRatingHelper.rate(index,4) } - Action { text: "5"; enabled: true; onTriggered: comicRatingHelper.rate(index,5) } - - delegate: MenuItem { - implicitHeight: 30 - } - } - } - - //comic rating - Text { - id: comicRating - anchors {bottom: realCell.bottom; right: ratingImage.left; margins: 4} - text: rating>0?rating:"-" - color: textColor - } } - } - Rectangle { - id: scrollView - objectName: "topScrollView" - anchors.fill: parent - anchors.margins: 0 - children: grid - - color: "transparent" - - function scrollToOrigin() { - grid.contentY = grid.originY - grid.contentX = grid.originX - } - - DropArea { + Rectangle { + id: scrollView + objectName: "topScrollView" anchors.fill: parent + anchors.margins: 0 + children: grid - onEntered: { - if(drag.hasUrls) - { - if(dropManager.canDropUrls(drag.urls, drag.action)) + color: "transparent" + + function scrollToOrigin() { + grid.contentY = grid.originY + grid.contentX = grid.originX + } + + DropArea { + anchors.fill: parent + + onEntered: { + if(drag.hasUrls) { + if(dropManager.canDropUrls(drag.urls, drag.action)) + { + drag.accepted = true; + }else + drag.accepted = false; + } + else if (dropManager.canDropFormats(drag.formats)) { drag.accepted = true; - }else + } else drag.accepted = false; } - else if (dropManager.canDropFormats(drag.formats)) { - drag.accepted = true; - } else - drag.accepted = false; - } - onDropped: { - if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action)) - { - dropManager.droppedFiles(drop.urls, drop.action); - } - else{ - if (dropManager.canDropFormats(drop.formats)) + onDropped: { + if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action)) { - var destItem = grid.itemAt(drop.x,drop.y + grid.contentY); - var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x - var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY); + dropManager.droppedFiles(drop.urls, drop.action); + } + else{ + if (dropManager.canDropFormats(drop.formats)) + { + var destItem = grid.itemAt(drop.x,drop.y + grid.contentY); + var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x + var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY); - if(realIndex === -1) - realIndex = grid.count - 1; + if(realIndex === -1) + realIndex = grid.count - 1; - var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1; - dropManager.droppedComicsForResortingAt(drop.getDataAsString(), destIndex); + var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1; + dropManager.droppedComicsForResortingAt(drop.getDataAsString(), destIndex); + } } } } - } - - property Component currentComicView: Component { - id: currentComicView - Rectangle { - id: currentComicViewTopView - color: "#00000000" - - height: showCurrentComic ? 270 : 20 + property Component currentComicView: Component { + id: currentComicView Rectangle { - color: (Qt.platform.os === "osx") ? "#88FFFFFF" : "#88000000" + id: currentComicViewTopView + color: "#00000000" - id: currentComicVisualView + height: showCurrentComic ? 270 : 20 - width: main.width - height: 250 + Rectangle { + color: (Qt.platform.os === "osx") ? "#88FFFFFF" : "#88000000" - visible: showCurrentComic + id: currentComicVisualView - //cover - Image { - id: currentCoverElement - anchors.fill: parent + width: main.width + height: 250 - anchors.leftMargin: 15 - anchors.topMargin: 15 - anchors.bottomMargin: 15 - anchors.rightMargin: 15 - horizontalAlignment: Image.AlignLeft - anchors {horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: 0} - source: comicsList.getCoverUrlPathForComicHash(currentComicInfo.hash.toString()) - fillMode: Image.PreserveAspectFit - smooth: true - mipmap: true - asynchronous : true - cache: false //TODO clear cache only when it is needed - } + visible: showCurrentComic - DropShadow { - anchors.fill: currentCoverElement - horizontalOffset: 0 - verticalOffset: 0 - radius: 8.0 - samples: 17 - color: "#FF000000" - source: currentCoverElement - visible: (Qt.platform.os === "osx") ? false : true; - } + //cover + Image { + id: currentCoverElement + anchors.fill: parent - ColumnLayout - { - id: currentComicInfoView - - x: currentCoverElement.anchors.rightMargin + currentCoverElement.paintedWidth + currentCoverElement.anchors.rightMargin - //y: currentCoverElement.anchors.topMargin - - anchors.top: currentCoverElement.top - anchors.right: parent.right - anchors.left: readButton.left - - spacing: 9 - - Text { - Layout.topMargin: 7 - Layout.fillWidth: true - Layout.rightMargin: 20 - - Layout.alignment: Qt.AlignTop | Qt.AlignLeft - - id: currentComicInfoTitleView - - color: infoTitleColor - font.family: "Arial" - font.bold: true - font.pixelSize: 21 - wrapMode: Text.WordWrap - - text: currentComic.getTitleIncludingNumber() + anchors.leftMargin: 15 + anchors.topMargin: 15 + anchors.bottomMargin: 15 + anchors.rightMargin: 15 + horizontalAlignment: Image.AlignLeft + anchors {horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: 0} + source: comicsList.getCoverUrlPathForComicHash(currentComicInfo.hash.toString()) + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: true + asynchronous : true + cache: false //TODO clear cache only when it is needed } - Flow { - spacing: 0 - Layout.alignment: Qt.AlignTop | Qt.AlignLeft - Layout.fillWidth: true - Layout.fillHeight: false + DropShadow { + anchors.fill: currentCoverElement + horizontalOffset: 0 + verticalOffset: 0 + radius: 8.0 + samples: 17 + color: "#FF000000" + source: currentCoverElement + visible: (Qt.platform.os === "osx") ? false : true; + } - id: currentComicDetailsFlowView - property font infoFont: Qt.font({ - family: "Arial", - pixelSize: 14 - }); - property string infoFlowTextColor: infoTextColor + ColumnLayout + { + id: currentComicInfoView + + x: currentCoverElement.anchors.rightMargin + currentCoverElement.paintedWidth + currentCoverElement.anchors.rightMargin + //y: currentCoverElement.anchors.topMargin + + anchors.top: currentCoverElement.top + anchors.right: parent.right + anchors.left: readButton.left + + spacing: 9 Text { - id: currentComicInfoVolume - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: currentComicInfo.volume ? currentComicInfo.volume : "" - rightPadding: 20 - visible: currentComicInfo.volume ? true : false + Layout.topMargin: 7 + Layout.fillWidth: true + Layout.rightMargin: 20 + + Layout.alignment: Qt.AlignTop | Qt.AlignLeft + + id: currentComicInfoTitleView + + color: infoTitleColor + font.family: "Arial" + font.bold: true + font.pixelSize: 21 + wrapMode: Text.WordWrap + + text: currentComic.getTitleIncludingNumber() } - Text { - id: currentComicInfoNumbering - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: currentComicInfo.number + "/" + currentComicInfo.count - rightPadding: 20 - visible : currentComicInfo.number ? true : false - } + Flow { + spacing: 0 + Layout.alignment: Qt.AlignTop | Qt.AlignLeft + Layout.fillWidth: true + Layout.fillHeight: false - Text { - id: currentComicInfoGenre - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: currentComicInfo.genere ? currentComicInfo.genere : "" - rightPadding: 20 - visible: currentComicInfo.genere ? true : false - } + id: currentComicDetailsFlowView + property font infoFont: Qt.font({ + family: "Arial", + pixelSize: 14 + }); + property string infoFlowTextColor: infoTextColor - Text { - id: currentComicInfoDate - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: currentComicInfo.date ? currentComicInfo.date : "" - rightPadding: 20 - visible: currentComicInfo.date ? true : false - } + Text { + id: currentComicInfoVolume + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: currentComicInfo.volume ? currentComicInfo.volume : "" + rightPadding: 20 + visible: currentComicInfo.volume ? true : false + } - Text { - id: currentComicInfoPages - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: (currentComicInfo.numPages ? currentComicInfo.numPages : "") + " pages" - rightPadding: 20 - visible: currentComicInfo.numPages ? true : false - } + Text { + id: currentComicInfoNumbering + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: currentComicInfo.number + "/" + currentComicInfo.count + rightPadding: 20 + visible : currentComicInfo.number ? true : false + } - Text { - id: currentComicInfoShowInComicVine - font: currentComicDetailsFlowView.infoFont - color: "#ffcc00" - text: "Show in Comic Vine" - visible: currentComicInfo.comicVineID ? true : false - MouseArea { - anchors.fill: parent - onClicked: { - Qt.openUrlExternally("http://www.comicvine.com/comic/4000-%1/".arg(comicInfo.comicVineID)); + Text { + id: currentComicInfoGenre + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: currentComicInfo.genere ? currentComicInfo.genere : "" + rightPadding: 20 + visible: currentComicInfo.genere ? true : false + } + + Text { + id: currentComicInfoDate + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: currentComicInfo.date ? currentComicInfo.date : "" + rightPadding: 20 + visible: currentComicInfo.date ? true : false + } + + Text { + id: currentComicInfoPages + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: (currentComicInfo.numPages ? currentComicInfo.numPages : "") + " pages" + rightPadding: 20 + visible: currentComicInfo.numPages ? true : false + } + + Text { + id: currentComicInfoShowInComicVine + font: currentComicDetailsFlowView.infoFont + color: "#ffcc00" + text: "Show in Comic Vine" + visible: currentComicInfo.comicVineID ? true : false + MouseArea { + anchors.fill: parent + onClicked: { + Qt.openUrlExternally("http://www.comicvine.com/comic/4000-%1/".arg(comicInfo.comicVineID)); + } } } } - } - ScrollView { - Layout.topMargin: 6 - Layout.rightMargin: 30 - Layout.bottomMargin: 5 - Layout.fillWidth: true - Layout.maximumHeight: (currentComicVisualView.height * 0.32) - Layout.maximumWidth: 960 - - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - contentItem: currentComicInfoSinopsis - - id: synopsisScroller - - clip: true - - Text { + ScrollView { + Layout.topMargin: 6 + Layout.rightMargin: 30 + Layout.bottomMargin: 5 + Layout.fillWidth: true + Layout.maximumHeight: (currentComicVisualView.height * 0.32) Layout.maximumWidth: 960 - width: synopsisScroller.width + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - id: currentComicInfoSinopsis - color: infoTitleColor - font.family: "Arial" - font.pixelSize: 14 - wrapMode: Text.WordWrap + contentItem: currentComicInfoSinopsis - text: '' + currentComicInfo.synopsis ?? "" + '' - visible: currentComicInfo.synopsis ?? false - textFormat: Text.RichText + visible: currentComicInfo.synopsis ?? false + textFormat: Text.RichText + } } } - } - Button { - text: "Read" - id: readButton - x: currentCoverElement.anchors.rightMargin + currentCoverElement.paintedWidth + currentCoverElement.anchors.rightMargin - anchors.bottom: currentCoverElement.bottom - anchors.bottomMargin: 15 + Button { + text: "Read" + id: readButton + x: currentCoverElement.anchors.rightMargin + currentCoverElement.paintedWidth + currentCoverElement.anchors.rightMargin + anchors.bottom: currentCoverElement.bottom + anchors.bottomMargin: 15 - onClicked: comicOpener.triggerOpenCurrentComic() + onClicked: comicOpener.triggerOpenCurrentComic() background: Rectangle { implicitWidth: 100 implicitHeight: 30 @@ -671,202 +671,202 @@ Rectangle { color: "white" text: readButton.text } - } + } - DropShadow { - anchors.fill: readButton - horizontalOffset: 0 - verticalOffset: 0 - radius: 8.0 - samples: 17 - color: "#AA000000" - source: readButton - visible: ((Qt.platform.os === "osx") ? false : true) && !readButton.pressed + DropShadow { + anchors.fill: readButton + horizontalOffset: 0 + verticalOffset: 0 + radius: 8.0 + samples: 17 + color: "#AA000000" + source: readButton + visible: ((Qt.platform.os === "osx") ? false : true) && !readButton.pressed + } } } } - } - GridView { - id:grid - objectName: "grid" + GridView { + id:grid + objectName: "grid" + anchors.fill: parent + cellHeight: cellCustomHeight + header: currentComicView + focus: true + model: comicsList + delegate: appDelegate + anchors.topMargin: 0 + anchors.bottomMargin: 10 + anchors.leftMargin: 0 + anchors.rightMargin: 0 + pixelAligned: true + highlightFollowsCurrentItem: true + + currentIndex: 0 + cacheBuffer: 0 + + interactive: true + + move: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + moveDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + remove: Transition { + ParallelAnimation { + NumberAnimation { property: "opacity"; to: 0; duration: 250 } + + } + } + + removeDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + + + displaced: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + function numCellsPerRow() { + return Math.floor(width / cellCustomWidth); + } + + onWidthChanged: { + calculateCellWidths(cellCustomWidth); + } + + function calculateCellWidths(cWidth) { + var wholeCells = Math.floor(width / cWidth); + var rest = width - (cWidth * wholeCells) + + grid.cellWidth = cWidth + Math.floor(rest / wholeCells); + } + + WheelHandler { + onWheel: { + if (grid.contentHeight <= grid.height) { + return; + } + + var newValue = Math.min((grid.contentHeight - grid.height - (showCurrentComic ? 270 : 20)), (Math.max(grid.originY , grid.contentY - event.angleDelta.y))); + grid.contentY = newValue; + } + } + + ScrollBar.vertical: ScrollBar { + visible: grid.contentHeight > grid.height + + contentItem: Item { + implicitWidth: 12 + implicitHeight: 26 + Rectangle { + color: "#88424242" + anchors.fill: parent + anchors.topMargin: 6 + anchors.leftMargin: 3 + anchors.rightMargin: 2 + anchors.bottomMargin: 6 + border.color: "#AA313131" + border.width: 1 + radius: 3.5 + } + } + } + + Keys.onPressed: { + if (event.modifiers & Qt.ControlModifier || event.modifiers & Qt.ShiftModifier) { + event.accepted = true + return; + } + + var numCells = grid.numCellsPerRow(); + var ci = 0; + if (event.key === Qt.Key_Right) { + ci = Math.min(grid.currentIndex+1,grid.count - 1); + } + else if (event.key === Qt.Key_Left) { + ci = Math.max(0,grid.currentIndex-1); + } + else if (event.key === Qt.Key_Up) { + ci = Math.max(0,grid.currentIndex-numCells); + } + else if (event.key === Qt.Key_Down) { + ci = Math.min(grid.currentIndex+numCells,grid.count - 1); + } else { + return; + } + + event.accepted = true; + grid.currentIndex = -1 + comicsSelectionHelper.clear(); + currentIndexHelper.setCurrentIndex(ci); + grid.currentIndex = ci; + } + } + } + } + + Rectangle { + id: info_container + objectName: "infoContainer" + SplitView.preferredWidth: 350 + SplitView.minimumWidth: 350 + SplitView.maximumWidth: 960 + height: parent.height + + color: infoBackgroundColor + + visible: showInfo + + Flickable{ + id: infoFlickable anchors.fill: parent - cellHeight: cellCustomHeight - header: currentComicView - focus: true - model: comicsList - delegate: appDelegate - anchors.topMargin: 0 - anchors.bottomMargin: 10 - anchors.leftMargin: 0 - anchors.rightMargin: 0 - pixelAligned: true - highlightFollowsCurrentItem: true + anchors.margins: 0 - currentIndex: 0 - cacheBuffer: 0 + contentWidth: infoView.width + contentHeight: infoView.height - interactive: true - - move: Transition { - NumberAnimation { properties: "x,y"; duration: 250 } + ComicInfoView { + id: infoView + width: info_container.width } - moveDisplaced: Transition { - NumberAnimation { properties: "x,y"; duration: 250 } - } - - remove: Transition { - ParallelAnimation { - NumberAnimation { property: "opacity"; to: 0; duration: 250 } + WheelHandler { + onWheel: { + if (infoFlickable.contentHeight <= infoFlickable.height) { + return; + } + var newValue = Math.min((infoFlickable.contentHeight - infoFlickable.height), (Math.max(infoFlickable.originY , infoFlickable.contentY - event.angleDelta.y))); + infoFlickable.contentY = newValue; } } - removeDisplaced: Transition { - NumberAnimation { properties: "x,y"; duration: 250 } + ScrollBar.vertical: ScrollBar { + visible: infoFlickable.contentHeight > infoFlickable.height + + contentItem: Item { + implicitWidth: 12 + implicitHeight: 26 + Rectangle { + color: "#424246" + anchors.fill: parent + anchors.topMargin: 6 + anchors.leftMargin: 5 + anchors.rightMargin: 4 + anchors.bottomMargin: 6 + radius: 2 + } + } } - - - - displaced: Transition { - NumberAnimation { properties: "x,y"; duration: 250 } - } - - function numCellsPerRow() { - return Math.floor(width / cellCustomWidth); - } - - onWidthChanged: { - calculateCellWidths(cellCustomWidth); - } - - function calculateCellWidths(cWidth) { - var wholeCells = Math.floor(width / cWidth); - var rest = width - (cWidth * wholeCells) - - grid.cellWidth = cWidth + Math.floor(rest / wholeCells); - } - - WheelHandler { - onWheel: { - if (grid.contentHeight <= grid.height) { - return; - } - - var newValue = Math.min((grid.contentHeight - grid.height - (showCurrentComic ? 270 : 20)), (Math.max(grid.originY , grid.contentY - event.angleDelta.y))); - grid.contentY = newValue; - } - } - - ScrollBar.vertical: ScrollBar { - visible: grid.contentHeight > grid.height - - contentItem: Item { - implicitWidth: 12 - implicitHeight: 26 - Rectangle { - color: "#88424242" - anchors.fill: parent - anchors.topMargin: 6 - anchors.leftMargin: 3 - anchors.rightMargin: 2 - anchors.bottomMargin: 6 - border.color: "#AA313131" - border.width: 1 - radius: 3.5 - } - } - } - - Keys.onPressed: { - if (event.modifiers & Qt.ControlModifier || event.modifiers & Qt.ShiftModifier) { - event.accepted = true - return; - } - - var numCells = grid.numCellsPerRow(); - var ci = 0; - if (event.key === Qt.Key_Right) { - ci = Math.min(grid.currentIndex+1,grid.count - 1); - } - else if (event.key === Qt.Key_Left) { - ci = Math.max(0,grid.currentIndex-1); - } - else if (event.key === Qt.Key_Up) { - ci = Math.max(0,grid.currentIndex-numCells); - } - else if (event.key === Qt.Key_Down) { - ci = Math.min(grid.currentIndex+numCells,grid.count - 1); - } else { - return; - } - - event.accepted = true; - grid.currentIndex = -1 - comicsSelectionHelper.clear(); - currentIndexHelper.setCurrentIndex(ci); - grid.currentIndex = ci; - } } + } } - -Rectangle { - id: info_container - objectName: "infoContainer" - SplitView.preferredWidth: 350 - SplitView.minimumWidth: 350 - SplitView.maximumWidth: 960 - height: parent.height - - color: infoBackgroundColor - - visible: showInfo - - Flickable{ - id: infoFlickable - anchors.fill: parent - anchors.margins: 0 - - contentWidth: infoView.width - contentHeight: infoView.height - - ComicInfoView { - id: infoView - width: info_container.width - } - - WheelHandler { - onWheel: { - if (infoFlickable.contentHeight <= infoFlickable.height) { - return; - } - - var newValue = Math.min((infoFlickable.contentHeight - infoFlickable.height), (Math.max(infoFlickable.originY , infoFlickable.contentY - event.angleDelta.y))); - infoFlickable.contentY = newValue; - } - } - - ScrollBar.vertical: ScrollBar { - visible: infoFlickable.contentHeight > infoFlickable.height - - contentItem: Item { - implicitWidth: 12 - implicitHeight: 26 - Rectangle { - color: "#424246" - anchors.fill: parent - anchors.topMargin: 6 - anchors.leftMargin: 5 - anchors.rightMargin: 4 - anchors.bottomMargin: 6 - radius: 2 - } - } - } - } - -} -} diff --git a/YACReaderLibrary/qml/GridComicsView6.qml b/YACReaderLibrary/qml/GridComicsView6.qml index 86f41494..f50e3652 100644 --- a/YACReaderLibrary/qml/GridComicsView6.qml +++ b/YACReaderLibrary/qml/GridComicsView6.qml @@ -20,73 +20,73 @@ SplitView { color: info_container.color } -Rectangle { - id: main - clip: true + Rectangle { + id: main + clip: true - Image { - id: backgroundImg - anchors.fill: parent - source: backgroundImage - fillMode: Image.PreserveAspectCrop - smooth: true - mipmap: true - asynchronous : true - cache: false //TODO clear cache only when it is needed - opacity: 0 - visible: false - } + Image { + id: backgroundImg + anchors.fill: parent + source: backgroundImage + fillMode: Image.PreserveAspectCrop + smooth: true + mipmap: true + asynchronous : true + cache: false //TODO clear cache only when it is needed + opacity: 0 + visible: false + } - FastBlur { - anchors.fill: backgroundImg - source: backgroundImg - radius: backgroundBlurRadius - opacity: backgroundBlurOpacity - visible: backgroundBlurVisible - } + FastBlur { + anchors.fill: backgroundImg + source: backgroundImg + radius: backgroundBlurRadius + opacity: backgroundBlurOpacity + visible: backgroundBlurVisible + } - color: backgroundColor - width: parent.width - (info_container.visible ? info_container.width : 0) - SplitView.fillWidth: true - SplitView.minimumWidth: coverWidth + 100 - height: parent.height - anchors.margins: 0 + color: backgroundColor + width: parent.width - (info_container.visible ? info_container.width : 0) + SplitView.fillWidth: true + SplitView.minimumWidth: coverWidth + 100 + height: parent.height + anchors.margins: 0 - Component { - id: appDelegate - Rectangle - { - id: cell - width: grid.cellWidth - height: grid.cellHeight - color: "#00000000" + Component { + id: appDelegate + Rectangle + { + id: cell + width: grid.cellWidth + height: grid.cellHeight + color: "#00000000" - scale: mouseArea.containsMouse ? 1.025 : 1 + scale: mouseArea.containsMouse ? 1.025 : 1 - Behavior on scale { - NumberAnimation { duration: 90 } - } + Behavior on scale { + NumberAnimation { duration: 90 } + } - DropShadow { - anchors.fill: realCell - transparentBorder: true - horizontalOffset: 0 - verticalOffset: 0 - radius: 10.0 - //samples: 17 - color: "#FF000000" - source: realCell - visible: (Qt.platform.os === "osx") ? false : true; - } + DropShadow { + anchors.fill: realCell + transparentBorder: true + horizontalOffset: 0 + verticalOffset: 0 + radius: 10.0 + //samples: 17 + color: "#FF000000" + source: realCell + visible: (Qt.platform.os === "osx") ? false : true; + } - Rectangle { - id: realCell + Rectangle { + id: realCell - property int position : 0 - property bool dragging: false; - Drag.active: mouseArea.drag.active - Drag.hotSpot.x: 32 - Drag.hotSpot.y: 32 + property int position : 0 + property bool dragging: false; + Drag.active: mouseArea.drag.active + Drag.hotSpot.x: 32 + Drag.hotSpot.y: 32 Drag.dragType: Drag.Automatic //Drag.mimeData: { "x": 1 } Drag.proposedAction: Qt.CopyAction @@ -397,267 +397,267 @@ Rectangle { id: comicRating anchors {bottom: realCell.bottom; right: ratingImage.left; margins: 4} text: rating>0?rating:"-" - color: textColor + color: textColor + } } } - } - Rectangle { - id: scrollView - objectName: "topScrollView" - anchors.fill: parent - anchors.margins: 0 - children: grid - - color: "transparent" - - function scrollToOrigin() { - grid.contentY = grid.originY - grid.contentX = grid.originX - } - - DropArea { + Rectangle { + id: scrollView + objectName: "topScrollView" anchors.fill: parent + anchors.margins: 0 + children: grid - onEntered: { - if(drag.hasUrls) - { - if(dropManager.canDropUrls(drag.urls, drag.action)) + color: "transparent" + + function scrollToOrigin() { + grid.contentY = grid.originY + grid.contentX = grid.originX + } + + DropArea { + anchors.fill: parent + + onEntered: { + if(drag.hasUrls) { + if(dropManager.canDropUrls(drag.urls, drag.action)) + { + drag.accepted = true; + }else + drag.accepted = false; + } + else if (dropManager.canDropFormats(drag.formats)) { drag.accepted = true; - }else + } else drag.accepted = false; } - else if (dropManager.canDropFormats(drag.formats)) { - drag.accepted = true; - } else - drag.accepted = false; - } - onDropped: { - if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action)) - { - dropManager.droppedFiles(drop.urls, drop.action); - } - else{ - if (dropManager.canDropFormats(drop.formats)) + onDropped: { + if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action)) { - var destItem = grid.itemAt(drop.x,drop.y + grid.contentY); - var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x - var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY); + dropManager.droppedFiles(drop.urls, drop.action); + } + else{ + if (dropManager.canDropFormats(drop.formats)) + { + var destItem = grid.itemAt(drop.x,drop.y + grid.contentY); + var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x + var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY); - if(realIndex === -1) - realIndex = grid.count - 1; + if(realIndex === -1) + realIndex = grid.count - 1; - var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1; - dropManager.droppedComicsForResortingAt(drop.getDataAsString(), destIndex); + var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1; + dropManager.droppedComicsForResortingAt(drop.getDataAsString(), destIndex); + } } } } - } - - property Component currentComicView: Component { - id: currentComicView - Rectangle { - id: currentComicViewTopView - color: "#00000000" - - height: showCurrentComic ? 270 : 20 + property Component currentComicView: Component { + id: currentComicView Rectangle { - color: (Qt.platform.os === "osx") ? "#88FFFFFF" : "#88000000" + id: currentComicViewTopView + color: "#00000000" - id: currentComicVisualView + height: showCurrentComic ? 270 : 20 - width: main.width - height: 250 + Rectangle { + color: (Qt.platform.os === "osx") ? "#88FFFFFF" : "#88000000" - visible: showCurrentComic + id: currentComicVisualView - //cover - Image { - id: currentCoverElement - anchors.fill: parent + width: main.width + height: 250 - anchors.leftMargin: 15 - anchors.topMargin: 15 - anchors.bottomMargin: 15 - anchors.rightMargin: 15 - horizontalAlignment: Image.AlignLeft - anchors {horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: 0} - source: comicsList.getCoverUrlPathForComicHash(currentComicInfo.hash.toString()) - fillMode: Image.PreserveAspectFit - smooth: true - mipmap: true - asynchronous : true - cache: false //TODO clear cache only when it is needed - } + visible: showCurrentComic - DropShadow { - anchors.fill: currentCoverElement - horizontalOffset: 0 - verticalOffset: 0 - radius: 8.0 - transparentBorder: true - //samples: 17 - color: "#FF000000" - source: currentCoverElement - visible: (Qt.platform.os === "osx") ? false : true; - } + //cover + Image { + id: currentCoverElement + anchors.fill: parent - ColumnLayout - { - id: currentComicInfoView - - x: currentCoverElement.anchors.rightMargin + currentCoverElement.paintedWidth + currentCoverElement.anchors.rightMargin - //y: currentCoverElement.anchors.topMargin - - anchors.top: currentCoverElement.top - anchors.right: parent.right - anchors.left: readButton.left - - spacing: 9 - - Text { - Layout.topMargin: 7 - Layout.fillWidth: true - Layout.rightMargin: 20 - - Layout.alignment: Qt.AlignTop | Qt.AlignLeft - - id: currentComicInfoTitleView - - color: infoTitleColor - font.family: "Arial" - font.bold: true - font.pixelSize: 21 - wrapMode: Text.WordWrap - - text: currentComic.getTitleIncludingNumber() + anchors.leftMargin: 15 + anchors.topMargin: 15 + anchors.bottomMargin: 15 + anchors.rightMargin: 15 + horizontalAlignment: Image.AlignLeft + anchors {horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: 0} + source: comicsList.getCoverUrlPathForComicHash(currentComicInfo.hash.toString()) + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: true + asynchronous : true + cache: false //TODO clear cache only when it is needed } - Flow { - spacing: 0 - Layout.alignment: Qt.AlignTop | Qt.AlignLeft - Layout.fillWidth: true - Layout.fillHeight: false + DropShadow { + anchors.fill: currentCoverElement + horizontalOffset: 0 + verticalOffset: 0 + radius: 8.0 + transparentBorder: true + //samples: 17 + color: "#FF000000" + source: currentCoverElement + visible: (Qt.platform.os === "osx") ? false : true; + } - id: currentComicDetailsFlowView - property font infoFont: Qt.font({ - family: "Arial", - pixelSize: 14 - }); - property string infoFlowTextColor: infoTextColor + ColumnLayout + { + id: currentComicInfoView + + x: currentCoverElement.anchors.rightMargin + currentCoverElement.paintedWidth + currentCoverElement.anchors.rightMargin + //y: currentCoverElement.anchors.topMargin + + anchors.top: currentCoverElement.top + anchors.right: parent.right + anchors.left: readButton.left + + spacing: 9 Text { - id: currentComicInfoVolume - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: currentComicInfo.volume ? currentComicInfo.volume : "" - rightPadding: 20 - visible: currentComicInfo.volume ? true : false + Layout.topMargin: 7 + Layout.fillWidth: true + Layout.rightMargin: 20 + + Layout.alignment: Qt.AlignTop | Qt.AlignLeft + + id: currentComicInfoTitleView + + color: infoTitleColor + font.family: "Arial" + font.bold: true + font.pixelSize: 21 + wrapMode: Text.WordWrap + + text: currentComic.getTitleIncludingNumber() } - Text { - id: currentComicInfoNumbering - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: currentComicInfo.number + "/" + currentComicInfo.count - rightPadding: 20 - visible : currentComicInfo.number ? true : false - } + Flow { + spacing: 0 + Layout.alignment: Qt.AlignTop | Qt.AlignLeft + Layout.fillWidth: true + Layout.fillHeight: false - Text { - id: currentComicInfoGenre - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: currentComicInfo.genere ? currentComicInfo.genere : "" - rightPadding: 20 - visible: currentComicInfo.genere ? true : false - } + id: currentComicDetailsFlowView + property font infoFont: Qt.font({ + family: "Arial", + pixelSize: 14 + }); + property string infoFlowTextColor: infoTextColor - Text { - id: currentComicInfoDate - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: currentComicInfo.date ? currentComicInfo.date : "" - rightPadding: 20 - visible: currentComicInfo.date ? true : false - } + Text { + id: currentComicInfoVolume + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: currentComicInfo.volume ? currentComicInfo.volume : "" + rightPadding: 20 + visible: currentComicInfo.volume ? true : false + } - Text { - id: currentComicInfoPages - color: currentComicDetailsFlowView.infoFlowTextColor - font: currentComicDetailsFlowView.infoFont - text: (currentComicInfo.numPages ? currentComicInfo.numPages : "") + " pages" - rightPadding: 20 - visible: currentComicInfo.numPages ? true : false - } + Text { + id: currentComicInfoNumbering + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: currentComicInfo.number + "/" + currentComicInfo.count + rightPadding: 20 + visible : currentComicInfo.number ? true : false + } - Text { - id: currentComicInfoShowInComicVine - font: currentComicDetailsFlowView.infoFont - color: "#ffcc00" - text: "Show in Comic Vine" - visible: currentComicInfo.comicVineID ? true : false - MouseArea { - anchors.fill: parent - onClicked: { - Qt.openUrlExternally("http://www.comicvine.com/comic/4000-%1/".arg(comicInfo.comicVineID)); + Text { + id: currentComicInfoGenre + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: currentComicInfo.genere ? currentComicInfo.genere : "" + rightPadding: 20 + visible: currentComicInfo.genere ? true : false + } + + Text { + id: currentComicInfoDate + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: currentComicInfo.date ? currentComicInfo.date : "" + rightPadding: 20 + visible: currentComicInfo.date ? true : false + } + + Text { + id: currentComicInfoPages + color: currentComicDetailsFlowView.infoFlowTextColor + font: currentComicDetailsFlowView.infoFont + text: (currentComicInfo.numPages ? currentComicInfo.numPages : "") + " pages" + rightPadding: 20 + visible: currentComicInfo.numPages ? true : false + } + + Text { + id: currentComicInfoShowInComicVine + font: currentComicDetailsFlowView.infoFont + color: "#ffcc00" + text: "Show in Comic Vine" + visible: currentComicInfo.comicVineID ? true : false + MouseArea { + anchors.fill: parent + onClicked: { + Qt.openUrlExternally("http://www.comicvine.com/comic/4000-%1/".arg(comicInfo.comicVineID)); + } } } } - } - ScrollView { - Layout.topMargin: 6 - Layout.rightMargin: 30 - Layout.bottomMargin: 5 - Layout.fillWidth: true - Layout.maximumHeight: (currentComicVisualView.height * 0.32) - Layout.maximumWidth: 960 - - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - contentWidth: -1 - contentItem: currentComicInfoSinopsis - - id: synopsisScroller - - clip: true - - Text { + ScrollView { + Layout.topMargin: 6 + Layout.rightMargin: 30 + Layout.bottomMargin: 5 + Layout.fillWidth: true + Layout.maximumHeight: (currentComicVisualView.height * 0.32) Layout.maximumWidth: 960 - width: synopsisScroller.width + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - id: currentComicInfoSinopsis - color: infoTitleColor - font.family: "Arial" - font.pixelSize: 14 - wrapMode: Text.WordWrap + contentWidth: -1 + contentItem: currentComicInfoSinopsis - text: '' + currentComicInfo.synopsis ?? "" + '' - visible: currentComicInfo.synopsis ?? false - textFormat: Text.RichText + visible: currentComicInfo.synopsis ?? false + textFormat: Text.RichText + } } } - } - Button { - containmentMask: null - text: "Read" - id: readButton - x: currentCoverElement.anchors.rightMargin + currentCoverElement.paintedWidth + currentCoverElement.anchors.rightMargin - anchors.bottom: currentCoverElement.bottom - anchors.bottomMargin: 15 + Button { + containmentMask: null + text: "Read" + id: readButton + x: currentCoverElement.anchors.rightMargin + currentCoverElement.paintedWidth + currentCoverElement.anchors.rightMargin + anchors.bottom: currentCoverElement.bottom + anchors.bottomMargin: 15 - onClicked: comicOpener.triggerOpenCurrentComic() + onClicked: comicOpener.triggerOpenCurrentComic() background: Rectangle { implicitWidth: 100 implicitHeight: 30 @@ -677,203 +677,203 @@ Rectangle { color: "white" text: readButton.text } - } + } - DropShadow { - anchors.fill: readButton - transparentBorder: true - horizontalOffset: 0 - verticalOffset: 0 - radius: 8.0 - //samples: 17 - color: "#AA000000" - source: readButton - visible: ((Qt.platform.os === "osx") ? false : true) && !readButton.pressed + DropShadow { + anchors.fill: readButton + transparentBorder: true + horizontalOffset: 0 + verticalOffset: 0 + radius: 8.0 + //samples: 17 + color: "#AA000000" + source: readButton + visible: ((Qt.platform.os === "osx") ? false : true) && !readButton.pressed + } } } } - } - GridView { - id:grid - objectName: "grid" + GridView { + id:grid + objectName: "grid" + anchors.fill: parent + cellHeight: cellCustomHeight + header: currentComicView + focus: true + model: comicsList + delegate: appDelegate + anchors.topMargin: 0 + anchors.bottomMargin: 10 + anchors.leftMargin: 0 + anchors.rightMargin: 0 + pixelAligned: true + highlightFollowsCurrentItem: true + + currentIndex: 0 + cacheBuffer: 0 + + interactive: true + + move: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + moveDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + remove: Transition { + ParallelAnimation { + NumberAnimation { property: "opacity"; to: 0; duration: 250 } + + } + } + + removeDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + + + displaced: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + function numCellsPerRow() { + return Math.floor(width / cellCustomWidth); + } + + onWidthChanged: { + calculateCellWidths(cellCustomWidth); + } + + function calculateCellWidths(cWidth) { + var wholeCells = Math.floor(width / cWidth); + var rest = width - (cWidth * wholeCells) + + grid.cellWidth = cWidth + Math.floor(rest / wholeCells); + } + + WheelHandler { + onWheel: { + if (grid.contentHeight <= grid.height) { + return; + } + + var newValue = Math.min((grid.contentHeight - grid.height - (showCurrentComic ? 270 : 20)), (Math.max(grid.originY , grid.contentY - event.angleDelta.y))); + grid.contentY = newValue; + } + } + + ScrollBar.vertical: ScrollBar { + visible: grid.contentHeight > grid.height + + contentItem: Item { + implicitWidth: 12 + implicitHeight: 26 + Rectangle { + color: "#88424242" + anchors.fill: parent + anchors.topMargin: 6 + anchors.leftMargin: 3 + anchors.rightMargin: 2 + anchors.bottomMargin: 6 + border.color: "#AA313131" + border.width: 1 + radius: 3.5 + } + } + } + + Keys.onPressed: { + if (event.modifiers & Qt.ControlModifier || event.modifiers & Qt.ShiftModifier) { + event.accepted = true + return; + } + + var numCells = grid.numCellsPerRow(); + var ci = 0; + if (event.key === Qt.Key_Right) { + ci = Math.min(grid.currentIndex+1,grid.count - 1); + } + else if (event.key === Qt.Key_Left) { + ci = Math.max(0,grid.currentIndex-1); + } + else if (event.key === Qt.Key_Up) { + ci = Math.max(0,grid.currentIndex-numCells); + } + else if (event.key === Qt.Key_Down) { + ci = Math.min(grid.currentIndex+numCells,grid.count - 1); + } else { + return; + } + + event.accepted = true; + grid.currentIndex = -1 + comicsSelectionHelper.clear(); + currentIndexHelper.setCurrentIndex(ci); + grid.currentIndex = ci; + } + } + } + } + + Rectangle { + id: info_container + objectName: "infoContainer" + SplitView.preferredWidth: 350 + SplitView.minimumWidth: 350 + SplitView.maximumWidth: 960 + height: parent.height + + color: infoBackgroundColor + + visible: showInfo + + Flickable{ + id: infoFlickable anchors.fill: parent - cellHeight: cellCustomHeight - header: currentComicView - focus: true - model: comicsList - delegate: appDelegate - anchors.topMargin: 0 - anchors.bottomMargin: 10 - anchors.leftMargin: 0 - anchors.rightMargin: 0 - pixelAligned: true - highlightFollowsCurrentItem: true + anchors.margins: 0 - currentIndex: 0 - cacheBuffer: 0 + contentWidth: infoView.width + contentHeight: infoView.height - interactive: true - - move: Transition { - NumberAnimation { properties: "x,y"; duration: 250 } + ComicInfoView { + id: infoView + width: info_container.width } - moveDisplaced: Transition { - NumberAnimation { properties: "x,y"; duration: 250 } - } - - remove: Transition { - ParallelAnimation { - NumberAnimation { property: "opacity"; to: 0; duration: 250 } + WheelHandler { + onWheel: { + if (infoFlickable.contentHeight <= infoFlickable.height) { + return; + } + var newValue = Math.min((infoFlickable.contentHeight - infoFlickable.height), (Math.max(infoFlickable.originY , infoFlickable.contentY - event.angleDelta.y))); + infoFlickable.contentY = newValue; } } - removeDisplaced: Transition { - NumberAnimation { properties: "x,y"; duration: 250 } + ScrollBar.vertical: ScrollBar { + visible: infoFlickable.contentHeight > infoFlickable.height + + contentItem: Item { + implicitWidth: 12 + implicitHeight: 26 + Rectangle { + color: "#424246" + anchors.fill: parent + anchors.topMargin: 6 + anchors.leftMargin: 5 + anchors.rightMargin: 4 + anchors.bottomMargin: 6 + radius: 2 + } + } } - - - - displaced: Transition { - NumberAnimation { properties: "x,y"; duration: 250 } - } - - function numCellsPerRow() { - return Math.floor(width / cellCustomWidth); - } - - onWidthChanged: { - calculateCellWidths(cellCustomWidth); - } - - function calculateCellWidths(cWidth) { - var wholeCells = Math.floor(width / cWidth); - var rest = width - (cWidth * wholeCells) - - grid.cellWidth = cWidth + Math.floor(rest / wholeCells); - } - - WheelHandler { - onWheel: { - if (grid.contentHeight <= grid.height) { - return; - } - - var newValue = Math.min((grid.contentHeight - grid.height - (showCurrentComic ? 270 : 20)), (Math.max(grid.originY , grid.contentY - event.angleDelta.y))); - grid.contentY = newValue; - } - } - - ScrollBar.vertical: ScrollBar { - visible: grid.contentHeight > grid.height - - contentItem: Item { - implicitWidth: 12 - implicitHeight: 26 - Rectangle { - color: "#88424242" - anchors.fill: parent - anchors.topMargin: 6 - anchors.leftMargin: 3 - anchors.rightMargin: 2 - anchors.bottomMargin: 6 - border.color: "#AA313131" - border.width: 1 - radius: 3.5 - } - } - } - - Keys.onPressed: { - if (event.modifiers & Qt.ControlModifier || event.modifiers & Qt.ShiftModifier) { - event.accepted = true - return; - } - - var numCells = grid.numCellsPerRow(); - var ci = 0; - if (event.key === Qt.Key_Right) { - ci = Math.min(grid.currentIndex+1,grid.count - 1); - } - else if (event.key === Qt.Key_Left) { - ci = Math.max(0,grid.currentIndex-1); - } - else if (event.key === Qt.Key_Up) { - ci = Math.max(0,grid.currentIndex-numCells); - } - else if (event.key === Qt.Key_Down) { - ci = Math.min(grid.currentIndex+numCells,grid.count - 1); - } else { - return; - } - - event.accepted = true; - grid.currentIndex = -1 - comicsSelectionHelper.clear(); - currentIndexHelper.setCurrentIndex(ci); - grid.currentIndex = ci; - } } + } } - -Rectangle { - id: info_container - objectName: "infoContainer" - SplitView.preferredWidth: 350 - SplitView.minimumWidth: 350 - SplitView.maximumWidth: 960 - height: parent.height - - color: infoBackgroundColor - - visible: showInfo - - Flickable{ - id: infoFlickable - anchors.fill: parent - anchors.margins: 0 - - contentWidth: infoView.width - contentHeight: infoView.height - - ComicInfoView { - id: infoView - width: info_container.width - } - - WheelHandler { - onWheel: { - if (infoFlickable.contentHeight <= infoFlickable.height) { - return; - } - - var newValue = Math.min((infoFlickable.contentHeight - infoFlickable.height), (Math.max(infoFlickable.originY , infoFlickable.contentY - event.angleDelta.y))); - infoFlickable.contentY = newValue; - } - } - - ScrollBar.vertical: ScrollBar { - visible: infoFlickable.contentHeight > infoFlickable.height - - contentItem: Item { - implicitWidth: 12 - implicitHeight: 26 - Rectangle { - color: "#424246" - anchors.fill: parent - anchors.topMargin: 6 - anchors.leftMargin: 5 - anchors.rightMargin: 4 - anchors.bottomMargin: 6 - radius: 2 - } - } - } - } - -} -} From ffd8fd3bfb5147ba1c237a4372e93868ed0c1ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 6 Nov 2022 11:48:27 +0100 Subject: [PATCH 03/21] Fix Drag&Drop in the comics grid view --- YACReaderLibrary/qml/GridComicsView.qml | 80 ++++++++++++------------ YACReaderLibrary/qml/GridComicsView6.qml | 80 ++++++++++++------------ 2 files changed, 80 insertions(+), 80 deletions(-) diff --git a/YACReaderLibrary/qml/GridComicsView.qml b/YACReaderLibrary/qml/GridComicsView.qml index eb8915b6..1786fca0 100644 --- a/YACReaderLibrary/qml/GridComicsView.qml +++ b/YACReaderLibrary/qml/GridComicsView.qml @@ -413,46 +413,6 @@ SplitView { grid.contentX = grid.originX } - DropArea { - anchors.fill: parent - - onEntered: { - if(drag.hasUrls) - { - if(dropManager.canDropUrls(drag.urls, drag.action)) - { - drag.accepted = true; - }else - drag.accepted = false; - } - else if (dropManager.canDropFormats(drag.formats)) { - drag.accepted = true; - } else - drag.accepted = false; - } - - onDropped: { - if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action)) - { - dropManager.droppedFiles(drop.urls, drop.action); - } - else{ - if (dropManager.canDropFormats(drop.formats)) - { - var destItem = grid.itemAt(drop.x,drop.y + grid.contentY); - var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x - var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY); - - if(realIndex === -1) - realIndex = grid.count - 1; - - var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1; - dropManager.droppedComicsForResortingAt(drop.getDataAsString(), destIndex); - } - } - } - } - property Component currentComicView: Component { id: currentComicView Rectangle { @@ -809,6 +769,46 @@ SplitView { currentIndexHelper.setCurrentIndex(ci); grid.currentIndex = ci; } + + DropArea { + anchors.fill: parent + + onEntered: drag => { + if(drag.hasUrls) + { + if(dropManager.canDropUrls(drag.urls, drag.action)) + { + drag.accepted = true; + }else + drag.accepted = false; + } + else if (dropManager.canDropFormats(drag.formats)) { + drag.accepted = true; + } else + drag.accepted = false; + } + + onDropped: drop => { + if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action)) + { + dropManager.droppedFiles(drop.urls, drop.action); + } + else{ + if (dropManager.canDropFormats(drop.formats)) + { + var destItem = grid.itemAt(drop.x,drop.y + grid.contentY); + var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x + var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY); + + if(realIndex === -1) + realIndex = grid.count - 1; + + var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1; + dropManager.droppedComicsForResortingAt("", destIndex); + } + } + } + } } } } diff --git a/YACReaderLibrary/qml/GridComicsView6.qml b/YACReaderLibrary/qml/GridComicsView6.qml index f50e3652..10294fc0 100644 --- a/YACReaderLibrary/qml/GridComicsView6.qml +++ b/YACReaderLibrary/qml/GridComicsView6.qml @@ -416,46 +416,6 @@ SplitView { grid.contentX = grid.originX } - DropArea { - anchors.fill: parent - - onEntered: { - if(drag.hasUrls) - { - if(dropManager.canDropUrls(drag.urls, drag.action)) - { - drag.accepted = true; - }else - drag.accepted = false; - } - else if (dropManager.canDropFormats(drag.formats)) { - drag.accepted = true; - } else - drag.accepted = false; - } - - onDropped: { - if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action)) - { - dropManager.droppedFiles(drop.urls, drop.action); - } - else{ - if (dropManager.canDropFormats(drop.formats)) - { - var destItem = grid.itemAt(drop.x,drop.y + grid.contentY); - var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x - var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY); - - if(realIndex === -1) - realIndex = grid.count - 1; - - var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1; - dropManager.droppedComicsForResortingAt(drop.getDataAsString(), destIndex); - } - } - } - } - property Component currentComicView: Component { id: currentComicView Rectangle { @@ -816,6 +776,46 @@ SplitView { currentIndexHelper.setCurrentIndex(ci); grid.currentIndex = ci; } + + DropArea { + anchors.fill: parent + + onEntered: drag => { + if(drag.hasUrls) + { + if(dropManager.canDropUrls(drag.urls, drag.action)) + { + drag.accepted = true; + }else + drag.accepted = false; + } + else if (dropManager.canDropFormats(drag.formats)) { + drag.accepted = true; + } else + drag.accepted = false; + } + + onDropped: drop => { + if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action)) + { + dropManager.droppedFiles(drop.urls, drop.action); + } + else{ + if (dropManager.canDropFormats(drop.formats)) + { + var destItem = grid.itemAt(drop.x,drop.y + grid.contentY); + var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x + var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY); + + if(realIndex === -1) + realIndex = grid.count - 1; + + var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1; + dropManager.droppedComicsForResortingAt("", destIndex); + } + } + } + } } } } From 2b56945374b791a79b70e410b67a0657c6db5e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Thu, 10 Nov 2022 21:46:36 +0100 Subject: [PATCH 04/21] Make comic vine dialog modal --- YACReaderLibrary/comic_vine/comic_vine_dialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp b/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp index bf26fe58..28781ada 100644 --- a/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp +++ b/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp @@ -33,6 +33,7 @@ ComicVineDialog::ComicVineDialog(QWidget *parent) : QDialog(parent) { setWindowFlags(Qt::Window); + setModal(true); doLayout(); doStackedWidgets(); From 0f9d782bb87bf841ea4e40e2e2858aa253c64711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Thu, 10 Nov 2022 21:46:51 +0100 Subject: [PATCH 05/21] Detect back/forward mouse buttons to move back and forward through the browsing history --- YACReaderLibrary/library_window.cpp | 23 +++++++++++++++++++++++ YACReaderLibrary/library_window.h | 2 ++ YACReaderLibrary/main.cpp | 2 ++ 3 files changed, 27 insertions(+) diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp index 2ce6ab4e..fa85756f 100644 --- a/YACReaderLibrary/library_window.cpp +++ b/YACReaderLibrary/library_window.cpp @@ -139,6 +139,29 @@ void LibraryWindow::afterLaunchTasks() } } +bool LibraryWindow::eventFilter(QObject *object, QEvent *event) +{ + if (this->isActiveWindow()) { + if (event->type() == QEvent::MouseButtonRelease) { + auto mouseEvent = static_cast(event); + + if (mouseEvent->button() == Qt::ForwardButton) { + forwardAction->trigger(); + event->accept(); + return true; + } + + if (mouseEvent->button() == Qt::BackButton) { + backAction->trigger(); + event->accept(); + return true; + } + } + } + + return QMainWindow::eventFilter(object, event); +} + void LibraryWindow::createSettings() { settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat); // TODO unificar la creación del fichero de config con el servidor diff --git a/YACReaderLibrary/library_window.h b/YACReaderLibrary/library_window.h index fc12dad1..acbf4ee2 100644 --- a/YACReaderLibrary/library_window.h +++ b/YACReaderLibrary/library_window.h @@ -434,6 +434,8 @@ public slots: void afterLaunchTasks(); + bool eventFilter(QObject *object, QEvent *event) override; + private: //! @brief Exits search mode if it is active. //! @return true If the search mode was active when this function was called. diff --git a/YACReaderLibrary/main.cpp b/YACReaderLibrary/main.cpp index 170d71a9..127242dd 100644 --- a/YACReaderLibrary/main.cpp +++ b/YACReaderLibrary/main.cpp @@ -269,6 +269,8 @@ int main(int argc, char **argv) } #endif + app.installEventFilter(mw); + int ret = app.exec(); QLOG_INFO() << "YACReaderLibrary closed with exit code :" << ret; From 27b5692f263c699020950ff198faf1cee9e30a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Thu, 10 Nov 2022 21:46:59 +0100 Subject: [PATCH 06/21] Update CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a49e8047..ac1c9586 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Version counting is based on semantic versioning (Major.Feature.Patch) +## WIP + +### YACReaderLibrary +* Fixed drag&drop in the comics grid view. +* Detect back/forward mouse buttons to move back and forward through the browsing history. + ## 9.10 ### YACReader From 35466e5080f48adfd1a9fd95d00fa4049d79945b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Thu, 17 Nov 2022 22:53:08 +0100 Subject: [PATCH 07/21] Fix crash caused by clearing the ip value ip is connected to regenerateQR --- YACReaderLibrary/server_config_dialog.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/YACReaderLibrary/server_config_dialog.cpp b/YACReaderLibrary/server_config_dialog.cpp index d16211eb..e27998b1 100644 --- a/YACReaderLibrary/server_config_dialog.cpp +++ b/YACReaderLibrary/server_config_dialog.cpp @@ -167,8 +167,13 @@ ServerConfigDialog::ServerConfigDialog(QWidget *parent) if (settings->value(SERVER_ON, true).toBool()) { check->setChecked(true); generateQR(); - } else + } else { + ip->setDisabled(true); + port->setDisabled(true); + accept->setDisabled(true); + check->setChecked(false); + } performanceWorkaroundCheck->setChecked(settings->value(REMOTE_BROWSE_PERFORMANCE_WORKAROUND, false).toBool()); @@ -184,14 +189,18 @@ void ServerConfigDialog::enableServer(int status) settings->beginGroup("libraryConfig"); if (status == Qt::Checked) { + ip->setDisabled(false); + port->setDisabled(false); + accept->setDisabled(false); httpServer->start(); this->generateQR(); settings->setValue(SERVER_ON, true); } else { httpServer->stop(); qrCode->setPixmap(QPixmap()); - ip->clear(); - port->setText(""); + ip->setDisabled(true); + port->setDisabled(true); + accept->setDisabled(true); settings->setValue(SERVER_ON, false); } settings->endGroup(); From 21b8b706574158f5fe807d3370a6e7414ceedc81 Mon Sep 17 00:00:00 2001 From: Felix Kauselmann Date: Sat, 12 Nov 2022 14:09:07 +0100 Subject: [PATCH 08/21] QsLog: Use dedicated logging thread to avoid segfaults at app shutdown When shutting down our apps, we clean up some ressources after app.exec() has finished. As our logger runs on the apps main thread, it can no longer respond to any debug messages generated during the cleanup phase. This can lead to segfaults and error masking. Solution: Run QsLog in a dedicated thread. --- CHANGELOG.md | 3 +++ third_party/QsLog/QsLog.pri | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac1c9586..5fe2bced 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ Version counting is based on semantic versioning (Major.Feature.Patch) * Fixed drag&drop in the comics grid view. * Detect back/forward mouse buttons to move back and forward through the browsing history. +### All apps +* Run logger in a dedicated thread to avoid segfaults at application shutdown + ## 9.10 ### YACReader diff --git a/third_party/QsLog/QsLog.pri b/third_party/QsLog/QsLog.pri index baf9d1f9..20363e1c 100644 --- a/third_party/QsLog/QsLog.pri +++ b/third_party/QsLog/QsLog.pri @@ -1,7 +1,7 @@ INCLUDEPATH += $$PWD #DEFINES += QS_LOG_LINE_NUMBERS # automatically writes the file and line for each log message #DEFINES += QS_LOG_DISABLE # logging code is replaced with a no-op -#DEFINES += QS_LOG_SEPARATE_THREAD # messages are queued and written from a separate thread +DEFINES += QS_LOG_SEPARATE_THREAD # messages are queued and written from a separate thread #DEFINES += QS_LOG_WIN_PRINTF_CONSOLE # Use fprintf instead of OutputDebugString on Windows #DEFINES += QS_LOG_WINDOW # allows easily showing log messages in a UI From 0414104067939c6ec890634ff3c294265070c6c9 Mon Sep 17 00:00:00 2001 From: Felix Kauselmann Date: Sat, 12 Nov 2022 23:09:27 +0100 Subject: [PATCH 09/21] YACReader: Fix crash when exiting while processing a comic When quitting YACReader while processing a comic, the comic thread needs to be properly terminated to avoid segfaults and other possible problems. --- CHANGELOG.md | 2 ++ YACReader/render.cpp | 23 +++++++++++++---------- common/comic.cpp | 2 ++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fe2bced..8de31e0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Version counting is based on semantic versioning (Major.Feature.Patch) ## WIP +### YACReader +*Fix segfault (or worse) when exiting YACReader while processing a comic ### YACReaderLibrary * Fixed drag&drop in the comics grid view. * Detect back/forward mouse buttons to move back and forward through the browsing history. diff --git a/YACReader/render.cpp b/YACReader/render.cpp index a0218a68..fee12b11 100644 --- a/YACReader/render.cpp +++ b/YACReader/render.cpp @@ -382,20 +382,23 @@ Render::Render() Render::~Render() { - if (comic != nullptr) { - comic->moveToThread(QApplication::instance()->thread()); - comic->deleteLater(); + for (auto *pr : pageRenders) { + if (pr != nullptr && pr->wait()) { + delete pr; + } } - foreach (PageRender *pr, pageRenders) - if (pr != nullptr) { - if (pr->wait()) - delete pr; - } - // TODO move to share_ptr - foreach (ImageFilter *filter, filters) + for (auto *filter : filters) { delete filter; + } + + if (comic != nullptr) { + comic->invalidate(); + comic->deleteLater(); + comic->thread()->quit(); + comic->thread()->wait(); + } } // Este método se encarga de forzar el renderizado de las páginas. // Actualiza el buffer según es necesario. diff --git a/common/comic.cpp b/common/comic.cpp index 0349bf93..69882fae 100644 --- a/common/comic.cpp +++ b/common/comic.cpp @@ -890,8 +890,10 @@ void PDFComic::renderPage(int page) #endif QByteArray ba; QBuffer buf(&ba); + buf.open(QIODevice::WriteOnly); img.save(&buf, "jpg", 96); _pages[page] = ba; + buf.close(); emit imageLoaded(page); emit imageLoaded(page, _pages[page]); } From be85954b0c424c2769f38ac5515768fd52ed7253 Mon Sep 17 00:00:00 2001 From: Felix Kauselmann Date: Sun, 13 Nov 2022 16:17:02 +0100 Subject: [PATCH 10/21] Use std::unique_ptr for pdf objects --- .../initial_comic_info_extractor.cpp | 24 ++++--------------- common/comic.cpp | 19 +++++---------- common/comic.h | 6 ++--- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/YACReaderLibrary/initial_comic_info_extractor.cpp b/YACReaderLibrary/initial_comic_info_extractor.cpp index 2d889f4c..d25d84c4 100644 --- a/YACReaderLibrary/initial_comic_info_extractor.cpp +++ b/YACReaderLibrary/initial_comic_info_extractor.cpp @@ -27,38 +27,27 @@ void InitialComicInfoExtractor::extract() #ifndef NO_PDF if (fi.suffix().compare("pdf", Qt::CaseInsensitive) == 0) { #if defined Q_OS_MAC && defined USE_PDFKIT - MacOSXPDFComic *pdfComic = new MacOSXPDFComic(); + auto pdfComic = std::make_unique(); if (!pdfComic->openComic(_fileSource)) { - delete pdfComic; - // QImage p; - // p.load(":/images/notCover.png"); - // p.save(_target); return; } #elif defined USE_PDFIUM - auto pdfComic = new PdfiumComic(); + auto pdfComic = std::make_unique(); if (!pdfComic->openComic(_fileSource)) { - delete pdfComic; return; } #else - Poppler::Document *pdfComic = Poppler::Document::load(_fileSource); + auto _pdfComic = Poppler::Document::load(_fileSource); + auto pdfComic = std::unique_ptr(_pdfComic); #endif - if (!pdfComic) { QLOG_WARN() << "Extracting cover: unable to open PDF file " << _fileSource; - // delete pdfComic; //TODO check if the delete is needed - pdfComic = 0; - // QImage p; - // p.load(":/images/notCover.png"); - // p.save(_target); return; } #if !defined USE_PDFKIT && !defined USE_PDFIUM // poppler only, not mac if (pdfComic->isLocked()) { QLOG_WARN() << "Extracting cover: unable to open PDF file " << _fileSource; - delete pdfComic; return; } #endif @@ -75,11 +64,8 @@ void InitialComicInfoExtractor::extract() saveCover(_target, p); } else if (_target != "") { QLOG_WARN() << "Extracting cover: requested cover index greater than numPages " << _fileSource; - // QImage p; - // p.load(":/images/notCover.png"); - // p.save(_target); + } - delete pdfComic; } return; } diff --git a/common/comic.cpp b/common/comic.cpp index 69882fae..26b3949e 100644 --- a/common/comic.cpp +++ b/common/comic.cpp @@ -796,24 +796,22 @@ bool PDFComic::load(const QString &path, const ComicDB &comic) void PDFComic::process() { #if defined Q_OS_MAC && defined USE_PDFKIT - pdfComic = new MacOSXPDFComic(); + pdfComic = std::make_unique(); if (!pdfComic->openComic(_path)) { - delete pdfComic; emit errorOpening(); return; } #elif defined USE_PDFIUM - pdfComic = new PdfiumComic(); + pdfComic = std::make_unique(); if (!pdfComic->openComic(_path)) { - delete pdfComic; emit errorOpening(); return; } #else - pdfComic = Poppler::Document::load(_path); + auto _pdfComic = Poppler::Document::load(_path); + pdfComic = std::unique_ptr(_pdfComic); + if (!pdfComic) { - // delete pdfComic; - // pdfComic = 0; moveToThread(QCoreApplication::instance()->thread()); emit errorOpening(); return; @@ -824,7 +822,6 @@ void PDFComic::process() return; } - // pdfComic->setRenderHint(Poppler::Document::Antialiasing, true); pdfComic->setRenderHint(Poppler::Document::TextAntialiasing, true); #endif @@ -853,7 +850,6 @@ void PDFComic::process() int buffered_index = _index; for (int i = buffered_index; i < nPages; i++) { if (_invalidated) { - delete pdfComic; moveToThread(QCoreApplication::instance()->thread()); return; } @@ -862,14 +858,12 @@ void PDFComic::process() } for (int i = 0; i < buffered_index; i++) { if (_invalidated) { - delete pdfComic; moveToThread(QCoreApplication::instance()->thread()); return; } renderPage(i); } - delete pdfComic; moveToThread(QCoreApplication::instance()->thread()); emit imagesLoaded(); } @@ -883,10 +877,9 @@ void PDFComic::renderPage(int page) QImage img = pdfComic->getPage(page); if (!img.isNull()) { #else - Poppler::Page *pdfpage = pdfComic->page(page); + std::unique_ptr pdfpage (pdfComic->page(page)); if (pdfpage) { QImage img = pdfpage->renderToImage(150, 150); - delete pdfpage; #endif QByteArray ba; QBuffer buf(&ba); diff --git a/common/comic.h b/common/comic.h index a64da6f5..9be08d43 100644 --- a/common/comic.h +++ b/common/comic.h @@ -165,11 +165,11 @@ class PDFComic : public Comic private: // pdf #if defined Q_OS_MAC && defined USE_PDFKIT - MacOSXPDFComic *pdfComic; + std::unique_ptr pdfComic; #elif defined USE_PDFIUM - PdfiumComic *pdfComic; + std::unique_ptr pdfComic; #else - Poppler::Document *pdfComic; + std::unique_ptr pdfComic; #endif void renderPage(int page); // void run(); From 4a59dd6db6b2372b83bced20650aea2ece56ff22 Mon Sep 17 00:00:00 2001 From: Felix Kauselmann Date: Sun, 13 Nov 2022 17:05:29 +0100 Subject: [PATCH 11/21] Add support for poppler-qt6 Fixes #352 --- CHANGELOG.md | 1 + .../initial_comic_info_extractor.cpp | 3 +- common/comic.cpp | 7 +++- common/comic.h | 3 +- common/pdf_comic.h | 5 +++ dependencies/pdf_backend.pri | 33 +++++++++++++------ 6 files changed, 38 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8de31e0e..61147e86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Version counting is based on semantic versioning (Major.Feature.Patch) ### All apps * Run logger in a dedicated thread to avoid segfaults at application shutdown +* Add support for poppler-qt6 pdf backend ## 9.10 diff --git a/YACReaderLibrary/initial_comic_info_extractor.cpp b/YACReaderLibrary/initial_comic_info_extractor.cpp index d25d84c4..63ee6a5b 100644 --- a/YACReaderLibrary/initial_comic_info_extractor.cpp +++ b/YACReaderLibrary/initial_comic_info_extractor.cpp @@ -27,7 +27,7 @@ void InitialComicInfoExtractor::extract() #ifndef NO_PDF if (fi.suffix().compare("pdf", Qt::CaseInsensitive) == 0) { #if defined Q_OS_MAC && defined USE_PDFKIT - auto pdfComic = std::make_unique(); + auto pdfComic = std::make_unique(); if (!pdfComic->openComic(_fileSource)) { return; } @@ -64,7 +64,6 @@ void InitialComicInfoExtractor::extract() saveCover(_target, p); } else if (_target != "") { QLOG_WARN() << "Extracting cover: requested cover index greater than numPages " << _fileSource; - } } return; diff --git a/common/comic.cpp b/common/comic.cpp index 26b3949e..059c6203 100644 --- a/common/comic.cpp +++ b/common/comic.cpp @@ -808,8 +808,13 @@ void PDFComic::process() return; } #else + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + pdfComic = Poppler::Document::load(_path); +#else auto _pdfComic = Poppler::Document::load(_path); pdfComic = std::unique_ptr(_pdfComic); +#endif if (!pdfComic) { moveToThread(QCoreApplication::instance()->thread()); @@ -877,7 +882,7 @@ void PDFComic::renderPage(int page) QImage img = pdfComic->getPage(page); if (!img.isNull()) { #else - std::unique_ptr pdfpage (pdfComic->page(page)); + std::unique_ptr pdfpage(pdfComic->page(page)); if (pdfpage) { QImage img = pdfpage->renderToImage(150, 150); #endif diff --git a/common/comic.h b/common/comic.h index 9be08d43..ae753a4c 100644 --- a/common/comic.h +++ b/common/comic.h @@ -12,7 +12,7 @@ #include "pdf_comic.h" #endif // NO_PDF class ComicDB; -//#define EXTENSIONS << "*.jpg" << "*.jpeg" << "*.png" << "*.gif" << "*.tiff" << "*.tif" << "*.bmp" Comic::getSupportedImageFormats() + //#define EXTENSIONS_LITERAL << ".jpg" << ".jpeg" << ".png" << ".gif" << ".tiff" << ".tif" << ".bmp" //Comic::getSupportedImageLiteralFormats() class Comic : public QObject { @@ -172,6 +172,7 @@ private: std::unique_ptr pdfComic; #endif void renderPage(int page); + // void run(); public: diff --git a/common/pdf_comic.h b/common/pdf_comic.h index 13febf5c..f2d8ff8c 100644 --- a/common/pdf_comic.h +++ b/common/pdf_comic.h @@ -5,6 +5,7 @@ #include #include #include +#include #if defined Q_OS_MAC && defined USE_PDFKIT class MacOSXPDFComic @@ -45,6 +46,10 @@ private: QFile pdfFile; }; #else +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include +#else #include "poppler-qt5.h" +#endif // QT_VERSION #endif // Q_OS_MAC #endif // PDF_COMIC_H diff --git a/dependencies/pdf_backend.pri b/dependencies/pdf_backend.pri index a14885bb..0905ede6 100644 --- a/dependencies/pdf_backend.pri +++ b/dependencies/pdf_backend.pri @@ -55,18 +55,31 @@ CONFIG(poppler) { LIBS += -L$$PWD/poppler/dependencies/bin } if(unix|mingw):!macx { - !contains(QT_CONFIG, no-pkg-config):packagesExist(poppler-qt5) { - message("Using system provided installation of poppler-qt5 found by pkg-config.") - CONFIG += link_pkgconfig - PKGCONFIG += poppler-qt5 - } else:!macx:exists(/usr/include/poppler/qt5) { - message("Using system provided installation of poppler-qt5.") - INCLUDEPATH += /usr/include/poppler/qt5 - LIBS += -lpoppler-qt5 + greaterThan (QT_MAJOR_VERSION, 5) { + !contains(QT_CONFIG, no-pkg-config):packagesExist(poppler-qt6) { + message("Using system provided installation of poppler-qt6 found by pkg-config.") + CONFIG += link_pkgconfig + PKGCONFIG += poppler-qt6 + } else:!macx:exists(/usr/include/poppler/qt6) { + message("Using system provided installation of poppler-qt6.") + INCLUDEPATH += /usr/include/poppler/qt6 + LIBS += -lpoppler-qt6 + } else { + error("Could not find poppler-qt6") + } } else { - error("Could not find poppler-qt5") + !contains(QT_CONFIG, no-pkg-config):packagesExist(poppler-qt5) { + message("Using system provided installation of poppler-qt5 found by pkg-config.") + CONFIG += link_pkgconfig + PKGCONFIG += poppler-qt5 + } else:!macx:exists(/usr/include/poppler/qt5) { + message("Using system provided installation of poppler-qt5.") + INCLUDEPATH += /usr/include/poppler/qt5 + LIBS += -lpoppler-qt5 + } else { + error("Could not find poppler-qt5") + } } - } unix:macx { error (Poppler backend is currently not supported on macOS) From d4f12ff066f1af1bf051cecff8c3ab7da7c17ef0 Mon Sep 17 00:00:00 2001 From: Felix Kauselmann Date: Fri, 18 Nov 2022 13:45:26 +0100 Subject: [PATCH 12/21] Fix poppler-qt6 setup for initial comic extractor --- YACReaderLibrary/initial_comic_info_extractor.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/YACReaderLibrary/initial_comic_info_extractor.cpp b/YACReaderLibrary/initial_comic_info_extractor.cpp index 63ee6a5b..11288a27 100644 --- a/YACReaderLibrary/initial_comic_info_extractor.cpp +++ b/YACReaderLibrary/initial_comic_info_extractor.cpp @@ -36,9 +36,13 @@ void InitialComicInfoExtractor::extract() if (!pdfComic->openComic(_fileSource)) { return; } +#else +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + auto pdfComic = Poppler::Document::load(_fileSource); #else auto _pdfComic = Poppler::Document::load(_fileSource); - auto pdfComic = std::unique_ptr(_pdfComic); + pdfComic = std::unique_ptr(_pdfComic); +#endif #endif if (!pdfComic) { QLOG_WARN() << "Extracting cover: unable to open PDF file " << _fileSource; From 06d744e88bf793afb30bc9e6961d7641a19640db Mon Sep 17 00:00:00 2001 From: Felix Kauselmann Date: Fri, 18 Nov 2022 14:50:42 +0100 Subject: [PATCH 13/21] Fix regression in poppler-qt5 build --- YACReaderLibrary/initial_comic_info_extractor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YACReaderLibrary/initial_comic_info_extractor.cpp b/YACReaderLibrary/initial_comic_info_extractor.cpp index 11288a27..763907f5 100644 --- a/YACReaderLibrary/initial_comic_info_extractor.cpp +++ b/YACReaderLibrary/initial_comic_info_extractor.cpp @@ -41,7 +41,7 @@ void InitialComicInfoExtractor::extract() auto pdfComic = Poppler::Document::load(_fileSource); #else auto _pdfComic = Poppler::Document::load(_fileSource); - pdfComic = std::unique_ptr(_pdfComic); + auto pdfComic = std::unique_ptr(_pdfComic); #endif #endif if (!pdfComic) { From fc1f48aaa5b7a4a9aafd822139211b80ab69baaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Mon, 12 Dec 2022 18:37:29 +0100 Subject: [PATCH 14/21] Remove image allocation limit This commit fixes this error: QImageIOHandler: Rejecting image as it exceeds the current allocation limit of 128 megabytes --- YACReader/main.cpp | 3 +++ YACReaderLibrary/main.cpp | 3 +++ YACReaderLibraryServer/main.cpp | 3 +++ 3 files changed, 9 insertions(+) diff --git a/YACReader/main.cpp b/YACReader/main.cpp index d7a2b48c..0bfe0a21 100644 --- a/YACReader/main.cpp +++ b/YACReader/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "main_window_viewer.h" #include "configuration.h" @@ -97,6 +98,8 @@ int main(int argc, char *argv[]) QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); + QImageReader::setAllocationLimit(0); + #if defined(_MSC_VER) && defined(_DEBUG) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif diff --git a/YACReaderLibrary/main.cpp b/YACReaderLibrary/main.cpp index 127242dd..29586e9e 100644 --- a/YACReaderLibrary/main.cpp +++ b/YACReaderLibrary/main.cpp @@ -11,6 +11,7 @@ #include #endif #include +#include #include "yacreader_global.h" #include "yacreader_http_server.h" @@ -130,6 +131,8 @@ int main(int argc, char **argv) QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); + QImageReader::setAllocationLimit(0); + QApplication app(argc, argv); #ifdef FORCE_ANGLE diff --git a/YACReaderLibraryServer/main.cpp b/YACReaderLibraryServer/main.cpp index df14beaa..b5ff93d4 100644 --- a/YACReaderLibraryServer/main.cpp +++ b/YACReaderLibraryServer/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "comic_db.h" #include "db_helper.h" @@ -81,6 +82,8 @@ int main(int argc, char **argv) QCoreApplication app(argc, argv); + QImageReader::setAllocationLimit(0); + app.setApplicationName("YACReaderLibrary"); app.setOrganizationName("YACReader"); From 7fed222cb76cbf5596b1a72748dced292efcc3bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Mon, 12 Dec 2022 21:53:07 +0100 Subject: [PATCH 15/21] Format --- YACReaderLibrary/import_widget.cpp | 2 +- YACReaderLibrary/library_window.cpp | 2 +- YACReaderLibrary/server/yacreader_http_server.cpp | 2 +- YACReaderLibraryServer/main.cpp | 2 +- common/comic.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/YACReaderLibrary/import_widget.cpp b/YACReaderLibrary/import_widget.cpp index 4a266268..7d721b48 100644 --- a/YACReaderLibrary/import_widget.cpp +++ b/YACReaderLibrary/import_widget.cpp @@ -11,7 +11,7 @@ #include #include // TODO: is QGLWidget needed here??? -//#include +// #include #include #include #include diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp index fa85756f..0ac891e6 100644 --- a/YACReaderLibrary/library_window.cpp +++ b/YACReaderLibrary/library_window.cpp @@ -59,7 +59,7 @@ #include "comic_vine_dialog.h" #include "api_key_dialog.h" -//#include "yacreader_social_dialog.h" +// #include "yacreader_social_dialog.h" #include "comics_view.h" diff --git a/YACReaderLibrary/server/yacreader_http_server.cpp b/YACReaderLibrary/server/yacreader_http_server.cpp index 40ba799d..3dd61cf7 100644 --- a/YACReaderLibrary/server/yacreader_http_server.cpp +++ b/YACReaderLibrary/server/yacreader_http_server.cpp @@ -5,7 +5,7 @@ #include "static.h" #include "yacreader_http_server.h" -//#include "dualfilelogger.h" +// #include "dualfilelogger.h" #include "httplistener.h" #include "requestmapper.h" #include "staticfilecontroller.h" diff --git a/YACReaderLibraryServer/main.cpp b/YACReaderLibraryServer/main.cpp index b5ff93d4..28ee5cf3 100644 --- a/YACReaderLibraryServer/main.cpp +++ b/YACReaderLibraryServer/main.cpp @@ -1,4 +1,4 @@ -//#include +// #include #include #include #include diff --git a/common/comic.h b/common/comic.h index ae753a4c..170cc885 100644 --- a/common/comic.h +++ b/common/comic.h @@ -13,7 +13,7 @@ #endif // NO_PDF class ComicDB; -//#define EXTENSIONS_LITERAL << ".jpg" << ".jpeg" << ".png" << ".gif" << ".tiff" << ".tif" << ".bmp" //Comic::getSupportedImageLiteralFormats() +// #define EXTENSIONS_LITERAL << ".jpg" << ".jpeg" << ".png" << ".gif" << ".tiff" << ".tif" << ".bmp" //Comic::getSupportedImageLiteralFormats() class Comic : public QObject { Q_OBJECT From 250c48848c3761a4488031ceeb563634960d0092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Mon, 12 Dec 2022 22:07:30 +0100 Subject: [PATCH 16/21] setAllocationLimit is Qt6 only --- YACReader/main.cpp | 2 ++ YACReaderLibrary/main.cpp | 2 ++ YACReaderLibraryServer/main.cpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/YACReader/main.cpp b/YACReader/main.cpp index 0bfe0a21..521c9dbf 100644 --- a/YACReader/main.cpp +++ b/YACReader/main.cpp @@ -98,7 +98,9 @@ int main(int argc, char *argv[]) QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QImageReader::setAllocationLimit(0); +#endif #if defined(_MSC_VER) && defined(_DEBUG) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); diff --git a/YACReaderLibrary/main.cpp b/YACReaderLibrary/main.cpp index 29586e9e..70e01b25 100644 --- a/YACReaderLibrary/main.cpp +++ b/YACReaderLibrary/main.cpp @@ -131,7 +131,9 @@ int main(int argc, char **argv) QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QImageReader::setAllocationLimit(0); +#endif QApplication app(argc, argv); diff --git a/YACReaderLibraryServer/main.cpp b/YACReaderLibraryServer/main.cpp index 28ee5cf3..bda5e416 100644 --- a/YACReaderLibraryServer/main.cpp +++ b/YACReaderLibraryServer/main.cpp @@ -82,7 +82,9 @@ int main(int argc, char **argv) QCoreApplication app(argc, argv); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QImageReader::setAllocationLimit(0); +#endif app.setApplicationName("YACReaderLibrary"); app.setOrganizationName("YACReader"); From 0afe2c33b72d0e7ae2919671d89bcc14b934b59e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 27 Dec 2022 09:26:55 +0100 Subject: [PATCH 17/21] Fix currentPage value when closing YACReader in double page mode If the latest page of the comic is visible, that should be the currentPage value so YACReaderLibrary can mark the comic as read. --- YACReader/viewer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/YACReader/viewer.cpp b/YACReader/viewer.cpp index 4894f25b..34598e47 100644 --- a/YACReader/viewer.cpp +++ b/YACReader/viewer.cpp @@ -1128,7 +1128,9 @@ void Viewer::updateComic(ComicDB &comic) if (!doublePage || (doublePage && render->currentPageIsDoublePage() == false)) { comic.info.currentPage = render->getIndex() + 1; } else { - if (!(render->getIndex() + 1 == comic.info.currentPage || render->getIndex() + 2 == comic.info.currentPage)) { + if (doublePage && render->currentPageIsDoublePage() && (render->getIndex() + 2 >= render->numPages())) { + comic.info.currentPage = std::min(render->numPages(), render->getIndex() + 2); + } else { comic.info.currentPage = std::min(render->numPages(), render->getIndex() + 1); } } From 399f4fd89f8c34d91eb3a6f2acbc74db923a3371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 27 Dec 2022 09:34:22 +0100 Subject: [PATCH 18/21] Update CHANGELOG --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61147e86..62945bc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,9 @@ Version counting is based on semantic versioning (Major.Feature.Patch) ## WIP ### YACReader -*Fix segfault (or worse) when exiting YACReader while processing a comic +* Fix segfault (or worse) when exiting YACReader while processing a comic +* Fix last read page calculation in double page mode. + ### YACReaderLibrary * Fixed drag&drop in the comics grid view. * Detect back/forward mouse buttons to move back and forward through the browsing history. @@ -13,6 +15,7 @@ Version counting is based on semantic versioning (Major.Feature.Patch) ### All apps * Run logger in a dedicated thread to avoid segfaults at application shutdown * Add support for poppler-qt6 pdf backend +* Remove image allocation limit. ## 9.10 From 5ddfa2c4f5609b9677b9cd0be4d1121acf96e597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Thu, 29 Dec 2022 08:26:34 +0100 Subject: [PATCH 19/21] Update CHANGELOG --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62945bc8..7c1a5b86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,13 @@ Version counting is based on semantic versioning (Major.Feature.Patch) ## WIP ### YACReader -* Fix segfault (or worse) when exiting YACReader while processing a comic +* Fix segfault (or worse) when exiting YACReader while processing a comic. * Fix last read page calculation in double page mode. ### YACReaderLibrary -* Fixed drag&drop in the comics grid view. +* Fix drag&drop in the comics grid view. * Detect back/forward mouse buttons to move back and forward through the browsing history. +* Fix crash when disabling the server. ### All apps * Run logger in a dedicated thread to avoid segfaults at application shutdown From 308fb22fd9a24ea54af7015c2fcd14cf68a61b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 3 Jan 2023 13:10:38 +0100 Subject: [PATCH 20/21] Bump vcredist version and hope that installation is fixed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit “X64 VC Redist no longer removes runtime files when run with /installer /passive switches.” --- azure-pipelines-windows-template-qt6.yml | 2 +- azure-pipelines-windows-template.yml | 2 +- azure-pipelines.yml | 6 +++--- ci/win/build_installer.iss | 4 ---- ci/win/build_installer_qt6.iss | 4 ---- 5 files changed, 5 insertions(+), 13 deletions(-) diff --git a/azure-pipelines-windows-template-qt6.yml b/azure-pipelines-windows-template-qt6.yml index c0621956..af4f0905 100644 --- a/azure-pipelines-windows-template-qt6.yml +++ b/azure-pipelines-windows-template-qt6.yml @@ -4,7 +4,7 @@ parameters: qt_version: '6.2.2' qt_spec: 'msvc2019_64' qt_aqt_spec: 'win64_msvc2019_64' - vc_redist_url: 'https://aka.ms/vs/16/release/vc_redist.x64.exe' + vc_redist_url: 'https://aka.ms/vs/17/release/vc_redist.x64.exe' vc_redist_file_name: 'vc_redist.x64.exe' vc_vars: 'vcvars64.bat' diff --git a/azure-pipelines-windows-template.yml b/azure-pipelines-windows-template.yml index 550eeaec..c39b000a 100644 --- a/azure-pipelines-windows-template.yml +++ b/azure-pipelines-windows-template.yml @@ -4,7 +4,7 @@ parameters: qt_version: '5.15.2' qt_spec: 'msvc2019_64' qt_aqt_spec: 'win64_msvc2019_64' - vc_redist_url: 'https://aka.ms/vs/16/release/vc_redist.x64.exe' + vc_redist_url: 'https://aka.ms/vs/17/release/vc_redist.x64.exe' vc_redist_file_name: 'vc_redist.x64.exe' vc_vars: 'vcvars64.bat' diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a2be1786..248acbc1 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -234,7 +234,7 @@ jobs: qt_version: '5.15.2' qt_spec: 'msvc2019_64' qt_aqt_spec: 'win64_msvc2019_64' - vc_redist_url: 'https://aka.ms/vs/16/release/vc_redist.x64.exe' + vc_redist_url: 'https://aka.ms/vs/17/release/vc_redist.x64.exe' vc_redist_file_name: 'vc_redist.x64.exe' vc_vars: 'vcvars64.bat' @@ -249,7 +249,7 @@ jobs: qt_version: '6.3.1' qt_spec: 'msvc2019_64' qt_aqt_spec: 'win64_msvc2019_64' - vc_redist_url: 'https://aka.ms/vs/16/release/vc_redist.x64.exe' + vc_redist_url: 'https://aka.ms/vs/17/release/vc_redist.x64.exe' vc_redist_file_name: 'vc_redist.x64.exe' vc_vars: 'vcvars64.bat' @@ -264,7 +264,7 @@ jobs: qt_version: '5.15.2' qt_spec: 'msvc2019' qt_aqt_spec: 'win32_msvc2019' - vc_redist_url: 'https://aka.ms/vs/16/release/vc_redist.x86.exe' + vc_redist_url: 'https://aka.ms/vs/17/release/vc_redist.x86.exe' vc_redist_file_name: 'vc_redist.x86.exe' vc_vars: 'vcvars32.bat' diff --git a/ci/win/build_installer.iss b/ci/win/build_installer.iss index 45f60110..88a7e67f 100644 --- a/ci/win/build_installer.iss +++ b/ci/win/build_installer.iss @@ -115,10 +115,6 @@ LaunchYACReaderLibrary=Start YACreaderLibrary after finishing installation LaunchYACReader=Start YACreader after finishing installation [Run] -Filename: {tmp}\vc_redist.{#PLATFORM}.exe; \ -Parameters: "/uninstall /quiet /norestart"; \ -StatusMsg: "Uninstalling VC++ Redistributables..." - Filename: {tmp}\vc_redist.{#PLATFORM}.exe; \ Parameters: "/install /quiet /norestart"; \ StatusMsg: "Installing VC++ Redistributables..." diff --git a/ci/win/build_installer_qt6.iss b/ci/win/build_installer_qt6.iss index 05534151..6ca80f80 100644 --- a/ci/win/build_installer_qt6.iss +++ b/ci/win/build_installer_qt6.iss @@ -124,10 +124,6 @@ LaunchYACReaderLibrary=Start YACreaderLibrary after finishing installation LaunchYACReader=Start YACreader after finishing installation [Run] -Filename: {tmp}\vc_redist.{#PLATFORM}.exe; \ -Parameters: "/uninstall /quiet /norestart"; \ -StatusMsg: "Uninstalling VC++ Redistributables..." - Filename: {tmp}\vc_redist.{#PLATFORM}.exe; \ Parameters: "/install /quiet /norestart"; \ StatusMsg: "Installing VC++ Redistributables..." From 49ef617757f5e4a61755604d18639d5eaa206846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sat, 7 Jan 2023 10:34:34 +0100 Subject: [PATCH 21/21] Bump version number and what's new --- common/yacreader_global.h | 2 +- custom_widgets/whats_new_dialog.cpp | 23 +++++++++-------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/common/yacreader_global.h b/common/yacreader_global.h index d2f35f97..8bddd9a7 100644 --- a/common/yacreader_global.h +++ b/common/yacreader_global.h @@ -6,7 +6,7 @@ #include #include -#define VERSION "9.10.0" +#define VERSION "9.11.0" #define REMOTE_BROWSE_PERFORMANCE_WORKAROUND "REMOTE_BROWSE_PERFORMANCE_WORKAROUND" #define IMPORT_COMIC_INFO_XML_METADATA "IMPORT_COMIC_INFO_XML_METADATA" diff --git a/custom_widgets/whats_new_dialog.cpp b/custom_widgets/whats_new_dialog.cpp index 42e36dcf..5d1e57a2 100644 --- a/custom_widgets/whats_new_dialog.cpp +++ b/custom_widgets/whats_new_dialog.cpp @@ -46,25 +46,20 @@ YACReader::WhatsNewDialog::WhatsNewDialog(QWidget *parent) "color:#858585;"); auto text = new QLabel(); - text->setText("New release with the following updates:
" + text->setText("A small update with a bunch of fixes:
" "
" "YACReader
" - " • Fixed color selection dialog appearing as a subwindow in macos.
" - " • Better support for HDPI screens (SVG icons).
" + " • Fix crash when exiting YACReader while it is processing a comic.
" + " • Fix last read page calculation in double page mode.
" "
" "YACReaderLibrary
" - " • New folder content view that replaces the old `subfolders in this folder` view shown when folders don't have direct comics. You may need to update your libraries to make folders display properly.
" - " • Continue Reading view that it is shown for the root folder.
" - " • UI gets updated when YACReaderLibrary gets updates from YACReader or YACReader for iOS.
" - " • Fixed going forward history navigation.
" - " • Fixed selected folder restoration after folder updates.
" - " • Add option to delete metadata from comics.
" - " • Better support for HDPI screens (SVG icons).
" - " • Importing ComicInfo.XML is now optional, you can change the behavior in Settings -> General.
" - " • Add option to scan XML metadata from all the comics in a folder.
" + " • Fix drag&drop in the comics grid view.
" + " • Detect back/forward mouse buttons to move back and forward through the browsing history.
" + " • Fix crash when disabling the server.
" "
" - "Server
" - " • New webui status page (reachable by navigating to server::port/webui).
" + "All apps
" + " • Add support for poppler-qt6 pdf backend (only relevat if you are building YACReader yourself).
" + " • Remove image allocation limit in Qt6.
" "
" "NOTE: Importing metadata from ComicInfo.XML in now disabled by default, if you want you can enable it Settings -> General.
" "
"