32b98346990763fc06645a0016b3c019d9c906d3
[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 "action.h"
24 #include "actioncollection.h"
25 #include "buffermodel.h"
26 #include "bufferview.h"
27 #include "bufferviewmanager.h"
28 #include "bufferwidget.h"
29 #include "channellistdlg.h"
30 #include "chatlinemodel.h"
31 #include "chatmonitorfilter.h"
32 #include "chatmonitorview.h"
33 #include "chatview.h"
34 #include "client.h"
35 #include "clientbacklogmanager.h"
36 #include "coreinfodlg.h"
37 #include "coreconnectdlg.h"
38 #include "debuglogwidget.h"
39 #include "debugmessagemodelfilter.h"
40 #include "iconloader.h"
41 #include "inputwidget.h"
42 #include "inputline.h"
43 #include "irclistmodel.h"
44 #include "jumpkeyhandler.h"
45 #include "msgprocessorstatuswidget.h"
46 #include "nicklistwidget.h"
47 #include "qtuiapplication.h"
48 #include "qtuimessageprocessor.h"
49 #include "qtuisettings.h"
50 #include "sessionsettings.h"
51 #include "settingsdlg.h"
52 #include "settingspagedlg.h"
53 #include "topicwidget.h"
54 #include "verticaldock.h"
55
56 #ifdef HAVE_DBUS
57 #  include "desktopnotificationbackend.h"
58 #endif
59 #ifdef HAVE_PHONON
60 #  include "phononnotificationbackend.h"
61 #endif
62 #include "systraynotificationbackend.h"
63 #include "taskbarnotificationbackend.h"
64
65 #include "settingspages/aliasessettingspage.h"
66 #include "settingspages/appearancesettingspage.h"
67 #include "settingspages/backlogsettingspage.h"
68 #include "settingspages/bufferviewsettingspage.h"
69 #include "settingspages/colorsettingspage.h"
70 #include "settingspages/fontssettingspage.h"
71 #include "settingspages/generalsettingspage.h"
72 #include "settingspages/highlightsettingspage.h"
73 #include "settingspages/identitiessettingspage.h"
74 #include "settingspages/networkssettingspage.h"
75 #include "settingspages/notificationssettingspage.h"
76
77 MainWin::MainWin(QWidget *parent)
78   : QMainWindow(parent),
79     coreLagLabel(new QLabel()),
80     sslLabel(new QLabel()),
81     msgProcessorStatusWidget(new MsgProcessorStatusWidget()),
82     _titleSetter(this),
83     _trayIcon(new QSystemTrayIcon(this))
84 {
85   QtUiSettings uiSettings;
86   QString style = uiSettings.value("Style", QString()).toString();
87   if(!style.isEmpty()) {
88     QApplication::setStyle(style);
89   }
90
91   QApplication::setQuitOnLastWindowClosed(false);
92
93   setWindowTitle("Quassel IRC");
94   setWindowIconText("Quassel IRC");
95   updateIcon();
96
97   installEventFilter(new JumpKeyHandler(this));
98
99   QtUi::registerNotificationBackend(new TaskbarNotificationBackend(this));
100   QtUi::registerNotificationBackend(new SystrayNotificationBackend(this));
101 #ifdef HAVE_PHONON
102   QtUi::registerNotificationBackend(new PhononNotificationBackend(this));
103 #endif
104 #ifdef HAVE_DBUS
105   QtUi::registerNotificationBackend(new DesktopNotificationBackend(this));
106 #endif
107
108   QtUiApplication* app = qobject_cast<QtUiApplication*> qApp;
109   connect(app, SIGNAL(saveStateToSession(const QString&)), SLOT(saveStateToSession(const QString&)));
110   connect(app, SIGNAL(saveStateToSessionSettings(SessionSettings&)), SLOT(saveStateToSessionSettings(SessionSettings&)));
111 }
112
113 void MainWin::init() {
114   QtUiSettings s;
115   if(s.value("MainWinSize").isValid())
116     resize(s.value("MainWinSize").toSize());
117   else
118     resize(QSize(800, 500));
119
120   connect(QApplication::instance(), SIGNAL(aboutToQuit()), SLOT(saveLayout()));
121   connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), SLOT(clientNetworkCreated(NetworkId)));
122   connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), SLOT(clientNetworkRemoved(NetworkId)));
123   connect(Client::mainUi()->actionProvider(), SIGNAL(showChannelList(NetworkId)), SLOT(showChannelList(NetworkId)));
124
125   // Setup Dock Areas
126   setDockNestingEnabled(true);
127   setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
128   setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
129   setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
130   setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
131
132   // Order is sometimes important
133   setupActions();
134   setupBufferWidget();
135   setupMenus();
136   setupViews();
137   setupTopicWidget();
138   setupChatMonitor();
139   setupNickWidget();
140   setupInputWidget();
141   setupStatusBar();
142   setupSystray();
143   setupTitleSetter();
144
145   // restore mainwin state
146   restoreState(s.value("MainWinState").toByteArray());
147
148   // restore locked state of docks
149   QtUi::actionCollection("General")->action("LockDockPositions")->setChecked(s.value("LockDocks", false).toBool());
150
151   setDisconnectedState();  // Disable menus and stuff
152
153   show();
154   showCoreConnectionDlg(true); // autoconnect if appropriate
155 }
156
157 MainWin::~MainWin() {
158   QtUiSettings s;
159   s.setValue("MainWinSize", size());
160   s.setValue("MainWinPos", pos());
161   s.setValue("MainWinState", saveState());
162 }
163
164 void MainWin::updateIcon() {
165   QPixmap icon;
166   if(Client::isConnected())
167     icon = DesktopIcon("quassel", IconLoader::SizeEnormous);
168   else
169     icon = DesktopIcon("quassel_disconnected", IconLoader::SizeEnormous);
170   setWindowIcon(icon);
171   qApp->setWindowIcon(icon);
172   systemTrayIcon()->setIcon(icon);
173 }
174
175 void MainWin::setupActions() {
176   ActionCollection *coll = QtUi::actionCollection("General");
177   // File
178   coll->addAction("ConnectCore", new Action(SmallIcon("network-connect"), tr("&Connect to Core..."), coll,
179                                              this, SLOT(showCoreConnectionDlg())));
180   coll->addAction("DisconnectCore", new Action(SmallIcon("network-disconnect"), tr("&Disconnect from Core"), coll,
181                                                 Client::instance(), SLOT(disconnectFromCore())));
182   coll->addAction("CoreInfo", new Action(SmallIcon("help-about"), tr("Core &Info..."), coll,
183                                           this, SLOT(showCoreInfoDlg())));
184   coll->addAction("EditNetworks", new Action(SmallIcon("configure"), tr("Edit &Networks..."), coll,
185                                               this, SLOT(on_actionEditNetworks_triggered())));
186   coll->addAction("Quit", new Action(SmallIcon("application-exit"), tr("&Quit"), coll,
187                                       qApp, SLOT(quit()), tr("Ctrl+Q")));
188
189   // View
190   coll->addAction("ManageBufferViews", new Action(SmallIcon("view-tree"), tr("&Manage Buffer Views..."), coll,
191                                              this, SLOT(on_actionManageViews_triggered())));
192   Action *lockAct = coll->addAction("LockDockPositions", new Action(tr("&Lock Dock Positions"), coll));
193   lockAct->setCheckable(true);
194   connect(lockAct, SIGNAL(toggled(bool)), SLOT(on_actionLockDockPositions_toggled(bool)));
195
196   coll->addAction("ToggleSearchBar", new Action(SmallIcon("edit-find"), tr("Show &Search Bar"), coll,
197                                                  0, 0, tr("Ctrl+F")))->setCheckable(true);
198   coll->addAction("ToggleStatusBar", new Action(tr("Show Status &Bar"), coll,
199                                                  0, 0))->setCheckable(true);
200
201   // Settings
202   coll->addAction("ConfigureQuassel", new Action(SmallIcon("configure"), tr("&Configure Quassel..."), coll,
203                                                   this, SLOT(showSettingsDlg()), tr("F7")));
204
205   // Help
206   coll->addAction("AboutQuassel", new Action(SmallIcon("quassel"), tr("&About Quassel..."), coll,
207                                               this, SLOT(showAboutDlg())));
208   coll->addAction("AboutQt", new Action(QIcon(":/pics/qt-logo.png"), tr("About &Qt..."), coll,
209                                          qApp, SLOT(aboutQt())));
210   coll->addAction("DebugNetworkModel", new Action(SmallIcon("tools-report-bug"), tr("Debug &NetworkModel"), coll,
211                                        this, SLOT(on_actionDebugNetworkModel_triggered())));
212   coll->addAction("DebugMessageModel", new Action(SmallIcon("tools-report-bug"), tr("Debug &MessageModel"), coll,
213                                        this, SLOT(on_actionDebugMessageModel_triggered())));
214   coll->addAction("DebugLog", new Action(SmallIcon("tools-report-bug"), tr("Debug &Log"), coll,
215                                        this, SLOT(on_actionDebugLog_triggered())));
216 }
217
218 void MainWin::setupMenus() {
219   ActionCollection *coll = QtUi::actionCollection("General");
220
221   _fileMenu = menuBar()->addMenu(tr("&File"));
222   _fileMenu->addAction(coll->action("ConnectCore"));
223   _fileMenu->addAction(coll->action("DisconnectCore"));
224   _fileMenu->addAction(coll->action("CoreInfo"));
225   _fileMenu->addSeparator();
226   _networksMenu = _fileMenu->addMenu(tr("&Networks"));
227   _networksMenu->addAction(coll->action("EditNetworks"));
228   _networksMenu->addSeparator();
229   _fileMenu->addSeparator();
230   _fileMenu->addAction(coll->action("Quit"));
231
232   _viewMenu = menuBar()->addMenu(tr("&View"));
233   _bufferViewsMenu = _viewMenu->addMenu(tr("&Buffer Views"));
234   _bufferViewsMenu->addAction(coll->action("ManageBufferViews"));
235   _viewMenu->addSeparator();
236   _viewMenu->addAction(coll->action("ToggleSearchBar"));
237   _viewMenu->addAction(coll->action("ToggleStatusBar"));
238   _viewMenu->addSeparator();
239   _viewMenu->addAction(coll->action("LockDockPositions"));
240
241   _settingsMenu = menuBar()->addMenu(tr("&Settings"));
242   _settingsMenu->addAction(coll->action("ConfigureQuassel"));
243
244   _helpMenu = menuBar()->addMenu(tr("&Help"));
245   _helpMenu->addAction(coll->action("AboutQuassel"));
246   _helpMenu->addAction(coll->action("AboutQt"));
247   _helpMenu->addSeparator();
248   _helpDebugMenu = _helpMenu->addMenu(SmallIcon("tools-report-bug"), tr("Debug"));
249   _helpDebugMenu->addAction(coll->action("DebugNetworkModel"));
250   _helpDebugMenu->addAction(coll->action("DebugMessageModel"));
251   _helpDebugMenu->addAction(coll->action("DebugLog"));
252 }
253
254 void MainWin::setupBufferWidget() {
255   _bufferWidget = new BufferWidget(this);
256   _bufferWidget->setModel(Client::bufferModel());
257   _bufferWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
258   setCentralWidget(_bufferWidget);
259 }
260
261 void MainWin::setupViews() {
262   addBufferView();
263 }
264
265 void MainWin::addBufferView(int bufferViewConfigId) {
266   addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewConfigId));
267 }
268
269 void MainWin::addBufferView(BufferViewConfig *config) {
270   BufferViewDock *dock;
271   if(config)
272     dock = new BufferViewDock(config, this);
273   else
274     dock = new BufferViewDock(this);
275
276   //create the view and initialize it's filter
277   BufferView *view = new BufferView(dock);
278   view->setFilteredModel(Client::bufferModel(), config);
279   view->show();
280
281   Client::bufferModel()->synchronizeView(view);
282
283   dock->setWidget(view);
284   dock->show();
285
286   addDockWidget(Qt::LeftDockWidgetArea, dock);
287   _bufferViewsMenu->addAction(dock->toggleViewAction());
288
289   _bufferViews.append(dock);
290 }
291
292 void MainWin::removeBufferView(int bufferViewConfigId) {
293   QVariant actionData;
294   BufferViewDock *dock;
295   foreach(QAction *action, _bufferViewsMenu->actions()) {
296     actionData = action->data();
297     if(!actionData.isValid())
298       continue;
299
300     dock = qobject_cast<BufferViewDock *>(action->parent());
301     if(dock && actionData.toInt() == bufferViewConfigId) {
302       removeAction(action);
303       dock->deleteLater();
304     }
305   }
306 }
307
308 BufferView *MainWin::allBuffersView() const {
309   // "All Buffers" is always the first dock created
310   if(_bufferViews.count() > 0)
311     return _bufferViews[0]->bufferView();
312   return 0;
313 }
314
315 void MainWin::on_actionEditNetworks_triggered() {
316   SettingsPageDlg dlg(new NetworksSettingsPage(this), this);
317   dlg.exec();
318 }
319
320 void MainWin::on_actionManageViews_triggered() {
321   SettingsPageDlg dlg(new BufferViewSettingsPage(this), this);
322   dlg.exec();
323 }
324
325 void MainWin::on_actionLockDockPositions_toggled(bool lock) {
326   QList<VerticalDock *> docks = findChildren<VerticalDock *>();
327   foreach(VerticalDock *dock, docks) {
328     dock->showTitle(!lock);
329   }
330   QtUiSettings().setValue("LockDocks", lock);
331 }
332
333 void MainWin::setupNickWidget() {
334   // create nick dock
335   NickListDock *nickDock = new NickListDock(tr("Nicks"), this);
336   nickDock->setObjectName("NickDock");
337   nickDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
338
339   _nickListWidget = new NickListWidget(nickDock);
340   nickDock->setWidget(_nickListWidget);
341
342   addDockWidget(Qt::RightDockWidgetArea, nickDock);
343   _viewMenu->addAction(nickDock->toggleViewAction());
344   nickDock->toggleViewAction()->setText(tr("Show Nick List"));
345   nickDock->toggleViewAction()->setIcon(SmallIcon("view-sidetree"));
346   // See NickListDock::NickListDock();
347   // connect(nickDock->toggleViewAction(), SIGNAL(triggered(bool)), nickListWidget, SLOT(showWidget(bool)));
348
349   // attach the NickListWidget to the BufferModel and the default selection
350   _nickListWidget->setModel(Client::bufferModel());
351   _nickListWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
352 }
353
354 void MainWin::setupChatMonitor() {
355   VerticalDock *dock = new VerticalDock(tr("Chat Monitor"), this);
356   dock->setObjectName("ChatMonitorDock");
357
358   ChatMonitorFilter *filter = new ChatMonitorFilter(Client::messageModel(), this);
359   ChatMonitorView *chatView = new ChatMonitorView(filter, this);
360   chatView->show();
361   dock->setWidget(chatView);
362   dock->show();
363
364   addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
365   _viewMenu->addAction(dock->toggleViewAction());
366   dock->toggleViewAction()->setText(tr("Show Chat Monitor"));
367 }
368
369 void MainWin::setupInputWidget() {
370   VerticalDock *dock = new VerticalDock(tr("Inputline"), this);
371   dock->setObjectName("InputDock");
372
373   InputWidget *inputWidget = new InputWidget(dock);
374   dock->setWidget(inputWidget);
375
376   addDockWidget(Qt::BottomDockWidgetArea, dock);
377
378   _viewMenu->addAction(dock->toggleViewAction());
379   dock->toggleViewAction()->setText(tr("Show Input Line"));
380
381   inputWidget->setModel(Client::bufferModel());
382   inputWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
383
384   _bufferWidget->setFocusProxy(inputWidget);
385
386   inputWidget->inputLine()->installEventFilter(_bufferWidget);
387 }
388
389 void MainWin::setupTopicWidget() {
390   VerticalDock *dock = new VerticalDock(tr("Topic"), this);
391   dock->setObjectName("TopicDock");
392   TopicWidget *topicwidget = new TopicWidget(dock);
393
394   dock->setWidget(topicwidget);
395
396   topicwidget->setModel(Client::bufferModel());
397   topicwidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
398
399   addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
400
401   _viewMenu->addAction(dock->toggleViewAction());
402   dock->toggleViewAction()->setText(tr("Show Topic Line"));
403 }
404
405 void MainWin::setupTitleSetter() {
406   _titleSetter.setModel(Client::bufferModel());
407   _titleSetter.setSelectionModel(Client::bufferModel()->standardSelectionModel());
408 }
409
410 void MainWin::setupStatusBar() {
411   // MessageProcessor progress
412   statusBar()->addPermanentWidget(msgProcessorStatusWidget);
413   connect(Client::messageProcessor(), SIGNAL(progressUpdated(int, int)), msgProcessorStatusWidget, SLOT(setProgress(int, int)));
414
415   // Core Lag:
416   updateLagIndicator(0);
417   statusBar()->addPermanentWidget(coreLagLabel);
418   connect(Client::signalProxy(), SIGNAL(lagUpdated(int)), this, SLOT(updateLagIndicator(int)));
419
420   // SSL indicator
421   connect(Client::instance(), SIGNAL(securedConnection()), this, SLOT(securedConnection()));
422   sslLabel->setPixmap(QPixmap());
423   statusBar()->addPermanentWidget(sslLabel);
424
425   _viewMenu->addSeparator();
426   QAction *showStatusbar = QtUi::actionCollection("General")->action("ToggleStatusBar");
427
428   QtUiSettings uiSettings;
429
430   bool enabled = uiSettings.value("ShowStatusBar", QVariant(true)).toBool();
431   showStatusbar->setChecked(enabled);
432   enabled ? statusBar()->show() : statusBar()->hide();
433
434   connect(showStatusbar, SIGNAL(toggled(bool)), statusBar(), SLOT(setVisible(bool)));
435   connect(showStatusbar, SIGNAL(toggled(bool)), this, SLOT(saveStatusBarStatus(bool)));
436
437   connect(Client::backlogManager(), SIGNAL(messagesRequested(const QString &)), this, SLOT(showStatusBarMessage(const QString &)));
438   connect(Client::backlogManager(), SIGNAL(messagesProcessed(const QString &)), this, SLOT(showStatusBarMessage(const QString &)));
439 }
440
441 void MainWin::saveStatusBarStatus(bool enabled) {
442   QtUiSettings uiSettings;
443   uiSettings.setValue("ShowStatusBar", enabled);
444 }
445
446 void MainWin::setupSystray() {
447   connect(Client::messageModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
448                                   SLOT(messagesInserted(const QModelIndex &, int, int)));
449
450   ActionCollection *coll = QtUi::actionCollection("General");
451   systrayMenu = new QMenu(this);
452   systrayMenu->addAction(coll->action("AboutQuassel"));
453   systrayMenu->addSeparator();
454   systrayMenu->addAction(coll->action("ConnectCore"));
455   systrayMenu->addAction(coll->action("DisconnectCore"));
456   systrayMenu->addSeparator();
457   systrayMenu->addAction(coll->action("Quit"));
458
459   systemTrayIcon()->setContextMenu(systrayMenu);
460
461   QtUiSettings s;
462   if(s.value("UseSystemTrayIcon", QVariant(true)).toBool()) {
463     systemTrayIcon()->show();
464   }
465
466 #ifndef Q_WS_MAC
467   connect(systemTrayIcon(), SIGNAL(activated( QSystemTrayIcon::ActivationReason )),
468           this, SLOT(systrayActivated( QSystemTrayIcon::ActivationReason )));
469 #endif
470
471 }
472
473 void MainWin::changeEvent(QEvent *event) {
474   if(event->type() == QEvent::WindowStateChange) {
475     if(windowState() & Qt::WindowMinimized) {
476       QtUiSettings s;
477       if(s.value("UseSystemTrayIcon").toBool() && s.value("MinimizeOnMinimize").toBool()) {
478         toggleVisibility();
479         event->ignore();
480       }
481     }
482   }
483 }
484
485 void MainWin::connectedToCore() {
486   Q_CHECK_PTR(Client::bufferViewManager());
487   connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int)));
488   connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigDeleted(int)), this, SLOT(removeBufferView(int)));
489   connect(Client::bufferViewManager(), SIGNAL(initDone()), this, SLOT(loadLayout()));
490
491   setConnectedState();
492 }
493
494 void MainWin::setConnectedState() {
495   ActionCollection *coll = QtUi::actionCollection("General");
496   //ui.menuCore->setEnabled(true);
497   coll->action("ConnectCore")->setEnabled(false);
498   coll->action("DisconnectCore")->setEnabled(true);
499   coll->action("CoreInfo")->setEnabled(true);
500   // _viewMenu->setEnabled(true);
501   statusBar()->showMessage(tr("Connected to core."));
502   if(sslLabel->width() == 0)
503     sslLabel->setPixmap(SmallIcon("security-low"));
504   updateIcon();
505 }
506
507 void MainWin::loadLayout() {
508   QtUiSettings s;
509   int accountId = Client::currentCoreAccount().toInt();
510   restoreState(s.value(QString("MainWinState-%1").arg(accountId)).toByteArray(), accountId);
511 }
512
513 void MainWin::saveLayout() {
514   QtUiSettings s;
515   int accountId = Client::currentCoreAccount().toInt();
516   if(accountId > 0) s.setValue(QString("MainWinState-%1").arg(accountId) , saveState(accountId));
517 }
518
519 void MainWin::updateLagIndicator(int lag) {
520   coreLagLabel->setText(QString(tr("Core Lag: %1 msec")).arg(lag));
521 }
522
523
524 void MainWin::securedConnection() {
525   // todo: make status bar entry
526   sslLabel->setPixmap(SmallIcon("security-high"));
527 }
528
529 void MainWin::disconnectedFromCore() {
530   // save core specific layout and remove bufferviews;
531   saveLayout();
532   QVariant actionData;
533   BufferViewDock *dock;
534   foreach(QAction *action, _bufferViewsMenu->actions()) {
535     actionData = action->data();
536     if(!actionData.isValid())
537       continue;
538
539     dock = qobject_cast<BufferViewDock *>(action->parent());
540     if(dock && actionData.toInt() != -1) {
541       removeAction(action);
542       dock->deleteLater();
543     }
544   }
545   QtUiSettings s;
546   restoreState(s.value("MainWinState").toByteArray());
547   setDisconnectedState();
548 }
549
550 void MainWin::setDisconnectedState() {
551   ActionCollection *coll = QtUi::actionCollection("General");
552   //ui.menuCore->setEnabled(false);
553   coll->action("ConnectCore")->setEnabled(true);
554   coll->action("DisconnectCore")->setEnabled(false);
555   coll->action("CoreInfo")->setEnabled(false);
556   //_viewMenu->setEnabled(false);
557   statusBar()->showMessage(tr("Not connected to core."));
558   sslLabel->setPixmap(QPixmap());
559   updateIcon();
560 }
561
562 void MainWin::showCoreConnectionDlg(bool autoConnect) {
563   CoreConnectDlg(autoConnect, this).exec();
564 }
565
566 void MainWin::showChannelList(NetworkId netId) {
567   ChannelListDlg *channelListDlg = new ChannelListDlg();
568
569   if(!netId.isValid()) {
570     QAction *action = qobject_cast<QAction *>(sender());
571     if(action)
572       netId = action->data().value<NetworkId>();
573   }
574
575   channelListDlg->setAttribute(Qt::WA_DeleteOnClose);
576   channelListDlg->setNetwork(netId);
577   channelListDlg->show();
578 }
579
580 void MainWin::showCoreInfoDlg() {
581   CoreInfoDlg(this).exec();
582 }
583
584 void MainWin::showSettingsDlg() {
585   SettingsDlg *dlg = new SettingsDlg();
586
587   //Category: Appearance
588   dlg->registerSettingsPage(new ColorSettingsPage(dlg));
589   dlg->registerSettingsPage(new FontsSettingsPage(dlg));
590   dlg->registerSettingsPage(new AppearanceSettingsPage(dlg)); //General
591   //Category: Behaviour
592   dlg->registerSettingsPage(new GeneralSettingsPage(dlg));
593   dlg->registerSettingsPage(new BacklogSettingsPage(dlg));
594   dlg->registerSettingsPage(new HighlightSettingsPage(dlg));
595   dlg->registerSettingsPage(new AliasesSettingsPage(dlg));
596   dlg->registerSettingsPage(new NotificationsSettingsPage(dlg));
597   //Category: General
598   dlg->registerSettingsPage(new IdentitiesSettingsPage(dlg));
599   dlg->registerSettingsPage(new NetworksSettingsPage(dlg));
600   dlg->registerSettingsPage(new BufferViewSettingsPage(dlg));
601
602   dlg->show();
603 }
604
605 void MainWin::showAboutDlg() {
606   AboutDlg(this).exec();
607 }
608
609 void MainWin::closeEvent(QCloseEvent *event) {
610   QtUiSettings s;
611   if(s.value("UseSystemTrayIcon").toBool() && s.value("MinimizeOnClose").toBool()) {
612     toggleVisibility();
613     event->ignore();
614   } else {
615     event->accept();
616     QApplication::quit();
617   }
618 }
619
620 void MainWin::systrayActivated( QSystemTrayIcon::ActivationReason activationReason) {
621   if(activationReason == QSystemTrayIcon::Trigger) {
622     toggleVisibility();
623   }
624 }
625
626 void MainWin::toggleVisibility() {
627   if(isHidden() /*|| !isActiveWindow()*/) {
628     show();
629     if(isMinimized()) {
630       if(isMaximized())
631         showMaximized();
632       else
633         showNormal();
634     }
635
636     raise();
637     activateWindow();
638     // setFocus(); //Qt::ActiveWindowFocusReason
639
640   } else {
641     if(systemTrayIcon()->isSystemTrayAvailable ()) {
642       clearFocus();
643       hide();
644       if(!systemTrayIcon()->isVisible()) {
645         systemTrayIcon()->show();
646       }
647     } else {
648       lower();
649     }
650   }
651 }
652
653 void MainWin::messagesInserted(const QModelIndex &parent, int start, int end) {
654   Q_UNUSED(parent);
655
656   if(QApplication::activeWindow() != 0)
657     return;
658
659   for(int i = start; i <= end; i++) {
660     QModelIndex idx = Client::messageModel()->index(i, ChatLineModel::ContentsColumn);
661     if(!idx.isValid()) {
662       qDebug() << "MainWin::messagesInserted(): Invalid model index!";
663       continue;
664     }
665     Message::Flags flags = (Message::Flags)idx.data(ChatLineModel::FlagsRole).toInt();
666     if(flags.testFlag(Message::Backlog)) continue;
667     flags |= Message::Backlog;  // we only want to trigger a highlight once!
668     Client::messageModel()->setData(idx, (int)flags, ChatLineModel::FlagsRole);
669
670     BufferId bufId = idx.data(ChatLineModel::BufferIdRole).value<BufferId>();
671     BufferInfo::Type bufType = Client::networkModel()->bufferType(bufId);
672
673     if(flags & Message::Highlight || bufType == BufferInfo::QueryBuffer) {
674       QModelIndex senderIdx = Client::messageModel()->index(i, ChatLineModel::SenderColumn);
675       QString sender = senderIdx.data(ChatLineModel::EditRole).toString();
676       QString contents = idx.data(ChatLineModel::DisplayRole).toString();
677       QtUi::invokeNotification(bufId, sender, contents);
678     }
679   }
680 }
681
682 bool MainWin::event(QEvent *event) {
683   if(event->type() == QEvent::WindowActivate)
684     QtUi::closeNotifications();
685   return QMainWindow::event(event);
686 }
687
688 void MainWin::clientNetworkCreated(NetworkId id) {
689   const Network *net = Client::network(id);
690   QAction *act = new QAction(net->networkName(), this);
691   act->setObjectName(QString("NetworkAction-%1").arg(id.toInt()));
692   act->setData(QVariant::fromValue<NetworkId>(id));
693   connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated()));
694   connect(act, SIGNAL(triggered()), this, SLOT(connectOrDisconnectFromNet()));
695
696   QAction *beforeAction = 0;
697   foreach(QAction *action, _networksMenu->actions()) {
698     if(!action->data().isValid())  // ignore stock actions
699       continue;
700     if(net->networkName().localeAwareCompare(action->text()) < 0) {
701       beforeAction = action;
702       break;
703     }
704   }
705   _networksMenu->insertAction(beforeAction, act);
706 }
707
708 void MainWin::clientNetworkUpdated() {
709   const Network *net = qobject_cast<const Network *>(sender());
710   if(!net)
711     return;
712
713   QAction *action = findChild<QAction *>(QString("NetworkAction-%1").arg(net->networkId().toInt()));
714   if(!action)
715     return;
716
717   action->setText(net->networkName());
718
719   switch(net->connectionState()) {
720   case Network::Initialized:
721     action->setIcon(SmallIcon("network-connect"));
722     break;
723   case Network::Disconnected:
724     action->setIcon(SmallIcon("network-disconnect"));
725     break;
726   default:
727     action->setIcon(SmallIcon("network-wired"));
728   }
729 }
730
731 void MainWin::clientNetworkRemoved(NetworkId id) {
732   QAction *action = findChild<QAction *>(QString("NetworkAction-%1").arg(id.toInt()));
733   if(!action)
734     return;
735
736   action->deleteLater();
737 }
738
739 void MainWin::connectOrDisconnectFromNet() {
740   QAction *act = qobject_cast<QAction *>(sender());
741   if(!act) return;
742   const Network *net = Client::network(act->data().value<NetworkId>());
743   if(!net) return;
744   if(net->connectionState() == Network::Disconnected) net->requestConnect();
745   else net->requestDisconnect();
746 }
747
748 void MainWin::on_actionDebugNetworkModel_triggered() {
749   QTreeView *view = new QTreeView;
750   view->setAttribute(Qt::WA_DeleteOnClose);
751   view->setWindowTitle("Debug NetworkModel View");
752   view->setModel(Client::networkModel());
753   view->setColumnWidth(0, 250);
754   view->setColumnWidth(1, 250);
755   view->setColumnWidth(2, 80);
756   view->resize(610, 300);
757   view->show();
758 }
759
760 void MainWin::on_actionDebugMessageModel_triggered() {
761   QTableView *view = new QTableView(0);
762   DebugMessageModelFilter *filter = new DebugMessageModelFilter(view);
763   filter->setSourceModel(Client::messageModel());
764   view->setModel(filter);
765   view->setAttribute(Qt::WA_DeleteOnClose, true);
766   view->verticalHeader()->hide();
767   view->horizontalHeader()->setStretchLastSection(true);
768   view->show();
769 }
770
771 void MainWin::on_actionDebugLog_triggered() {
772   DebugLogWidget *logWidget = new DebugLogWidget(0);
773   logWidget->show();
774 }
775
776 void MainWin::saveStateToSession(const QString &sessionId) {
777   return;
778   SessionSettings s(sessionId);
779
780   s.setValue("MainWinSize", size());
781   s.setValue("MainWinPos", pos());
782   s.setValue("MainWinState", saveState());
783 }
784
785 void MainWin::saveStateToSessionSettings(SessionSettings & s)
786 {
787   s.setValue("MainWinSize", size());
788   s.setValue("MainWinPos", pos());
789   s.setValue("MainWinState", saveState());
790 }
791
792 void MainWin::showStatusBarMessage(const QString &message) {
793   statusBar()->showMessage(message, 10000);
794 }