merge qtextbrowser, covid here, have to take pause
This commit is contained in:
parent
52798f9ed2
commit
983f1eef10
@ -568,9 +568,13 @@ if(USE_WEBENGINE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
# Lite non-WebEngine message browser.
|
# Litehtml.
|
||||||
gui/webviewers/litehtml/litehtmlviewer.h
|
gui/webviewers/litehtml/litehtmlviewer.h
|
||||||
gui/webviewers/litehtml/litehtmlviewer.cpp
|
gui/webviewers/litehtml/litehtmlviewer.cpp
|
||||||
|
|
||||||
|
# QTextBrowser.
|
||||||
|
gui/webviewers/qtextbrowser/textbrowserviewer.h
|
||||||
|
gui/webviewers/qtextbrowser/textbrowserviewer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Deal with .ui files.
|
# Deal with .ui files.
|
||||||
|
@ -26,10 +26,11 @@ class DiscoverFeedsButton;
|
|||||||
class SearchTextWidget;
|
class SearchTextWidget;
|
||||||
|
|
||||||
class WebBrowser : public TabContent {
|
class WebBrowser : public TabContent {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
friend class WebEngineViewer;
|
friend class WebEngineViewer;
|
||||||
friend class LiteHtmlViewer;
|
friend class LiteHtmlViewer;
|
||||||
|
friend class TextBrowserViewer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WebBrowser(WebViewer* viewer = nullptr, QWidget* parent = nullptr);
|
explicit WebBrowser(WebViewer* viewer = nullptr, QWidget* parent = nullptr);
|
||||||
|
@ -161,7 +161,8 @@ QPair<QString, QUrl> LiteHtmlViewer::prepareHtmlForMessage(const QList<Message>&
|
|||||||
else {*/
|
else {*/
|
||||||
QString cnts = message.m_contents;
|
QString cnts = message.m_contents;
|
||||||
|
|
||||||
html += cnts.replace(imgTagRegex, QString());
|
html += cnts;
|
||||||
|
// html += cnts.replace(imgTagRegex, QString());
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -0,0 +1,275 @@
|
|||||||
|
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||||
|
|
||||||
|
#include "gui/webviewers/qtextbrowser/textbrowserviewer.h"
|
||||||
|
|
||||||
|
#include "gui/messagebox.h"
|
||||||
|
#include "gui/webbrowser.h"
|
||||||
|
#include "miscellaneous/application.h"
|
||||||
|
#include "miscellaneous/externaltool.h"
|
||||||
|
#include "miscellaneous/iconfactory.h"
|
||||||
|
#include "network-web/webfactory.h"
|
||||||
|
|
||||||
|
#include <QContextMenuEvent>
|
||||||
|
#include <QFileIconProvider>
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
TextBrowserViewer::TextBrowserViewer(QWidget* parent) : QTextBrowser(parent) {
|
||||||
|
setAutoFillBackground(true);
|
||||||
|
setFrameShape(QFrame::Shape::StyledPanel);
|
||||||
|
setFrameShadow(QFrame::Shadow::Plain);
|
||||||
|
setTabChangesFocus(true);
|
||||||
|
setOpenLinks(false);
|
||||||
|
viewport()->setAutoFillBackground(true);
|
||||||
|
|
||||||
|
connect(this, &QTextBrowser::anchorClicked, this, &TextBrowserViewer::onAnchorClicked);
|
||||||
|
connect(this, QOverload<const QUrl&>::of(&QTextBrowser::highlighted), this, &TextBrowserViewer::linkMouseHighlighted);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TextBrowserViewer::loadResource(int type, const QUrl& name) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize TextBrowserViewer::sizeHint() const {
|
||||||
|
auto doc_size = document()->size().toSize();
|
||||||
|
|
||||||
|
doc_size.setHeight(doc_size.height() + contentsMargins().top() + contentsMargins().bottom());
|
||||||
|
return doc_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<QString, QUrl> TextBrowserViewer::prepareHtmlForMessage(const QList<Message>& messages,
|
||||||
|
RootItem* selected_item) const {
|
||||||
|
QString html;
|
||||||
|
|
||||||
|
for (const Message& message : messages) {
|
||||||
|
html += QString("<h2 align=\"center\">%1</h2>").arg(message.m_title);
|
||||||
|
|
||||||
|
if (!message.m_url.isEmpty()) {
|
||||||
|
html += QString("[url] <a href=\"%1\">%1</a><br/>").arg(message.m_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Enclosure& enc : message.m_enclosures) {
|
||||||
|
html += QString("[%2] <a href=\"%1\">%1</a><br/>").arg(enc.m_url, enc.m_mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRegularExpression imgTagRegex("\\<img[^\\>]*src\\s*=\\s*[\"\']([^\"\']*)[\"\'][^\\>]*\\>",
|
||||||
|
QRegularExpression::PatternOption::CaseInsensitiveOption |
|
||||||
|
QRegularExpression::PatternOption::InvertedGreedinessOption);
|
||||||
|
QRegularExpressionMatchIterator i = imgTagRegex.globalMatch(message.m_contents);
|
||||||
|
QString pictures_html;
|
||||||
|
|
||||||
|
while (i.hasNext()) {
|
||||||
|
QRegularExpressionMatch match = i.next();
|
||||||
|
|
||||||
|
pictures_html += QString("<br/>[%1] <a href=\"%2\">%2</a>").arg(tr("image"), match.captured(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::DisplayImagePlaceholders)).toBool()) {
|
||||||
|
html += message.m_contents;
|
||||||
|
}
|
||||||
|
else {*/
|
||||||
|
QString cnts = message.m_contents;
|
||||||
|
|
||||||
|
html += cnts;
|
||||||
|
// html += cnts.replace(imgTagRegex, QString());
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
html += pictures_html;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: If FgInteresting not defined by the skin
|
||||||
|
// use current pallette/Highlight color perhaps.
|
||||||
|
return {
|
||||||
|
QSL("<html>"
|
||||||
|
"<head><style>"
|
||||||
|
"a { color: %2; }"
|
||||||
|
"</style></head>"
|
||||||
|
"<body>%1</body>"
|
||||||
|
"</html>")
|
||||||
|
.arg(html,
|
||||||
|
qApp->skins()->currentSkin().colorForModel(SkinEnums::PaletteColors::FgInteresting).value<QColor>().name()),
|
||||||
|
QUrl()};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::bindToBrowser(WebBrowser* browser) {
|
||||||
|
installEventFilter(browser);
|
||||||
|
|
||||||
|
browser->m_actionBack = new QAction(this);
|
||||||
|
browser->m_actionForward = new QAction(this);
|
||||||
|
browser->m_actionReload = new QAction(this);
|
||||||
|
browser->m_actionStop = new QAction(this);
|
||||||
|
|
||||||
|
browser->m_actionBack->setEnabled(false);
|
||||||
|
browser->m_actionForward->setEnabled(false);
|
||||||
|
browser->m_actionReload->setEnabled(false);
|
||||||
|
|
||||||
|
// TODO: When clicked "Stop", save the "Stop" state and return {} from "handleResource(...)"
|
||||||
|
// right away.
|
||||||
|
browser->m_actionStop->setEnabled(false);
|
||||||
|
|
||||||
|
// TODO: add "Open in new tab" to context menu.
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::findText(const QString& text, bool backwards) {
|
||||||
|
if (!text.isEmpty()) {
|
||||||
|
QTextBrowser::find(text, backwards ? QTextDocument::FindFlag::FindBackward : QTextDocument::FindFlag(0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
textCursor().clearSelection();
|
||||||
|
moveCursor(QTextCursor::MoveOperation::Left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::setUrl(const QUrl& url) {}
|
||||||
|
|
||||||
|
void TextBrowserViewer::setHtml(const QString& html, const QUrl& base_url) {
|
||||||
|
m_currentUrl = base_url;
|
||||||
|
|
||||||
|
QTextBrowser::setHtml(html);
|
||||||
|
|
||||||
|
emit pageTitleChanged(documentTitle());
|
||||||
|
emit pageUrlChanged(base_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TextBrowserViewer::html() const {
|
||||||
|
return QTextBrowser::toHtml();
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl TextBrowserViewer::url() const {
|
||||||
|
return m_currentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::clear() {
|
||||||
|
setHtml({});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::loadMessages(const QList<Message>& messages, RootItem* root) {
|
||||||
|
m_root = root;
|
||||||
|
|
||||||
|
auto html_messages = prepareHtmlForMessage(messages, root);
|
||||||
|
|
||||||
|
setHtml(html_messages.first, html_messages.second);
|
||||||
|
emit loadingFinished(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
double TextBrowserViewer::verticalScrollBarPosition() const {
|
||||||
|
return verticalScrollBar()->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::setVerticalScrollBarPosition(double pos) {
|
||||||
|
verticalScrollBar()->setValue(int(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::applyFont(const QFont& fon) {
|
||||||
|
setFont(fon);
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal TextBrowserViewer::zoomFactor() const {
|
||||||
|
return font().pointSize() / 12.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::setZoomFactor(qreal zoom_factor) {
|
||||||
|
auto fon = font();
|
||||||
|
fon.setPointSize(fon.pointSize() * zoom_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::contextMenuEvent(QContextMenuEvent* event) {
|
||||||
|
event->accept();
|
||||||
|
|
||||||
|
auto* menu = createStandardContextMenu();
|
||||||
|
|
||||||
|
if (menu == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto anchor = anchorAt(event->pos());
|
||||||
|
|
||||||
|
if (!anchor.isEmpty()) {
|
||||||
|
QFileIconProvider icon_provider;
|
||||||
|
QMenu* menu_ext_tools = new QMenu(tr("Open with external tool"), menu);
|
||||||
|
auto tools = ExternalTool::toolsFromSettings();
|
||||||
|
|
||||||
|
menu_ext_tools->setIcon(qApp->icons()->fromTheme(QSL("document-open")));
|
||||||
|
|
||||||
|
for (const ExternalTool& tool : qAsConst(tools)) {
|
||||||
|
QAction* act_tool = new QAction(QFileInfo(tool.executable()).fileName(), menu_ext_tools);
|
||||||
|
|
||||||
|
act_tool->setIcon(icon_provider.icon(QFileInfo(tool.executable())));
|
||||||
|
act_tool->setToolTip(tool.executable());
|
||||||
|
act_tool->setData(QVariant::fromValue(tool));
|
||||||
|
menu_ext_tools->addAction(act_tool);
|
||||||
|
|
||||||
|
connect(act_tool, &QAction::triggered, this, [act_tool, anchor]() {
|
||||||
|
act_tool->data().value<ExternalTool>().run(anchor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menu_ext_tools->actions().isEmpty()) {
|
||||||
|
QAction* act_not_tools = new QAction("No external tools activated");
|
||||||
|
|
||||||
|
act_not_tools->setEnabled(false);
|
||||||
|
menu_ext_tools->addAction(act_not_tools);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu->addMenu(menu_ext_tools);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu->popup(event->globalPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::resizeEvent(QResizeEvent* event) {
|
||||||
|
// Notify parents about changed geometry.
|
||||||
|
updateGeometry();
|
||||||
|
QTextBrowser::resizeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::onAnchorClicked(const QUrl& url) {
|
||||||
|
if (!url.isEmpty()) {
|
||||||
|
bool open_externally_now =
|
||||||
|
qApp->settings()->value(GROUP(Browser), SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool();
|
||||||
|
|
||||||
|
if (open_externally_now) {
|
||||||
|
qApp->web()->openUrlInExternalBrowser(url.toString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// User clicked some URL. Open it in external browser or download?
|
||||||
|
MsgBox box(qApp->mainFormWidget());
|
||||||
|
|
||||||
|
box.setText(tr("You clicked some link. You can download the link contents or open it in external web browser."));
|
||||||
|
box.setInformativeText(tr("What action do you want to take?"));
|
||||||
|
box.setDetailedText(url.toString());
|
||||||
|
|
||||||
|
QAbstractButton* btn_open = box.addButton(tr("Open in external browser"), QMessageBox::ButtonRole::ActionRole);
|
||||||
|
QAbstractButton* btn_download = box.addButton(tr("Download"), QMessageBox::ButtonRole::ActionRole);
|
||||||
|
QAbstractButton* btn_cancel = box.addButton(QMessageBox::StandardButton::Cancel);
|
||||||
|
bool always;
|
||||||
|
|
||||||
|
MsgBox::setCheckBox(&box, tr("Always open links in external browser."), &always);
|
||||||
|
|
||||||
|
box.setDefaultButton(QMessageBox::StandardButton::Cancel);
|
||||||
|
box.exec();
|
||||||
|
|
||||||
|
if (box.clickedButton() != box.button(QMessageBox::StandardButton::Cancel)) {
|
||||||
|
// Store selected checkbox value.
|
||||||
|
qApp->settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, always);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (box.clickedButton() == btn_open) {
|
||||||
|
qApp->web()->openUrlInExternalBrowser(url.toString());
|
||||||
|
}
|
||||||
|
else if (box.clickedButton() == btn_download) {
|
||||||
|
qApp->downloadManager()->download(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
btn_download->deleteLater();
|
||||||
|
btn_open->deleteLater();
|
||||||
|
btn_cancel->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MsgBox::show(qApp->mainFormWidget(),
|
||||||
|
QMessageBox::Warning,
|
||||||
|
tr("Incorrect link"),
|
||||||
|
tr("Selected hyperlink is invalid."));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||||
|
|
||||||
|
#ifndef TEXTBROWSERVIEWER_H
|
||||||
|
#define TEXTBROWSERVIEWER_H
|
||||||
|
|
||||||
|
#include "gui/webviewers/webviewer.h"
|
||||||
|
|
||||||
|
#include <QTextBrowser>
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
class QContextMenuEvent;
|
||||||
|
class QResizeEvent;
|
||||||
|
class WebBrowser;
|
||||||
|
|
||||||
|
class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_INTERFACES(WebViewer)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit TextBrowserViewer(QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
virtual QVariant loadResource(int type, const QUrl& name);
|
||||||
|
virtual QSize sizeHint() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void bindToBrowser(WebBrowser* browser);
|
||||||
|
virtual void findText(const QString& text, bool backwards);
|
||||||
|
virtual void setUrl(const QUrl& url);
|
||||||
|
virtual void setHtml(const QString& html, const QUrl& base_url = {});
|
||||||
|
virtual QString html() const;
|
||||||
|
virtual QUrl url() const;
|
||||||
|
virtual void clear();
|
||||||
|
virtual void loadMessages(const QList<Message>& messages, RootItem* root);
|
||||||
|
virtual double verticalScrollBarPosition() const;
|
||||||
|
virtual void setVerticalScrollBarPosition(double pos);
|
||||||
|
virtual void applyFont(const QFont& fon);
|
||||||
|
virtual qreal zoomFactor() const;
|
||||||
|
virtual void setZoomFactor(qreal zoom_factor);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void contextMenuEvent(QContextMenuEvent* event);
|
||||||
|
virtual void resizeEvent(QResizeEvent* event);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onAnchorClicked(const QUrl& url);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void pageTitleChanged(const QString& new_title);
|
||||||
|
void pageUrlChanged(const QUrl& url);
|
||||||
|
void pageIconChanged(const QIcon&);
|
||||||
|
void linkMouseHighlighted(const QUrl& url);
|
||||||
|
void loadingStarted();
|
||||||
|
void loadingProgress(int progress);
|
||||||
|
void loadingFinished(bool success);
|
||||||
|
void newWindowRequested(WebViewer* viewer);
|
||||||
|
void closeWindowRequested();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPair<QString, QUrl> prepareHtmlForMessage(const QList<Message>& messages, RootItem* selected_item) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QUrl m_currentUrl;
|
||||||
|
QPointer<RootItem> m_root;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TEXTBROWSERVIEWER_H
|
@ -11,7 +11,8 @@
|
|||||||
#include "gui/feedsview.h"
|
#include "gui/feedsview.h"
|
||||||
#include "gui/messagebox.h"
|
#include "gui/messagebox.h"
|
||||||
#include "gui/toolbars/statusbar.h"
|
#include "gui/toolbars/statusbar.h"
|
||||||
#include "gui/webviewers/litehtml/litehtmlviewer.h" // QLiteHtml-based web browsing.
|
#include "gui/webviewers/litehtml/litehtmlviewer.h" // QLiteHtml-based web browsing.
|
||||||
|
#include "gui/webviewers/qtextbrowser/textbrowserviewer.h" // QTextBrowser-based web browsing.
|
||||||
#include "miscellaneous/feedreader.h"
|
#include "miscellaneous/feedreader.h"
|
||||||
#include "miscellaneous/iconfactory.h"
|
#include "miscellaneous/iconfactory.h"
|
||||||
#include "miscellaneous/iofactory.h"
|
#include "miscellaneous/iofactory.h"
|
||||||
@ -62,7 +63,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Application::Application(const QString &id, int &argc, char **argv, const QStringList &raw_cli_args)
|
Application::Application(const QString& id, int& argc, char** argv, const QStringList& raw_cli_args)
|
||||||
: SingleApplication(id, argc, argv), m_updateFeedsLock(new Mutex()) {
|
: SingleApplication(id, argc, argv), m_updateFeedsLock(new Mutex()) {
|
||||||
parseCmdArgumentsFromMyInstance(raw_cli_args);
|
parseCmdArgumentsFromMyInstance(raw_cli_args);
|
||||||
qInstallMessageHandler(performLogging);
|
qInstallMessageHandler(performLogging);
|
||||||
@ -87,15 +88,19 @@ Application::Application(const QString &id, int &argc, char **argv, const QStrin
|
|||||||
m_windowsTaskBar = nullptr;
|
m_windowsTaskBar = nullptr;
|
||||||
|
|
||||||
const GUID qIID_ITaskbarList4 = {0xc43dc798, 0x95d1, 0x4bea, {0x90, 0x30, 0xbb, 0x99, 0xe2, 0x98, 0x3a, 0x1a}};
|
const GUID qIID_ITaskbarList4 = {0xc43dc798, 0x95d1, 0x4bea, {0x90, 0x30, 0xbb, 0x99, 0xe2, 0x98, 0x3a, 0x1a}};
|
||||||
HRESULT task_result = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, qIID_ITaskbarList4,
|
HRESULT task_result = CoCreateInstance(CLSID_TaskbarList,
|
||||||
reinterpret_cast<void **>(&m_windowsTaskBar));
|
nullptr,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
qIID_ITaskbarList4,
|
||||||
|
reinterpret_cast<void**>(&m_windowsTaskBar));
|
||||||
|
|
||||||
if (FAILED(task_result)) {
|
if (FAILED(task_result)) {
|
||||||
qCriticalNN << LOGSEC_CORE << "Taskbar integration for Windows failed to initialize with HRESULT:"
|
qCriticalNN << LOGSEC_CORE << "Taskbar integration for Windows failed to initialize with HRESULT:"
|
||||||
<< QUOTE_W_SPACE_DOT(task_result);
|
<< QUOTE_W_SPACE_DOT(task_result);
|
||||||
|
|
||||||
m_windowsTaskBar = nullptr;
|
m_windowsTaskBar = nullptr;
|
||||||
} else if (FAILED(m_windowsTaskBar->HrInit())) {
|
}
|
||||||
|
else if (FAILED(m_windowsTaskBar->HrInit())) {
|
||||||
qCriticalNN << LOGSEC_CORE << "Taskbar integration for Windows failed to initialize with inner HRESULT:"
|
qCriticalNN << LOGSEC_CORE << "Taskbar integration for Windows failed to initialize with inner HRESULT:"
|
||||||
<< QUOTE_W_SPACE_DOT(m_windowsTaskBar->HrInit());
|
<< QUOTE_W_SPACE_DOT(m_windowsTaskBar->HrInit());
|
||||||
|
|
||||||
@ -156,7 +161,9 @@ Application::Application(const QString &id, int &argc, char **argv, const QStrin
|
|||||||
qDebugNN << LOGSEC_NETWORK << "Persistent web data storage path:"
|
qDebugNN << LOGSEC_NETWORK << "Persistent web data storage path:"
|
||||||
<< QUOTE_W_SPACE_DOT(QWebEngineProfile::defaultProfile()->persistentStoragePath());
|
<< QUOTE_W_SPACE_DOT(QWebEngineProfile::defaultProfile()->persistentStoragePath());
|
||||||
|
|
||||||
connect(QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested, this,
|
connect(QWebEngineProfile::defaultProfile(),
|
||||||
|
&QWebEngineProfile::downloadRequested,
|
||||||
|
this,
|
||||||
&Application::downloadRequested);
|
&Application::downloadRequested);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -164,9 +171,10 @@ Application::Application(const QString &id, int &argc, char **argv, const QStrin
|
|||||||
|
|
||||||
QTimer::singleShot(3000, this, [=]() {
|
QTimer::singleShot(3000, this, [=]() {
|
||||||
try {
|
try {
|
||||||
m_webFactory->adBlock()->setEnabled(
|
m_webFactory->adBlock()
|
||||||
qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::AdBlockEnabled)).toBool());
|
->setEnabled(qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::AdBlockEnabled)).toBool());
|
||||||
} catch (...) {
|
}
|
||||||
|
catch (...) {
|
||||||
onAdBlockFailure();
|
onAdBlockFailure();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -175,14 +183,16 @@ Application::Application(const QString &id, int &argc, char **argv, const QStrin
|
|||||||
|
|
||||||
if (isFirstRun()) {
|
if (isFirstRun()) {
|
||||||
m_notifications->save({Notification(Notification::Event::GeneralEvent, true),
|
m_notifications->save({Notification(Notification::Event::GeneralEvent, true),
|
||||||
Notification(Notification::Event::NewUnreadArticlesFetched, true,
|
Notification(Notification::Event::NewUnreadArticlesFetched,
|
||||||
|
true,
|
||||||
QSL("%1/notify.wav").arg(SOUNDS_BUILTIN_DIRECTORY)),
|
QSL("%1/notify.wav").arg(SOUNDS_BUILTIN_DIRECTORY)),
|
||||||
Notification(Notification::Event::NewAppVersionAvailable, true),
|
Notification(Notification::Event::NewAppVersionAvailable, true),
|
||||||
Notification(Notification::Event::LoginFailure, true),
|
Notification(Notification::Event::LoginFailure, true),
|
||||||
Notification(Notification::Event::NodePackageUpdated, true),
|
Notification(Notification::Event::NodePackageUpdated, true),
|
||||||
Notification(Notification::Event::NodePackageFailedToUpdate, true)},
|
Notification(Notification::Event::NodePackageFailedToUpdate, true)},
|
||||||
settings());
|
settings());
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
m_notifications->load(settings());
|
m_notifications->load(settings());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +216,7 @@ Application::~Application() {
|
|||||||
QString s_customLogFile = QString();
|
QString s_customLogFile = QString();
|
||||||
bool s_disableDebug = false;
|
bool s_disableDebug = false;
|
||||||
|
|
||||||
void Application::performLogging(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
|
void Application::performLogging(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
|
||||||
#ifndef QT_NO_DEBUG_OUTPUT
|
#ifndef QT_NO_DEBUG_OUTPUT
|
||||||
QString console_message = qFormatLogMessage(type, context, msg);
|
QString console_message = qFormatLogMessage(type, context, msg);
|
||||||
|
|
||||||
@ -244,13 +254,16 @@ void Application::hideOrShowMainForm() {
|
|||||||
SystemTrayIcon::isSystemTrayDesired() && SystemTrayIcon::isSystemTrayAreaAvailable()) {
|
SystemTrayIcon::isSystemTrayDesired() && SystemTrayIcon::isSystemTrayAreaAvailable()) {
|
||||||
qDebugNN << LOGSEC_CORE << "Hiding the main window when the application is starting.";
|
qDebugNN << LOGSEC_CORE << "Hiding the main window when the application is starting.";
|
||||||
mainForm()->switchVisibility(true);
|
mainForm()->switchVisibility(true);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
qDebugNN << LOGSEC_CORE << "Showing the main window when the application is starting.";
|
qDebugNN << LOGSEC_CORE << "Showing the main window when the application is starting.";
|
||||||
mainForm()->show();
|
mainForm()->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::loadDynamicShortcuts() { DynamicShortcuts::load(userActions()); }
|
void Application::loadDynamicShortcuts() {
|
||||||
|
DynamicShortcuts::load(userActions());
|
||||||
|
}
|
||||||
|
|
||||||
void Application::showPolls() const {
|
void Application::showPolls() const {
|
||||||
/*
|
/*
|
||||||
@ -271,7 +284,10 @@ void Application::offerChanges() const {
|
|||||||
"version by clicking this popup notification.")
|
"version by clicking this popup notification.")
|
||||||
.arg(QSL(APP_LONG_NAME)),
|
.arg(QSL(APP_LONG_NAME)),
|
||||||
QSystemTrayIcon::MessageIcon::NoIcon},
|
QSystemTrayIcon::MessageIcon::NoIcon},
|
||||||
{}, {tr("Go to changelog"), [] { FormAbout(qApp->mainForm()).exec(); }});
|
{},
|
||||||
|
{tr("Go to changelog"), [] {
|
||||||
|
FormAbout(qApp->mainForm()).exec();
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,15 +300,21 @@ bool Application::isAlreadyRunning() {
|
|||||||
|
|
||||||
QStringList Application::builtinSounds() const {
|
QStringList Application::builtinSounds() const {
|
||||||
auto builtin_sounds = QDir(QSL(SOUNDS_BUILTIN_DIRECTORY)).entryInfoList(QDir::Filter::Files, QDir::SortFlag::Name);
|
auto builtin_sounds = QDir(QSL(SOUNDS_BUILTIN_DIRECTORY)).entryInfoList(QDir::Filter::Files, QDir::SortFlag::Name);
|
||||||
auto iter = boolinq::from(builtin_sounds).select([](const QFileInfo &i) { return i.absoluteFilePath(); }).toStdList();
|
auto iter = boolinq::from(builtin_sounds)
|
||||||
|
.select([](const QFileInfo& i) {
|
||||||
|
return i.absoluteFilePath();
|
||||||
|
})
|
||||||
|
.toStdList();
|
||||||
auto descs = FROM_STD_LIST(QStringList, iter);
|
auto descs = FROM_STD_LIST(QStringList, iter);
|
||||||
|
|
||||||
return descs;
|
return descs;
|
||||||
}
|
}
|
||||||
|
|
||||||
FeedReader *Application::feedReader() { return m_feedReader; }
|
FeedReader* Application::feedReader() {
|
||||||
|
return m_feedReader;
|
||||||
|
}
|
||||||
|
|
||||||
QList<QAction *> Application::userActions() {
|
QList<QAction*> Application::userActions() {
|
||||||
if (m_mainForm != nullptr && m_userActions.isEmpty()) {
|
if (m_mainForm != nullptr && m_userActions.isEmpty()) {
|
||||||
m_userActions = m_mainForm->allActions();
|
m_userActions = m_mainForm->allActions();
|
||||||
m_userActions.append(m_webFactory->adBlock()->adBlockIcon());
|
m_userActions.append(m_webFactory->adBlock()->adBlockIcon());
|
||||||
@ -301,21 +323,37 @@ QList<QAction *> Application::userActions() {
|
|||||||
return m_userActions;
|
return m_userActions;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::isFirstRun() const { return m_firstRunEver; }
|
bool Application::isFirstRun() const {
|
||||||
|
return m_firstRunEver;
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::isFirstRunCurrentVersion() const { return m_firstRunCurrentVersion; }
|
bool Application::isFirstRunCurrentVersion() const {
|
||||||
|
return m_firstRunCurrentVersion;
|
||||||
|
}
|
||||||
|
|
||||||
QCommandLineParser *Application::cmdParser() { return &m_cmdParser; }
|
QCommandLineParser* Application::cmdParser() {
|
||||||
|
return &m_cmdParser;
|
||||||
|
}
|
||||||
|
|
||||||
WebFactory *Application::web() const { return m_webFactory; }
|
WebFactory* Application::web() const {
|
||||||
|
return m_webFactory;
|
||||||
|
}
|
||||||
|
|
||||||
SystemFactory *Application::system() { return m_system; }
|
SystemFactory* Application::system() {
|
||||||
|
return m_system;
|
||||||
|
}
|
||||||
|
|
||||||
SkinFactory *Application::skins() { return m_skins; }
|
SkinFactory* Application::skins() {
|
||||||
|
return m_skins;
|
||||||
|
}
|
||||||
|
|
||||||
Localization *Application::localization() { return m_localization; }
|
Localization* Application::localization() {
|
||||||
|
return m_localization;
|
||||||
|
}
|
||||||
|
|
||||||
DatabaseFactory *Application::database() { return m_database; }
|
DatabaseFactory* Application::database() {
|
||||||
|
return m_database;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::eliminateFirstRuns() {
|
void Application::eliminateFirstRuns() {
|
||||||
settings()->setValue(GROUP(General), General::FirstRun, false);
|
settings()->setValue(GROUP(General), General::FirstRun, false);
|
||||||
@ -323,15 +361,21 @@ void Application::eliminateFirstRuns() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_WEBENGINE)
|
#if defined(USE_WEBENGINE)
|
||||||
bool Application::forcedNoWebEngine() const { return m_forcedNoWebEngine; }
|
bool Application::forcedNoWebEngine() const {
|
||||||
|
return m_forcedNoWebEngine;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NodeJs *Application::nodejs() const { return m_nodejs; }
|
NodeJs* Application::nodejs() const {
|
||||||
|
return m_nodejs;
|
||||||
|
}
|
||||||
|
|
||||||
NotificationFactory *Application::notifications() const { return m_notifications; }
|
NotificationFactory* Application::notifications() const {
|
||||||
|
return m_notifications;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setFeedReader(FeedReader *feed_reader) {
|
void Application::setFeedReader(FeedReader* feed_reader) {
|
||||||
m_feedReader = feed_reader;
|
m_feedReader = feed_reader;
|
||||||
|
|
||||||
connect(m_feedReader, &FeedReader::feedUpdatesStarted, this, &Application::onFeedUpdatesStarted);
|
connect(m_feedReader, &FeedReader::feedUpdatesStarted, this, &Application::onFeedUpdatesStarted);
|
||||||
@ -340,29 +384,45 @@ void Application::setFeedReader(FeedReader *feed_reader) {
|
|||||||
connect(m_feedReader->feedsModel(), &FeedsModel::messageCountsChanged, this, &Application::showMessagesNumber);
|
connect(m_feedReader->feedsModel(), &FeedsModel::messageCountsChanged, this, &Application::showMessagesNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
IconFactory *Application::icons() { return m_icons; }
|
IconFactory* Application::icons() {
|
||||||
|
return m_icons;
|
||||||
|
}
|
||||||
|
|
||||||
DownloadManager *Application::downloadManager() {
|
DownloadManager* Application::downloadManager() {
|
||||||
if (m_downloadManager == nullptr) {
|
if (m_downloadManager == nullptr) {
|
||||||
m_downloadManager = new DownloadManager();
|
m_downloadManager = new DownloadManager();
|
||||||
connect(m_downloadManager, &DownloadManager::downloadFinished, mainForm()->statusBar(),
|
connect(m_downloadManager,
|
||||||
|
&DownloadManager::downloadFinished,
|
||||||
|
mainForm()->statusBar(),
|
||||||
&StatusBar::clearProgressDownload);
|
&StatusBar::clearProgressDownload);
|
||||||
connect(m_downloadManager, &DownloadManager::downloadProgressed, mainForm()->statusBar(),
|
connect(m_downloadManager,
|
||||||
|
&DownloadManager::downloadProgressed,
|
||||||
|
mainForm()->statusBar(),
|
||||||
&StatusBar::showProgressDownload);
|
&StatusBar::showProgressDownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_downloadManager;
|
return m_downloadManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings *Application::settings() const { return m_settings; }
|
Settings* Application::settings() const {
|
||||||
|
return m_settings;
|
||||||
|
}
|
||||||
|
|
||||||
Mutex *Application::feedUpdateLock() { return m_updateFeedsLock.data(); }
|
Mutex* Application::feedUpdateLock() {
|
||||||
|
return m_updateFeedsLock.data();
|
||||||
|
}
|
||||||
|
|
||||||
FormMain *Application::mainForm() { return m_mainForm; }
|
FormMain* Application::mainForm() {
|
||||||
|
return m_mainForm;
|
||||||
|
}
|
||||||
|
|
||||||
QWidget *Application::mainFormWidget() { return m_mainForm; }
|
QWidget* Application::mainFormWidget() {
|
||||||
|
return m_mainForm;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setMainForm(FormMain *main_form) { m_mainForm = main_form; }
|
void Application::setMainForm(FormMain* main_form) {
|
||||||
|
m_mainForm = main_form;
|
||||||
|
}
|
||||||
|
|
||||||
QString Application::configFolder() const {
|
QString Application::configFolder() const {
|
||||||
return IOFactory::getSystemFolder(QStandardPaths::StandardLocation::GenericConfigLocation);
|
return IOFactory::getSystemFolder(QStandardPaths::StandardLocation::GenericConfigLocation);
|
||||||
@ -377,9 +437,11 @@ QString Application::userDataAppFolder() const {
|
|||||||
QString Application::userDataFolder() {
|
QString Application::userDataFolder() {
|
||||||
if (settings()->type() == SettingsProperties::SettingsType::Custom) {
|
if (settings()->type() == SettingsProperties::SettingsType::Custom) {
|
||||||
return customDataFolder();
|
return customDataFolder();
|
||||||
} else if (settings()->type() == SettingsProperties::SettingsType::Portable) {
|
}
|
||||||
|
else if (settings()->type() == SettingsProperties::SettingsType::Portable) {
|
||||||
return userDataAppFolder();
|
return userDataAppFolder();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return userDataHomeFolder();
|
return userDataHomeFolder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -421,8 +483,10 @@ QString Application::homeFolder() const {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::backupDatabaseSettings(bool backup_database, bool backup_settings, const QString &target_path,
|
void Application::backupDatabaseSettings(bool backup_database,
|
||||||
const QString &backup_name) {
|
bool backup_settings,
|
||||||
|
const QString& target_path,
|
||||||
|
const QString& backup_name) {
|
||||||
if (!QFileInfo(target_path).isWritable()) {
|
if (!QFileInfo(target_path).isWritable()) {
|
||||||
throw ApplicationException(tr("Output directory is not writable."));
|
throw ApplicationException(tr("Output directory is not writable."));
|
||||||
}
|
}
|
||||||
@ -443,29 +507,31 @@ void Application::backupDatabaseSettings(bool backup_database, bool backup_setti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::restoreDatabaseSettings(bool restore_database, bool restore_settings,
|
void Application::restoreDatabaseSettings(bool restore_database,
|
||||||
const QString &source_database_file_path,
|
bool restore_settings,
|
||||||
const QString &source_settings_file_path) {
|
const QString& source_database_file_path,
|
||||||
|
const QString& source_settings_file_path) {
|
||||||
if (restore_database) {
|
if (restore_database) {
|
||||||
if (!qApp->database()->driver()->initiateRestoration(source_database_file_path)) {
|
if (!qApp->database()->driver()->initiateRestoration(source_database_file_path)) {
|
||||||
throw ApplicationException(
|
throw ApplicationException(tr("Database restoration was not initiated. Make sure that output directory is "
|
||||||
tr("Database restoration was not initiated. Make sure that output directory is writable."));
|
"writable."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restore_settings) {
|
if (restore_settings) {
|
||||||
if (!qApp->settings()->initiateRestoration(source_settings_file_path)) {
|
if (!qApp->settings()->initiateRestoration(source_settings_file_path)) {
|
||||||
throw ApplicationException(
|
throw ApplicationException(tr("Settings restoration was not initiated. Make sure that output directory is "
|
||||||
tr("Settings restoration was not initiated. Make sure that output directory is writable."));
|
"writable."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemTrayIcon *Application::trayIcon() {
|
SystemTrayIcon* Application::trayIcon() {
|
||||||
if (m_trayIcon == nullptr) {
|
if (m_trayIcon == nullptr) {
|
||||||
if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MonochromeTrayIcon)).toBool()) {
|
if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MonochromeTrayIcon)).toBool()) {
|
||||||
m_trayIcon = new SystemTrayIcon(APP_ICON_MONO_PATH, APP_ICON_MONO_PLAIN_PATH, m_mainForm);
|
m_trayIcon = new SystemTrayIcon(APP_ICON_MONO_PATH, APP_ICON_MONO_PLAIN_PATH, m_mainForm);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
m_trayIcon = new SystemTrayIcon(APP_ICON_PATH, APP_ICON_PLAIN_PATH, m_mainForm);
|
m_trayIcon = new SystemTrayIcon(APP_ICON_PATH, APP_ICON_PLAIN_PATH, m_mainForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,7 +546,8 @@ QIcon Application::desktopAwareIcon() const {
|
|||||||
|
|
||||||
if (!from_theme.isNull()) {
|
if (!from_theme.isNull()) {
|
||||||
return from_theme;
|
return from_theme;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return QIcon(APP_ICON_PATH);
|
return QIcon(APP_ICON_PATH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -494,7 +561,8 @@ void Application::showTrayIcon() {
|
|||||||
if (SystemTrayIcon::isSystemTrayAreaAvailable()) {
|
if (SystemTrayIcon::isSystemTrayAreaAvailable()) {
|
||||||
qDebugNN << LOGSEC_GUI << "Tray icon is available, showing now.";
|
qDebugNN << LOGSEC_GUI << "Tray icon is available, showing now.";
|
||||||
trayIcon()->show();
|
trayIcon()->show();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
m_feedReader->feedsModel()->notifyWithCounts();
|
m_feedReader->feedsModel()->notifyWithCounts();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -504,12 +572,14 @@ void Application::showTrayIcon() {
|
|||||||
if (SystemTrayIcon::isSystemTrayAreaAvailable()) {
|
if (SystemTrayIcon::isSystemTrayAreaAvailable()) {
|
||||||
qWarningNN << LOGSEC_GUI << "Tray icon is available, showing now.";
|
qWarningNN << LOGSEC_GUI << "Tray icon is available, showing now.";
|
||||||
trayIcon()->show();
|
trayIcon()->show();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
m_feedReader->feedsModel()->notifyWithCounts();
|
m_feedReader->feedsModel()->notifyWithCounts();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
m_feedReader->feedsModel()->notifyWithCounts();
|
m_feedReader->feedsModel()->notifyWithCounts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,8 +596,11 @@ void Application::deleteTrayIcon() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::showGuiMessage(Notification::Event event, const GuiMessage &msg, const GuiMessageDestination &dest,
|
void Application::showGuiMessage(Notification::Event event,
|
||||||
const GuiAction &action, QWidget *parent) {
|
const GuiMessage& msg,
|
||||||
|
const GuiMessageDestination& dest,
|
||||||
|
const GuiAction& action,
|
||||||
|
QWidget* parent) {
|
||||||
|
|
||||||
if (SystemTrayIcon::areNotificationsEnabled()) {
|
if (SystemTrayIcon::areNotificationsEnabled()) {
|
||||||
auto notification = m_notifications->notificationForEvent(event);
|
auto notification = m_notifications->notificationForEvent(event);
|
||||||
@ -538,36 +611,51 @@ void Application::showGuiMessage(Notification::Event event, const GuiMessage &ms
|
|||||||
notification.balloonEnabled() && dest.m_tray) {
|
notification.balloonEnabled() && dest.m_tray) {
|
||||||
trayIcon()->showMessage(msg.m_title.simplified().isEmpty() ? Notification::nameForEvent(notification.event())
|
trayIcon()->showMessage(msg.m_title.simplified().isEmpty() ? Notification::nameForEvent(notification.event())
|
||||||
: msg.m_title,
|
: msg.m_title,
|
||||||
msg.m_message, msg.m_type, TRAY_ICON_BUBBLE_TIMEOUT, std::move(action.m_action));
|
msg.m_message,
|
||||||
|
msg.m_type,
|
||||||
|
TRAY_ICON_BUBBLE_TIMEOUT,
|
||||||
|
std::move(action.m_action));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dest.m_messageBox || msg.m_type == QSystemTrayIcon::MessageIcon::Critical) {
|
if (dest.m_messageBox || msg.m_type == QSystemTrayIcon::MessageIcon::Critical) {
|
||||||
// Tray icon or OSD is not available, display simple text box.
|
// Tray icon or OSD is not available, display simple text box.
|
||||||
MsgBox::show(parent == nullptr ? mainFormWidget() : parent, QMessageBox::Icon(msg.m_type), msg.m_title,
|
MsgBox::show(parent == nullptr ? mainFormWidget() : parent,
|
||||||
msg.m_message, {}, {}, QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok, {},
|
QMessageBox::Icon(msg.m_type),
|
||||||
action.m_title, action.m_action);
|
msg.m_title,
|
||||||
} else if (dest.m_statusBar && mainForm()->statusBar() != nullptr && mainForm()->statusBar()->isVisible()) {
|
msg.m_message,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
QMessageBox::StandardButton::Ok,
|
||||||
|
QMessageBox::StandardButton::Ok,
|
||||||
|
{},
|
||||||
|
action.m_title,
|
||||||
|
action.m_action);
|
||||||
|
}
|
||||||
|
else if (dest.m_statusBar && mainForm()->statusBar() != nullptr && mainForm()->statusBar()->isVisible()) {
|
||||||
mainForm()->statusBar()->showMessage(msg.m_message);
|
mainForm()->statusBar()->showMessage(msg.m_message);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
qDebugNN << LOGSEC_CORE << "Silencing GUI message:" << QUOTE_W_SPACE_DOT(msg.m_message);
|
qDebugNN << LOGSEC_CORE << "Silencing GUI message:" << QUOTE_W_SPACE_DOT(msg.m_message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WebViewer *Application::createWebView() {
|
WebViewer* Application::createWebView() {
|
||||||
#if !defined(USE_WEBENGINE)
|
#if !defined(USE_WEBENGINE)
|
||||||
return new LiteHtmlViewer();
|
return new LiteHtmlViewer();
|
||||||
#else
|
#else
|
||||||
if (forcedNoWebEngine()) {
|
if (forcedNoWebEngine()) {
|
||||||
return new LiteHtmlViewer();
|
return new TextBrowserViewer();
|
||||||
} else {
|
// return new LiteHtmlViewer();
|
||||||
|
}
|
||||||
|
else {
|
||||||
return new WebEngineViewer();
|
return new WebEngineViewer();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::onCommitData(QSessionManager &manager) {
|
void Application::onCommitData(QSessionManager& manager) {
|
||||||
qDebugNN << LOGSEC_CORE << "OS asked application to commit its data.";
|
qDebugNN << LOGSEC_CORE << "OS asked application to commit its data.";
|
||||||
|
|
||||||
onAboutToQuit();
|
onAboutToQuit();
|
||||||
@ -576,7 +664,7 @@ void Application::onCommitData(QSessionManager &manager) {
|
|||||||
manager.release();
|
manager.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::onSaveState(QSessionManager &manager) {
|
void Application::onSaveState(QSessionManager& manager) {
|
||||||
qDebugNN << LOGSEC_CORE << "OS asked application to save its state.";
|
qDebugNN << LOGSEC_CORE << "OS asked application to save its state.";
|
||||||
|
|
||||||
manager.setRestartHint(QSessionManager::RestartHint::RestartNever);
|
manager.setRestartHint(QSessionManager::RestartHint::RestartNever);
|
||||||
@ -603,7 +691,8 @@ void Application::onAboutToQuit() {
|
|||||||
|
|
||||||
// We locked the lock to exit peacefully, unlock it to avoid warnings.
|
// We locked the lock to exit peacefully, unlock it to avoid warnings.
|
||||||
feedUpdateLock()->unlock();
|
feedUpdateLock()->unlock();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Request for write lock timed-out. This means
|
// Request for write lock timed-out. This means
|
||||||
// that some critical action can be processed right now.
|
// that some critical action can be processed right now.
|
||||||
qWarningNN << LOGSEC_CORE << "Close lock timed-out.";
|
qWarningNN << LOGSEC_CORE << "Close lock timed-out.";
|
||||||
@ -623,7 +712,8 @@ void Application::onAboutToQuit() {
|
|||||||
|
|
||||||
if (QProcess::startDetached(QDir::toNativeSeparators(applicationFilePath()), arguments().mid(1))) {
|
if (QProcess::startDetached(QDir::toNativeSeparators(applicationFilePath()), arguments().mid(1))) {
|
||||||
qDebugNN << LOGSEC_CORE << "New application instance was started.";
|
qDebugNN << LOGSEC_CORE << "New application instance was started.";
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
qCriticalNN << LOGSEC_CORE << "New application instance was not started successfully.";
|
qCriticalNN << LOGSEC_CORE << "New application instance was not started successfully.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -663,9 +753,10 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_
|
|||||||
HICON overlay_hicon = overlay_icon.toHICON();
|
HICON overlay_hicon = overlay_icon.toHICON();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HRESULT overlay_result = m_windowsTaskBar->SetOverlayIcon(
|
HRESULT overlay_result =
|
||||||
reinterpret_cast<HWND>(m_mainForm->winId()),
|
m_windowsTaskBar->SetOverlayIcon(reinterpret_cast<HWND>(m_mainForm->winId()),
|
||||||
(task_bar_count_enabled && unread_messages > 0) ? overlay_hicon : nullptr, nullptr);
|
(task_bar_count_enabled && unread_messages > 0) ? overlay_hicon : nullptr,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
DestroyIcon(overlay_hicon);
|
DestroyIcon(overlay_hicon);
|
||||||
|
|
||||||
@ -690,9 +781,11 @@ QImage Application::generateOverlayIcon(int number) const {
|
|||||||
|
|
||||||
if (number < 1000) {
|
if (number < 1000) {
|
||||||
num_txt = QString::number(number);
|
num_txt = QString::number(number);
|
||||||
} else if (number < 100000) {
|
}
|
||||||
|
else if (number < 100000) {
|
||||||
num_txt = QSL("%1k").arg(int(number / 1000));
|
num_txt = QSL("%1k").arg(int(number / 1000));
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
num_txt = QChar(8734);
|
num_txt = QChar(8734);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,9 +795,11 @@ QImage Application::generateOverlayIcon(int number) const {
|
|||||||
|
|
||||||
if (num_txt.size() == 3) {
|
if (num_txt.size() == 3) {
|
||||||
fon.setPixelSize(img.width() * 0.52);
|
fon.setPixelSize(img.width() * 0.52);
|
||||||
} else if (num_txt.size() == 2) {
|
}
|
||||||
|
else if (num_txt.size() == 2) {
|
||||||
fon.setPixelSize(img.width() * 0.68);
|
fon.setPixelSize(img.width() * 0.68);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
fon.setPixelSize(img.width() * 0.79);
|
fon.setPixelSize(img.width() * 0.79);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,7 +816,8 @@ QImage Application::generateOverlayIcon(int number) const {
|
|||||||
p.setPen(Qt::GlobalColor::black);
|
p.setPen(Qt::GlobalColor::black);
|
||||||
p.drawPath(rounded_rectangle);
|
p.drawPath(rounded_rectangle);
|
||||||
|
|
||||||
p.drawText(img.rect().marginsRemoved(QMargins(0, 0, 0, img.height() * 0.05)), num_txt,
|
p.drawText(img.rect().marginsRemoved(QMargins(0, 0, 0, img.height() * 0.05)),
|
||||||
|
num_txt,
|
||||||
QTextOption(Qt::AlignmentFlag::AlignCenter));
|
QTextOption(Qt::AlignmentFlag::AlignCenter));
|
||||||
p.end();
|
p.end();
|
||||||
|
|
||||||
@ -738,9 +834,9 @@ void Application::restart() {
|
|||||||
#if defined(USE_WEBENGINE)
|
#if defined(USE_WEBENGINE)
|
||||||
|
|
||||||
#if QT_VERSION_MAJOR == 6
|
#if QT_VERSION_MAJOR == 6
|
||||||
void Application::downloadRequested(QWebEngineDownloadRequest *download_item) {
|
void Application::downloadRequested(QWebEngineDownloadRequest* download_item) {
|
||||||
#else
|
#else
|
||||||
void Application::downloadRequested(QWebEngineDownloadItem *download_item) {
|
void Application::downloadRequested(QWebEngineDownloadItem* download_item) {
|
||||||
#endif
|
#endif
|
||||||
downloadManager()->download(download_item->url());
|
downloadManager()->download(download_item->url());
|
||||||
download_item->cancel();
|
download_item->cancel();
|
||||||
@ -760,7 +856,7 @@ void Application::onFeedUpdatesStarted() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::onFeedUpdatesProgress(const Feed *feed, int current, int total) {
|
void Application::onFeedUpdatesProgress(const Feed* feed, int current, int total) {
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
// Use SetOverlayIcon Windows API method on Windows.
|
// Use SetOverlayIcon Windows API method on Windows.
|
||||||
bool task_bar_count_enabled = settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
|
bool task_bar_count_enabled = settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
|
||||||
@ -771,7 +867,7 @@ void Application::onFeedUpdatesProgress(const Feed *feed, int current, int total
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::onFeedUpdatesFinished(const FeedDownloadResults &results) {
|
void Application::onFeedUpdatesFinished(const FeedDownloadResults& results) {
|
||||||
if (!results.updatedFeeds().isEmpty()) {
|
if (!results.updatedFeeds().isEmpty()) {
|
||||||
// Now, inform about results via GUI message/notification.
|
// Now, inform about results via GUI message/notification.
|
||||||
qApp->showGuiMessage(Notification::Event::NewUnreadArticlesFetched,
|
qApp->showGuiMessage(Notification::Event::NewUnreadArticlesFetched,
|
||||||
@ -788,7 +884,7 @@ void Application::onFeedUpdatesFinished(const FeedDownloadResults &results) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setupCustomDataFolder(const QString &data_folder) {
|
void Application::setupCustomDataFolder(const QString& data_folder) {
|
||||||
if (!QDir().mkpath(data_folder)) {
|
if (!QDir().mkpath(data_folder)) {
|
||||||
qCriticalNN << LOGSEC_CORE << "Failed to create custom data path" << QUOTE_W_SPACE(data_folder)
|
qCriticalNN << LOGSEC_CORE << "Failed to create custom data path" << QUOTE_W_SPACE(data_folder)
|
||||||
<< "thus falling back to standard setup.";
|
<< "thus falling back to standard setup.";
|
||||||
@ -822,7 +918,7 @@ void Application::determineFirstRuns() {
|
|||||||
eliminateFirstRuns();
|
eliminateFirstRuns();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::parseCmdArgumentsFromOtherInstance(const QString &message) {
|
void Application::parseCmdArgumentsFromOtherInstance(const QString& message) {
|
||||||
if (message.isEmpty()) {
|
if (message.isEmpty()) {
|
||||||
qDebugNN << LOGSEC_CORE << "No execution message received from other app instances.";
|
qDebugNN << LOGSEC_CORE << "No execution message received from other app instances.";
|
||||||
return;
|
return;
|
||||||
@ -842,9 +938,10 @@ void Application::parseCmdArgumentsFromOtherInstance(const QString &message) {
|
|||||||
|
|
||||||
cmd_parser.addOption(QCommandLineOption({QSL(CLI_QUIT_INSTANCE)}));
|
cmd_parser.addOption(QCommandLineOption({QSL(CLI_QUIT_INSTANCE)}));
|
||||||
cmd_parser.addOption(QCommandLineOption({QSL(CLI_IS_RUNNING)}));
|
cmd_parser.addOption(QCommandLineOption({QSL(CLI_IS_RUNNING)}));
|
||||||
cmd_parser.addPositionalArgument(
|
cmd_parser
|
||||||
QSL("urls"), QSL("List of URL addresses pointing to individual online feeds which should be added."),
|
.addPositionalArgument(QSL("urls"),
|
||||||
QSL("[url-1 ... url-n]"));
|
QSL("List of URL addresses pointing to individual online feeds which should be added."),
|
||||||
|
QSL("[url-1 ... url-n]"));
|
||||||
|
|
||||||
if (!cmd_parser.parse(messages)) {
|
if (!cmd_parser.parse(messages)) {
|
||||||
qCriticalNN << LOGSEC_CORE << cmd_parser.errorText();
|
qCriticalNN << LOGSEC_CORE << cmd_parser.errorText();
|
||||||
@ -853,23 +950,27 @@ void Application::parseCmdArgumentsFromOtherInstance(const QString &message) {
|
|||||||
if (cmd_parser.isSet(QSL(CLI_QUIT_INSTANCE))) {
|
if (cmd_parser.isSet(QSL(CLI_QUIT_INSTANCE))) {
|
||||||
quit();
|
quit();
|
||||||
return;
|
return;
|
||||||
} else if (cmd_parser.isSet(QSL(CLI_IS_RUNNING))) {
|
}
|
||||||
showGuiMessage(Notification::Event::GeneralEvent, {tr("Already running"), tr("Application is already running."),
|
else if (cmd_parser.isSet(QSL(CLI_IS_RUNNING))) {
|
||||||
QSystemTrayIcon::MessageIcon::Information});
|
showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
|
{tr("Already running"),
|
||||||
|
tr("Application is already running."),
|
||||||
|
QSystemTrayIcon::MessageIcon::Information});
|
||||||
mainForm()->display();
|
mainForm()->display();
|
||||||
}
|
}
|
||||||
|
|
||||||
messages = cmd_parser.positionalArguments();
|
messages = cmd_parser.positionalArguments();
|
||||||
|
|
||||||
for (const QString &msg : qAsConst(messages)) {
|
for (const QString& msg : qAsConst(messages)) {
|
||||||
// Application was running, and someone wants to add new feed.
|
// Application was running, and someone wants to add new feed.
|
||||||
ServiceRoot *rt = boolinq::from(feedReader()->feedsModel()->serviceRoots()).firstOrDefault([](ServiceRoot *root) {
|
ServiceRoot* rt = boolinq::from(feedReader()->feedsModel()->serviceRoots()).firstOrDefault([](ServiceRoot* root) {
|
||||||
return root->supportsFeedAdding();
|
return root->supportsFeedAdding();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (rt != nullptr) {
|
if (rt != nullptr) {
|
||||||
rt->addNewFeed(nullptr, msg);
|
rt->addNewFeed(nullptr, msg);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
showGuiMessage(Notification::Event::GeneralEvent,
|
showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
{tr("Cannot add feed"),
|
{tr("Cannot add feed"),
|
||||||
tr("Feed cannot be added because there is no active account which can add feeds."),
|
tr("Feed cannot be added because there is no active account which can add feeds."),
|
||||||
@ -878,15 +979,17 @@ void Application::parseCmdArgumentsFromOtherInstance(const QString &message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::parseCmdArgumentsFromMyInstance(const QStringList &raw_cli_args) {
|
void Application::parseCmdArgumentsFromMyInstance(const QStringList& raw_cli_args) {
|
||||||
QCommandLineOption help({QSL(CLI_HELP_SHORT), QSL(CLI_HELP_LONG)}, QSL("Displays overview of CLI."));
|
QCommandLineOption help({QSL(CLI_HELP_SHORT), QSL(CLI_HELP_LONG)}, QSL("Displays overview of CLI."));
|
||||||
QCommandLineOption version({QSL(CLI_VER_SHORT), QSL(CLI_VER_LONG)}, QSL("Displays version of the application."));
|
QCommandLineOption version({QSL(CLI_VER_SHORT), QSL(CLI_VER_LONG)}, QSL("Displays version of the application."));
|
||||||
QCommandLineOption log_file(
|
QCommandLineOption
|
||||||
{QSL(CLI_LOG_SHORT), QSL(CLI_LOG_LONG)},
|
log_file({QSL(CLI_LOG_SHORT), QSL(CLI_LOG_LONG)},
|
||||||
QSL("Write application debug log to file. Note that logging to file may slow application down."), QSL("log-file"));
|
QSL("Write application debug log to file. Note that logging to file may slow application down."),
|
||||||
QCommandLineOption custom_data_folder(
|
QSL("log-file"));
|
||||||
{QSL(CLI_DAT_SHORT), QSL(CLI_DAT_LONG)},
|
QCommandLineOption
|
||||||
QSL("Use custom folder for user data and disable single instance application mode."), QSL("user-data-folder"));
|
custom_data_folder({QSL(CLI_DAT_SHORT), QSL(CLI_DAT_LONG)},
|
||||||
|
QSL("Use custom folder for user data and disable single instance application mode."),
|
||||||
|
QSL("user-data-folder"));
|
||||||
QCommandLineOption disable_singleinstance({QSL(CLI_SIN_SHORT), QSL(CLI_SIN_LONG)},
|
QCommandLineOption disable_singleinstance({QSL(CLI_SIN_SHORT), QSL(CLI_SIN_LONG)},
|
||||||
QSL("Allow running of multiple application instances."));
|
QSL("Allow running of multiple application instances."));
|
||||||
|
|
||||||
@ -899,7 +1002,8 @@ void Application::parseCmdArgumentsFromMyInstance(const QStringList &raw_cli_arg
|
|||||||
QSL("Disable just \"debug\" output."));
|
QSL("Disable just \"debug\" output."));
|
||||||
QCommandLineOption disable_debug({QSL(CLI_NSTDOUTERR_SHORT), QSL(CLI_NSTDOUTERR_LONG)},
|
QCommandLineOption disable_debug({QSL(CLI_NSTDOUTERR_SHORT), QSL(CLI_NSTDOUTERR_LONG)},
|
||||||
QSL("Completely disable stdout/stderr outputs."));
|
QSL("Completely disable stdout/stderr outputs."));
|
||||||
QCommandLineOption forced_style({QSL(CLI_STYLE_SHORT), QSL(CLI_STYLE_LONG)}, QSL("Force some application style."),
|
QCommandLineOption forced_style({QSL(CLI_STYLE_SHORT), QSL(CLI_STYLE_LONG)},
|
||||||
|
QSL("Force some application style."),
|
||||||
QSL("style-name"));
|
QSL("style-name"));
|
||||||
|
|
||||||
m_cmdParser.addOptions({
|
m_cmdParser.addOptions({
|
||||||
@ -909,9 +1013,10 @@ void Application::parseCmdArgumentsFromMyInstance(const QStringList &raw_cli_arg
|
|||||||
#endif
|
#endif
|
||||||
forced_style
|
forced_style
|
||||||
});
|
});
|
||||||
m_cmdParser.addPositionalArgument(
|
m_cmdParser
|
||||||
QSL("urls"), QSL("List of URL addresses pointing to individual online feeds which should be added."),
|
.addPositionalArgument(QSL("urls"),
|
||||||
QSL("[url-1 ... url-n]"));
|
QSL("List of URL addresses pointing to individual online feeds which should be added."),
|
||||||
|
QSL("[url-1 ... url-n]"));
|
||||||
m_cmdParser.setApplicationDescription(QSL(APP_NAME));
|
m_cmdParser.setApplicationDescription(QSL(APP_NAME));
|
||||||
m_cmdParser.setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode::ParseAsLongOptions);
|
m_cmdParser.setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode::ParseAsLongOptions);
|
||||||
|
|
||||||
@ -940,13 +1045,15 @@ void Application::parseCmdArgumentsFromMyInstance(const QStringList &raw_cli_arg
|
|||||||
<< QUOTE_W_SPACE_DOT(data_folder);
|
<< QUOTE_W_SPACE_DOT(data_folder);
|
||||||
|
|
||||||
setupCustomDataFolder(data_folder);
|
setupCustomDataFolder(data_folder);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
m_allowMultipleInstances = false;
|
m_allowMultipleInstances = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cmdParser.isSet(QSL(CLI_HELP_SHORT))) {
|
if (m_cmdParser.isSet(QSL(CLI_HELP_SHORT))) {
|
||||||
m_cmdParser.showHelp();
|
m_cmdParser.showHelp();
|
||||||
} else if (m_cmdParser.isSet(QSL(CLI_VER_SHORT))) {
|
}
|
||||||
|
else if (m_cmdParser.isSet(QSL(CLI_VER_SHORT))) {
|
||||||
m_cmdParser.showVersion();
|
m_cmdParser.showVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,15 +1076,15 @@ void Application::parseCmdArgumentsFromMyInstance(const QStringList &raw_cli_arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::onNodeJsPackageUpdateError(const QList<NodeJs::PackageMetadata> &pkgs, const QString &error) {
|
void Application::onNodeJsPackageUpdateError(const QList<NodeJs::PackageMetadata>& pkgs, const QString& error) {
|
||||||
qApp->showGuiMessage(
|
qApp->showGuiMessage(Notification::Event::NodePackageFailedToUpdate,
|
||||||
Notification::Event::NodePackageFailedToUpdate,
|
{{},
|
||||||
{{},
|
tr("Packages %1 were NOT updated because of error: %2.")
|
||||||
tr("Packages %1 were NOT updated because of error: %2.").arg(NodeJs::packagesToString(pkgs), error),
|
.arg(NodeJs::packagesToString(pkgs), error),
|
||||||
QSystemTrayIcon::MessageIcon::Critical});
|
QSystemTrayIcon::MessageIcon::Critical});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::onNodeJsPackageInstalled(const QList<NodeJs::PackageMetadata> &pkgs, bool already_up_to_date) {
|
void Application::onNodeJsPackageInstalled(const QList<NodeJs::PackageMetadata>& pkgs, bool already_up_to_date) {
|
||||||
if (!already_up_to_date) {
|
if (!already_up_to_date) {
|
||||||
qApp->showGuiMessage(Notification::Event::NodePackageUpdated,
|
qApp->showGuiMessage(Notification::Event::NodePackageUpdated,
|
||||||
{{},
|
{{},
|
||||||
@ -986,4 +1093,6 @@ void Application::onNodeJsPackageInstalled(const QList<NodeJs::PackageMetadata>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Application::customDataFolder() const { return m_customDataFolder; }
|
QString Application::customDataFolder() const {
|
||||||
|
return m_customDataFolder;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user