Initial notification implementation.

This commit is contained in:
Martin Rotter 2015-06-29 08:46:00 +02:00
parent 4ffab88435
commit bdcd47a946
4 changed files with 307 additions and 0 deletions

View File

@ -341,6 +341,7 @@ set(APP_SOURCES
src/gui/dialogs/formdatabasecleanup.cpp src/gui/dialogs/formdatabasecleanup.cpp
src/gui/dialogs/formbackupdatabasesettings.cpp src/gui/dialogs/formbackupdatabasesettings.cpp
src/gui/dialogs/formrestoredatabasesettings.cpp src/gui/dialogs/formrestoredatabasesettings.cpp
src/gui/notifications/notification.cpp
src/gui/systemtrayicon.cpp src/gui/systemtrayicon.cpp
src/gui/baselineedit.cpp src/gui/baselineedit.cpp
src/gui/locationlineedit.cpp src/gui/locationlineedit.cpp
@ -454,6 +455,7 @@ set(APP_HEADERS
src/gui/dialogs/formrestoredatabasesettings.h src/gui/dialogs/formrestoredatabasesettings.h
src/gui/dialogs/formdatabasecleanup.h src/gui/dialogs/formdatabasecleanup.h
src/gui/dialogs/formupdate.h src/gui/dialogs/formupdate.h
src/gui/notifications/notification.h
src/gui/systemtrayicon.h src/gui/systemtrayicon.h
src/gui/baselineedit.h src/gui/baselineedit.h
src/gui/locationlineedit.h src/gui/locationlineedit.h
@ -700,6 +702,7 @@ include_directories (
${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/src/gui ${CMAKE_SOURCE_DIR}/src/gui
${CMAKE_SOURCE_DIR}/src/gui/dialogs ${CMAKE_SOURCE_DIR}/src/gui/dialogs
${CMAKE_SOURCE_DIR}/src/gui/notifications
${CMAKE_SOURCE_DIR}/src/network-web ${CMAKE_SOURCE_DIR}/src/network-web
${CMAKE_SOURCE_DIR}/src/network-web/adblock ${CMAKE_SOURCE_DIR}/src/network-web/adblock
${CMAKE_SOURCE_DIR}/src/dynamic-shortcuts ${CMAKE_SOURCE_DIR}/src/dynamic-shortcuts

View File

@ -39,6 +39,7 @@
#include "gui/dialogs/formimportexport.h" #include "gui/dialogs/formimportexport.h"
#include "gui/dialogs/formbackupdatabasesettings.h" #include "gui/dialogs/formbackupdatabasesettings.h"
#include "gui/dialogs/formrestoredatabasesettings.h" #include "gui/dialogs/formrestoredatabasesettings.h"
#include "gui/notifications/notification.h"
#include <QCloseEvent> #include <QCloseEvent>
#include <QSessionManager> #include <QSessionManager>
@ -78,6 +79,8 @@ FormMain::FormMain(QWidget *parent, Qt::WindowFlags f)
// Initialize the web factory. // Initialize the web factory.
WebFactory::instance()->loadState(); 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() { FormMain::~FormMain() {

View File

@ -0,0 +1,233 @@
// 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, QSystemTrayIcon::MessageIcon icon) {
hide();
// Set new values.
m_text = text;
m_title = title;
m_icon = MessageBox::iconForStatus((QMessageBox::Icon) icon).pixmap(64, 64);
// Show it.
updateGeometries();
repaint();
show();
}
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);
// TODO: dodělat pozice x, y
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::focusInEvent(QFocusEvent *event) {
QWidget::focusInEvent(event);
repaint();
}
void Notification::focusOutEvent(QFocusEvent *event) {
QWidget::focusOutEvent(event);
repaint();
}
void Notification::paintEvent(QPaintEvent *event) {
Q_UNUSED(event)
QPainter painter(this);
painter.setFont(font());
QFontMetrics font_metrics = painter.fontMetrics();
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,68 @@
// 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, QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::Information);
protected:
void focusInEvent(QFocusEvent *event);
void focusOutEvent(QFocusEvent *event);
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