Merge branch 'master' of bitbucket.org:skunkos/rssguard

This commit is contained in:
Martin Rotter 2015-06-29 16:48:28 +02:00
commit 80a5a257f9
9 changed files with 328 additions and 17 deletions

View File

@ -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

View File

@ -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"

View File

@ -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() {

View 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.
}

View 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

View File

@ -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));
}

View File

@ -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,

View File

@ -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();

View File

@ -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