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