save work
This commit is contained in:
parent
7e489dcbb9
commit
1cfcc0b952
@ -61,8 +61,8 @@
|
||||
|
||||
#define RELEASES_LIST "https://api.github.com/repos/martinrotter/rssguard/releases"
|
||||
#define MSG_FILTERING_HELP APP_URL_DOCUMENTATION "#fltr"
|
||||
#define URL_REGEXP \
|
||||
"^(http|https|feed|ftp):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/" \
|
||||
#define URL_REGEXP \
|
||||
"^(http|https|feed|ftp):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/" \
|
||||
"~\\+#])?$"
|
||||
#define SCRIPT_SOURCE_TYPE_REGEXP "^.+#.*$"
|
||||
#define TEXT_TITLE_LIMIT 30
|
||||
@ -99,6 +99,8 @@
|
||||
#define DEFAULT_NOTIFICATION_VOLUME 50
|
||||
#define MAX_THREADPOOL_THREADS 32
|
||||
#define WEB_BROWSER_SCROLL_STEP 50.0
|
||||
#define NOTIFICATIONS_MARGIN 16
|
||||
#define NOTIFICATIONS_WIDTH 256
|
||||
|
||||
#define GOOGLE_SEARCH_URL "https://www.google.com/search?q=%1&ie=utf-8&oe=utf-8"
|
||||
#define GOOGLE_SUGGEST_URL "http://suggestqueries.google.com/complete/search?output=toolbar&hl=en&q=%1"
|
||||
@ -178,13 +180,13 @@
|
||||
#define ZOOM_FACTOR_STEP 0.05f
|
||||
|
||||
#if defined(USE_WEBENGINE)
|
||||
#define HTTP_COMPLETE_USERAGENT \
|
||||
(qApp->web()->engineProfile()->httpUserAgent().toLocal8Bit() + QByteArrayLiteral(" ") + \
|
||||
#define HTTP_COMPLETE_USERAGENT \
|
||||
(qApp->web()->engineProfile()->httpUserAgent().toLocal8Bit() + QByteArrayLiteral(" ") + \
|
||||
QByteArrayLiteral(APP_USERAGENT))
|
||||
#else
|
||||
#define HTTP_COMPLETE_USERAGENT \
|
||||
(QByteArrayLiteral("Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " \
|
||||
"QtWebEngine/5.15.2 Chrome/83.0.4103.122 Safari/537.36 ") + \
|
||||
#define HTTP_COMPLETE_USERAGENT \
|
||||
(QByteArrayLiteral("Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " \
|
||||
"QtWebEngine/5.15.2 Chrome/83.0.4103.122 Safari/537.36 ") + \
|
||||
QByteArrayLiteral(APP_USERAGENT))
|
||||
#endif
|
||||
|
||||
|
@ -1090,7 +1090,18 @@ void FormMain::showAddAccountDialog() {
|
||||
}
|
||||
|
||||
void FormMain::reportABug() {
|
||||
qApp->web()->openUrlInExternalBrowser(QSL(APP_URL_ISSUES_NEW));
|
||||
qApp
|
||||
->showGuiMessage(Notification::Event::GeneralEvent,
|
||||
GuiMessage(QDateTime::currentDateTime().toString(),
|
||||
"Quisque ullamcorper ut purus nec tempus. Vivamus eros dolor, sagittis ultrices augue "
|
||||
"ut, posuere fringilla lorem. Donec posuere, enim sit amet fermentum dignissim, tellus "
|
||||
"lectus laoreet lectus, vestibulum laoreet felis tortor eget nunc. Curabitur sagittis "
|
||||
"quam in scelerisque placerat. Vivamus vel porta tortor. Vivamus nec volutpat sem",
|
||||
QSystemTrayIcon::MessageIcon::Information),
|
||||
GuiMessageDestination(),
|
||||
GuiAction("test", []() {}));
|
||||
|
||||
// qApp->web()->openUrlInExternalBrowser(QSL(APP_URL_ISSUES_NEW));
|
||||
}
|
||||
|
||||
void FormMain::donate() {
|
||||
|
@ -4,9 +4,12 @@
|
||||
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
|
||||
#include <QCloseEvent>
|
||||
|
||||
BaseToastNotification::BaseToastNotification(QWidget* parent) : QDialog(parent) {
|
||||
setAttribute(Qt::WidgetAttribute::WA_ShowWithoutActivating);
|
||||
setAttribute(Qt::WidgetAttribute::WA_TranslucentBackground);
|
||||
setFixedWidth(NOTIFICATIONS_WIDTH);
|
||||
setFocusPolicy(Qt::FocusPolicy::NoFocus);
|
||||
|
||||
setWindowFlags(
|
||||
#ifdef Q_OS_MAC
|
||||
@ -15,10 +18,27 @@ BaseToastNotification::BaseToastNotification(QWidget* parent) : QDialog(parent)
|
||||
Qt::WindowType::Tool |
|
||||
#endif
|
||||
Qt::WindowType::FramelessWindowHint | Qt::WindowType::WindowStaysOnTopHint | Qt::WindowType::WindowSystemMenuHint);
|
||||
|
||||
installEventFilter(this);
|
||||
}
|
||||
|
||||
BaseToastNotification::~BaseToastNotification() {}
|
||||
|
||||
void BaseToastNotification::setupCloseButton(QAbstractButton* btn) {
|
||||
btn->setIcon(qApp->icons()->fromTheme(QSL("dialog-close"), QSL("gtk-close")));
|
||||
|
||||
connect(btn, &QAbstractButton::clicked, this, &BaseToastNotification::closeRequested);
|
||||
}
|
||||
|
||||
bool BaseToastNotification::eventFilter(QObject* watched, QEvent* event) {
|
||||
if (event->type() == QEvent::Type::KeyPress) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return QDialog::eventFilter(watched, event);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseToastNotification::closeEvent(QCloseEvent* event) {
|
||||
event->ignore();
|
||||
}
|
||||
|
@ -14,8 +14,17 @@ class BaseToastNotification : public QDialog {
|
||||
explicit BaseToastNotification(QWidget* parent = nullptr);
|
||||
virtual ~BaseToastNotification();
|
||||
|
||||
// If true, then notification is always moved as close to top as possible.
|
||||
virtual bool alwaysOnTop() const = 0;
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject* watched, QEvent* event);
|
||||
virtual void closeEvent(QCloseEvent* event);
|
||||
|
||||
void setupCloseButton(QAbstractButton* btn);
|
||||
|
||||
signals:
|
||||
void closeRequested();
|
||||
};
|
||||
|
||||
#endif // BASETOASTNOTIFICATION_H
|
||||
|
@ -19,6 +19,10 @@ ToastNotification::ToastNotification(Notification::Event event,
|
||||
loadNotification(event, msg, action);
|
||||
}
|
||||
|
||||
bool ToastNotification::alwaysOnTop() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ToastNotification::loadNotification(Notification::Event event, const GuiMessage& msg, const GuiAction& action) {
|
||||
m_ui.m_lblTitle->setText(msg.m_title);
|
||||
m_ui.m_lblBody->setText(msg.m_message);
|
||||
|
@ -18,6 +18,8 @@ class ToastNotification : public BaseToastNotification {
|
||||
const GuiAction& action,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
virtual bool alwaysOnTop() const;
|
||||
|
||||
private:
|
||||
void loadNotification(Notification::Event event, const GuiMessage& msg, const GuiAction& action);
|
||||
|
||||
|
@ -2,8 +2,14 @@
|
||||
|
||||
#include "gui/notifications/toastnotificationsmanager.h"
|
||||
|
||||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "gui/notifications/basetoastnotification.h"
|
||||
#include "gui/notifications/toastnotification.h"
|
||||
|
||||
#include <QRect>
|
||||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
|
||||
ToastNotificationsManager::ToastNotificationsManager(QObject* parent)
|
||||
: QObject(parent), m_position(NotificationPosition::BottomRight), m_screen(-1) {}
|
||||
|
||||
@ -43,17 +49,115 @@ void ToastNotificationsManager::clear() {
|
||||
void ToastNotificationsManager::showNotification(Notification::Event event,
|
||||
const GuiMessage& msg,
|
||||
const GuiAction& action) {
|
||||
// Remove top existing notifications as long as their combined height with height of this
|
||||
// new notification extends.
|
||||
|
||||
ToastNotification* notif = new ToastNotification(event, msg, action, qApp->mainFormWidget());
|
||||
|
||||
auto aa = notif->height();
|
||||
auto* screen = moveToProperScreen(notif);
|
||||
|
||||
// Insert new notification into free space.
|
||||
notif->show();
|
||||
|
||||
auto bb = notif->height();
|
||||
auto cc = notif->height();
|
||||
auto notif_new_pos = cornerForNewNotification(screen->availableGeometry());
|
||||
|
||||
moveNotificationToCorner(notif, notif_new_pos);
|
||||
|
||||
notif->move(notif_new_pos);
|
||||
|
||||
// Make sure notification is finally resized.
|
||||
notif->adjustSize();
|
||||
qApp->processEvents();
|
||||
|
||||
// Remove out-of-bounds old notifications and shift existing
|
||||
// ones to make space for new notifications.
|
||||
removeOutOfBoundsNotifications(notif->height());
|
||||
makeSpaceForNotification(notif->height());
|
||||
|
||||
m_activeNotifications.prepend(notif);
|
||||
}
|
||||
|
||||
void ToastNotificationsManager::showNotification(const QList<Message>& new_messages) {}
|
||||
|
||||
QScreen* ToastNotificationsManager::activeScreen() const {
|
||||
if (m_screen >= 0) {
|
||||
auto all_screens = QGuiApplication::screens();
|
||||
|
||||
if (m_screen < all_screens.size()) {
|
||||
return all_screens.at(m_screen);
|
||||
}
|
||||
}
|
||||
|
||||
return QGuiApplication::primaryScreen();
|
||||
}
|
||||
|
||||
QPoint ToastNotificationsManager::cornerForNewNotification(QRect rect) {
|
||||
switch (m_position) {
|
||||
case ToastNotificationsManager::TopLeft:
|
||||
return rect.topLeft() + QPoint(NOTIFICATIONS_MARGIN, NOTIFICATIONS_MARGIN);
|
||||
|
||||
case ToastNotificationsManager::TopRight:
|
||||
return rect.topRight() - QPoint(NOTIFICATIONS_WIDTH + NOTIFICATIONS_MARGIN, -NOTIFICATIONS_MARGIN);
|
||||
|
||||
case ToastNotificationsManager::BottomLeft:
|
||||
return rect.bottomLeft() - QPoint(-NOTIFICATIONS_MARGIN, NOTIFICATIONS_MARGIN);
|
||||
|
||||
case ToastNotificationsManager::BottomRight:
|
||||
return rect.bottomRight() - QPoint(NOTIFICATIONS_MARGIN, NOTIFICATIONS_MARGIN);
|
||||
}
|
||||
}
|
||||
|
||||
void ToastNotificationsManager::moveNotificationToCorner(BaseToastNotification* notif, const QPoint& corner) {
|
||||
switch (m_position) {
|
||||
case ToastNotificationsManager::TopLeft:
|
||||
notif->move(corner);
|
||||
break;
|
||||
|
||||
case ToastNotificationsManager::TopRight:
|
||||
notif->move(corner);
|
||||
break;
|
||||
|
||||
case ToastNotificationsManager::BottomLeft:
|
||||
notif->move(corner);
|
||||
break;
|
||||
|
||||
case ToastNotificationsManager::BottomRight:
|
||||
notif->move(corner);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ToastNotificationsManager::makeSpaceForNotification(int height_to_make_space) {
|
||||
for (BaseToastNotification* notif : m_activeNotifications) {
|
||||
notif->move(notif->pos().x(), notif->pos().y() + height_to_make_space + NOTIFICATIONS_MARGIN);
|
||||
}
|
||||
}
|
||||
|
||||
void ToastNotificationsManager::removeOutOfBoundsNotifications(int height_to_reserve) {
|
||||
auto* screen = activeScreen();
|
||||
|
||||
int available_height = screen->availableSize().height();
|
||||
|
||||
while (boolinq::from(m_activeNotifications).sum([](BaseToastNotification* notif) {
|
||||
return notif->height() + NOTIFICATIONS_MARGIN;
|
||||
}) + height_to_reserve >
|
||||
available_height) {
|
||||
if (!m_activeNotifications.isEmpty()) {
|
||||
m_activeNotifications.takeLast()->deleteLater();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QScreen* ToastNotificationsManager::moveToProperScreen(BaseToastNotification* notif) {
|
||||
if (m_screen >= 0) {
|
||||
auto all_screens = QGuiApplication::screens();
|
||||
|
||||
if (m_screen < all_screens.size()) {
|
||||
notif->windowHandle()->setScreen(all_screens.at(m_screen));
|
||||
|
||||
return all_screens.at(m_screen);
|
||||
}
|
||||
}
|
||||
|
||||
return QGuiApplication::primaryScreen();
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
class BaseToastNotification;
|
||||
class ToastNotification;
|
||||
class QScreen;
|
||||
|
||||
class ToastNotificationsManager : public QObject {
|
||||
Q_OBJECT
|
||||
@ -39,9 +40,20 @@ class ToastNotificationsManager : public QObject {
|
||||
void showNotification(Notification::Event event, const GuiMessage& msg, const GuiAction& action);
|
||||
void showNotification(const QList<Message>& new_messages);
|
||||
|
||||
private:
|
||||
QScreen* activeScreen() const;
|
||||
QPoint cornerForNewNotification(QRect rect);
|
||||
void moveNotificationToCorner(BaseToastNotification* notif, const QPoint& corner);
|
||||
void makeSpaceForNotification(int height_to_make_space);
|
||||
void removeOutOfBoundsNotifications(int height_to_reserve);
|
||||
QScreen* moveToProperScreen(BaseToastNotification* notif);
|
||||
|
||||
private:
|
||||
NotificationPosition m_position;
|
||||
int m_screen;
|
||||
|
||||
// List of all displayed notifications, newest notifications are in the beginning of the list
|
||||
// and oldest at the end.
|
||||
QList<BaseToastNotification*> m_activeNotifications;
|
||||
};
|
||||
|
||||
|
@ -177,9 +177,11 @@ Application::Application(const QString& id, int& argc, char** argv, const QStrin
|
||||
#if defined(USE_WEBENGINE)
|
||||
m_webFactory->urlIinterceptor()->load();
|
||||
|
||||
m_webFactory->engineProfile()->setCachePath(cacheFolder() + QDir::separator() + QSL("web") + QDir::separator() + QSL("cache"));
|
||||
m_webFactory->engineProfile()->setCachePath(cacheFolder() + QDir::separator() + QSL("web") + QDir::separator() +
|
||||
QSL("cache"));
|
||||
m_webFactory->engineProfile()->setHttpCacheType(QWebEngineProfile::HttpCacheType::DiskHttpCache);
|
||||
m_webFactory->engineProfile()->setPersistentStoragePath(userDataFolder() + QDir::separator() + QSL("web") + QDir::separator() + QSL("storage"));
|
||||
m_webFactory->engineProfile()->setPersistentStoragePath(userDataFolder() + QDir::separator() + QSL("web") +
|
||||
QDir::separator() + QSL("storage"));
|
||||
|
||||
m_webFactory->loadCustomCss(userDataFolder() + QDir::separator() + QSL("web") + QDir::separator() +
|
||||
QSL("user-styles.css"));
|
||||
@ -833,7 +835,10 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_
|
||||
m_trayIcon->setNumber(unread_messages, any_feed_has_new_unread_messages);
|
||||
}
|
||||
|
||||
// Set task bar overlay with number of unread articles.
|
||||
// Use Qt function to set "badge" number directly in some cases.
|
||||
#if defined(Q_OS_MACOS) && QT_VERSION >= 0x060500 // Qt >= 6.5.0
|
||||
qApp->setBadgeNumber(unread_messages);
|
||||
#else
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
// Use D-Bus "LauncherEntry" service on Linux.
|
||||
bool task_bar_count_enabled = settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
|
||||
@ -882,6 +887,7 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_
|
||||
else {
|
||||
qCriticalNN << LOGSEC_GUI << "Main form not set for setting numbers.";
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (m_mainForm != nullptr) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user