Merge branch 'master' of bitbucket.org:skunkos/rssguard
This commit is contained in:
commit
80a5a257f9
@ -341,6 +341,7 @@ set(APP_SOURCES
|
||||
src/gui/dialogs/formdatabasecleanup.cpp
|
||||
src/gui/dialogs/formbackupdatabasesettings.cpp
|
||||
src/gui/dialogs/formrestoredatabasesettings.cpp
|
||||
src/gui/notifications/notification.cpp
|
||||
src/gui/systemtrayicon.cpp
|
||||
src/gui/baselineedit.cpp
|
||||
src/gui/locationlineedit.cpp
|
||||
@ -454,6 +455,7 @@ set(APP_HEADERS
|
||||
src/gui/dialogs/formrestoredatabasesettings.h
|
||||
src/gui/dialogs/formdatabasecleanup.h
|
||||
src/gui/dialogs/formupdate.h
|
||||
src/gui/notifications/notification.h
|
||||
src/gui/systemtrayicon.h
|
||||
src/gui/baselineedit.h
|
||||
src/gui/locationlineedit.h
|
||||
@ -700,6 +702,7 @@ include_directories (
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src/gui
|
||||
${CMAKE_SOURCE_DIR}/src/gui/dialogs
|
||||
${CMAKE_SOURCE_DIR}/src/gui/notifications
|
||||
${CMAKE_SOURCE_DIR}/src/network-web
|
||||
${CMAKE_SOURCE_DIR}/src/network-web/adblock
|
||||
${CMAKE_SOURCE_DIR}/src/dynamic-shortcuts
|
||||
|
@ -82,6 +82,7 @@
|
||||
#define ACCEPT_HEADER_FOR_FEED_DOWNLOADER "application/atom+xml,application/xml;q=0.9,text/xml;q=0.8,*/*;q=0.7"
|
||||
#define MIME_TYPE_ITEM_POINTER "@APP_LOW_NAME@/itempointer"
|
||||
#define DOWNLOADER_ICON_SIZE 48
|
||||
#define NOTIFICATION_ICON_SIZE 64
|
||||
#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"
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "gui/dialogs/formimportexport.h"
|
||||
#include "gui/dialogs/formbackupdatabasesettings.h"
|
||||
#include "gui/dialogs/formrestoredatabasesettings.h"
|
||||
#include "gui/notifications/notification.h"
|
||||
|
||||
#include <QCloseEvent>
|
||||
#include <QSessionManager>
|
||||
@ -78,6 +79,8 @@ FormMain::FormMain(QWidget *parent, Qt::WindowFlags f)
|
||||
|
||||
// Initialize the web factory.
|
||||
WebFactory::instance()->loadState();
|
||||
|
||||
(new Notification())->notify("abcd abcd abcd abcd abcd abcd \naaa\n\n\nabcd abcd abcd abcd abcd", "def def def def def");
|
||||
}
|
||||
|
||||
FormMain::~FormMain() {
|
||||
|
223
src/gui/notifications/notification.cpp
Normal file
223
src/gui/notifications/notification.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
// This file is part of RSS Guard.
|
||||
//
|
||||
// Copyright (C) 2011-2015 by Martin Rotter <rotter.martinos@gmail.com>
|
||||
//
|
||||
// RSS Guard is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// RSS Guard is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "gui/notifications/notification.h"
|
||||
|
||||
#include "gui/messagebox.h"
|
||||
#include "definitions/definitions.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
|
||||
Notification::Notification() : QWidget(0), m_title(QString()), m_text(QString()), m_icon(QPixmap()), m_screen(-1),
|
||||
m_width(-1), m_height(-1), m_padding(5), m_widgetMargin(2 * m_padding) {
|
||||
setupWidget();
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
Notification::~Notification() {
|
||||
}
|
||||
|
||||
void Notification::notify(const QString &text, const QString &title, const QIcon &icon) {
|
||||
hide();
|
||||
|
||||
// Set new values.
|
||||
m_text = text;
|
||||
m_title = title;
|
||||
m_icon = icon.pixmap(NOTIFICATION_ICON_SIZE, NOTIFICATION_ICON_SIZE);
|
||||
|
||||
// Show it.
|
||||
updateGeometries();
|
||||
repaint();
|
||||
show();
|
||||
}
|
||||
|
||||
void Notification::notify(const QString &text, const QString &title, QSystemTrayIcon::MessageIcon icon) {
|
||||
notify(text, title, MessageBox::iconForStatus((QMessageBox::Icon) icon));
|
||||
}
|
||||
|
||||
void Notification::updateGeometries() {
|
||||
// Calculate width and height of notification with given icon and text.
|
||||
m_width = m_padding +
|
||||
m_icon.width() + m_padding + /* contents */ qMax(stringWidth(m_title), stringWidth(m_text)) +
|
||||
m_padding;
|
||||
m_height = m_padding +
|
||||
/* contents */
|
||||
qMax(m_icon.height(),
|
||||
stringHeight(m_title) + m_padding + stringHeight(m_text)) +
|
||||
m_padding;
|
||||
|
||||
// Calculate real position.
|
||||
int x, y;
|
||||
QRect screen_geometry = QApplication::desktop()->availableGeometry(m_screen);
|
||||
|
||||
switch (m_position) {
|
||||
case Qt::BottomLeftCorner:
|
||||
x = m_widgetMargin;
|
||||
y = screen_geometry.height() - m_widgetMargin - m_height;
|
||||
break;
|
||||
|
||||
case Qt::TopLeftCorner:
|
||||
x = m_widgetMargin;
|
||||
y = m_widgetMargin;
|
||||
break;
|
||||
|
||||
case Qt::TopRightCorner:
|
||||
x = screen_geometry.width() - m_widgetMargin - m_width;
|
||||
y = m_widgetMargin;
|
||||
break;
|
||||
|
||||
case Qt::BottomRightCorner:
|
||||
default:
|
||||
x = screen_geometry.width() - m_widgetMargin - m_width;
|
||||
y = screen_geometry.height() - m_widgetMargin - m_height;
|
||||
break;
|
||||
}
|
||||
|
||||
setGeometry(x, y, m_width, m_height);
|
||||
}
|
||||
|
||||
void Notification::paintEvent(QPaintEvent *event) {
|
||||
Q_UNUSED(event)
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setFont(font());
|
||||
|
||||
if (!underMouse()) {
|
||||
painter.setOpacity(0.7);
|
||||
}
|
||||
else {
|
||||
painter.setOpacity(0.95);
|
||||
}
|
||||
|
||||
// Draw background.
|
||||
painter.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::Qt4CompatiblePainting);
|
||||
painter.setBrush(QColor(220, 220, 220));
|
||||
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawRoundedRect(0, 0, width(), height(), 5.0, 5.0);
|
||||
|
||||
// Draw icon.
|
||||
painter.drawPixmap(m_padding, m_padding, m_icon);
|
||||
|
||||
// Draw text.
|
||||
painter.setPen(Qt::black);
|
||||
|
||||
// Needed heighs/widths.
|
||||
int title_height = stringHeight(m_title);
|
||||
int remaining_width = width() - m_padding - m_icon.width() - m_padding /* - here comes contents */ - m_padding;
|
||||
int remaining_height = height() - m_padding - title_height - m_padding /* - here comes contents */ - m_padding;
|
||||
|
||||
painter.drawText(m_padding + m_icon.width() + m_padding, m_padding + title_height + m_padding,
|
||||
remaining_width, remaining_height,
|
||||
Qt::AlignLeft, m_text);
|
||||
|
||||
// Draw heading.
|
||||
QFont font = painter.font();
|
||||
font.setBold(true);
|
||||
painter.setFont(font);
|
||||
|
||||
painter.drawText(m_padding + m_icon.width() + m_padding, m_padding,
|
||||
remaining_width, remaining_height,
|
||||
Qt::AlignHCenter | Qt::AlignTop, m_title);
|
||||
}
|
||||
|
||||
void Notification::mousePressEvent(QMouseEvent *event) {
|
||||
QWidget::mousePressEvent(event);
|
||||
QTimer::singleShot(0, this, SLOT(hide()));
|
||||
}
|
||||
|
||||
void Notification::enterEvent(QEvent *event) {
|
||||
QWidget::enterEvent(event);
|
||||
repaint();
|
||||
}
|
||||
|
||||
void Notification::leaveEvent(QEvent *event) {
|
||||
QWidget::leaveEvent(event);
|
||||
repaint();
|
||||
}
|
||||
|
||||
int Notification::stringHeight(const QString &string) {
|
||||
int count_lines = string.split(QL1C('\n')).size();
|
||||
return fontMetrics().height() * count_lines;
|
||||
}
|
||||
|
||||
int Notification::stringWidth(const QString &string) {
|
||||
QStringList lines = string.split(QL1C('\n'));
|
||||
int width = 0;
|
||||
|
||||
foreach (const QString &line, lines) {
|
||||
int line_width = fontMetrics().width(line);
|
||||
|
||||
if (line_width > width) {
|
||||
width = line_width;
|
||||
}
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
void Notification::loadSettings() {
|
||||
// TODO: načist z nastaveni.
|
||||
m_position = Qt::BottomRightCorner;
|
||||
}
|
||||
|
||||
void Notification::setupWidget() {
|
||||
// Set window flags.
|
||||
Qt::WindowFlags window_flags = Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
|
||||
Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint |
|
||||
Qt::WindowDoesNotAcceptFocus;
|
||||
|
||||
#if defined (Q_OS_MAC)
|
||||
window_flags |= Qt::SubWindow;
|
||||
#else
|
||||
window_flags |= Qt::Tool;
|
||||
#endif
|
||||
|
||||
setWindowFlags(window_flags);
|
||||
|
||||
// Set widget attributes.
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
setAttribute(Qt::WA_X11DoNotAcceptFocus);
|
||||
setAttribute(Qt::WA_ShowWithoutActivating);
|
||||
|
||||
#if defined (Q_OS_MAC)
|
||||
winId();
|
||||
|
||||
int setAttr[] = {kHIWindowBitDoesNotHide, kHIWindowBitDoesNotCycle, kHIWindowBitNoShadow, 0};
|
||||
int clearAttr[] = {0};
|
||||
HIWindowChangeAttributes(qt_mac_window_for(this), setAttr, clearAttr);
|
||||
#endif
|
||||
|
||||
// Window will be meant to be on top, but should not steal focus.
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
// TODO: pokracovat
|
||||
// https://github.com/binaryking/QNotify/blob/master/QNotify.cpp
|
||||
// http://stackoverflow.com/questions/5823700/notification-window-in-mac-with-or-without-qt
|
||||
// quiterss
|
||||
// a odkazy z issue
|
||||
// promyslet esli tam dat jen ciste label a ikonu, nebo i seznam nejnovesich zprav atp.
|
||||
}
|
67
src/gui/notifications/notification.h
Normal file
67
src/gui/notifications/notification.h
Normal file
@ -0,0 +1,67 @@
|
||||
// This file is part of RSS Guard.
|
||||
//
|
||||
// Copyright (C) 2011-2015 by Martin Rotter <rotter.martinos@gmail.com>
|
||||
//
|
||||
// RSS Guard is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// RSS Guard is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef NOTIFICATION_H
|
||||
#define NOTIFICATION_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
|
||||
class Notification : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// Constructors.
|
||||
explicit Notification();
|
||||
virtual ~Notification();
|
||||
|
||||
public slots:
|
||||
void notify(const QString &text, const QString &title, const QIcon &icon);
|
||||
void notify(const QString &text, const QString &title, QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::Information);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void enterEvent(QEvent *event);
|
||||
void leaveEvent(QEvent *event);
|
||||
|
||||
private:
|
||||
int stringHeight(const QString &string);
|
||||
int stringWidth(const QString &string);
|
||||
|
||||
void loadSettings();
|
||||
void setupWidget();
|
||||
void updateGeometries();
|
||||
|
||||
QString m_title;
|
||||
QString m_text;
|
||||
QPixmap m_icon;
|
||||
|
||||
// Defaults to -1, which means "default" (primary) screen.
|
||||
int m_screen;
|
||||
Qt::Corner m_position;
|
||||
|
||||
// Is calculated according to contents.
|
||||
int m_width;
|
||||
int m_height;
|
||||
int m_padding;
|
||||
int m_widgetMargin;
|
||||
};
|
||||
|
||||
#endif // NOTIFICATION_H
|
@ -35,8 +35,7 @@ TrayIconMenu::~TrayIconMenu() {
|
||||
}
|
||||
|
||||
bool TrayIconMenu::event(QEvent *event) {
|
||||
if (Application::activeModalWidget() != NULL &&
|
||||
event->type() == QEvent::Show) {
|
||||
if (Application::activeModalWidget() != NULL && event->type() == QEvent::Show) {
|
||||
QTimer::singleShot(0, this, SLOT(hide()));
|
||||
qApp->trayIcon()->showMessage(QSL(APP_LONG_NAME),
|
||||
tr("Close opened modal dialogs first."),
|
||||
@ -46,9 +45,7 @@ bool TrayIconMenu::event(QEvent *event) {
|
||||
}
|
||||
#endif
|
||||
|
||||
SystemTrayIcon::SystemTrayIcon(const QString &normal_icon,
|
||||
const QString &plain_icon,
|
||||
FormMain *parent)
|
||||
SystemTrayIcon::SystemTrayIcon(const QString &normal_icon, const QString &plain_icon, FormMain *parent)
|
||||
: QSystemTrayIcon(parent),
|
||||
m_normalIcon(normal_icon),
|
||||
m_plainPixmap(plain_icon),
|
||||
@ -116,7 +113,7 @@ void SystemTrayIcon::show() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void SystemTrayIcon::setNumber(int number, bool any_unread_message) {
|
||||
void SystemTrayIcon::setNumber(int number, bool any_new_message) {
|
||||
if (number <= 0) {
|
||||
setToolTip(QSL(APP_LONG_NAME));
|
||||
QSystemTrayIcon::setIcon(QIcon(m_normalIcon));
|
||||
@ -129,7 +126,7 @@ void SystemTrayIcon::setNumber(int number, bool any_unread_message) {
|
||||
|
||||
// TODO: Here draw different background instead of different color of number.
|
||||
tray_painter.begin(&background);
|
||||
tray_painter.setPen(any_unread_message ? Qt::blue : Qt::black);
|
||||
tray_painter.setPen(any_new_message ? Qt::blue : Qt::black);
|
||||
tray_painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
tray_painter.setRenderHint(QPainter::TextAntialiasing, true);
|
||||
|
||||
@ -137,7 +134,6 @@ void SystemTrayIcon::setNumber(int number, bool any_unread_message) {
|
||||
// infinity symbol in that case.
|
||||
if (number > 999) {
|
||||
m_font.setPixelSize(100);
|
||||
|
||||
tray_painter.setFont(m_font);
|
||||
tray_painter.drawText(QRect(0, 0, 128, 128), Qt::AlignVCenter | Qt::AlignCenter, QChar(8734));
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ class SystemTrayIcon : public QSystemTrayIcon {
|
||||
virtual ~SystemTrayIcon();
|
||||
|
||||
// Sets the number to be visible in the tray icon, number <= 0 removes it.
|
||||
void setNumber(int number = -1, bool any_unread_message = false);
|
||||
void setNumber(int number = -1, bool any_new_message = false);
|
||||
|
||||
void showMessage(const QString &title, const QString &message, MessageIcon icon = Information,
|
||||
int milliseconds_timeout_hint = TRAY_ICON_BUBBLE_TIMEOUT, QObject *click_target = NULL,
|
||||
|
@ -26,19 +26,19 @@
|
||||
#include "gui/statusbar.h"
|
||||
#include "gui/dialogs/formmain.h"
|
||||
#include "exceptions/applicationexception.h"
|
||||
#include "adblock/adblockmanager.h"
|
||||
|
||||
#include <QSessionManager>
|
||||
#include <QThread>
|
||||
#include <QProcess>
|
||||
|
||||
#include <adblock/adblockmanager.h>
|
||||
|
||||
|
||||
Application::Application(const QString &id, int &argc, char **argv)
|
||||
: QtSingleApplication(id, argc, argv),
|
||||
m_updateFeedsLock(NULL), m_userActions(QList<QAction*>()), m_mainForm(NULL),
|
||||
m_trayIcon(NULL), m_settings(NULL), m_system(NULL), m_skins(NULL),
|
||||
m_localization(NULL), m_icons(NULL), m_database(NULL), m_downloadManager(NULL), m_shouldRestart(false) {
|
||||
m_localization(NULL), m_icons(NULL), m_database(NULL), m_downloadManager(NULL), m_shouldRestart(false),
|
||||
m_notification(NULL) {
|
||||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(onAboutToQuit()));
|
||||
connect(this, SIGNAL(commitDataRequest(QSessionManager&)), this, SLOT(onCommitData(QSessionManager&)));
|
||||
connect(this, SIGNAL(saveStateRequest(QSessionManager&)), this, SLOT(onSaveState(QSessionManager&)));
|
||||
@ -84,7 +84,7 @@ Mutex *Application::feedUpdateLock() {
|
||||
}
|
||||
|
||||
void Application::backupDatabaseSettings(bool backup_database, bool backup_settings,
|
||||
const QString &target_path, const QString &backup_name) {
|
||||
const QString &target_path, const QString &backup_name) {
|
||||
if (!QFileInfo(target_path).isWritable()) {
|
||||
throw ApplicationException(tr("Output directory is not writable."));
|
||||
}
|
||||
@ -168,15 +168,18 @@ void Application::deleteTrayIcon() {
|
||||
}
|
||||
}
|
||||
|
||||
void Application::showGuiMessage(const QString& title, const QString& message,
|
||||
void Application::showGuiMessage(const QString &title, const QString &message,
|
||||
QSystemTrayIcon::MessageIcon message_type,
|
||||
QWidget *parent, int duration) {
|
||||
if (SystemTrayIcon::isSystemTrayActivated()) {
|
||||
// TODO: Maybe show OSD instead if tray icon bubble, depending on settings.
|
||||
/*if (true) {
|
||||
// Show OSD instead if tray icon bubble, depending on settings.
|
||||
notification()->notify(message, title, message_type);
|
||||
}
|
||||
else */if (SystemTrayIcon::isSystemTrayActivated()) {
|
||||
trayIcon()->showMessage(title, message, message_type, duration);
|
||||
}
|
||||
else {
|
||||
// TODO: Tray icon or OSD is not available, display simple text box.
|
||||
// Tray icon or OSD is not available, display simple text box.
|
||||
MessageBox::show(parent, (QMessageBox::Icon) message_type, title, message);
|
||||
}
|
||||
}
|
||||
@ -225,6 +228,11 @@ void Application::onAboutToQuit() {
|
||||
qDebug("Close lock timed-out.");
|
||||
}
|
||||
|
||||
if (m_notification != NULL) {
|
||||
m_notification->deleteLater();
|
||||
m_notification = NULL;
|
||||
}
|
||||
|
||||
// Now, we can check if application should just quit or restart itself.
|
||||
if (m_shouldRestart) {
|
||||
finish();
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/iofactory.h"
|
||||
#include "gui/systemtrayicon.h"
|
||||
#include "gui/notifications/notification.h"
|
||||
#include "network-web/downloadmanager.h"
|
||||
|
||||
#include <QList>
|
||||
@ -63,6 +64,14 @@ class Application : public QtSingleApplication {
|
||||
return m_system;
|
||||
}
|
||||
|
||||
inline Notification *notification() {
|
||||
if (m_notification == NULL) {
|
||||
m_notification = new Notification();
|
||||
}
|
||||
|
||||
return m_notification;
|
||||
}
|
||||
|
||||
inline SkinFactory *skins() {
|
||||
if (m_skins == NULL) {
|
||||
m_skins = new SkinFactory(this);
|
||||
@ -184,6 +193,7 @@ class Application : public QtSingleApplication {
|
||||
DatabaseFactory *m_database;
|
||||
DownloadManager *m_downloadManager;
|
||||
bool m_shouldRestart;
|
||||
Notification *m_notification;
|
||||
};
|
||||
|
||||
#endif // APPLICATION_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user