fixed slow buffer switches
[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     _currentBuffer(0)
36 {
37   ui.setupUi(this);
38 }
39
40 BufferWidget::~BufferWidget() {
41 }
42
43 void BufferWidget::init() {
44 }
45
46 void BufferWidget::setModel(BufferModel *bufferModel) {
47   if(_bufferModel) {
48     disconnect(_bufferModel, 0, this, 0);
49   }
50   _bufferModel = bufferModel;
51
52   if(bufferModel) {
53     connect(bufferModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
54             this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
55   }
56 }
57
58 void BufferWidget::setSelectionModel(QItemSelectionModel *selectionModel) {
59   if(_selectionModel) {
60     disconnect(_selectionModel, 0, this, 0);
61   }
62   _selectionModel = selectionModel;
63
64   if(selectionModel) {
65     connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
66             this, SLOT(currentChanged(QModelIndex, QModelIndex)));
67   }
68 }
69
70 void BufferWidget::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) {
71   Q_ASSERT(model());
72   if(!parent.isValid()) {
73     // ok this means that whole networks are about to be removed
74     // we can't determine which buffers are affect, so we hope that all nets are removed
75     // this is the most common case (for example disconnecting from the core or terminating the clint)
76     if(model()->rowCount(parent) != end - start + 1)
77       return;
78
79     ChatWidget *chatWidget;
80     QHash<BufferId, ChatWidget *>::iterator iter = _chatWidgets.begin();
81     while(iter != _chatWidgets.end()) {
82       chatWidget = *iter;
83       iter = _chatWidgets.erase(iter);
84       ui.stackedWidget->removeWidget(chatWidget);
85       chatWidget->deleteLater();
86     }
87     
88   } else {
89     // check if there are explicitly buffers removed
90     for(int i = start; i <= end; i++) {
91       QVariant variant = parent.child(i,0).data(NetworkModel::BufferIdRole);
92       if(!variant.isValid())
93         continue;
94       
95       BufferId bufferId = qVariantValue<BufferId>(variant);
96       removeBuffer(bufferId);
97     }
98   }
99 }
100
101 void BufferWidget::removeBuffer(BufferId bufferId) {
102   if(!_chatWidgets.contains(bufferId))
103     return;
104
105   if(Client::buffer(bufferId)) Client::buffer(bufferId)->setVisible(false);
106   ChatWidget *chatWidget = _chatWidgets.take(bufferId);
107   ui.stackedWidget->removeWidget(chatWidget);
108   chatWidget->deleteLater();
109 }
110
111 void BufferWidget::currentChanged(const QModelIndex &current, const QModelIndex &previous) {
112   Q_UNUSED(previous);
113   QVariant variant;
114
115   variant = current.data(NetworkModel::BufferIdRole);
116   if(!variant.isValid())
117     return;
118   setCurrentBuffer(variant.value<BufferId>());
119 }
120
121 void BufferWidget::setCurrentBuffer(BufferId bufferId) {
122   ChatWidget *chatWidget = 0;
123   Buffer *buf = Client::buffer(bufferId);
124   if(!buf) {
125     qWarning() << "BufferWidget::setBuffer(BufferId): Can't show unknown Buffer:" << bufferId;
126     return;
127   }
128   Buffer *prevBuffer = Client::buffer(currentBuffer());
129   if(prevBuffer) prevBuffer->setVisible(false);
130   if(_chatWidgets.contains(bufferId)) {
131      chatWidget = _chatWidgets[bufferId];
132   } else {
133     chatWidget = new ChatWidget(this);
134     chatWidget->init(bufferId);
135     QList<ChatLine *> lines;
136     QList<AbstractUiMsg *> msgs = buf->contents();
137     foreach(AbstractUiMsg *msg, msgs) {
138       lines.append(dynamic_cast<ChatLine*>(msg));
139     }
140     chatWidget->setContents(lines);
141     connect(buf, SIGNAL(msgAppended(AbstractUiMsg *)), chatWidget, SLOT(appendMsg(AbstractUiMsg *)));
142     connect(buf, SIGNAL(msgPrepended(AbstractUiMsg *)), chatWidget, SLOT(prependMsg(AbstractUiMsg *)));
143     _chatWidgets[bufferId] = chatWidget;
144     ui.stackedWidget->addWidget(chatWidget);
145     chatWidget->setFocusProxy(this);
146   }
147   _currentBuffer = bufferId;
148   ui.stackedWidget->setCurrentWidget(chatWidget);
149   buf->setVisible(true);
150   setFocus();
151 }
152