Merged changes from branch "sput" r50:55 back into trunk.
[quassel.git] / gui / mainwin.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005 by The Quassel Team                                *
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) any later version.                                   *
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
21 #include <QtGui>
22 #include <QtCore>
23
24 #include "global.h"
25 #include "message.h"
26 #include "guiproxy.h"
27
28 #include "mainwin.h"
29 #include "buffer.h"
30 #include "networkview.h"
31 #include "serverlist.h"
32 #include "coreconnectdlg.h"
33 #include "settings.h"
34
35 MainWin::MainWin() : QMainWindow() {
36   ui.setupUi(this);
37   widget = 0;
38
39   setWindowTitle("Quassel IRC");
40   setWindowIcon(QIcon(":/qirc-icon.png"));
41   setWindowIconText("Quassel IRC");
42
43   QSettings s;
44   s.beginGroup("Geometry");
45   resize(s.value("MainWinSize", QSize(500, 400)).toSize());
46   move(s.value("MainWinPos", QPoint(50, 50)).toPoint());
47   s.endGroup();
48
49   //workspace = new QWorkspace(this);
50   //setCentralWidget(workspace);
51   statusBar()->showMessage(tr("Waiting for core..."));
52
53   netView = new NetworkView("", this);
54   netView->setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea);
55   addDockWidget(Qt::LeftDockWidgetArea, netView);
56   connect(netView, SIGNAL(bufferSelected(QString, QString)), this, SLOT(showBuffer(QString, QString)));
57   connect(this, SIGNAL(bufferSelected(QString, QString)), netView, SLOT(selectBuffer(QString, QString)));
58
59   connect(guiProxy, SIGNAL(csServerState(QString, QVariant)), this, SLOT(recvNetworkState(QString, QVariant)));
60   connect(guiProxy, SIGNAL(csServerConnected(QString)), this, SLOT(networkConnected(QString)));
61   connect(guiProxy, SIGNAL(csServerDisconnected(QString)), this, SLOT(networkDisconnected(QString)));
62   connect(guiProxy, SIGNAL(csDisplayMsg(QString, Message)), this, SLOT(recvMessage(QString, Message)));
63   connect(guiProxy, SIGNAL(csDisplayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString)));
64   connect(guiProxy, SIGNAL(csTopicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString)));
65   connect(guiProxy, SIGNAL(csSetNicks(QString, QString, QStringList)), this, SLOT(setNicks(QString, QString, QStringList)));
66   connect(guiProxy, SIGNAL(csNickAdded(QString, QString, VarMap)), this, SLOT(addNick(QString, QString, VarMap)));
67   connect(guiProxy, SIGNAL(csNickRemoved(QString, QString)), this, SLOT(removeNick(QString, QString)));
68   connect(guiProxy, SIGNAL(csNickRenamed(QString, QString, QString)), this, SLOT(renameNick(QString, QString, QString)));
69   connect(guiProxy, SIGNAL(csNickUpdated(QString, QString, VarMap)), this, SLOT(updateNick(QString, QString, VarMap)));
70   connect(guiProxy, SIGNAL(csOwnNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString)));
71   connect(this, SIGNAL(sendInput( QString, QString, QString )), guiProxy, SLOT(gsUserInput(QString, QString, QString)));
72
73   show();
74   syncToCore();
75   statusBar()->showMessage(tr("Ready."));
76
77   buffersUpdated();
78
79   serverListDlg = new ServerListDlg(this);
80   serverListDlg->setVisible(serverListDlg->showOnStartup());
81   settingsDlg = new SettingsDlg(this);
82   settingsDlg->setVisible(false);
83   setupMenus();
84
85   // replay backlog
86   foreach(QString net, coreBackLog.keys()) {
87     while(coreBackLog[net].count()) {
88       recvMessage(net, coreBackLog[net].takeFirst());
89     }
90   }
91   /*
92   foreach(QString key, buffers.keys()) {
93     foreach(Buffer *b, buffers[key].values()) {
94       QWidget *widget = b->showWidget(this);
95       workspace->addWindow(widget);
96       widget->show();
97     }
98   }
99   */
100   s.beginGroup("Buffers");
101   QString net = s.value("CurrentNetwork", "").toString();
102   QString buf = s.value("CurrentBuffer", "").toString();
103   s.endGroup();
104   if(!net.isEmpty()) {
105     if(buffers.contains(net)) {
106       if(buffers[net].contains(buf)) {
107         showBuffer(net, buf);
108       } else {
109         showBuffer(net, "");
110       }
111     }
112   }
113 }
114
115 void MainWin::setupMenus() {
116   connect(ui.actionNetworkList, SIGNAL(triggered()), this, SLOT(showServerList()));
117   connect(ui.actionEditIdentities, SIGNAL(triggered()), serverListDlg, SLOT(editIdentities()));
118   connect(ui.actionSettingsDlg, SIGNAL(triggered()), this, SLOT(showSettingsDlg()));
119   ui.actionSettingsDlg->setEnabled(false);
120 }
121
122 void MainWin::showServerList() {
123 //  if(!serverListDlg) {
124 //    serverListDlg = new ServerListDlg(this);
125 //  }
126   serverListDlg->show();
127 }
128
129 void MainWin::showSettingsDlg() {
130   settingsDlg->show();
131 }
132
133 void MainWin::closeEvent(QCloseEvent *event)
134 {
135   //if (userReallyWantsToQuit()) {
136     QSettings s;
137     s.beginGroup("Geometry");
138     s.setValue("MainWinSize", size());
139     s.setValue("MainWinPos", pos());
140     s.endGroup();
141     s.beginGroup("Buffers");
142     s.setValue("CurrentNetwork", currentNetwork);
143     s.setValue("CurrentBuffer", currentBuffer);
144     s.endGroup();
145     event->accept();
146   //} else {
147     //event->ignore();
148   //}
149 }
150
151 void MainWin::showBuffer(QString net, QString buf) {
152   currentBuffer = buf; currentNetwork = net;
153   Buffer *b = getBuffer(net, buf);
154   QWidget *old = widget;
155   widget = b->showWidget(this);
156   if(widget == old) return;
157   //workspace->addWindow(widget);
158   //widget->show();
159   setCentralWidget(widget);
160   widget->show();
161   //workspace->setActiveWindow(widget);
162   widget->setFocus();
163   //workspace->setFocus();
164   widget->activateWindow();
165   widget->setFocus(Qt::MouseFocusReason);
166   focusNextChild();
167   //workspace->tile();
168   emit bufferSelected(net, buf);
169 }
170
171 void MainWin::networkConnected(QString net) {
172   connected[net] = true;
173   Buffer *b = getBuffer(net, "");
174   b->setActive(true);
175   b->displayMsg(Message::server("", tr("Connected.")));
176   buffersUpdated();
177 }
178
179 void MainWin::networkDisconnected(QString net) {
180   //getBuffer(net, "")->setActive(false);
181   foreach(QString buf, buffers[net].keys()) {
182     Buffer *b = getBuffer(net, buf);
183     b->displayMsg(Message::server(buf, tr("Server disconnected.")));
184     b->setActive(false);
185
186   }
187   connected[net] = false;
188 }
189
190 Buffer * MainWin::getBuffer(QString net, QString buf) {
191   if(!buffers[net].contains(buf)) {
192     Buffer *b = new Buffer(net, buf);
193     b->setOwnNick(ownNick[net]);
194     connect(b, SIGNAL(userInput(QString, QString, QString)), this, SLOT(userInput(QString, QString, QString)));
195     buffers[net][buf] = b;
196     buffersUpdated();
197   }
198   return buffers[net][buf];
199 }
200
201 void MainWin::buffersUpdated() {
202   netView->buffersUpdated(buffers);
203 }
204
205 void MainWin::recvNetworkState(QString net, QVariant state) {
206   connected[net] = true;
207   setOwnNick(net, state.toMap()["OwnNick"].toString());
208   getBuffer(net, "")->setActive(true);
209   VarMap t = state.toMap()["Topics"].toMap();
210   VarMap n = state.toMap()["Nicks"].toMap();
211   foreach(QString buf, t.keys()) {
212     getBuffer(net, buf)->setActive(true);
213     setTopic(net, buf, t[buf].toString());
214   }
215   foreach(QString nick, n.keys()) {
216     addNick(net, nick, n[nick].toMap());
217   }
218   buffersUpdated();
219 }
220
221 void MainWin::recvMessage(QString net, Message msg) {
222   Buffer *b = getBuffer(net, msg.target);
223   b->displayMsg(msg);
224 }
225
226 void MainWin::recvStatusMsg(QString net, QString msg) {
227   recvMessage(net, Message::server("", QString("[STATUS] %1").arg(msg)));
228
229 }
230
231 void MainWin::userInput(QString net, QString buf, QString msg) {
232   emit sendInput(net, buf, msg);
233 }
234
235 void MainWin::setTopic(QString net, QString buf, QString topic) {
236   if(!connected[net]) return;
237   Buffer *b = getBuffer(net, buf);
238   b->setTopic(topic);
239   buffersUpdated();
240   //if(!b->isActive()) {
241   //  b->setActive(true);
242   //  buffersUpdated();
243   //}
244 }
245
246 void MainWin::setNicks(QString net, QString buf, QStringList nicks) {
247   Q_ASSERT(false);
248 }
249
250 void MainWin::addNick(QString net, QString nick, VarMap props) {
251   if(!connected[net]) return;
252   nicks[net][nick] = props;
253   VarMap chans = props["Channels"].toMap();
254   QStringList c = chans.keys();
255   foreach(QString bufname, c) {
256     getBuffer(net, bufname)->addNick(nick, props);
257   }
258   buffersUpdated();
259 }
260
261 void MainWin::renameNick(QString net, QString oldnick, QString newnick) {
262   if(!connected[net]) return;
263   QStringList chans = nicks[net][oldnick]["Channels"].toMap().keys();
264   foreach(QString c, chans) {
265     getBuffer(net, c)->renameNick(oldnick, newnick);
266   }
267   nicks[net][newnick] = nicks[net].take(oldnick);
268 }
269
270 void MainWin::updateNick(QString net, QString nick, VarMap props) {
271   if(!connected[net]) return;
272   QStringList oldchans = nicks[net][nick]["Channels"].toMap().keys();
273   QStringList newchans = props["Channels"].toMap().keys();
274   foreach(QString c, newchans) {
275     if(oldchans.contains(c)) getBuffer(net, c)->updateNick(nick, props);
276     else getBuffer(net, c)->addNick(nick, props);
277   }
278   foreach(QString c, oldchans) {
279     if(!newchans.contains(c)) getBuffer(net, c)->removeNick(nick);
280   }
281   nicks[net][nick] = props;
282   buffersUpdated();
283 }
284
285 void MainWin::removeNick(QString net, QString nick) {
286   if(!connected[net]) return;
287   VarMap chans = nicks[net][nick]["Channels"].toMap();
288   foreach(QString bufname, chans.keys()) {
289     getBuffer(net, bufname)->removeNick(nick);
290   }
291   nicks[net].remove(nick);
292   buffersUpdated();
293 }
294
295 void MainWin::setOwnNick(QString net, QString nick) {
296   if(!connected[net]) return;
297   ownNick[net] = nick;
298   foreach(Buffer *b, buffers[net].values()) {
299     b->setOwnNick(nick);
300   }
301 }
302