4b439687698cfc05611ef564d4cde1d53aade61e
[quassel.git] / src / qtui / bufferwidget.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
21 #include "bufferwidget.h"
22 #include "buffer.h"
23 #include "chatline-old.h"
24 #include "chatwidget.h"
25 #include "settings.h"
26 #include "client.h"
27 #include "identity.h"
28 #include "network.h"
29 #include "networkmodel.h"
30
31 BufferWidget::BufferWidget(QWidget *parent)
32   : QWidget(parent),
33     _bufferModel(0),
34     _selectionModel(0)
35 {
36   ui.setupUi(this);
37   ui.ownNick->clear();  // TODO add nick history
38   connect(ui.inputEdit, SIGNAL(returnPressed()), this, SLOT(enterPressed()));
39   connect(ui.ownNick, SIGNAL(activated(QString)), this, SLOT(changeNick(QString)));
40 }
41
42 BufferWidget::~BufferWidget() {
43 }
44
45 void BufferWidget::init() {
46 }
47
48 void BufferWidget::setModel(BufferModel *bufferModel) {
49   if(_bufferModel) {
50     disconnect(_bufferModel, 0, this, 0);
51   }
52   _bufferModel = bufferModel;
53   connect(bufferModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
54           this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
55 }
56
57 void BufferWidget::setSelectionModel(QItemSelectionModel *selectionModel) {
58   if(_selectionModel) {
59     disconnect(_selectionModel, 0, this, 0);
60   }
61   _selectionModel = selectionModel;
62   connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
63           this, SLOT(currentChanged(QModelIndex, QModelIndex)));
64 }
65
66 void BufferWidget::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) {
67   Q_ASSERT(model());
68   if(!parent.isValid()) {
69     // ok this means that whole networks are about to be removed
70     // we can't determine which buffers are affect, so we hope that all nets are removed
71     // this is the most common case (for example disconnecting from the core or terminating the clint)
72     if(model()->rowCount(parent) != end - start + 1)
73       return;
74
75     ChatWidget *chatWidget;
76     QHash<BufferId, ChatWidget *>::iterator iter = _chatWidgets.begin();
77     while(iter != _chatWidgets.end()) {
78       chatWidget = *iter;
79       iter = _chatWidgets.erase(iter);
80       ui.stackedWidget->removeWidget(chatWidget);
81       chatWidget->deleteLater();
82     }
83     
84   } else {
85     // check if there are explicitly buffers removed
86     for(int i = start; i <= end; i++) {
87       QVariant variant = parent.child(i,0).data(NetworkModel::BufferIdRole);
88       if(!variant.isValid())
89         continue;
90       
91       BufferId bufferId = qVariantValue<BufferId>(variant);
92       removeBuffer(bufferId);
93     }
94   }
95 }
96
97 void BufferWidget::removeBuffer(BufferId bufferId) {
98   if(!_chatWidgets.contains(bufferId))
99     return;
100
101   ChatWidget *chatWidget = _chatWidgets.take(bufferId);
102   ui.stackedWidget->removeWidget(chatWidget);
103   chatWidget->deleteLater();
104 }
105
106 void BufferWidget::currentChanged(const QModelIndex &current, const QModelIndex &previous) {
107   Q_UNUSED(previous);
108   QVariant variant;
109
110   variant = current.data(NetworkModel::BufferIdRole);
111   if(!variant.isValid())
112     return;
113   
114   setCurrentBuffer(qVariantValue<BufferId>(variant));
115   updateNickSelector();
116 }
117
118 void BufferWidget::setCurrentBuffer(BufferId bufferId) {
119   ChatWidget *chatWidget;
120   if(_chatWidgets.contains(bufferId)) {
121      chatWidget = _chatWidgets[bufferId];
122   } else {
123     Buffer *buf = Client::buffer(bufferId);
124     if(!buf) {
125       qWarning() << "BufferWidget::setBuffer(BufferId): Can't show unknown Buffer:" << bufferId;
126       return;
127     }
128     chatWidget = new ChatWidget(this);
129     chatWidget->init(bufferId);
130     QList<ChatLine *> lines;
131     QList<AbstractUiMsg *> msgs = buf->contents();
132     foreach(AbstractUiMsg *msg, msgs) {
133       lines.append(dynamic_cast<ChatLine*>(msg));
134     }
135     chatWidget->setContents(lines);
136     connect(buf, SIGNAL(msgAppended(AbstractUiMsg *)), chatWidget, SLOT(appendMsg(AbstractUiMsg *)));
137     connect(buf, SIGNAL(msgPrepended(AbstractUiMsg *)), chatWidget, SLOT(prependMsg(AbstractUiMsg *)));
138     _chatWidgets[bufferId] = chatWidget;
139     ui.stackedWidget->addWidget(chatWidget);
140   }
141   ui.stackedWidget->setCurrentWidget(chatWidget);
142   disconnect(this, SIGNAL(userInput(QString)), 0, 0);
143   connect(this, SIGNAL(userInput(QString)), Client::buffer(bufferId), SLOT(processUserInput(QString)));
144   chatWidget->setFocusProxy(ui.inputEdit);
145   ui.inputEdit->setFocus();
146
147 }
148
149 const Network *BufferWidget::currentNetwork() const {
150   if(!selectionModel())
151     return 0;
152
153   QVariant variant = selectionModel()->currentIndex().data(NetworkModel::NetworkIdRole);
154   if(!variant.isValid())
155     return 0;
156
157   return Client::network(variant.value<NetworkId>());
158 }
159
160 void BufferWidget::updateNickSelector() const {
161   const Network *net = currentNetwork();
162   if(!net)
163     return;
164
165   const Identity *identity = Client::identity(net->identity());
166   if(!identity) {
167     qWarning() << "BufferWidget::setCurrentNetwork(): can't find Identity for Network" << net->networkId();
168     return;
169   }
170
171   int nickIdx;
172   QStringList nicks = identity->nicks();
173   if((nickIdx = nicks.indexOf(net->myNick())) == -1) {
174     nicks.prepend(net->myNick());
175     nickIdx = 0;
176   }
177   
178   ui.ownNick->clear();
179   ui.ownNick->addItems(nicks);
180   ui.ownNick->setCurrentIndex(nickIdx);
181 }
182
183 void BufferWidget::changeNick(const QString &newNick) const {
184   const Network *net = currentNetwork();
185   if(!net || net->isMyNick(newNick))
186     return;
187   emit userInput(QString("/nick %1").arg(newNick));
188 }
189
190 void BufferWidget::enterPressed() {
191   QStringList lines = ui.inputEdit->text().split('\n', QString::SkipEmptyParts);
192   foreach(QString msg, lines) {
193     if(msg.isEmpty()) continue;
194     emit userInput(msg);
195   }
196   ui.inputEdit->clear();
197 }
198