RabbitCommon v2.2.6
Loading...
Searching...
No Matches
DlgAbout.cpp
1/*++
2Copyright (c) Kang Lin studio, All Rights Reserved
3
4Author:
5 Kang Lin <kl222@126.com>
6
7Module Name:
8
9 DlgAbout.cpp
10
11Abstract:
12
13 This file contains about dialog implement.
14 */
15
16#include "DlgAbout.h"
17#include "ui_DlgAbout.h"
18#include "RabbitCommonDir.h"
19#include "RabbitCommonTools.h"
20
21#include "Log/Log.h"
22#include "Information.h"
23
24#ifdef HAVE_WebEngineWidgets
25 #include <QWebEngineView>
26#endif
27#include <QTextEdit>
28#include <QFile>
29#include <QDir>
30#include <QMenu>
31#include <QStandardPaths>
32#include <QSslError>
33#include <QDateTime>
34#include <QCursor>
35#include <QLoggingCategory>
36#include <QApplication>
37
38#ifdef HAVE_CMARK
39 #include "cmark.h"
40#endif
41#ifdef HAVE_CMARK_GFM
42 #include "cmark-gfm.h"
43 #include "cmark-gfm-core-extensions.h"
44 #include "registry.h"
45 #include "parser.h"
46#endif
47
48static Q_LOGGING_CATEGORY(log, "RabbitCommon.DlgAbout")
49
50CDlgAbout::CDlgAbout(QWidget *parent) :
51 QDialog(parent),
52 ui(new Ui::CDlgAbout)
53{
54#ifdef HAVE_CMARK_GFM
55 cmark_gfm_core_extensions_ensure_registered();
56 // free extensions at application exit (cmark-gfm is not able to register/unregister more than once)
57 std::atexit(cmark_release_plugins);
58#endif
59
60 ui->setupUi(this);
61
62 setAttribute(Qt::WA_QuitOnClose, true);
63
64 m_szAppName = qApp->applicationDisplayName();
65
66 m_szVersion = qApp->applicationVersion();
67#ifdef RabbitCommon_VERSION
68 if(m_szVersion.isEmpty())
69 {
70 qWarning(log) << "The m_szVersion is not set. Please use qApp->setApplicationVersion() or m_szVersion";
71 m_szVersion = RabbitCommon_VERSION;
72 }
73#endif
74
75 m_szArch = QSysInfo::buildCpuArchitecture();
76
77 m_szAuthor = tr("KangLin");
78 m_szEmail = "kl222@126.com";
79 m_szHomePage = "https://github.com/KangLin/" + qApp->applicationName();
80 m_szCopyrightOwner = tr("Kang Lin Studio");
81 m_szCopyrightStartTime = "2019";
82 m_AppIcon = QImage(":/icon/RabbitCommon/App");
83 m_CopyrightIcon = QImage(":/icon/RabbitCommon/CopyRight");
84 m_DonationIcon = QImage(":/icon/RabbitCommon/Contribute");
85
86 QVector<QUrl> urls;
87 urls << QUrl("https://github.com/KangLin/RabbitCommon/raw/master/Src/Resource/image/Contribute.png")
88 << QUrl("https://gitee.com/kl222/RabbitCommon/raw/master/Src/Resource/image/Contribute.png")
89 << QUrl("https://gitlab.com/kl222/RabbitCommon/-/raw/master/Src/Resource/image/Contribute.png");
90 m_Download = QSharedPointer<RabbitCommon::CDownload>(
91 new RabbitCommon::CDownload(), &QObject::deleteLater);
92 bool check = connect(m_Download.data(), SIGNAL(sigFinished(const QString)),
93 this, SLOT(slotDownloadFileFinished(const QString)));
94 Q_ASSERT(check);
95 check = connect(m_Download.data(), SIGNAL(sigError(int, const QString)),
96 this, SLOT(slotDownloadError(int, const QString)));
97 Q_ASSERT(check);
98 m_Download->Start(urls);
99
100#if (defined(HAVE_CMARK) || defined (HAVE_CMARK_GFM)) && defined(HAVE_WebEngineWidgets)
101 m_pLicense = new QWebEngineView(ui->tabWidget);
102 ui->tabWidget->addTab(m_pLicense, tr("License"));
103 m_pChangeLog = new QWebEngineView(ui->tabWidget);
104 ui->tabWidget->addTab(m_pChangeLog, tr("Change log"));
105 m_pThanks = new QWebEngineView(ui->tabWidget);
106 ui->tabWidget->addTab(m_pThanks, tr("Thanks"));
107#else
108 m_pLicense = new QTextEdit(ui->tabWidget);
109 qobject_cast<QTextEdit*>(m_pLicense)->setReadOnly(true);
110 ui->tabWidget->addTab(m_pLicense, tr("License"));
111 m_pChangeLog = new QTextEdit(ui->tabWidget);
112 qobject_cast<QTextEdit*>(m_pChangeLog)->setReadOnly(false);
113 ui->tabWidget->addTab(m_pChangeLog, tr("Change log"));
114 m_pThanks = new QTextEdit(ui->tabWidget);
115 qobject_cast<QTextEdit*>(m_pThanks)->setReadOnly(false);
116 ui->tabWidget->addTab(m_pThanks, tr("Thanks"));
117#endif
118
119 AppendFile(m_pChangeLog, "ChangeLog");
120 AppendFile(m_pLicense, "License");
121 AppendFile(m_pThanks, "Authors");
122
123#if defined (Q_OS_ANDROID)
124 ui->lbDonation->installEventFilter(this);
125#else
126 ui->lbDonation->setContextMenuPolicy(Qt::CustomContextMenu);
127 check = connect(ui->lbDonation, SIGNAL(customContextMenuRequested(const QPoint &)),
128 this, SLOT(slotDonation(const QPoint &)));
129 Q_ASSERT(check);
130#endif
131
132}
133
134void CDlgAbout::showEvent(QShowEvent *event)
135{
136 Q_UNUSED(event)
137
138 setWindowIcon(QIcon(QPixmap::fromImage(m_AppIcon)));
139 ui->lblLogo->setPixmap(QPixmap::fromImage(m_AppIcon));
140 ui->lbCopyrightIcon->setPixmap(QPixmap::fromImage(m_CopyrightIcon));
141 ui->lbDonation->setPixmap(QPixmap::fromImage(m_DonationIcon));
142 ui->lblName->setText(m_szAppName);
143 ui->lbVersion->setText(Version());
144 ui->lbVersion->setOpenExternalLinks(true);
145 ui->lbAuthor->setText(tr("Author: ") + m_szAuthor
146 + tr(" Email: ") + "<a href=\"" + m_szEmail + "\">"
147 + m_szEmail + "</a>");
148 ui->lbAuthor->setOpenExternalLinks(true);
149 ui->lbHome->setOpenExternalLinks(true);
150 ui->lbHome->setText(tr("Home page: ") + "<a href=\"" + m_szHomePage + "\">"
151 + m_szHomePage + "</a>");
152 if(m_szCopyright.isEmpty())
153 {
154 if(m_szCopyrightTime.isEmpty())
155 m_szCopyrightTime = tr("%1 - %2").arg(m_szCopyrightStartTime,
156 QString::number(QDate::currentDate().year()));
157 m_szCopyright = tr("Copyright (C)") + " " + m_szCopyrightTime + " " + m_szCopyrightOwner;
158 }
159 ui->lbCopyright->setText(m_szCopyright);
160
161 adjustSize();
162}
163
164CDlgAbout::~CDlgAbout()
165{
166 delete ui;
167}
168
169int CDlgAbout::AppendFile(QWidget* pWidget, const QString &szFile)
170{
171 QDir d;
172 QString szFileLocation;
173
174 szFileLocation = RabbitCommon::CDir::Instance()->GetDirDocument(
175 QApplication::applicationName(), true)
176 + QDir::separator()
177 + szFile + "_" + RabbitCommon::CTools::Instance()->GetLanguage() + ".md";
178 if(!d.exists(szFileLocation))
179 szFileLocation = RabbitCommon::CDir::Instance()->GetDirDocument(
180 QApplication::applicationName(), true)
181 + QDir::separator()
182 + szFile + ".md";
183 //TODO: be will remove in 3.0
184 if(!d.exists(szFileLocation))
185 szFileLocation = RabbitCommon::CDir::Instance()->GetDirApplicationInstallRoot() + QDir::separator()
186 + szFile + "_" + RabbitCommon::CTools::Instance()->GetLanguage() + ".md";
187 if(!d.exists(szFileLocation))
188 szFileLocation = RabbitCommon::CDir::Instance()->GetDirApplicationInstallRoot()
189 + QDir::separator() + szFile + ".md";
190
191 QFile readme(szFileLocation);
192 if(readme.open(QFile::ReadOnly))
193 {
194 QByteArray text;
195 text = readme.readAll();
196#if (defined(HAVE_CMARK) || defined(HAVE_CMARK_GFM)) && defined(HAVE_WebEngineWidgets)
197 QWebEngineView* pEdit = qobject_cast<QWebEngineView*>(pWidget);
198 QString szText = MarkDownToHtml(text);
199 if(szText.isEmpty())
200 szText = text;
201 pEdit->setHtml(szText);
202#else
203 QTextEdit* pEdit = qobject_cast<QTextEdit*>(pWidget);
204 pEdit->append(text);
205 //把光标移动文档开始处
206 QTextCursor cursor = pEdit->textCursor();
207 cursor.movePosition(QTextCursor::Start);
208 pEdit->setTextCursor(cursor);
209#endif
210 readme.close();
211 }
212 return 0;
213}
214
215QString CDlgAbout::MarkDownToHtml(const QString &szText)
216{
217 QString szRetureText = szText;
218
219#ifdef HAVE_CMARK_GFM
220
221 // TODO make this method which takes input and provides output: cmark_to_html()
222 cmark_mem* mem = cmark_get_default_mem_allocator();
223 // TODO control which extensions to use in MindForger config
224 cmark_llist* syntax_extensions = cmark_list_syntax_extensions(mem);
225 // TODO parse options
226 cmark_parser* parser = cmark_parser_new(CMARK_OPT_DEFAULT | CMARK_OPT_UNSAFE);
227 for (cmark_llist* tmp = syntax_extensions; tmp; tmp = tmp->next) {
228 cmark_parser_attach_syntax_extension(parser, (cmark_syntax_extension*)tmp->data);
229 }
230 cmark_parser_feed(parser, szText.toStdString().c_str(), szText.toStdString().length());
231
232 //cmark_node* doc = cmark_parse_document (markdown->c_str(), markdown->size(), CMARK_OPT_DEFAULT | CMARK_OPT_UNSAFE);
233 cmark_node* doc = cmark_parser_finish(parser);
234 if(doc) {
235 char *rendered_html = cmark_render_html_with_mem(doc, CMARK_OPT_DEFAULT | CMARK_OPT_UNSAFE, parser->syntax_extensions, mem);
236 if (rendered_html) {
237 szRetureText = rendered_html;
238 free(rendered_html);
239 }
240 cmark_node_free(doc);
241 }
242 cmark_llist_free(mem, syntax_extensions);
243 cmark_parser_free(parser);
244
245#elif HAVE_CMARK
246
247 char* pHtml = cmark_markdown_to_html(szText.toStdString().c_str(),
248 szText.toStdString().length(),
249 0);
250 if(pHtml)
251 {
252 szRetureText = pHtml;
253 free(pHtml);
254 }
255
256#endif
257 return szRetureText;
258}
259
260void CDlgAbout::on_pbOK_clicked()
261{
262 close();
263}
264
265void CDlgAbout::slotDonation(const QPoint &pos)
266{
267 Q_UNUSED(pos)
268 QMenu m;
269 m.addAction(QIcon::fromTheme("document-save"), tr("Save"),
270 this, SLOT(slotSaveDonation()));
271 m.exec(QCursor::pos());
272}
273
274void CDlgAbout::slotSaveDonation()
275{
276 QString szDir = RabbitCommon::CDir::Instance()->GetDirUserImage()
277 + QDir::separator() + "donation.png";
278 QString szFile = QFileDialog::getSaveFileName(this,
279 tr("Save donation picture"),
280 szDir,
281 tr("Images (*.png *.xpm *.jpg)"));
282 QFileInfo fi(szFile);
283 if(fi.suffix().isEmpty())
284 szFile += ".png";
285 if(!szFile.isEmpty())
286 m_DonationIcon.save(szFile);
287}
288
289#if defined (Q_OS_ANDROID)
290bool CDlgAbout::eventFilter(QObject *watched, QEvent *event)
291{
292 qDebug() << event->type();
293 if(event->type() == QEvent::MouseButtonRelease)
294 slotSaveDonation();
295 return QDialog::eventFilter(watched, event);
296}
297#endif
298
299int CDlgAbout::SetDonationIcon(const QImage &img)
300{
301 m_Download.clear();
302 m_DonationIcon = img;
303 return 0;
304}
305
306QString CDlgAbout::BuildTime()
307{
308 if(m_szBuildTime.isEmpty())
309 return QString("%1/%2").arg(__DATE__, __TIME__);
310 return m_szBuildTime;
311}
312
313QString CDlgAbout::Version()
314{
315 QString szVersion;
316 if(m_szVersionRevision.isEmpty())
317 {
318 szVersion = tr("Version: ") + m_szVersion + " " + tr("Arch: ") + m_szArch;
319 } else {
320 if(m_szVersionRevisionUrl.isEmpty())
321 {
322 m_szVersionRevisionUrl =
323 m_szHomePage + "/tree/" + m_szVersionRevision;
324 }
325 szVersion = tr("Version: ") + m_szVersion + tr(" (From revision: ")
326#if (defined(HAVE_CMARK) || defined(HAVE_CMARK_GFM)) && defined(HAVE_WebEngineWidgets)
327 + "<a href=\"" + m_szVersionRevisionUrl + "\">"
328 + m_szVersionRevision + "</a>"
329#else
330 + m_szVersionRevision
331#endif
332 + ") " + tr("Arch: ") + m_szArch;
333 }
334 return szVersion;
335}
336
337void CDlgAbout::slotDownloadError(int nErr, const QString szError)
338{
339 QString szMsg;
340 szMsg = tr("Failed:") + tr("Download file is Failed.");
341 if(!szError.isEmpty())
342 szMsg += "(" + szError + ")";
343 qCritical(log) << szMsg << nErr;
344}
345
346void CDlgAbout::slotDownloadFileFinished(const QString szFile)
347{
348 qDebug(log) << "slotDownloadFileFinished:" << szFile;
349 m_DonationIcon.load(szFile);
350 ui->lbDonation->setPixmap(QPixmap::fromImage(m_DonationIcon));
351}
352
353void CDlgAbout::on_pbDetails_clicked()
354{
355 QString szApp;
356
357 szApp = tr("### ") + QApplication::applicationDisplayName() + "\n";
358 szApp += "- " + Version() + "\n";
359 szApp += "- " + tr("Build Date/Time: ") + BuildTime() + "\n";
360 szApp += "- " + tr("File Path: ") + QApplication::applicationFilePath() + "\n";
361 szApp += "- " + tr("Arguments: ") + qApp->arguments().join(' ') + "\n";
362
363 QCursor cursor = this->cursor();
364 setCursor(Qt::WaitCursor);
365 CInformation info(szApp, m_szDetails, this);
366#if defined (Q_OS_ANDROID)
367 info.showMaximized();
368#endif
369 info.exec();
370 setCursor(cursor);
371}
About dialog.
Definition DlgAbout.h:69
QString m_szVersion
The application version, it is different RabbitCommon::CTools::Version()
Definition DlgAbout.h:80
QString GetDirDocument(QString szProjectName=QString(), bool bReadOnly=false)
GetDirDocument.
Download the same file from multiple URLs.
Definition Download.h:45