4c3f16b4181e42e22934892119aca15d004ae704
[quassel.git] / src / qtui / mainwin.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-08 by the Quassel Project                          *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #include "mainwin.h"
21
22 #include "aboutdlg.h"
23 #include "chatwidget.h"
24 #include "bufferview.h"
25 #include "bufferviewconfig.h"
26 #include "bufferviewfilter.h"
27 #include "bufferviewmanager.h"
28 #include "channellistdlg.h"
29 #include "client.h"
30 #include "clientbacklogmanager.h"
31 #include "coreinfodlg.h"
32 #include "coreconnectdlg.h"
33 #include "networkmodel.h"
34 #include "buffermodel.h"
35 #include "nicklistwidget.h"
36 #include "settingsdlg.h"
37 #include "settingspagedlg.h"
38 #include "signalproxy.h"
39 #include "topicwidget.h"
40 #include "inputwidget.h"
41 #include "irclistmodel.h"
42 #include "verticaldock.h"
43 #include "uisettings.h"
44 #include "util.h"
45 #include "qtuisettings.h"
46 #include "jumpkeyhandler.h"
47
48 #include "uisettings.h"
49
50 #include "selectionmodelsynchronizer.h"
51 #include "mappedselectionmodel.h"
52
53 #include "settingspages/aliasessettingspage.h"
54 #include "settingspages/appearancesettingspage.h"
55 #include "settingspages/bufferviewsettingspage.h"
56 #include "settingspages/colorsettingspage.h"
57 #include "settingspages/fontssettingspage.h"
58 #include "settingspages/generalsettingspage.h"
59 #include "settingspages/highlightsettingspage.h"
60 #include "settingspages/identitiessettingspage.h"
61 #include "settingspages/networkssettingspage.h"
62
63
64 #include "debugconsole.h"
65 #include "global.h"
66 #include "qtuistyle.h"
67
68 #include <Qt/QtDBus>
69
70
71 MainWin::MainWin(QtUi *_gui, QWidget *parent)
72   : QMainWindow(parent),
73     gui(_gui),
74     coreLagLabel(new QLabel()),
75     sslLabel(new QLabel()),
76     _titleSetter(this),
77     systray(new QSystemTrayIcon(this)),
78     activeTrayIcon(":/icons/quassel-icon-active.png"),
79     onlineTrayIcon(":/icons/quassel-icon.png"),
80     offlineTrayIcon(":/icons/quassel-icon-offline.png"),
81     trayIconActive(false),
82     timer(new QTimer(this)),
83     channelListDlg(new ChannelListDlg(this)),
84     settingsDlg(new SettingsDlg(this)),
85     debugConsole(new DebugConsole(this))
86 {
87   UiSettings uiSettings;
88   loadTranslation(uiSettings.value("Locale", QLocale::system()).value<QLocale>());
89   
90   QString style = uiSettings.value("Style", QString("")).toString();
91   if(style != "") {
92     QApplication::setStyle(style);
93   }
94   
95   ui.setupUi(this);
96   setWindowTitle("Quassel IRC");
97   setWindowIcon(offlineTrayIcon);
98   qApp->setWindowIcon(offlineTrayIcon);
99   systray->setIcon(offlineTrayIcon);
100   setWindowIconText("Quassel IRC");
101
102   statusBar()->showMessage(tr("Waiting for core..."));
103
104   installEventFilter(new JumpKeyHandler(this));
105
106 }
107
108 void MainWin::init() {
109   QtUiSettings s;
110   if(s.value("MainWinSize").isValid())
111     resize(s.value("MainWinSize").toSize());
112   else
113     resize(QSize(800, 500));
114
115   Client::signalProxy()->attachSignal(this, SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)));
116
117   connect(QApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(saveLayout()));
118
119   connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientNetworkCreated(NetworkId)));
120   connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientNetworkRemoved(NetworkId)));
121
122   show();
123
124   statusBar()->showMessage(tr("Not connected to core."));
125
126   // DOCK OPTIONS
127   setDockNestingEnabled(true);
128
129   setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
130   setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
131   setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
132   setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
133
134   // setup stuff...
135   setupMenus();
136   setupViews();
137   setupNickWidget();
138   setupTopicWidget();
139   setupChatMonitor();
140   setupInputWidget();
141   setupStatusBar();
142   setupSystray();
143
144   setupSettingsDlg();
145
146   // restore mainwin state
147   restoreState(s.value("MainWinState").toByteArray());
148
149   // restore locked state of docks  
150   ui.actionLockDockPositions->setChecked(s.value("LockDocks", false).toBool());
151   
152
153   setDisconnectedState();  // Disable menus and stuff
154   showCoreConnectionDlg(true); // autoconnect if appropriate
155
156   // attach the BufferWidget to the BufferModel and the default selection
157   ui.bufferWidget->setModel(Client::bufferModel());
158   ui.bufferWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
159
160   _titleSetter.setModel(Client::bufferModel());
161   _titleSetter.setSelectionModel(Client::bufferModel()->standardSelectionModel());
162 }
163
164 MainWin::~MainWin() {
165   QtUiSettings s;
166   s.setValue("MainWinSize", size());
167   s.setValue("MainWinPos", pos());
168   s.setValue("MainWinState", saveState());
169 }
170
171 void MainWin::setupMenus() {
172   connect(ui.actionConnectCore, SIGNAL(triggered()), this, SLOT(showCoreConnectionDlg()));
173   connect(ui.actionDisconnectCore, SIGNAL(triggered()), Client::instance(), SLOT(disconnectFromCore()));
174   connect(ui.actionCoreInfo, SIGNAL(triggered()), this, SLOT(showCoreInfoDlg()));
175   connect(ui.actionQuit, SIGNAL(triggered()), QCoreApplication::instance(), SLOT(quit()));
176   connect(ui.actionSettingsDlg, SIGNAL(triggered()), this, SLOT(showSettingsDlg()));
177   // connect(ui.actionDebug_Console, SIGNAL(triggered()), this, SLOT(showDebugConsole()));
178   connect(ui.actionAboutQuassel, SIGNAL(triggered()), this, SLOT(showAboutDlg()));
179   connect(ui.actionAboutQt, SIGNAL(triggered()), QApplication::instance(), SLOT(aboutQt()));
180 }
181
182 void MainWin::setupViews() {
183   addBufferView();
184 }
185
186 void MainWin::addBufferView(int bufferViewConfigId) {
187   addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewConfigId));
188 }
189
190 void MainWin::addBufferView(BufferViewConfig *config) {
191   BufferViewDock *dock;
192   if(config)
193     dock = new BufferViewDock(config, this);
194   else
195     dock = new BufferViewDock(this);
196
197   //create the view and initialize it's filter
198   BufferView *view = new BufferView(dock);
199   view->setFilteredModel(Client::bufferModel(), config);
200   view->show();
201
202   connect(&view->showChannelList, SIGNAL(triggered()), this, SLOT(showChannelList()));
203   
204   Client::bufferModel()->synchronizeView(view);
205
206   dock->setWidget(view);
207   dock->show();
208
209   addDockWidget(Qt::LeftDockWidgetArea, dock);
210   ui.menuBufferViews->addAction(dock->toggleViewAction());
211
212   _netViews.append(dock);
213 }
214
215 void MainWin::removeBufferView(int bufferViewConfigId) {
216   QVariant actionData;
217   BufferViewDock *dock;
218   foreach(QAction *action, ui.menuBufferViews->actions()) {
219     actionData = action->data();
220     if(!actionData.isValid())
221       continue;
222
223     dock = qobject_cast<BufferViewDock *>(action->parent());
224     if(dock && actionData.toInt() == bufferViewConfigId) {
225       removeAction(action);
226       dock->deleteLater();
227     }
228   }
229 }
230
231 void MainWin::setupSettingsDlg() {
232   //Category: Appearance
233   settingsDlg->registerSettingsPage(new ColorSettingsPage(settingsDlg));
234   settingsDlg->registerSettingsPage(new FontsSettingsPage(settingsDlg));
235   settingsDlg->registerSettingsPage(new AppearanceSettingsPage(settingsDlg)); //General
236   //Category: Behaviour
237   settingsDlg->registerSettingsPage(new GeneralSettingsPage(settingsDlg));
238   settingsDlg->registerSettingsPage(new HighlightSettingsPage(settingsDlg));
239   settingsDlg->registerSettingsPage(new AliasesSettingsPage(settingsDlg));
240   //Category: General
241   settingsDlg->registerSettingsPage(new IdentitiesSettingsPage(settingsDlg));
242   settingsDlg->registerSettingsPage(new NetworksSettingsPage(settingsDlg));
243   settingsDlg->registerSettingsPage(new BufferViewSettingsPage(settingsDlg));
244 }
245
246 void MainWin::on_actionEditNetworks_triggered() {
247   SettingsPageDlg dlg(new NetworksSettingsPage(this), this);
248   dlg.exec();
249 }
250
251 void MainWin::on_actionManageViews_triggered() {
252   SettingsPageDlg dlg(new BufferViewSettingsPage(this), this);
253   dlg.exec();
254 }
255
256 void MainWin::on_actionLockDockPositions_toggled(bool lock) {
257   QList<VerticalDock *> docks = findChildren<VerticalDock *>();
258   foreach(VerticalDock *dock, docks) {
259     dock->showTitle(!lock);
260   }
261   QtUiSettings().setValue("LockDocks", lock);
262 }
263
264 void MainWin::setupNickWidget() {
265   // create nick dock
266   NickListDock *nickDock = new NickListDock(tr("Nicks"), this);
267   nickDock->setObjectName("NickDock");
268   nickDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
269
270   nickListWidget = new NickListWidget(nickDock);
271   nickDock->setWidget(nickListWidget);
272
273   addDockWidget(Qt::RightDockWidgetArea, nickDock);
274   ui.menuViews->addAction(nickDock->toggleViewAction());
275   // See NickListDock::NickListDock();
276   // connect(nickDock->toggleViewAction(), SIGNAL(triggered(bool)), nickListWidget, SLOT(showWidget(bool)));
277
278   // attach the NickListWidget to the BufferModel and the default selection
279   nickListWidget->setModel(Client::bufferModel());
280   nickListWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
281 }
282
283 void MainWin::setupChatMonitor() {
284 #ifndef SPUTDEV
285   VerticalDock *dock = new VerticalDock(tr("Chat Monitor"), this);
286   dock->setObjectName("ChatMonitorDock");
287
288   ChatWidget *chatWidget = new ChatWidget(0, this);
289   chatWidget->show();
290   dock->setWidget(chatWidget);
291   dock->show();
292
293   Buffer *buf = Client::monitorBuffer();
294   if(!buf)
295     return;
296
297   chatWidget->setContents(buf->contents());
298   connect(buf, SIGNAL(msgAppended(AbstractUiMsg *)), chatWidget, SLOT(appendMsg(AbstractUiMsg *)));
299   connect(buf, SIGNAL(msgPrepended(AbstractUiMsg *)), chatWidget, SLOT(prependMsg(AbstractUiMsg *)));
300
301   addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
302   ui.menuViews->addAction(dock->toggleViewAction());
303 #endif /* SPUTDEV */
304 }
305
306 void MainWin::setupInputWidget() {
307   VerticalDock *dock = new VerticalDock(tr("Inputline"), this);
308   dock->setObjectName("InputDock");
309
310   InputWidget *inputWidget = new InputWidget(dock);
311   dock->setWidget(inputWidget);
312
313   addDockWidget(Qt::BottomDockWidgetArea, dock);
314
315   ui.menuViews->addAction(dock->toggleViewAction());
316
317   inputWidget->setModel(Client::bufferModel());
318   inputWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
319
320   ui.bufferWidget->setFocusProxy(inputWidget);
321 }
322
323 void MainWin::setupTopicWidget() {
324   VerticalDock *dock = new VerticalDock(tr("Topic"), this);
325   dock->setObjectName("TopicDock");
326   TopicWidget *topicwidget = new TopicWidget(dock);
327   connect(topicwidget, SIGNAL(topicChanged(const QString &)), this, SLOT(changeTopic(const QString &)));
328
329   dock->setWidget(topicwidget);
330
331   topicwidget->setModel(Client::bufferModel());
332   topicwidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
333
334   addDockWidget(Qt::TopDockWidgetArea, dock);
335
336   ui.menuViews->addAction(dock->toggleViewAction());
337 }
338
339 void MainWin::setupStatusBar() {
340   // Core Lag:
341   updateLagIndicator(0);
342   statusBar()->addPermanentWidget(coreLagLabel);
343   connect(Client::signalProxy(), SIGNAL(lagUpdated(int)), this, SLOT(updateLagIndicator(int)));
344
345   // SSL indicator
346   connect(Client::instance(), SIGNAL(securedConnection()), this, SLOT(securedConnection()));
347   sslLabel->setPixmap(QPixmap());
348   statusBar()->addPermanentWidget(sslLabel);
349
350   ui.menuViews->addSeparator();
351   QAction *showStatusbar = ui.menuViews->addAction(tr("Statusbar"));
352   showStatusbar->setCheckable(true);
353
354   UiSettings uiSettings;
355
356   bool enabled = uiSettings.value("ShowStatusBar", QVariant(true)).toBool();
357   showStatusbar->setChecked(enabled);
358   enabled ? statusBar()->show() : statusBar()->hide();
359
360   connect(showStatusbar, SIGNAL(toggled(bool)), statusBar(), SLOT(setVisible(bool)));
361   connect(showStatusbar, SIGNAL(toggled(bool)), this, SLOT(saveStatusBarStatus(bool)));
362 }
363
364 void MainWin::saveStatusBarStatus(bool enabled) {
365   UiSettings uiSettings;
366   uiSettings.setValue("ShowStatusBar", enabled);
367 }
368
369 void MainWin::setupSystray() {
370   connect(timer, SIGNAL(timeout()), this, SLOT(makeTrayIconBlink()));
371   connect(Client::instance(), SIGNAL(messageReceived(const Message &)), this, SLOT(receiveMessage(const Message &)));
372
373   systrayMenu = new QMenu(this);
374   systrayMenu->addAction(ui.actionAboutQuassel);
375   systrayMenu->addSeparator();
376   systrayMenu->addAction(ui.actionConnectCore);
377   systrayMenu->addAction(ui.actionDisconnectCore);
378   systrayMenu->addSeparator();
379   systrayMenu->addAction(ui.actionQuit);
380
381   systray->setContextMenu(systrayMenu);
382
383   UiSettings s;
384   if(s.value("UseSystemTrayIcon", QVariant(true)).toBool()) {
385     systray->show();
386   }
387
388 #ifndef Q_WS_MAC
389   connect(systray, SIGNAL(activated( QSystemTrayIcon::ActivationReason )),
390           this, SLOT(systrayActivated( QSystemTrayIcon::ActivationReason )));
391 #endif
392
393 }
394
395 void MainWin::changeEvent(QEvent *event) {
396   if(event->type() == QEvent::WindowStateChange) {
397     if(windowState() & Qt::WindowMinimized) {
398       UiSettings s;
399       if(s.value("UseSystemTrayIcon").toBool() && s.value("MinimizeOnMinimize").toBool()) {
400         toggleVisibility();
401         event->ignore();
402       }
403     }
404   }
405 }
406
407 // FIXME this should be made prettier...
408 void MainWin::changeTopic(const QString &topic) {
409   BufferId id = ui.bufferWidget->currentBuffer();
410   if(!id.isValid()) return;
411   Buffer *buffer = Client::buffer(id);
412   if(buffer) Client::userInput(buffer->bufferInfo(), QString("/topic %1").arg(topic));
413 }
414
415 void MainWin::connectedToCore() {
416   Q_CHECK_PTR(Client::bufferViewManager());
417   connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int)));
418   connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigDeleted(int)), this, SLOT(removeBufferView(int)));
419   connect(Client::bufferViewManager(), SIGNAL(initDone()), this, SLOT(loadLayout()));
420
421   foreach(BufferInfo id, Client::allBufferInfos()) {
422     Client::backlogManager()->requestBacklog(id.bufferId(), 500, -1);
423   }
424   setConnectedState();
425 }
426
427 void MainWin::setConnectedState() {
428   //ui.menuCore->setEnabled(true);
429   ui.actionConnectCore->setEnabled(false);
430   ui.actionDisconnectCore->setEnabled(true);
431   ui.actionCoreInfo->setEnabled(true);
432   ui.menuViews->setEnabled(true);
433   ui.bufferWidget->show();
434   statusBar()->showMessage(tr("Connected to core."));
435   setWindowIcon(onlineTrayIcon);
436   qApp->setWindowIcon(onlineTrayIcon);
437   systray->setIcon(onlineTrayIcon);
438   if(sslLabel->width() == 0)
439     sslLabel->setPixmap(QPixmap::fromImage(QImage(":/16x16/status/no-ssl")));
440 }
441
442 void MainWin::loadLayout() {
443   QtUiSettings s;
444   int accountId = Client::currentCoreAccount().toInt();
445   restoreState(s.value(QString("MainWinState-%1").arg(accountId)).toByteArray(), accountId);
446 }
447
448 void MainWin::saveLayout() {
449   QtUiSettings s;
450   int accountId = Client::currentCoreAccount().toInt();
451   if(accountId > 0) s.setValue(QString("MainWinState-%1").arg(accountId) , saveState(accountId));
452 }
453
454 void MainWin::updateLagIndicator(int lag) {
455   coreLagLabel->setText(QString("Core Lag: %1 msec").arg(lag));
456 }
457
458
459 void MainWin::securedConnection() {
460   // todo: make status bar entry
461   sslLabel->setPixmap(QPixmap::fromImage(QImage(":/16x16/status/ssl")));
462 }
463
464 void MainWin::disconnectedFromCore() {
465   // save core specific layout and remove bufferviews;
466   saveLayout();
467   QVariant actionData;
468   BufferViewDock *dock;
469   foreach(QAction *action, ui.menuBufferViews->actions()) {
470     actionData = action->data();
471     if(!actionData.isValid())
472       continue;
473
474     dock = qobject_cast<BufferViewDock *>(action->parent());
475     if(dock && actionData.toInt() != -1) {
476       removeAction(action);
477       dock->deleteLater();
478     }
479   }
480   QtUiSettings s;
481   restoreState(s.value("MainWinState").toByteArray());
482   setDisconnectedState();
483 }
484
485 void MainWin::setDisconnectedState() {
486   //ui.menuCore->setEnabled(false);
487   ui.actionConnectCore->setEnabled(true);
488   ui.actionDisconnectCore->setEnabled(false);
489   ui.actionCoreInfo->setEnabled(false);
490   ui.menuViews->setEnabled(false);
491   ui.bufferWidget->hide();
492   statusBar()->showMessage(tr("Not connected to core."));
493   setWindowIcon(offlineTrayIcon);
494   qApp->setWindowIcon(offlineTrayIcon);
495   systray->setIcon(offlineTrayIcon);
496   sslLabel->setPixmap(QPixmap());
497 }
498
499 void MainWin::showCoreConnectionDlg(bool autoConnect) {
500   coreConnectDlg = new CoreConnectDlg(this, autoConnect);
501   connect(coreConnectDlg, SIGNAL(finished(int)), this, SLOT(coreConnectionDlgFinished(int)));
502   coreConnectDlg->setModal(true);
503   coreConnectDlg->show();
504 }
505
506 void MainWin::coreConnectionDlgFinished(int /*code*/) {
507   coreConnectDlg->close();
508   //exit(1);
509 }
510
511 void MainWin::showChannelList(NetworkId netId) {
512   if(!netId.isValid()) {
513     QAction *action = qobject_cast<QAction *>(sender());
514     if(action)
515       netId = action->data().value<NetworkId>();
516   }
517   channelListDlg->setNetwork(netId);
518   channelListDlg->show();
519 }
520
521 void MainWin::showCoreInfoDlg() {
522   CoreInfoDlg dlg(this);
523   dlg.exec();
524 }
525
526 void MainWin::showSettingsDlg() {
527   settingsDlg->show();
528 }
529
530 void MainWin::showDebugConsole() {
531   debugConsole->show();
532 }
533
534 void MainWin::showAboutDlg() {
535   AboutDlg dlg(this);
536   dlg.exec();
537 }
538
539 void MainWin::closeEvent(QCloseEvent *event) {
540   UiSettings s;
541   if(s.value("UseSystemTrayIcon").toBool() && s.value("MinimizeOnClose").toBool()) {
542     toggleVisibility();
543     event->ignore();
544   } else {
545     event->accept();
546   }
547 }
548
549 void MainWin::systrayActivated( QSystemTrayIcon::ActivationReason activationReason) {
550   if(activationReason == QSystemTrayIcon::Trigger) {
551     toggleVisibility();
552   }
553 }
554
555 void MainWin::toggleVisibility() {
556   if(isHidden() /*|| !isActiveWindow()*/) {
557     show();
558     if(isMinimized()) {
559       if(isMaximized())
560         showMaximized();
561       else
562         showNormal();
563     }
564
565     raise();
566     activateWindow();
567     // setFocus(); //Qt::ActiveWindowFocusReason
568
569   } else {
570     if(systray->isSystemTrayAvailable ()) {
571       clearFocus();
572       hide();
573       if(!systray->isVisible()) {
574         systray->show();
575       }
576     } else {
577       lower();
578     }
579   }
580 }
581
582 void MainWin::receiveMessage(const Message &msg) {
583   if(QApplication::activeWindow() != 0)
584     return;
585
586   if(msg.flags() & Message::Highlight || msg.bufferInfo().type() == BufferInfo::QueryBuffer) {
587     QString title = msg.bufferInfo().bufferName();;
588     if(msg.bufferInfo().type() != BufferInfo::QueryBuffer) {
589       QString sender = msg.sender();
590       int i = sender.indexOf("!");
591       if(i != -1)
592         sender = sender.left(i);
593       title += QString(" - %1").arg(sender);
594     }
595
596     UiSettings uiSettings;
597
598 #ifndef SPUTDEV
599     if(uiSettings.value("DisplayPopupMessages", QVariant(true)).toBool()) {
600       // FIXME don't invoke style engine for this!
601       QString text = QtUi::style()->styleString(Message::mircToInternal(msg.contents())).plainText;
602       displayTrayIconMessage(title, text);
603           sendDesktopNotification(title, text);
604     }
605 #endif
606     if(uiSettings.value("AnimateTrayIcon", QVariant(true)).toBool()) {
607       QApplication::alert(this);
608       setTrayIconActivity(true);
609     }
610   }
611 }
612
613 bool MainWin::event(QEvent *event) {
614   if(event->type() == QEvent::WindowActivate)
615     setTrayIconActivity(false);
616   return QMainWindow::event(event);
617 }
618
619
620 /*
621 Using the notification-daemon from Freedesktop's Galago project
622 http://www.galago-project.org/specs/notification/0.9/x408.html#command-notify
623 */
624 void MainWin::sendDesktopNotification(const QString &title, const QString &message)
625 {
626         QStringList actions;
627         QMap<QString, QVariant> hints;
628         QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "", "Notify");
629
630         hints["x"] = 100; // Standard hint: x location for the popup to show up
631         hints["y"] = 100; // Standard hint: y location for the popup to show up
632
633         msg << "Quassel"; // Application name
634         msg << quint32(0); // ID of previous notification to replace
635         msg << ""; // Icon to display
636         msg << "Quassel: " + title; // Summary / Header of the message to display
637         msg << message; // Body of the message to display
638         msg << actions; // Actions from which the user may choose
639         msg << hints; // Hints to the server displaying the message
640         msg << qint32(10000); // Timeout in milliseconds
641
642         (void)QDBusConnection::sessionBus().call(msg); // Would return a message containing the id of this notification
643 }
644
645
646 void MainWin::displayTrayIconMessage(const QString &title, const QString &message) {
647   systray->showMessage(title, message);
648 }
649
650 void MainWin::setTrayIconActivity(bool active) {
651   if(active) {
652     if(!timer->isActive())
653       timer->start(500);
654   } else {
655     timer->stop();
656     systray->setIcon(onlineTrayIcon);
657   }
658 }
659
660 void MainWin::makeTrayIconBlink() {
661   if(trayIconActive) {
662     systray->setIcon(onlineTrayIcon);
663     trayIconActive = false;
664   } else {
665     systray->setIcon(activeTrayIcon);
666     trayIconActive = true;
667   }
668 }
669
670 void MainWin::clientNetworkCreated(NetworkId id) {
671   const Network *net = Client::network(id);
672   QAction *act = new QAction(net->networkName(), this);
673   act->setObjectName(QString("NetworkAction-%1").arg(id.toInt()));
674   act->setData(QVariant::fromValue<NetworkId>(id));
675   connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated()));
676   connect(act, SIGNAL(triggered()), this, SLOT(connectOrDisconnectFromNet()));
677
678   QAction *beforeAction = 0;
679   foreach(QAction *action, ui.menuNetworks->actions()) {
680     if(action->isSeparator()) {
681       beforeAction = action;
682       break;
683     }
684     if(net->networkName().localeAwareCompare(action->text()) < 0) {
685       beforeAction = action;
686       break;
687     }
688   }
689   Q_CHECK_PTR(beforeAction);
690   ui.menuNetworks->insertAction(beforeAction, act);
691 }
692
693 void MainWin::clientNetworkUpdated() {
694   const Network *net = qobject_cast<const Network *>(sender());
695   if(!net)
696     return;
697
698   QAction *action = findChild<QAction *>(QString("NetworkAction-%1").arg(net->networkId().toInt()));
699   if(!action)
700     return;
701
702   action->setText(net->networkName());
703
704   switch(net->connectionState()) {
705   case Network::Initialized:
706     action->setIcon(QIcon(":/16x16/actions/network-connect"));
707     break;
708   case Network::Disconnected:
709     action->setIcon(QIcon(":/16x16/actions/network-disconnect"));
710     break;
711   default:
712     action->setIcon(QIcon(":/16x16/actions/gear"));
713   }
714 }
715
716 void MainWin::clientNetworkRemoved(NetworkId id) {
717   QAction *action = findChild<QAction *>(QString("NetworkAction-%1").arg(id.toInt()));
718   if(!action)
719     return;
720   
721   action->deleteLater();
722 }
723
724 void MainWin::connectOrDisconnectFromNet() {
725   QAction *act = qobject_cast<QAction *>(sender());
726   if(!act) return;
727   const Network *net = Client::network(act->data().value<NetworkId>());
728   if(!net) return;
729   if(net->connectionState() == Network::Disconnected) net->requestConnect();
730   else net->requestDisconnect();
731 }
732