]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinview.cpp
commited initial version of Dolphin
[dolphin.git] / src / dolphinview.cpp
1 /***************************************************************************
2 * Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at> *
3 * Copyright (C) 2006 by Gregor Kališnik <gregor@podnapisi.net> *
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) any later version. *
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 "dolphinview.h"
22
23 #include <qlayout.h>
24 //Added by qt3to4:
25 #include <Q3ValueList>
26 #include <QDropEvent>
27 #include <QMouseEvent>
28 #include <Q3VBoxLayout>
29 #include <kurl.h>
30 #include <klocale.h>
31 #include <kio/netaccess.h>
32 #include <kio/renamedlg.h>
33 #include <assert.h>
34
35 #include "urlnavigator.h"
36 #include "dolphinstatusbar.h"
37 #include "dolphin.h"
38 #include "dolphindirlister.h"
39 #include "viewproperties.h"
40 #include "dolphindetailsview.h"
41 #include "dolphiniconsview.h"
42 #include "dolphincontextmenu.h"
43 #include "undomanager.h"
44 #include "renamedialog.h"
45 #include "progressindicator.h"
46
47 #include "filterbar.h"
48
49 DolphinView::DolphinView(QWidget *parent,
50 const KUrl& url,
51 Mode mode,
52 bool showHiddenFiles) :
53 QWidget(parent),
54 m_refreshing(false),
55 m_showProgress(false),
56 m_mode(mode),
57 m_iconsView(0),
58 m_detailsView(0),
59 m_statusBar(0),
60 m_iconSize(0),
61 m_folderCount(0),
62 m_fileCount(0),
63 m_filterBar(0)
64 {
65 setFocusPolicy(Qt::StrongFocus);
66 m_topLayout = new Q3VBoxLayout(this);
67
68 Dolphin& dolphin = Dolphin::mainWin();
69
70 connect(this, SIGNAL(signalModeChanged()),
71 &dolphin, SLOT(slotViewModeChanged()));
72 connect(this, SIGNAL(signalShowHiddenFilesChanged()),
73 &dolphin, SLOT(slotShowHiddenFilesChanged()));
74 connect(this, SIGNAL(signalSortingChanged(DolphinView::Sorting)),
75 &dolphin, SLOT(slotSortingChanged(DolphinView::Sorting)));
76 connect(this, SIGNAL(signalSortOrderChanged(Qt::SortOrder)),
77 &dolphin, SLOT(slotSortOrderChanged(Qt::SortOrder)));
78
79 m_urlNavigator = new URLNavigator(url, this);
80 connect(m_urlNavigator, SIGNAL(urlChanged(const KUrl&)),
81 this, SLOT(slotURLChanged(const KUrl&)));
82 connect(m_urlNavigator, SIGNAL(urlChanged(const KUrl&)),
83 &dolphin, SLOT(slotURLChanged(const KUrl&)));
84 connect(m_urlNavigator, SIGNAL(historyChanged()),
85 &dolphin, SLOT(slotHistoryChanged()));
86
87 m_statusBar = new DolphinStatusBar(this);
88
89 m_dirLister = new DolphinDirLister();
90 m_dirLister->setAutoUpdate(true);
91 m_dirLister->setMainWindow(this);
92 m_dirLister->setShowingDotFiles(showHiddenFiles);
93 connect(m_dirLister, SIGNAL(clear()),
94 this, SLOT(slotClear()));
95 connect(m_dirLister, SIGNAL(percent(int)),
96 this, SLOT(slotPercent(int)));
97 connect(m_dirLister, SIGNAL(deleteItem(KFileItem*)),
98 this, SLOT(slotDeleteItem(KFileItem*)));
99 connect(m_dirLister, SIGNAL(completed()),
100 this, SLOT(slotCompleted()));
101 connect(m_dirLister, SIGNAL(infoMessage(const QString&)),
102 this, SLOT(slotInfoMessage(const QString&)));
103 connect(m_dirLister, SIGNAL(errorMessage(const QString&)),
104 this, SLOT(slotErrorMessage(const QString&)));
105 connect(m_dirLister, SIGNAL(refreshItems(const KFileItemList&)),
106 this, SLOT(slotRefreshItems(const KFileItemList&)));
107 connect(m_dirLister, SIGNAL(redirection(const KUrl&, const KUrl&)),
108 this, SIGNAL(redirection(const KUrl&, const KUrl&)));
109 connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
110 this, SLOT(slotAddItems(const KFileItemList&)));
111
112 m_iconSize = K3Icon::SizeMedium;
113
114 m_topLayout->addWidget(m_urlNavigator);
115 createView();
116
117 m_filterBar = new FilterBar(this);
118 m_filterBar->hide();
119 m_topLayout->addWidget(m_filterBar);
120 connect(m_filterBar, SIGNAL(signalFilterChanged(const QString&)),
121 this, SLOT(slotChangeNameFilter(const QString&)));
122
123 m_topLayout->addWidget(m_statusBar);
124 }
125
126 DolphinView::~DolphinView()
127 {
128 delete m_dirLister;
129 m_dirLister = 0;
130 }
131
132 void DolphinView::setURL(const KUrl& url)
133 {
134 m_urlNavigator->setURL(url);
135 }
136
137 const KUrl& DolphinView::url() const
138 {
139 return m_urlNavigator->url();
140 }
141
142 void DolphinView::requestActivation()
143 {
144 Dolphin::mainWin().setActiveView(this);
145 }
146
147 bool DolphinView::isActive() const
148 {
149 return (Dolphin::mainWin().activeView() == this);
150 }
151
152 void DolphinView::setMode(Mode mode)
153 {
154 if (mode == m_mode) {
155 return; // the wished mode is already set
156 }
157
158 QWidget* view = (m_iconsView != 0) ? static_cast<QWidget*>(m_iconsView) :
159 static_cast<QWidget*>(m_detailsView);
160 if (view != 0) {
161 m_topLayout->remove(view);
162 view->close();
163 view->deleteLater();
164 m_iconsView = 0;
165 m_detailsView = 0;
166 }
167
168 m_mode = mode;
169
170 createView();
171
172 ViewProperties props(m_urlNavigator->url());
173 props.setViewMode(m_mode);
174
175 emit signalModeChanged();
176 }
177
178 DolphinView::Mode DolphinView::mode() const
179 {
180 return m_mode;
181 }
182
183 void DolphinView::setShowHiddenFilesEnabled(bool show)
184 {
185 if (m_dirLister->showingDotFiles() == show) {
186 return;
187 }
188
189 ViewProperties props(m_urlNavigator->url());
190 props.setShowHiddenFilesEnabled(show);
191 props.save();
192
193 m_dirLister->setShowingDotFiles(show);
194
195 emit signalShowHiddenFilesChanged();
196
197 reload();
198 }
199
200 bool DolphinView::isShowHiddenFilesEnabled() const
201 {
202 return m_dirLister->showingDotFiles();
203 }
204
205 void DolphinView::setViewProperties(const ViewProperties& props)
206 {
207 setMode(props.viewMode());
208 setSorting(props.sorting());
209 setSortOrder(props.sortOrder());
210 setShowHiddenFilesEnabled(props.isShowHiddenFilesEnabled());
211 }
212
213 void DolphinView::renameSelectedItems()
214 {
215 const KUrl::List urls = selectedURLs();
216 if (urls.count() > 1) {
217 // More than one item has been selected for renaming. Open
218 // a rename dialog and rename all items afterwards.
219 RenameDialog dialog(urls);
220 if (dialog.exec() == QDialog::Rejected) {
221 return;
222 }
223
224 DolphinView* view = Dolphin::mainWin().activeView();
225 const QString& newName = dialog.newName();
226 if (newName.isEmpty()) {
227 view->statusBar()->setMessage(i18n("The new item name is invalid."),
228 DolphinStatusBar::Error);
229 }
230 else {
231 UndoManager& undoMan = UndoManager::instance();
232 undoMan.beginMacro();
233
234 assert(newName.contains('#'));
235
236 const int urlsCount = urls.count();
237 ProgressIndicator* progressIndicator =
238 new ProgressIndicator(i18n("Renaming items..."),
239 i18n("Renaming finished."),
240 urlsCount);
241
242 // iterate through all selected items and rename them...
243 const int replaceIndex = newName.find('#');
244 assert(replaceIndex >= 0);
245 for (int i = 0; i < urlsCount; ++i) {
246 const KUrl& source = urls[i];
247 QString name(newName);
248 name.replace(replaceIndex, 1, renameIndexPresentation(i + 1, urlsCount));
249
250 if (source.fileName() != name) {
251 KUrl dest(source.upUrl());
252 dest.addPath(name);
253
254 const bool destExists = KIO::NetAccess::exists(dest, false, view);
255 if (destExists) {
256 delete progressIndicator;
257 progressIndicator = 0;
258 view->statusBar()->setMessage(i18n("Renaming failed (item '%1' already exists).").arg(name),
259 DolphinStatusBar::Error);
260 break;
261 }
262 else if (KIO::NetAccess::file_move(source, dest)) {
263 // TODO: From the users point of view he executed one 'rename n files' operation,
264 // but internally we store it as n 'rename 1 file' operations for the undo mechanism.
265 DolphinCommand command(DolphinCommand::Rename, source, dest);
266 undoMan.addCommand(command);
267 }
268 }
269
270 progressIndicator->execOperation();
271 }
272 delete progressIndicator;
273 progressIndicator = 0;
274
275 undoMan.endMacro();
276 }
277 }
278 else {
279 // Only one item has been selected for renaming. Use the custom
280 // renaming mechanism from the views.
281 assert(urls.count() == 1);
282 if (m_mode == DetailsView) {
283 Q3ListViewItem* item = m_detailsView->firstChild();
284 while (item != 0) {
285 if (item->isSelected()) {
286 m_detailsView->rename(item, DolphinDetailsView::NameColumn);
287 break;
288 }
289 item = item->nextSibling();
290 }
291 }
292 else {
293 KFileIconViewItem* item = static_cast<KFileIconViewItem*>(m_iconsView->firstItem());
294 while (item != 0) {
295 if (item->isSelected()) {
296 item->rename();
297 break;
298 }
299 item = static_cast<KFileIconViewItem*>(item->nextItem());
300 }
301 }
302 }
303 }
304
305 void DolphinView::selectAll()
306 {
307 fileView()->selectAll();
308 }
309
310 void DolphinView::invertSelection()
311 {
312 fileView()->invertSelection();
313 }
314
315 DolphinStatusBar* DolphinView::statusBar() const
316 {
317 return m_statusBar;
318 }
319
320 int DolphinView::contentsX() const
321 {
322 return scrollView()->contentsX();
323 }
324
325 int DolphinView::contentsY() const
326 {
327 return scrollView()->contentsY();
328 }
329
330 void DolphinView::refreshSettings()
331 {
332 if (m_iconsView != 0) {
333 m_iconsView->refreshSettings();
334 }
335
336 if (m_detailsView != 0) {
337 // TODO: There is no usable interface in QListView/KFileDetailView
338 // to hide/show columns. The easiest approach is to delete
339 // the current instance and recreate a new one, which automatically
340 // refreshs the settings. If a proper interface is available in Qt4
341 // m_detailsView->refreshSettings() would be enough.
342 m_topLayout->remove(m_detailsView);
343 m_detailsView->close();
344 m_detailsView->deleteLater();
345 m_detailsView = 0;
346
347 createView();
348 }
349 }
350
351 void DolphinView::updateStatusBar()
352 {
353 // As the item count information is less important
354 // in comparison with other messages, it should only
355 // be shown if:
356 // - the status bar is empty or
357 // - shows already the item count information or
358 // - shows only a not very important information
359 // - if any progress is given don't show the item count info at all
360 const QString msg(m_statusBar->message());
361 const bool updateStatusBarMsg = (msg.isEmpty() ||
362 (msg == m_statusBar->defaultText()) ||
363 (m_statusBar->type() == DolphinStatusBar::Information)) &&
364 (m_statusBar->progress() == 100);
365
366 const QString text(hasSelection() ? selectionStatusBarText() : defaultStatusBarText());
367 m_statusBar->setDefaultText(text);
368
369 if (updateStatusBarMsg) {
370 m_statusBar->setMessage(text, DolphinStatusBar::Default);
371 }
372 }
373
374 void DolphinView::requestItemInfo(const KUrl& url)
375 {
376 emit signalRequestItemInfo(url);
377 }
378
379 bool DolphinView::isURLEditable() const
380 {
381 return m_urlNavigator->isURLEditable();
382 }
383
384 void DolphinView::zoomIn()
385 {
386 itemEffectsManager()->zoomIn();
387 }
388
389 void DolphinView::zoomOut()
390 {
391 itemEffectsManager()->zoomOut();
392 }
393
394 bool DolphinView::isZoomInPossible() const
395 {
396 return itemEffectsManager()->isZoomInPossible();
397 }
398
399 bool DolphinView::isZoomOutPossible() const
400 {
401 return itemEffectsManager()->isZoomOutPossible();
402 }
403
404 void DolphinView::setSorting(Sorting sorting)
405 {
406 if (sorting != this->sorting()) {
407 KFileView* view = fileView();
408 int spec = view->sorting() & ~QDir::Name & ~QDir::Size & ~QDir::Time & ~QDir::Unsorted;
409
410 switch (sorting) {
411 case SortByName: spec = spec | QDir::Name; break;
412 case SortBySize: spec = spec | QDir::Size; break;
413 case SortByDate: spec = spec | QDir::Time; break;
414 default: break;
415 }
416
417 ViewProperties props(url());
418 props.setSorting(sorting);
419
420 view->setSorting(static_cast<QDir::SortSpec>(spec));
421
422 emit signalSortingChanged(sorting);
423 }
424 }
425
426 DolphinView::Sorting DolphinView::sorting() const
427 {
428 const QDir::SortSpec spec = fileView()->sorting();
429
430 if (spec & QDir::Time) {
431 return SortByDate;
432 }
433
434 if (spec & QDir::Size) {
435 return SortBySize;
436 }
437
438 return SortByName;
439 }
440
441 void DolphinView::setSortOrder(Qt::SortOrder order)
442 {
443 if (sortOrder() != order) {
444 KFileView* view = fileView();
445 int sorting = view->sorting();
446 sorting = (order == Qt::Ascending) ? (sorting & ~QDir::Reversed) :
447 (sorting | QDir::Reversed);
448
449 ViewProperties props(url());
450 props.setSortOrder(order);
451
452 view->setSorting(static_cast<QDir::SortSpec>(sorting));
453
454 emit signalSortOrderChanged(order);
455 }
456 }
457
458 Qt::SortOrder DolphinView::sortOrder() const
459 {
460 return fileView()->isReversed() ? Qt::Descending : Qt::Ascending;
461 }
462
463 void DolphinView::goBack()
464 {
465 m_urlNavigator->goBack();
466 }
467
468 void DolphinView::goForward()
469 {
470 m_urlNavigator->goForward();
471 }
472
473 void DolphinView::goUp()
474 {
475 m_urlNavigator->goUp();
476 }
477
478 void DolphinView::goHome()
479 {
480 m_urlNavigator->goHome();
481 }
482
483 void DolphinView::setURLEditable(bool editable)
484 {
485 m_urlNavigator->editURL(editable);
486 }
487
488 const Q3ValueList<URLNavigator::HistoryElem> DolphinView::urlHistory(int& index) const
489 {
490 return m_urlNavigator->history(index);
491 }
492
493 bool DolphinView::hasSelection() const
494 {
495 const KFileItemList* list = selectedItems();
496 return (list != 0) && !list->isEmpty();
497 }
498
499 const KFileItemList* DolphinView::selectedItems() const
500 {
501 return fileView()->selectedItems();
502 }
503
504 KUrl::List DolphinView::selectedURLs() const
505 {
506 KUrl::List urls;
507
508 const KFileItemList* list = fileView()->selectedItems();
509 if (list != 0) {
510 KFileItemList::const_iterator it = list->begin();
511 const KFileItemList::const_iterator end = list->end();
512 KFileItem* item = 0;
513 while (it != end) {
514 urls.append(item->url());
515 ++it;
516 }
517 }
518
519 return urls;
520 }
521
522 const KFileItem* DolphinView::currentFileItem() const
523 {
524 return fileView()->currentFileItem();
525 }
526
527 void DolphinView::openContextMenu(KFileItem* fileInfo, const QPoint& pos)
528 {
529 DolphinContextMenu contextMenu(this, fileInfo, pos);
530 contextMenu.open();
531 }
532
533 void DolphinView::rename(const KUrl& source, const QString& newName)
534 {
535 bool ok = false;
536
537 if (newName.isEmpty() || (source.fileName() == newName)) {
538 return;
539 }
540
541 KUrl dest(source.upUrl());
542 dest.addPath(newName);
543
544 const bool destExists = KIO::NetAccess::exists(dest,
545 false,
546 Dolphin::mainWin().activeView());
547 if (destExists) {
548 // the destination already exists, hence ask the user
549 // how to proceed...
550 KIO::RenameDlg renameDialog(this,
551 i18n("File Already Exists"),
552 source.path(),
553 dest.path(),
554 KIO::M_OVERWRITE);
555 switch (renameDialog.exec()) {
556 case KIO::R_OVERWRITE:
557 // the destination should be overwritten
558 ok = KIO::NetAccess::file_move(source, dest, -1, true);
559 break;
560
561 case KIO::R_RENAME: {
562 // a new name for the destination has been used
563 KUrl newDest(renameDialog.newDestUrl());
564 ok = KIO::NetAccess::file_move(source, newDest);
565 break;
566 }
567
568 default:
569 // the renaming operation has been canceled
570 reload();
571 return;
572 }
573 }
574 else {
575 // no destination exists, hence just move the file to
576 // do the renaming
577 ok = KIO::NetAccess::file_move(source, dest);
578 }
579
580 if (ok) {
581 m_statusBar->setMessage(i18n("Renamed file '%1' to '%2'.").arg(source.fileName(), dest.fileName()),
582 DolphinStatusBar::OperationCompleted);
583
584 DolphinCommand command(DolphinCommand::Rename, source, dest);
585 UndoManager::instance().addCommand(command);
586 }
587 else {
588 m_statusBar->setMessage(i18n("Renaming of file '%1' to '%2' failed.").arg(source.fileName(), dest.fileName()),
589 DolphinStatusBar::Error);
590 reload();
591 }
592 }
593
594 void DolphinView::reload()
595 {
596 startDirLister(m_urlNavigator->url(), true);
597 }
598
599 void DolphinView::slotURLListDropped(QDropEvent* /* event */,
600 const KUrl::List& urls,
601 const KUrl& url)
602 {
603 KUrl destination(url);
604 if (destination.isEmpty()) {
605 destination = m_urlNavigator->url();
606 }
607 else {
608 // Check whether the destination URL is a directory. If this is not the
609 // case, use the navigator URL as destination (otherwise the destination,
610 // which represents a file, would be replaced by a copy- or move-operation).
611 KFileItem fileItem(KFileItem::Unknown, KFileItem::Unknown, destination);
612 if (!fileItem.isDir()) {
613 destination = m_urlNavigator->url();
614 }
615 }
616
617 Dolphin::mainWin().dropURLs(urls, destination);
618 }
619
620 void DolphinView::mouseReleaseEvent(QMouseEvent* event)
621 {
622 QWidget::mouseReleaseEvent(event);
623 Dolphin::mainWin().setActiveView(this);
624 }
625
626 void DolphinView::slotURLChanged(const KUrl& url)
627 {
628 const ViewProperties props(url);
629 setMode(props.viewMode());
630
631 const bool showHiddenFiles = props.isShowHiddenFilesEnabled();
632 setShowHiddenFilesEnabled(showHiddenFiles);
633 m_dirLister->setShowingDotFiles(showHiddenFiles);
634
635 setSorting(props.sorting());
636 setSortOrder(props.sortOrder());
637
638 startDirLister(url);
639
640 // The selectionChanged signal is not emitted when a new view object is
641 // created. The application does not care whether a view is represented by a
642 // different instance, hence inform the application that the selection might have
643 // changed so that it can update it's actions.
644 Dolphin::mainWin().slotSelectionChanged();
645
646 emit signalURLChanged(url);
647 }
648
649 void DolphinView::triggerIconsViewItem(Q3IconViewItem* item)
650 {
651 /* KDE4-TODO:
652 const Qt::ButtonState keyboardState = KApplication::keyboardMouseState();
653 const bool isSelectionActive = ((keyboardState & Qt::ShiftModifier) > 0) ||
654 ((keyboardState & Qt::ControlModifier) > 0);*/
655 const bool isSelectionActive = false;
656 if ((item != 0) && !isSelectionActive) {
657 // Updating the URL must be done outside the scope of this slot,
658 // as iconview items will get deleted.
659 QTimer::singleShot(0, this, SLOT(updateURL()));
660 Dolphin::mainWin().setActiveView(this);
661 }
662 }
663
664 void DolphinView::triggerDetailsViewItem(Q3ListViewItem* item,
665 const QPoint& pos,
666 int /* column */)
667 {
668 if (item == 0) {
669 return;
670 }
671
672 if (m_detailsView->isOnFilename(item, pos)) {
673 // Updating the URL must be done outside the scope of this slot,
674 // as listview items will get deleted.
675 QTimer::singleShot(0, this, SLOT(updateURL()));
676 Dolphin::mainWin().setActiveView(this);
677 }
678 else {
679 m_detailsView->clearSelection();
680 }
681 }
682
683 void DolphinView::triggerDetailsViewItem(Q3ListViewItem* item)
684 {
685 const QPoint pos(0, item->itemPos());
686 triggerDetailsViewItem(item, pos, 0);
687 }
688
689 void DolphinView::updateURL()
690 {
691 KFileView* fileView = (m_iconsView != 0) ? static_cast<KFileView*>(m_iconsView) :
692 static_cast<KFileView*>(m_detailsView);
693
694 KFileItem* fileItem = fileView->currentFileItem();
695 if (fileItem == 0) {
696 return;
697 }
698
699 if (fileItem->isDir()) {
700 // Prefer the local path over the URL. This assures that the
701 // volume space information is correct. Assuming that the URL is media:/sda1,
702 // and the local path is /windows/C: For the URL the space info is related
703 // to the root partition (and hence wrong) and for the local path the space
704 // info is related to the windows partition (-> correct).
705 const QString localPath(fileItem->localPath());
706 if (localPath.isEmpty()) {
707 setURL(fileItem->url());
708 }
709 else {
710 setURL(KUrl(localPath));
711 }
712 }
713 else {
714 fileItem->run();
715 }
716 }
717
718 void DolphinView::slotPercent(int percent)
719 {
720 if (m_showProgress) {
721 m_statusBar->setProgress(percent);
722 }
723 }
724
725 void DolphinView::slotClear()
726 {
727 fileView()->clearView();
728 updateStatusBar();
729 }
730
731 void DolphinView::slotDeleteItem(KFileItem* item)
732 {
733 fileView()->removeItem(item);
734 updateStatusBar();
735 }
736
737 void DolphinView::slotCompleted()
738 {
739 m_refreshing = true;
740
741 KFileView* view = fileView();
742 view->clearView();
743
744 // TODO: in Qt4 the code should get a lot
745 // simpler and nicer due to Interview...
746 if (m_iconsView != 0) {
747 m_iconsView->beginItemUpdates();
748 }
749 if (m_detailsView != 0) {
750 m_detailsView->beginItemUpdates();
751 }
752
753 if (m_showProgress) {
754 m_statusBar->setProgressText(QString::null);
755 m_statusBar->setProgress(100);
756 m_showProgress = false;
757 }
758
759 KFileItemList items(m_dirLister->items());
760 KFileItemList::const_iterator it = items.begin();
761 const KFileItemList::const_iterator end = items.end();
762
763 m_fileCount = 0;
764 m_folderCount = 0;
765
766 KFileItem* item = 0;
767 while (it != end) {
768 view->insertItem(item);
769 if (item->isDir()) {
770 ++m_folderCount;
771 }
772 else {
773 ++m_fileCount;
774 }
775 ++it;
776 }
777
778 updateStatusBar();
779
780 if (m_iconsView != 0) {
781 // Prevent a flickering of the icon view widget by giving a small
782 // timeslot to swallow asynchronous update events.
783 m_iconsView->setUpdatesEnabled(false);
784 QTimer::singleShot(10, this, SLOT(slotDelayedUpdate()));
785 }
786
787 if (m_detailsView != 0) {
788 m_detailsView->endItemUpdates();
789 m_refreshing = false;
790 }
791 }
792
793 void DolphinView::slotDelayedUpdate()
794 {
795 if (m_iconsView != 0) {
796 m_iconsView->setUpdatesEnabled(true);
797 m_iconsView->endItemUpdates();
798 }
799 m_refreshing = false;
800 }
801
802 void DolphinView::slotInfoMessage(const QString& msg)
803 {
804 m_statusBar->setMessage(msg, DolphinStatusBar::Information);
805 }
806
807 void DolphinView::slotErrorMessage(const QString& msg)
808 {
809 m_statusBar->setMessage(msg, DolphinStatusBar::Error);
810 }
811
812 void DolphinView::slotRefreshItems(const KFileItemList& /* list */)
813 {
814 QTimer::singleShot(0, this, SLOT(reload()));
815 }
816
817 void DolphinView::slotAddItems(const KFileItemList& list)
818 {
819 fileView()->addItemList(list);
820 fileView()->updateView();
821 }
822
823 void DolphinView::slotGrabActivation()
824 {
825 Dolphin::mainWin().setActiveView(this);
826 }
827
828 void DolphinView::slotContentsMoving(int x, int y)
829 {
830 if (!m_refreshing) {
831 // Only emit a 'contents moved' signal if the user
832 // moved the content by adjusting the sliders. Adjustments
833 // resulted by refreshing a directory should not be respected.
834 emit contentsMoved(x, y);
835 }
836 }
837
838 void DolphinView::createView()
839 {
840 assert(m_iconsView == 0);
841 assert(m_detailsView == 0);
842
843 switch (m_mode) {
844 case IconsView:
845 case PreviewsView: {
846 const DolphinIconsView::LayoutMode layoutMode = (m_mode == IconsView) ?
847 DolphinIconsView::Icons :
848 DolphinIconsView::Previews;
849 m_iconsView = new DolphinIconsView(this, layoutMode);
850 m_topLayout->insertWidget(1, m_iconsView);
851 setFocusProxy(m_iconsView);
852
853 connect(m_iconsView, SIGNAL(executed(Q3IconViewItem*)),
854 this, SLOT(triggerIconsViewItem(Q3IconViewItem*)));
855 connect(m_iconsView, SIGNAL(returnPressed(Q3IconViewItem*)),
856 this, SLOT(triggerIconsViewItem(Q3IconViewItem*)));
857 connect(m_iconsView, SIGNAL(signalRequestActivation()),
858 this, SLOT(slotGrabActivation()));
859
860 m_iconsView->endItemUpdates();
861 m_iconsView->show();
862 m_iconsView->setFocus();
863 break;
864 }
865
866 case DetailsView: {
867 m_detailsView = new DolphinDetailsView(this);
868 m_topLayout->insertWidget(1, m_detailsView);
869 setFocusProxy(m_detailsView);
870
871 connect(m_detailsView, SIGNAL(executed(Q3ListViewItem*, const QPoint&, int)),
872 this, SLOT(triggerDetailsViewItem(Q3ListViewItem*, const QPoint&, int)));
873 connect(m_detailsView, SIGNAL(returnPressed(Q3ListViewItem*)),
874 this, SLOT(triggerDetailsViewItem(Q3ListViewItem*)));
875 connect(m_detailsView, SIGNAL(signalRequestActivation()),
876 this, SLOT(slotGrabActivation()));
877 m_detailsView->show();
878 m_detailsView->setFocus();
879 break;
880 }
881
882 default:
883 break;
884 }
885
886 connect(scrollView(), SIGNAL(contentsMoving(int, int)),
887 this, SLOT(slotContentsMoving(int, int)));
888
889 startDirLister(m_urlNavigator->url());
890 }
891
892 KFileView* DolphinView::fileView() const
893 {
894 return (m_mode == DetailsView) ? static_cast<KFileView*>(m_detailsView) :
895 static_cast<KFileView*>(m_iconsView);
896 }
897
898 Q3ScrollView* DolphinView::scrollView() const
899 {
900 return (m_mode == DetailsView) ? static_cast<Q3ScrollView*>(m_detailsView) :
901 static_cast<Q3ScrollView*>(m_iconsView);
902 }
903
904 ItemEffectsManager* DolphinView::itemEffectsManager() const
905 {
906 return (m_mode == DetailsView) ? static_cast<ItemEffectsManager*>(m_detailsView) :
907 static_cast<ItemEffectsManager*>(m_iconsView);
908 }
909
910 void DolphinView::startDirLister(const KUrl& url, bool reload)
911 {
912 if (!url.isValid()) {
913 const QString location(url.pathOrUrl());
914 if (location.isEmpty()) {
915 m_statusBar->setMessage(i18n("The location is empty."), DolphinStatusBar::Error);
916 }
917 else {
918 m_statusBar->setMessage(i18n("The location '%1' is invalid.").arg(location),
919 DolphinStatusBar::Error);
920 }
921 return;
922 }
923
924 // Only show the directory loading progress if the status bar does
925 // not contain another progress information. This means that
926 // the directory loading progress information has the lowest priority.
927 const QString progressText(m_statusBar->progressText());
928 m_showProgress = progressText.isEmpty() ||
929 (progressText == i18n("Loading directory..."));
930 if (m_showProgress) {
931 m_statusBar->setProgressText(i18n("Loading directory..."));
932 m_statusBar->setProgress(0);
933 }
934
935 m_refreshing = true;
936 m_dirLister->stop();
937 m_dirLister->openUrl(url, false, reload);
938 }
939
940 QString DolphinView::defaultStatusBarText() const
941 {
942 // TODO: the following code is not suitable for languages where multiple forms
943 // of plurals are given (e. g. in Poland three forms of plurals exist).
944 const int itemCount = m_folderCount + m_fileCount;
945
946 QString text;
947 if (itemCount == 1) {
948 text = i18n("1 Item");
949 }
950 else {
951 text = i18n("%1 Items").arg(itemCount);
952 }
953
954 text += " (";
955
956 if (m_folderCount == 1) {
957 text += i18n("1 Folder");
958 }
959 else {
960 text += i18n("%1 Folders").arg(m_folderCount);
961 }
962
963 text += ", ";
964
965 if (m_fileCount == 1) {
966 text += i18n("1 File");
967 }
968 else {
969 text += i18n("%1 Files").arg(m_fileCount);
970 }
971
972 text += ")";
973
974 return text;
975 }
976
977 QString DolphinView::selectionStatusBarText() const
978 {
979 // TODO: the following code is not suitable for languages where multiple forms
980 // of plurals are given (e. g. in Poland three forms of plurals exist).
981 QString text;
982 const KFileItemList* list = selectedItems();
983 assert((list != 0) && !list->isEmpty());
984
985 int fileCount = 0;
986 int folderCount = 0;
987 KIO::filesize_t byteSize = 0;
988 KFileItemList::const_iterator it = list->begin();
989 const KFileItemList::const_iterator end = list->end();
990 while (it != end){
991 KFileItem* item = *it;
992 if (item->isDir()) {
993 ++folderCount;
994 }
995 else {
996 ++fileCount;
997 byteSize += item->size();
998 }
999 ++it;
1000 }
1001
1002 if (folderCount == 1) {
1003 text = i18n("1 Folder selected");
1004 }
1005 else if (folderCount > 1) {
1006 text = i18n("%1 Folders selected").arg(folderCount);
1007 }
1008
1009 if ((fileCount > 0) && (folderCount > 0)) {
1010 text += ", ";
1011 }
1012
1013 const QString sizeText(KIO::convertSize(byteSize));
1014 if (fileCount == 1) {
1015 text += i18n("1 File selected (%1)").arg(sizeText);
1016 }
1017 else if (fileCount > 1) {
1018 text += i18n("%1 Files selected (%1)").arg(fileCount).arg(sizeText);
1019 }
1020
1021 return text;
1022 }
1023
1024 QString DolphinView::renameIndexPresentation(int index, int itemCount) const
1025 {
1026 // assure that the string reprentation for all indicess have the same
1027 // number of characters based on the given number of items
1028 QString str(QString::number(index));
1029 int chrCount = 1;
1030 while (itemCount >= 10) {
1031 ++chrCount;
1032 itemCount /= 10;
1033 }
1034 str.reserve(chrCount);
1035
1036 const int insertCount = chrCount - str.length();
1037 for (int i = 0; i < insertCount; ++i) {
1038 str.insert(0, '0');
1039 }
1040 return str;
1041 }
1042
1043 void DolphinView::slotShowFilterBar(bool show)
1044 {
1045 assert(m_filterBar != 0);
1046 if (show) {
1047 m_filterBar->show();
1048 }
1049 else {
1050 m_filterBar->hide();
1051 }
1052 }
1053
1054 void DolphinView::slotChangeNameFilter(const QString& nameFilter)
1055 {
1056 // The name filter of KDirLister does a 'hard' filtering, which
1057 // means that only the items are shown where the names match
1058 // exactly the filter. This is non-transparent for the user, which
1059 // just wants to have a 'soft' filtering: does the name contain
1060 // the filter string?
1061 QString adjustedFilter(nameFilter);
1062 adjustedFilter.insert(0, '*');
1063 adjustedFilter.append('*');
1064
1065 m_dirLister->setNameFilter(adjustedFilter);
1066 m_dirLister->emitChanges();
1067
1068 // TODO: this is a workaround for QIconView: the item position
1069 // stay as they are by filtering, only an inserting of an item
1070 // results to an automatic adjusting of the item position. In Qt4/KDE4
1071 // this workaround should get obsolete due to Interview.
1072 KFileView* view = fileView();
1073 if (view == m_iconsView) {
1074 KFileItem* first = view->firstFileItem();
1075 if (first != 0) {
1076 view->removeItem(first);
1077 view->insertItem(first);
1078 }
1079 }
1080 }
1081
1082 bool DolphinView::isFilterBarVisible()
1083 {
1084 return m_filterBar->isVisible();
1085 }
1086
1087 #include "dolphinview.moc"