some boundary checks (prevents erroneous/bad clients from crashing the core)
[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 "chatline-old.h"
29 #include "client.h"
30 #include "clientbacklogmanager.h"
31 #include "coreconnectdlg.h"
32 #include "networkmodel.h"
33 #include "buffermodel.h"
34 #include "nicklistwidget.h"
35 #include "settingsdlg.h"
36 #include "settingspagedlg.h"
37 #include "signalproxy.h"
38 #include "topicwidget.h"
39 #include "inputwidget.h"
40 #include "verticaldock.h"
41 #include "uisettings.h"
42 #include "qtuisettings.h"
43 #include "jumpkeyhandler.h"
44
45 #include "uisettings.h"
46
47 #include "selectionmodelsynchronizer.h"
48 #include "mappedselectionmodel.h"
49
50 #include "settingspages/appearancesettingspage.h"
51 #include "settingspages/bufferviewsettingspage.h"
52 #include "settingspages/colorsettingspage.h"
53 #include "settingspages/fontssettingspage.h"
54 #include "settingspages/generalsettingspage.h"
55 #include "settingspages/highlightsettingspage.h"
56 #include "settingspages/identitiessettingspage.h"
57 #include "settingspages/networkssettingspage.h"
58
59
60 #include "debugconsole.h"
61 #include "global.h"
62 #include "qtuistyle.h"
63
64 MainWin::MainWin(QtUi *_gui, QWidget *parent)
65   : QMainWindow(parent),
66     gui(_gui),
67     sslLabel(new QLabel()),
68     systray(new QSystemTrayIcon(this)),
69     activeTrayIcon(":/icons/quassel-icon-active.png"),
70     onlineTrayIcon(":/icons/quassel-icon.png"),
71     offlineTrayIcon(":/icons/quassel-icon-offline.png"),
72     trayIconActive(false),
73     timer(new QTimer(this)),
74     settingsDlg(new SettingsDlg(this)),
75     debugConsole(new DebugConsole(this))
76 {
77   ui.setupUi(this);
78   setWindowTitle("Quassel IRC");
79   setWindowIcon(offlineTrayIcon);
80   systray->setIcon(offlineTrayIcon);
81   setWindowIconText("Quassel IRC");
82
83   statusBar()->showMessage(tr("Waiting for core..."));
84
85   installEventFilter(new JumpKeyHandler(this));
86
87   UiSettings uiSettings;
88   QString style = uiSettings.value("Style", QString("")).toString();
89   if(style != "") {
90     QApplication::setStyle(style);
91   }
92 }
93
94 void MainWin::init() {
95   QtUiSettings s;
96   if(s.value("MainWinSize").isValid())
97     resize(s.value("MainWinSize").toSize());
98   else
99     resize(QSize(800, 500));
100
101   Client::signalProxy()->attachSignal(this, SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)));
102
103   connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientNetworkCreated(NetworkId)));
104   connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientNetworkRemoved(NetworkId)));
105   //ui.bufferWidget->init();
106
107   show();
108
109   statusBar()->showMessage(tr("Not connected to core."));
110
111   // DOCK OPTIONS
112   setDockNestingEnabled(true);
113
114   setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
115   setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
116   setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
117   setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
118
119   // setup stuff...
120   setupMenus();
121   setupViews();
122   setupNickWidget();
123   setupTopicWidget();
124   setupChatMonitor();
125   setupInputWidget();
126   setupStatusBar();
127   setupSystray();
128
129   setupSettingsDlg();
130
131   // restore mainwin state
132   restoreState(s.value("MainWinState").toByteArray());
133
134   disconnectedFromCore();  // Disable menus and stuff
135   showCoreConnectionDlg(true); // autoconnect if appropriate
136
137   // attach the BufferWidget to the BufferModel and the default selection
138   ui.bufferWidget->setModel(Client::bufferModel());
139   ui.bufferWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
140
141 }
142
143 MainWin::~MainWin() {
144   QtUiSettings s;
145   s.setValue("MainWinSize", size());
146   s.setValue("MainWinPos", pos());
147   s.setValue("MainWinState", saveState());
148 }
149
150 void MainWin::setupMenus() {
151   connect(ui.actionConnectCore, SIGNAL(triggered()), this, SLOT(showCoreConnectionDlg()));
152   connect(ui.actionDisconnectCore, SIGNAL(triggered()), Client::instance(), SLOT(disconnectFromCore()));
153   connect(ui.actionQuit, SIGNAL(triggered()), QCoreApplication::instance(), SLOT(quit()));
154   //connect(ui.actionNetworkList, SIGNAL(triggered()), this, SLOT(showServerList()));
155   connect(ui.actionSettingsDlg, SIGNAL(triggered()), this, SLOT(showSettingsDlg()));
156   connect(ui.actionDebug_Console, SIGNAL(triggered()), this, SLOT(showDebugConsole()));
157   connect(ui.actionAboutQuassel, SIGNAL(triggered()), this, SLOT(showAboutDlg()));
158   connect(ui.actionAboutQt, SIGNAL(triggered()), QApplication::instance(), SLOT(aboutQt()));
159
160   actionEditNetworks = new QAction(QIcon(":/22x22/actions/configure"), tr("Edit &Networks..."), this);
161   ui.menuNetworks->addAction(actionEditNetworks);
162   connect(actionEditNetworks, SIGNAL(triggered()), this, SLOT(showNetworkDlg()));
163   connect(ui.actionManageViews, SIGNAL(triggered()), this, SLOT(showManageViewsDlg()));
164 }
165
166 void MainWin::setupViews() {
167   QAction *separator = ui.menuViews->addSeparator();
168   separator->setData("__EOBV__");
169   addBufferView();
170 }
171
172 void MainWin::addBufferView(int bufferViewConfigId) {
173   addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewConfigId));
174 }
175
176 void MainWin::addBufferView(BufferViewConfig *config) {
177   BufferViewDock *dock;
178   if(config)
179     dock = new BufferViewDock(config, this);
180   else
181     dock = new BufferViewDock(this);
182
183   //create the view and initialize it's filter
184   BufferView *view = new BufferView(dock);
185   view->setFilteredModel(Client::bufferModel(), config);
186   view->show();
187
188   Client::bufferModel()->synchronizeView(view);
189
190   dock->setWidget(view);
191   dock->show();
192
193   addDockWidget(Qt::LeftDockWidgetArea, dock);
194
195   QAction *endOfBufferViews = 0;
196   foreach(QAction *action, ui.menuViews->actions()) {
197     if(action->data().toString() == "__EOBV__") {
198       endOfBufferViews = action;
199       break;
200     }
201   }
202   Q_CHECK_PTR(endOfBufferViews);
203   ui.menuViews->insertAction(endOfBufferViews, dock->toggleViewAction());
204
205   _netViews.append(dock);
206 }
207
208 void MainWin::removeBufferView(int bufferViewConfigId) {
209   QVariant actionData;
210   BufferViewDock *dock;
211   foreach(QAction *action, ui.menuViews->actions()) {
212     actionData = action->data();
213     if(!actionData.isValid())
214       continue;
215     
216     if(actionData.toString() == "__EOBV__")
217       break;
218
219     dock = qobject_cast<BufferViewDock *>(action->parent());
220     if(dock && actionData.toInt() == bufferViewConfigId) {
221       removeAction(action);
222       dock->deleteLater();
223     }
224   }
225 }
226
227 void MainWin::setupSettingsDlg() {
228   //Category: Appearance
229   settingsDlg->registerSettingsPage(new ColorSettingsPage(settingsDlg));
230   settingsDlg->registerSettingsPage(new FontsSettingsPage(settingsDlg));
231   settingsDlg->registerSettingsPage(new AppearanceSettingsPage(settingsDlg)); //General
232   //Category: Behaviour
233   settingsDlg->registerSettingsPage(new GeneralSettingsPage(settingsDlg));
234   settingsDlg->registerSettingsPage(new HighlightSettingsPage(settingsDlg));
235   //Category: General
236   settingsDlg->registerSettingsPage(new IdentitiesSettingsPage(settingsDlg));
237   settingsDlg->registerSettingsPage(new NetworksSettingsPage(settingsDlg));
238   settingsDlg->registerSettingsPage(new BufferViewSettingsPage(settingsDlg));
239 }
240
241 void MainWin::showNetworkDlg() {
242   SettingsPageDlg dlg(new NetworksSettingsPage(this), this);
243   dlg.exec();
244 }
245
246 void MainWin::showManageViewsDlg() {
247   SettingsPageDlg dlg(new BufferViewSettingsPage(this), this);
248   dlg.exec();
249 }
250
251 void MainWin::setupNickWidget() {
252   // create nick dock
253   NickListDock *nickDock = new NickListDock(tr("Nicks"), this);
254   nickDock->setObjectName("NickDock");
255   nickDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
256
257   nickListWidget = new NickListWidget(nickDock);
258   nickDock->setWidget(nickListWidget);
259
260   addDockWidget(Qt::RightDockWidgetArea, nickDock);
261   ui.menuViews->addAction(nickDock->toggleViewAction());
262   connect(nickDock->toggleViewAction(), SIGNAL(triggered(bool)), nickListWidget, SLOT(showWidget(bool)));
263
264   // attach the NickListWidget to the BufferModel and the default selection
265   nickListWidget->setModel(Client::bufferModel());
266   nickListWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
267 }
268
269 void MainWin::setupChatMonitor() {
270   VerticalDock *dock = new VerticalDock(tr("Chat Monitor"), this);
271   dock->setObjectName("ChatMonitorDock");
272
273   ChatWidget *chatWidget = new ChatWidget(0, this);
274   chatWidget->show();
275   dock->setWidget(chatWidget);
276   dock->show();
277
278   Buffer *buf = Client::monitorBuffer();
279   if(!buf)
280     return;
281
282   chatWidget->setContents(buf->contents());
283   connect(buf, SIGNAL(msgAppended(AbstractUiMsg *)), chatWidget, SLOT(appendMsg(AbstractUiMsg *)));
284   connect(buf, SIGNAL(msgPrepended(AbstractUiMsg *)), chatWidget, SLOT(prependMsg(AbstractUiMsg *)));
285
286   addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
287   ui.menuViews->addAction(dock->toggleViewAction());
288 }
289
290 void MainWin::setupInputWidget() {
291   VerticalDock *dock = new VerticalDock(tr("Inputline"), this);
292   dock->setObjectName("InputDock");
293
294   InputWidget *inputWidget = new InputWidget(dock);
295   dock->setWidget(inputWidget);
296
297   addDockWidget(Qt::BottomDockWidgetArea, dock);
298
299   ui.menuViews->addAction(dock->toggleViewAction());
300
301   inputWidget->setModel(Client::bufferModel());
302   inputWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
303
304   ui.bufferWidget->setFocusProxy(inputWidget);
305 }
306
307 void MainWin::setupTopicWidget() {
308   VerticalDock *dock = new VerticalDock(tr("Topic"), this);
309   dock->setObjectName("TopicDock");
310   TopicWidget *topicwidget = new TopicWidget(dock);
311   connect(topicwidget, SIGNAL(topicChanged(const QString &)), this, SLOT(changeTopic(const QString &)));
312
313   dock->setWidget(topicwidget);
314
315   topicwidget->setModel(Client::bufferModel());
316   topicwidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
317
318   addDockWidget(Qt::TopDockWidgetArea, dock);
319
320   ui.menuViews->addAction(dock->toggleViewAction());
321 }
322
323 void MainWin::setupStatusBar() {
324   connect(Client::instance(), SIGNAL(securedConnection()), this, SLOT(securedConnection()));
325   sslLabel->setPixmap(QPixmap());
326   statusBar()->addPermanentWidget(sslLabel);
327
328   ui.menuViews->addSeparator();
329   QAction *showStatusbar = ui.menuViews->addAction(tr("Statusbar"));
330   showStatusbar->setCheckable(true);
331
332   UiSettings uiSettings;
333
334   bool enabled = uiSettings.value("ShowStatusBar", QVariant(true)).toBool();
335   showStatusbar->setChecked(enabled);
336   enabled ? statusBar()->show() : statusBar()->hide();
337
338   connect(showStatusbar, SIGNAL(toggled(bool)), statusBar(), SLOT(setVisible(bool)));
339   connect(showStatusbar, SIGNAL(toggled(bool)), this, SLOT(saveStatusBarStatus(bool)));
340 }
341
342 void MainWin::saveStatusBarStatus(bool enabled) {
343   UiSettings uiSettings;
344   uiSettings.setValue("ShowStatusBar", enabled);
345 }
346
347 void MainWin::setupSystray() {
348   connect(timer, SIGNAL(timeout()), this, SLOT(makeTrayIconBlink()));
349   connect(Client::instance(), SIGNAL(messageReceived(const Message &)), this, SLOT(receiveMessage(const Message &)));
350
351   systrayMenu = new QMenu(this);
352   systrayMenu->addAction(ui.actionAboutQuassel);
353   systrayMenu->addSeparator();
354   systrayMenu->addAction(ui.actionConnectCore);
355   systrayMenu->addAction(ui.actionDisconnectCore);
356   systrayMenu->addSeparator();
357   systrayMenu->addAction(ui.actionQuit);
358
359   systray->setContextMenu(systrayMenu);
360
361   UiSettings s;
362   if(s.value("UseSystemTrayIcon", QVariant(true)).toBool()) {
363     systray->show();
364   }
365
366 #ifndef Q_WS_MAC
367   connect(systray, SIGNAL(activated( QSystemTrayIcon::ActivationReason )),
368           this, SLOT(systrayActivated( QSystemTrayIcon::ActivationReason )));
369 #endif
370
371 }
372
373 void MainWin::changeEvent(QEvent *event) {
374   if(event->type() == QEvent::WindowStateChange) {
375     if(windowState() & Qt::WindowMinimized) {
376       UiSettings s;
377       if(s.value("UseSystemTrayIcon").toBool() && s.value("MinimizeOnMinimize").toBool()) {
378         toggleVisibility();
379         event->ignore();
380       }
381     }
382   }
383 }
384
385 // FIXME this should be made prettier...
386 void MainWin::changeTopic(const QString &topic) {
387   BufferId id = ui.bufferWidget->currentBuffer();
388   if(!id.isValid()) return;
389   Buffer *buffer = Client::buffer(id);
390   if(buffer) Client::userInput(buffer->bufferInfo(), QString("/topic %1").arg(topic));
391 }
392
393 void MainWin::connectedToCore() {
394   Q_CHECK_PTR(Client::bufferViewManager());
395   connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int)));
396   connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigDeleted(int)), this, SLOT(removeBufferView(int)));
397   connect(Client::bufferViewManager(), SIGNAL(initDone()), this, SLOT(loadLayout()));
398   
399   foreach(BufferInfo id, Client::allBufferInfos()) {
400     Client::backlogManager()->requestBacklog(id.bufferId(), 500, -1);
401   }
402
403   ui.menuViews->setEnabled(true);
404   //ui.menuCore->setEnabled(true);
405   ui.actionConnectCore->setEnabled(false);
406   ui.actionDisconnectCore->setEnabled(true);
407   //ui.actionNetworkList->setEnabled(true);
408   ui.bufferWidget->show();
409   statusBar()->showMessage(tr("Connected to core."));
410   setWindowIcon(onlineTrayIcon);
411   systray->setIcon(onlineTrayIcon);
412   if(sslLabel->width() == 0)
413     sslLabel->setPixmap(QPixmap::fromImage(QImage(":/16x16/status/no-ssl")));
414 }
415
416 void MainWin::loadLayout() {
417   QtUiSettings s;
418   int accountId = Client::currentCoreAccount().toInt();
419   restoreState(s.value(QString("MainWinState-%1").arg(accountId)).toByteArray(), accountId);
420 }
421
422 void MainWin::securedConnection() {
423   // todo: make status bar entry
424   qDebug() << "secured the connection";
425
426   sslLabel->setPixmap(QPixmap::fromImage(QImage(":/16x16/status/ssl")));
427 }
428
429 void MainWin::disconnectedFromCore() {
430   // save core specific layout and remove bufferviews;
431   QtUiSettings s;
432   int accountId = Client::currentCoreAccount().toInt();
433   s.setValue(QString("MainWinState-%1").arg(accountId) , saveState(accountId));
434   QVariant actionData;
435   BufferViewDock *dock;
436   foreach(QAction *action, ui.menuViews->actions()) {
437     actionData = action->data();
438     if(!actionData.isValid())
439       continue;
440     
441     if(actionData.toString() == "__EOBV__")
442       break;
443
444     dock = qobject_cast<BufferViewDock *>(action->parent());
445     if(dock && actionData.toInt() != -1) {
446       removeAction(action);
447       dock->deleteLater();
448     }
449   }
450
451   ui.menuViews->setEnabled(false);
452   //ui.menuCore->setEnabled(false);
453   ui.actionDisconnectCore->setEnabled(false);
454   //ui.actionNetworkList->setEnabled(false);
455   ui.bufferWidget->hide();
456   ui.actionConnectCore->setEnabled(true);
457   // nickListWidget->reset();
458   statusBar()->showMessage(tr("Not connected to core."));
459   setWindowIcon(offlineTrayIcon);
460   systray->setIcon(offlineTrayIcon);
461   sslLabel->setPixmap(QPixmap());
462 }
463
464 AbstractUiMsg *MainWin::layoutMsg(const Message &msg) {
465   return new ChatLineOld(msg);
466 }
467
468 void MainWin::showCoreConnectionDlg(bool autoConnect) {
469   coreConnectDlg = new CoreConnectDlg(this, autoConnect);
470   connect(coreConnectDlg, SIGNAL(finished(int)), this, SLOT(coreConnectionDlgFinished(int)));
471   coreConnectDlg->setModal(true);
472   coreConnectDlg->show();
473 }
474
475 void MainWin::coreConnectionDlgFinished(int /*code*/) {
476   coreConnectDlg->close();
477   //exit(1);
478 }
479
480 void MainWin::showSettingsDlg() {
481   settingsDlg->show();
482 }
483
484 void MainWin::showDebugConsole() {
485   debugConsole->show();
486 }
487
488 void MainWin::showAboutDlg() {
489   AboutDlg dlg(this);
490   dlg.exec();
491 }
492
493 void MainWin::closeEvent(QCloseEvent *event) {
494   UiSettings s;
495   if(s.value("UseSystemTrayIcon").toBool() && s.value("MinimizeOnClose").toBool()) {
496     toggleVisibility();
497     event->ignore();
498   } else {
499     event->accept();
500   }
501 }
502
503 void MainWin::systrayActivated( QSystemTrayIcon::ActivationReason activationReason) {
504   if (activationReason == QSystemTrayIcon::Trigger) {
505     toggleVisibility();
506   }
507 }
508
509 void MainWin::toggleVisibility() {
510   if(isHidden() /*|| !isActiveWindow()*/) {
511     show();
512     if(isMinimized())
513       if (isMaximized())
514         showMaximized();
515       else
516         showNormal();
517
518     raise();
519     activateWindow();
520     // setFocus(); //Qt::ActiveWindowFocusReason
521
522   } else {
523     if(systray->isSystemTrayAvailable ()) {
524       clearFocus();
525       hide();
526       if(!systray->isVisible()) {
527         systray->show();
528       }
529     } else {
530       lower();
531     }
532   }
533 }
534
535 void MainWin::receiveMessage(const Message &msg) {
536   if(QApplication::activeWindow() != 0)
537     return;
538
539   if(msg.flags() & Message::Highlight || msg.bufferInfo().type() == BufferInfo::QueryBuffer) {
540     QString title = msg.bufferInfo().bufferName();;
541     if(msg.bufferInfo().type() != BufferInfo::QueryBuffer) {
542       QString sender = msg.sender();
543       int i = sender.indexOf("!");
544       if(i != -1)
545         sender = sender.left(i);
546       title += QString(" - %1").arg(sender);
547     }
548
549     UiSettings uiSettings;
550
551     if(uiSettings.value("DisplayPopupMessages", QVariant(true)).toBool()) {
552       // FIXME don't invoke style engine for this!
553       QString text = QtUi::style()->styleString(Message::mircToInternal(msg.text())).text;
554       displayTrayIconMessage(title, text);
555     }
556
557     if(uiSettings.value("AnimateTrayIcon", QVariant(true)).toBool()) {
558       QApplication::alert(this);
559       setTrayIconActivity(true);
560     }
561   }
562 }
563
564 bool MainWin::event(QEvent *event) {
565   if(event->type() == QEvent::WindowActivate)
566     setTrayIconActivity(false);
567   return QMainWindow::event(event);
568 }
569
570 void MainWin::displayTrayIconMessage(const QString &title, const QString &message) {
571   systray->showMessage(title, message);
572 }
573
574 void MainWin::setTrayIconActivity(bool active) {
575   if(active) {
576     if(!timer->isActive())
577       timer->start(500);
578   } else {
579     timer->stop();
580     systray->setIcon(onlineTrayIcon);
581   }
582 }
583
584 void MainWin::makeTrayIconBlink() {
585   if(trayIconActive) {
586     systray->setIcon(onlineTrayIcon);
587     trayIconActive = false;
588   } else {
589     systray->setIcon(activeTrayIcon);
590     trayIconActive = true;
591   }
592 }
593
594
595 void MainWin::clientNetworkCreated(NetworkId id) {
596   const Network *net = Client::network(id);
597   QAction *act = new QAction(net->networkName(), this);
598   act->setData(QVariant::fromValue<NetworkId>(id));
599   connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated()));
600   connect(act, SIGNAL(triggered()), this, SLOT(connectOrDisconnectFromNet()));
601   bool inserted = false;
602   for(int i = 0; i < networkActions.count(); i++) {
603     if(net->networkName().localeAwareCompare(networkActions[i]->text()) < 0) {
604       networkActions.insert(i, act);
605       inserted = true;
606       break;
607     }
608   }
609   if(!inserted) networkActions.append(act);
610   ui.menuNetworks->clear();  // why the f*** isn't there a QMenu::insertAction()???
611   foreach(QAction *a, networkActions) ui.menuNetworks->addAction(a);
612   ui.menuNetworks->addSeparator();
613   ui.menuNetworks->addAction(actionEditNetworks);
614 }
615
616 void MainWin::clientNetworkUpdated() {
617   const Network *net = qobject_cast<const Network *>(sender());
618   if(!net) return;
619   foreach(QAction *a, networkActions) {
620     if(a->data().value<NetworkId>() == net->networkId()) {
621       a->setText(net->networkName());
622       if(net->connectionState() == Network::Initialized) {
623         a->setIcon(QIcon(":/16x16/actions/network-connect"));
624         //a->setEnabled(true);
625       } else if(net->connectionState() == Network::Disconnected) {
626         a->setIcon(QIcon(":/16x16/actions/network-disconnect"));
627         //a->setEnabled(true);
628       } else {
629         a->setIcon(QIcon(":/16x16/actions/gear"));
630         //a->setEnabled(false);
631       }
632       return;
633     }
634   }
635 }
636
637 void MainWin::clientNetworkRemoved(NetworkId id) {
638   QList<QAction *>::iterator actionIter = networkActions.begin();;
639   QAction *action;
640   while(actionIter != networkActions.end()) {
641     action = *actionIter;
642     if(action->data().value<NetworkId>() == id) {
643       action->deleteLater();
644       actionIter = networkActions.erase(actionIter);
645     } else
646       actionIter++;
647   }
648 }
649
650 void MainWin::connectOrDisconnectFromNet() {
651   QAction *act = qobject_cast<QAction *>(sender());
652   if(!act) return;
653   const Network *net = Client::network(act->data().value<NetworkId>());
654   if(!net) return;
655   if(net->connectionState() == Network::Disconnected) net->requestConnect();
656   else net->requestDisconnect();
657 }
658