mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-04 21:39:52 +08:00
editor: add supports for GitHub and WeChat image hosting (#1007)
* 增加了github imagebed的配置窗口 * 已经完成批量上传 * 基本上可以使用 * 基本上可以使用 * 加入进度条 * 就差开始的认证过程 * 差不多就这样了 * 修改中文的readme * 修改了一下readme * 找到不能传gif的问题所在 * 修改gif不能上传的bug * 增加图床使用说明限制 * 增加一些注释 * 将进度条delete调 * 增加大文件上传错误提示 * 修复cancel的问题 * 已知问题: 上传多张图片时, 较大的图片的进度条不一定能出来 * 将进度条弹出来的时候修改成1s后 * 加入wechat设置, 改成QTabWidget * wechat设置成功 * 成功获取了token * 先保存一下, 文件上传有bug,替换好像也有bug * 解决了boundary的引号导致图片不能上传的问题 * 注释掉一些输出 * 加入ip不在白名单的提示 * 增加图片大小大于1M的提示 * 将ip地址设置进剪切板, 并显示在弹框上 * 添加markdown转微信的url设置 * 增加自动打开openwrite的链接, 修复文件大小应为1024*1024 * 改成clear * 将类型校验放到开始的地方 * 加入openwrite默认为空的判断 * Delete github-imagebed.md * Apply suggestions from code review Co-Authored-By: Le Tan <tamlokveer@gmail.com> * Apply suggestions from code review Co-Authored-By: Le Tan <tamlokveer@gmail.com> * Apply suggestions from code review Co-Authored-By: Le Tan <tamlokveer@gmail.com> * 根据要求修改了一下 * changed indentation and deleted empty line * add some tr() * Delete .DS_Store * delete some comment and use CamelCase * resolved sth
This commit is contained in:
parent
fccf6863d7
commit
c828ef00c4
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
VNote.pro.user*
|
||||
CMakeLists.txt.user
|
||||
.DS_Store
|
||||
|
@ -109,6 +109,7 @@ Utilizing Qt, VNote could run on **Linux**, **Windows**, and **macOS**.
|
||||
- Attachments of notes;
|
||||
- Themes and dark mode;
|
||||
- Rich and extensible export, such as HTML, PDF, PDF (All In One), and images;
|
||||
- GitHub and WeChat image hosting;
|
||||
|
||||
# Donate
|
||||
You could help VNote's development in many ways.
|
||||
|
@ -110,6 +110,7 @@ VNote 不是一个简单的 Markdown 编辑器。通过提供笔记管理功能
|
||||
- 笔记附件;
|
||||
- 主题以及深色模式;
|
||||
- 丰富、可扩展的导出,包括 HTML、PDF、PDF(多合一)和图片;
|
||||
- GitHub和微信图床;
|
||||
|
||||
# 捐赠
|
||||
您可以通过很多途径帮助 VNote 的开发。
|
||||
|
@ -66,6 +66,7 @@ VSettingsDialog::VSettingsDialog(QWidget *p_parent)
|
||||
addTab(new VNoteManagementTab(), tr("Note Management"));
|
||||
addTab(new VMarkdownTab(), tr("Markdown"));
|
||||
addTab(new VMiscTab(), tr("Misc"));
|
||||
addTab(new VImageHostingTab(), tr("Image Hosting"));
|
||||
|
||||
m_tabList->setMaximumWidth(m_tabList->sizeHintForColumn(0) + 5);
|
||||
|
||||
@ -206,6 +207,15 @@ void VSettingsDialog::loadConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
// ImageBed Tab
|
||||
{
|
||||
VImageHostingTab *imageBedTab = dynamic_cast<VImageHostingTab *>(m_tabs->widget(idx++));
|
||||
Q_ASSERT(imageBedTab);
|
||||
if (!imageBedTab->loadConfiguration()) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
err:
|
||||
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
|
||||
@ -271,6 +281,15 @@ void VSettingsDialog::saveConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
// Image Hosting Tab.
|
||||
{
|
||||
VImageHostingTab *imageBedTab = dynamic_cast<VImageHostingTab *>(m_tabs->widget(idx++));
|
||||
Q_ASSERT(imageBedTab);
|
||||
if (!imageBedTab->saveConfiguration()) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
accept();
|
||||
return;
|
||||
err:
|
||||
@ -1547,7 +1566,6 @@ bool VMiscTab::loadConfiguration()
|
||||
if (!loadMatchesInPage()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1571,3 +1589,162 @@ bool VMiscTab::saveMatchesInPage()
|
||||
g_config->setHighlightMatchesInPage(m_matchesInPageCB->isChecked());
|
||||
return true;
|
||||
}
|
||||
|
||||
VImageHostingTab::VImageHostingTab(QWidget *p_parent)
|
||||
: QWidget(p_parent)
|
||||
{
|
||||
QTabWidget *imageHostingTabWeg = new QTabWidget(this);
|
||||
QWidget *githubImageHostingTab = new QWidget();
|
||||
QWidget *wechatImageHostingTab = new QWidget();
|
||||
imageHostingTabWeg->addTab(githubImageHostingTab, tr("GitHub"));
|
||||
imageHostingTabWeg->addTab(wechatImageHostingTab, tr("WeChat"));
|
||||
imageHostingTabWeg->setCurrentIndex(0);
|
||||
|
||||
// Set the tab of GitHub image Hosting
|
||||
m_personalAccessTokenEdit = new VLineEdit();
|
||||
m_personalAccessTokenEdit->setToolTip(tr("GitHub personal access token"));
|
||||
m_repoNameEdit = new VLineEdit();
|
||||
m_repoNameEdit->setToolTip(tr("Name of GitHub repository for image hosting"));
|
||||
m_userNameEdit = new VLineEdit();
|
||||
m_userNameEdit->setToolTip(tr("User name of GitHub"));
|
||||
|
||||
QFormLayout *githubLayout = new QFormLayout();
|
||||
githubLayout->addRow(tr("Personal access token:"), m_personalAccessTokenEdit);
|
||||
githubLayout->addRow(tr("Repo name:"), m_repoNameEdit);
|
||||
githubLayout->addRow(tr("User name:"), m_userNameEdit);
|
||||
|
||||
githubImageHostingTab->setLayout(githubLayout);
|
||||
|
||||
// Set the tab of GitHub image Hosting
|
||||
m_appidEdit = new VLineEdit();
|
||||
m_appidEdit->setToolTip(tr("WeChat appid"));
|
||||
m_secretEdit = new VLineEdit();
|
||||
m_secretEdit->setToolTip(tr("Please input wechat secret"));
|
||||
m_markdown2WechatToolUrlEdit = new VLineEdit();
|
||||
m_markdown2WechatToolUrlEdit->setToolTip(tr("Please input markdown to wechat tool's url"));
|
||||
|
||||
QFormLayout *wechatLayout = new QFormLayout();
|
||||
wechatLayout->addRow(tr("appid:"), m_appidEdit);
|
||||
wechatLayout->addRow(tr("secret:"), m_secretEdit);
|
||||
wechatLayout->addRow(tr("markdown2WechatToolUrl"), m_markdown2WechatToolUrlEdit);
|
||||
|
||||
wechatImageHostingTab->setLayout(wechatLayout);
|
||||
}
|
||||
|
||||
bool VImageHostingTab::loadAppid()
|
||||
{
|
||||
m_appidEdit->setText(g_config->getAppid());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::saveAppid()
|
||||
{
|
||||
g_config->setAppid(m_appidEdit->text());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::loadSecret()
|
||||
{
|
||||
m_secretEdit->setText(g_config->getSecret());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::saveSecret()
|
||||
{
|
||||
g_config->setSecret(m_secretEdit->text());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::loadMarkdown2WechatToolUrl()
|
||||
{
|
||||
m_markdown2WechatToolUrlEdit->setText(g_config->getMarkdown2WechatToolUrl());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::saveMarkdown2WechatToolUrl()
|
||||
{
|
||||
g_config->setMarkdown2WechatToolUrl(m_markdown2WechatToolUrlEdit->text());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::loadpersonalAccessToken()
|
||||
{
|
||||
m_personalAccessTokenEdit->setText(g_config->getpersonalAccessToken());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::savepersonalAccessToken()
|
||||
{
|
||||
g_config->setpersonalAccessToken(m_personalAccessTokenEdit->text());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::loadReposName()
|
||||
{
|
||||
m_repoNameEdit->setText(g_config->getReposName());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::saveReposName()
|
||||
{
|
||||
g_config->setReposName(m_repoNameEdit->text());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::loadUserName()
|
||||
{
|
||||
m_userNameEdit->setText(g_config->getUserName());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::saveUserName()
|
||||
{
|
||||
g_config->setUserName(m_userNameEdit->text());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::loadConfiguration()
|
||||
{
|
||||
if(!loadpersonalAccessToken()){
|
||||
return false;
|
||||
}
|
||||
if(!loadReposName()){
|
||||
return false;
|
||||
}
|
||||
if(!loadUserName()){
|
||||
return false;
|
||||
}
|
||||
if(!loadAppid()){
|
||||
return false;
|
||||
}
|
||||
if(!loadSecret()){
|
||||
return false;
|
||||
}
|
||||
if(!loadMarkdown2WechatToolUrl()){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VImageHostingTab::saveConfiguration()
|
||||
{
|
||||
if(!savepersonalAccessToken()){
|
||||
return false;
|
||||
}
|
||||
if(!saveReposName()){
|
||||
return false;
|
||||
}
|
||||
if(!saveUserName()){
|
||||
return false;
|
||||
}
|
||||
if(!saveAppid()){
|
||||
return false;
|
||||
}
|
||||
if(!saveSecret()){
|
||||
return false;
|
||||
}
|
||||
if(!saveMarkdown2WechatToolUrl()){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QDialog>
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include <QTabWidget>
|
||||
|
||||
class QDialogButtonBox;
|
||||
class QComboBox;
|
||||
@ -270,6 +271,47 @@ private:
|
||||
QCheckBox *m_matchesInPageCB;
|
||||
};
|
||||
|
||||
class VImageHostingTab : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VImageHostingTab(QWidget *p_parent = 0);
|
||||
bool loadConfiguration();
|
||||
bool saveConfiguration();
|
||||
|
||||
private:
|
||||
bool loadpersonalAccessToken();
|
||||
bool savepersonalAccessToken();
|
||||
|
||||
bool loadReposName();
|
||||
bool saveReposName();
|
||||
|
||||
bool loadUserName();
|
||||
bool saveUserName();
|
||||
|
||||
bool loadAppid();
|
||||
bool saveAppid();
|
||||
|
||||
bool loadSecret();
|
||||
bool saveSecret();
|
||||
|
||||
bool loadMarkdown2WechatToolUrl();
|
||||
bool saveMarkdown2WechatToolUrl();
|
||||
|
||||
// personalAccessToken
|
||||
VLineEdit *m_personalAccessTokenEdit;
|
||||
// reposName
|
||||
VLineEdit *m_repoNameEdit;
|
||||
// userName
|
||||
VLineEdit *m_userNameEdit;
|
||||
// appid
|
||||
VLineEdit *m_appidEdit;
|
||||
// secret
|
||||
VLineEdit *m_secretEdit;
|
||||
// markdown to wechat tools url
|
||||
VLineEdit *m_markdown2WechatToolUrlEdit;
|
||||
};
|
||||
|
||||
class VSettingsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -1,4 +1,13 @@
|
||||
[global]
|
||||
; Wechat ImageBed
|
||||
wechat_appid=
|
||||
wechat_secret=
|
||||
wechat_markdown_to_wechat_tool_url=
|
||||
; Github ImageBed
|
||||
github_personal_access_token=
|
||||
github_repos_name=
|
||||
github_user_name=
|
||||
|
||||
; Theme name
|
||||
theme=v_pure
|
||||
|
||||
|
@ -79,6 +79,14 @@ void VConfigManager::initialize()
|
||||
|
||||
initCodeBlockCssStyles();
|
||||
|
||||
m_personalAccessToken = getConfigFromSettings("global", "github_personal_access_token").toString();
|
||||
m_reposName = getConfigFromSettings("global", "github_repos_name").toString();
|
||||
m_userName = getConfigFromSettings("global", "github_user_name").toString();
|
||||
|
||||
m_appid = getConfigFromSettings("global", "wechat_appid").toString();
|
||||
m_secret = getConfigFromSettings("global", "wechat_secret").toString();
|
||||
m_markdown2WechatToolUrl = getConfigFromSettings("global", "wechat_markdown_to_wechat_tool_url").toString();
|
||||
|
||||
m_theme = getConfigFromSettings("global", "theme").toString();
|
||||
|
||||
m_editorStyle = getConfigFromSettings("global", "editor_style").toString();
|
||||
|
@ -648,6 +648,27 @@ public:
|
||||
|
||||
bool getEnableCodeBlockCopyButton() const;
|
||||
|
||||
// github image hosting setting
|
||||
const QString &getpersonalAccessToken() const;
|
||||
void setpersonalAccessToken(const QString &p_token);
|
||||
|
||||
const QString &getReposName() const;
|
||||
void setReposName(const QString &p_reposName);
|
||||
|
||||
const QString &getUserName() const;
|
||||
void setUserName(const QString &p_userName);
|
||||
|
||||
// wechat image hosting setting
|
||||
const QString &getAppid() const;
|
||||
void setAppid(const QString &p_appid);
|
||||
|
||||
const QString &getSecret() const;
|
||||
void setSecret(const QString &p_secret);
|
||||
|
||||
const QString &getMarkdown2WechatToolUrl() const;
|
||||
void setMarkdown2WechatToolUrl(const QString &p_markdown2WechatToolUrl);
|
||||
|
||||
|
||||
private:
|
||||
void initEditorConfigs();
|
||||
|
||||
@ -1071,6 +1092,16 @@ private:
|
||||
|
||||
QString m_plantUMLCmd;
|
||||
|
||||
// github imagebed
|
||||
QString m_personalAccessToken;
|
||||
QString m_reposName;
|
||||
QString m_userName;
|
||||
|
||||
// wechat imagebed
|
||||
QString m_appid;
|
||||
QString m_secret;
|
||||
QString m_markdown2WechatToolUrl;
|
||||
|
||||
// Size of history.
|
||||
int m_historySize;
|
||||
|
||||
@ -2989,4 +3020,92 @@ inline bool VConfigManager::getEnableCodeBlockCopyButton() const
|
||||
return m_enableCodeBlockCopyButton;
|
||||
}
|
||||
|
||||
inline const QString &VConfigManager::getAppid() const
|
||||
{
|
||||
return m_appid;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setAppid(const QString &p_appid)
|
||||
{
|
||||
if(m_appid == p_appid){
|
||||
return;
|
||||
}
|
||||
m_appid = p_appid;
|
||||
setConfigToSettings("global", "wechat_appid", p_appid);
|
||||
}
|
||||
|
||||
inline const QString &VConfigManager::getSecret() const
|
||||
{
|
||||
return m_secret;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setSecret(const QString &p_secret)
|
||||
{
|
||||
if(m_secret == p_secret){
|
||||
return;
|
||||
}
|
||||
m_secret = p_secret;
|
||||
setConfigToSettings("global", "wechat_secret", p_secret);
|
||||
}
|
||||
|
||||
inline const QString &VConfigManager::getMarkdown2WechatToolUrl() const
|
||||
{
|
||||
return m_markdown2WechatToolUrl;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setMarkdown2WechatToolUrl(const QString &p_markdown2WechatToolUrl)
|
||||
{
|
||||
if(m_markdown2WechatToolUrl == p_markdown2WechatToolUrl){
|
||||
return;
|
||||
}
|
||||
m_markdown2WechatToolUrl = p_markdown2WechatToolUrl;
|
||||
setConfigToSettings("global", "wechat_markdown_to_wechat_tool_url", p_markdown2WechatToolUrl);
|
||||
}
|
||||
|
||||
|
||||
inline const QString &VConfigManager::getpersonalAccessToken() const
|
||||
{
|
||||
return m_personalAccessToken;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setpersonalAccessToken(const QString &p_token)
|
||||
{
|
||||
if (m_personalAccessToken == p_token) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_personalAccessToken = p_token;
|
||||
setConfigToSettings("global", "github_personal_access_token", p_token);
|
||||
}
|
||||
|
||||
inline const QString &VConfigManager::getReposName() const
|
||||
{
|
||||
return m_reposName;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setReposName(const QString &p_reposName)
|
||||
{
|
||||
if (m_reposName == p_reposName) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_reposName = p_reposName;
|
||||
setConfigToSettings("global", "github_repos_name", p_reposName);
|
||||
}
|
||||
|
||||
inline const QString &VConfigManager::getUserName() const
|
||||
{
|
||||
return m_userName;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setUserName(const QString &p_userName)
|
||||
{
|
||||
if (m_userName == p_userName) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_userName = p_userName;
|
||||
setConfigToSettings("global", "github_user_name", p_userName);
|
||||
}
|
||||
|
||||
#endif // VCONFIGMANAGER_H
|
||||
|
666
src/vmdtab.cpp
666
src/vmdtab.cpp
@ -113,6 +113,9 @@ void VMdTab::setupUI()
|
||||
// Setup editor when we really need it.
|
||||
m_editor = NULL;
|
||||
|
||||
reply = Q_NULLPTR;
|
||||
imageUploaded = false;
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout();
|
||||
layout->addWidget(m_splitter);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
@ -443,6 +446,10 @@ 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,
|
||||
this, &VMdTab::handleUploadImageToWechatRequested);
|
||||
|
||||
VPreviewPage *page = new VPreviewPage(m_webViewer);
|
||||
m_webViewer->setPage(page);
|
||||
@ -1503,6 +1510,665 @@ void VMdTab::handleSavePageRequested()
|
||||
m_webViewer->page()->save(fileName, format);
|
||||
}
|
||||
|
||||
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<ImageLink> 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;i<images.size() ;i++)
|
||||
{
|
||||
if(images[i].m_url.contains(".png") || images[i].m_url.contains(".jpg")|| images[i].m_url.contains(".gif")){
|
||||
imageUrlMap.insert(images[i].m_url,"");
|
||||
}else{
|
||||
delete proDlg;
|
||||
imageUrlMap.clear();
|
||||
qDebug() << "Unsupported type...";
|
||||
QFileInfo fileInfo(images[i].m_path.toLocal8Bit());
|
||||
QString fileSuffix = fileInfo.suffix();
|
||||
QString info = tr("Unsupported type: ") + fileSuffix;
|
||||
QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
githubImageBedUploadManager();
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << m_file->getName() << " 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<QString, QString> 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<QString> klist = imageUrlMap.keys();
|
||||
QString temp;
|
||||
for(int i=0;i<klist.count();i++)
|
||||
{
|
||||
|
||||
temp = klist[i].split("/")[1];
|
||||
if(imageName.contains(temp))
|
||||
{
|
||||
// You can assign values in the map
|
||||
imageUrlMap.insert(klist[i], downloadUrl);
|
||||
|
||||
// Replace the link in the original
|
||||
newFileContent.replace(klist[i], downloadUrl);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Start calling the method. Whether the value in the map is empty determines whether to stop
|
||||
githubImageBedUploadManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
delete proDlg;
|
||||
imageUrlMap.clear();
|
||||
qDebug() << "Resolution failure!";
|
||||
qDebug() << "Resolution failure's json: " << bytes;
|
||||
if(imageUploaded){
|
||||
githubImageBedReplaceLink(newFileContent, m_file->fetchPath());
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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<ImageLink> 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;i<images.size() ;i++)
|
||||
{
|
||||
if(images[i].m_url.contains(".png") || images[i].m_url.contains(".jpg")){
|
||||
imageUrlMap.insert(images[i].m_url,"");
|
||||
}else{
|
||||
delete proDlg;
|
||||
imageUrlMap.clear();
|
||||
qDebug() << "Unsupported type...";
|
||||
QFileInfo file_info(images[i].m_path.toLocal8Bit());
|
||||
QString file_suffix = file_info.suffix();
|
||||
QString info = tr("Unsupported type: ") + file_suffix;
|
||||
QMessageBox::warning(NULL, tr("Wechat Image Hosting"), info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
wechatImageBedUploadManager();
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << m_file->getName() << " 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<QString, QString> 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
|
||||
}
|
||||
|
||||
VWordCountInfo VMdTab::fetchWordCountInfo(bool p_editMode) const
|
||||
{
|
||||
if (p_editMode) {
|
||||
|
65
src/vmdtab.h
65
src/vmdtab.h
@ -1,9 +1,12 @@
|
||||
#ifndef VMDTAB_H
|
||||
#define VMDTAB_H
|
||||
|
||||
#include <QtNetwork>
|
||||
#include <QString>
|
||||
#include <QPointer>
|
||||
#include <QSharedPointer>
|
||||
#include <QProgressDialog>
|
||||
#include <QDesktopServices>
|
||||
#include "vedittab.h"
|
||||
#include "vconstants.h"
|
||||
#include "vmarkdownconverter.h"
|
||||
@ -107,6 +110,27 @@ 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;
|
||||
@ -161,6 +185,24 @@ private slots:
|
||||
// Selection changed in web.
|
||||
void handleWebSelectionChanged();
|
||||
|
||||
// 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 };
|
||||
|
||||
@ -277,6 +319,29 @@ private:
|
||||
VMathJaxInplacePreviewHelper *m_mathjaxPreviewHelper;
|
||||
|
||||
int m_documentID;
|
||||
|
||||
QNetworkAccessManager manager;
|
||||
QNetworkReply *reply;
|
||||
QMap<QString, QString> 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;
|
||||
};
|
||||
|
||||
inline VMdEditor *VMdTab::getEditor()
|
||||
|
@ -98,6 +98,16 @@ void VWebView::contextMenuEvent(QContextMenuEvent *p_event)
|
||||
connect(savePageAct, &QAction::triggered,
|
||||
this, &VWebView::requestSavePage);
|
||||
menu->addAction(savePageAct);
|
||||
|
||||
// In preview mode, add the right-click menu and upload the image to GitHub image hosting
|
||||
QAction *uploadImageToGithub = new QAction(tr("Upload Image To &GitHub"),menu);
|
||||
connect(uploadImageToGithub, &QAction::triggered, this, &VWebView::requestUploadImageToGithub);
|
||||
menu->addAction(uploadImageToGithub);
|
||||
|
||||
// In preview mode, add the right-click menu and upload the image to Wechat image hosting
|
||||
QAction *uploadImageToWechat = new QAction(tr("Upload Image To &Wechat"),menu);
|
||||
connect(uploadImageToWechat, &QAction::triggered, this, &VWebView::requestUploadImageToWechat);
|
||||
menu->addAction(uploadImageToWechat);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,10 @@ signals:
|
||||
|
||||
void requestExpandRestorePreviewArea();
|
||||
|
||||
void requestUploadImageToGithub();
|
||||
|
||||
void requestUploadImageToWechat();
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent *p_event);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user