]> cloud.milkyroute.net Git - dolphin.git/blob - src/views/selectionmanager.cpp
Move the FileMetaDataConfigurationDialog from "settings" to "panels/information"...
[dolphin.git] / src / views / selectionmanager.cpp
1 /***************************************************************************
2 * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
19
20 #include "selectionmanager.h"
21
22 #include "dolphinmodel.h"
23 #include "selectiontoggle.h"
24 #include <kdirmodel.h>
25 #include <kiconeffect.h>
26
27 #include <QAbstractButton>
28 #include <QAbstractItemView>
29 #include <QAbstractProxyModel>
30 #include <QApplication>
31 #include <QModelIndex>
32 #include <QPainter>
33 #include <QPaintEvent>
34 #include <QRect>
35 #include <QTimeLine>
36
37 SelectionManager::SelectionManager(QAbstractItemView* parent) :
38 QObject(parent),
39 m_view(parent),
40 m_toggle(0),
41 m_connected(false),
42 m_appliedPointingHandCursor(false)
43 {
44 connect(parent, SIGNAL(entered(const QModelIndex&)),
45 this, SLOT(slotEntered(const QModelIndex&)));
46 connect(parent, SIGNAL(viewportEntered()),
47 this, SLOT(slotViewportEntered()));
48 m_toggle = new SelectionToggle(m_view->viewport());
49 m_toggle->setCheckable(true);
50 m_toggle->hide();
51 connect(m_toggle, SIGNAL(clicked(bool)),
52 this, SLOT(setItemSelected(bool)));
53 m_toggle->installEventFilter(this);
54
55 m_view->viewport()->installEventFilter(this);
56 }
57
58 SelectionManager::~SelectionManager()
59 {
60 }
61
62 bool SelectionManager::eventFilter(QObject* watched, QEvent* event)
63 {
64 if (watched == m_view->viewport()) {
65 switch (event->type()) {
66 case QEvent::Leave:
67 m_toggle->hide();
68 break;
69
70 case QEvent::MouseButtonPress: {
71 // Set the toggle invisible, if a mouse button has been pressed
72 // outside the toggle boundaries. This e.g. assures, that the toggle
73 // gets invisible during dragging items.
74 const QRect toggleBounds(m_toggle->mapToGlobal(QPoint(0, 0)), m_toggle->size());
75 m_toggle->setVisible(toggleBounds.contains(QCursor::pos()));
76 break;
77 }
78
79 default:
80 break;
81 }
82 } else if (watched == m_toggle) {
83 switch (event->type()) {
84 case QEvent::Hide:
85 // If the toggle button gets hidden, the cursor is not above the item
86 // anymore and the shape must get restored
87 restoreCursor();
88 break;
89
90 case QEvent::Enter:
91 QApplication::changeOverrideCursor(Qt::ArrowCursor);
92 break;
93
94 case QEvent::Leave:
95 QApplication::changeOverrideCursor(Qt::PointingHandCursor);
96 break;
97
98 default:
99 break;
100 }
101 }
102
103 return QObject::eventFilter(watched, event);
104 }
105
106 void SelectionManager::reset()
107 {
108 m_toggle->reset();
109 }
110
111 void SelectionManager::slotEntered(const QModelIndex& index)
112 {
113 m_toggle->hide();
114 const bool showToggle = index.isValid() &&
115 (index.column() == DolphinModel::Name) &&
116 (QApplication::mouseButtons() == Qt::NoButton);
117 if (showToggle) {
118 applyPointingHandCursor();
119
120 m_toggle->setUrl(urlForIndex(index));
121
122 if (!m_connected) {
123 connect(m_view->model(), SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
124 this, SLOT(slotRowsRemoved(const QModelIndex&, int, int)));
125 connect(m_view->selectionModel(),
126 SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
127 this,
128 SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection&)));
129 m_connected = true;
130 }
131
132 // Increase the size of the toggle for large items
133 const int iconHeight = m_view->iconSize().height();
134
135 int toggleSize = KIconLoader::SizeSmall;
136 if (iconHeight >= KIconLoader::SizeEnormous) {
137 toggleSize = KIconLoader::SizeMedium;
138 } else if (iconHeight >= KIconLoader::SizeLarge) {
139 toggleSize = KIconLoader::SizeSmallMedium;
140 }
141
142 // Add a small invisible margin, if the item-height is nearly
143 // equal to the toggleSize (#169494).
144 const QRect rect = m_view->visualRect(index);
145 int margin = (rect.height() - toggleSize) / 2;
146 if (margin > 4) {
147 margin = 0;
148 }
149 toggleSize += 2 * margin;
150 m_toggle->setMargin(margin);
151 m_toggle->resize(toggleSize, toggleSize);
152 m_toggle->move(rect.topLeft());
153
154 QItemSelectionModel* selModel = m_view->selectionModel();
155 m_toggle->setChecked(selModel->isSelected(index));
156 m_toggle->show();
157 } else {
158 m_toggle->setUrl(KUrl());
159 disconnect(m_view->model(), SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
160 this, SLOT(slotRowsRemoved(const QModelIndex&, int, int)));
161 disconnect(m_view->selectionModel(),
162 SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
163 this,
164 SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection&)));
165 m_connected = false;
166 }
167 }
168
169 void SelectionManager::slotViewportEntered()
170 {
171 m_toggle->hide();
172 }
173
174 void SelectionManager::setItemSelected(bool selected)
175 {
176 emit selectionChanged();
177
178 if (!m_toggle->url().isEmpty()) {
179 const QModelIndex index = indexForUrl(m_toggle->url());
180 if (index.isValid()) {
181 QItemSelectionModel* selModel = m_view->selectionModel();
182 if (selected) {
183 selModel->select(index, QItemSelectionModel::Select);
184 } else {
185 selModel->select(index, QItemSelectionModel::Deselect);
186 }
187 selModel->setCurrentIndex(index, QItemSelectionModel::Current);
188 }
189 }
190 }
191
192 void SelectionManager::slotRowsRemoved(const QModelIndex& parent, int start, int end)
193 {
194 Q_UNUSED(parent);
195 Q_UNUSED(start);
196 Q_UNUSED(end);
197 m_toggle->hide();
198 }
199
200 void SelectionManager::slotSelectionChanged(const QItemSelection& selected,
201 const QItemSelection& deselected)
202 {
203 // The selection has been changed outside the scope of the selection manager
204 // (e. g. by the rubberband or the "Select All" action). Take care updating
205 // the state of the toggle button.
206 if (!m_toggle->url().isEmpty()) {
207 const QModelIndex index = indexForUrl(m_toggle->url());
208 if (index.isValid()) {
209 if (selected.contains(index)) {
210 m_toggle->setChecked(true);
211 }
212
213 if (deselected.contains(index)) {
214 m_toggle->setChecked(false);
215 }
216 }
217 }
218 }
219
220 KUrl SelectionManager::urlForIndex(const QModelIndex& index) const
221 {
222 QAbstractProxyModel* proxyModel = static_cast<QAbstractProxyModel*>(m_view->model());
223 KDirModel* dirModel = static_cast<KDirModel*>(proxyModel->sourceModel());
224 const QModelIndex dirIndex = proxyModel->mapToSource(index);
225 return dirModel->itemForIndex(dirIndex).url();
226 }
227
228 const QModelIndex SelectionManager::indexForUrl(const KUrl& url) const
229 {
230 QAbstractProxyModel* proxyModel = static_cast<QAbstractProxyModel*>(m_view->model());
231 KDirModel* dirModel = static_cast<KDirModel*>(proxyModel->sourceModel());
232 const QModelIndex dirIndex = dirModel->indexForUrl(url);
233 return proxyModel->mapFromSource(dirIndex);
234 }
235
236
237 void SelectionManager::applyPointingHandCursor()
238 {
239 if (!m_appliedPointingHandCursor) {
240 QApplication::setOverrideCursor(QCursor(Qt::PointingHandCursor));
241 m_appliedPointingHandCursor = true;
242 }
243 }
244
245 void SelectionManager::restoreCursor()
246 {
247 if (m_appliedPointingHandCursor) {
248 QApplication::restoreOverrideCursor();
249 m_appliedPointingHandCursor = false;
250 }
251 }
252
253 #include "selectionmanager.moc"