Added system tray icon

+ Can be used for setting client size and closing the client.

Will expand on by sending client alerts to the tray.

Updated to push message notifactions to the toolbar

Preview image:

Added setting to enable/disable message popups

Added functionality

+ updated popup message and translation
+ Double clicking tray icon will now bring up the app/minimize it
+ can now be alerted of mentions
+ added setting to set if you want mentions on desktop
+ clicking mention message will take you to the main chat
+ added translations for icon menu
+ removed maximize/minimize/restore from menu, not needed.

Added disconnect

+ Disconnects any previous message slots/signals from the system icon
message bubble
This commit is contained in:
Matt Lowe 2015-03-18 16:36:07 +01:00
parent b2e032b365
commit 81a8141fe5
15 changed files with 302 additions and 120 deletions

View file

@ -5,6 +5,7 @@
#include <QDesktopServices>
#include <QApplication>
#include <QDebug>
#include <QSystemTrayIcon>
#include "chatview.h"
#include "user_level.h"
#include "user_context_menu.h"
@ -223,6 +224,10 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use
cursor.insertText("@" + userName, mentionFormat);
message = message.mid(mention.size());
QApplication::alert(this);
if (shouldShowSystemPopup()) {
QString ref = sender.left(sender.length() - 2);
showSystemPopup(ref);
}
} else {
int mentionEndIndex = message.indexOf(QRegExp("\\W"), 1);// from 1 as @ is non-char
if (mentionEndIndex == -1)
@ -251,6 +256,22 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
void ChatView::actMessageClicked() {
emit messageClickedSignal();
}
bool ChatView::shouldShowSystemPopup() {
return tabSupervisor->currentIndex() != tabSupervisor->indexOf(this) ||
QApplication::activeWindow() == 0 || QApplication::focusWidget() == 0;
}
void ChatView::showSystemPopup(QString &sender) {
disconnect(trayIcon, SIGNAL(messageClicked()), 0, 0);
trayIcon->showMessage(sender + tr(" mentioned you."), tr("Click to view"));
connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(actMessageClicked()));
}
QColor ChatView::getCustomMentionColor() {
QColor customColor;
customColor.setNamedColor("#" + settingsCache->getChatMentionColor());

View file

@ -5,6 +5,7 @@
#include <QTextFragment>
#include <QTextCursor>
#include <QColor>
#include <QAction>
#include "userlist.h"
#include "user_level.h"
#include "tab_supervisor.h"
@ -32,14 +33,18 @@ private:
bool showTimestamps;
HoveredItemType hoveredItemType;
QString hoveredContent;
QAction *messageClicked;
QTextFragment getFragmentUnderMouse(const QPoint &pos) const;
QTextCursor prepareBlock(bool same = false);
void appendCardTag(QTextCursor &cursor, const QString &cardName);
void appendUrlTag(QTextCursor &cursor, QString url);
QString getNameFromUserList(QMap<QString, UserListTWI *> &userList, QString &userName);
QColor getCustomMentionColor();
bool shouldShowSystemPopup();
void showSystemPopup(QString &sender);
private slots:
void openLink(const QUrl &link);
void actMessageClicked();
public:
ChatView(const TabSupervisor *_tabSupervisor, TabGame *_game, bool _showTimestamps, QWidget *parent = 0);
void retranslateUi();
@ -59,6 +64,7 @@ signals:
void showCardInfoPopup(QPoint pos, QString cardName);
void deleteCardInfoPopup(QString cardName);
void addMentionTag(QString mentionTag);
void messageClickedSignal();
};
#endif

View file

@ -598,6 +598,12 @@ MessagesSettingsPage::MessagesSettingsPage()
updateMentionPreview();
connect(mentionColor, SIGNAL(textChanged(QString)), this, SLOT(updateColor(QString)));
messagePopups.setChecked(settingsCache->getShowMessagePopup());
connect(&messagePopups, SIGNAL(stateChanged(int)), settingsCache, SLOT(setShowMessagePopups(int)));
mentionPopups.setChecked(settingsCache->getShowMentionPopup());
connect(&mentionPopups, SIGNAL(stateChanged(int)), settingsCache, SLOT(setShowMentionPopups(int)));
QGridLayout *chatGrid = new QGridLayout;
chatGrid->addWidget(&chatMentionCheckBox, 0, 0);
chatGrid->addWidget(&invertMentionForeground, 0, 1);
@ -605,6 +611,8 @@ MessagesSettingsPage::MessagesSettingsPage()
chatGrid->addWidget(&ignoreUnregUsersMainChat, 1, 0);
chatGrid->addWidget(&hexLabel, 1, 2);
chatGrid->addWidget(&ignoreUnregUserMessages, 2, 0);
chatGrid->addWidget(&messagePopups, 3, 0);
chatGrid->addWidget(&mentionPopups, 4, 0);
chatGroupBox = new QGroupBox;
chatGroupBox->setLayout(chatGrid);
@ -699,6 +707,8 @@ void MessagesSettingsPage::retranslateUi()
ignoreUnregUsersMainChat.setText(tr("Ignore chat room messages sent by unregistered users."));
ignoreUnregUserMessages.setText(tr("Ignore private messages sent by unregistered users."));
invertMentionForeground.setText(tr("Invert text color"));
messagePopups.setText(tr("Enable desktop notifications for private messages."));
mentionPopups.setText(tr("Enable desktop notification for mentions."));
hexLabel.setText(tr("(Color is hexadecimal)"));
}

