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