From 8b159c9da69cb6a07b24cab87f21b9439cd5d8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Fri, 9 May 2025 19:58:52 +0200 Subject: [PATCH] Support drag&drop for setting a custom cover in the properties dialog --- YACReaderLibrary/properties_dialog.cpp | 8 +++- YACReaderLibrary/properties_dialog.h | 7 +++- common/yacreader_global_gui.cpp | 37 +++++++++++++++++++ common/yacreader_global_gui.h | 1 + .../custom_widgets_yacreaderlibrary.pri | 7 ++-- custom_widgets/yacreader_cover_label.cpp | 31 ++++++++++++++++ custom_widgets/yacreader_cover_label.h | 29 +++++++++++++++ 7 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 custom_widgets/yacreader_cover_label.cpp create mode 100644 custom_widgets/yacreader_cover_label.h diff --git a/YACReaderLibrary/properties_dialog.cpp b/YACReaderLibrary/properties_dialog.cpp index d0eea83a..b86b0d6c 100644 --- a/YACReaderLibrary/properties_dialog.cpp +++ b/YACReaderLibrary/properties_dialog.cpp @@ -8,6 +8,7 @@ #include "yacreader_field_edit.h" #include "yacreader_field_plain_text_edit.h" #include "db_helper.h" +#include "yacreader_cover_label.h" #include #include @@ -39,7 +40,8 @@ PropertiesDialog::PropertiesDialog(QWidget *parent) createTabBar(); auto rootLayout = new QGridLayout; - cover = new QLabel(); + cover = new YACReader::CoverLabel(); + connect(cover, &YACReader::CoverLabel::imageDropped, this, &PropertiesDialog::loadCustomCoverImageFromPath); mainLayout = new QGridLayout; mainLayout->addWidget(tabBar, 0, 0); @@ -1165,7 +1167,11 @@ void PropertiesDialog::resetCover() void PropertiesDialog::loadCustomCoverImage() { auto path = YACReader::imageFileLoader(this); + loadCustomCoverImageFromPath(path); +} +void PropertiesDialog::loadCustomCoverImageFromPath(const QString &path) +{ if (path.isEmpty()) { return; } diff --git a/YACReaderLibrary/properties_dialog.h b/YACReaderLibrary/properties_dialog.h index 8d95f08d..b90734fe 100644 --- a/YACReaderLibrary/properties_dialog.h +++ b/YACReaderLibrary/properties_dialog.h @@ -19,6 +19,10 @@ class QComboBox; // class YACReaderBusyWidget; class QToolButton; +namespace YACReader { +class CoverLabel; +} + #include "comic_db.h" class PropertiesDialog : public QDialog @@ -33,7 +37,7 @@ private: QTabWidget *tabBar; QWidget *coverBox; - QLabel *cover; + YACReader::CoverLabel *cover; QScrollArea *sa; QWidget *generalInfoBox; @@ -175,6 +179,7 @@ public slots: void loadPreviousCover(); void resetCover(); void loadCustomCoverImage(); + void loadCustomCoverImageFromPath(const QString &path); void setCoverPage(int pageNumber); bool close(); diff --git a/common/yacreader_global_gui.cpp b/common/yacreader_global_gui.cpp index a196ab1c..a5c08f2f 100644 --- a/common/yacreader_global_gui.cpp +++ b/common/yacreader_global_gui.cpp @@ -111,3 +111,40 @@ QString YACReader::imageFileLoader(QWidget *parent) return QFileDialog::getOpenFileName(parent, QObject::tr("Select custom cover"), QDir::homePath(), QObject::tr("Images (%1)").arg(supportedImageFormatsString)); } + +QString YACReader::imagePathFromMimeData(const QMimeData *mimeData) +{ + QString filePath; + + // Check for URLs (drag from browser or file explorer) + if (mimeData->hasUrls()) { + QList urlList = mimeData->urls(); + + // We only handle the first URL for simplicity + if (!urlList.isEmpty()) { + QUrl url = urlList.first(); + if (url.isLocalFile()) { + filePath = url.toLocalFile(); + + // Verify it's an image file using the extension + QFileInfo fileInfo(filePath); + QString extension = fileInfo.suffix().toLower(); + QList supportedFormats = QImageReader::supportedImageFormats(); + bool isSupported = false; + + for (const QByteArray &format : supportedFormats) { + if (extension == QString(format).toLower()) { + isSupported = true; + break; + } + } + + if (!isSupported) { + filePath.clear(); // Not a supported image format + } + } + } + } + + return filePath; +} diff --git a/common/yacreader_global_gui.h b/common/yacreader_global_gui.h index c4758204..b6bedfd4 100644 --- a/common/yacreader_global_gui.h +++ b/common/yacreader_global_gui.h @@ -113,5 +113,6 @@ QString addExtensionToIconPathInToolbar(const QString &path); QAction *actionWithCustomIcon(const QIcon &icon, QAction *action); QPixmap hdpiPixmap(const QString &file, QSize size); QString imageFileLoader(QWidget *parent); +QString imagePathFromMimeData(const QMimeData *mimeData); } #endif diff --git a/custom_widgets/custom_widgets_yacreaderlibrary.pri b/custom_widgets/custom_widgets_yacreaderlibrary.pri index 0ea43ca6..1b218b77 100644 --- a/custom_widgets/custom_widgets_yacreaderlibrary.pri +++ b/custom_widgets/custom_widgets_yacreaderlibrary.pri @@ -21,7 +21,8 @@ HEADERS += \ $$PWD/yacreader_library_list_widget.h \ $$PWD/yacreader_library_item_widget.h \ $$PWD/yacreader_treeview.h \ - $$PWD/yacreader_busy_widget.h + $$PWD/yacreader_busy_widget.h \ + $$PWD/yacreader_cover_label.h !CONFIG(no_opengl){ HEADERS += $$PWD/yacreader_gl_flow_config_widget.h } @@ -50,8 +51,8 @@ SOURCES += \ $$PWD/yacreader_library_list_widget.cpp \ $$PWD/yacreader_library_item_widget.cpp \ $$PWD/yacreader_treeview.cpp \ - $$PWD/yacreader_busy_widget.cpp - + $$PWD/yacreader_busy_widget.cpp \ + $$PWD/yacreader_cover_label.cpp !CONFIG(no_opengl){ SOURCES += $$PWD/yacreader_gl_flow_config_widget.cpp } diff --git a/custom_widgets/yacreader_cover_label.cpp b/custom_widgets/yacreader_cover_label.cpp new file mode 100644 index 00000000..63a2db7a --- /dev/null +++ b/custom_widgets/yacreader_cover_label.cpp @@ -0,0 +1,31 @@ +#include "yacreader_cover_label.h" +#include "yacreader_global_gui.h" + +YACReader::CoverLabel::CoverLabel(QWidget *parent) + : QLabel(parent) +{ + setAcceptDrops(true); +} + +void YACReader::CoverLabel::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasUrls() && !YACReader::imagePathFromMimeData(event->mimeData()).isEmpty()) { + event->acceptProposedAction(); + } +} + +void YACReader::CoverLabel::dragMoveEvent(QDragMoveEvent *event) +{ + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } +} + +void YACReader::CoverLabel::dropEvent(QDropEvent *event) +{ + QString path = YACReader::imagePathFromMimeData(event->mimeData()); + if (!path.isEmpty()) { + emit imageDropped(path); + event->acceptProposedAction(); + } +} diff --git a/custom_widgets/yacreader_cover_label.h b/custom_widgets/yacreader_cover_label.h new file mode 100644 index 00000000..8d570c9f --- /dev/null +++ b/custom_widgets/yacreader_cover_label.h @@ -0,0 +1,29 @@ +#ifndef DROP_LABEL_H +#define DROP_LABEL_H + +#include +#include +#include +#include + +namespace YACReader { + +class CoverLabel : public QLabel +{ + Q_OBJECT + +public: + explicit CoverLabel(QWidget *parent = nullptr); + +protected: + void dragEnterEvent(QDragEnterEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + void dropEvent(QDropEvent *event) override; + +signals: + void imageDropped(const QString &path); +}; + +} + +#endif // DROP_LABEL_H