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