• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KFile

kdiroperator.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 1999,2000 Stephan Kulow <coolo@kde.org>
00003                   1999,2000,2001,2002,2003 Carsten Pfeiffer <pfeiffer@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kdiroperator.h"
00022 #include "kdirmodel.h"
00023 #include "kdiroperatordetailview_p.h"
00024 #include "kdirsortfilterproxymodel.h"
00025 #include "kfileitem.h"
00026 #include "kfilemetapreview.h"
00027 #include "kpreviewwidgetbase.h"
00028 
00029 #include <config-kfile.h>
00030 
00031 #include <unistd.h>
00032 
00033 #include <QtCore/QDir>
00034 #include <QtCore/QRegExp>
00035 #include <QtCore/QTimer>
00036 #include <QtCore/QAbstractItemModel>
00037 #include <QtGui/QApplication>
00038 #include <QtGui/QDialog>
00039 #include <QtGui/QHeaderView>
00040 #include <QtGui/QLabel>
00041 #include <QtGui/QLayout>
00042 #include <QtGui/QListView>
00043 #include <QtGui/QMouseEvent>
00044 #include <QtGui/QTreeView>
00045 #include <QtGui/QPushButton>
00046 #include <QtGui/QProgressBar>
00047 #include <QtGui/QScrollBar>
00048 #include <QtGui/QSplitter>
00049 #include <QtGui/QWheelEvent>
00050 
00051 #include <kaction.h>
00052 #include <kapplication.h>
00053 #include <kdebug.h>
00054 #include <kdialog.h>
00055 #include <kdirlister.h>
00056 #include <kfileitemdelegate.h>
00057 #include <kicon.h>
00058 #include <kinputdialog.h>
00059 #include <klocale.h>
00060 #include <kmessagebox.h>
00061 #include <kmenu.h>
00062 #include <kstandardaction.h>
00063 #include <kio/job.h>
00064 #include <kio/deletejob.h>
00065 #include <kio/copyjob.h>
00066 #include <kio/jobuidelegate.h>
00067 #include <kio/jobclasses.h>
00068 #include <kio/netaccess.h>
00069 #include <kio/previewjob.h>
00070 #include <kio/renamedialog.h>
00071 #include <kpropertiesdialog.h>
00072 #include <kstandardshortcut.h>
00073 #include <kde_file.h>
00074 #include <kactioncollection.h>
00075 #include <ktoggleaction.h>
00076 #include <kactionmenu.h>
00077 #include <kconfiggroup.h>
00078 #include <kdeversion.h>
00079 
00080 
00081 template class QHash<QString, KFileItem>;
00082 
00087 class KDirOperatorIconView : public QListView
00088 {
00089 public:
00090     KDirOperatorIconView(QWidget *parent = 0);
00091     virtual ~KDirOperatorIconView();
00092 
00093 protected:
00094     virtual QStyleOptionViewItem viewOptions() const;
00095     virtual void dragEnterEvent(QDragEnterEvent* event);
00096     virtual void mousePressEvent(QMouseEvent *event);
00097     virtual void wheelEvent(QWheelEvent *event);
00098 };
00099 
00100 KDirOperatorIconView::KDirOperatorIconView(QWidget *parent) :
00101     QListView(parent)
00102 {
00103     setViewMode(QListView::IconMode);
00104     setFlow(QListView::TopToBottom);
00105     setResizeMode(QListView::Adjust);
00106     setSpacing(KDialog::spacingHint());
00107     setMovement(QListView::Static);
00108     setDragDropMode(QListView::DragOnly);
00109     setVerticalScrollMode(QListView::ScrollPerPixel);
00110     setHorizontalScrollMode(QListView::ScrollPerPixel);
00111     setEditTriggers(QAbstractItemView::NoEditTriggers);
00112 
00113     QFontMetrics metrics(viewOptions().font);
00114     const int fontHeight = metrics.height();
00115     setGridSize(QSize(fontHeight * 10, fontHeight + 4));
00116 }
00117 
00118 KDirOperatorIconView::~KDirOperatorIconView()
00119 {
00120 }
00121 
00122 QStyleOptionViewItem KDirOperatorIconView::viewOptions() const
00123 {
00124     QStyleOptionViewItem viewOptions = QListView::viewOptions();
00125     viewOptions.showDecorationSelected = true;
00126     viewOptions.decorationPosition = QStyleOptionViewItem::Left;
00127     viewOptions.displayAlignment = Qt::AlignLeft | Qt::AlignVCenter;
00128     viewOptions.decorationSize = QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
00129 
00130     return viewOptions;
00131 }
00132 
00133 void KDirOperatorIconView::dragEnterEvent(QDragEnterEvent* event)
00134 {
00135     if (event->mimeData()->hasUrls()) {
00136         event->acceptProposedAction();
00137     }
00138 }
00139 
00140 void KDirOperatorIconView::mousePressEvent(QMouseEvent *event)
00141 {
00142     if (!indexAt(event->pos()).isValid()) {
00143         const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
00144         if (!(modifiers & Qt::ShiftModifier) && !(modifiers & Qt::ControlModifier)) {
00145             clearSelection();
00146         }
00147     }
00148 
00149     QListView::mousePressEvent(event);
00150 }
00151 
00152 void KDirOperatorIconView::wheelEvent(QWheelEvent *event)
00153 {
00154     QListView::wheelEvent(event);
00155 
00156     // apply the vertical wheel event to the horizontal scrollbar, as
00157     // the items are aligned from left to right
00158     if (event->orientation() == Qt::Vertical) {
00159         QWheelEvent horizEvent(event->pos(),
00160                                event->delta(),
00161                                event->buttons(),
00162                                event->modifiers(),
00163                                Qt::Horizontal);
00164         QApplication::sendEvent(horizontalScrollBar(), &horizEvent);
00165     }
00166 }
00167 
00168 class KDirOperator::Private
00169 {
00170 public:
00171     Private( KDirOperator *parent );
00172     ~Private();
00173 
00174     // private methods
00175     bool checkPreviewInternal() const;
00176     void checkPath(const QString &txt, bool takeFiles = false);
00177     bool openUrl(const KUrl &url, KDirLister::OpenUrlFlags flags = KDirLister::NoFlags);
00178     int sortColumn() const;
00179     Qt::SortOrder sortOrder() const;
00180     void triggerSorting();
00181 
00182     static bool isReadable(const KUrl &url);
00183 
00184     // private slots
00185     void _k_slotDetailedView();
00186     void _k_slotSimpleView();
00187     void _k_slotToggleHidden(bool);
00188     void _k_togglePreview(bool);
00189     void _k_slotSortByName();
00190     void _k_slotSortBySize();
00191     void _k_slotSortByDate();
00192     void _k_slotSortByType();
00193     void _k_slotSortReversed();
00194     void _k_slotToggleDirsFirst();
00195     void _k_slotToggleIgnoreCase();
00196     void _k_slotStarted();
00197     void _k_slotProgress(int);
00198     void _k_slotShowProgress();
00199     void _k_slotIOFinished();
00200     void _k_slotCanceled();
00201     void _k_slotRedirected(const KUrl&);
00202     void _k_slotProperties();
00203     void _k_slotPressed(const QModelIndex&);
00204     void _k_slotClicked(const QModelIndex&);
00205     void _k_slotActivated(const QModelIndex&);
00206     void _k_slotDoubleClicked(const QModelIndex&);
00207     void _k_slotSelectionChanged();
00208     void _k_openContextMenu(const QPoint&);
00209     void _k_triggerPreview(const QModelIndex&);
00210     void _k_showPreview();
00211     void _k_slotSplitterMoved(int, int);
00212     void _k_assureVisibleSelection();
00213     void _k_synchronizeSortingState(int, Qt::SortOrder);
00214 
00215     // private members
00216     KDirOperator *parent;
00217     QStack<KUrl*> backStack;    
00218     QStack<KUrl*> forwardStack; 
00219 
00220     QModelIndex lastHoveredIndex;
00221 
00222     KDirLister *dirLister;
00223     KUrl currUrl;
00224 
00225     KCompletion completion;
00226     KCompletion dirCompletion;
00227     bool completeListDirty;
00228     QDir::SortFlags sorting;
00229 
00230     QSplitter *splitter;
00231 
00232     QAbstractItemView *itemView;
00233     KDirModel *dirModel;
00234     KDirSortFilterProxyModel *proxyModel;
00235 
00236     KFileItemList pendingMimeTypes;
00237 
00238     // the enum KFile::FileView as an int
00239     int viewKind;
00240     int defaultView;
00241 
00242     KFile::Modes mode;
00243     QProgressBar *progressBar;
00244 
00245     KPreviewWidgetBase *preview;
00246     KUrl previewUrl;
00247     int previewWidth;
00248 
00249     bool leftButtonPressed;
00250     bool dirHighlighting;
00251     bool onlyDoubleClickSelectsFiles;
00252     QString lastURL; // used for highlighting a directory on cdUp
00253     QTimer *progressDelayTimer;
00254     int dropOptions;
00255 
00256     KActionMenu *actionMenu;
00257     KActionCollection *actionCollection;
00258 
00259     KConfigGroup *configGroup;
00260 };
00261 
00262 KDirOperator::Private::Private(KDirOperator *_parent) :
00263     parent(_parent),
00264     dirLister(0),
00265     splitter(0),
00266     itemView(0),
00267     dirModel(0),
00268     proxyModel(0),
00269     progressBar(0),
00270     preview(0),
00271     previewUrl(),
00272     previewWidth(0),
00273     leftButtonPressed(false),
00274     dirHighlighting(false),
00275     onlyDoubleClickSelectsFiles(false),
00276     progressDelayTimer(0),
00277     dropOptions(0),
00278     actionMenu(0),
00279     actionCollection(0),
00280     configGroup(0)
00281 {
00282 }
00283 
00284 KDirOperator::Private::~Private()
00285 {
00286     delete itemView;
00287     itemView = 0;
00288 
00289     // TODO:
00290     // if (configGroup) {
00291     //     itemView->writeConfig(configGroup);
00292     // }
00293 
00294     qDeleteAll(backStack);
00295     qDeleteAll(forwardStack);
00296     delete preview;
00297     preview = 0;
00298 
00299     delete proxyModel;
00300     proxyModel = 0;
00301     delete dirModel;
00302     dirModel = 0;
00303     dirLister = 0; // deleted by KDirModel
00304     delete configGroup;
00305     configGroup = 0;
00306 
00307     delete progressDelayTimer;
00308     progressDelayTimer = 0;
00309 }
00310 
00311 KDirOperator::KDirOperator(const KUrl& _url, QWidget *parent) :
00312     QWidget(parent),
00313     d(new Private(this))
00314 {
00315     d->splitter = new QSplitter(this);
00316     d->splitter->setChildrenCollapsible(false);
00317     connect(d->splitter, SIGNAL(splitterMoved(int, int)),
00318             this, SLOT(_k_slotSplitterMoved(int, int)));
00319 
00320     d->preview = 0;
00321 
00322     d->mode = KFile::File;
00323     d->viewKind = KFile::Simple;
00324     d->sorting = QDir::Name | QDir::DirsFirst;
00325 
00326     if (_url.isEmpty()) { // no dir specified -> current dir
00327         QString strPath = QDir::currentPath();
00328         strPath.append(QChar('/'));
00329         d->currUrl = KUrl();
00330         d->currUrl.setProtocol(QLatin1String("file"));
00331         d->currUrl.setPath(strPath);
00332     } else {
00333         d->currUrl = _url;
00334         if (d->currUrl.protocol().isEmpty())
00335             d->currUrl.setProtocol(QLatin1String("file"));
00336 
00337         d->currUrl.addPath("/"); // make sure we have a trailing slash!
00338     }
00339 
00340     setDirLister(new KDirLister());
00341 
00342     connect(&d->completion, SIGNAL(match(const QString&)),
00343             SLOT(slotCompletionMatch(const QString&)));
00344 
00345     d->progressBar = new QProgressBar(this);
00346     d->progressBar->setObjectName("d->progressBar");
00347     d->progressBar->adjustSize();
00348     d->progressBar->move(2, height() - d->progressBar->height() - 2);
00349 
00350     d->progressDelayTimer = new QTimer(this);
00351     d->progressDelayTimer->setObjectName(QLatin1String("d->progressBar delay timer"));
00352     connect(d->progressDelayTimer, SIGNAL(timeout()),
00353             SLOT(_k_slotShowProgress()));
00354 
00355     d->completeListDirty = false;
00356 
00357     // action stuff
00358     setupActions();
00359     setupMenu();
00360 
00361     setFocusPolicy(Qt::WheelFocus);
00362 }
00363 
00364 KDirOperator::~KDirOperator()
00365 {
00366     resetCursor();
00367     delete d;
00368 }
00369 
00370 
00371 void KDirOperator::setSorting(QDir::SortFlags spec)
00372 {
00373     d->sorting = spec;
00374     d->triggerSorting();
00375     updateSortActions();
00376 }
00377 
00378 QDir::SortFlags KDirOperator::sorting() const
00379 {
00380     return d->sorting;
00381 }
00382 
00383 bool KDirOperator::isRoot() const
00384 {
00385     return url().path() == QString(QLatin1Char('/'));
00386 }
00387 
00388 KDirLister *KDirOperator::dirLister() const
00389 {
00390     return d->dirLister;
00391 }
00392 
00393 void KDirOperator::resetCursor()
00394 {
00395     if (qApp)
00396         QApplication::restoreOverrideCursor();
00397     d->progressBar->hide();
00398 }
00399 
00400 void KDirOperator::sortByName()
00401 {
00402     d->sorting = QDir::Name;
00403     d->actionCollection->action("by name")->setChecked(true);
00404 }
00405 
00406 void KDirOperator::sortBySize()
00407 {
00408     d->sorting = (d->sorting & ~QDir::SortByMask) | QDir::Size;
00409     d->actionCollection->action("by size")->setChecked(true);
00410 }
00411 
00412 void KDirOperator::sortByDate()
00413 {
00414     d->sorting = (d->sorting & ~QDir::SortByMask) | QDir::Time;
00415     d->actionCollection->action("by date")->setChecked(true);
00416 }
00417 
00418 void KDirOperator::sortByType()
00419 {
00420     d->sorting = (d->sorting & ~QDir::SortByMask) | QDir::Type;
00421     d->actionCollection->action("by type")->setChecked(true);
00422 }
00423 
00424 void KDirOperator::sortReversed()
00425 {
00426     if (d->sorting & QDir::Reversed) {
00427         d->sorting = d->sorting & ~QDir::Reversed;
00428         d->actionCollection->action("descending")->setChecked(false);
00429     } else {
00430         d->sorting = d->sorting | QDir::Reversed;
00431         d->actionCollection->action("descending")->setChecked(true);
00432     }
00433 }
00434 
00435 void KDirOperator::toggleDirsFirst()
00436 {
00437     // TODO: not offered yet
00438 }
00439 
00440 void KDirOperator::toggleIgnoreCase()
00441 {
00442     if (d->proxyModel != 0) {
00443         Qt::CaseSensitivity cs = d->proxyModel->sortCaseSensitivity();
00444         cs = (cs == Qt::CaseSensitive) ? Qt::CaseInsensitive : Qt::CaseSensitive;
00445         d->proxyModel->setSortCaseSensitivity(cs);
00446     }
00447 }
00448 
00449 void KDirOperator::updateSelectionDependentActions()
00450 {
00451     const bool hasSelection = (d->itemView != 0) &&
00452                               d->itemView->selectionModel()->hasSelection();
00453     d->actionCollection->action("trash")->setEnabled(hasSelection);
00454     d->actionCollection->action("delete")->setEnabled(hasSelection);
00455     d->actionCollection->action("properties")->setEnabled(hasSelection);
00456 }
00457 
00458 void KDirOperator::setPreviewWidget(KPreviewWidgetBase *w)
00459 {
00460     const bool showPreview = (w != 0);
00461     if (showPreview) {
00462         d->viewKind = (d->viewKind | KFile::PreviewContents);
00463     } else {
00464         d->viewKind = (d->viewKind & ~KFile::PreviewContents);
00465     }
00466 
00467     delete d->preview;
00468     d->preview = w;
00469 
00470     if (w) {
00471         d->splitter->addWidget(w);
00472     }
00473 
00474     KToggleAction *previewAction = static_cast<KToggleAction*>(d->actionCollection->action("preview"));
00475     previewAction->setEnabled(showPreview);
00476     previewAction->setChecked(showPreview);
00477     setView(static_cast<KFile::FileView>(d->viewKind));
00478 }
00479 
00480 KFileItemList KDirOperator::selectedItems() const
00481 {
00482     KFileItemList itemList;
00483     if (d->itemView == 0) {
00484         return itemList;
00485     }
00486 
00487     const QItemSelection selection = d->proxyModel->mapSelectionToSource(d->itemView->selectionModel()->selection());
00488 
00489     const QModelIndexList indexList = selection.indexes();
00490     foreach(const QModelIndex &index, indexList) {
00491         KFileItem item = d->dirModel->itemForIndex(index);
00492         if (!item.isNull()) {
00493             itemList.append(item);
00494         }
00495     }
00496 
00497     return itemList;
00498 }
00499 
00500 bool KDirOperator::isSelected(const KFileItem &item) const
00501 {
00502     if ((item.isNull()) || (d->itemView == 0)) {
00503         return false;
00504     }
00505 
00506     const QModelIndex dirIndex = d->dirModel->indexForItem(item);
00507     const QModelIndex proxyIndex = d->proxyModel->mapFromSource(dirIndex);
00508     return d->itemView->selectionModel()->isSelected(proxyIndex);
00509 }
00510 
00511 int KDirOperator::numDirs() const
00512 {
00513     return (d->dirLister == 0) ? 0 : d->dirLister->directories().count();
00514 }
00515 
00516 int KDirOperator::numFiles() const
00517 {
00518     return (d->dirLister == 0) ? 0 : d->dirLister->items().count() - numDirs();
00519 }
00520 
00521 KCompletion * KDirOperator::completionObject() const
00522 {
00523     return const_cast<KCompletion *>(&d->completion);
00524 }
00525 
00526 KCompletion *KDirOperator::dirCompletionObject() const
00527 {
00528     return const_cast<KCompletion *>(&d->dirCompletion);
00529 }
00530 
00531 KActionCollection * KDirOperator::actionCollection() const
00532 {
00533     return d->actionCollection;
00534 }
00535 
00536 void KDirOperator::Private::_k_slotDetailedView()
00537 {
00538     KFile::FileView view = static_cast<KFile::FileView>((viewKind & ~KFile::Simple) | KFile::Detail);
00539     parent->setView(view);
00540 }
00541 
00542 void KDirOperator::Private::_k_slotSimpleView()
00543 {
00544     KFile::FileView view = static_cast<KFile::FileView>((viewKind & ~KFile::Detail) | KFile::Simple);
00545     parent->setView(view);
00546 }
00547 
00548 void KDirOperator::Private::_k_slotToggleHidden(bool show)
00549 {
00550     dirLister->setShowingDotFiles(show);
00551     parent->updateDir();
00552     _k_assureVisibleSelection();
00553 }
00554 
00555 void KDirOperator::Private::_k_togglePreview(bool on)
00556 {
00557     if (on) {
00558         viewKind = viewKind | KFile::PreviewContents;
00559         if (preview == 0) {
00560             preview = new KFileMetaPreview(parent);
00561             actionCollection->action("preview")->setChecked(true);
00562             splitter->addWidget(preview);
00563         }
00564 
00565         preview->show();
00566 
00567         QMetaObject::invokeMethod(parent, "_k_assureVisibleSelection", Qt::QueuedConnection);
00568         if (itemView != 0) {
00569             const QModelIndex index = itemView->selectionModel()->currentIndex();
00570             if (index.isValid()) {
00571                 _k_triggerPreview(index);
00572             }
00573         }
00574     } else if (preview != 0) {
00575         viewKind = viewKind & ~KFile::PreviewContents;
00576         preview->hide();
00577     }
00578 }
00579 
00580 void KDirOperator::Private::_k_slotSortByName()
00581 {
00582     parent->sortByName();
00583     triggerSorting();
00584 }
00585 
00586 void KDirOperator::Private::_k_slotSortBySize()
00587 {
00588     parent->sortBySize();
00589     triggerSorting();
00590 }
00591 
00592 void KDirOperator::Private::_k_slotSortByDate()
00593 {
00594     parent->sortByDate();
00595     triggerSorting();
00596 }
00597 
00598 void KDirOperator::Private::_k_slotSortByType()
00599 {
00600     parent->sortByType();
00601     triggerSorting();
00602 }
00603 
00604 void KDirOperator::Private::_k_slotSortReversed()
00605 {
00606     parent->sortReversed();
00607     triggerSorting();
00608 }
00609 
00610 void KDirOperator::Private::_k_slotToggleDirsFirst()
00611 {
00612     // TODO: port to Qt4's QAbstractItemView
00613     /*if ( !d->fileView )
00614       return;
00615 
00616     QDir::SortFlags sorting = d->fileView->sorting();
00617     if ( !KFile::isSortDirsFirst( sorting ) )
00618         d->fileView->setSorting( sorting | QDir::DirsFirst );
00619     else
00620         d->fileView->setSorting( sorting & ~QDir::DirsFirst );
00621     d->sorting = d->fileView->sorting();*/
00622 }
00623 
00624 void KDirOperator::Private::_k_slotToggleIgnoreCase()
00625 {
00626     // TODO: port to Qt4's QAbstractItemView
00627     /*if ( !d->fileView )
00628       return;
00629 
00630     QDir::SortFlags sorting = d->fileView->sorting();
00631     if ( !KFile::isSortCaseInsensitive( sorting ) )
00632         d->fileView->setSorting( sorting | QDir::IgnoreCase );
00633     else
00634         d->fileView->setSorting( sorting & ~QDir::IgnoreCase );
00635     d->sorting = d->fileView->sorting();*/
00636 }
00637 
00638 void KDirOperator::mkdir()
00639 {
00640     bool ok;
00641     QString where = url().pathOrUrl();
00642     QString name = i18n("New Folder");
00643 #ifdef Q_WS_WIN
00644     if (url().isLocalFile() && QFileInfo(url().toLocalFile() + name).exists())
00645 #else
00646     if (url().isLocalFile() && QFileInfo(url().path(KUrl::AddTrailingSlash) + name).exists())
00647 #endif
00648         name = KIO::RenameDialog::suggestName(url(), name);
00649 
00650     QString folder = KInputDialog::getText(i18n("New Folder"),
00651                                            i18n("Create new folder in:\n%1" ,  where),
00652                                            name, &ok, this);
00653     if (ok)
00654         KDirOperator::mkdir(KIO::encodeFileName(folder), true);
00655 }
00656 
00657 bool KDirOperator::mkdir(const QString& directory, bool enterDirectory)
00658 {
00659     // Creates "directory", relative to the current directory (d->currUrl).
00660     // The given path may contain any number directories, existent or not.
00661     // They will all be created, if possible.
00662 
00663     bool writeOk = false;
00664     bool exists = false;
00665     KUrl url(d->currUrl);
00666 
00667     const QStringList dirs = directory.split(QDir::separator(), QString::SkipEmptyParts);
00668     QStringList::ConstIterator it = dirs.begin();
00669 
00670     for (; it != dirs.end(); ++it) {
00671         url.addPath(*it);
00672         exists = KIO::NetAccess::exists(url, KIO::NetAccess::DestinationSide, 0);
00673         writeOk = !exists && KIO::NetAccess::mkdir(url, topLevelWidget());
00674     }
00675 
00676     if (exists) { // url was already existent
00677         KMessageBox::sorry(d->itemView, i18n("A file or folder named %1 already exists.", url.pathOrUrl()));
00678         enterDirectory = false;
00679     } else if (!writeOk) {
00680         KMessageBox::sorry(d->itemView, i18n("You do not have permission to "
00681                                               "create that folder."));
00682     } else if (enterDirectory) {
00683         setUrl(url, true);
00684     }
00685 
00686     return writeOk;
00687 }
00688 
00689 KIO::DeleteJob * KDirOperator::del(const KFileItemList& items,
00690                                    QWidget *parent,
00691                                    bool ask, bool showProgress)
00692 {
00693     if (items.isEmpty()) {
00694         KMessageBox::information(parent,
00695                                  i18n("You did not select a file to delete."),
00696                                  i18n("Nothing to Delete"));
00697         return 0L;
00698     }
00699 
00700     if (parent == 0) {
00701         parent = this;
00702     }
00703 
00704     KUrl::List urls;
00705     QStringList files;
00706     foreach (const KFileItem &item, items) {
00707         const KUrl url = item.url();
00708         urls.append(url);
00709         files.append(url.pathOrUrl());
00710     }
00711 
00712     bool doIt = !ask;
00713     if (ask) {
00714         int ret;
00715         if (items.count() == 1) {
00716             ret = KMessageBox::warningContinueCancel(parent,
00717                     i18n("<qt>Do you really want to delete\n <b>'%1'</b>?</qt>" ,
00718                          files.first()),
00719                     i18n("Delete File"),
00720                     KStandardGuiItem::del(),
00721                     KStandardGuiItem::cancel(), "AskForDelete");
00722         } else
00723             ret = KMessageBox::warningContinueCancelList(parent,
00724                     i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", items.count()),
00725                     files,
00726                     i18n("Delete Files"),
00727                     KStandardGuiItem::del(),
00728                     KStandardGuiItem::cancel(), "AskForDelete");
00729         doIt = (ret == KMessageBox::Continue);
00730     }
00731 
00732     if (doIt) {
00733         KIO::JobFlags flags = showProgress ? KIO::DefaultFlags : KIO::HideProgressInfo;
00734         KIO::DeleteJob *job = KIO::del(urls, flags);
00735         job->ui()->setWindow(topLevelWidget());
00736         job->ui()->setAutoErrorHandlingEnabled(true);
00737         return job;
00738     }
00739 
00740     return 0L;
00741 }
00742 
00743 void KDirOperator::deleteSelected()
00744 {
00745     const KFileItemList list = selectedItems();
00746     if (!list.isEmpty()) {
00747         del(list, this);
00748     }
00749 }
00750 
00751 KIO::CopyJob * KDirOperator::trash(const KFileItemList& items,
00752                                    QWidget *parent,
00753                                    bool ask, bool showProgress)
00754 {
00755     if (items.isEmpty()) {
00756         KMessageBox::information(parent,
00757                                  i18n("You did not select a file to trash."),
00758                                  i18n("Nothing to Trash"));
00759         return 0L;
00760     }
00761 
00762     KUrl::List urls;
00763     QStringList files;
00764     foreach (const KFileItem &item, items) {
00765         const KUrl url = item.url();
00766         urls.append(url);
00767         files.append(url.pathOrUrl());
00768     }
00769 
00770     bool doIt = !ask;
00771     if (ask) {
00772         int ret;
00773         if (items.count() == 1) {
00774             ret = KMessageBox::warningContinueCancel(parent,
00775                     i18n("<qt>Do you really want to trash\n <b>'%1'</b>?</qt>" ,
00776                          files.first()),
00777                     i18n("Trash File"),
00778                     KGuiItem(i18nc("to trash", "&Trash"), "user-trash"),
00779                     KStandardGuiItem::cancel(), "AskForTrash");
00780         } else
00781             ret = KMessageBox::warningContinueCancelList(parent,
00782                     i18np("translators: not called for n == 1", "Do you really want to trash these %1 items?", items.count()),
00783                     files,
00784                     i18n("Trash Files"),
00785                     KGuiItem(i18nc("to trash", "&Trash"), "user-trash"),
00786                     KStandardGuiItem::cancel(), "AskForTrash");
00787         doIt = (ret == KMessageBox::Continue);
00788     }
00789 
00790     if (doIt) {
00791         KIO::JobFlags flags = showProgress ? KIO::DefaultFlags : KIO::HideProgressInfo;
00792         KIO::CopyJob *job = KIO::trash(urls, flags);
00793         job->ui()->setWindow(topLevelWidget());
00794         job->ui()->setAutoErrorHandlingEnabled(true);
00795         return job;
00796     }
00797 
00798     return 0L;
00799 }
00800 
00801 void KDirOperator::trashSelected()
00802 {
00803     if (d->itemView == 0) {
00804         return;
00805     }
00806 
00807     if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {
00808         deleteSelected();
00809         return;
00810     }
00811 
00812     const KFileItemList list = selectedItems();
00813     if (!list.isEmpty()) {
00814         trash(list, this);
00815     }
00816 }
00817 
00818 void KDirOperator::close()
00819 {
00820     resetCursor();
00821     d->pendingMimeTypes.clear();
00822     d->completion.clear();
00823     d->dirCompletion.clear();
00824     d->completeListDirty = true;
00825     d->dirLister->stop();
00826 }
00827 
00828 void KDirOperator::Private::checkPath(const QString &, bool /*takeFiles*/) // SLOT
00829 {
00830 #if 0
00831     // copy the argument in a temporary string
00832     QString text = _txt;
00833     // it's unlikely to happen, that at the beginning are spaces, but
00834     // for the end, it happens quite often, I guess.
00835     text = text.trimmed();
00836     // if the argument is no URL (the check is quite fragil) and it's
00837     // no absolute path, we add the current directory to get a correct url
00838     if (text.find(':') < 0 && text[0] != '/')
00839         text.insert(0, d->currUrl);
00840 
00841     // in case we have a selection defined and someone patched the file-
00842     // name, we check, if the end of the new name is changed.
00843     if (!selection.isNull()) {
00844         int position = text.lastIndexOf('/');
00845         ASSERT(position >= 0); // we already inserted the current d->dirLister in case
00846         QString filename = text.mid(position + 1, text.length());
00847         if (filename != selection)
00848             selection = QString();
00849     }
00850 
00851     KUrl u(text); // I have to take care of entered URLs
00852     bool filenameEntered = false;
00853 
00854     if (u.isLocalFile()) {
00855         // the empty path is kind of a hack
00856         KFileItem i("", u.toLocalFile());
00857         if (i.isDir())
00858             setUrl(text, true);
00859         else {
00860             if (takeFiles)
00861                 if (acceptOnlyExisting && !i.isFile())
00862                     warning("you entered an invalid URL");
00863                 else
00864                     filenameEntered = true;
00865         }
00866     } else
00867         setUrl(text, true);
00868 
00869     if (filenameEntered) {
00870         filename_ = u.url();
00871         emit fileSelected(filename_);
00872 
00873         QApplication::restoreOverrideCursor();
00874 
00875         accept();
00876     }
00877 #endif
00878     kDebug(kfile_area) << "TODO KDirOperator::checkPath()";
00879 }
00880 
00881 void KDirOperator::setUrl(const KUrl& _newurl, bool clearforward)
00882 {
00883     KUrl newurl;
00884 
00885     if (!_newurl.isValid())
00886         newurl.setPath(QDir::homePath());
00887     else
00888         newurl = _newurl;
00889 
00890     newurl.adjustPath( KUrl::AddTrailingSlash );
00891 #ifdef Q_WS_WIN
00892     QString pathstr = newurl.toLocalFile();
00893 #else
00894     QString pathstr = newurl.path();
00895 #endif
00896     newurl.setPath(pathstr);
00897 
00898     // already set
00899     if (newurl.equals(d->currUrl, KUrl::CompareWithoutTrailingSlash))
00900         return;
00901 
00902     if (!Private::isReadable(newurl)) {
00903         // maybe newurl is a file? check its parent directory
00904         newurl.cd(QLatin1String(".."));
00905         KIO::UDSEntry entry;
00906         bool res = KIO::NetAccess::stat(newurl, entry, this);
00907         KFileItem i(entry, newurl);
00908         if ((!res || !Private::isReadable(newurl)) && i.isDir()) {
00909             resetCursor();
00910             KMessageBox::error(d->itemView,
00911                                i18n("The specified folder does not exist "
00912                                     "or was not readable."));
00913             return;
00914         } else if (!i.isDir()) {
00915             return;
00916         }
00917     }
00918 
00919     if (clearforward) {
00920         // autodelete should remove this one
00921         d->backStack.push(new KUrl(d->currUrl));
00922         qDeleteAll(d->forwardStack);
00923         d->forwardStack.clear();
00924     }
00925 
00926     d->lastURL = d->currUrl.url(KUrl::RemoveTrailingSlash);
00927     d->currUrl = newurl;
00928 
00929     pathChanged();
00930     emit urlEntered(newurl);
00931 
00932     // enable/disable actions
00933     QAction* forwardAction = d->actionCollection->action("forward");
00934     forwardAction->setEnabled(!d->forwardStack.isEmpty());
00935 
00936     QAction* backAction = d->actionCollection->action("back");
00937     backAction->setEnabled(!d->backStack.isEmpty());
00938 
00939     QAction* upAction = d->actionCollection->action("up");
00940     upAction->setEnabled(!isRoot());
00941 
00942     d->openUrl(newurl);
00943 }
00944 
00945 void KDirOperator::updateDir()
00946 {
00947     d->dirLister->emitChanges();
00948 }
00949 
00950 void KDirOperator::rereadDir()
00951 {
00952     pathChanged();
00953     d->openUrl(d->currUrl, KDirLister::Reload);
00954 }
00955 
00956 
00957 bool KDirOperator::Private::openUrl(const KUrl& url, KDirLister::OpenUrlFlags flags)
00958 {
00959     bool result = dirLister->openUrl(url, flags);
00960     if (!result)   // in that case, neither completed() nor canceled() will be emitted by KDL
00961         _k_slotCanceled();
00962 
00963     return result;
00964 }
00965 
00966 int KDirOperator::Private::sortColumn() const
00967 {
00968     int column = KDirModel::Name;
00969     if (KFile::isSortByDate(sorting)) {
00970         column = KDirModel::ModifiedTime;
00971     } else if (KFile::isSortBySize(sorting)) {
00972         column = KDirModel::Size;
00973     } else if (KFile::isSortByType(sorting)) {
00974         column = KDirModel::Type;
00975     } else {
00976         Q_ASSERT(KFile::isSortByName(sorting));
00977     }
00978 
00979     return column;
00980 }
00981 
00982 Qt::SortOrder KDirOperator::Private::sortOrder() const
00983 {
00984     return (sorting & QDir::Reversed) ? Qt::DescendingOrder :
00985                                         Qt::AscendingOrder;
00986 }
00987 
00988 void KDirOperator::Private::triggerSorting()
00989 {
00990     proxyModel->sort(sortColumn(), sortOrder());
00991 
00992     // TODO: The headers from QTreeView don't take care about a sorting
00993     // change of the proxy model hence they must be updated the manually.
00994     // This is done here by a qobject_cast, but it would be nicer to:
00995     // - provide a signal 'sortingChanged()'
00996     // - connect KDirOperatorDetailView() with this signal and update the
00997     //   header internally
00998     QTreeView* treeView = qobject_cast<QTreeView*>(itemView);
00999     if (treeView != 0) {
01000         QHeaderView* headerView = treeView->header();
01001         headerView->blockSignals(true);
01002         headerView->setSortIndicator(sortColumn(), sortOrder());
01003         headerView->blockSignals(false);
01004     }
01005 
01006     _k_assureVisibleSelection();
01007 }
01008 
01009 // Protected
01010 void KDirOperator::pathChanged()
01011 {
01012     if (d->itemView == 0)
01013         return;
01014 
01015     d->pendingMimeTypes.clear();
01016     //d->fileView->clear(); TODO
01017     d->completion.clear();
01018     d->dirCompletion.clear();
01019 
01020     // it may be, that we weren't ready at this time
01021     QApplication::restoreOverrideCursor();
01022 
01023     // when KIO::Job emits finished, the slot will restore the cursor
01024     QApplication::setOverrideCursor(Qt::WaitCursor);
01025 
01026     if (!Private::isReadable(d->currUrl)) {
01027         KMessageBox::error(d->itemView,
01028                            i18n("The specified folder does not exist "
01029                                 "or was not readable."));
01030         if (d->backStack.isEmpty())
01031             home();
01032         else
01033             back();
01034     }
01035 }
01036 
01037 void KDirOperator::Private::_k_slotRedirected(const KUrl& newURL)
01038 {
01039     currUrl = newURL;
01040     pendingMimeTypes.clear();
01041     completion.clear();
01042     dirCompletion.clear();
01043     completeListDirty = true;
01044     emit parent->urlEntered(newURL);
01045 }
01046 
01047 // Code pinched from kfm then hacked
01048 void KDirOperator::back()
01049 {
01050     if (d->backStack.isEmpty())
01051         return;
01052 
01053     d->forwardStack.push(new KUrl(d->currUrl));
01054 
01055     KUrl *s = d->backStack.pop();
01056 
01057     setUrl(*s, false);
01058     delete s;
01059 }
01060 
01061 // Code pinched from kfm then hacked
01062 void KDirOperator::forward()
01063 {
01064     if (d->forwardStack.isEmpty())
01065         return;
01066 
01067     d->backStack.push(new KUrl(d->currUrl));
01068 
01069     KUrl *s = d->forwardStack.pop();
01070     setUrl(*s, false);
01071     delete s;
01072 }
01073 
01074 KUrl KDirOperator::url() const
01075 {
01076     return d->currUrl;
01077 }
01078 
01079 void KDirOperator::cdUp()
01080 {
01081     KUrl tmp(d->currUrl);
01082     tmp.cd(QLatin1String(".."));
01083     setUrl(tmp, true);
01084 }
01085 
01086 void KDirOperator::home()
01087 {
01088     KUrl u;
01089     u.setPath(QDir::homePath());
01090     setUrl(u, true);
01091 }
01092 
01093 void KDirOperator::clearFilter()
01094 {
01095     d->dirLister->setNameFilter(QString());
01096     d->dirLister->clearMimeFilter();
01097     checkPreviewSupport();
01098 }
01099 
01100 void KDirOperator::setNameFilter(const QString& filter)
01101 {
01102     d->dirLister->setNameFilter(filter);
01103     checkPreviewSupport();
01104 }
01105 
01106 QString KDirOperator::nameFilter() const
01107 {
01108     return d->dirLister->nameFilter();
01109 }
01110 
01111 void KDirOperator::setMimeFilter(const QStringList& mimetypes)
01112 {
01113     d->dirLister->setMimeFilter(mimetypes);
01114     checkPreviewSupport();
01115 }
01116 
01117 QStringList KDirOperator::mimeFilter() const
01118 {
01119     return d->dirLister->mimeFilters();
01120 }
01121 
01122 bool KDirOperator::checkPreviewSupport()
01123 {
01124     KToggleAction *previewAction = static_cast<KToggleAction*>(d->actionCollection->action("preview"));
01125 
01126     bool hasPreviewSupport = false;
01127     KConfigGroup cg(KGlobal::config(), ConfigGroup);
01128     if (cg.readEntry("Show Default Preview", true))
01129         hasPreviewSupport = d->checkPreviewInternal();
01130 
01131     previewAction->setEnabled(hasPreviewSupport);
01132     return hasPreviewSupport;
01133 }
01134 
01135 void KDirOperator::activatedMenu(const KFileItem &item, const QPoint &pos)
01136 {
01137     Q_UNUSED(item);
01138     setupMenu();
01139     updateSelectionDependentActions();
01140 
01141     d->actionMenu->menu()->exec(pos);
01142 }
01143 
01144 void KDirOperator::changeEvent(QEvent *event)
01145 {
01146     QWidget::changeEvent(event);
01147 
01148     if (event->type() == QEvent::FontChange) {
01149         // Only cast when necessary, speeding up things
01150         KDirOperatorIconView *iconView = dynamic_cast<KDirOperatorIconView*>(d->itemView);
01151 
01152         if (!iconView) {
01153             return;
01154         }
01155 
01156         QFontMetrics metrics(font());
01157         const int fontHeight = metrics.height();
01158         iconView->setGridSize(QSize(fontHeight * 10, fontHeight + 4));
01159     }
01160 }
01161 
01162 bool KDirOperator::eventFilter(QObject *watched, QEvent *event)
01163 {
01164     Q_UNUSED(watched);
01165 
01166     // If we are not hovering any items, check if there is a current index
01167     // set. In that case, we show the preview of that item.
01168     if ((event->type() == QEvent::MouseMove) && (d->preview != 0)) {
01169         const QModelIndex hoveredIndex = d->itemView->indexAt(d->itemView->viewport()->mapFromGlobal(QCursor::pos()));
01170 
01171         if (d->lastHoveredIndex == hoveredIndex)
01172             return false;
01173 
01174         d->lastHoveredIndex = hoveredIndex;
01175 
01176         const QModelIndex focusedIndex = d->itemView->selectionModel() ? d->itemView->selectionModel()->currentIndex()
01177                                                                        : QModelIndex();
01178 
01179         if (!hoveredIndex.isValid() && focusedIndex.isValid() &&
01180             d->itemView->selectionModel()->isSelected(focusedIndex) &&
01181             (d->lastHoveredIndex != focusedIndex)) {
01182             const QModelIndex sourceFocusedIndex = d->proxyModel->mapToSource(focusedIndex);
01183             const KFileItem item = d->dirModel->itemForIndex(sourceFocusedIndex);
01184             if (!item.isNull()) {
01185                 d->preview->showPreview(item.url());
01186             }
01187         }
01188     }
01189     else if ((event->type() == QEvent::MouseButtonRelease) && (d->preview != 0)) {
01190         const QModelIndex hoveredIndex = d->itemView->indexAt(d->itemView->viewport()->mapFromGlobal(QCursor::pos()));
01191         const QModelIndex focusedIndex = d->itemView->selectionModel() ? d->itemView->selectionModel()->currentIndex()
01192                                                                        : QModelIndex();
01193 
01194         if (((!focusedIndex.isValid()) ||
01195              !d->itemView->selectionModel()->isSelected(focusedIndex)) &&
01196             (!hoveredIndex.isValid())) {
01197             d->preview->clearPreview();
01198         }
01199     }
01200 
01201     return false;
01202 }
01203 
01204 bool KDirOperator::Private::checkPreviewInternal() const
01205 {
01206     const QStringList supported = KIO::PreviewJob::supportedMimeTypes();
01207     // no preview support for directories?
01208     if (parent->dirOnlyMode() && supported.indexOf("inode/directory") == -1)
01209         return false;
01210 
01211     QStringList mimeTypes = dirLister->mimeFilters();
01212     const QStringList nameFilter = dirLister->nameFilter().split(" ", QString::SkipEmptyParts);
01213 
01214     if (mimeTypes.isEmpty() && nameFilter.isEmpty() && !supported.isEmpty())
01215         return true;
01216     else {
01217         QRegExp r;
01218         r.setPatternSyntax(QRegExp::Wildcard);   // the "mimetype" can be "image/*"
01219 
01220         if (!mimeTypes.isEmpty()) {
01221             QStringList::ConstIterator it = supported.begin();
01222 
01223             for (; it != supported.end(); ++it) {
01224                 r.setPattern(*it);
01225 
01226                 QStringList result = mimeTypes.filter(r);
01227                 if (!result.isEmpty()) {   // matches! -> we want previews
01228                     return true;
01229                 }
01230             }
01231         }
01232 
01233         if (!nameFilter.isEmpty()) {
01234             // find the mimetypes of all the filter-patterns
01235             QStringList::const_iterator it1 = nameFilter.begin();
01236             for (; it1 != nameFilter.end(); ++it1) {
01237                 if ((*it1) == "*") {
01238                     return true;
01239                 }
01240 
01241                 KMimeType::Ptr mt = KMimeType::findByPath(*it1, 0, true /*fast mode, no file contents exist*/);
01242                 if (!mt)
01243                     continue;
01244                 QString mime = mt->name();
01245 
01246                 // the "mimetypes" we get from the PreviewJob can be "image/*"
01247                 // so we need to check in wildcard mode
01248                 QStringList::ConstIterator it2 = supported.begin();
01249                 for (; it2 != supported.end(); ++it2) {
01250                     r.setPattern(*it2);
01251                     if (r.indexIn(mime) != -1) {
01252                         return true;
01253                     }
01254                 }
01255             }
01256         }
01257     }
01258 
01259     return false;
01260 }
01261 
01262 QAbstractItemView* KDirOperator::createView(QWidget* parent, KFile::FileView viewKind)
01263 {
01264     QAbstractItemView *itemView = 0;
01265     if (KFile::isDetailView(viewKind)) {
01266         KDirOperatorDetailView *detailView = new KDirOperatorDetailView(parent);
01267         connect(detailView->header(), SIGNAL(sortIndicatorChanged (int, Qt::SortOrder)),
01268                 this, SLOT(_k_synchronizeSortingState(int, Qt::SortOrder)));
01269         itemView = detailView;
01270     } else {
01271         itemView = new KDirOperatorIconView(parent);
01272     }
01273 
01274     return itemView;
01275 }
01276 
01277 void KDirOperator::setAcceptDrops(bool b)
01278 {
01279     // TODO:
01280     //if (d->fileView)
01281     //   d->fileView->widget()->setAcceptDrops(b);
01282     QWidget::setAcceptDrops(b);
01283 }
01284 
01285 void KDirOperator::setDropOptions(int options)
01286 {
01287     d->dropOptions = options;
01288     // TODO:
01289     //if (d->fileView)
01290     //   d->fileView->setDropOptions(options);
01291 }
01292 
01293 void KDirOperator::setView(KFile::FileView viewKind)
01294 {
01295     bool preview = (KFile::isPreviewInfo(viewKind) || KFile::isPreviewContents(viewKind));
01296 
01297     if (viewKind == KFile::Default) {
01298         if (KFile::isDetailView((KFile::FileView)d->defaultView)) {
01299             viewKind = KFile::Detail;
01300         } else {
01301             viewKind = KFile::Simple;
01302         }
01303 
01304         const KFile::FileView defaultViewKind = static_cast<KFile::FileView>(d->defaultView);
01305         preview = (KFile::isPreviewInfo(defaultViewKind) || KFile::isPreviewContents(defaultViewKind))
01306                   && d->actionCollection->action("preview")->isEnabled();
01307     }
01308 
01309     d->viewKind = static_cast<int>(viewKind);
01310     viewKind = static_cast<KFile::FileView>(d->viewKind);
01311 
01312     QAbstractItemView *newView = createView(this, viewKind);
01313     setView(newView);
01314 
01315     d->_k_togglePreview(preview);
01316 }
01317 
01318 QAbstractItemView * KDirOperator::view() const
01319 {
01320     return d->itemView;
01321 }
01322 
01323 KFile::Modes KDirOperator::mode() const
01324 {
01325     return d->mode;
01326 }
01327 
01328 void KDirOperator::setMode(KFile::Modes mode)
01329 {
01330     if (d->mode == mode)
01331         return;
01332 
01333     d->mode = mode;
01334 
01335     d->dirLister->setDirOnlyMode(dirOnlyMode());
01336 
01337     // reset the view with the different mode
01338     setView(static_cast<KFile::FileView>(d->viewKind));
01339 }
01340 
01341 void KDirOperator::setView(QAbstractItemView *view)
01342 {
01343     if (view == d->itemView) {
01344         return;
01345     }
01346 
01347     // TODO: do a real timer and restart it after that
01348     d->pendingMimeTypes.clear();
01349     const bool listDir = (d->itemView == 0);
01350 
01351     if (d->mode & KFile::Files) {
01352         view->setSelectionMode(QAbstractItemView::ExtendedSelection);
01353     } else {
01354         view->setSelectionMode(QAbstractItemView::SingleSelection);
01355     }
01356 
01357     QItemSelectionModel *selectionModel = 0;
01358     if ((d->itemView != 0) && d->itemView->selectionModel()->hasSelection()) {
01359         // remember the selection of the current item view and apply this selection
01360         // to the new view later
01361         const QItemSelection selection = d->itemView->selectionModel()->selection();
01362         selectionModel = new QItemSelectionModel(d->proxyModel, this);
01363         selectionModel->select(selection, QItemSelectionModel::Select);
01364     }
01365 
01366     delete d->itemView;
01367     d->itemView = view;
01368     d->itemView->setModel(d->proxyModel);
01369 
01370     view->viewport()->installEventFilter(this);
01371 
01372     KFileItemDelegate *delegate = new KFileItemDelegate(d->itemView);
01373     d->itemView->setItemDelegate(delegate);
01374     d->itemView->viewport()->setAttribute(Qt::WA_Hover);
01375     d->itemView->setContextMenuPolicy(Qt::CustomContextMenu);
01376     d->itemView->setMouseTracking(true);
01377     //d->itemView->setDropOptions(d->dropOptions);
01378 
01379     connect(d->itemView, SIGNAL(activated(const QModelIndex&)),
01380             this, SLOT(_k_slotActivated(const QModelIndex&)));
01381     connect(d->itemView, SIGNAL(pressed(const QModelIndex&)),
01382             this, SLOT(_k_slotPressed(const QModelIndex&)));
01383     connect(d->itemView, SIGNAL(clicked(const QModelIndex&)),
01384             this, SLOT(_k_slotClicked(const QModelIndex&)));
01385     connect(d->itemView, SIGNAL(doubleClicked(const QModelIndex&)),
01386             this, SLOT(_k_slotDoubleClicked(const QModelIndex&)));
01387     connect(d->itemView, SIGNAL(customContextMenuRequested(const QPoint&)),
01388             this, SLOT(_k_openContextMenu(const QPoint&)));
01389     connect(d->itemView, SIGNAL(entered(const QModelIndex&)),
01390             this, SLOT(_k_triggerPreview(const QModelIndex&)));
01391     // assure that the sorting state d->sorting matches with the current action
01392     const bool descending = d->actionCollection->action("descending")->isChecked();
01393     if (!descending && d->sorting & QDir::Reversed) {
01394         d->sorting = d->sorting & ~QDir::Reversed;
01395     } else if (descending && !(d->sorting & QDir::Reversed)) {
01396         d->sorting = d->sorting | QDir::Reversed;
01397     }
01398     d->triggerSorting();
01399 
01400     updateViewActions();
01401     d->splitter->insertWidget(0, d->itemView);
01402 
01403     d->splitter->resize(size());
01404     d->itemView->show();
01405 
01406     if (listDir) {
01407         QApplication::setOverrideCursor(Qt::WaitCursor);
01408         d->openUrl(d->currUrl);
01409     }
01410 
01411     if (selectionModel != 0) {
01412         d->itemView->setSelectionModel(selectionModel);
01413         QMetaObject::invokeMethod(this, "_k_assureVisibleSelection", Qt::QueuedConnection);
01414     }
01415     connect(d->itemView->selectionModel(),
01416             SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)),
01417             this, SLOT(_k_triggerPreview(const QModelIndex&)));
01418     connect(d->itemView->selectionModel(),
01419             SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
01420             this, SLOT(_k_slotSelectionChanged()));
01421 
01422     emit viewChanged(view);
01423 }
01424 
01425 void KDirOperator::setDirLister(KDirLister *lister)
01426 {
01427     if (lister == d->dirLister)   // sanity check
01428         return;
01429 
01430     delete d->dirModel;
01431     d->dirModel = 0;
01432 
01433     delete d->proxyModel;
01434     d->proxyModel = 0;
01435 
01436     //delete d->dirLister; // deleted by KDirModel already, which took ownership
01437     d->dirLister = lister;
01438 
01439     d->dirModel = new KDirModel();
01440     d->dirModel->setDirLister(d->dirLister);
01441     d->dirModel->setDropsAllowed(KDirModel::DropOnDirectory);
01442 
01443     d->proxyModel = new KDirSortFilterProxyModel(this);
01444     d->proxyModel->setSourceModel(d->dirModel);
01445 
01446     d->dirLister->setAutoUpdate(true);
01447     d->dirLister->setDelayedMimeTypes(true);
01448 
01449     QWidget* mainWidget = topLevelWidget();
01450     d->dirLister->setMainWindow(mainWidget);
01451     kDebug(kfile_area) << "mainWidget=" << mainWidget;
01452 
01453     connect(d->dirLister, SIGNAL(percent(int)),
01454             SLOT(_k_slotProgress(int)));
01455     connect(d->dirLister, SIGNAL(started(const KUrl&)), SLOT(_k_slotStarted()));
01456     connect(d->dirLister, SIGNAL(completed()), SLOT(_k_slotIOFinished()));
01457     connect(d->dirLister, SIGNAL(canceled()), SLOT(_k_slotCanceled()));
01458     connect(d->dirLister, SIGNAL(redirection(const KUrl&)),
01459             SLOT(_k_slotRedirected(const KUrl&)));
01460 }
01461 
01462 void KDirOperator::selectDir(const KFileItem &item)
01463 {
01464     setUrl(item.targetUrl(), true);
01465 }
01466 
01467 void KDirOperator::selectFile(const KFileItem &item)
01468 {
01469     QApplication::restoreOverrideCursor();
01470 
01471     emit fileSelected(item);
01472 }
01473 
01474 void KDirOperator::highlightFile(const KFileItem &item)
01475 {
01476     if ((d->preview != 0) && !item.isNull()) {
01477         d->preview->showPreview(item.url());
01478     }
01479 
01480     emit fileHighlighted(item);
01481 }
01482 
01483 void KDirOperator::setCurrentItem(const QString& filename)
01484 {
01485     KFileItem item;
01486     if ( !filename.isNull() ) {
01487         item = d->dirLister->findByName(filename);
01488     }
01489     setCurrentItem(item);
01490 }
01491 
01492 void KDirOperator::setCurrentItem(const KFileItem& item)
01493 {
01494     if (d->itemView == 0) {
01495         return;
01496     }
01497 
01498     QItemSelectionModel *selModel = d->itemView->selectionModel();
01499     if (selModel) {
01500         selModel->clear();
01501         if (!item.isNull()) {
01502             const QModelIndex dirIndex = d->dirModel->indexForItem(item);
01503             const QModelIndex proxyIndex = d->proxyModel->mapFromSource(dirIndex);
01504             selModel->setCurrentIndex(proxyIndex, QItemSelectionModel::SelectCurrent);
01505             QMetaObject::invokeMethod(this, "_k_assureVisibleSelection", Qt::QueuedConnection);
01506         }
01507     }
01508 }
01509 
01510 QString KDirOperator::makeCompletion(const QString& string)
01511 {
01512     if (string.isEmpty()) {
01513         d->itemView->selectionModel()->clear();
01514         return QString();
01515     }
01516 
01517     prepareCompletionObjects();
01518     return d->completion.makeCompletion(string);
01519 }
01520 
01521 QString KDirOperator::makeDirCompletion(const QString& string)
01522 {
01523     if (string.isEmpty()) {
01524         d->itemView->selectionModel()->clear();
01525         return QString();
01526     }
01527 
01528     prepareCompletionObjects();
01529     return d->dirCompletion.makeCompletion(string);
01530 }
01531 
01532 void KDirOperator::prepareCompletionObjects()
01533 {
01534     if (d->itemView == 0) {
01535         return;
01536     }
01537 
01538     if (d->completeListDirty) {   // create the list of all possible completions
01539         const KFileItemList itemList = d->dirLister->items();
01540         foreach (const KFileItem &item, itemList) {
01541             d->completion.addItem(item.name());
01542             if (item.isDir()) {
01543                 d->dirCompletion.addItem(item.name());
01544             }
01545         }
01546         d->completeListDirty = false;
01547     }
01548 }
01549 
01550 void KDirOperator::slotCompletionMatch(const QString& match)
01551 {
01552     setCurrentItem(match);
01553     emit completion(match);
01554 }
01555 
01556 void KDirOperator::setupActions()
01557 {
01558     d->actionCollection = new KActionCollection(this);
01559     d->actionCollection->setObjectName("KDirOperator::actionCollection");
01560 
01561     d->actionMenu = new KActionMenu(i18n("Menu"), this);
01562     d->actionCollection->addAction("popupMenu", d->actionMenu);
01563 
01564     QAction* upAction = d->actionCollection->addAction(KStandardAction::Up, "up", this, SLOT(cdUp()));
01565     upAction->setText(i18n("Parent Folder"));
01566 
01567     d->actionCollection->addAction(KStandardAction::Back, "back", this, SLOT(back()));
01568 
01569     d->actionCollection->addAction(KStandardAction::Forward, "forward", this, SLOT(forward()));
01570 
01571     QAction* homeAction = d->actionCollection->addAction(KStandardAction::Home, "home", this, SLOT(home()));
01572     homeAction->setText(i18n("Home Folder"));
01573 
01574     KAction* reloadAction = d->actionCollection->addAction(KStandardAction::Redisplay, "reload", this, SLOT(rereadDir()));
01575     reloadAction->setText(i18n("Reload"));
01576     reloadAction->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Reload));
01577 
01578     KAction* mkdirAction = new KAction(i18n("New Folder..."), this);
01579     d->actionCollection->addAction("mkdir", mkdirAction);
01580     mkdirAction->setIcon(KIcon(QLatin1String("folder-new")));
01581     connect(mkdirAction, SIGNAL(triggered(bool)), this, SLOT(mkdir()));
01582 
01583     KAction* trash = new KAction(i18n("Move to Trash"), this);
01584     d->actionCollection->addAction("trash", trash);
01585     trash->setIcon(KIcon("user-trash"));
01586     trash->setShortcuts(KShortcut(Qt::Key_Delete));
01587     connect(trash, SIGNAL(triggered(bool)), SLOT(trashSelected()));
01588 
01589     KAction* action = new KAction(i18n("Delete"), this);
01590     d->actionCollection->addAction("delete", action);
01591     action->setIcon(KIcon("edit-delete"));
01592     action->setShortcuts(KShortcut(Qt::SHIFT + Qt::Key_Delete));
01593     connect(action, SIGNAL(triggered(bool)), this, SLOT(deleteSelected()));
01594 
01595     // the sort menu actions
01596     KActionMenu *sortMenu = new KActionMenu(i18n("Sorting"), this);
01597     d->actionCollection->addAction("sorting menu",  sortMenu);
01598 
01599     KToggleAction *byNameAction = new KToggleAction(i18n("By Name"), this);
01600     d->actionCollection->addAction("by name", byNameAction);
01601     connect(byNameAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortByName()));
01602 
01603     KToggleAction *bySizeAction = new KToggleAction(i18n("By Size"), this);
01604     d->actionCollection->addAction("by size", bySizeAction);
01605     connect(bySizeAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortBySize()));
01606 
01607     KToggleAction *byDateAction = new KToggleAction(i18n("By Date"), this);
01608     d->actionCollection->addAction("by date", byDateAction);
01609     connect(byDateAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortByDate()));
01610 
01611     KToggleAction *byTypeAction = new KToggleAction(i18n("By Type"), this);
01612     d->actionCollection->addAction("by type", byTypeAction);
01613     connect(byTypeAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortByType()));
01614 
01615     KToggleAction *descendingAction = new KToggleAction(i18n("Descending"), this);
01616     d->actionCollection->addAction("descending", descendingAction);
01617     connect(descendingAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortReversed()));
01618 
01619     QActionGroup* sortGroup = new QActionGroup(this);
01620     byNameAction->setActionGroup(sortGroup);
01621     bySizeAction->setActionGroup(sortGroup);
01622     byDateAction->setActionGroup(sortGroup);
01623     byTypeAction->setActionGroup(sortGroup);
01624 
01625     KToggleAction *shortAction = new KToggleAction(i18n("Short View"), this);
01626     d->actionCollection->addAction("short view",  shortAction);
01627     shortAction->setIcon(KIcon(QLatin1String("view-list-icons")));
01628     connect(shortAction, SIGNAL(triggered()), SLOT(_k_slotSimpleView()));
01629 
01630     KToggleAction *detailedAction = new KToggleAction(i18n("Detailed View"), this);
01631     d->actionCollection->addAction("detailed view", detailedAction);
01632     detailedAction->setIcon(KIcon(QLatin1String("view-list-details")));
01633     connect(detailedAction, SIGNAL(triggered ()), SLOT(_k_slotDetailedView()));
01634 
01635     QActionGroup* viewGroup = new QActionGroup(this);
01636     shortAction->setActionGroup(viewGroup);
01637     detailedAction->setActionGroup(viewGroup);
01638 
01639     KToggleAction *showHiddenAction = new KToggleAction(i18n("Show Hidden Files"), this);
01640     d->actionCollection->addAction("show hidden", showHiddenAction);
01641     connect(showHiddenAction, SIGNAL(toggled(bool)), SLOT(_k_slotToggleHidden(bool)));
01642 
01643     KToggleAction *previewAction = new KToggleAction(i18n("Show Preview"), this);
01644     d->actionCollection->addAction("preview", previewAction);
01645     previewAction->setIcon(KIcon("view-preview"));
01646     connect(previewAction, SIGNAL(toggled(bool)),
01647             SLOT(_k_togglePreview(bool)));
01648 
01649     action = new KAction(i18n("Properties"), this);
01650     d->actionCollection->addAction("properties", action);
01651     action->setIcon(KIcon("document-properties"));
01652     action->setShortcut(KShortcut(Qt::ALT + Qt::Key_Return));
01653     connect(action, SIGNAL(triggered(bool)), this, SLOT(_k_slotProperties()));
01654 
01655     // the view menu actions
01656     KActionMenu* viewMenu = new KActionMenu(i18n("&View"), this);
01657     d->actionCollection->addAction("view menu", viewMenu);
01658     viewMenu->addAction(shortAction);
01659     viewMenu->addAction(detailedAction);
01660     // TODO: QAbstractItemView does not offer an action collection. Provide
01661     // an interface to add a custom action collection.
01662 
01663     d->actionCollection->addAssociatedWidget(parentWidget());
01664     foreach (QAction* action, d->actionCollection->actions())
01665       action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
01666 }
01667 
01668 void KDirOperator::setupMenu()
01669 {
01670     setupMenu(SortActions | ViewActions | FileActions);
01671 }
01672 
01673 void KDirOperator::setupMenu(int whichActions)
01674 {
01675     // first fill the submenus (sort and view)
01676     KActionMenu *sortMenu = static_cast<KActionMenu*>(d->actionCollection->action("sorting menu"));
01677     sortMenu->menu()->clear();
01678     sortMenu->addAction(d->actionCollection->action("by name"));
01679     sortMenu->addAction(d->actionCollection->action("by size"));
01680     sortMenu->addAction(d->actionCollection->action("by date"));
01681     sortMenu->addAction(d->actionCollection->action("by type"));
01682     sortMenu->addSeparator();
01683     sortMenu->addAction(d->actionCollection->action("descending"));
01684 
01685     // now plug everything into the popupmenu
01686     d->actionMenu->menu()->clear();
01687     if (whichActions & NavActions) {
01688         d->actionMenu->addAction(d->actionCollection->action("up"));
01689         d->actionMenu->addAction(d->actionCollection->action("back"));
01690         d->actionMenu->addAction(d->actionCollection->action("forward"));
01691         d->actionMenu->addAction(d->actionCollection->action("home"));
01692         d->actionMenu->addSeparator();
01693     }
01694 
01695     if (whichActions & FileActions) {
01696         d->actionMenu->addAction(d->actionCollection->action("mkdir"));
01697         if (d->currUrl.isLocalFile() && !(QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
01698             d->actionMenu->addAction(d->actionCollection->action("trash"));
01699         }
01700         KConfigGroup cg(KGlobal::config(), QLatin1String("KDE"));
01701         const bool del = !d->currUrl.isLocalFile() ||
01702                          (QApplication::keyboardModifiers() & Qt::ShiftModifier) ||
01703                          cg.readEntry("ShowDeleteCommand", false);
01704         if (del) {
01705             d->actionMenu->addAction(d->actionCollection->action("delete"));
01706         }
01707         d->actionMenu->addSeparator();
01708     }
01709 
01710     if (whichActions & SortActions) {
01711         d->actionMenu->addAction(sortMenu);
01712         if (!(whichActions & ViewActions)) {
01713             d->actionMenu->addSeparator();
01714         }
01715     }
01716 
01717     if (whichActions & ViewActions) {
01718         d->actionMenu->addAction(d->actionCollection->action("view menu"));
01719         d->actionMenu->addSeparator();
01720     }
01721 
01722     if (whichActions & FileActions) {
01723         d->actionMenu->addAction(d->actionCollection->action("properties"));
01724     }
01725 }
01726 
01727 void KDirOperator::updateSortActions()
01728 {
01729     if (KFile::isSortByName(d->sorting)) {
01730         d->actionCollection->action("by name")->setChecked(true);
01731     } else if (KFile::isSortByDate(d->sorting)) {
01732         d->actionCollection->action("by date")->setChecked(true);
01733     } else if (KFile::isSortBySize(d->sorting)) {
01734         d->actionCollection->action("by size")->setChecked(true);
01735     } else if (KFile::isSortByType(d->sorting)) {
01736         d->actionCollection->action("by type")->setChecked(true);
01737     }
01738     d->actionCollection->action("descending")->setChecked(d->sorting & QDir::Reversed);
01739 }
01740 
01741 void KDirOperator::updateViewActions()
01742 {
01743     KFile::FileView fv = static_cast<KFile::FileView>(d->viewKind);
01744 
01745     //QAction *separateDirs = d->actionCollection->action("separate dirs");
01746     //separateDirs->setChecked(KFile::isSeparateDirs(fv) &&
01747     //                         separateDirs->isEnabled());
01748 
01749     d->actionCollection->action("short view")->setChecked(KFile::isSimpleView(fv));
01750     d->actionCollection->action("detailed view")->setChecked(KFile::isDetailView(fv));
01751 }
01752 
01753 void KDirOperator::readConfig(const KConfigGroup& configGroup)
01754 {
01755     d->defaultView = 0;
01756     QDir::SortFlags sorting = QDir::Name;
01757 
01758     QString viewStyle = configGroup.readEntry("View Style", "Simple");
01759     if (viewStyle == QLatin1String("Detail")) {
01760         d->defaultView |= KFile::Detail;
01761     } else {
01762         d->defaultView |= KFile::Simple;
01763     }
01764 
01765     //if (configGroup.readEntry(QLatin1String("Separate Directories"),
01766     //                          DefaultMixDirsAndFiles)) {
01767     //    d->defaultView |= KFile::SeparateDirs;
01768     //}
01769     if (configGroup.readEntry(QLatin1String("Show Preview"), false)) {
01770         d->defaultView |= KFile::PreviewContents;
01771     }
01772     d->previewWidth = configGroup.readEntry(QLatin1String("Preview Width"), 100);
01773 
01774     if (configGroup.readEntry(QLatin1String("Sort directories first"),
01775                               DefaultDirsFirst)) {
01776         sorting |= QDir::DirsFirst;
01777     }
01778 
01779     QString name = QLatin1String("Name");
01780     QString sortBy = configGroup.readEntry(QLatin1String("Sort by"), name);
01781     if (sortBy == name) {
01782         sorting |= QDir::Name;
01783     } else if (sortBy == QLatin1String("Size")) {
01784         sorting |= QDir::Size;
01785     } else if (sortBy == QLatin1String("Date")) {
01786         sorting |= QDir::Time;
01787     } else if (sortBy == QLatin1String("Type")) {
01788         sorting |= QDir::Type;
01789     }
01790 
01791     d->sorting = sorting;
01792     setSorting(d->sorting);
01793 
01794     if (configGroup.readEntry(QLatin1String("Show hidden files"),
01795                               DefaultShowHidden)) {
01796         d->actionCollection->action("show hidden")->setChecked(true);
01797         d->dirLister->setShowingDotFiles(true);
01798     }
01799     const bool descending = configGroup.readEntry(QLatin1String("Sort reversed"),
01800                                                   DefaultSortReversed);
01801     d->actionCollection->action("descending")->setChecked(descending);
01802     if (descending) {
01803         d->sorting = d->sorting | QDir::Reversed;
01804     }
01805 }
01806 
01807 void KDirOperator::writeConfig(KConfigGroup& configGroup)
01808 {
01809     QString sortBy = QLatin1String("Name");
01810     if (KFile::isSortBySize(d->sorting)) {
01811         sortBy = QLatin1String("Size");
01812     } else if (KFile::isSortByDate(d->sorting)) {
01813         sortBy = QLatin1String("Date");
01814     } else if (KFile::isSortByType(d->sorting)) {
01815         sortBy = QLatin1String("Type");
01816     }
01817 
01818     configGroup.writeEntry(QLatin1String("Sort by"), sortBy);
01819 
01820     configGroup.writeEntry(QLatin1String("Sort reversed"),
01821                            d->actionCollection->action("descending")->isChecked());
01822 
01823     // don't save the preview when an application specific preview is in use.
01824     bool appSpecificPreview = false;
01825     if (d->preview) {
01826         KFileMetaPreview *tmp = dynamic_cast<KFileMetaPreview*>(d->preview);
01827         appSpecificPreview = (tmp == 0);
01828     }
01829 
01830     if (!appSpecificPreview) {
01831         KToggleAction *previewAction = static_cast<KToggleAction*>(d->actionCollection->action("preview"));
01832         if (previewAction->isEnabled()) {
01833             bool hasPreview = previewAction->isChecked();
01834             configGroup.writeEntry(QLatin1String("Show Preview"), hasPreview);
01835 
01836             if (hasPreview) {
01837                 // remember the width of the preview widget
01838                 QList<int> sizes = d->splitter->sizes();
01839                 Q_ASSERT(sizes.count() == 2);
01840                 configGroup.writeEntry(QLatin1String("Preview Width"), sizes[1]);
01841             }
01842         }
01843     }
01844 
01845     configGroup.writeEntry(QLatin1String("Show hidden files"),
01846                            d->actionCollection->action("show hidden")->isChecked());
01847 
01848     KFile::FileView fv = static_cast<KFile::FileView>(d->viewKind);
01849     QString style;
01850     if (KFile::isDetailView(fv))
01851         style = QLatin1String("Detail");
01852     else if (KFile::isSimpleView(fv))
01853         style = QLatin1String("Simple");
01854     configGroup.writeEntry(QLatin1String("View Style"), style);
01855 
01856 }
01857 
01858 void KDirOperator::resizeEvent(QResizeEvent *)
01859 {
01860     // resize the splitter and assure that the width of
01861     // the preview widget is restored
01862     QList<int> sizes = d->splitter->sizes();
01863     const bool hasPreview = (sizes.count() == 2);
01864     const bool restorePreviewWidth = hasPreview && (d->previewWidth != sizes[1]);
01865 
01866     d->splitter->resize(size());
01867 
01868     sizes = d->splitter->sizes();
01869     if (restorePreviewWidth) {
01870         const int availableWidth = sizes[0] + sizes[1];
01871         sizes[0] = availableWidth - d->previewWidth;
01872         sizes[1] = d->previewWidth;
01873         d->splitter->setSizes(sizes);
01874     }
01875     if (hasPreview) {
01876         d->previewWidth = sizes[1];
01877     }
01878 
01879     if (d->progressBar->parent() == this) {
01880         // might be reparented into a statusbar
01881         d->progressBar->move(2, height() - d->progressBar->height() - 2);
01882     }
01883 }
01884 
01885 void KDirOperator::setOnlyDoubleClickSelectsFiles(bool enable)
01886 {
01887     d->onlyDoubleClickSelectsFiles = enable;
01888     // TODO: port to Qt4's QAbstractItemModel
01889     //if (d->itemView != 0) {
01890     //    d->itemView->setOnlyDoubleClickSelectsFiles(enable);
01891     //}
01892 }
01893 
01894 bool KDirOperator::onlyDoubleClickSelectsFiles() const
01895 {
01896     return d->onlyDoubleClickSelectsFiles;
01897 }
01898 
01899 void KDirOperator::Private::_k_slotStarted()
01900 {
01901     progressBar->setValue(0);
01902     // delay showing the progressbar for one second
01903     progressDelayTimer->setSingleShot(true);
01904     progressDelayTimer->start(1000);
01905 }
01906 
01907 void KDirOperator::Private::_k_slotShowProgress()
01908 {
01909     progressBar->raise();
01910     progressBar->show();
01911     QApplication::flush();
01912 }
01913 
01914 void KDirOperator::Private::_k_slotProgress(int percent)
01915 {
01916     progressBar->setValue(percent);
01917     // we have to redraw this as fast as possible
01918     if (progressBar->isVisible())
01919         QApplication::flush();
01920 }
01921 
01922 
01923 void KDirOperator::Private::_k_slotIOFinished()
01924 {
01925     progressDelayTimer->stop();
01926     _k_slotProgress(100);
01927     progressBar->hide();
01928     emit parent->finishedLoading();
01929     parent->resetCursor();
01930 
01931     if (preview) {
01932         preview->clearPreview();
01933     }
01934 }
01935 
01936 void KDirOperator::Private::_k_slotCanceled()
01937 {
01938     emit parent->finishedLoading();
01939     parent->resetCursor();
01940 }
01941 
01942 QProgressBar * KDirOperator::progressBar() const
01943 {
01944     return d->progressBar;
01945 }
01946 
01947 void KDirOperator::clearHistory()
01948 {
01949     qDeleteAll(d->backStack);
01950     d->backStack.clear();
01951     d->actionCollection->action("back")->setEnabled(false);
01952 
01953     qDeleteAll(d->forwardStack);
01954     d->forwardStack.clear();
01955     d->actionCollection->action("forward")->setEnabled(false);
01956 }
01957 
01958 void KDirOperator::setEnableDirHighlighting(bool enable)
01959 {
01960     d->dirHighlighting = enable;
01961 }
01962 
01963 bool KDirOperator::dirHighlighting() const
01964 {
01965     return d->dirHighlighting;
01966 }
01967 
01968 bool KDirOperator::dirOnlyMode() const
01969 {
01970     return dirOnlyMode(d->mode);
01971 }
01972 
01973 bool KDirOperator::dirOnlyMode(uint mode)
01974 {
01975     return ((mode & KFile::Directory) &&
01976             (mode & (KFile::File | KFile::Files)) == 0);
01977 }
01978 
01979 void KDirOperator::Private::_k_slotProperties()
01980 {
01981     if (itemView == 0) {
01982         return;
01983     }
01984 
01985     const KFileItemList list = parent->selectedItems();
01986     if (!list.isEmpty()) {
01987         KPropertiesDialog dialog(list, parent);
01988         dialog.exec();
01989     }
01990 }
01991 
01992 void KDirOperator::Private::_k_slotPressed(const QModelIndex&)
01993 {
01994     // Remember whether the left mouse button has been pressed, to prevent
01995     // that a right-click on an item opens an item (see _k_slotClicked(),
01996     // _k_slotDoubleClicked() and _k_openContextMenu()).
01997     const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
01998     leftButtonPressed = (QApplication::mouseButtons() & Qt::LeftButton) &&
01999                         !(modifiers & Qt::ShiftModifier) && !(modifiers & Qt::ControlModifier);
02000 }
02001 
02002 void KDirOperator::Private::_k_slotClicked(const QModelIndex& index)
02003 {
02004     if (!leftButtonPressed || (index.column() != KDirModel::Name)) {
02005         return;
02006     }
02007 
02008     if (!parent->onlyDoubleClickSelectsFiles())
02009         _k_slotDoubleClicked(index);
02010     else
02011         _k_slotActivated(index);
02012 }
02013 
02014 void KDirOperator::Private::_k_slotActivated(const QModelIndex& index)
02015 {
02016     const QModelIndex dirIndex = proxyModel->mapToSource(index);
02017     KFileItem item = dirModel->itemForIndex(dirIndex);
02018     bool selectDir = false;
02019 
02020     const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
02021     if (item.isNull() || (modifiers & Qt::ShiftModifier) || (modifiers & Qt::ControlModifier))
02022         return;
02023 
02024     if (item.isDir()) {
02025         const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
02026         selectDir = KGlobalSettings::singleClick() &&
02027                     !(modifiers & Qt::ShiftModifier) &&
02028                     !(modifiers & Qt::ControlModifier);
02029     }
02030 
02031     if (selectDir) {
02032         parent->selectDir(item);
02033     } else {
02034         parent->selectFile(item);
02035     }
02036 }
02037 
02038 void KDirOperator::Private::_k_slotDoubleClicked(const QModelIndex& index)
02039 {
02040     if (!leftButtonPressed) {
02041         return;
02042     }
02043 
02044     const QModelIndex dirIndex = proxyModel->mapToSource(index);
02045     KFileItem item = dirModel->itemForIndex(dirIndex);
02046 
02047     if (item.isNull())
02048         return;
02049 
02050     if (item.isDir()) {
02051         parent->selectDir(item);
02052     } else {
02053         parent->selectFile(item);
02054     }
02055 }
02056 
02057 void KDirOperator::Private::_k_slotSelectionChanged()
02058 {
02059     if (itemView == 0) {
02060         return;
02061     }
02062 
02063     // In the multiselection mode each selection change is indicated by
02064     // emitting a null item. Also when the selection has been cleared, a
02065     // null item must be emitted (see _k_slotClicked()).
02066     const bool multiSelectionMode = (itemView->selectionMode() == QAbstractItemView::ExtendedSelection);
02067     const bool hasSelection = itemView->selectionModel()->hasSelection();
02068     if (multiSelectionMode || !hasSelection) {
02069         KFileItem nullItem;
02070         parent->highlightFile(nullItem);
02071     }
02072     else {
02073         KFileItem selectedItem = parent->selectedItems().first();
02074         parent->highlightFile(selectedItem);
02075     }
02076 }
02077 
02078 void KDirOperator::Private::_k_openContextMenu(const QPoint& pos)
02079 {
02080     leftButtonPressed = false;
02081 
02082     const QModelIndex proxyIndex = itemView->indexAt(pos);
02083     const QModelIndex dirIndex = proxyModel->mapToSource(proxyIndex);
02084     KFileItem item = dirModel->itemForIndex(dirIndex);
02085 
02086     if (item.isNull())
02087         return;
02088 
02089     parent->activatedMenu(item, QCursor::pos());
02090 }
02091 
02092 void KDirOperator::Private::_k_triggerPreview(const QModelIndex& index)
02093 {
02094     if ((preview != 0) && index.isValid() && (index.column() == KDirModel::Name)) {
02095         const QModelIndex dirIndex = proxyModel->mapToSource(index);
02096         const KFileItem item = dirModel->itemForIndex(dirIndex);
02097 
02098         if (item.isNull())
02099             return;
02100 
02101         if (!item.isDir()) {
02102             previewUrl = item.url();
02103             _k_showPreview();
02104         } else {
02105             preview->clearPreview();
02106         }
02107     }
02108 }
02109 
02110 void KDirOperator::Private::_k_showPreview()
02111 {
02112     if (preview != 0) {
02113         preview->showPreview(previewUrl);
02114     }
02115 }
02116 
02117 void KDirOperator::Private::_k_slotSplitterMoved(int, int)
02118 {
02119     const QList<int> sizes = splitter->sizes();
02120     if (sizes.count() == 2) {
02121         // remember the width of the preview widget (see KDirOperator::resizeEvent())
02122         previewWidth = sizes[1];
02123     }
02124 }
02125 
02126 void KDirOperator::Private::_k_assureVisibleSelection()
02127 {
02128     if (itemView == 0) {
02129         return;
02130     }
02131 
02132     QItemSelectionModel* selModel = itemView->selectionModel();
02133     if (selModel->hasSelection()) {
02134         const QModelIndex index = selModel->currentIndex();
02135         itemView->scrollTo(index, QAbstractItemView::PositionAtCenter);
02136         _k_triggerPreview(index);
02137     }
02138 }
02139 
02140 
02141 void KDirOperator::Private::_k_synchronizeSortingState(int logicalIndex, Qt::SortOrder order)
02142 {
02143     switch (logicalIndex) {
02144     case KDirModel::Name: parent->sortByName(); break;
02145     case KDirModel::Size: parent->sortBySize(); break;
02146     case KDirModel::ModifiedTime: parent->sortByDate(); break;
02147     case KDirModel::Type: parent->sortByType(); break;
02148     }
02149 
02150     const bool descending = actionCollection->action("descending")->isChecked();
02151     const bool reverseSorting = ((order == Qt::AscendingOrder) && descending) ||
02152                                 ((order == Qt::DescendingOrder) && !descending);
02153     if (reverseSorting) {
02154         parent->sortReversed();
02155     }
02156 
02157     proxyModel->sort(sortColumn(), sortOrder());
02158     QMetaObject::invokeMethod(parent, "_k_assureVisibleSelection", Qt::QueuedConnection);
02159 }
02160 
02161 void KDirOperator::setViewConfig(KConfigGroup& configGroup)
02162 {
02163     delete d->configGroup;
02164     d->configGroup = new KConfigGroup(configGroup);
02165 }
02166 
02167 KConfigGroup* KDirOperator::viewConfigGroup() const
02168 {
02169     return d->configGroup;
02170 }
02171 
02172 void KDirOperator::setShowHiddenFiles(bool s)
02173 {
02174     d->actionCollection->action("show hidden")->setChecked(s);
02175 }
02176 
02177 bool KDirOperator::showHiddenFiles() const
02178 {
02179     return d->actionCollection->action("show hidden")->isChecked();
02180 }
02181 
02182 // ### temporary code
02183 #include <dirent.h>
02184 bool KDirOperator::Private::isReadable(const KUrl& url)
02185 {
02186     if (!url.isLocalFile())
02187         return true; // what else can we say?
02188 
02189     KDE_struct_stat buf;
02190 #ifdef Q_WS_WIN
02191     QString ts = url.toLocalFile();
02192 #else
02193     QString ts = url.path(KUrl::AddTrailingSlash);
02194 #endif
02195     bool readable = (KDE_stat(QFile::encodeName(ts), &buf) == 0);
02196     if (readable) { // further checks
02197         DIR *test;
02198         test = opendir(QFile::encodeName(ts));    // we do it just to test here
02199         readable = (test != 0);
02200         if (test)
02201             closedir(test);
02202     }
02203     return readable;
02204 }
02205 
02206 #include "kdiroperator.moc"

KFile

Skip menu "KFile"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal