ea29d3fe5e7fb99d629feb127a2bf675121a7312
[quassel.git] / src / uisupport / nickview.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2016 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  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #include "nickview.h"
22
23 #include <QApplication>
24 #include <QHeaderView>
25 #include <QScrollBar>
26 #include <QDebug>
27 #include <QMenu>
28 #include <QTouchEvent>
29 #include <QScrollBar>
30
31 #include "buffermodel.h"
32 #include "client.h"
33 #include "contextmenuactionprovider.h"
34 #include "graphicalui.h"
35 #include "nickview.h"
36 #include "nickviewfilter.h"
37 #include "networkmodel.h"
38 #include "types.h"
39
40 NickView::NickView(QWidget *parent)
41     : QTreeView(parent)
42 {
43     setIndentation(10);
44     header()->hide();
45     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
46     setSortingEnabled(true);
47     sortByColumn(0, Qt::AscendingOrder);
48
49     setContextMenuPolicy(Qt::CustomContextMenu);
50     setSelectionMode(QAbstractItemView::ExtendedSelection);
51
52 //   // breaks with Qt 4.8
53 //   if(QString("4.8.0") > qVersion()) // FIXME breaks with Qt versions >= 4.10!
54     setAnimated(true);
55
56     connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &)));
57
58 #if defined Q_WS_QWS || defined Q_WS_X11
59     connect(this, SIGNAL(doubleClicked(QModelIndex)), SLOT(startQuery(QModelIndex)));
60 #else
61     // afaik this is better on Mac and Windows
62     connect(this, SIGNAL(activated(QModelIndex)), SLOT(startQuery(QModelIndex)));
63 #endif
64 }
65
66
67 void NickView::init()
68 {
69     if (!model())
70         return;
71
72     for (int i = 1; i < model()->columnCount(); i++)
73         setColumnHidden(i, true);
74
75     connect(selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), SIGNAL(selectionUpdated()));
76     connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SIGNAL(selectionUpdated()));
77         setAttribute(Qt::WA_AcceptTouchEvents);
78 }
79
80
81 void NickView::setModel(QAbstractItemModel *model_)
82 {
83     if (model())
84         disconnect(model(), 0, this, 0);
85
86     QTreeView::setModel(model_);
87     init();
88 }
89
90
91 void NickView::rowsInserted(const QModelIndex &parent, int start, int end)
92 {
93     QTreeView::rowsInserted(parent, start, end);
94     if (model()->data(parent, NetworkModel::ItemTypeRole) == NetworkModel::UserCategoryItemType && !isExpanded(parent)) {
95         unanimatedExpandAll();
96     }
97 }
98
99
100 void NickView::setRootIndex(const QModelIndex &index)
101 {
102     QAbstractItemView::setRootIndex(index);
103     if (index.isValid())
104         unanimatedExpandAll();
105 }
106
107
108 QModelIndexList NickView::selectedIndexes() const
109 {
110     QModelIndexList indexList = QTreeView::selectedIndexes();
111
112     // make sure the item we clicked on is first
113     if (indexList.contains(currentIndex())) {
114         indexList.removeAll(currentIndex());
115         indexList.prepend(currentIndex());
116     }
117
118     return indexList;
119 }
120
121
122 void NickView::unanimatedExpandAll()
123 {
124     // since of Qt Version 4.8.0 the default expandAll will not properly work if
125     // animations are enabled. Therefore we perform an unanimated expand when a
126     // model is set or a toplevel node is inserted.
127     bool wasAnimated = isAnimated();
128     setAnimated(false);
129     expandAll();
130     setAnimated(wasAnimated);
131 }
132
133
134 void NickView::showContextMenu(const QPoint &pos)
135 {
136     Q_UNUSED(pos);
137
138     QMenu contextMenu(this);
139     GraphicalUi::contextMenuActionProvider()->addActions(&contextMenu, selectedIndexes());
140     contextMenu.exec(QCursor::pos());
141 }
142
143
144 void NickView::startQuery(const QModelIndex &index)
145 {
146     if (index.data(NetworkModel::ItemTypeRole) != NetworkModel::IrcUserItemType)
147         return;
148
149     IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
150     NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
151     if (!ircUser || !networkId.isValid())
152         return;
153
154     Client::bufferModel()->switchToOrStartQuery(networkId, ircUser->nick());
155 }
156
157 bool NickView::event(QEvent *event) {
158         if (event->type() == QEvent::TouchBegin && _lastTouchStart < QDateTime::currentMSecsSinceEpoch() - 1000) { //(slow) double tab = normal behaviour = select multiple. 1000 ok?
159                 _touchScrollInProgress = true;
160                 _lastTouchStart = QDateTime::currentMSecsSinceEpoch();
161                 setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
162                 return true;
163         }
164
165         if (event->type() == QEvent::TouchUpdate && _touchScrollInProgress) {
166                 QTouchEvent::TouchPoint p = ((QTouchEvent*)event)->touchPoints().at(0);
167                 verticalScrollBar()->setValue(verticalScrollBar()->value() - (p.pos().y() - p.lastPos().y()));
168                 return true;
169         }
170
171 #if QT_VERSION >= 0x050000
172         if (event->type() == QEvent::TouchEnd || event->type() == QEvent::TouchCancel) {
173 #else
174     if (event->type() == QEvent::TouchEnd) {
175 #endif
176                 _touchScrollInProgress = false;
177                 return true;
178         }
179
180         return QTreeView::event(event);
181 }
182
183 void NickView::mousePressEvent(QMouseEvent * event) {
184         if (!_touchScrollInProgress)
185                 QTreeView::mousePressEvent(event);
186 }
187
188 void NickView::mouseMoveEvent(QMouseEvent * event) {
189         if (!_touchScrollInProgress)
190                 QTreeView::mouseMoveEvent(event);
191 }