Log: clean up notification handling; add Notification Center support for OS X.

This commit is contained in:
Mikkel Krautz 2012-08-06 20:49:02 +02:00
parent f8d57e49c8
commit 7a0f358fbf
6 changed files with 245 additions and 114 deletions

View File

@ -42,16 +42,6 @@
#include "ServerHandler.h"
#include "TextToSpeech.h"
#ifdef Q_OS_MAC
extern bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret);
static bool growl_available(void) {
OSStatus err = LSFindApplicationForInfo('GRRR', CFSTR("com.Growl.GrowlHelperApp"), CFSTR("GrowlHelperApp.app"), NULL, NULL);
return err != kLSApplicationNotFoundErr;
}
#endif
static ConfigWidget *LogConfigDialogNew(Settings &st) {
return new LogConfig(st);
}
@ -204,25 +194,6 @@ Log::Log(QObject *p) : QObject(p) {
tts->setVolume(g.s.iTTSVolume);
uiLastId = 0;
qdDate = QDate::currentDate();
#ifdef Q_OS_MAC
QStringList qslAllEvents;
for (int i = Log::firstMsgType; i <= Log::lastMsgType; ++i) {
Log::MsgType t = static_cast<Log::MsgType>(i);
qslAllEvents << QString::fromLatin1("\"%1\"").arg(g.l->msgName(t));
}
QString qsScript = QString::fromLatin1(
"tell application \"GrowlHelperApp\"\n"
" set the allNotificationsList to {%1}\n"
" set the enabledNotificationsList to {%1}\n"
" register as application \"Mumble\""
" all notifications allNotificationsList"
" default notifications enabledNotificationsList"
" icon of application \"Mumble\"\n"
"end tell\n").arg(qslAllEvents.join(QLatin1String(",")));
if (growl_available())
qt_mac_execute_apple_script(qsScript, NULL);
#endif
}
const char *Log::msgNames[] = {
@ -494,88 +465,7 @@ void Log::log(MsgType mt, const QString &console, const QString &terse, bool own
return;
// Message notification with balloon tooltips
if ((flags & Settings::LogBalloon) && !(g.mw->isActiveWindow() && g.mw->qdwLog->isVisible())) {
QString qsIcon;
switch (mt) {
case DebugInfo:
case CriticalError:
qsIcon=QLatin1String("gtk-dialog-error");
break;
case Warning:
qsIcon=QLatin1String("gtk-dialog-warning");
break;
case TextMessage:
qsIcon=QLatin1String("gtk-edit");
break;
default:
qsIcon=QLatin1String("gtk-dialog-info");
break;
}
#ifdef USE_DBUS
QDBusMessage response;
QVariantMap hints;
hints.insert(QLatin1String("desktop-entry"), QLatin1String("mumble"));
{
QDBusInterface kde(QLatin1String("org.kde.VisualNotifications"), QLatin1String("/VisualNotifications"), QLatin1String("org.kde.VisualNotifications"));
if (kde.isValid()) {
QList<QVariant> args;
args.append(QLatin1String("mumble"));
args.append(uiLastId);
args.append(QString());
args.append(QLatin1String("mumble"));
args.append(msgName(mt));
args.append(console);
args.append(QStringList());
args.append(hints);
args.append(5000);
response = kde.callWithArgumentList(QDBus::AutoDetect, QLatin1String("Notify"), args);
}
}
if (response.type()!=QDBusMessage::ReplyMessage || response.arguments().at(0).toUInt()==0) {
QDBusInterface gnome(QLatin1String("org.freedesktop.Notifications"), QLatin1String("/org/freedesktop/Notifications"), QLatin1String("org.freedesktop.Notifications"));
if (gnome.isValid())
response = gnome.call(QLatin1String("Notify"), QLatin1String("Mumble"), uiLastId, qsIcon, msgName(mt), console, QStringList(), hints, -1);
}
if (response.type()==QDBusMessage::ReplyMessage && response.arguments().count() == 1) {
uiLastId = response.arguments().at(0).toUInt();
} else {
#else
if (true) {
#endif
if (g.mw->qstiIcon->isSystemTrayAvailable() && g.mw->qstiIcon->supportsMessages()) {
QSystemTrayIcon::MessageIcon msgIcon;
switch (mt) {
case DebugInfo:
case CriticalError:
msgIcon=QSystemTrayIcon::Critical;
break;
case Warning:
msgIcon=QSystemTrayIcon::Warning;
break;
default:
msgIcon=QSystemTrayIcon::Information;
break;
}
g.mw->qstiIcon->showMessage(msgName(mt), plain, msgIcon);
}
}
#ifdef Q_OS_MAC
QString qsScript = QString::fromLatin1(
"tell application \"GrowlHelperApp\"\n"
" notify with name \"%1\" title \"%1\" description \"%2\" application name \"Mumble\"\n"
"end tell\n").arg(msgName(mt)).arg(plain);
if (growl_available())
qt_mac_execute_apple_script(qsScript, NULL);
#endif
}
postNotification(mt, console, plain);
// Don't make any noise if we are self deafened
if (g.s.bDeaf)
@ -635,6 +525,26 @@ void Log::log(MsgType mt, const QString &console, const QString &terse, bool own
tts->say(terse);
}
// Post a notification using the MainWindow's QSystemTrayIcon.
void Log::postQtNotification(MsgType mt, const QString &plain) {
if (g.mw->qstiIcon->isSystemTrayAvailable() && g.mw->qstiIcon->supportsMessages()) {
QSystemTrayIcon::MessageIcon msgIcon;
switch (mt) {
case DebugInfo:
case CriticalError:
msgIcon = QSystemTrayIcon::Critical;
break;
case Warning:
msgIcon = QSystemTrayIcon::Warning;
break;
default:
msgIcon = QSystemTrayIcon::Information;
break;
}
g.mw->qstiIcon->showMessage(msgName(mt), plain, msgIcon);
}
}
ValidDocument::ValidDocument(bool allowhttp, QObject *p) : QTextDocument(p) {
bValid = true;
qslValidImage << QLatin1String("data");

View File

@ -83,6 +83,8 @@ class Log : public QObject {
unsigned int uiLastId;
QDate qdDate;
static const QStringList allowedSchemes();
void postNotification(MsgType mt, const QString &console, const QString &plain);
void postQtNotification(MsgType mt, const QString &plain);
public:
Log(QObject *p = NULL);
QString msgName(MsgType t) const;

84
src/mumble/Log_macx.mm Normal file
View File

@ -0,0 +1,84 @@
/* Copyright (C) 2012, Mikkel Krautz <mikkel@krautz.dk>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mumble_pch.hpp"
#include "Log.h"
#include "Global.h"
static NSString *Log_QString_to_NSString(const QString& string) {
return const_cast<NSString *>(reinterpret_cast<const NSString *>(CFStringCreateWithCharacters(kCFAllocatorDefault,
reinterpret_cast<const UniChar *>(string.unicode()), string.length())));
}
extern bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret);
static bool growl_available() {
static int isAvailable = -1;
if (isAvailable == -1) {
OSStatus err = LSFindApplicationForInfo('GRRR', CFSTR("com.Growl.GrowlHelperApp"), CFSTR("GrowlHelperApp.app"), NULL, NULL);
isAvailable = (err != kLSApplicationNotFoundErr) ? 1 : 0;
if (isAvailable) {
QStringList qslAllEvents;
for (int i = Log::firstMsgType; i <= Log::lastMsgType; ++i) {
Log::MsgType t = static_cast<Log::MsgType>(i);
qslAllEvents << QString::fromLatin1("\"%1\"").arg(g.l->msgName(t));
}
QString qsScript = QString::fromLatin1(
"tell application \"GrowlHelperApp\"\n"
" set the allNotificationsList to {%1}\n"
" set the enabledNotificationsList to {%1}\n"
" register as application \"Mumble\""
" all notifications allNotificationsList"
" default notifications enabledNotificationsList"
" icon of application \"Mumble\"\n"
"end tell\n").arg(qslAllEvents.join(QLatin1String(",")));
qt_mac_execute_apple_script(qsScript, NULL);
}
}
return isAvailable == 1;
}
void Log::postNotification(MsgType mt, const QString &console, const QString &plain) {
QString title = msgName(mt);
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_MOUNTAINLION) {
NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease];
userNotification.title = [Log_QString_to_NSString(title) autorelease];
userNotification.informativeText = [Log_QString_to_NSString(plain) autorelease];
[[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification];
} else {
QString qsScript = QString::fromLatin1(
"tell application \"GrowlHelperApp\"\n"
" notify with name \"%1\" title \"%1\" description \"%2\" application name \"Mumble\"\n"
"end tell\n").arg(title).arg(plain);
if (growl_available())
qt_mac_execute_apple_script(qsScript, NULL);
}
}

97
src/mumble/Log_unix.cpp Normal file
View File

@ -0,0 +1,97 @@
/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>
Copyright (C) 2009-2011, Stefan Hacker <dd0t@users.sourceforge.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mumble_pch.hpp"
#include "Log.h"
#include "Global.h"
#include "MainWindow.h"
#include "Settings.h"
void Log::postNotification(MsgType mt, const QString &console, const QString &plain) {
// Message notification with balloon tooltips
if ((flags & Settings::LogBalloon) && !(g.mw->isActiveWindow() && g.mw->qdwLog->isVisible())) {
QString qsIcon;
switch (mt) {
case DebugInfo:
case CriticalError:
qsIcon=QLatin1String("gtk-dialog-error");
break;
case Warning:
qsIcon=QLatin1String("gtk-dialog-warning");
break;
case TextMessage:
qsIcon=QLatin1String("gtk-edit");
break;
default:
qsIcon=QLatin1String("gtk-dialog-info");
break;
}
#ifdef USE_DBUS
QDBusMessage response;
QVariantMap hints;
hints.insert(QLatin1String("desktop-entry"), QLatin1String("mumble"));
{
QDBusInterface kde(QLatin1String("org.kde.VisualNotifications"), QLatin1String("/VisualNotifications"), QLatin1String("org.kde.VisualNotifications"));
if (kde.isValid()) {
QList<QVariant> args;
args.append(QLatin1String("mumble"));
args.append(uiLastId);
args.append(QString());
args.append(QLatin1String("mumble"));
args.append(msgName(mt));
args.append(console);
args.append(QStringList());
args.append(hints);
args.append(5000);
response = kde.callWithArgumentList(QDBus::AutoDetect, QLatin1String("Notify"), args);
}
}
if (response.type()!=QDBusMessage::ReplyMessage || response.arguments().at(0).toUInt()==0) {
QDBusInterface gnome(QLatin1String("org.freedesktop.Notifications"), QLatin1String("/org/freedesktop/Notifications"), QLatin1String("org.freedesktop.Notifications"));
if (gnome.isValid())
response = gnome.call(QLatin1String("Notify"), QLatin1String("Mumble"), uiLastId, qsIcon, msgName(mt), console, QStringList(), hints, -1);
}
if (response.type()==QDBusMessage::ReplyMessage && response.arguments().count() == 1) {
uiLastId = response.arguments().at(0).toUInt();
} else {
#else
if (true) {
#endif
postQtNotification(mt, plain);
}
}
}

38
src/mumble/Log_win.cpp Normal file
View File

@ -0,0 +1,38 @@
/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>
Copyright (C) 2009-2011, Stefan Hacker <dd0t@users.sourceforge.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mumble_pch.hpp"
#include "Log.h"
void Log::postNotification(MsgType mt, const QString &console, const QString &plain) {
postQtNotification(mt, plain);
}

View File

@ -95,7 +95,7 @@ unix:!CONFIG(bundled-opus):system(pkg-config --exists opus) {
win32 {
RC_FILE = mumble.rc
HEADERS *= GlobalShortcut_win.h TaskList.h
SOURCES *= GlobalShortcut_win.cpp TextToSpeech_win.cpp Overlay_win.cpp SharedMemory_win.cpp os_win.cpp TaskList.cpp ../../overlay/HardHook.cpp ../../overlay/ods.cpp
SOURCES *= GlobalShortcut_win.cpp TextToSpeech_win.cpp Overlay_win.cpp SharedMemory_win.cpp Log_win.cpp os_win.cpp TaskList.cpp ../../overlay/HardHook.cpp ../../overlay/ods.cpp
LIBS *= -l"$$(DXSDK_DIR)Lib/x86/dxguid" -l"$$(DXSDK_DIR)Lib/x86/dinput8" -lsapi -lole32 -lws2_32 -ladvapi32 -lwintrust -ldbghelp -llibsndfile-1 -lshell32 -lshlwapi -luser32 -lgdi32
LIBS *= -ldelayimp -delayload:speex.dll -delayload:shell32.dll
@ -152,7 +152,7 @@ unix {
HEADERS *= GlobalShortcut_macx.h ConfigDialogDelegate.h
SOURCES *= TextToSpeech_macx.cpp SharedMemory_unix.cpp
OBJECTIVE_SOURCES *= GlobalShortcut_macx.mm os_macx.mm
OBJECTIVE_SOURCES *= GlobalShortcut_macx.mm os_macx.mm Log_macx.mm
!CONFIG(no-cocoa) {
# Link against libxar so we can inspect Mac OS X installer packages.
@ -176,7 +176,7 @@ unix {
HEADERS += CoreAudio.h
} else {
HEADERS *= GlobalShortcut_unix.h
SOURCES *= GlobalShortcut_unix.cpp TextToSpeech_unix.cpp Overlay_unix.cpp SharedMemory_unix.cpp
SOURCES *= GlobalShortcut_unix.cpp TextToSpeech_unix.cpp Overlay_unix.cpp SharedMemory_unix.cpp Log_unix.cpp
PKGCONFIG *= x11
LIBS *= -lrt -lXi