From a85c39aa260a3e21a367ddec33a6c9a91d32089b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=AF=E6=96=87=E5=8D=8E?= <807296772@qq.com> Date: Fri, 8 Nov 2019 22:17:53 +0800 Subject: [PATCH] Image hosting code refactoring (#1032) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 将图床单独提取出来成为一个类 * Split the image hosting code into two classes * change null to parent * delect empty line,add p_,rename file and so on --- src/resources/vnote.ini | 4 +- src/src.pro | 2 + src/vimagehosting.cpp | 692 ++++++++++++++++++++++++++++++++++++++++ src/vimagehosting.h | 131 ++++++++ src/vmdtab.cpp | 659 +------------------------------------- src/vmdtab.h | 61 +--- 6 files changed, 836 insertions(+), 713 deletions(-) create mode 100644 src/vimagehosting.cpp create mode 100644 src/vimagehosting.h diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini index c0f60fbb..d98afe80 100644 --- a/src/resources/vnote.ini +++ b/src/resources/vnote.ini @@ -1,9 +1,9 @@ [global] -; Wechat ImageBed +; Wechat Image Hosting wechat_appid= wechat_secret= wechat_markdown_to_wechat_tool_url= -; Github ImageBed +; Github Image Hosting github_personal_access_token= github_repos_name= github_user_name= diff --git a/src/src.pro b/src/src.pro index 631d98e0..f0cef11e 100644 --- a/src/src.pro +++ b/src/src.pro @@ -28,6 +28,7 @@ TRANSLATIONS += translations/vnote_zh_CN.ts \ } SOURCES += main.cpp\ + vimagehosting.cpp \ vmainwindow.cpp \ vdirectorytree.cpp \ vnote.cpp \ @@ -165,6 +166,7 @@ SOURCES += main.cpp\ HEADERS += vmainwindow.h \ vdirectorytree.h \ + vimagehosting.h \ vnote.h \ vnotebook.h \ dialog/vnewdirdialog.h \ diff --git a/src/vimagehosting.cpp b/src/vimagehosting.cpp new file mode 100644 index 00000000..2ff29d9f --- /dev/null +++ b/src/vimagehosting.cpp @@ -0,0 +1,692 @@ +#include "vimagehosting.h" +#include "utils/vutils.h" +#include "vedittab.h" + +extern VConfigManager *g_config; + +VGithubImageHosting::VGithubImageHosting(VFile *p_file, QWidget *p_parent) + :QObject(p_parent), + m_file(p_file) +{ + reply = Q_NULLPTR; + imageUploaded = false; +} + +void VGithubImageHosting::handleUploadImageToGithubRequested() +{ + qDebug() << "Start processing the image upload request to GitHub"; + + if(g_config->getpersonalAccessToken().isEmpty() || g_config->getReposName().isEmpty() || g_config->getUserName().isEmpty()) + { + qDebug() << "Please configure the GitHub image hosting first!"; + QMessageBox::warning(NULL, tr("Github Image Hosting"), tr("Please configure the GitHub image hosting first!")); + return; + } + + authenticateGithubImageHosting(g_config->getpersonalAccessToken()); +} + +void VGithubImageHosting::authenticateGithubImageHosting(QString p_token) +{ + qDebug() << "start the authentication process "; + QApplication::setOverrideCursor(Qt::WaitCursor); + QNetworkRequest request; + QUrl url = QUrl("https://api.github.com"); + QString ptoken = "token " + p_token; + request.setRawHeader("Authorization", ptoken.toLocal8Bit()); + request.setUrl(url); + if(reply != Q_NULLPTR) { + reply->deleteLater(); + } + reply = manager.get(request); + connect(reply, &QNetworkReply::finished, this, &VGithubImageHosting::githubImageBedAuthFinished); +} + +void VGithubImageHosting::githubImageBedAuthFinished() +{ + switch (reply->error()) { + case QNetworkReply::NoError: + { + QByteArray bytes = reply->readAll(); + + if(bytes.contains("Bad credentials")){ + qDebug() << "Authentication failed"; + QApplication::restoreOverrideCursor(); // Recovery pointer + QMessageBox::warning(NULL, tr("Github Image Hosting"), tr("Bad credentials!! ") + + tr("Please check your Github Image Hosting parameters !!")); + return; + }else{ + qDebug() << "Authentication completed"; + + qDebug() << "The current article path is: " << m_file->fetchPath(); + imageBasePath = m_file->fetchBasePath(); + newFileContent = m_file->getContent(); + + QVector images = VUtils::fetchImagesFromMarkdownFile(m_file,ImageLink::LocalRelativeInternal); + QApplication::restoreOverrideCursor(); // Recovery pointer + if(images.size() > 0) + { + proDlg = new QProgressDialog(tr("Uploading images to github..."), + tr("Abort"), + 0, + images.size(), + NULL); + proDlg->setWindowModality(Qt::WindowModal); + proDlg->setWindowTitle(tr("Uploading Images To Github")); + proDlg->setMinimumDuration(1); + + uploadImageCount = images.size(); + uploadImageCountIndex = uploadImageCount; + for(int i=0;igetName() << " No images to upload"; + QString info = m_file->getName() + " No pictures to upload"; + QMessageBox::information(NULL, tr("Github Image Hosting"), info); + } + } + break; + } + default: + { + QApplication::restoreOverrideCursor(); // Recovery pointer + qDebug() << "Network error: " << reply->errorString() << " error " << reply->error(); + QString info = tr("Network error: ") + reply->errorString(); + QMessageBox::warning(NULL, tr("Github Image Hosting"), info); + } + } +} + +void VGithubImageHosting::githubImageBedUploadManager() +{ + uploadImageCountIndex--; + + QString imageToUpload; + QMapIterator it(imageUrlMap); + while(it.hasNext()) + { + it.next(); + if(it.value() == ""){ + imageToUpload = it.key(); + proDlg->setValue(uploadImageCount - 1 - uploadImageCountIndex); + proDlg->setLabelText(tr("Uploaading image: %1").arg(imageToUpload)); + break; + } + } + + if(imageToUpload == ""){ + qDebug() << "All images have been uploaded"; + githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); + return; + } + + if(g_config->getpersonalAccessToken().isEmpty() || + g_config->getReposName().isEmpty() || + g_config->getUserName().isEmpty()) + { + qDebug() << "Please configure the GitHub image hosting first!"; + QMessageBox::warning(NULL, tr("Github Image Hosting"), tr("Please configure the GitHub image hosting first!")); + imageUrlMap.clear(); + return; + } + + QString path = imageBasePath + QDir::separator(); + path += imageToUpload; + githubImageBedUploadImage(g_config->getUserName(), + g_config->getReposName(), + path, + g_config->getpersonalAccessToken()); +} + +void VGithubImageHosting::githubImageBedUploadImage(const QString &p_username, + const QString &p_repository, + const QString &p_image_path, + const QString &p_token) +{ + QFileInfo fileInfo(p_image_path.toLocal8Bit()); + if(!fileInfo.exists()){ + qDebug() << "The picture does not exist in this path: " << p_image_path.toLocal8Bit(); + QString info = tr("The picture does not exist in this path: ") + p_image_path.toLocal8Bit(); + QMessageBox::warning(NULL, tr("Github Image Hosting"), info); + imageUrlMap.clear(); + if(imageUploaded){ + githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); + } + return; + } + + QString fileSuffix = fileInfo.suffix(); // file extension + QString fileName = fileInfo.fileName(); // filename + QString uploadUrl; // Image upload URL + uploadUrl = "https://api.github.com/repos/" + p_username + "/" + p_repository + "/contents/" + + QString::number(QDateTime::currentDateTime().toTime_t()) +"_" + fileName; + if(fileSuffix != QString::fromLocal8Bit("jpg") && fileSuffix != QString::fromLocal8Bit("png") + && fileSuffix != QString::fromLocal8Bit("gif")){ + qDebug() << "Unsupported type..."; + QString info = tr("Unsupported type: ") + fileSuffix; + QMessageBox::warning(NULL, tr("Github Image Hosting"), info); + imageUrlMap.clear(); + if(imageUploaded){ + githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); + } + return; + } + + QNetworkRequest request; + QUrl url = QUrl(uploadUrl); + QString ptoken = "token " + p_token; + request.setRawHeader("Authorization", ptoken.toLocal8Bit()); + request.setUrl(url); + if(reply != Q_NULLPTR) { + reply->deleteLater(); + } + + QString param = githubImageBedGenerateParam(p_image_path); + QByteArray postData; + postData.append(param); + reply = manager.put(request, postData); + qDebug() << "Start uploading images: " + p_image_path + " Waiting for upload to complete"; + uploadImageStatus = true; + currentUploadImage = p_image_path; + connect(reply, &QNetworkReply::finished, this, &VGithubImageHosting::githubImageBedUploadFinished); +} + +void VGithubImageHosting::githubImageBedUploadFinished() +{ + if (proDlg->wasCanceled()) { + qDebug() << "User stops uploading"; + reply->abort(); // Stop network request + imageUrlMap.clear(); + // The ones that have been uploaded successfully before still need to stay + if(imageUploaded){ + githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); + } + return; + } + + switch (reply->error()) { + case QNetworkReply::NoError: + { + QByteArray bytes = reply->readAll(); + int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + if(httpStatus == 201){ + qDebug() << "Upload success"; + + QString downloadUrl; + QString imageName; + QJsonDocument doucment = QJsonDocument::fromJson(bytes); + if (!doucment.isNull() ) + { + if (doucment.isObject()) { + QJsonObject object = doucment.object(); + if (object.contains("content")) { + QJsonValue value = object.value("content"); + if (value.isObject()) { + QJsonObject obj = value.toObject(); + if (obj.contains("download_url")) { + QJsonValue value = obj.value("download_url"); + if (value.isString()) { + downloadUrl = value.toString(); + qDebug() << "json decode: download_url : " << downloadUrl; + imageUploaded = true; // On behalf of successfully uploaded images + proDlg->setValue(uploadImageCount); + } + } + if(obj.contains("name")){ + QJsonValue value = obj.value("name"); + if(value.isString()){ + imageName = value.toString(); + } + } + + // Traverse key in imageurlmap + QList klist = imageUrlMap.keys(); + QString temp; + for(int i=0;ifetchPath()); + } + QString info = tr("Json decode error, Please contact the developer~"); + QMessageBox::warning(NULL, tr("Github Image Hosting"), info); + } + }else{ + // If status is not 201, it means there is a problem. + delete proDlg; + imageUrlMap.clear(); + qDebug() << "Upload failure"; + if(imageUploaded){ + githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); + } + QString info = tr("github status code != 201, Please contact the developer~"); + QMessageBox::warning(NULL, tr("Github Image Hosting"), info); + } + break; + } + default: + { + delete proDlg; + imageUrlMap.clear(); + qDebug()<<"network error: " << reply->errorString() << " error " << reply->error(); + QByteArray bytes = reply->readAll(); + qDebug() << bytes; + int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + qDebug() << "status: " << httpStatus; + + if(imageUploaded){ + githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); + } + QString info = tr("Uploading ") + currentUploadImage + tr(" \n\nNetwork error: ") + + reply->errorString() + tr("\n\nPlease check the network or image size"); + QMessageBox::warning(NULL, tr("Github Image Hosting"), info); + } + } +} + +void VGithubImageHosting::githubImageBedReplaceLink(const QString p_fileContent, const QString p_filePath) +{ + // This function must be executed when the upload is completed or fails in the middle. + // Write content to file. + QFile file(p_filePath); + file.open(QIODevice::WriteOnly | QIODevice::Text); + file.write(p_fileContent.toUtf8()); + file.close(); + + // Reset. + imageUrlMap.clear(); + imageUploaded = false; +} + +QString VGithubImageHosting::githubImageBedGenerateParam(const QString p_image_path){ + // According to the requirements of GitHub interface, pictures must be in Base64 format. + // Image to base64. + QByteArray hexed; + QFile imgFile(p_image_path); + imgFile.open(QIODevice::ReadOnly); + hexed = imgFile.readAll().toBase64(); + + QString imgBase64 = hexed; + QJsonObject json; + json.insert("message", QString("updatetest")); + json.insert("content", imgBase64); + + QJsonDocument document; + document.setObject(json); + QByteArray byteArray = document.toJson(QJsonDocument::Compact); + QString jsonStr(byteArray); + return jsonStr; +} + +VWechatImageHosting::VWechatImageHosting(VFile *p_file, QWidget *p_parent) + :QObject(p_parent), + m_file(p_file) +{ + reply = Q_NULLPTR; + imageUploaded = false; +} + +void VWechatImageHosting::handleUploadImageToWechatRequested() +{ + qDebug() << "Start processing image upload request to wechat"; + QString appid = g_config->getAppid(); + QString secret = g_config->getSecret(); + if(appid.isEmpty() || secret.isEmpty()) + { + qDebug() << "Please configure the Wechat image hosting first!"; + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), + tr("Please configure the Wechat image hosting first!")); + return; + } + + authenticateWechatImageHosting(appid, secret); +} + +void VWechatImageHosting::authenticateWechatImageHosting(const QString p_appid, const QString p_secret) +{ + qDebug() << "Start certification"; + // Set the mouse to wait + QApplication::setOverrideCursor(Qt::WaitCursor); + QNetworkRequest request; + QString auth_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ + p_appid.toLocal8Bit() + "&secret=" + p_secret.toLocal8Bit(); + QUrl url = QUrl(auth_url); + request.setUrl(url); + if(reply != Q_NULLPTR) { + reply->deleteLater(); + } + reply = manager.get(request); + connect(reply, &QNetworkReply::finished, this, &VWechatImageHosting::wechatImageBedAuthFinished); +} + +void VWechatImageHosting::wechatImageBedAuthFinished() +{ + switch (reply->error()) { + case QNetworkReply::NoError: + { + QByteArray bytes = reply->readAll(); + QJsonDocument document = QJsonDocument::fromJson(bytes); + if(!document.isNull()){ + if(document.isObject()){ + QJsonObject object = document.object(); + if(object.contains("access_token")){ + QJsonValue value = object.value("access_token"); + if(value.isString()){ + qDebug() << "Authentication successful, get token"; + // Parsing token. + wechatAccessToken = value.toString(); + + qDebug() << "The current article path is: " << m_file->fetchPath(); + imageBasePath = m_file->fetchBasePath(); + newFileContent = m_file->getContent(); + + QVector images = VUtils::fetchImagesFromMarkdownFile(m_file,ImageLink::LocalRelativeInternal); + QApplication::restoreOverrideCursor(); // Recovery pointer + if(images.size() > 0) + { + proDlg = new QProgressDialog(tr("Uploading images to github..."), + tr("Abort"), + 0, + images.size(), + NULL); + proDlg->setWindowModality(Qt::WindowModal); + proDlg->setWindowTitle(tr("Uploading Images To Github")); + proDlg->setMinimumDuration(1); + uploadImageCount = images.size(); + uploadImageCountIndex = uploadImageCount; + for(int i=0;igetName() << " No pictures to upload"; + QString info = m_file->getName() + tr(" No pictures to upload"); + QMessageBox::information(NULL, tr("Wechat Image Hosting"), info); + } + } + }else{ + qDebug() << "Authentication failed"; + QString string = bytes; + qDebug() << string; + // You can refine the error here. + QApplication::restoreOverrideCursor(); + if(string.contains("invalid ip")){ + QString ip = string.split(" ")[2]; + QClipboard *board = QApplication::clipboard(); + board->setText(ip); + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), + tr("Your ip address was set to the Clipboard!") + + tr("\nPlease add the IP address: ") + + ip + tr(" to the wechat ip whitelist!")); + }else{ + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), + tr("Please check your Wechat Image Hosting parameters !!\n") + + string); + } + return; + } + } + }else{ + delete proDlg; + imageUrlMap.clear(); + qDebug() << "Resolution failure!"; + qDebug() << "Resolution failure's json: " << bytes; + QString info = tr("Json decode error, Please contact the developer~"); + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); + } + + break; + } + default: + { + QApplication::restoreOverrideCursor(); + qDebug() << "Network error: " << reply->errorString() << " error " << reply->error(); + QString info = tr("Network error: ") + reply->errorString(); + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); + } + } +} + +void VWechatImageHosting::wechatImageBedUploadManager() +{ + uploadImageCountIndex--; + + QString image_to_upload = ""; + QMapIterator it(imageUrlMap); + while(it.hasNext()) + { + it.next(); + if(it.value() == ""){ + image_to_upload = it.key(); + proDlg->setValue(uploadImageCount - 1 - uploadImageCountIndex); + proDlg->setLabelText(tr("Uploaading image: %1").arg(image_to_upload)); + break; + } + } + + if(image_to_upload == ""){ + qDebug() << "All pictures have been uploaded"; + // Copy content to clipboard. + wechatImageBedReplaceLink(newFileContent); + return; + } + + QString path = imageBasePath + QDir::separator(); + path += image_to_upload; + currentUploadRelativeImagePah = image_to_upload; + wechatImageBedUploadImage(path, wechatAccessToken); +} + +void VWechatImageHosting::wechatImageBedUploadImage(const QString p_image_path, const QString p_token) +{ + qDebug() << "To deal with: " << p_image_path; + QFileInfo fileInfo(p_image_path.toLocal8Bit()); + if(!fileInfo.exists()){ + delete proDlg; + imageUrlMap.clear(); + qDebug() << "The picture does not exist in this path: " << p_image_path.toLocal8Bit(); + QString info = tr("The picture does not exist in this path: ") + p_image_path.toLocal8Bit(); + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); + return; + } + + QString file_suffix = fileInfo.suffix(); // File extension. + QString file_name = fileInfo.fileName(); // Filename. + if(file_suffix != QString::fromLocal8Bit("jpg") && file_suffix != QString::fromLocal8Bit("png")){ + delete proDlg; + imageUrlMap.clear(); + qDebug() << "Unsupported type..."; + QString info = tr("Unsupported type: ") + file_suffix; + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); + return; + } + + qint64 file_size = fileInfo.size(); // Unit is byte. + qDebug() << "Image size: " << file_size; + if(file_size > 1024*1024){ + delete proDlg; + imageUrlMap.clear(); + qDebug() << "The size of the picture is more than 1M"; + QString info = tr("The size of the picture is more than 1M! Wechat API does not support!!"); + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); + return; + } + + QString upload_img_url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=" + p_token; + + QNetworkRequest request; + request.setUrl(upload_img_url); + if(reply != Q_NULLPTR){ + reply->deleteLater(); + } + + QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + QHttpPart imagePart; + imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png")); + QString filename = p_image_path.split(QDir::separator()).last(); + QString contentVariant = QString("form-data; name=\"media\"; filename=\"%1\";").arg(filename); + imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(contentVariant)); + QFile *file = new QFile(p_image_path); + if(!file->open(QIODevice::ReadOnly)){ + qDebug() << "File open failed"; + } + imagePart.setBodyDevice(file); + file->setParent(multiPart); + multiPart->append(imagePart); + + // Set boundary + // Because boundary is quoted by QNetworkAccessManager, the wechat api is not recognized... + QByteArray m_boundary; + m_boundary.append("multipart/form-data; boundary="); + m_boundary.append(multiPart->boundary()); + request.setRawHeader(QByteArray("Content-Type"), m_boundary); + + reply = manager.post(request, multiPart); + multiPart->setParent(reply); + + qDebug() << "Start uploading images: " + p_image_path + " Waiting for upload to complete"; + uploadImageStatus=true; + currentUploadImage = p_image_path; + connect(reply, &QNetworkReply::finished, this, &VWechatImageHosting::wechatImageBedUploadFinished); +} + +void VWechatImageHosting::wechatImageBedUploadFinished() +{ + if(proDlg->wasCanceled()){ + qDebug() << "User stops uploading"; + reply->abort(); + // If the upload was successful, don't use it!!! + imageUrlMap.clear(); + return; + } + + switch (reply->error()) { + case QNetworkReply::NoError: + { + QByteArray bytes = reply->readAll(); + + QJsonDocument document = QJsonDocument::fromJson(bytes); + if(!document.isNull()){ + if(document.isObject()){ + QJsonObject object = document.object(); + if(object.contains("url")){ + QJsonValue value = object.value("url"); + if(value.isString()){ + qDebug() << "Authentication successful, get online link"; + imageUploaded = true; + proDlg->setValue(uploadImageCount); + + imageUrlMap.insert(currentUploadRelativeImagePah, value.toString()); + newFileContent.replace(currentUploadRelativeImagePah, value.toString()); + // Start calling the method. + // Whether the value in the map is empty determines whether to stop + wechatImageBedUploadManager(); + } + }else{ + delete proDlg; + imageUrlMap.clear(); + qDebug() << "Upload failure: "; + QString error = bytes; + qDebug() << bytes; + QString info = tr("upload failed! Please contact the developer~"); + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); + } + } + }else{ + delete proDlg; + imageUrlMap.clear(); + qDebug() << "Resolution failure!"; + qDebug() << "Resolution failure's json: " << bytes; + QString info = tr("Json decode error, Please contact the developer~"); + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); + } + + break; + } + default: + { + delete proDlg; + qDebug()<<"Network error: " << reply->errorString() << " error " << reply->error(); + + QString info = tr("Uploading ") + currentUploadImage + tr(" \n\nNetwork error: ") + + reply->errorString() + tr("\n\nPlease check the network or image size"); + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); + } + } +} + +void VWechatImageHosting::wechatImageBedReplaceLink(const QString p_file_content) +{ + // Write content to clipboard. + QClipboard *board = QApplication::clipboard(); + board->setText(p_file_content); + QString url = g_config->getMarkdown2WechatToolUrl(); + if(url.isEmpty()){ + QMessageBox::warning(NULL, tr("Wechat Image Hosting"), + tr("The article has been copied to the clipboard. Please find a text file and save it!!")); + }else{ + QMessageBox::StandardButton result; + result = QMessageBox::question(NULL, tr("Wechat Image Hosting"), + tr("The article has been copied to the clipboard.") + + tr("Do you want to open the tool link of mark down to wechat?"), + QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes); + if(result == QMessageBox::Yes){ + QDesktopServices::openUrl(QUrl(url)); + } + } + imageUrlMap.clear(); + imageUploaded = false; // Reset. +} diff --git a/src/vimagehosting.h b/src/vimagehosting.h new file mode 100644 index 00000000..941b6e79 --- /dev/null +++ b/src/vimagehosting.h @@ -0,0 +1,131 @@ +#ifndef VGITHUBIMAGEHOSTING_H +#define VGITHUBIMAGEHOSTING_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class VGithubImageHosting : public QObject +{ + Q_OBJECT +public: + explicit VGithubImageHosting(VFile *p_file, QWidget *p_parent = nullptr); + + // GitHub identity authentication. + void authenticateGithubImageHosting(QString p_token); + + // Upload a single image. + void githubImageBedUploadImage(const QString &p_username, + const QString &p_repository, + const QString &p_image_path, + const QString &p_token); + + // Parameters needed to generate uploaded images. + QString githubImageBedGenerateParam(const QString p_image_path); + + // Control image to upload. + void githubImageBedUploadManager(); + + // Replace old links with new ones for images. + void githubImageBedReplaceLink(const QString p_file_content, const QString p_file_path); + + // Process the image upload request to GitHub. + void handleUploadImageToGithubRequested(); + +public slots: + // GitHub image hosting identity authentication completed. + void githubImageBedAuthFinished(); + + // GitHub image hosting upload completed. + void githubImageBedUploadFinished(); + +private: + QNetworkAccessManager manager; + QNetworkReply *reply; + QMap imageUrlMap; + // Similar to "_v_image/". + QString imageBasePath; + // Replace the file content with the new link. + QString newFileContent; + // Whether the picture has been uploaded successfully. + bool imageUploaded; + // Image upload progress bar. + QProgressDialog *proDlg; + // Total number of images to upload. + int uploadImageCount; + int uploadImageCountIndex; + // Currently uploaded picture name. + QString currentUploadImage; + // Image upload status. + bool uploadImageStatus; + // Token returned after successful wechat authentication. + QString wechatAccessToken; + // Relative image path currently Uploaded. + QString currentUploadRelativeImagePah; + VFile *m_file; +}; + +class VWechatImageHosting : public QObject +{ + Q_OBJECT +public: + explicit VWechatImageHosting(VFile *p_file, QWidget *p_parent = nullptr); + + // Wechat identity authentication. + void authenticateWechatImageHosting(const QString p_appid, const QString p_secret); + + // Control image to upload. + void wechatImageBedUploadManager(); + + // Replace old links with new ones for images. + void wechatImageBedReplaceLink(const QString p_file_content); + + // Upload a single image. + void wechatImageBedUploadImage(const QString p_image_path, const QString p_token); + + // Process image upload request to wechat. + void handleUploadImageToWechatRequested(); + +public slots: + // Wechat mage hosting identity authentication completed. + void wechatImageBedAuthFinished(); + + // Wechat image hosting upload completed. + void wechatImageBedUploadFinished(); + +private: + QNetworkAccessManager manager; + QNetworkReply *reply; + QMap imageUrlMap; + // Similar to "_v_image/". + QString imageBasePath; + // Replace the file content with the new link. + QString newFileContent; + // Whether the picture has been uploaded successfully. + bool imageUploaded; + // Image upload progress bar. + QProgressDialog *proDlg; + // Total number of images to upload. + int uploadImageCount; + int uploadImageCountIndex; + // Currently uploaded picture name. + QString currentUploadImage; + // Image upload status + bool uploadImageStatus; + // Token returned after successful wechat authentication. + QString wechatAccessToken; + // Relative image path currently Uploaded. + QString currentUploadRelativeImagePah; + VFile *m_file; +}; + +#endif // VGITHUBIMAGEHOSTING_H diff --git a/src/vmdtab.cpp b/src/vmdtab.cpp index aa0429cc..65c2be9d 100644 --- a/src/vmdtab.cpp +++ b/src/vmdtab.cpp @@ -113,8 +113,9 @@ void VMdTab::setupUI() // Setup editor when we really need it. m_editor = NULL; - reply = Q_NULLPTR; - imageUploaded = false; + // The following is the image hosting initialization + vGithubImageHosting = new VGithubImageHosting(m_file, this); + vWechatImageHosting = new VWechatImageHosting(m_file, this); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(m_splitter); @@ -446,6 +447,7 @@ void VMdTab::setupMarkdownViewer() this, &VMdTab::handleWebSelectionChanged); connect(m_webViewer, &VWebView::requestExpandRestorePreviewArea, this, &VMdTab::expandRestorePreviewArea); + connect(m_webViewer, &VWebView::requestUploadImageToGithub, this, &VMdTab::handleUploadImageToGithubRequested); connect(m_webViewer, &VWebView::requestUploadImageToWechat, @@ -1512,661 +1514,12 @@ void VMdTab::handleSavePageRequested() void VMdTab::handleUploadImageToGithubRequested() { - qDebug() << "Start processing the image upload request to GitHub"; - - if(g_config->getpersonalAccessToken().isEmpty() || g_config->getReposName().isEmpty() || g_config->getUserName().isEmpty()) - { - qDebug() << "Please configure the GitHub image hosting first!"; - QMessageBox::warning(NULL, tr("Github Image Hosting"), tr("Please configure the GitHub image hosting first!")); - return; - } - - authenticateGithubImageHosting(g_config->getpersonalAccessToken()); -} - -void VMdTab::authenticateGithubImageHosting(QString p_token) -{ - qDebug() << "start the authentication process "; - QApplication::setOverrideCursor(Qt::WaitCursor); - QNetworkRequest request; - QUrl url = QUrl("https://api.github.com"); - QString ptoken = "token " + p_token; - request.setRawHeader("Authorization", ptoken.toLocal8Bit()); - request.setUrl(url); - if(reply != Q_NULLPTR) { - reply->deleteLater(); - } - reply = manager.get(request); - connect(reply, &QNetworkReply::finished, this, &VMdTab::githubImageBedAuthFinished); -} - -void VMdTab::githubImageBedAuthFinished() -{ - switch (reply->error()) { - case QNetworkReply::NoError: - { - QByteArray bytes = reply->readAll(); - - if(bytes.contains("Bad credentials")){ - qDebug() << "Authentication failed"; - QApplication::restoreOverrideCursor(); // Recovery pointer - QMessageBox::warning(NULL, tr("Github Image Hosting"), tr("Bad credentials!! Please check your Github Image Hosting parameters !!")); - return; - }else{ - qDebug() << "Authentication completed"; - - qDebug() << "The current article path is: " << m_file->fetchPath(); - imageBasePath = m_file->fetchBasePath(); - newFileContent = m_file->getContent(); - - QVector images = VUtils::fetchImagesFromMarkdownFile(m_file,ImageLink::LocalRelativeInternal); - QApplication::restoreOverrideCursor(); // Recovery pointer - if(images.size() > 0) - { - - proDlg = new QProgressDialog(tr("Uploading images to github..."), - tr("Abort"), - 0, - images.size(), - this); - proDlg->setWindowModality(Qt::WindowModal); - proDlg->setWindowTitle(tr("Uploading Images To Github")); - proDlg->setMinimumDuration(1); - uploadImageCount = images.size(); - uploadImageCountIndex = uploadImageCount; - for(int i=0;igetName() << " No images to upload"; - QString info = m_file->getName() + " No pictures to upload"; - QMessageBox::information(NULL, tr("Github Image Hosting"), info); - } - } - break; - } - default: - { - QApplication::restoreOverrideCursor(); // Recovery pointer - qDebug() << "Network error: " << reply->errorString() << " error " << reply->error(); - QString info = tr("Network error: ") + reply->errorString(); - QMessageBox::warning(NULL, tr("Github Image Hosting"), info); - } - } -} - -void VMdTab::githubImageBedUploadManager() -{ - uploadImageCountIndex--; - - QString imageToUpload = ""; - QMapIterator it(imageUrlMap); - while(it.hasNext()) - { - it.next(); - if(it.value() == ""){ - imageToUpload = it.key(); - proDlg->setValue(uploadImageCount - 1 - uploadImageCountIndex); - proDlg->setLabelText(tr("Uploaading image: %1").arg(imageToUpload)); - break; - } - } - - if(imageToUpload == ""){ - qDebug() << "All images have been uploaded"; - githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); - return; - } - - if(g_config->getpersonalAccessToken().isEmpty() || g_config->getReposName().isEmpty() || g_config->getUserName().isEmpty()) - { - qDebug() << "Please configure the GitHub image hosting first!"; - QMessageBox::warning(NULL, tr("Github Image Hosting"), tr("Please configure the GitHub image hosting first!")); - imageUrlMap.clear(); - return; - } - - QString path = imageBasePath + QDir::separator(); - path += imageToUpload; - githubImageBedUploadImage(g_config->getUserName(), g_config->getReposName(), path, g_config->getpersonalAccessToken()); -} - -void VMdTab::githubImageBedUploadImage(QString username, QString repository, QString imagePath, QString token) -{ - QFileInfo fileInfo(imagePath.toLocal8Bit()); - if(!fileInfo.exists()){ - qDebug() << "The picture does not exist in this path: " << imagePath.toLocal8Bit(); - QString info = tr("The picture does not exist in this path: ") + imagePath.toLocal8Bit(); - QMessageBox::warning(NULL, tr("Github Image Hosting"), info); - imageUrlMap.clear(); - if(imageUploaded){ - githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); - } - return; - } - - QString fileSuffix = fileInfo.suffix(); // file extension - QString fileName = fileInfo.fileName(); // filename - QString uploadUrl; // Image upload URL - uploadUrl = "https://api.github.com/repos/" + username + "/" + repository + "/contents/" + QString::number(QDateTime::currentDateTime().toTime_t()) +"_" + fileName; - if(fileSuffix != QString::fromLocal8Bit("jpg") && fileSuffix != QString::fromLocal8Bit("png") && fileSuffix != QString::fromLocal8Bit("gif")){ - qDebug() << "Unsupported type..."; - QString info = tr("Unsupported type: ") + fileSuffix; - QMessageBox::warning(NULL, tr("Github Image Hosting"), info); - imageUrlMap.clear(); - if(imageUploaded){ - githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); - } - return; - } - - QNetworkRequest request; - QUrl url = QUrl(uploadUrl); - QString ptoken = "token " + token; - request.setRawHeader("Authorization", ptoken.toLocal8Bit()); - request.setUrl(url); - if(reply != Q_NULLPTR) { - reply->deleteLater(); - } - - QString param = githubImageBedGenerateParam(imagePath); - QByteArray postData; - postData.append(param); - reply = manager.put(request, postData); - qDebug() << "Start uploading images: " + imagePath + " Waiting for upload to complete"; - uploadImageStatus = true; - currentUploadImage = imagePath; - connect(reply, &QNetworkReply::finished, this, &VMdTab::githubImageBedUploadFinished); -} - -void VMdTab::githubImageBedUploadFinished() -{ - if (proDlg->wasCanceled()) { - qDebug() << "User stops uploading"; - reply->abort(); // Stop network request - imageUrlMap.clear(); - // The ones that have been uploaded successfully before still need to stay - if(imageUploaded){ - githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); - } - return; - } - - switch (reply->error()) { - case QNetworkReply::NoError: - { - QByteArray bytes = reply->readAll(); - int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if(httpStatus == 201){ - qDebug() << "Upload success"; - - QString downloadUrl; - QString imageName; - QJsonDocument doucment = QJsonDocument::fromJson(bytes); - if (!doucment.isNull() ) - { - if (doucment.isObject()) { - QJsonObject object = doucment.object(); - if (object.contains("content")) { - QJsonValue value = object.value("content"); - if (value.isObject()) { - QJsonObject obj = value.toObject(); - if (obj.contains("download_url")) { - QJsonValue value = obj.value("download_url"); - if (value.isString()) { - downloadUrl = value.toString(); - qDebug() << "json decode: download_url : " << downloadUrl; - imageUploaded = true; // On behalf of successfully uploaded images - proDlg->setValue(uploadImageCount); - } - } - if(obj.contains("name")){ - QJsonValue value = obj.value("name"); - if(value.isString()){ - imageName = value.toString(); - } - } - - // Traverse key in imageurlmap - QList klist = imageUrlMap.keys(); - QString temp; - for(int i=0;ifetchPath()); - } - QString info = tr("Json decode error, Please contact the developer~"); - QMessageBox::warning(NULL, tr("Github Image Hosting"), info); - } - - - }else{ - // If status is not 201, it means there is a problem - delete proDlg; - imageUrlMap.clear(); - qDebug() << "Upload failure"; - if(imageUploaded){ - githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); - } - QString info = tr("github status code != 201, Please contact the developer~"); - QMessageBox::warning(NULL, tr("Github Image Hosting"), info); - } - break; - } - default: - { - delete proDlg; - imageUrlMap.clear(); - qDebug()<<"network error: " << reply->errorString() << " error " << reply->error(); - QByteArray bytes = reply->readAll(); - qDebug() << bytes; - int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - qDebug() << "status: " << httpStatus; - - if(imageUploaded){ - githubImageBedReplaceLink(newFileContent, m_file->fetchPath()); - } - QString info = tr("Uploading ") + currentUploadImage + tr(" \n\nNetwork error: ") + reply->errorString() + tr("\n\nPlease check the network or image size"); - QMessageBox::warning(NULL, tr("Github Image Hosting"), info); - } - } -} - -void VMdTab::githubImageBedReplaceLink(QString fileContent, QString filePath) -{ - // This function must be executed when the upload is completed or fails in the middle - // Write content to file - QFile file(filePath); - file.open(QIODevice::WriteOnly | QIODevice::Text); - file.write(fileContent.toUtf8()); - file.close(); - // Reset - imageUrlMap.clear(); - imageUploaded = false; -} - -QString VMdTab::githubImageBedGenerateParam(QString imagePath){ - // According to the requirements of GitHub interface, pictures must be in Base64 format - // img to base64 - QByteArray hexed; - QFile imgFile(imagePath); - imgFile.open(QIODevice::ReadOnly); - hexed = imgFile.readAll().toBase64(); - - QString imgBase64 = hexed; // Base64 encoding of images - QJsonObject json; - json.insert("message", QString("updatetest")); - json.insert("content", imgBase64); - - QJsonDocument document; - document.setObject(json); - QByteArray byteArray = document.toJson(QJsonDocument::Compact); - QString jsonStr(byteArray); - return jsonStr; + vGithubImageHosting->handleUploadImageToGithubRequested(); } void VMdTab::handleUploadImageToWechatRequested() { - qDebug() << "Start processing image upload request to wechat"; - QString appid = g_config->getAppid(); - QString secret = g_config->getSecret(); - if(appid.isEmpty() || secret.isEmpty()) - { - qDebug() << "Please configure the Wechat image hosting first!"; - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), tr("Please configure the Wechat image hosting first!")); - return; - } - - authenticateWechatImageHosting(appid, secret); -} - -void VMdTab::authenticateWechatImageHosting(QString appid, QString secret) -{ - qDebug() << "Start certification"; - QApplication::setOverrideCursor(Qt::WaitCursor); // Set the mouse to wait - QNetworkRequest request; - QString auth_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appid.toLocal8Bit() + "&secret=" + secret.toLocal8Bit(); - QUrl url = QUrl(auth_url); -// request.setRawHeader("grant_type", "client_credential"); -// request.setRawHeader("appid", appid.toLocal8Bit()); -// request.setRawHeader("secret", secret.toLocal8Bit()); - request.setUrl(url); - if(reply != Q_NULLPTR) { - reply->deleteLater(); - } - reply = manager.get(request); - connect(reply, &QNetworkReply::finished, this, &VMdTab::wechatImageBedAuthFinished); -} - -void VMdTab::wechatImageBedAuthFinished() -{ - switch (reply->error()) { - case QNetworkReply::NoError: - { - QByteArray bytes = reply->readAll(); - QJsonDocument document = QJsonDocument::fromJson(bytes); - if(!document.isNull()){ - if(document.isObject()){ - QJsonObject object = document.object(); - if(object.contains("access_token")){ - QJsonValue value = object.value("access_token"); - if(value.isString()){ - qDebug() << "Authentication successful, get token"; - // Parsing token - wechatAccessToken = value.toString(); - - qDebug() << "The current article path is: " << m_file->fetchPath(); - imageBasePath = m_file->fetchBasePath(); - newFileContent = m_file->getContent(); - - QVector images = VUtils::fetchImagesFromMarkdownFile(m_file,ImageLink::LocalRelativeInternal); - QApplication::restoreOverrideCursor(); // Recovery pointer - if(images.size() > 0) - { - - proDlg = new QProgressDialog(tr("Uploading images to github..."), - tr("Abort"), - 0, - images.size(), - this); - proDlg->setWindowModality(Qt::WindowModal); - proDlg->setWindowTitle(tr("Uploading Images To Github")); - proDlg->setMinimumDuration(1); - uploadImageCount = images.size(); - uploadImageCountIndex = uploadImageCount; - for(int i=0;igetName() << " No pictures to upload"; - QString info = m_file->getName() + tr(" No pictures to upload"); - QMessageBox::information(NULL, tr("Wechat Image Hosting"), info); - } - } - }else{ - qDebug() << "Authentication failed"; - QString string = bytes; - qDebug() << string; - // You can refine the error here - QApplication::restoreOverrideCursor(); - if(string.contains("invalid ip")){ - QString ip = string.split(" ")[2]; - QClipboard *board = QApplication::clipboard(); - board->setText(ip); - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), tr("Your ip address was set to the Clipboard! \nPlease add the IP address: ") + ip + tr(" to the wechat ip whitelist!")); - }else{ - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), tr("Please check your Wechat Image Hosting parameters !!\n") + string); - } - return; - } - } - }else{ - delete proDlg; - imageUrlMap.clear(); - qDebug() << "Resolution failure!"; - qDebug() << "Resolution failure's json: " << bytes; - QString info = tr("Json decode error, Please contact the developer~"); - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); - } - - - break; - } - default: - { - QApplication::restoreOverrideCursor(); - qDebug() << "Network error: " << reply->errorString() << " error " << reply->error(); - QString info = tr("Network error: ") + reply->errorString(); - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); - } - } -} - -void VMdTab::wechatImageBedUploadManager() -{ - uploadImageCountIndex--; - - QString image_to_upload = ""; - QMapIterator it(imageUrlMap); - while(it.hasNext()) - { - it.next(); - if(it.value() == ""){ - image_to_upload = it.key(); - proDlg->setValue(uploadImageCount - 1 - uploadImageCountIndex); - proDlg->setLabelText(tr("Uploaading image: %1").arg(image_to_upload)); - break; - } - - } - - if(image_to_upload == ""){ - qDebug() << "All pictures have been uploaded"; - // Copy content to clipboard - wechatImageBedReplaceLink(newFileContent, m_file->fetchPath()); - return; - } - - QString path = imageBasePath + QDir::separator(); - path += image_to_upload; - currentUploadRelativeImagePah = image_to_upload; - wechatImageBedUploadImage(path, wechatAccessToken); -} - -void VMdTab::wechatImageBedUploadImage(QString image_path, QString token) -{ - qDebug() << "To deal with: " << image_path; - QFileInfo fileInfo(image_path.toLocal8Bit()); - if(!fileInfo.exists()){ - delete proDlg; - imageUrlMap.clear(); - qDebug() << "The picture does not exist in this path: " << image_path.toLocal8Bit(); - QString info = tr("The picture does not exist in this path: ") + image_path.toLocal8Bit(); - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); - return; - } - - QString file_suffix = fileInfo.suffix(); // File extension - QString file_name = fileInfo.fileName(); // filename - if(file_suffix != QString::fromLocal8Bit("jpg") && file_suffix != QString::fromLocal8Bit("png")){ - delete proDlg; - imageUrlMap.clear(); - qDebug() << "Unsupported type..."; - QString info = tr("Unsupported type: ") + file_suffix; - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); - return; - } - - qint64 file_size = fileInfo.size(); // Unit is byte - qDebug() << "Image size: " << file_size; - if(file_size > 1024*1024){ - delete proDlg; - imageUrlMap.clear(); - qDebug() << "The size of the picture is more than 1M"; - QString info = tr("The size of the picture is more than 1M! Wechat API does not support!!"); - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); - return; - } - - QString upload_img_url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=" + token; - - QNetworkRequest request; - request.setUrl(upload_img_url); - if(reply != Q_NULLPTR){ - reply->deleteLater(); - } - - QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); - QHttpPart imagePart; - imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png")); - QString filename = image_path.split(QDir::separator()).last(); - QString contentVariant = QString("form-data; name=\"media\"; filename=\"%1\";").arg(filename); - imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(contentVariant)); - QFile *file = new QFile(image_path); - if(!file->open(QIODevice::ReadOnly)){ - qDebug() << "File open failed"; - } - imagePart.setBodyDevice(file); - file->setParent(multiPart); - multiPart->append(imagePart); - - // Set boundary - // Because boundary is quoted by QNetworkAccessManager, the wechat api is not recognized... - QByteArray m_boundary; - m_boundary.append("multipart/form-data; boundary="); - m_boundary.append(multiPart->boundary()); - request.setRawHeader(QByteArray("Content-Type"), m_boundary); - - reply = manager.post(request, multiPart); - multiPart->setParent(reply); - - - qDebug() << "Start uploading images: " + image_path + " Waiting for upload to complete"; - uploadImageStatus=true; - currentUploadImage = image_path; - connect(reply, &QNetworkReply::finished, this, &VMdTab::wechatImageBedUploadFinished); - -} - -void VMdTab::wechatImageBedUploadFinished() -{ - if(proDlg->wasCanceled()){ - qDebug() << "User stops uploading"; - reply->abort(); - // If the upload was successful, don't use it!!! - imageUrlMap.clear(); - return; - } - - switch (reply->error()) { - case QNetworkReply::NoError: - { - QByteArray bytes = reply->readAll(); - - //qDebug() << "The returned contents are as follows: "; - //QString a = bytes; - //qDebug() << qPrintable(a); - - QJsonDocument document = QJsonDocument::fromJson(bytes); - if(!document.isNull()){ - if(document.isObject()){ - QJsonObject object = document.object(); - if(object.contains("url")){ - QJsonValue value = object.value("url"); - if(value.isString()){ - qDebug() << "Authentication successful, get online link"; - imageUploaded = true; - proDlg->setValue(uploadImageCount); - - imageUrlMap.insert(currentUploadRelativeImagePah, value.toString()); - newFileContent.replace(currentUploadRelativeImagePah, value.toString()); - // Start calling the method. Whether the value in the map is empty determines whether to stop - wechatImageBedUploadManager(); - } - }else{ - delete proDlg; - imageUrlMap.clear(); - qDebug() << "Upload failure: "; - QString error = bytes; - qDebug() << bytes; - QString info = tr("upload failed! Please contact the developer~"); - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); - } - } - }else{ - delete proDlg; - imageUrlMap.clear(); - qDebug() << "Resolution failure!"; - qDebug() << "Resolution failure's json: " << bytes; - QString info = tr("Json decode error, Please contact the developer~"); - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); - } - - break; - } - default: - { - delete proDlg; - qDebug()<<"Network error: " << reply->errorString() << " error " << reply->error(); - - QString info = tr("Uploading ") + currentUploadImage + tr(" \n\nNetwork error: ") + reply->errorString() + tr("\n\nPlease check the network or image size"); - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info); - - } - - } -} -void VMdTab::wechatImageBedReplaceLink(QString file_content, QString file_path) -{ - // Write content to clipboard - QClipboard *board = QApplication::clipboard(); - board->setText(file_content); - QString url = g_config->getMarkdown2WechatToolUrl(); - if(url.isEmpty()){ - QMessageBox::warning(NULL, tr("Wechat Image Hosting"), tr("The article has been copied to the clipboard. Please find a text file and save it!!")); - }else{ - QMessageBox::StandardButton result; - result = QMessageBox::question(this, tr("Wechat Image Hosting"), tr("The article has been copied to the clipboard. Do you want to open the tool link of mark down to wechat?"), QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes); - if(result == QMessageBox::Yes){ - QDesktopServices::openUrl(QUrl(url)); - } - } - imageUrlMap.clear(); - imageUploaded = false; // reset + vWechatImageHosting->handleUploadImageToWechatRequested(); } VWordCountInfo VMdTab::fetchWordCountInfo(bool p_editMode) const diff --git a/src/vmdtab.h b/src/vmdtab.h index 49e230ec..d7629452 100644 --- a/src/vmdtab.h +++ b/src/vmdtab.h @@ -1,16 +1,14 @@ #ifndef VMDTAB_H #define VMDTAB_H -#include #include #include #include -#include -#include #include "vedittab.h" #include "vconstants.h" #include "vmarkdownconverter.h" #include "vconfigmanager.h" +#include "vimagehosting.h" class VWebView; class VDocument; @@ -110,27 +108,6 @@ public: bool expandRestorePreviewArea(); - // github image hosting - // GitHub identity authentication - void authenticateGithubImageHosting(QString p_token); - // Upload a single image - void githubImageBedUploadImage(QString username,QString repository,QString image_path,QString token); - // Parameters needed to generate uploaded images - QString githubImageBedGenerateParam(QString image_path); - // Control image upload - void githubImageBedUploadManager(); - // Replace old links with new ones for images - void githubImageBedReplaceLink(QString file_content, QString file_path); - - // wechat image hosting - void authenticateWechatImageHosting(QString appid, QString secret); - // Control image upload - void wechatImageBedUploadManager(); - // Replace old links with new ones for images - void wechatImageBedReplaceLink(QString file_content, QString file_path); - // Upload a single image - void wechatImageBedUploadImage(QString image_path,QString token); - public slots: // Enter edit mode. void editFile() Q_DECL_OVERRIDE; @@ -188,21 +165,9 @@ private slots: // Process the image upload request to GitHub void handleUploadImageToGithubRequested(); - // GitHub image hosting identity authentication completed - void githubImageBedAuthFinished(); - - // GitHub image hosting upload completed - void githubImageBedUploadFinished(); - // Process image upload request to wechat void handleUploadImageToWechatRequested(); - // Wechat mage hosting identity authentication completed - void wechatImageBedAuthFinished(); - - // Wechat image hosting upload completed - void wechatImageBedUploadFinished(); - private: enum TabReady { None = 0, ReadMode = 0x1, EditMode = 0x2 }; @@ -320,28 +285,8 @@ private: int m_documentID; - QNetworkAccessManager manager; - QNetworkReply *reply; - QMap imageUrlMap; - // Similar to _v_image/ - QString imageBasePath; - // Replace the file content with the new link - QString newFileContent; - // Whether the picture has been uploaded successfully - bool imageUploaded; - // Image upload progress bar - QProgressDialog *proDlg; - // Total number of images to upload - int uploadImageCount; - int uploadImageCountIndex; - // Currently uploaded picture name - QString currentUploadImage; - // Image upload status - bool uploadImageStatus; - // Token returned after successful wechat authentication - QString wechatAccessToken; - // Relative image path currently Uploaded - QString currentUploadRelativeImagePah; + VGithubImageHosting *vGithubImageHosting; + VWechatImageHosting *vWechatImageHosting; }; inline VMdEditor *VMdTab::getEditor()