1 /* This file is part of the KDE libraries
2 Copyright (C) 1999,2000 Stephan Kulow <coolo@kde.org>
3 1999,2000,2001,2002,2003 Carsten Pfeiffer <pfeiffer@kde.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library 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 GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 #include "kdiroperator.h"
22 #include "kdirmodel.h"
23 #include "kdiroperatordetailview_p.h"
24 #include "kdirsortfilterproxymodel.h"
25 #include "kfileitem.h"
26 #include "kfilemetapreview.h"
27 #include "kpreviewwidgetbase.h"
29 #include <config-kfile.h>
33 #include <QtCore/QDir>
34 #include <QtCore/QRegExp>
35 #include <QtCore/QTimer>
36 #include <QtCore/QAbstractItemModel>
37 #include <QtGui/QApplication>
38 #include <QtGui/QDialog>
39 #include <QtGui/QHeaderView>
40 #include <QtGui/QLabel>
41 #include <QtGui/QLayout>
42 #include <QtGui/QListView>
43 #include <QtGui/QMouseEvent>
44 #include <QtGui/QTreeView>
45 #include <QtGui/QPushButton>
46 #include <QtGui/QProgressBar>
47 #include <QtGui/QScrollBar>
48 #include <QtGui/QSplitter>
49 #include <QtGui/QWheelEvent>
52 #include <kapplication.h>
55 #include <kdirlister.h>
56 #include <kfileitemdelegate.h>
58 #include <kinputdialog.h>
60 #include <kmessagebox.h>
62 #include <kstandardaction.h>
64 #include <kio/deletejob.h>
65 #include <kio/copyjob.h>
66 #include <kio/jobuidelegate.h>
67 #include <kio/jobclasses.h>
68 #include <kio/netaccess.h>
69 #include <kio/previewjob.h>
70 #include <kio/renamedialog.h>
71 #include <kfilepreviewgenerator.h>
72 #include <kpropertiesdialog.h>
73 #include <kstandardshortcut.h>
75 #include <kactioncollection.h>
76 #include <ktoggleaction.h>
77 #include <kactionmenu.h>
78 #include <kconfiggroup.h>
79 #include <kdeversion.h>
82 template class QHash
<QString
, KFileItem
>;
84 static QStyleOptionViewItem::Position decorationPosition
= QStyleOptionViewItem::Left
;
87 * Default icon view for KDirOperator using
88 * custom view options.
90 class KDirOperatorIconView
: public QListView
93 KDirOperatorIconView(QWidget
*parent
= 0);
94 virtual ~KDirOperatorIconView();
97 virtual QStyleOptionViewItem
viewOptions() const;
98 virtual void dragEnterEvent(QDragEnterEvent
* event
);
99 virtual void mousePressEvent(QMouseEvent
*event
);
100 virtual void wheelEvent(QWheelEvent
*event
);
103 KDirOperatorIconView::KDirOperatorIconView(QWidget
*parent
) :
106 setViewMode(QListView::IconMode
);
107 setFlow(QListView::TopToBottom
);
108 setResizeMode(QListView::Adjust
);
109 setSpacing(KDialog::spacingHint());
110 setMovement(QListView::Static
);
111 setDragDropMode(QListView::DragOnly
);
112 setVerticalScrollMode(QListView::ScrollPerPixel
);
113 setHorizontalScrollMode(QListView::ScrollPerPixel
);
114 setEditTriggers(QAbstractItemView::NoEditTriggers
);
116 setIconSize(QSize(KIconLoader::SizeSmall
, KIconLoader::SizeSmall
));
119 KDirOperatorIconView::~KDirOperatorIconView()
123 QStyleOptionViewItem
KDirOperatorIconView::viewOptions() const
125 QStyleOptionViewItem viewOptions
= QListView::viewOptions();
126 viewOptions
.showDecorationSelected
= true;
127 viewOptions
.decorationPosition
= decorationPosition
;
128 if (decorationPosition
== QStyleOptionViewItem::Left
) {
129 viewOptions
.displayAlignment
= Qt::AlignLeft
| Qt::AlignVCenter
;
131 viewOptions
.displayAlignment
= Qt::AlignCenter
;
137 void KDirOperatorIconView::dragEnterEvent(QDragEnterEvent
* event
)
139 if (event
->mimeData()->hasUrls()) {
140 event
->acceptProposedAction();
144 void KDirOperatorIconView::mousePressEvent(QMouseEvent
*event
)
146 if (!indexAt(event
->pos()).isValid()) {
147 const Qt::KeyboardModifiers modifiers
= QApplication::keyboardModifiers();
148 if (!(modifiers
& Qt::ShiftModifier
) && !(modifiers
& Qt::ControlModifier
)) {
153 QListView::mousePressEvent(event
);
156 void KDirOperatorIconView::wheelEvent(QWheelEvent
*event
)
158 QListView::wheelEvent(event
);
160 // apply the vertical wheel event to the horizontal scrollbar, as
161 // the items are aligned from left to right
162 if (event
->orientation() == Qt::Vertical
) {
163 QWheelEvent
horizEvent(event
->pos(),
168 QApplication::sendEvent(horizontalScrollBar(), &horizEvent
);
172 class KDirOperator::Private
175 Private( KDirOperator
*parent
);
178 enum InlinePreviewState
{
185 bool checkPreviewInternal() const;
186 void checkPath(const QString
&txt
, bool takeFiles
= false);
187 bool openUrl(const KUrl
&url
, KDirLister::OpenUrlFlags flags
= KDirLister::NoFlags
);
188 int sortColumn() const;
189 Qt::SortOrder
sortOrder() const;
190 void triggerSorting();
192 static bool isReadable(const KUrl
&url
);
194 KFile::FileView
allViews();
197 void _k_slotDetailedView();
198 void _k_slotSimpleView();
199 void _k_slotTreeView();
200 void _k_slotDetailedTreeView();
201 void _k_slotToggleHidden(bool);
202 void _k_togglePreview(bool);
203 void _k_toggleInlinePreviews(bool);
204 void _k_slotSortByName();
205 void _k_slotSortBySize();
206 void _k_slotSortByDate();
207 void _k_slotSortByType();
208 void _k_slotSortReversed(bool doReverse
);
209 void _k_slotToggleDirsFirst();
210 void _k_slotToggleIgnoreCase();
211 void _k_slotStarted();
212 void _k_slotProgress(int);
213 void _k_slotShowProgress();
214 void _k_slotIOFinished();
215 void _k_slotCanceled();
216 void _k_slotRedirected(const KUrl
&);
217 void _k_slotProperties();
218 void _k_slotPressed(const QModelIndex
&);
219 void _k_slotActivated(const QModelIndex
&);
220 void _k_slotDoubleClicked(const QModelIndex
&);
221 void _k_slotSelectionChanged();
222 void _k_openContextMenu(const QPoint
&);
223 void _k_triggerPreview(const QModelIndex
&);
224 void _k_showPreview();
225 void _k_slotSplitterMoved(int, int);
226 void _k_assureVisibleSelection();
227 void _k_synchronizeSortingState(int, Qt::SortOrder
);
228 void _k_slotChangeDecorationPosition();
229 void _k_slotExpandToUrl(const QModelIndex
&);
231 void updateListViewGrid();
232 int iconSizeForViewType(QAbstractItemView
*itemView
) const;
235 KDirOperator
*parent
;
236 QStack
<KUrl
*> backStack
; ///< Contains all URLs you can reach with the back button.
237 QStack
<KUrl
*> forwardStack
; ///< Contains all URLs you can reach with the forward button.
239 QModelIndex lastHoveredIndex
;
241 KDirLister
*dirLister
;
244 KCompletion completion
;
245 KCompletion dirCompletion
;
246 bool completeListDirty
;
247 QDir::SortFlags sorting
;
251 QAbstractItemView
*itemView
;
253 KDirSortFilterProxyModel
*proxyModel
;
255 KFileItemList pendingMimeTypes
;
257 // the enum KFile::FileView as an int
262 QProgressBar
*progressBar
;
264 KPreviewWidgetBase
*preview
;
268 bool leftButtonPressed
;
269 bool dirHighlighting
;
270 bool onlyDoubleClickSelectsFiles
;
271 QString lastURL
; // used for highlighting a directory on cdUp
272 QTimer
*progressDelayTimer
;
275 KActionMenu
*actionMenu
;
276 KActionCollection
*actionCollection
;
278 KConfigGroup
*configGroup
;
280 KFilePreviewGenerator
*previewGenerator
;
287 KActionMenu
*decorationMenu
;
288 KToggleAction
*leftAction
;
289 KUrl::List itemsToBeSetAsCurrent
;
290 bool shouldFetchForItems
;
291 InlinePreviewState inlinePreviewState
;
294 KDirOperator::Private::Private(KDirOperator
*_parent
) :
305 leftButtonPressed(false),
306 dirHighlighting(false),
307 onlyDoubleClickSelectsFiles(!KGlobalSettings::singleClick()),
308 progressDelayTimer(0),
319 shouldFetchForItems(false),
320 inlinePreviewState(NotForced
)
324 KDirOperator::Private::~Private()
330 // if (configGroup) {
331 // itemView->writeConfig(configGroup);
334 qDeleteAll(backStack
);
335 qDeleteAll(forwardStack
);
343 dirLister
= 0; // deleted by KDirModel
347 delete progressDelayTimer
;
348 progressDelayTimer
= 0;
351 KDirOperator::KDirOperator(const KUrl
& _url
, QWidget
*parent
) :
355 d
->splitter
= new QSplitter(this);
356 d
->splitter
->setChildrenCollapsible(false);
357 connect(d
->splitter
, SIGNAL(splitterMoved(int, int)),
358 this, SLOT(_k_slotSplitterMoved(int, int)));
362 d
->mode
= KFile::File
;
363 d
->viewKind
= KFile::Simple
;
364 d
->sorting
= QDir::Name
| QDir::DirsFirst
;
366 if (_url
.isEmpty()) { // no dir specified -> current dir
367 QString strPath
= QDir::currentPath();
368 strPath
.append(QChar('/'));
370 d
->currUrl
.setProtocol(QLatin1String("file"));
371 d
->currUrl
.setPath(strPath
);
374 if (d
->currUrl
.protocol().isEmpty())
375 d
->currUrl
.setProtocol(QLatin1String("file"));
377 d
->currUrl
.addPath("/"); // make sure we have a trailing slash!
380 // We set the direction of this widget to LTR, since even on RTL desktops
381 // viewing directory listings in RTL mode makes people's head explode.
382 // Is this the correct place? Maybe it should be in some lower level widgets...?
383 setLayoutDirection(Qt::LeftToRight
);
384 setDirLister(new KDirLister());
386 connect(&d
->completion
, SIGNAL(match(const QString
&)),
387 SLOT(slotCompletionMatch(const QString
&)));
389 d
->progressBar
= new QProgressBar(this);
390 d
->progressBar
->setObjectName("d->progressBar");
391 d
->progressBar
->adjustSize();
392 d
->progressBar
->move(2, height() - d
->progressBar
->height() - 2);
394 d
->progressDelayTimer
= new QTimer(this);
395 d
->progressDelayTimer
->setObjectName(QLatin1String("d->progressBar delay timer"));
396 connect(d
->progressDelayTimer
, SIGNAL(timeout()),
397 SLOT(_k_slotShowProgress()));
399 d
->completeListDirty
= false;
405 setFocusPolicy(Qt::WheelFocus
);
408 KDirOperator::~KDirOperator()
415 void KDirOperator::setSorting(QDir::SortFlags spec
)
422 QDir::SortFlags
KDirOperator::sorting() const
427 bool KDirOperator::isRoot() const
430 if (url().isLocalFile()) {
431 const QString path
= url().toLocalFile();
432 if (path
.length() >= 2)
433 return (path
[0].isLetter() && path
[1] == ':');
437 return url().path() == QString(QLatin1Char('/'));
440 KDirLister
*KDirOperator::dirLister() const
445 void KDirOperator::resetCursor()
448 QApplication::restoreOverrideCursor();
449 d
->progressBar
->hide();
452 void KDirOperator::sortByName()
454 d
->sorting
= QDir::Name
;
455 d
->actionCollection
->action("by name")->setChecked(true);
458 void KDirOperator::sortBySize()
460 d
->sorting
= (d
->sorting
& ~QDir::SortByMask
) | QDir::Size
;
461 d
->actionCollection
->action("by size")->setChecked(true);
464 void KDirOperator::sortByDate()
466 d
->sorting
= (d
->sorting
& ~QDir::SortByMask
) | QDir::Time
;
467 d
->actionCollection
->action("by date")->setChecked(true);
470 void KDirOperator::sortByType()
472 d
->sorting
= (d
->sorting
& ~QDir::SortByMask
) | QDir::Type
;
473 d
->actionCollection
->action("by type")->setChecked(true);
476 void KDirOperator::sortReversed()
478 if (d
->sorting
& QDir::Reversed
) {
479 d
->sorting
= d
->sorting
& ~QDir::Reversed
;
480 d
->actionCollection
->action("descending")->setChecked(false);
482 d
->sorting
= d
->sorting
| QDir::Reversed
;
483 d
->actionCollection
->action("descending")->setChecked(true);
487 void KDirOperator::toggleDirsFirst()
489 // TODO: not offered yet
492 void KDirOperator::toggleIgnoreCase()
494 if (d
->proxyModel
!= 0) {
495 Qt::CaseSensitivity cs
= d
->proxyModel
->sortCaseSensitivity();
496 cs
= (cs
== Qt::CaseSensitive
) ? Qt::CaseInsensitive
: Qt::CaseSensitive
;
497 d
->proxyModel
->setSortCaseSensitivity(cs
);
501 void KDirOperator::updateSelectionDependentActions()
503 const bool hasSelection
= (d
->itemView
!= 0) &&
504 d
->itemView
->selectionModel()->hasSelection();
505 d
->actionCollection
->action("trash")->setEnabled(hasSelection
);
506 d
->actionCollection
->action("delete")->setEnabled(hasSelection
);
507 d
->actionCollection
->action("properties")->setEnabled(hasSelection
);
510 void KDirOperator::setPreviewWidget(KPreviewWidgetBase
*w
)
512 const bool showPreview
= (w
!= 0);
514 d
->viewKind
= (d
->viewKind
| KFile::PreviewContents
);
516 d
->viewKind
= (d
->viewKind
& ~KFile::PreviewContents
);
523 d
->splitter
->addWidget(w
);
526 KToggleAction
*previewAction
= static_cast<KToggleAction
*>(d
->actionCollection
->action("preview"));
527 previewAction
->setEnabled(showPreview
);
528 previewAction
->setChecked(showPreview
);
529 setView(static_cast<KFile::FileView
>(d
->viewKind
));
532 KFileItemList
KDirOperator::selectedItems() const
534 KFileItemList itemList
;
535 if (d
->itemView
== 0) {
539 const QItemSelection selection
= d
->proxyModel
->mapSelectionToSource(d
->itemView
->selectionModel()->selection());
541 const QModelIndexList indexList
= selection
.indexes();
542 foreach(const QModelIndex
&index
, indexList
) {
543 KFileItem item
= d
->dirModel
->itemForIndex(index
);
544 if (!item
.isNull()) {
545 itemList
.append(item
);
552 bool KDirOperator::isSelected(const KFileItem
&item
) const
554 if ((item
.isNull()) || (d
->itemView
== 0)) {
558 const QModelIndex dirIndex
= d
->dirModel
->indexForItem(item
);
559 const QModelIndex proxyIndex
= d
->proxyModel
->mapFromSource(dirIndex
);
560 return d
->itemView
->selectionModel()->isSelected(proxyIndex
);
563 int KDirOperator::numDirs() const
565 return (d
->dirLister
== 0) ? 0 : d
->dirLister
->directories().count();
568 int KDirOperator::numFiles() const
570 return (d
->dirLister
== 0) ? 0 : d
->dirLister
->items().count() - numDirs();
573 KCompletion
* KDirOperator::completionObject() const
575 return const_cast<KCompletion
*>(&d
->completion
);
578 KCompletion
*KDirOperator::dirCompletionObject() const
580 return const_cast<KCompletion
*>(&d
->dirCompletion
);
583 KActionCollection
* KDirOperator::actionCollection() const
585 return d
->actionCollection
;
588 KFile::FileView
KDirOperator::Private::allViews() {
589 return static_cast<KFile::FileView
>(KFile::Simple
| KFile::Detail
| KFile::Tree
| KFile::DetailTree
);
592 void KDirOperator::Private::_k_slotDetailedView()
594 KFile::FileView view
= static_cast<KFile::FileView
>((viewKind
& ~allViews()) | KFile::Detail
);
595 parent
->setView(view
);
598 void KDirOperator::Private::_k_slotSimpleView()
600 KFile::FileView view
= static_cast<KFile::FileView
>((viewKind
& ~allViews()) | KFile::Simple
);
601 parent
->setView(view
);
604 void KDirOperator::Private::_k_slotTreeView()
606 KFile::FileView view
= static_cast<KFile::FileView
>((viewKind
& ~allViews()) | KFile::Tree
);
607 parent
->setView(view
);
610 void KDirOperator::Private::_k_slotDetailedTreeView()
612 KFile::FileView view
= static_cast<KFile::FileView
>((viewKind
& ~allViews()) | KFile::DetailTree
);
613 parent
->setView(view
);
616 void KDirOperator::Private::_k_slotToggleHidden(bool show
)
618 dirLister
->setShowingDotFiles(show
);
620 _k_assureVisibleSelection();
623 void KDirOperator::Private::_k_togglePreview(bool on
)
626 viewKind
= viewKind
| KFile::PreviewContents
;
628 preview
= new KFileMetaPreview(parent
);
629 actionCollection
->action("preview")->setChecked(true);
630 splitter
->addWidget(preview
);
635 QMetaObject::invokeMethod(parent
, "_k_assureVisibleSelection", Qt::QueuedConnection
);
637 const QModelIndex index
= itemView
->selectionModel()->currentIndex();
638 if (index
.isValid()) {
639 _k_triggerPreview(index
);
642 } else if (preview
!= 0) {
643 viewKind
= viewKind
& ~KFile::PreviewContents
;
648 void KDirOperator::Private::_k_toggleInlinePreviews(bool show
)
650 if (showPreviews
== show
) {
656 if (!previewGenerator
) {
660 previewGenerator
->setPreviewShown(show
);
663 // remove all generated previews
664 QAbstractItemModel
*model
= dirModel
;
665 for (int i
= 0; i
< model
->rowCount(); ++i
) {
666 QModelIndex index
= model
->index(i
, 0);
667 const KFileItem item
= dirModel
->itemForIndex(index
);
668 const_cast<QAbstractItemModel
*>(index
.model())->setData(index
, KIcon(item
.iconName()), Qt::DecorationRole
);
673 void KDirOperator::Private::_k_slotSortByName()
675 parent
->sortByName();
679 void KDirOperator::Private::_k_slotSortBySize()
681 parent
->sortBySize();
685 void KDirOperator::Private::_k_slotSortByDate()
687 parent
->sortByDate();
691 void KDirOperator::Private::_k_slotSortByType()
693 parent
->sortByType();
697 void KDirOperator::Private::_k_slotSortReversed(bool doReverse
)
700 sorting
|= QDir::Reversed
;
703 sorting
&= ~QDir::Reversed
;
709 void KDirOperator::Private::_k_slotToggleDirsFirst()
711 // TODO: port to Qt4's QAbstractItemView
712 /*if ( !d->fileView )
715 QDir::SortFlags sorting = d->fileView->sorting();
716 if ( !KFile::isSortDirsFirst( sorting ) )
717 d->fileView->setSorting( sorting | QDir::DirsFirst );
719 d->fileView->setSorting( sorting & ~QDir::DirsFirst );
720 d->sorting = d->fileView->sorting();*/
723 void KDirOperator::Private::_k_slotToggleIgnoreCase()
725 // TODO: port to Qt4's QAbstractItemView
726 /*if ( !d->fileView )
729 QDir::SortFlags sorting = d->fileView->sorting();
730 if ( !KFile::isSortCaseInsensitive( sorting ) )
731 d->fileView->setSorting( sorting | QDir::IgnoreCase );
733 d->fileView->setSorting( sorting & ~QDir::IgnoreCase );
734 d->sorting = d->fileView->sorting();*/
737 void KDirOperator::mkdir()
740 QString where
= url().pathOrUrl();
741 QString name
= i18n("New Folder");
743 if (url().isLocalFile() && QFileInfo(url().toLocalFile() + name
).exists())
745 if (url().isLocalFile() && QFileInfo(url().path(KUrl::AddTrailingSlash
) + name
).exists())
747 name
= KIO::RenameDialog::suggestName(url(), name
);
749 QString folder
= KInputDialog::getText(i18n("New Folder"),
750 i18n("Create new folder in:\n%1" , where
),
753 KDirOperator::mkdir(KIO::encodeFileName(folder
), true);
756 bool KDirOperator::mkdir(const QString
& directory
, bool enterDirectory
)
758 // Creates "directory", relative to the current directory (d->currUrl).
759 // The given path may contain any number directories, existent or not.
760 // They will all be created, if possible.
762 bool writeOk
= false;
764 KUrl
url(d
->currUrl
);
766 const QStringList dirs
= directory
.split(QDir::separator(), QString::SkipEmptyParts
);
767 QStringList::ConstIterator it
= dirs
.begin();
769 for (; it
!= dirs
.end(); ++it
) {
771 exists
= KIO::NetAccess::exists(url
, KIO::NetAccess::DestinationSide
, 0);
772 writeOk
= !exists
&& KIO::NetAccess::mkdir(url
, topLevelWidget());
775 if (exists
) { // url was already existent
776 KMessageBox::sorry(d
->itemView
, i18n("A file or folder named %1 already exists.", url
.pathOrUrl()));
777 enterDirectory
= false;
778 } else if (!writeOk
) {
779 KMessageBox::sorry(d
->itemView
, i18n("You do not have permission to "
780 "create that folder."));
781 } else if (enterDirectory
) {
788 KIO::DeleteJob
* KDirOperator::del(const KFileItemList
& items
,
790 bool ask
, bool showProgress
)
792 if (items
.isEmpty()) {
793 KMessageBox::information(parent
,
794 i18n("You did not select a file to delete."),
795 i18n("Nothing to Delete"));
805 foreach (const KFileItem
&item
, items
) {
806 const KUrl url
= item
.url();
808 files
.append(url
.pathOrUrl());
814 if (items
.count() == 1) {
815 ret
= KMessageBox::warningContinueCancel(parent
,
816 i18n("<qt>Do you really want to delete\n <b>'%1'</b>?</qt>" ,
819 KStandardGuiItem::del(),
820 KStandardGuiItem::cancel(), "AskForDelete");
822 ret
= KMessageBox::warningContinueCancelList(parent
,
823 i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", items
.count()),
825 i18n("Delete Files"),
826 KStandardGuiItem::del(),
827 KStandardGuiItem::cancel(), "AskForDelete");
828 doIt
= (ret
== KMessageBox::Continue
);
832 KIO::JobFlags flags
= showProgress
? KIO::DefaultFlags
: KIO::HideProgressInfo
;
833 KIO::DeleteJob
*job
= KIO::del(urls
, flags
);
834 job
->ui()->setWindow(topLevelWidget());
835 job
->ui()->setAutoErrorHandlingEnabled(true);
842 void KDirOperator::deleteSelected()
844 const KFileItemList list
= selectedItems();
845 if (!list
.isEmpty()) {
850 KIO::CopyJob
* KDirOperator::trash(const KFileItemList
& items
,
852 bool ask
, bool showProgress
)
854 if (items
.isEmpty()) {
855 KMessageBox::information(parent
,
856 i18n("You did not select a file to trash."),
857 i18n("Nothing to Trash"));
863 foreach (const KFileItem
&item
, items
) {
864 const KUrl url
= item
.url();
866 files
.append(url
.pathOrUrl());
872 if (items
.count() == 1) {
873 ret
= KMessageBox::warningContinueCancel(parent
,
874 i18n("<qt>Do you really want to trash\n <b>'%1'</b>?</qt>" ,
877 KGuiItem(i18nc("to trash", "&Trash"), "user-trash"),
878 KStandardGuiItem::cancel(), "AskForTrash");
880 ret
= KMessageBox::warningContinueCancelList(parent
,
881 i18np("translators: not called for n == 1", "Do you really want to trash these %1 items?", items
.count()),
884 KGuiItem(i18nc("to trash", "&Trash"), "user-trash"),
885 KStandardGuiItem::cancel(), "AskForTrash");
886 doIt
= (ret
== KMessageBox::Continue
);
890 KIO::JobFlags flags
= showProgress
? KIO::DefaultFlags
: KIO::HideProgressInfo
;
891 KIO::CopyJob
*job
= KIO::trash(urls
, flags
);
892 job
->ui()->setWindow(topLevelWidget());
893 job
->ui()->setAutoErrorHandlingEnabled(true);
900 KFilePreviewGenerator
*KDirOperator::previewGenerator() const
902 return d
->previewGenerator
;
905 void KDirOperator::setInlinePreviewShown(bool show
)
907 d
->inlinePreviewState
= show
? Private::ForcedToTrue
: Private::ForcedToFalse
;
910 bool KDirOperator::isInlinePreviewShown() const
912 return d
->showPreviews
;
915 int KDirOperator::iconsZoom() const
920 void KDirOperator::setIsSaving(bool isSaving
)
922 d
->isSaving
= isSaving
;
925 bool KDirOperator::isSaving() const
930 void KDirOperator::trashSelected()
932 if (d
->itemView
== 0) {
936 if (QApplication::keyboardModifiers() & Qt::ShiftModifier
) {
941 const KFileItemList list
= selectedItems();
942 if (!list
.isEmpty()) {
947 void KDirOperator::setIconsZoom(int _value
)
949 if (d
->iconsZoom
== _value
) {
954 value
= qMin(100, value
);
955 value
= qMax(0, value
);
957 d
->iconsZoom
= value
;
959 if (d
->configGroup
&& d
->inlinePreviewState
== Private::NotForced
) {
960 if (qobject_cast
<QListView
*>(d
->itemView
)) {
961 d
->configGroup
->writeEntry("listViewIconSize", d
->iconsZoom
);
963 d
->configGroup
->writeEntry("detailedViewIconSize", d
->iconsZoom
);
967 if (!d
->previewGenerator
) {
971 const int maxSize
= KIconLoader::SizeEnormous
- KIconLoader::SizeSmall
;
972 const int val
= (maxSize
* value
/ 100) + KIconLoader::SizeSmall
;
973 d
->itemView
->setIconSize(QSize(val
, val
));
974 d
->updateListViewGrid();
975 d
->previewGenerator
->updatePreviews();
977 emit
currentIconSizeChanged(value
);
980 void KDirOperator::close()
983 d
->pendingMimeTypes
.clear();
984 d
->completion
.clear();
985 d
->dirCompletion
.clear();
986 d
->completeListDirty
= true;
987 d
->dirLister
->stop();
990 void KDirOperator::Private::checkPath(const QString
&, bool /*takeFiles*/) // SLOT
993 // copy the argument in a temporary string
995 // it's unlikely to happen, that at the beginning are spaces, but
996 // for the end, it happens quite often, I guess.
997 text
= text
.trimmed();
998 // if the argument is no URL (the check is quite fragil) and it's
999 // no absolute path, we add the current directory to get a correct url
1000 if (text
.find(':') < 0 && text
[0] != '/')
1001 text
.insert(0, d
->currUrl
);
1003 // in case we have a selection defined and someone patched the file-
1004 // name, we check, if the end of the new name is changed.
1005 if (!selection
.isNull()) {
1006 int position
= text
.lastIndexOf('/');
1007 ASSERT(position
>= 0); // we already inserted the current d->dirLister in case
1008 QString filename
= text
.mid(position
+ 1, text
.length());
1009 if (filename
!= selection
)
1013 KUrl
u(text
); // I have to take care of entered URLs
1014 bool filenameEntered
= false;
1016 if (u
.isLocalFile()) {
1017 // the empty path is kind of a hack
1018 KFileItem
i("", u
.toLocalFile());
1023 if (acceptOnlyExisting
&& !i
.isFile())
1024 warning("you entered an invalid URL");
1026 filenameEntered
= true;
1031 if (filenameEntered
) {
1032 filename_
= u
.url();
1033 emit
fileSelected(filename_
);
1035 QApplication::restoreOverrideCursor();
1040 kDebug(kfile_area
) << "TODO KDirOperator::checkPath()";
1043 void KDirOperator::setUrl(const KUrl
& _newurl
, bool clearforward
)
1047 if (!_newurl
.isValid())
1048 newurl
.setPath(QDir::homePath());
1052 newurl
.adjustPath( KUrl::AddTrailingSlash
);
1054 QString pathstr
= QDir::fromNativeSeparators(newurl
.toLocalFile());
1056 QString pathstr
= newurl
.path();
1058 newurl
.setPath(pathstr
);
1061 if (newurl
.equals(d
->currUrl
, KUrl::CompareWithoutTrailingSlash
))
1064 if (!Private::isReadable(newurl
)) {
1065 // maybe newurl is a file? check its parent directory
1066 newurl
.setPath(newurl
.directory());
1067 if (newurl
.equals(d
->currUrl
, KUrl::CompareWithoutTrailingSlash
))
1068 return; // parent is current dir, nothing to do (fixes #173454, too)
1069 KIO::UDSEntry entry
;
1070 bool res
= KIO::NetAccess::stat(newurl
, entry
, this);
1071 KFileItem
i(entry
, newurl
);
1072 if ((!res
|| !Private::isReadable(newurl
)) && i
.isDir()) {
1074 KMessageBox::error(d
->itemView
,
1075 i18n("The specified folder does not exist "
1076 "or was not readable."));
1078 } else if (!i
.isDir()) {
1084 // autodelete should remove this one
1085 d
->backStack
.push(new KUrl(d
->currUrl
));
1086 qDeleteAll(d
->forwardStack
);
1087 d
->forwardStack
.clear();
1090 d
->lastURL
= d
->currUrl
.url(KUrl::RemoveTrailingSlash
);
1091 d
->currUrl
= newurl
;
1094 emit
urlEntered(newurl
);
1096 // enable/disable actions
1097 QAction
* forwardAction
= d
->actionCollection
->action("forward");
1098 forwardAction
->setEnabled(!d
->forwardStack
.isEmpty());
1100 QAction
* backAction
= d
->actionCollection
->action("back");
1101 backAction
->setEnabled(!d
->backStack
.isEmpty());
1103 QAction
* upAction
= d
->actionCollection
->action("up");
1104 upAction
->setEnabled(!isRoot());
1109 void KDirOperator::updateDir()
1111 QApplication::setOverrideCursor(Qt::WaitCursor
);
1112 d
->dirLister
->emitChanges();
1113 QApplication::restoreOverrideCursor();
1116 void KDirOperator::rereadDir()
1119 d
->openUrl(d
->currUrl
, KDirLister::Reload
);
1123 bool KDirOperator::Private::openUrl(const KUrl
& url
, KDirLister::OpenUrlFlags flags
)
1125 bool result
= dirLister
->openUrl(url
, flags
);
1126 if (!result
) // in that case, neither completed() nor canceled() will be emitted by KDL
1132 int KDirOperator::Private::sortColumn() const
1134 int column
= KDirModel::Name
;
1135 if (KFile::isSortByDate(sorting
)) {
1136 column
= KDirModel::ModifiedTime
;
1137 } else if (KFile::isSortBySize(sorting
)) {
1138 column
= KDirModel::Size
;
1139 } else if (KFile::isSortByType(sorting
)) {
1140 column
= KDirModel::Type
;
1142 Q_ASSERT(KFile::isSortByName(sorting
));
1148 Qt::SortOrder
KDirOperator::Private::sortOrder() const
1150 return (sorting
& QDir::Reversed
) ? Qt::DescendingOrder
:
1154 void KDirOperator::Private::triggerSorting()
1156 proxyModel
->sort(sortColumn(), sortOrder());
1158 // TODO: The headers from QTreeView don't take care about a sorting
1159 // change of the proxy model hence they must be updated the manually.
1160 // This is done here by a qobject_cast, but it would be nicer to:
1161 // - provide a signal 'sortingChanged()'
1162 // - connect KDirOperatorDetailView() with this signal and update the
1163 // header internally
1164 QTreeView
* treeView
= qobject_cast
<QTreeView
*>(itemView
);
1165 if (treeView
!= 0) {
1166 QHeaderView
* headerView
= treeView
->header();
1167 headerView
->blockSignals(true);
1168 headerView
->setSortIndicator(sortColumn(), sortOrder());
1169 headerView
->blockSignals(false);
1172 _k_assureVisibleSelection();
1176 void KDirOperator::pathChanged()
1178 if (d
->itemView
== 0)
1181 d
->pendingMimeTypes
.clear();
1182 //d->fileView->clear(); TODO
1183 d
->completion
.clear();
1184 d
->dirCompletion
.clear();
1186 // it may be, that we weren't ready at this time
1187 QApplication::restoreOverrideCursor();
1189 // when KIO::Job emits finished, the slot will restore the cursor
1190 QApplication::setOverrideCursor(Qt::WaitCursor
);
1192 if (!Private::isReadable(d
->currUrl
)) {
1193 KMessageBox::error(d
->itemView
,
1194 i18n("The specified folder does not exist "
1195 "or was not readable."));
1196 if (d
->backStack
.isEmpty())
1203 void KDirOperator::Private::_k_slotRedirected(const KUrl
& newURL
)
1206 pendingMimeTypes
.clear();
1208 dirCompletion
.clear();
1209 completeListDirty
= true;
1210 emit parent
->urlEntered(newURL
);
1213 // Code pinched from kfm then hacked
1214 void KDirOperator::back()
1216 if (d
->backStack
.isEmpty())
1219 d
->forwardStack
.push(new KUrl(d
->currUrl
));
1221 KUrl
*s
= d
->backStack
.pop();
1227 // Code pinched from kfm then hacked
1228 void KDirOperator::forward()
1230 if (d
->forwardStack
.isEmpty())
1233 d
->backStack
.push(new KUrl(d
->currUrl
));
1235 KUrl
*s
= d
->forwardStack
.pop();
1240 KUrl
KDirOperator::url() const
1245 void KDirOperator::cdUp()
1247 KUrl
tmp(d
->currUrl
);
1248 tmp
.cd(QLatin1String(".."));
1252 void KDirOperator::home()
1255 u
.setPath(QDir::homePath());
1259 void KDirOperator::clearFilter()
1261 d
->dirLister
->setNameFilter(QString());
1262 d
->dirLister
->clearMimeFilter();
1263 checkPreviewSupport();
1266 void KDirOperator::setNameFilter(const QString
& filter
)
1268 d
->dirLister
->setNameFilter(filter
);
1269 checkPreviewSupport();
1272 QString
KDirOperator::nameFilter() const
1274 return d
->dirLister
->nameFilter();
1277 void KDirOperator::setMimeFilter(const QStringList
& mimetypes
)
1279 d
->dirLister
->setMimeFilter(mimetypes
);
1280 checkPreviewSupport();
1283 QStringList
KDirOperator::mimeFilter() const
1285 return d
->dirLister
->mimeFilters();
1288 bool KDirOperator::checkPreviewSupport()
1290 KToggleAction
*previewAction
= static_cast<KToggleAction
*>(d
->actionCollection
->action("preview"));
1292 bool hasPreviewSupport
= false;
1293 KConfigGroup
cg(KGlobal::config(), ConfigGroup
);
1294 if (cg
.readEntry("Show Default Preview", true))
1295 hasPreviewSupport
= d
->checkPreviewInternal();
1297 previewAction
->setEnabled(hasPreviewSupport
);
1298 return hasPreviewSupport
;
1301 void KDirOperator::activatedMenu(const KFileItem
&item
, const QPoint
&pos
)
1305 updateSelectionDependentActions();
1307 emit
contextMenuAboutToShow( item
, d
->actionMenu
->menu() );
1309 d
->actionMenu
->menu()->exec(pos
);
1312 void KDirOperator::changeEvent(QEvent
*event
)
1314 QWidget::changeEvent(event
);
1317 bool KDirOperator::eventFilter(QObject
*watched
, QEvent
*event
)
1321 // If we are not hovering any items, check if there is a current index
1322 // set. In that case, we show the preview of that item.
1323 switch(event
->type()) {
1324 case QEvent::MouseMove
: {
1326 const QModelIndex hoveredIndex
= d
->itemView
->indexAt(d
->itemView
->viewport()->mapFromGlobal(QCursor::pos()));
1328 if (d
->lastHoveredIndex
== hoveredIndex
)
1331 d
->lastHoveredIndex
= hoveredIndex
;
1333 const QModelIndex focusedIndex
= d
->itemView
->selectionModel() ? d
->itemView
->selectionModel()->currentIndex()
1336 if (!hoveredIndex
.isValid() && focusedIndex
.isValid() &&
1337 d
->itemView
->selectionModel()->isSelected(focusedIndex
) &&
1338 (d
->lastHoveredIndex
!= focusedIndex
)) {
1339 const QModelIndex sourceFocusedIndex
= d
->proxyModel
->mapToSource(focusedIndex
);
1340 const KFileItem item
= d
->dirModel
->itemForIndex(sourceFocusedIndex
);
1341 if (!item
.isNull()) {
1342 d
->preview
->showPreview(item
.url());
1348 case QEvent::MouseButtonRelease
: {
1349 if (d
->preview
!= 0) {
1350 const QModelIndex hoveredIndex
= d
->itemView
->indexAt(d
->itemView
->viewport()->mapFromGlobal(QCursor::pos()));
1351 const QModelIndex focusedIndex
= d
->itemView
->selectionModel() ? d
->itemView
->selectionModel()->currentIndex()
1354 if (((!focusedIndex
.isValid()) ||
1355 !d
->itemView
->selectionModel()->isSelected(focusedIndex
)) &&
1356 (!hoveredIndex
.isValid())) {
1357 d
->preview
->clearPreview();
1362 case QEvent::Wheel
: {
1363 QWheelEvent
*evt
= static_cast<QWheelEvent
*>(event
);
1364 if (evt
->modifiers() & Qt::ControlModifier
) {
1365 if (evt
->delta() > 0) {
1366 setIconsZoom(d
->iconsZoom
+ 10);
1368 setIconsZoom(d
->iconsZoom
- 10);
1381 bool KDirOperator::Private::checkPreviewInternal() const
1383 const QStringList supported
= KIO::PreviewJob::supportedMimeTypes();
1384 // no preview support for directories?
1385 if (parent
->dirOnlyMode() && supported
.indexOf("inode/directory") == -1)
1388 QStringList mimeTypes
= dirLister
->mimeFilters();
1389 const QStringList nameFilter
= dirLister
->nameFilter().split(' ', QString::SkipEmptyParts
);
1391 if (mimeTypes
.isEmpty() && nameFilter
.isEmpty() && !supported
.isEmpty())
1395 r
.setPatternSyntax(QRegExp::Wildcard
); // the "mimetype" can be "image/*"
1397 if (!mimeTypes
.isEmpty()) {
1398 QStringList::ConstIterator it
= supported
.begin();
1400 for (; it
!= supported
.end(); ++it
) {
1403 QStringList result
= mimeTypes
.filter(r
);
1404 if (!result
.isEmpty()) { // matches! -> we want previews
1410 if (!nameFilter
.isEmpty()) {
1411 // find the mimetypes of all the filter-patterns
1412 QStringList::const_iterator it1
= nameFilter
.begin();
1413 for (; it1
!= nameFilter
.end(); ++it1
) {
1414 if ((*it1
) == "*") {
1418 KMimeType::Ptr mt
= KMimeType::findByPath(*it1
, 0, true /*fast mode, no file contents exist*/);
1421 QString mime
= mt
->name();
1423 // the "mimetypes" we get from the PreviewJob can be "image/*"
1424 // so we need to check in wildcard mode
1425 QStringList::ConstIterator it2
= supported
.begin();
1426 for (; it2
!= supported
.end(); ++it2
) {
1428 if (r
.indexIn(mime
) != -1) {
1439 QAbstractItemView
* KDirOperator::createView(QWidget
* parent
, KFile::FileView viewKind
)
1441 QAbstractItemView
*itemView
= 0;
1442 if (KFile::isDetailView(viewKind
) || KFile::isTreeView(viewKind
) || KFile::isDetailTreeView(viewKind
)) {
1443 KDirOperatorDetailView
*detailView
= new KDirOperatorDetailView(parent
);
1444 detailView
->setViewMode(viewKind
);
1445 connect(detailView
->header(), SIGNAL(sortIndicatorChanged (int, Qt::SortOrder
)),
1446 this, SLOT(_k_synchronizeSortingState(int, Qt::SortOrder
)));
1447 itemView
= detailView
;
1449 itemView
= new KDirOperatorIconView(parent
);
1455 void KDirOperator::setAcceptDrops(bool b
)
1459 // d->fileView->widget()->setAcceptDrops(b);
1460 QWidget::setAcceptDrops(b
);
1463 void KDirOperator::setDropOptions(int options
)
1465 d
->dropOptions
= options
;
1468 // d->fileView->setDropOptions(options);
1471 void KDirOperator::setView(KFile::FileView viewKind
)
1473 bool preview
= (KFile::isPreviewInfo(viewKind
) || KFile::isPreviewContents(viewKind
));
1475 if (viewKind
== KFile::Default
) {
1476 if (KFile::isDetailView((KFile::FileView
)d
->defaultView
)) {
1477 viewKind
= KFile::Detail
;
1478 } else if (KFile::isTreeView((KFile::FileView
)d
->defaultView
)) {
1479 viewKind
= KFile::Tree
;
1480 } else if (KFile::isDetailTreeView((KFile::FileView
)d
->defaultView
)) {
1481 viewKind
= KFile::DetailTree
;
1483 viewKind
= KFile::Simple
;
1486 const KFile::FileView defaultViewKind
= static_cast<KFile::FileView
>(d
->defaultView
);
1487 preview
= (KFile::isPreviewInfo(defaultViewKind
) || KFile::isPreviewContents(defaultViewKind
))
1488 && d
->actionCollection
->action("preview")->isEnabled();
1491 d
->viewKind
= static_cast<int>(viewKind
);
1492 viewKind
= static_cast<KFile::FileView
>(d
->viewKind
);
1494 QAbstractItemView
*newView
= createView(this, viewKind
);
1497 d
->_k_togglePreview(preview
);
1500 QAbstractItemView
* KDirOperator::view() const
1505 KFile::Modes
KDirOperator::mode() const
1510 void KDirOperator::setMode(KFile::Modes mode
)
1512 if (d
->mode
== mode
)
1517 d
->dirLister
->setDirOnlyMode(dirOnlyMode());
1519 // reset the view with the different mode
1520 setView(static_cast<KFile::FileView
>(d
->viewKind
));
1523 void KDirOperator::setView(QAbstractItemView
*view
)
1525 if (view
== d
->itemView
) {
1529 // TODO: do a real timer and restart it after that
1530 d
->pendingMimeTypes
.clear();
1531 const bool listDir
= (d
->itemView
== 0);
1533 if (d
->mode
& KFile::Files
) {
1534 view
->setSelectionMode(QAbstractItemView::ExtendedSelection
);
1536 view
->setSelectionMode(QAbstractItemView::SingleSelection
);
1539 QItemSelectionModel
*selectionModel
= 0;
1540 if ((d
->itemView
!= 0) && d
->itemView
->selectionModel()->hasSelection()) {
1541 // remember the selection of the current item view and apply this selection
1542 // to the new view later
1543 const QItemSelection selection
= d
->itemView
->selectionModel()->selection();
1544 selectionModel
= new QItemSelectionModel(d
->proxyModel
, this);
1545 selectionModel
->select(selection
, QItemSelectionModel::Select
);
1551 d
->itemView
->setModel(d
->proxyModel
);
1552 setFocusProxy(d
->itemView
);
1554 view
->viewport()->installEventFilter(this);
1556 KFileItemDelegate
*delegate
= new KFileItemDelegate(d
->itemView
);
1557 d
->itemView
->setItemDelegate(delegate
);
1558 d
->itemView
->viewport()->setAttribute(Qt::WA_Hover
);
1559 d
->itemView
->setContextMenuPolicy(Qt::CustomContextMenu
);
1560 d
->itemView
->setMouseTracking(true);
1561 //d->itemView->setDropOptions(d->dropOptions);
1563 connect(d
->itemView
, SIGNAL(activated(const QModelIndex
&)),
1564 this, SLOT(_k_slotActivated(const QModelIndex
&)));
1565 connect(d
->itemView
, SIGNAL(doubleClicked(const QModelIndex
&)),
1566 this, SLOT(_k_slotDoubleClicked(const QModelIndex
&)));
1567 connect(d
->itemView
, SIGNAL(pressed(const QModelIndex
&)),
1568 this, SLOT(_k_slotPressed(const QModelIndex
&)));
1569 connect(d
->itemView
, SIGNAL(customContextMenuRequested(const QPoint
&)),
1570 this, SLOT(_k_openContextMenu(const QPoint
&)));
1571 connect(d
->itemView
, SIGNAL(entered(const QModelIndex
&)),
1572 this, SLOT(_k_triggerPreview(const QModelIndex
&)));
1573 // assure that the sorting state d->sorting matches with the current action
1574 const bool descending
= d
->actionCollection
->action("descending")->isChecked();
1576 d
->sorting
= d
->sorting
| QDir::Reversed
;
1578 d
->sorting
= d
->sorting
& ~QDir::Reversed
;
1580 d
->triggerSorting();
1582 updateViewActions();
1583 d
->splitter
->insertWidget(0, d
->itemView
);
1585 d
->splitter
->resize(size());
1586 d
->itemView
->show();
1589 QApplication::setOverrideCursor(Qt::WaitCursor
);
1590 d
->openUrl(d
->currUrl
);
1593 if (selectionModel
!= 0) {
1594 d
->itemView
->setSelectionModel(selectionModel
);
1595 QMetaObject::invokeMethod(this, "_k_assureVisibleSelection", Qt::QueuedConnection
);
1598 connect(d
->itemView
->selectionModel(),
1599 SIGNAL(currentChanged(const QModelIndex
&,const QModelIndex
&)),
1600 this, SLOT(_k_triggerPreview(const QModelIndex
&)));
1601 connect(d
->itemView
->selectionModel(),
1602 SIGNAL(selectionChanged(const QItemSelection
&, const QItemSelection
&)),
1603 this, SLOT(_k_slotSelectionChanged()));
1605 // if we cannot cast it to a QListView, disable the "Icon Position" menu. Note that this check
1606 // needs to be done here, and not in createView, since we can be set an external view
1607 d
->decorationMenu
->setEnabled(qobject_cast
<QListView
*>(d
->itemView
));
1609 d
->shouldFetchForItems
= qobject_cast
<QTreeView
*>(view
);
1610 if (d
->shouldFetchForItems
) {
1611 connect(d
->dirModel
, SIGNAL(expand(QModelIndex
)), this, SLOT(_k_slotExpandToUrl(QModelIndex
)));
1613 d
->itemsToBeSetAsCurrent
.clear();
1616 const bool previewForcedToTrue
= d
->inlinePreviewState
== Private::ForcedToTrue
;
1617 const bool previewShown
= d
->inlinePreviewState
== Private::NotForced
? d
->showPreviews
: previewForcedToTrue
;
1618 d
->previewGenerator
= new KFilePreviewGenerator(d
->itemView
);
1619 const int maxSize
= KIconLoader::SizeEnormous
- KIconLoader::SizeSmall
;
1620 const int val
= (maxSize
* d
->iconsZoom
/ 100) + KIconLoader::SizeSmall
;
1621 d
->itemView
->setIconSize(previewForcedToTrue
? QSize(KIconLoader::SizeHuge
, KIconLoader::SizeHuge
) : QSize(val
, val
));
1622 d
->previewGenerator
->setPreviewShown(previewShown
);
1623 d
->actionCollection
->action("inline preview")->setChecked(previewShown
);
1625 // ensure we change everything needed
1626 d
->_k_slotChangeDecorationPosition();
1628 emit
viewChanged(view
);
1630 const int zoom
= previewForcedToTrue
? (KIconLoader::SizeHuge
- KIconLoader::SizeSmall
+ 1) * 100 / maxSize
: d
->iconSizeForViewType(view
);
1632 // this will make d->iconsZoom be updated, since setIconsZoom slot will be called
1633 emit
currentIconSizeChanged(zoom
);
1636 void KDirOperator::setDirLister(KDirLister
*lister
)
1638 if (lister
== d
->dirLister
) // sanity check
1644 delete d
->proxyModel
;
1647 //delete d->dirLister; // deleted by KDirModel already, which took ownership
1648 d
->dirLister
= lister
;
1650 d
->dirModel
= new KDirModel();
1651 d
->dirModel
->setDirLister(d
->dirLister
);
1652 d
->dirModel
->setDropsAllowed(KDirModel::DropOnDirectory
);
1654 d
->shouldFetchForItems
= qobject_cast
<QTreeView
*>(d
->itemView
);
1655 if (d
->shouldFetchForItems
) {
1656 connect(d
->dirModel
, SIGNAL(expand(QModelIndex
)), this, SLOT(_k_slotExpandToUrl(QModelIndex
)));
1658 d
->itemsToBeSetAsCurrent
.clear();
1661 d
->proxyModel
= new KDirSortFilterProxyModel(this);
1662 d
->proxyModel
->setSourceModel(d
->dirModel
);
1664 d
->dirLister
->setAutoUpdate(true);
1665 d
->dirLister
->setDelayedMimeTypes(true);
1667 QWidget
* mainWidget
= topLevelWidget();
1668 d
->dirLister
->setMainWindow(mainWidget
);
1669 kDebug(kfile_area
) << "mainWidget=" << mainWidget
;
1671 connect(d
->dirLister
, SIGNAL(percent(int)),
1672 SLOT(_k_slotProgress(int)));
1673 connect(d
->dirLister
, SIGNAL(started(const KUrl
&)), SLOT(_k_slotStarted()));
1674 connect(d
->dirLister
, SIGNAL(completed()), SLOT(_k_slotIOFinished()));
1675 connect(d
->dirLister
, SIGNAL(canceled()), SLOT(_k_slotCanceled()));
1676 connect(d
->dirLister
, SIGNAL(redirection(const KUrl
&)),
1677 SLOT(_k_slotRedirected(const KUrl
&)));
1680 void KDirOperator::selectDir(const KFileItem
&item
)
1682 setUrl(item
.targetUrl(), true);
1685 void KDirOperator::selectFile(const KFileItem
&item
)
1687 QApplication::restoreOverrideCursor();
1689 emit
fileSelected(item
);
1692 void KDirOperator::highlightFile(const KFileItem
&item
)
1694 if ((d
->preview
!= 0) && !item
.isNull()) {
1695 d
->preview
->showPreview(item
.url());
1698 emit
fileHighlighted(item
);
1701 void KDirOperator::setCurrentItem(const QString
& url
)
1705 KFileItem item
= d
->dirLister
->findByUrl(url
);
1706 if (d
->shouldFetchForItems
&& item
.isNull()) {
1707 d
->itemsToBeSetAsCurrent
<< url
;
1708 d
->dirModel
->expandToUrl(url
);
1712 setCurrentItem(item
);
1715 void KDirOperator::setCurrentItem(const KFileItem
& item
)
1723 QItemSelectionModel
*selModel
= d
->itemView
->selectionModel();
1726 if (!item
.isNull()) {
1727 const QModelIndex dirIndex
= d
->dirModel
->indexForItem(item
);
1728 const QModelIndex proxyIndex
= d
->proxyModel
->mapFromSource(dirIndex
);
1729 selModel
->setCurrentIndex(proxyIndex
, QItemSelectionModel::Select
);
1734 void KDirOperator::setCurrentItems(const QStringList
& urls
)
1742 KFileItemList itemList
;
1743 foreach (const QString
&url
, urls
) {
1744 KFileItem item
= d
->dirLister
->findByUrl(url
);
1745 if (d
->shouldFetchForItems
&& item
.isNull()) {
1746 d
->itemsToBeSetAsCurrent
<< url
;
1747 d
->dirModel
->expandToUrl(url
);
1753 setCurrentItems(itemList
);
1756 void KDirOperator::setCurrentItems(const KFileItemList
& items
)
1760 if (d
->itemView
== 0) {
1764 QItemSelectionModel
*selModel
= d
->itemView
->selectionModel();
1767 QModelIndex proxyIndex
;
1768 foreach (const KFileItem
&item
, items
) {
1769 if (!item
.isNull()) {
1770 const QModelIndex dirIndex
= d
->dirModel
->indexForItem(item
);
1771 proxyIndex
= d
->proxyModel
->mapFromSource(dirIndex
);
1772 selModel
->select(proxyIndex
, QItemSelectionModel::Select
);
1775 if (proxyIndex
.isValid()) {
1776 selModel
->setCurrentIndex(proxyIndex
, QItemSelectionModel::NoUpdate
);
1781 QString
KDirOperator::makeCompletion(const QString
& string
)
1783 if (string
.isEmpty()) {
1784 d
->itemView
->selectionModel()->clear();
1788 prepareCompletionObjects();
1789 return d
->completion
.makeCompletion(string
);
1792 QString
KDirOperator::makeDirCompletion(const QString
& string
)
1794 if (string
.isEmpty()) {
1795 d
->itemView
->selectionModel()->clear();
1799 prepareCompletionObjects();
1800 return d
->dirCompletion
.makeCompletion(string
);
1803 void KDirOperator::prepareCompletionObjects()
1805 if (d
->itemView
== 0) {
1809 if (d
->completeListDirty
) { // create the list of all possible completions
1810 const KFileItemList itemList
= d
->dirLister
->items();
1811 foreach (const KFileItem
&item
, itemList
) {
1812 d
->completion
.addItem(item
.name());
1814 d
->dirCompletion
.addItem(item
.name());
1817 d
->completeListDirty
= false;
1821 void KDirOperator::slotCompletionMatch(const QString
& match
)
1823 setCurrentItem(match
);
1824 emit
completion(match
);
1827 void KDirOperator::setupActions()
1829 d
->actionCollection
= new KActionCollection(this);
1830 d
->actionCollection
->setObjectName("KDirOperator::actionCollection");
1832 d
->actionMenu
= new KActionMenu(i18n("Menu"), this);
1833 d
->actionCollection
->addAction("popupMenu", d
->actionMenu
);
1835 QAction
* upAction
= d
->actionCollection
->addAction(KStandardAction::Up
, "up", this, SLOT(cdUp()));
1836 upAction
->setText(i18n("Parent Folder"));
1838 d
->actionCollection
->addAction(KStandardAction::Back
, "back", this, SLOT(back()));
1840 d
->actionCollection
->addAction(KStandardAction::Forward
, "forward", this, SLOT(forward()));
1842 QAction
* homeAction
= d
->actionCollection
->addAction(KStandardAction::Home
, "home", this, SLOT(home()));
1843 homeAction
->setText(i18n("Home Folder"));
1845 KAction
* reloadAction
= d
->actionCollection
->addAction(KStandardAction::Redisplay
, "reload", this, SLOT(rereadDir()));
1846 reloadAction
->setText(i18n("Reload"));
1847 reloadAction
->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Reload
));
1849 KAction
* mkdirAction
= new KAction(i18n("New Folder..."), this);
1850 d
->actionCollection
->addAction("mkdir", mkdirAction
);
1851 mkdirAction
->setIcon(KIcon(QLatin1String("folder-new")));
1852 connect(mkdirAction
, SIGNAL(triggered(bool)), this, SLOT(mkdir()));
1854 KAction
* trash
= new KAction(i18n("Move to Trash"), this);
1855 d
->actionCollection
->addAction("trash", trash
);
1856 trash
->setIcon(KIcon("user-trash"));
1857 trash
->setShortcuts(KShortcut(Qt::Key_Delete
));
1858 connect(trash
, SIGNAL(triggered(bool)), SLOT(trashSelected()));
1860 KAction
* action
= new KAction(i18n("Delete"), this);
1861 d
->actionCollection
->addAction("delete", action
);
1862 action
->setIcon(KIcon("edit-delete"));
1863 action
->setShortcuts(KShortcut(Qt::SHIFT
+ Qt::Key_Delete
));
1864 connect(action
, SIGNAL(triggered(bool)), this, SLOT(deleteSelected()));
1866 // the sort menu actions
1867 KActionMenu
*sortMenu
= new KActionMenu(i18n("Sorting"), this);
1868 d
->actionCollection
->addAction("sorting menu", sortMenu
);
1870 KToggleAction
*byNameAction
= new KToggleAction(i18n("By Name"), this);
1871 d
->actionCollection
->addAction("by name", byNameAction
);
1872 connect(byNameAction
, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortByName()));
1874 KToggleAction
*bySizeAction
= new KToggleAction(i18n("By Size"), this);
1875 d
->actionCollection
->addAction("by size", bySizeAction
);
1876 connect(bySizeAction
, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortBySize()));
1878 KToggleAction
*byDateAction
= new KToggleAction(i18n("By Date"), this);
1879 d
->actionCollection
->addAction("by date", byDateAction
);
1880 connect(byDateAction
, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortByDate()));
1882 KToggleAction
*byTypeAction
= new KToggleAction(i18n("By Type"), this);
1883 d
->actionCollection
->addAction("by type", byTypeAction
);
1884 connect(byTypeAction
, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortByType()));
1886 KToggleAction
*descendingAction
= new KToggleAction(i18n("Descending"), this);
1887 d
->actionCollection
->addAction("descending", descendingAction
);
1888 connect(descendingAction
, SIGNAL(toggled(bool)), this, SLOT(_k_slotSortReversed(bool)));
1890 QActionGroup
* sortGroup
= new QActionGroup(this);
1891 byNameAction
->setActionGroup(sortGroup
);
1892 bySizeAction
->setActionGroup(sortGroup
);
1893 byDateAction
->setActionGroup(sortGroup
);
1894 byTypeAction
->setActionGroup(sortGroup
);
1896 d
->decorationMenu
= new KActionMenu(i18n("Icon Position"), this);
1897 d
->actionCollection
->addAction("decoration menu", d
->decorationMenu
);
1899 d
->leftAction
= new KToggleAction(i18n("Next to File Name"), this);
1900 d
->actionCollection
->addAction("decorationAtLeft", d
->leftAction
);
1901 connect(d
->leftAction
, SIGNAL(triggered(bool)), this, SLOT(_k_slotChangeDecorationPosition()));
1903 KToggleAction
*topAction
= new KToggleAction(i18n("Above File Name"), this);
1904 d
->actionCollection
->addAction("decorationAtTop", topAction
);
1905 connect(topAction
, SIGNAL(triggered(bool)), this, SLOT(_k_slotChangeDecorationPosition()));
1907 d
->decorationMenu
->addAction(d
->leftAction
);
1908 d
->decorationMenu
->addAction(topAction
);
1910 QActionGroup
* decorationGroup
= new QActionGroup(this);
1911 d
->leftAction
->setActionGroup(decorationGroup
);
1912 topAction
->setActionGroup(decorationGroup
);
1914 KToggleAction
*shortAction
= new KToggleAction(i18n("Short View"), this);
1915 d
->actionCollection
->addAction("short view", shortAction
);
1916 shortAction
->setIcon(KIcon(QLatin1String("view-list-icons")));
1917 connect(shortAction
, SIGNAL(triggered()), SLOT(_k_slotSimpleView()));
1919 KToggleAction
*detailedAction
= new KToggleAction(i18n("Detailed View"), this);
1920 d
->actionCollection
->addAction("detailed view", detailedAction
);
1921 detailedAction
->setIcon(KIcon(QLatin1String("view-list-details")));
1922 connect(detailedAction
, SIGNAL(triggered ()), SLOT(_k_slotDetailedView()));
1924 KToggleAction
*treeAction
= new KToggleAction(i18n("Tree View"), this);
1925 d
->actionCollection
->addAction("tree view", treeAction
);
1926 treeAction
->setIcon(KIcon(QLatin1String("view-list-tree")));
1927 connect(treeAction
, SIGNAL(triggered ()), SLOT(_k_slotTreeView()));
1929 KToggleAction
*detailedTreeAction
= new KToggleAction(i18n("Detailed Tree View"), this);
1930 d
->actionCollection
->addAction("detailed tree view", detailedTreeAction
);
1931 detailedTreeAction
->setIcon(KIcon(QLatin1String("view-list-tree")));
1932 connect(detailedTreeAction
, SIGNAL(triggered ()), SLOT(_k_slotDetailedTreeView()));
1934 QActionGroup
* viewGroup
= new QActionGroup(this);
1935 shortAction
->setActionGroup(viewGroup
);
1936 detailedAction
->setActionGroup(viewGroup
);
1937 treeAction
->setActionGroup(viewGroup
);
1938 detailedTreeAction
->setActionGroup(viewGroup
);
1940 KToggleAction
*showHiddenAction
= new KToggleAction(i18n("Show Hidden Files"), this);
1941 d
->actionCollection
->addAction("show hidden", showHiddenAction
);
1942 connect(showHiddenAction
, SIGNAL(toggled(bool)), SLOT(_k_slotToggleHidden(bool)));
1944 KToggleAction
*previewAction
= new KToggleAction(i18n("Show Aside Preview"), this);
1945 d
->actionCollection
->addAction("preview", previewAction
);
1946 connect(previewAction
, SIGNAL(toggled(bool)),
1947 SLOT(_k_togglePreview(bool)));
1949 KToggleAction
*inlinePreview
= new KToggleAction(KIcon("view-preview"),
1950 i18n("Show Preview"), this);
1951 d
->actionCollection
->addAction("inline preview", inlinePreview
);
1952 connect(inlinePreview
, SIGNAL(toggled(bool)), SLOT(_k_toggleInlinePreviews(bool)));
1954 action
= new KAction(i18n("Properties"), this);
1955 d
->actionCollection
->addAction("properties", action
);
1956 action
->setIcon(KIcon("document-properties"));
1957 action
->setShortcut(KShortcut(Qt::ALT
+ Qt::Key_Return
));
1958 connect(action
, SIGNAL(triggered(bool)), this, SLOT(_k_slotProperties()));
1960 // the view menu actions
1961 KActionMenu
* viewMenu
= new KActionMenu(i18n("&View"), this);
1962 d
->actionCollection
->addAction("view menu", viewMenu
);
1963 viewMenu
->addAction(shortAction
);
1964 viewMenu
->addAction(detailedAction
);
1965 // Comment following lines to hide the extra two modes
1966 viewMenu
->addAction(treeAction
);
1967 viewMenu
->addAction(detailedTreeAction
);
1968 // TODO: QAbstractItemView does not offer an action collection. Provide
1969 // an interface to add a custom action collection.
1971 d
->actionCollection
->addAssociatedWidget(this);
1972 foreach (QAction
* action
, d
->actionCollection
->actions())
1973 action
->setShortcutContext(Qt::WidgetWithChildrenShortcut
);
1976 void KDirOperator::setupMenu()
1978 setupMenu(SortActions
| ViewActions
| FileActions
);
1981 void KDirOperator::setupMenu(int whichActions
)
1983 // first fill the submenus (sort and view)
1984 KActionMenu
*sortMenu
= static_cast<KActionMenu
*>(d
->actionCollection
->action("sorting menu"));
1985 sortMenu
->menu()->clear();
1986 sortMenu
->addAction(d
->actionCollection
->action("by name"));
1987 sortMenu
->addAction(d
->actionCollection
->action("by size"));
1988 sortMenu
->addAction(d
->actionCollection
->action("by date"));
1989 sortMenu
->addAction(d
->actionCollection
->action("by type"));
1990 sortMenu
->addSeparator();
1991 sortMenu
->addAction(d
->actionCollection
->action("descending"));
1993 // now plug everything into the popupmenu
1994 d
->actionMenu
->menu()->clear();
1995 if (whichActions
& NavActions
) {
1996 d
->actionMenu
->addAction(d
->actionCollection
->action("up"));
1997 d
->actionMenu
->addAction(d
->actionCollection
->action("back"));
1998 d
->actionMenu
->addAction(d
->actionCollection
->action("forward"));
1999 d
->actionMenu
->addAction(d
->actionCollection
->action("home"));
2000 d
->actionMenu
->addSeparator();
2003 if (whichActions
& FileActions
) {
2004 d
->actionMenu
->addAction(d
->actionCollection
->action("mkdir"));
2005 if (d
->currUrl
.isLocalFile() && !(QApplication::keyboardModifiers() & Qt::ShiftModifier
)) {
2006 d
->actionMenu
->addAction(d
->actionCollection
->action("trash"));
2008 KConfigGroup
cg(KGlobal::config(), QLatin1String("KDE"));
2009 const bool del
= !d
->currUrl
.isLocalFile() ||
2010 (QApplication::keyboardModifiers() & Qt::ShiftModifier
) ||
2011 cg
.readEntry("ShowDeleteCommand", false);
2013 d
->actionMenu
->addAction(d
->actionCollection
->action("delete"));
2015 d
->actionMenu
->addSeparator();
2018 if (whichActions
& SortActions
) {
2019 d
->actionMenu
->addAction(sortMenu
);
2020 if (!(whichActions
& ViewActions
)) {
2021 d
->actionMenu
->addSeparator();
2025 if (whichActions
& ViewActions
) {
2026 d
->actionMenu
->addAction(d
->actionCollection
->action("view menu"));
2027 d
->actionMenu
->addSeparator();
2030 if (whichActions
& FileActions
) {
2031 d
->actionMenu
->addAction(d
->actionCollection
->action("properties"));
2035 void KDirOperator::updateSortActions()
2037 if (KFile::isSortByName(d
->sorting
)) {
2038 d
->actionCollection
->action("by name")->setChecked(true);
2039 } else if (KFile::isSortByDate(d
->sorting
)) {
2040 d
->actionCollection
->action("by date")->setChecked(true);
2041 } else if (KFile::isSortBySize(d
->sorting
)) {
2042 d
->actionCollection
->action("by size")->setChecked(true);
2043 } else if (KFile::isSortByType(d
->sorting
)) {
2044 d
->actionCollection
->action("by type")->setChecked(true);
2046 d
->actionCollection
->action("descending")->setChecked(d
->sorting
& QDir::Reversed
);
2049 void KDirOperator::updateViewActions()
2051 KFile::FileView fv
= static_cast<KFile::FileView
>(d
->viewKind
);
2053 //QAction *separateDirs = d->actionCollection->action("separate dirs");
2054 //separateDirs->setChecked(KFile::isSeparateDirs(fv) &&
2055 // separateDirs->isEnabled());
2057 d
->actionCollection
->action("short view")->setChecked(KFile::isSimpleView(fv
));
2058 d
->actionCollection
->action("detailed view")->setChecked(KFile::isDetailView(fv
));
2059 d
->actionCollection
->action("tree view")->setChecked(KFile::isTreeView(fv
));
2060 d
->actionCollection
->action("detailed tree view")->setChecked(KFile::isDetailTreeView(fv
));
2063 void KDirOperator::readConfig(const KConfigGroup
& configGroup
)
2066 QDir::SortFlags sorting
= QDir::Name
;
2068 QString viewStyle
= configGroup
.readEntry("View Style", "Simple");
2069 if (viewStyle
== QLatin1String("Detail")) {
2070 d
->defaultView
|= KFile::Detail
;
2071 } else if (viewStyle
== QLatin1String("Tree")) {
2072 d
->defaultView
|= KFile::Tree
;
2073 } else if (viewStyle
== QLatin1String("DetailTree")) {
2074 d
->defaultView
|= KFile::DetailTree
;
2076 d
->defaultView
|= KFile::Simple
;
2079 //if (configGroup.readEntry(QLatin1String("Separate Directories"),
2080 // DefaultMixDirsAndFiles)) {
2081 // d->defaultView |= KFile::SeparateDirs;
2083 if (configGroup
.readEntry(QLatin1String("Show Preview"), false)) {
2084 d
->defaultView
|= KFile::PreviewContents
;
2086 d
->previewWidth
= configGroup
.readEntry(QLatin1String("Preview Width"), 100);
2088 if (configGroup
.readEntry(QLatin1String("Sort directories first"),
2089 DefaultDirsFirst
)) {
2090 sorting
|= QDir::DirsFirst
;
2093 QString name
= QLatin1String("Name");
2094 QString sortBy
= configGroup
.readEntry(QLatin1String("Sort by"), name
);
2095 if (sortBy
== name
) {
2096 sorting
|= QDir::Name
;
2097 } else if (sortBy
== QLatin1String("Size")) {
2098 sorting
|= QDir::Size
;
2099 } else if (sortBy
== QLatin1String("Date")) {
2100 sorting
|= QDir::Time
;
2101 } else if (sortBy
== QLatin1String("Type")) {
2102 sorting
|= QDir::Type
;
2105 d
->sorting
= sorting
;
2107 if (configGroup
.readEntry(QLatin1String("Show hidden files"),
2108 DefaultShowHidden
)) {
2109 d
->actionCollection
->action("show hidden")->setChecked(true);
2110 d
->dirLister
->setShowingDotFiles(true);
2112 const bool descending
= configGroup
.readEntry(QLatin1String("Sort reversed"),
2113 DefaultSortReversed
);
2114 d
->actionCollection
->action("descending")->setChecked(descending
);
2116 d
->sorting
= d
->sorting
| QDir::Reversed
;
2119 setSorting(d
->sorting
);
2120 if (d
->inlinePreviewState
== Private::NotForced
) {
2121 d
->showPreviews
= configGroup
.readEntry(QLatin1String("Previews"), false);
2124 decorationPosition
= (QStyleOptionViewItem::Position
) configGroup
.readEntry(QLatin1String("Decoration position"), (int) QStyleOptionViewItem::Left
);
2125 const bool decorationAtLeft
= decorationPosition
== QStyleOptionViewItem::Left
;
2126 d
->actionCollection
->action("decorationAtLeft")->setChecked(decorationAtLeft
);
2127 d
->actionCollection
->action("decorationAtTop")->setChecked(!decorationAtLeft
);
2130 void KDirOperator::writeConfig(KConfigGroup
& configGroup
)
2132 QString sortBy
= QLatin1String("Name");
2133 if (KFile::isSortBySize(d
->sorting
)) {
2134 sortBy
= QLatin1String("Size");
2135 } else if (KFile::isSortByDate(d
->sorting
)) {
2136 sortBy
= QLatin1String("Date");
2137 } else if (KFile::isSortByType(d
->sorting
)) {
2138 sortBy
= QLatin1String("Type");
2141 configGroup
.writeEntry(QLatin1String("Sort by"), sortBy
);
2143 configGroup
.writeEntry(QLatin1String("Sort reversed"),
2144 d
->actionCollection
->action("descending")->isChecked());
2146 // don't save the preview when an application specific preview is in use.
2147 bool appSpecificPreview
= false;
2149 KFileMetaPreview
*tmp
= dynamic_cast<KFileMetaPreview
*>(d
->preview
);
2150 appSpecificPreview
= (tmp
== 0);
2153 if (!appSpecificPreview
) {
2154 KToggleAction
*previewAction
= static_cast<KToggleAction
*>(d
->actionCollection
->action("preview"));
2155 if (previewAction
->isEnabled()) {
2156 bool hasPreview
= previewAction
->isChecked();
2157 configGroup
.writeEntry(QLatin1String("Show Preview"), hasPreview
);
2160 // remember the width of the preview widget
2161 QList
<int> sizes
= d
->splitter
->sizes();
2162 Q_ASSERT(sizes
.count() == 2);
2163 configGroup
.writeEntry(QLatin1String("Preview Width"), sizes
[1]);
2168 configGroup
.writeEntry(QLatin1String("Show hidden files"),
2169 d
->actionCollection
->action("show hidden")->isChecked());
2171 KFile::FileView fv
= static_cast<KFile::FileView
>(d
->viewKind
);
2173 if (KFile::isDetailView(fv
))
2174 style
= QLatin1String("Detail");
2175 else if (KFile::isSimpleView(fv
))
2176 style
= QLatin1String("Simple");
2177 else if (KFile::isTreeView(fv
))
2178 style
= QLatin1String("Tree");
2179 else if (KFile::isDetailTreeView(fv
))
2180 style
= QLatin1String("DetailTree");
2181 configGroup
.writeEntry(QLatin1String("View Style"), style
);
2183 if (d
->inlinePreviewState
== Private::NotForced
) {
2184 configGroup
.writeEntry(QLatin1String("Previews"), d
->showPreviews
);
2187 configGroup
.writeEntry(QLatin1String("Decoration position"), (int) decorationPosition
);
2190 void KDirOperator::resizeEvent(QResizeEvent
*)
2192 // resize the splitter and assure that the width of
2193 // the preview widget is restored
2194 QList
<int> sizes
= d
->splitter
->sizes();
2195 const bool hasPreview
= (sizes
.count() == 2);
2197 d
->splitter
->resize(size());
2198 sizes
= d
->splitter
->sizes();
2200 const bool restorePreviewWidth
= hasPreview
&& (d
->previewWidth
!= sizes
[1]);
2201 if (restorePreviewWidth
) {
2202 const int availableWidth
= sizes
[0] + sizes
[1];
2203 sizes
[0] = availableWidth
- d
->previewWidth
;
2204 sizes
[1] = d
->previewWidth
;
2205 d
->splitter
->setSizes(sizes
);
2208 d
->previewWidth
= sizes
[1];
2211 if (d
->progressBar
->parent() == this) {
2212 // might be reparented into a statusbar
2213 d
->progressBar
->move(2, height() - d
->progressBar
->height() - 2);
2217 void KDirOperator::setOnlyDoubleClickSelectsFiles(bool enable
)
2219 d
->onlyDoubleClickSelectsFiles
= enable
;
2220 // TODO: port to Qt4's QAbstractItemModel
2221 //if (d->itemView != 0) {
2222 // d->itemView->setOnlyDoubleClickSelectsFiles(enable);
2226 bool KDirOperator::onlyDoubleClickSelectsFiles() const
2228 return d
->onlyDoubleClickSelectsFiles
;
2231 void KDirOperator::Private::_k_slotStarted()
2233 progressBar
->setValue(0);
2234 // delay showing the progressbar for one second
2235 progressDelayTimer
->setSingleShot(true);
2236 progressDelayTimer
->start(1000);
2239 void KDirOperator::Private::_k_slotShowProgress()
2241 progressBar
->raise();
2242 progressBar
->show();
2243 QApplication::flush();
2246 void KDirOperator::Private::_k_slotProgress(int percent
)
2248 progressBar
->setValue(percent
);
2249 // we have to redraw this as fast as possible
2250 if (progressBar
->isVisible())
2251 QApplication::flush();
2255 void KDirOperator::Private::_k_slotIOFinished()
2257 progressDelayTimer
->stop();
2258 _k_slotProgress(100);
2259 progressBar
->hide();
2260 emit parent
->finishedLoading();
2261 parent
->resetCursor();
2264 preview
->clearPreview();
2268 void KDirOperator::Private::_k_slotCanceled()
2270 emit parent
->finishedLoading();
2271 parent
->resetCursor();
2274 QProgressBar
* KDirOperator::progressBar() const
2276 return d
->progressBar
;
2279 void KDirOperator::clearHistory()
2281 qDeleteAll(d
->backStack
);
2282 d
->backStack
.clear();
2283 d
->actionCollection
->action("back")->setEnabled(false);
2285 qDeleteAll(d
->forwardStack
);
2286 d
->forwardStack
.clear();
2287 d
->actionCollection
->action("forward")->setEnabled(false);
2290 void KDirOperator::setEnableDirHighlighting(bool enable
)
2292 d
->dirHighlighting
= enable
;
2295 bool KDirOperator::dirHighlighting() const
2297 return d
->dirHighlighting
;
2300 bool KDirOperator::dirOnlyMode() const
2302 return dirOnlyMode(d
->mode
);
2305 bool KDirOperator::dirOnlyMode(uint mode
)
2307 return ((mode
& KFile::Directory
) &&
2308 (mode
& (KFile::File
| KFile::Files
)) == 0);
2311 void KDirOperator::Private::_k_slotProperties()
2313 if (itemView
== 0) {
2317 const KFileItemList list
= parent
->selectedItems();
2318 if (!list
.isEmpty()) {
2319 KPropertiesDialog
dialog(list
, parent
);
2324 void KDirOperator::Private::_k_slotPressed(const QModelIndex
&)
2326 // Remember whether the left mouse button has been pressed, to prevent
2327 // that a right-click on an item opens an item (see _k_slotDoubleClicked() and
2328 // _k_openContextMenu()).
2329 const Qt::KeyboardModifiers modifiers
= QApplication::keyboardModifiers();
2330 leftButtonPressed
= (QApplication::mouseButtons() & Qt::LeftButton
) &&
2331 !(modifiers
& Qt::ShiftModifier
) && !(modifiers
& Qt::ControlModifier
);
2334 void KDirOperator::Private::_k_slotActivated(const QModelIndex
& index
)
2336 const QModelIndex dirIndex
= proxyModel
->mapToSource(index
);
2337 KFileItem item
= dirModel
->itemForIndex(dirIndex
);
2339 const Qt::KeyboardModifiers modifiers
= QApplication::keyboardModifiers();
2340 if (item
.isNull() || (modifiers
& Qt::ShiftModifier
) || (modifiers
& Qt::ControlModifier
))
2344 parent
->selectDir(item
);
2345 } else if (!isSaving
) {
2346 parent
->selectFile(item
);
2350 void KDirOperator::Private::_k_slotDoubleClicked(const QModelIndex
& index
)
2352 if (!leftButtonPressed
) {
2356 const QModelIndex dirIndex
= proxyModel
->mapToSource(index
);
2357 KFileItem item
= dirModel
->itemForIndex(dirIndex
);
2363 parent
->selectDir(item
);
2365 parent
->selectFile(item
);
2369 void KDirOperator::Private::_k_slotSelectionChanged()
2371 if (itemView
== 0) {
2375 // In the multiselection mode each selection change is indicated by
2376 // emitting a null item. Also when the selection has been cleared, a
2377 // null item must be emitted.
2378 const bool multiSelectionMode
= (itemView
->selectionMode() == QAbstractItemView::ExtendedSelection
);
2379 const bool hasSelection
= itemView
->selectionModel()->hasSelection();
2380 if (multiSelectionMode
|| !hasSelection
) {
2382 parent
->highlightFile(nullItem
);
2385 KFileItem selectedItem
= parent
->selectedItems().first();
2386 parent
->highlightFile(selectedItem
);
2390 void KDirOperator::Private::_k_openContextMenu(const QPoint
& pos
)
2392 leftButtonPressed
= false;
2394 const QModelIndex proxyIndex
= itemView
->indexAt(pos
);
2395 const QModelIndex dirIndex
= proxyModel
->mapToSource(proxyIndex
);
2396 KFileItem item
= dirModel
->itemForIndex(dirIndex
);
2401 parent
->activatedMenu(item
, QCursor::pos());
2404 void KDirOperator::Private::_k_triggerPreview(const QModelIndex
& index
)
2406 if ((preview
!= 0) && index
.isValid() && (index
.column() == KDirModel::Name
)) {
2407 const QModelIndex dirIndex
= proxyModel
->mapToSource(index
);
2408 const KFileItem item
= dirModel
->itemForIndex(dirIndex
);
2413 if (!item
.isDir()) {
2414 previewUrl
= item
.url();
2417 preview
->clearPreview();
2422 void KDirOperator::Private::_k_showPreview()
2425 preview
->showPreview(previewUrl
);
2429 void KDirOperator::Private::_k_slotSplitterMoved(int, int)
2431 const QList
<int> sizes
= splitter
->sizes();
2432 if (sizes
.count() == 2) {
2433 // remember the width of the preview widget (see KDirOperator::resizeEvent())
2434 previewWidth
= sizes
[1];
2438 void KDirOperator::Private::_k_assureVisibleSelection()
2440 if (itemView
== 0) {
2444 QItemSelectionModel
* selModel
= itemView
->selectionModel();
2445 if (selModel
->hasSelection()) {
2446 const QModelIndex index
= selModel
->currentIndex();
2447 itemView
->scrollTo(index
, QAbstractItemView::EnsureVisible
);
2448 _k_triggerPreview(index
);
2453 void KDirOperator::Private::_k_synchronizeSortingState(int logicalIndex
, Qt::SortOrder order
)
2455 switch (logicalIndex
) {
2456 case KDirModel::Name
: parent
->sortByName(); break;
2457 case KDirModel::Size
: parent
->sortBySize(); break;
2458 case KDirModel::ModifiedTime
: parent
->sortByDate(); break;
2459 case KDirModel::Type
: parent
->sortByType(); break;
2462 actionCollection
->action("descending")->setChecked(order
== Qt::DescendingOrder
);
2464 proxyModel
->sort(sortColumn(), sortOrder());
2465 QMetaObject::invokeMethod(parent
, "_k_assureVisibleSelection", Qt::QueuedConnection
);
2468 void KDirOperator::Private::_k_slotChangeDecorationPosition()
2474 QListView
*view
= qobject_cast
<QListView
*>(itemView
);
2480 const bool leftChecked
= actionCollection
->action("decorationAtLeft")->isChecked();
2483 decorationPosition
= QStyleOptionViewItem::Left
;
2484 view
->setFlow(QListView::TopToBottom
);
2486 decorationPosition
= QStyleOptionViewItem::Top
;
2487 view
->setFlow(QListView::LeftToRight
);
2490 updateListViewGrid();
2495 void KDirOperator::Private::_k_slotExpandToUrl(const QModelIndex
&index
)
2497 QTreeView
*treeView
= qobject_cast
<QTreeView
*>(itemView
);
2503 const KFileItem item
= dirModel
->itemForIndex(index
);
2505 if (item
.isNull()) {
2509 if (!item
.isDir()) {
2510 const QModelIndex proxyIndex
= proxyModel
->mapFromSource(index
);
2512 KUrl::List::Iterator it
= itemsToBeSetAsCurrent
.begin();
2513 while (it
!= itemsToBeSetAsCurrent
.end()) {
2514 const KUrl url
= *it
;
2515 if (url
.isParentOf(item
.url())) {
2516 const KFileItem _item
= dirLister
->findByUrl(url
);
2517 if (_item
.isDir()) {
2518 const QModelIndex _index
= dirModel
->indexForItem(_item
);
2519 const QModelIndex _proxyIndex
= proxyModel
->mapFromSource(_index
);
2520 treeView
->expand(_proxyIndex
);
2522 // if we have expanded the last parent of this item, select it
2523 if (item
.url().directory() == url
.path(KUrl::RemoveTrailingSlash
)) {
2524 treeView
->selectionModel()->select(proxyIndex
, QItemSelectionModel::Select
);
2527 it
= itemsToBeSetAsCurrent
.erase(it
);
2532 } else if (!itemsToBeSetAsCurrent
.contains(item
.url())) {
2533 itemsToBeSetAsCurrent
<< item
.url();
2537 void KDirOperator::Private::updateListViewGrid()
2543 QListView
*view
= qobject_cast
<QListView
*>(itemView
);
2549 const bool leftChecked
= actionCollection
->action("decorationAtLeft")->isChecked();
2552 view
->setGridSize(QSize());
2553 KFileItemDelegate
*delegate
= qobject_cast
<KFileItemDelegate
*>(view
->itemDelegate());
2555 delegate
->setMaximumSize(QSize());
2558 const QFontMetrics
metrics(itemView
->viewport()->font());
2559 int size
= itemView
->iconSize().height() + metrics
.height() * 2;
2560 // some heuristics for good looking. let's guess width = height * (3 / 2) is nice
2561 view
->setGridSize(QSize(size
* (3.0 / 2.0), size
+ metrics
.height()));
2562 KFileItemDelegate
*delegate
= qobject_cast
<KFileItemDelegate
*>(view
->itemDelegate());
2564 delegate
->setMaximumSize(QSize(size
* (3.0 / 2.0), size
+ metrics
.height()));
2569 int KDirOperator::Private::iconSizeForViewType(QAbstractItemView
*itemView
) const
2571 if (!itemView
|| !configGroup
) {
2575 if (qobject_cast
<QListView
*>(itemView
)) {
2576 return configGroup
->readEntry("listViewIconSize", 0);
2578 return configGroup
->readEntry("detailedViewIconSize", 0);
2582 void KDirOperator::setViewConfig(KConfigGroup
& configGroup
)
2584 delete d
->configGroup
;
2585 d
->configGroup
= new KConfigGroup(configGroup
);
2588 KConfigGroup
* KDirOperator::viewConfigGroup() const
2590 return d
->configGroup
;
2593 void KDirOperator::setShowHiddenFiles(bool s
)
2595 d
->actionCollection
->action("show hidden")->setChecked(s
);
2598 bool KDirOperator::showHiddenFiles() const
2600 return d
->actionCollection
->action("show hidden")->isChecked();
2603 // ### temporary code
2605 bool KDirOperator::Private::isReadable(const KUrl
& url
)
2607 if (!url
.isLocalFile())
2608 return true; // what else can we say?
2610 KDE_struct_stat buf
;
2612 QString ts
= url
.toLocalFile();
2614 QString ts
= url
.path(KUrl::AddTrailingSlash
);
2616 bool readable
= (KDE::stat(ts
, &buf
) == 0);
2617 if (readable
) { // further checks
2619 test
= opendir(QFile::encodeName(ts
)); // we do it just to test here
2620 readable
= (test
!= 0);
2627 #include "kdiroperator.moc"