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