From 435d47bb74185dd92951a81c044e69bb2071da5e Mon Sep 17 00:00:00 2001 From: Le Tan Date: Tue, 1 Nov 2016 21:32:30 +0800 Subject: [PATCH] support downloading image from URL Signed-off-by: Le Tan --- src/dialog/vinsertimagedialog.cpp | 12 +++ src/dialog/vinsertimagedialog.h | 5 ++ src/src.pro | 8 +- src/vdownloader.cpp | 23 +++++ src/vdownloader.h | 29 +++++++ src/vmdeditoperations.cpp | 140 +++++++++++++++++++----------- src/vmdeditoperations.h | 7 +- 7 files changed, 171 insertions(+), 53 deletions(-) create mode 100644 src/vdownloader.cpp create mode 100644 src/vdownloader.h diff --git a/src/dialog/vinsertimagedialog.cpp b/src/dialog/vinsertimagedialog.cpp index eb12598f..111a4cd0 100644 --- a/src/dialog/vinsertimagedialog.cpp +++ b/src/dialog/vinsertimagedialog.cpp @@ -118,3 +118,15 @@ void VInsertImageDialog::setBrowseable(bool browseable) pathEdit->setVisible(browseable); browseBtn->setVisible(browseable); } + +void VInsertImageDialog::imageDownloaded(const QByteArray &data) +{ + setImage(QImage::fromData(data)); +} + +QImage VInsertImageDialog::getImage() const +{ + if (!image) { + return QImage(); + } else return *image; +} diff --git a/src/dialog/vinsertimagedialog.h b/src/dialog/vinsertimagedialog.h index 04a9985a..6e3342d1 100644 --- a/src/dialog/vinsertimagedialog.h +++ b/src/dialog/vinsertimagedialog.h @@ -4,6 +4,7 @@ #include #include #include +#include class QLabel; class QLineEdit; @@ -21,8 +22,12 @@ public: QString getPathInput() const; void setImage(const QImage &image); + QImage getImage() const; void setBrowseable(bool browseable); +public slots: + void imageDownloaded(const QByteArray &data); + private slots: void enableOkButton(); void handleBrowseBtnClicked(); diff --git a/src/src.pro b/src/src.pro index 7bc6e0f6..ed1aac0e 100644 --- a/src/src.pro +++ b/src/src.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui webenginewidgets webchannel +QT += core gui webenginewidgets webchannel network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -39,7 +39,8 @@ SOURCES += main.cpp\ dialog/vfileinfodialog.cpp \ veditoperations.cpp \ vmdeditoperations.cpp \ - dialog/vinsertimagedialog.cpp + dialog/vinsertimagedialog.cpp \ + vdownloader.cpp HEADERS += vmainwindow.h \ vdirectorytree.h \ @@ -69,7 +70,8 @@ HEADERS += vmainwindow.h \ dialog/vfileinfodialog.h \ veditoperations.h \ vmdeditoperations.h \ - dialog/vinsertimagedialog.h + dialog/vinsertimagedialog.h \ + vdownloader.h RESOURCES += \ vnote.qrc diff --git a/src/vdownloader.cpp b/src/vdownloader.cpp new file mode 100644 index 00000000..5c2f144d --- /dev/null +++ b/src/vdownloader.cpp @@ -0,0 +1,23 @@ +#include "vdownloader.h" + +VDownloader::VDownloader(QObject *parent) + : QObject(parent) +{ + connect(&webCtrl, &QNetworkAccessManager::finished, + this, &VDownloader::handleDownloadFinished); +} + +void VDownloader::handleDownloadFinished(QNetworkReply *reply) +{ + data = reply->readAll(); + reply->deleteLater(); + emit downloadFinished(data); +} + +void VDownloader::download(QUrl url) +{ + Q_ASSERT(url.isValid()); + QNetworkRequest request(url); + webCtrl.get(request); + qDebug() << "VDownloader get" << url.toString(); +} diff --git a/src/vdownloader.h b/src/vdownloader.h new file mode 100644 index 00000000..287daf8e --- /dev/null +++ b/src/vdownloader.h @@ -0,0 +1,29 @@ +#ifndef VDOWNLOADER_H +#define VDOWNLOADER_H + +#include +#include +#include +#include +#include +#include + +class VDownloader : public QObject +{ + Q_OBJECT +public: + explicit VDownloader(QObject *parent = 0); + void download(QUrl url); + +signals: + void downloadFinished(const QByteArray &data); + +private slots: + void handleDownloadFinished(QNetworkReply *reply); + +private: + QNetworkAccessManager webCtrl; + QByteArray data; +}; + +#endif // VDOWNLOADER_H diff --git a/src/vmdeditoperations.cpp b/src/vmdeditoperations.cpp index b89e6829..bfad7605 100644 --- a/src/vmdeditoperations.cpp +++ b/src/vmdeditoperations.cpp @@ -12,6 +12,7 @@ #include "vnotefile.h" #include "utils/vutils.h" #include "vedit.h" +#include "vdownloader.h" VMdEditOperations::VMdEditOperations(VEdit *editor, VNoteFile *noteFile) : VEditOperations(editor, noteFile) @@ -29,55 +30,96 @@ bool VMdEditOperations::insertImageFromMimeData(const QMimeData *source) dialog.setBrowseable(false); dialog.setImage(image); if (dialog.exec() == QDialog::Accepted) { - QString title = dialog.getImageTitleInput(); - QString path = QDir::cleanPath(QDir(noteFile->basePath).filePath("images")); - QString fileName = VUtils::generateImageFileName(path, title); - qDebug() << "insert image" << path << title << fileName; - QString filePath = QDir(path).filePath(fileName); - Q_ASSERT(!QFile(filePath).exists()); - bool ret = image.save(filePath); - if (!ret) { - QMessageBox msgBox(QMessageBox::Warning, QObject::tr("Warning"), QString("Fail to save image %1").arg(filePath), - QMessageBox::Ok, (QWidget *)editor); - msgBox.exec(); - return true; - } - - QString md = QString("![%1](images/%2)").arg(title).arg(fileName); - insertTextAtCurPos(md); + insertImageFromQImage(dialog.getImageTitleInput(), + QDir::cleanPath(QDir(noteFile->basePath).filePath("images")), + image); } return true; } -bool VMdEditOperations::insertImageFromPath(const QString &imagePath) +void VMdEditOperations::insertImageFromQImage(const QString &title, const QString &path, + const QImage &image) { - QImage image(imagePath); - if (image.isNull()) { - qWarning() << "error: image is null"; - return false; + QString fileName = VUtils::generateImageFileName(path, title); + qDebug() << "insert image" << path << title << fileName; + QString filePath = QDir(path).filePath(fileName); + Q_ASSERT(!QFile(filePath).exists()); + bool ret = image.save(filePath); + if (!ret) { + QMessageBox msgBox(QMessageBox::Warning, QObject::tr("Warning"), QString("Fail to save image %1").arg(filePath), + QMessageBox::Ok, (QWidget *)editor); + msgBox.exec(); + return; } - VInsertImageDialog dialog(QObject::tr("Insert image from file"), QObject::tr("image_title"), - "", (QWidget *)editor); - dialog.setBrowseable(false); - dialog.setImage(image); - if (dialog.exec() == QDialog::Accepted) { - QString title = dialog.getImageTitleInput(); - QString path = QDir::cleanPath(QDir(noteFile->basePath).filePath("images")); - QString fileName = VUtils::generateImageFileName(path, title, QFileInfo(imagePath).suffix()); - qDebug() << "insert image" << path << title << fileName; - QString filePath = QDir(path).filePath(fileName); - Q_ASSERT(!QFile(filePath).exists()); - bool ret = QFile::copy(imagePath, filePath); - if (!ret) { - qWarning() << "error: fail to copy" << imagePath << "to" << filePath; - QMessageBox msgBox(QMessageBox::Warning, QObject::tr("Warning"), QString("Fail to save image %1").arg(filePath), - QMessageBox::Ok, (QWidget *)editor); - msgBox.exec(); + + QString md = QString("![%1](images/%2)").arg(title).arg(fileName); + insertTextAtCurPos(md); +} + +void VMdEditOperations::insertImageFromPath(const QString &title, + const QString &path, const QString &oriImagePath) +{ + QString fileName = VUtils::generateImageFileName(path, title, QFileInfo(oriImagePath).suffix()); + qDebug() << "insert image" << path << title << fileName << oriImagePath; + QString filePath = QDir(path).filePath(fileName); + Q_ASSERT(!QFile(filePath).exists()); + bool ret = QFile::copy(oriImagePath, filePath); + if (!ret) { + qWarning() << "error: fail to copy" << oriImagePath << "to" << filePath; + QMessageBox msgBox(QMessageBox::Warning, QObject::tr("Warning"), QString("Fail to save image %1").arg(filePath), + QMessageBox::Ok, (QWidget *)editor); + msgBox.exec(); + return; + } + + QString md = QString("![%1](images/%2)").arg(title).arg(fileName); + insertTextAtCurPos(md); +} + +bool VMdEditOperations::insertImageFromURL(const QUrl &imageUrl) +{ + QString imagePath; + QImage image; + bool isLocal = imageUrl.isLocalFile(); + QString title; + + // Whether it is a local file or web URL + if (isLocal) { + imagePath = imageUrl.toLocalFile(); + image = QImage(imagePath); + + if (image.isNull()) { + qWarning() << "error: image is null"; return false; } + title = "Insert image from file"; + } else { + imagePath = imageUrl.toString(); + title = "Insert image from network"; + } - QString md = QString("![%1](images/%2)").arg(title).arg(fileName); - insertTextAtCurPos(md); + + VInsertImageDialog dialog(title, QObject::tr("image_title"), imagePath, (QWidget *)editor); + dialog.setBrowseable(false); + if (isLocal) { + dialog.setImage(image); + } else { + // Download it to a QImage + VDownloader *downloader = new VDownloader(&dialog); + QObject::connect(downloader, &VDownloader::downloadFinished, + &dialog, &VInsertImageDialog::imageDownloaded); + downloader->download(imageUrl.toString()); + } + if (dialog.exec() == QDialog::Accepted) { + if (isLocal) { + insertImageFromPath(dialog.getImageTitleInput(), + QDir::cleanPath(QDir(noteFile->basePath).filePath("images")), + imagePath); + } else { + insertImageFromQImage(dialog.getImageTitleInput(), + QDir::cleanPath(QDir(noteFile->basePath).filePath("images")), + dialog.getImage()); + } } return true; } @@ -85,17 +127,17 @@ bool VMdEditOperations::insertImageFromPath(const QString &imagePath) bool VMdEditOperations::insertURLFromMimeData(const QMimeData *source) { foreach (QUrl url, source->urls()) { + QString urlStr; if (url.isLocalFile()) { - QFileInfo info(url.toLocalFile()); - if (QImageReader::supportedImageFormats().contains(info.suffix().toLower().toLatin1())) { - insertImageFromPath(info.filePath()); - } else { - insertTextAtCurPos(url.toLocalFile()); - } + urlStr = url.toLocalFile(); } else { - // TODO: download http image - // Just insert the URL for non-image - insertTextAtCurPos(url.toString()); + urlStr = url.toString(); + } + QFileInfo info(urlStr); + if (QImageReader::supportedImageFormats().contains(info.suffix().toLower().toLatin1())) { + insertImageFromURL(url); + } else { + insertTextAtCurPos(urlStr); } } return true; diff --git a/src/vmdeditoperations.h b/src/vmdeditoperations.h index 4838e1a6..12f48dd9 100644 --- a/src/vmdeditoperations.h +++ b/src/vmdeditoperations.h @@ -2,6 +2,9 @@ #define VMDEDITOPERATIONS_H #include +#include +#include +#include #include "veditoperations.h" // Editor operations for Markdown @@ -11,7 +14,9 @@ public: VMdEditOperations(VEdit *editor, VNoteFile *noteFile); bool insertImageFromMimeData(const QMimeData *source) Q_DECL_OVERRIDE; bool insertURLFromMimeData(const QMimeData *source) Q_DECL_OVERRIDE; - bool insertImageFromPath(const QString &imagePath); + bool insertImageFromURL(const QUrl &imageUrl); + void insertImageFromPath(const QString &title, const QString &path, const QString &oriImagePath); + void insertImageFromQImage(const QString &title, const QString &path, const QImage &image); }; #endif // VMDEDITOPERATIONS_H