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