View file

@ -169,6 +169,8 @@ private:
QCheckBox invertMentionForeground;
QCheckBox ignoreUnregUsersMainChat;
QCheckBox ignoreUnregUserMessages;
QCheckBox messagePopups;
QCheckBox mentionPopups;
QGroupBox *chatGroupBox;
QGroupBox *messageShortcuts;
QLineEdit *mentionColor;

View file

@ -31,6 +31,7 @@
#include <QDir>
#include <QDesktopServices>
#include <QDebug>
#include <QSystemTrayIcon>
#include "main.h"
#include "window_main.h"
@ -48,6 +49,8 @@ QTranslator *translator, *qtTranslator;
SettingsCache *settingsCache;
RNG_Abstract *rng;
SoundEngine *soundEngine;
QSystemTrayIcon *trayIcon;
const QString translationPrefix = "cockatrice";
#ifdef TRANSLATION_PATH

View file

@ -3,10 +3,12 @@
class CardDatabase;
class QTranslator;
class QSystemTrayIcon;
class SoundEngine;
extern CardDatabase *db;
extern QSystemTrayIcon *trayIcon;
extern QTranslator *translator;
extern const QString translationPrefix;
extern QString translationPath;

View file

@ -75,6 +75,8 @@ SettingsCache::SettingsCache()
attemptAutoConnect = settings->value("server/auto_connect", 0).toBool();
scaleCards = settings->value("cards/scaleCards", true).toBool();
showMessagePopups = settings->value("chat/showmessagepopups", true).toBool();
showMentionPopups = settings->value("chat/showmentionpopups", true).toBool();
}
void SettingsCache::setCardScaling(const int _scaleCards) {
@ -82,6 +84,16 @@ void SettingsCache::setCardScaling(const int _scaleCards) {
settings->setValue("cards/scaleCards", scaleCards);
}
void SettingsCache::setShowMessagePopups(const int _showMessagePopups) {
showMessagePopups = _showMessagePopups;
settings->setValue("chat/showmessagepopups", showMessagePopups);
}
void SettingsCache::setShowMentionPopups(const int _showMentionPopus) {
showMentionPopups = _showMentionPopus;
settings->setValue("chat/showmentionpopups", showMentionPopups);
}
void SettingsCache::setLang(const QString &_lang)
{
lang = _lang;

View file

@ -75,6 +75,8 @@ private:
bool attemptAutoConnect;
int pixmapCacheSize;
bool scaleCards;
bool showMessagePopups;
bool showMentionPopups;
public:
SettingsCache();
const QByteArray &getMainWindowGeometry() const { return mainWindowGeometry; }
@ -127,6 +129,8 @@ public:
bool getAutoConnect() const { return attemptAutoConnect; }
int getPixmapCacheSize() const { return pixmapCacheSize; }
bool getScaleCards() const { return scaleCards; }
bool getShowMessagePopup() const { return showMessagePopups; }
bool getShowMentionPopup() const { return showMentionPopups; }
public slots:
void setMainWindowGeometry(const QByteArray &_mainWindowGeometry);
void setLang(const QString &_lang);
@ -172,6 +176,8 @@ public slots:
void setAutoConnect(const bool &_autoConnect);
void setPixmapCacheSize(const int _pixmapCacheSize);
void setCardScaling(const int _scaleCards);
void setShowMessagePopups(const int _showMessagePopups);
void setShowMentionPopups(const int _showMentionPopups);
};
extern SettingsCache *settingsCache;

View file

@ -6,6 +6,10 @@
#include "tab_message.h"
#include "abstractclient.h"
#include "chatview.h"
#include "main.h"
#include "settingscache.h"
#include <QSystemTrayIcon>
#include <QApplication>
#include "pending_command.h"
#include "pb/session_commands.pb.h"
@ -107,9 +111,29 @@ void TabMessage::processUserMessageEvent(const Event_UserMessage &event)
{
const UserLevelFlags userLevel(event.sender_name() == otherUserInfo->name() ? otherUserInfo->user_level() : ownUserInfo->user_level());
chatView->appendMessage(QString::fromStdString(event.message()), QString::fromStdString(event.sender_name()), userLevel, true);
if (settingsCache->getShowMessagePopup() && shouldShowSystemPopup(event))
showSystemPopup(event);
emit userEvent();
}
bool TabMessage::shouldShowSystemPopup(const Event_UserMessage &event) {
return (event.sender_name() == otherUserInfo->name() &&
tabSupervisor->currentIndex() != tabSupervisor->indexOf(this)) ||
QApplication::activeWindow() == 0 || QApplication::focusWidget() == 0;
}
void TabMessage::showSystemPopup(const Event_UserMessage &event) {
disconnect(trayIcon, SIGNAL(messageClicked()), 0, 0);
trayIcon->showMessage(tr("Private message from ") + otherUserInfo->name().c_str(), event.message().c_str());
connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
}
void TabMessage::messageClicked() {
tabSupervisor->setCurrentIndex(tabSupervisor->indexOf(this));
QApplication::setActiveWindow(this);
}
void TabMessage::processUserLeft()
{
chatView->appendMessage(tr("%1 has left the server.").arg(QString::fromStdString(otherUserInfo->name())));

View file

@ -30,6 +30,7 @@ private slots:
void actLeave();
void messageSent(const Response &response);
void addMentionTag(QString mentionTag);
void messageClicked();
public:
TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User &_ownUserInfo, const ServerInfo_User &_otherUserInfo);
~TabMessage();
@ -40,8 +41,12 @@ public:
QString getTabText() const;
void processUserMessageEvent(const Event_UserMessage &event);
void processUserLeft();
void processUserJoined(const ServerInfo_User &_userInfo);
private:
bool shouldShowSystemPopup(const Event_UserMessage &event);
void showSystemPopup(const Event_UserMessage &event);
};
#endif

