summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2011-12-24 10:08:47 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-12-24 11:00:04 (GMT)
commit3e2a3a4cdb0b6bc0cf79423c48400c544830177a (patch)
treedcc53224fd0b0ed0bd704a4b097f5c425dbd672e
parentf69d027b7e3b4260e514a77f7195ec511977b63e (diff)
downloadswift-contrib-3e2a3a4cdb0b6bc0cf79423c48400c544830177a.zip
swift-contrib-3e2a3a4cdb0b6bc0cf79423c48400c544830177a.tar.bz2
Enable "Show notifications" toggle when Growl isn't installed.
-rw-r--r--SwifTools/Notifier/GrowlNotifier.h1
-rw-r--r--SwifTools/Notifier/GrowlNotifier.mm12
-rw-r--r--SwifTools/Notifier/Notifier.h4
-rw-r--r--SwifTools/Notifier/TogglableNotifier.h6
-rw-r--r--Swift/Controllers/MainController.cpp1
-rw-r--r--Swift/Controllers/UIInterfaces/LoginWindow.h1
-rw-r--r--Swift/QtUI/QtLoginWindow.cpp12
-rw-r--r--Swift/QtUI/QtLoginWindow.h1
8 files changed, 31 insertions, 7 deletions
diff --git a/SwifTools/Notifier/GrowlNotifier.h b/SwifTools/Notifier/GrowlNotifier.h
index ffd717a..cb0d089 100644
--- a/SwifTools/Notifier/GrowlNotifier.h
+++ b/SwifTools/Notifier/GrowlNotifier.h
@@ -1,34 +1,35 @@
/*
* Copyright (c) 2010-2011 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <boost/filesystem/fstream.hpp>
#include <SwifTools/Notifier/Notifier.h>
namespace Swift {
/**
* Preconditions for using growlnotifier:
* - Must be part a bundle.
* - The Carbon/Cocoa application loop must be running (e.g. through QApplication)
* such that notifications are coming through.
*/
class GrowlNotifier : public Notifier {
public:
GrowlNotifier(const std::string& name);
virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback);
+ virtual bool isExternallyConfigured() const;
// Called by the delegate. Don't call.
void handleNotificationClicked(void* data);
void handleNotificationTimedOut(void* data);
private:
class Private;
boost::shared_ptr<Private> p;
};
}
diff --git a/SwifTools/Notifier/GrowlNotifier.mm b/SwifTools/Notifier/GrowlNotifier.mm
index 108259a..cb4790e 100644
--- a/SwifTools/Notifier/GrowlNotifier.mm
+++ b/SwifTools/Notifier/GrowlNotifier.mm
@@ -16,69 +16,75 @@
#pragma GCC diagnostic ignored "-Wold-style-cast"
namespace {
struct Context {
Context(const boost::function<void()>& callback) : callback(new boost::function<void()>(callback)) {}
boost::function<void()>* callback;
};
}
namespace Swift {
class GrowlNotifier::Private {
public:
boost::intrusive_ptr<GrowlNotifierDelegate> delegate;
};
GrowlNotifier::GrowlNotifier(const std::string& name) {
p = boost::make_shared<Private>();
p->delegate = boost::intrusive_ptr<GrowlNotifierDelegate>([[GrowlNotifierDelegate alloc] init], false);
p->delegate.get().name = STD2NSSTRING(name);
NSMutableArray* allNotifications = [[NSMutableArray alloc] init];
foreach(Type type, getAllTypes()) {
[allNotifications addObject: STD2NSSTRING(typeToString(type))];
}
NSMutableArray* defaultNotifications = [[NSMutableArray alloc] init];
foreach(Type type, getDefaultTypes()) {
[defaultNotifications addObject: STD2NSSTRING(typeToString(type))];
}
p->delegate.get().registrationDictionary = [[[NSDictionary alloc]
initWithObjects: [NSArray arrayWithObjects: allNotifications, defaultNotifications, nil]
forKeys: [NSArray arrayWithObjects: GROWL_NOTIFICATIONS_ALL, GROWL_NOTIFICATIONS_DEFAULT, nil]] autorelease];
+
+ [allNotifications release];
+ [defaultNotifications release];
[GrowlApplicationBridge setGrowlDelegate: p->delegate.get()];
}
void GrowlNotifier::showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picturePath, boost::function<void()> callback) {
ByteArray picture;
readByteArrayFromFile(picture, picturePath.string());
- Context* contextPtr = new Context(callback);
- NSData* context = [NSData dataWithBytes: &contextPtr length: sizeof(contextPtr)];
+ Context* context = new Context(callback);
[GrowlApplicationBridge
notifyWithTitle: STD2NSSTRING(subject)
description: STD2NSSTRING(description)
notificationName: STD2NSSTRING(typeToString(type))
iconData: [NSData dataWithBytes: vecptr(picture) length: picture.size()]
priority: 0
isSticky: NO
- clickContext: context];
+ clickContext: [NSData dataWithBytes: &context length: sizeof(context)]];
}
void GrowlNotifier::handleNotificationClicked(void* rawData) {
Context* context = *(Context**) [((NSData*) rawData) bytes];
if (!context->callback->empty()) {
(*context->callback)();
}
delete context;
}
void GrowlNotifier::handleNotificationTimedOut(void* rawData) {
delete *(Context**) [((NSData*) rawData) bytes];
}
+bool GrowlNotifier::isExternallyConfigured() const {
+ return ![GrowlApplicationBridge isMistEnabled];
+}
+
}
diff --git a/SwifTools/Notifier/Notifier.h b/SwifTools/Notifier/Notifier.h
index d6bd878..1bcd58d 100644
--- a/SwifTools/Notifier/Notifier.h
+++ b/SwifTools/Notifier/Notifier.h
@@ -1,43 +1,47 @@
/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <boost/function.hpp>
#include <boost/filesystem/path.hpp>
#include <string>
#include <vector>
namespace Swift {
class Notifier {
public:
virtual ~Notifier();
enum Type { ContactAvailable, ContactUnavailable, ContactStatusChange, IncomingMessage, SystemMessage };
/**
* Picture is a PNG image.
*/
virtual void showMessage(
Type type,
const std::string& subject,
const std::string& description,
const boost::filesystem::path& picture,
boost::function<void()> callback) = 0;
virtual bool isAvailable() const {
return true;
}
+ virtual bool isExternallyConfigured() const {
+ return false;
+ }
+
protected:
std::string typeToString(Type type);
static std::vector<Type> getAllTypes();
static std::vector<Type> getDefaultTypes();
static const int DEFAULT_STATUS_NOTIFICATION_TIMEOUT_SECONDS;
static const int DEFAULT_MESSAGE_NOTIFICATION_TIMEOUT_SECONDS;
};
}
diff --git a/SwifTools/Notifier/TogglableNotifier.h b/SwifTools/Notifier/TogglableNotifier.h
index e8de5de..7abfd42 100644
--- a/SwifTools/Notifier/TogglableNotifier.h
+++ b/SwifTools/Notifier/TogglableNotifier.h
@@ -9,46 +9,50 @@
#include <SwifTools/Notifier/Notifier.h>
namespace Swift {
class TogglableNotifier : public Notifier {
public:
TogglableNotifier(Notifier* notifier) : notifier(notifier), persistentEnabled(true), temporarilyDisabled(false) {
}
/**
* Set a long-term (usually user-set) enabled.
* This may be temporarily overriden by the application, e.g. if the
* user is marked DND.
*/
void setPersistentEnabled(bool b) {
persistentEnabled = b;
}
/**
* Set a temporary override to stop notifications without changing the
* long-term state. e.g. if the user goes DND, but the persistent
* enabled shouldn't be lost when they become available again.
*/
void setTemporarilyDisabled(bool b) {
temporarilyDisabled = b;
}
/**
* Get the result of applying the temporary override to the persistent
* enabledness.
*/
bool getCurrentlyEnabled() const {
return persistentEnabled && !temporarilyDisabled;
}
virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void()> callback) {
- if (getCurrentlyEnabled()) {
+ if (getCurrentlyEnabled() || notifier->isExternallyConfigured()) {
notifier->showMessage(type, subject, description, picture, callback);
}
}
+ virtual bool isExternallyConfigured() const {
+ return notifier->isExternallyConfigured();
+ }
+
private:
Notifier* notifier;
bool persistentEnabled;
bool temporarilyDisabled;
};
}
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 7ed53a2..046120d 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -104,70 +104,71 @@ MainController::MainController(
certificateStorageFactory_(certificateStorageFactory),
settings_(settings),
uriHandler_(uriHandler),
idleDetector_(idleDetector),
loginWindow_(NULL) ,
useDelayForLatency_(useDelayForLatency),
eagleMode_(eagleMode),
ftOverview_(NULL) {
storages_ = NULL;
certificateStorage_ = NULL;
statusTracker_ = NULL;
presenceNotifier_ = NULL;
eventNotifier_ = NULL;
rosterController_ = NULL;
chatsManager_ = NULL;
eventWindowController_ = NULL;
profileController_ = NULL;
contactEditController_ = NULL;
userSearchControllerChat_ = NULL;
userSearchControllerAdd_ = NULL;
adHocManager_ = NULL;
quitRequested_ = false;
clientInitialized_ = false;
offlineRequested_ = false;
timeBeforeNextReconnect_ = -1;
dock_ = dock;
uiEventStream_ = new UIEventStream();
notifier_ = new TogglableNotifier(notifier);
eventController_ = new EventController();
eventController_->onEventQueueLengthChange.connect(boost::bind(&MainController::handleEventQueueLengthChange, this, _1));
systemTrayController_ = new SystemTrayController(eventController_, systemTray);
loginWindow_ = uiFactory_->createLoginWindow(uiEventStream_);
+ loginWindow_->setShowNotificationToggle(!notifier->isExternallyConfigured());
soundEventController_ = new SoundEventController(eventController_, soundPlayer, settings, uiEventStream_);
xmppURIController_ = new XMPPURIController(uriHandler_, uiEventStream_);
std::string selectedLoginJID = settings_->getStringSetting("lastLoginJID");
bool loginAutomatically = settings_->getBoolSetting("loginAutomatically", false);
std::string cachedPassword;
std::string cachedCertificate;
if (!eagleMode_) {
foreach (std::string profile, settings->getAvailableProfiles()) {
ProfileSettingsProvider profileSettings(profile, settings);
std::string password = eagleMode ? "" : profileSettings.getStringSetting("pass");
std::string certificate = profileSettings.getStringSetting("certificate");
std::string jid = profileSettings.getStringSetting("jid");
loginWindow_->addAvailableAccount(jid, password, certificate);
if (jid == selectedLoginJID) {
cachedPassword = password;
cachedCertificate = certificate;
}
}
loginWindow_->selectUser(selectedLoginJID);
loginWindow_->setLoginAutomatically(loginAutomatically);
}
loginWindow_->onLoginRequest.connect(boost::bind(&MainController::handleLoginRequest, this, _1, _2, _3, _4, _5));
loginWindow_->onPurgeSavedLoginRequest.connect(boost::bind(&MainController::handlePurgeSavedLoginRequest, this, _1));
loginWindow_->onCancelLoginRequest.connect(boost::bind(&MainController::handleCancelLoginRequest, this));
loginWindow_->onQuitRequest.connect(boost::bind(&MainController::handleQuitRequest, this));
idleDetector_->setIdleTimeSeconds(600);
idleDetector_->onIdleChanged.connect(boost::bind(&MainController::handleInputIdleChanged, this, _1));
xmlConsoleController_ = new XMLConsoleController(uiEventStream_, uiFactory_);
diff --git a/Swift/Controllers/UIInterfaces/LoginWindow.h b/Swift/Controllers/UIInterfaces/LoginWindow.h
index 61fcaa1..a8ee5a4 100644
--- a/Swift/Controllers/UIInterfaces/LoginWindow.h
+++ b/Swift/Controllers/UIInterfaces/LoginWindow.h
@@ -1,37 +1,38 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "Swiften/Base/boost_bsignals.h"
#include <boost/shared_ptr.hpp>
#include <string>
#include <Swiften/TLS/Certificate.h>
namespace Swift {
class MainWindow;
class LoginWindow {
public:
virtual ~LoginWindow() {};
virtual void selectUser(const std::string&) = 0;
virtual void morphInto(MainWindow *mainWindow) = 0;
virtual void loggedOut() = 0;
+ virtual void setShowNotificationToggle(bool) = 0;
virtual void setMessage(const std::string&) = 0;
virtual void setIsLoggingIn(bool loggingIn) = 0;
virtual void addAvailableAccount(const std::string& defaultJID, const std::string& defaultPassword, const std::string& defaultCertificate) = 0;
virtual void removeAvailableAccount(const std::string& jid) = 0;
boost::signal<void (const std::string&, const std::string&, const std::string& /* certificateFile */, bool /* remember password*/, bool /* login automatically */)> onLoginRequest;
virtual void setLoginAutomatically(bool loginAutomatically) = 0;
virtual void quit() = 0;
/** Blocking request whether a cert should be permanently trusted.*/
virtual bool askUserToTrustCertificatePermanently(const std::string& message, Certificate::ref) = 0;
boost::signal<void ()> onCancelLoginRequest;
boost::signal<void ()> onQuitRequest;
boost::signal<void (const std::string&)> onPurgeSavedLoginRequest;
};
}
diff --git a/Swift/QtUI/QtLoginWindow.cpp b/Swift/QtUI/QtLoginWindow.cpp
index 5a8b9ab..43abd91 100644
--- a/Swift/QtUI/QtLoginWindow.cpp
+++ b/Swift/QtUI/QtLoginWindow.cpp
@@ -153,101 +153,107 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, bool eagleMode) : QMa
swiftMenu_ = new QMenu(tr("&Swift"), this);
#ifdef SWIFTEN_PLATFORM_MACOSX
generalMenu_ = new QMenu(tr("&General"), this);
#else
generalMenu_ = swiftMenu_;
#endif
#ifdef SWIFTEN_PLATFORM_MACOSX
QAction* aboutAction = new QAction(QString("&About %1").arg("Swift"), this);
#else
QAction* aboutAction = new QAction(QString(tr("&About %1")).arg("Swift"), this);
#endif
connect(aboutAction, SIGNAL(triggered()), SLOT(handleAbout()));
swiftMenu_->addAction(aboutAction);
xmlConsoleAction_ = new QAction(tr("&Show Debug Console"), this);
connect(xmlConsoleAction_, SIGNAL(triggered()), SLOT(handleShowXMLConsole()));
generalMenu_->addAction(xmlConsoleAction_);
#ifdef SWIFT_EXPERIMENTAL_FT
fileTransferOverviewAction_ = new QAction(tr("Show &File Transfer Overview"), this);
connect(fileTransferOverviewAction_, SIGNAL(triggered()), SLOT(handleShowFileTransferOverview()));
generalMenu_->addAction(fileTransferOverviewAction_);
#endif
toggleSoundsAction_ = new QAction(tr("&Play Sounds"), this);
toggleSoundsAction_->setCheckable(true);
toggleSoundsAction_->setChecked(true);
connect(toggleSoundsAction_, SIGNAL(toggled(bool)), SLOT(handleToggleSounds(bool)));
generalMenu_->addAction(toggleSoundsAction_);
toggleNotificationsAction_ = new QAction(tr("Display Pop-up &Notifications"), this);
toggleNotificationsAction_->setCheckable(true);
toggleNotificationsAction_->setChecked(true);
connect(toggleNotificationsAction_, SIGNAL(toggled(bool)), SLOT(handleToggleNotifications(bool)));
-#if defined(SWIFTEN_PLATFORM_LINUX) || defined(SWIFTEN_PLATFORM_WINDOWS)
- generalMenu_->addAction(toggleNotificationsAction_);
-#endif
#ifndef SWIFTEN_PLATFORM_MACOSX
swiftMenu_->addSeparator();
#endif
#ifdef SWIFTEN_PLATFORM_MACOSX
QAction* quitAction = new QAction("&Quit", this);
#else
QAction* quitAction = new QAction(tr("&Quit"), this);
#endif
connect(quitAction, SIGNAL(triggered()), SLOT(handleQuit()));
swiftMenu_->addAction(quitAction);
setInitialMenus();
uiEventStream_->onUIEvent.connect(boost::bind(&QtLoginWindow::handleUIEvent, this, _1));
remember_->setEnabled(!eagleMode_);
loginAutomatically_->setEnabled(!eagleMode_);
xmlConsoleAction_->setEnabled(!eagleMode_);
if (eagleMode_) {
remember_->setChecked(false);
loginAutomatically_->setChecked(false);
}
this->show();
}
+void QtLoginWindow::setShowNotificationToggle(bool toggle) {
+ if (toggle) {
+ generalMenu_->addAction(toggleNotificationsAction_);
+ }
+ else {
+ generalMenu_->removeAction(toggleNotificationsAction_);
+ }
+}
+
bool QtLoginWindow::eventFilter(QObject *obj, QEvent *event) {
if (obj == username_->view() && event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Delete || keyEvent->key() == Qt::Key_Backspace) {
QString jid(username_->view()->currentIndex().data().toString());
int result = QMessageBox::question(this, tr("Remove profile"), tr("Remove the profile '%1'?").arg(jid), QMessageBox::Yes | QMessageBox::No);
if (result == QMessageBox::Yes) {
onPurgeSavedLoginRequest(Q2PSTRING(jid));
}
return true;
}
}
return QObject::eventFilter(obj, event);
}
void QtLoginWindow::handleUIEvent(boost::shared_ptr<UIEvent> event) {
boost::shared_ptr<ToggleSoundsUIEvent> soundEvent = boost::dynamic_pointer_cast<ToggleSoundsUIEvent>(event);
if (soundEvent) {
toggleSoundsAction_->setChecked(soundEvent->getEnabled());
}
boost::shared_ptr<ToggleNotificationsUIEvent> notificationsEvent = boost::dynamic_pointer_cast<ToggleNotificationsUIEvent>(event);
if (notificationsEvent) {
toggleNotificationsAction_->setChecked(notificationsEvent->getEnabled());
}
}
void QtLoginWindow::selectUser(const std::string& username) {
for (int i = 0; i < usernames_.count(); i++) {
if (P2QSTRING(username) == usernames_[i]) {
username_->setCurrentIndex(i);
password_->setFocus();
break;
}
}
}
diff --git a/Swift/QtUI/QtLoginWindow.h b/Swift/QtUI/QtLoginWindow.h
index a830af5..df133b1 100644
--- a/Swift/QtUI/QtLoginWindow.h
+++ b/Swift/QtUI/QtLoginWindow.h
@@ -6,70 +6,71 @@
#pragma once
#include <QMainWindow>
#include <QPointer>
#include <QLineEdit>
#include <QPushButton>
#include <QCheckBox>
#include <QStackedWidget>
#include <QMenuBar>
#include "Swift/Controllers/UIInterfaces/LoginWindow.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "Swift/Controllers/UIInterfaces/MainWindow.h"
#include "QtAboutWidget.h"
class QLabel;
class QToolButton;
class QComboBox;
namespace Swift {
class QtLoginWindow : public QMainWindow, public LoginWindow {
Q_OBJECT
public:
struct QtMenus {
QtMenus(QMenu* swiftMenu, QMenu* generalMenu) : swiftMenu(swiftMenu), generalMenu(generalMenu) {}
QMenu* swiftMenu;
QMenu* generalMenu;
};
public:
QtLoginWindow(UIEventStream* uiEventStream, bool eagleMode);
void morphInto(MainWindow *mainWindow);
virtual void loggedOut();
+ virtual void setShowNotificationToggle(bool);
virtual void setMessage(const std::string& message);
virtual void addAvailableAccount(const std::string& defaultJID, const std::string& defaultPassword, const std::string& defaultCertificate);
virtual void removeAvailableAccount(const std::string& jid);
virtual void setLoginAutomatically(bool loginAutomatically);
virtual void setIsLoggingIn(bool loggingIn);
void selectUser(const std::string& user);
bool askUserToTrustCertificatePermanently(const std::string& message, Certificate::ref certificate);
void hide();
QtMenus getMenus() const;
virtual void quit();
signals:
void geometryChanged();
private slots:
void loginClicked();
void handleCertficateChecked(bool);
void handleQuit();
void handleShowXMLConsole();
void handleShowFileTransferOverview();
void handleToggleSounds(bool enabled);
void handleToggleNotifications(bool enabled);
void handleAbout();
void bringToFront();
void handleUsernameTextChanged();
void resizeEvent(QResizeEvent* event);
void moveEvent(QMoveEvent* event);
void handleUIEvent(boost::shared_ptr<UIEvent> event);
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
void setInitialMenus();
QWidget* loginWidgetWrapper_;