Lots of additions again. Working on implementing commands and prettifying the output.
[quassel.git] / gui / channelwidget.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 "channelwidget.h"
22 #include "guiproxy.h"
23
24 #include <QtGui>
25 #include <iostream>
26
27 ChannelWidget::ChannelWidget(QString netname, QString bufname, QString own, QWidget *parent) : QWidget(parent) {
28   ui.setupUi(this);
29   _networkName = netname;
30   _bufferName = bufname;
31   ui.ownNick->clear();
32   ui.ownNick->addItem(own);
33   if(bufname.isEmpty()) {
34     // Server Buffer
35     ui.nickTree->hide();
36     ui.topicEdit->hide();
37     ui.chanSettingsButton->hide();
38   }
39   connect(ui.inputEdit, SIGNAL(returnPressed()), this, SLOT(enterPressed()));
40   //ui.inputEdit->setFocus();
41
42   // Define standard colors
43   stdCol = QColor("black");
44   noticeCol = QColor("darkblue");
45   serverCol = QColor("darkblue");
46   errorCol = QColor("red");
47   joinCol = QColor("green");
48   quitCol = QColor("firebrick");
49   partCol = QColor("firebrick");
50   
51 }
52
53 void ChannelWidget::enterPressed() {
54   emit sendInput(networkName(), bufferName(), ui.inputEdit->text());
55   ui.inputEdit->clear();
56 }
57
58 void ChannelWidget::recvMessage(Message msg) {
59   QString s;
60   QColor c = stdCol;
61   switch(msg.type) {
62     case Message::Msg:
63       c = stdCol; s = QString("<%1> %2").arg(msg.sender).arg(msg.msg);
64       break;
65     case Message::Server:
66       c = serverCol; s = msg.msg;
67       break;
68     case Message::Error:
69       c = errorCol; s = msg.msg;
70       break;
71     case Message::Join:
72       c = joinCol; s = msg.msg;
73       break;
74     default:
75       c = stdCol; s = QString("[%1] %2").arg(msg.sender).arg(msg.msg);
76       break;
77   }
78   ui.chatWidget->setTextColor(c);
79   ui.chatWidget->insertPlainText(QString("[%2] %1\n").arg(s).arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss")));
80   //ui.chatWidget->insertHtml(QString("<table><tr><td>[12:13]</td><td width=20><div align=right>[nickname]</div></td><td>This is the Message!</td></tr>"
81   //    "<tr><td>[12:13]</td><td><div align=right>[nick]</div></td><td>This is the Message!</td></tr>"
82   //    "<tr><td>[12:13]</td><td><div align=right>[looongnickname]</div></td><td>This is the Message!</td></tr>"
83   //    "<tr><td>[12:13]</td><td><div align=right>[nickname]</div></td><td>This is the Message!</td></tr></table>"
84   //                                 ));
85   ui.chatWidget->ensureCursorVisible();
86 }
87
88 void ChannelWidget::recvStatusMsg(QString msg) {
89   ui.chatWidget->insertPlainText(QString("[STATUS] %1").arg(msg));
90   ui.chatWidget->ensureCursorVisible();
91 }
92
93 void ChannelWidget::setTopic(QString topic) {
94   ui.topicEdit->setText(topic);
95 }
96
97 void ChannelWidget::setNicks(QStringList nicks) {
98
99
100 }
101
102 void ChannelWidget::addNick(QString nick, VarMap props) {
103   nicks[nick] = props;
104   updateNickList();
105 }
106
107 void ChannelWidget::updateNick(QString nick, VarMap props) {
108   nicks[nick] = props;
109   updateNickList();
110 }
111
112 void ChannelWidget::removeNick(QString nick) {
113   nicks[nick].toMap().remove(nick);
114   updateNickList();
115 }
116
117 void ChannelWidget::setOwnNick(QString nick) {
118   ui.ownNick->clear();
119   ui.ownNick->addItem(nick);
120 }
121
122 void ChannelWidget::updateNickList() {
123   ui.nickTree->clear();
124   if(nicks.count() != 1) ui.nickTree->setHeaderLabel(tr("%1 Users").arg(nicks.count()));
125   else ui.nickTree->setHeaderLabel(tr("1 User"));
126   QTreeWidgetItem *ops = new QTreeWidgetItem();
127   QTreeWidgetItem *voiced = new QTreeWidgetItem();
128   QTreeWidgetItem *users = new QTreeWidgetItem();
129   // To sort case-insensitive, we have to put all nicks in a map which is sorted by (lowercase) key...
130   QMap<QString, QString> sorted;
131   foreach(QString n, nicks.keys()) { sorted[n.toLower()] = n; }
132   foreach(QString n, sorted.keys()) {
133     QString nick = sorted[n];
134     QString mode = nicks[nick].toMap()["Channels"].toMap()[bufferName()].toMap()["Mode"].toString();
135     if(mode.contains('o')) { new QTreeWidgetItem(ops, QStringList(QString("@%1").arg(nick))); }
136     else if(mode.contains('v')) { new QTreeWidgetItem(voiced, QStringList(QString("+%1").arg(nick))); }
137     else new QTreeWidgetItem(users, QStringList(nick));
138   }
139   if(ops->childCount()) {
140     ops->setText(0, tr("%1 Operators").arg(ops->childCount()));
141    ui.nickTree->addTopLevelItem(ops);
142     ops->setExpanded(true);
143   } else delete ops;
144   if(voiced->childCount()) {
145     voiced->setText(0, tr("%1 Voiced").arg(voiced->childCount()));
146     ui.nickTree->addTopLevelItem(voiced);
147     voiced->setExpanded(true);
148   } else delete voiced;
149   if(users->childCount()) {
150     users->setText(0, tr("%1 Users").arg(users->childCount()));
151     ui.nickTree->addTopLevelItem(users);
152     users->setExpanded(true);
153   } else delete users;
154 }
155 /**********************************************************************************************/
156
157
158 IrcWidget::IrcWidget(QWidget *parent) : QWidget(parent) {
159   ui.setupUi(this);
160   ui.tabWidget->removeTab(0);
161
162   connect(guiProxy, SIGNAL(csDisplayMsg(QString, QString, Message)), this, SLOT(recvMessage(QString, QString, Message)));
163   connect(guiProxy, SIGNAL(csDisplayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString)));
164   connect(guiProxy, SIGNAL(csTopicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString)));
165   connect(guiProxy, SIGNAL(csSetNicks(QString, QString, QStringList)), this, SLOT(setNicks(QString, QString, QStringList)));
166   connect(guiProxy, SIGNAL(csNickAdded(QString, QString, VarMap)), this, SLOT(addNick(QString, QString, VarMap)));
167   connect(guiProxy, SIGNAL(csNickRemoved(QString, QString)), this, SLOT(removeNick(QString, QString)));
168   connect(guiProxy, SIGNAL(csNickUpdated(QString, QString, VarMap)), this, SLOT(updateNick(QString, QString, VarMap)));
169   connect(guiProxy, SIGNAL(csOwnNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString)));
170   connect(this, SIGNAL(sendInput( QString, QString, QString )), guiProxy, SLOT(gsUserInput(QString, QString, QString)));
171 }
172
173 ChannelWidget * IrcWidget::getBuffer(QString net, QString buf) {
174   QString key = net + buf;
175   if(!buffers.contains(key)) {
176     ChannelWidget *cw = new ChannelWidget(net, buf, ownNick);
177     connect(cw, SIGNAL(sendInput(QString, QString, QString)), this, SLOT(userInput(QString, QString, QString)));
178     ui.tabWidget->addTab(cw, net+buf);
179     ui.tabWidget->setCurrentWidget(cw);
180     //cw->setFocus();
181     buffers[key] = cw;
182   }
183   return buffers[key];
184 }
185
186
187 void IrcWidget::recvMessage(QString net, QString buf, Message msg) {
188   ChannelWidget *cw = getBuffer(net, buf);
189   cw->recvMessage(msg);
190 }
191
192 void IrcWidget::recvStatusMsg(QString net, QString msg) {
193   recvMessage(net, "", QString("[STATUS] %1").arg(msg));
194
195 }
196
197 void IrcWidget::userInput(QString net, QString buf, QString msg) {
198   emit sendInput(net, buf, msg);
199 }
200
201 void IrcWidget::setTopic(QString net, QString buf, QString topic) {
202   ChannelWidget *cw = getBuffer(net, buf);
203   cw->setTopic(topic);
204 }
205
206 void IrcWidget::setNicks(QString net, QString buf, QStringList nicks) {
207   ChannelWidget *cw = getBuffer(net, buf);
208   cw->setNicks(nicks);
209 }
210
211 void IrcWidget::addNick(QString net, QString nick, VarMap props) {
212   nicks[net].toMap()[nick] = props;
213   VarMap chans = props["Channels"].toMap();
214   QStringList c = chans.keys();
215   foreach(QString bufname, c) {
216     getBuffer(net, bufname)->addNick(nick, props);
217   }
218 }
219
220 void IrcWidget::updateNick(QString net, QString nick, VarMap props) {
221   QStringList oldchans = nicks[net].toMap()[nick].toMap()["Channels"].toMap().keys();
222   QStringList newchans = props["Channels"].toMap().keys();
223   foreach(QString c, newchans) {
224     if(oldchans.contains(c)) getBuffer(net, c)->updateNick(nick, props);
225     else getBuffer(net, c)->addNick(nick, props);
226   }
227   foreach(QString c, oldchans) {
228     if(!newchans.contains(c)) getBuffer(net, c)->removeNick(nick);
229   }
230   nicks[net].toMap()[nick] = props;
231 }
232
233 void IrcWidget::removeNick(QString net, QString nick) {
234   VarMap chans = nicks[net].toMap()[nick].toMap()["Channels"].toMap();
235   foreach(QString bufname, chans.keys()) {
236     getBuffer(net, bufname)->removeNick(nick);
237   }
238   qDebug() << nicks;
239   nicks[net].toMap().remove(nick);
240   qDebug() << nicks;
241 }
242
243 void IrcWidget::setOwnNick(QString net, QString nick) {
244   ownNick = nick;
245   foreach(ChannelWidget *cw, buffers.values()) {
246     if(cw->networkName() == net) cw->setOwnNick(nick);
247   }
248 }
249