Merged changes from branch "sput" r50:55 back into trunk.
[quassel.git] / gui / buffer.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005/06 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 "buffer.h"
22 #include "util.h"
23 #include "chatwidget.h"
24
25 Buffer::Buffer(QString netname, QString bufname) {
26   networkName = netname;
27   bufferName = bufname;
28
29   widget = 0;
30   chatWidget = 0;
31   contentsWidget = 0;
32   active = false;
33 }
34
35 Buffer::~Buffer() {
36   delete widget;
37   delete chatWidget;
38 }
39
40 void Buffer::setActive(bool a) {
41   if(a != active) {
42     active = a;
43     if(widget) widget->setActive(a);
44   }
45 }
46
47 void Buffer::displayMsg(Message msg) {
48   contents.append(msg);
49   if(widget) widget->displayMsg(msg);
50 }
51
52 void Buffer::userInput(QString msg) {
53   emit userInput(networkName, bufferName, msg);
54 }
55
56 /* FIXME do we need this? */
57 void Buffer::scrollToEnd() {
58   if(!widget) return;
59   //widget->scrollToEnd();
60 }
61
62 QWidget * Buffer::showWidget(QWidget *parent) {
63
64   if(widget) {
65     return qobject_cast<QWidget*>(widget);
66   }
67
68   if(!contentsWidget) {
69     contentsWidget = new ChatWidgetContents(networkName, bufferName, 0);
70     contentsWidget->hide();
71     /* FIXME do we need this? */
72     for(int i = 0; i < contents.count(); i++) {
73       contentsWidget->appendMsg(contents[i]);
74     }
75   }
76   contentsWidget->hide();
77   widget = new BufferWidget(networkName, bufferName, isActive(), ownNick, contentsWidget, this, parent);
78   widget->setTopic(topic);
79   widget->updateNickList(nicks);
80   connect(widget, SIGNAL(userInput(QString)), this, SLOT(userInput(QString)));
81   return qobject_cast<QWidget*>(widget);
82 }
83
84 void Buffer::hideWidget() {
85   delete widget;
86   widget = 0;
87 }
88
89 void Buffer::deleteWidget() {
90   widget = 0;
91 }
92
93 QWidget * Buffer::getWidget() {
94   return qobject_cast<QWidget*>(widget);
95 }
96
97 void Buffer::setTopic(QString t) {
98   topic = t;
99   if(widget) widget->setTopic(t);
100 }
101
102 void Buffer::addNick(QString nick, VarMap props) {
103   if(nick == ownNick) setActive(true);
104   nicks[nick] = props;
105   if(widget) widget->updateNickList(nicks);
106 }
107
108 void Buffer::updateNick(QString nick, VarMap props) {
109   nicks[nick] = props;
110   if(widget) widget->updateNickList(nicks);
111 }
112
113 void Buffer::renameNick(QString oldnick, QString newnick) {
114   QVariant v = nicks.take(oldnick);
115   nicks[newnick] = v;
116   if(widget) widget->updateNickList(nicks);
117 }
118
119 void Buffer::removeNick(QString nick) {
120   if(nick == ownNick) setActive(false);
121   nicks.remove(nick);
122   if(widget) widget->updateNickList(nicks);
123 }
124
125 void Buffer::setOwnNick(QString nick) {
126   ownNick = nick;
127   if(widget) widget->setOwnNick(nick);
128 }
129
130 /****************************************************************************************/
131
132
133
134 /****************************************************************************************/
135
136 BufferWidget::BufferWidget(QString netname, QString bufname, bool act, QString own, ChatWidgetContents *contents, Buffer *pBuf, QWidget *parent) : QWidget(parent) {
137   ui.setupUi(this);
138   networkName = netname;
139   bufferName = bufname;
140   active = act;
141   parentBuffer = pBuf;
142
143   ui.chatWidget->init(netname, bufname, contents);
144
145   ui.ownNick->clear();
146   ui.ownNick->addItem(own);
147   if(bufname.isEmpty()) {
148     // Server Buffer
149     ui.nickTree->hide();
150     ui.topicEdit->hide();
151     ui.chanSettingsButton->hide();
152   }
153   connect(ui.nickTree, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(itemExpansionChanged(QTreeWidgetItem*)));
154   connect(ui.nickTree, SIGNAL(itemCollapsed(QTreeWidgetItem *)), this, SLOT(itemExpansionChanged(QTreeWidgetItem*)));
155   connect(ui.inputEdit, SIGNAL(returnPressed()), this, SLOT(enterPressed()));
156
157   opsExpanded = voicedExpanded = usersExpanded = true;
158
159   ui.chatWidget->setFocusProxy(ui.inputEdit);
160   updateTitle();
161 }
162
163 BufferWidget::~BufferWidget() {
164   ui.chatWidget->takeWidget();   /* remove ownership so the chatwidget contents does not get destroyed */
165   parentBuffer->deleteWidget();  /* make sure the parent buffer knows we are gone */
166 }
167
168 void BufferWidget::updateTitle() {
169   QString title = QString("%1 in %2 [%3]: %4").arg(ui.ownNick->currentText()).arg(bufferName).arg(networkName).arg(ui.topicEdit->text());
170   setWindowTitle(title);
171 }
172
173 void BufferWidget::enterPressed() {
174   QStringList lines = ui.inputEdit->text().split('\n', QString::SkipEmptyParts);
175   foreach(QString msg, lines) {
176     if(msg.isEmpty()) continue;
177     emit userInput(msg);
178   }
179   ui.inputEdit->clear();
180 }
181
182 void BufferWidget::setActive(bool act) {
183   if(act != active) {
184     active = act;
185     //renderContents();
186     //scrollToEnd();
187   }
188 }
189
190 void BufferWidget::displayMsg(Message msg) {
191   ui.chatWidget->appendMsg(msg);
192 }
193
194 void BufferWidget::setOwnNick(QString nick) {
195   ui.ownNick->clear();
196   ui.ownNick->addItem(nick);
197   updateTitle();
198 }
199
200 void BufferWidget::setTopic(QString topic) {
201   ui.topicEdit->setText(topic);
202   updateTitle();
203 }
204
205 void BufferWidget::updateNickList(VarMap nicks) {
206   ui.nickTree->clear();
207   if(nicks.count() != 1) ui.nickTree->setHeaderLabel(tr("%1 Users").arg(nicks.count()));
208   else ui.nickTree->setHeaderLabel(tr("1 User"));
209   QTreeWidgetItem *ops = new QTreeWidgetItem();
210   QTreeWidgetItem *voiced = new QTreeWidgetItem();
211   QTreeWidgetItem *users = new QTreeWidgetItem();
212   // To sort case-insensitive, we have to put all nicks in a map which is sorted by (lowercase) key...
213   QMap<QString, QString> sorted;
214   foreach(QString n, nicks.keys()) { sorted[n.toLower()] = n; }
215   foreach(QString n, sorted.keys()) {
216     QString nick = sorted[n];
217     QString mode = nicks[nick].toMap()["Channels"].toMap()[bufferName].toMap()["Mode"].toString();
218     if(mode.contains('o')) { new QTreeWidgetItem(ops, QStringList(QString("@%1").arg(nick))); }
219     else if(mode.contains('v')) { new QTreeWidgetItem(voiced, QStringList(QString("+%1").arg(nick))); }
220     else new QTreeWidgetItem(users, QStringList(nick));
221   }
222   if(ops->childCount()) {
223     ops->setText(0, tr("%1 Operators").arg(ops->childCount()));
224     ui.nickTree->addTopLevelItem(ops);
225     ops->setExpanded(opsExpanded);
226   } else delete ops;
227   if(voiced->childCount()) {
228     voiced->setText(0, tr("%1 Voiced").arg(voiced->childCount()));
229     ui.nickTree->addTopLevelItem(voiced);
230     voiced->setExpanded(voicedExpanded);
231   } else delete voiced;
232   if(users->childCount()) {
233     users->setText(0, tr("%1 Users").arg(users->childCount()));
234     ui.nickTree->addTopLevelItem(users);
235     users->setExpanded(usersExpanded);
236   } else delete users;
237 }
238
239 void BufferWidget::itemExpansionChanged(QTreeWidgetItem *item) {
240   if(item->child(0)->text(0).startsWith('@')) opsExpanded = item->isExpanded();
241   else if(item->child(0)->text(0).startsWith('+')) voicedExpanded = item->isExpanded();
242   else usersExpanded = item->isExpanded();
243 }
244