View file

@ -9,6 +9,7 @@
#include <QLabel>
#include <QToolButton>
#include <QSplitter>
#include <QApplication>
#include "tab_supervisor.h"
#include "tab_room.h"
#include "tab_userlists.h"
@ -42,6 +43,7 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, ServerI
connect(userList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool)));
chatView = new ChatView(tabSupervisor, 0, true);
connect(chatView, SIGNAL(messageClickedSignal()), this, SLOT(focusTab()));
connect(chatView, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
@ -125,6 +127,11 @@ void TabRoom::retranslateUi()
aOpenChatSettings->setText(tr("Chat Settings..."));
}
void TabRoom::focusTab() {
QApplication::setActiveWindow(this);
tabSupervisor->setCurrentIndex(tabSupervisor->indexOf(this));
}
void TabRoom::closeRequest()
{
actLeaveRoom();

View file

@ -56,6 +56,7 @@ private slots:
void actClearChat();
void actOpenChatSettings();
void addMentionTag(QString mentionTag);
void focusTab();
void processListGamesEvent(const Event_ListGames &event);
void processJoinRoomEvent(const Event_JoinRoom &event);

View file

@ -28,6 +28,8 @@
#include <QFileDialog>
#include <QThread>
#include <QDateTime>
#include <QSystemTrayIcon>
#include <QApplication>
#include "main.h"
#include "window_main.h"
@ -413,6 +415,11 @@ MainWindow::MainWindow(QWidget *parent)
resize(900, 700);
restoreGeometry(settingsCache->getMainWindowGeometry());
aFullScreen->setChecked(windowState() & Qt::WindowFullScreen);
if (QSystemTrayIcon::isSystemTrayAvailable()) {
createTrayActions();
createTrayIcon();
}
}
MainWindow::~MainWindow()
@ -421,6 +428,37 @@ MainWindow::~MainWindow()
clientThread->wait();
}
void MainWindow::createTrayIcon() {
QMenu *trayIconMenu = new QMenu(this);
trayIconMenu->addAction(closeAction);
trayIcon = new QSystemTrayIcon(this);
trayIcon->setContextMenu(trayIconMenu);
trayIcon->setIcon(QIcon(":/resources/appicon.svg"));
trayIcon->show();
connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
}
void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) {
if (reason == QSystemTrayIcon::DoubleClick) {
if (windowState() != Qt::WindowMinimized)
showMinimized();
else {
showNormal();
QApplication::setActiveWindow(this);
}
}
}
void MainWindow::createTrayActions() {
closeAction = new QAction(tr("&Exit"), this);
connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
}
void MainWindow::closeEvent(QCloseEvent *event)
{
// workaround Qt bug where closeEvent gets called twice

View file

@ -21,6 +21,7 @@
#define WINDOW_H
#include <QMainWindow>
#include <QSystemTrayIcon>
#include "abstractclient.h"
#include "pb/response.pb.h"
@ -56,18 +57,28 @@ private slots:
void actExit();
void actAbout();
void iconActivated(QSystemTrayIcon::ActivationReason reason);
private:
static const QString appName;
void setClientStatusTitle();
void retranslateUi();
void createActions();
void createMenus();
void createTrayIcon();
void createTrayActions();
QList<QMenu *> tabMenus;
QMenu *cockatriceMenu, *helpMenu;
QAction *aConnect, *aDisconnect, *aSinglePlayer, *aWatchReplay, *aDeckEditor, *aFullScreen, *aSettings, *aExit,
*aAbout;
TabSupervisor *tabSupervisor;
QMenu *trayIconMenu;
QAction *closeAction;
RemoteClient *client;
QThread *clientThread;