]> cloud.milkyroute.net Git - dolphin.git/blob - src/panels/information/informationpanel.cpp
When changing the selection, the currently shown file item should be reset. This...
[dolphin.git] / src / panels / information / informationpanel.cpp
1 /***************************************************************************
2 * Copyright (C) 2006-2009 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 "informationpanel.h"
21 #include <kdirnotify.h>
22 #include <QShowEvent>
23 #include "informationpanelcontent.h"
24
25 InformationPanel::InformationPanel(QWidget* parent) :
26 Panel(parent),
27 m_initialized(false),
28 m_infoTimer(0),
29 m_urlChangedTimer(0),
30 m_resetUrlTimer(0),
31 m_shownUrl(),
32 m_urlCandidate(),
33 m_invalidUrlCandidate(),
34 m_fileItem(),
35 m_selection(),
36 m_content(0)
37 {
38 }
39
40 InformationPanel::~InformationPanel()
41 {
42 }
43
44 QSize InformationPanel::sizeHint() const
45 {
46 QSize size = Panel::sizeHint();
47 size.setWidth(minimumSizeHint().width());
48 return size;
49 }
50
51 void InformationPanel::setUrl(const KUrl& url)
52 {
53 Panel::setUrl(url);
54 if (url.isValid() && !isEqualToShownUrl(url)) {
55 if (isVisible()) {
56 cancelRequest();
57 m_shownUrl = url;
58 // Update the content with a delay. This gives
59 // the directory lister the chance to show the content
60 // before expensive operations are done to show
61 // meta information.
62 m_urlChangedTimer->start();
63 } else {
64 m_shownUrl = url;
65 }
66 }
67 }
68
69 void InformationPanel::setSelection(const KFileItemList& selection)
70 {
71 if (!isVisible()) {
72 return;
73 }
74
75 if ((selection.count() == 0) && (m_selection.count() == 0)) {
76 // The selection has not really changed, only the current index.
77 // QItemSelectionModel emits a signal in this case and it is less
78 // expensive doing the check this way instead of patching
79 // DolphinView::emitSelectionChanged().
80 return;
81 }
82
83 m_selection = selection;
84 m_fileItem = KFileItem();
85
86 const int count = selection.count();
87 if (count == 0) {
88 if (!isEqualToShownUrl(url())) {
89 m_shownUrl = url();
90 showItemInfo();
91 }
92 } else {
93 if ((count == 1) && !selection.first().url().isEmpty()) {
94 m_urlCandidate = selection.first().url();
95 }
96 m_infoTimer->start();
97 }
98 }
99
100 void InformationPanel::requestDelayedItemInfo(const KFileItem& item)
101 {
102 if (!isVisible()) {
103 return;
104 }
105
106 cancelRequest();
107
108 m_fileItem = KFileItem();
109 if (item.isNull()) {
110 // The cursor is above the viewport. If files are selected,
111 // show information regarding the selection.
112 if (m_selection.size() > 0) {
113 m_infoTimer->start();
114 }
115 } else {
116 const KUrl url = item.url();
117 if (url.isValid() && !isEqualToShownUrl(url)) {
118 m_urlCandidate = item.url();
119 m_fileItem = item;
120 m_infoTimer->start();
121 }
122 }
123 }
124
125 void InformationPanel::showEvent(QShowEvent* event)
126 {
127 Panel::showEvent(event);
128 if (!event->spontaneous()) {
129 if (!m_initialized) {
130 // do a delayed initialization so that no performance
131 // penalty is given when Dolphin is started with a closed
132 // Information Panel
133 init();
134 }
135 showItemInfo();
136 }
137 }
138
139 void InformationPanel::resizeEvent(QResizeEvent* event)
140 {
141 if (isVisible()) {
142 m_urlCandidate = m_shownUrl;
143 m_infoTimer->start();
144 }
145 Panel::resizeEvent(event);
146 }
147
148 void InformationPanel::contextMenuEvent(QContextMenuEvent* event)
149 {
150 m_content->configureSettings();
151 Panel::contextMenuEvent(event);
152 }
153
154 void InformationPanel::showItemInfo()
155 {
156 if (!isVisible()) {
157 return;
158 }
159
160 cancelRequest();
161
162 if (showMultipleSelectionInfo()) {
163 m_content->showItems(m_selection);
164 m_shownUrl = KUrl();
165 } else {
166 KFileItem item;
167 if (!m_fileItem.isNull()) {
168 item = m_fileItem;
169 } else if (!m_selection.isEmpty()) {
170 Q_ASSERT(m_selection.count() == 1);
171 item = m_selection.first();
172 } else {
173 // no item is hovered and no selection has been done: provide
174 // an item for the directory represented by m_shownUrl
175 item = KFileItem(KFileItem::Unknown, KFileItem::Unknown, m_shownUrl);
176 item.refresh();
177 }
178
179 m_content->showItem(item);
180 }
181 }
182
183 void InformationPanel::slotInfoTimeout()
184 {
185 m_shownUrl = m_urlCandidate;
186 showItemInfo();
187 }
188
189 void InformationPanel::reset()
190 {
191 if (m_invalidUrlCandidate == m_shownUrl) {
192 m_invalidUrlCandidate = KUrl();
193
194 // The current URL is still invalid. Reset
195 // the content to show the directory URL.
196 m_selection.clear();
197 m_shownUrl = url();
198 m_fileItem = KFileItem();
199 showItemInfo();
200 }
201 }
202
203 void InformationPanel::slotFileRenamed(const QString& source, const QString& dest)
204 {
205 if (m_shownUrl == KUrl(source)) {
206 m_shownUrl = KUrl(dest);
207 m_fileItem = KFileItem(KFileItem::Unknown, KFileItem::Unknown, m_shownUrl);
208 showItemInfo();
209 }
210 }
211
212 void InformationPanel::slotFilesAdded(const QString& directory)
213 {
214 if (m_shownUrl == KUrl(directory)) {
215 // If the 'trash' icon changes because the trash has been emptied or got filled,
216 // the signal filesAdded("trash:/") will be emitted.
217 KFileItem item(KFileItem::Unknown, KFileItem::Unknown, KUrl(directory));
218 requestDelayedItemInfo(item);
219 }
220 }
221
222 void InformationPanel::slotFilesChanged(const QStringList& files)
223 {
224 foreach (const QString& fileName, files) {
225 if (m_shownUrl == KUrl(fileName)) {
226 showItemInfo();
227 break;
228 }
229 }
230 }
231
232 void InformationPanel::slotFilesRemoved(const QStringList& files)
233 {
234 foreach (const QString& fileName, files) {
235 if (m_shownUrl == KUrl(fileName)) {
236 // the currently shown item has been removed, show
237 // the parent directory as fallback
238 markUrlAsInvalid();
239 break;
240 }
241 }
242 }
243
244 void InformationPanel::slotEnteredDirectory(const QString& directory)
245 {
246 if (m_shownUrl == KUrl(directory)) {
247 KFileItem item(KFileItem::Unknown, KFileItem::Unknown, KUrl(directory));
248 requestDelayedItemInfo(item);
249 }
250 }
251
252 void InformationPanel::slotLeftDirectory(const QString& directory)
253 {
254 if (m_shownUrl == KUrl(directory)) {
255 // The signal 'leftDirectory' is also emitted when a media
256 // has been unmounted. In this case no directory change will be
257 // done in Dolphin, but the Information Panel must be updated to
258 // indicate an invalid directory.
259 markUrlAsInvalid();
260 }
261 }
262
263 void InformationPanel::cancelRequest()
264 {
265 m_infoTimer->stop();
266 }
267
268 bool InformationPanel::showMultipleSelectionInfo() const
269 {
270 return m_fileItem.isNull() && (m_selection.count() > 1);
271 }
272
273 bool InformationPanel::isEqualToShownUrl(const KUrl& url) const
274 {
275 return m_shownUrl.equals(url, KUrl::CompareWithoutTrailingSlash);
276 }
277
278 void InformationPanel::markUrlAsInvalid()
279 {
280 m_invalidUrlCandidate = m_shownUrl;
281 m_resetUrlTimer->start();
282 }
283
284 void InformationPanel::init()
285 {
286 const int defaultDelay = 300;
287
288 m_infoTimer = new QTimer(this);
289 m_infoTimer->setInterval(defaultDelay);
290 m_infoTimer->setSingleShot(true);
291 connect(m_infoTimer, SIGNAL(timeout()),
292 this, SLOT(slotInfoTimeout()));
293
294 m_urlChangedTimer = new QTimer(this);
295 m_urlChangedTimer->setInterval(defaultDelay);
296 m_urlChangedTimer->setSingleShot(true);
297 connect(m_urlChangedTimer, SIGNAL(timeout()),
298 this, SLOT(showItemInfo()));
299
300 m_resetUrlTimer = new QTimer(this);
301 m_resetUrlTimer->setInterval(defaultDelay * 3);
302 m_resetUrlTimer->setSingleShot(true);
303 connect(m_resetUrlTimer, SIGNAL(timeout()),
304 this, SLOT(reset()));
305
306 org::kde::KDirNotify* dirNotify = new org::kde::KDirNotify(QString(), QString(),
307 QDBusConnection::sessionBus(), this);
308 connect(dirNotify, SIGNAL(FileRenamed(QString, QString)), SLOT(slotFileRenamed(QString, QString)));
309 connect(dirNotify, SIGNAL(FilesAdded(QString)), SLOT(slotFilesAdded(QString)));
310 connect(dirNotify, SIGNAL(FilesChanged(QStringList)), SLOT(slotFilesChanged(QStringList)));
311 connect(dirNotify, SIGNAL(FilesRemoved(QStringList)), SLOT(slotFilesRemoved(QStringList)));
312 connect(dirNotify, SIGNAL(enteredDirectory(QString)), SLOT(slotEnteredDirectory(QString)));
313 connect(dirNotify, SIGNAL(leftDirectory(QString)), SLOT(slotLeftDirectory(QString)));
314
315 m_content = new InformationPanelContent(this);
316 connect(m_content, SIGNAL(urlActivated(KUrl)), this, SIGNAL(urlActivated(KUrl)));
317
318 m_initialized = true;
319 }
320
321 #include "informationpanel.moc"