00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00086
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
00168
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
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
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
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
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;
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
00340
00341
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;
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()) {
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("/");
00387 }
00388
00389
00390
00391
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
00411 setupActions();
00412 setupMenu();
00413
00414 d->sorting = QDir::NoSort;
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
00485 d->_k_slotSortReversed(!(d->sorting & QDir::Reversed));
00486 }
00487
00488 void KDirOperator::toggleDirsFirst()
00489 {
00490
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
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
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 }
00716
00717 void KDirOperator::Private::_k_slotToggleIgnoreCase()
00718 {
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
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
00753
00754
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) {
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 )
00985 {
00986 #if 0
00987
00988 QString text = _txt;
00989
00990
00991 text = text.trimmed();
00992
00993
00994 if (text.find(':') < 0 && text[0] != '/')
00995 text.insert(0, d->currUrl);
00996
00997
00998
00999 if (!selection.isNull()) {
01000 int position = text.lastIndexOf('/');
01001 ASSERT(position >= 0);
01002 QString filename = text.mid(position + 1, text.length());
01003 if (filename != selection)
01004 selection.clear();
01005 }
01006
01007 KUrl u(text);
01008 bool filenameEntered = false;
01009
01010 if (u.isLocalFile()) {
01011
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
01055 if (newurl.equals(d->currUrl, KUrl::CompareWithoutTrailingSlash))
01056 return;
01057
01058 if (!Private::isReadable(newurl)) {
01059
01060 newurl.setPath(newurl.directory(KUrl::ObeyTrailingSlash));
01061 if (newurl.equals(d->currUrl, KUrl::CompareWithoutTrailingSlash))
01062 return;
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
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
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)
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
01160
01161
01162
01163
01164
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
01177 void KDirOperator::pathChanged()
01178 {
01179 if (d->itemView == 0)
01180 return;
01181
01182 d->pendingMimeTypes.clear();
01183
01184 d->completion.clear();
01185 d->dirCompletion.clear();
01186
01187
01188 QApplication::restoreOverrideCursor();
01189
01190
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
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
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
01323
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
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);
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()) {
01406 return true;
01407 }
01408 }
01409 }
01410
01411 if (!nameFilter.isEmpty()) {
01412
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 );
01420 if (!mt)
01421 continue;
01422 QString mime = mt->name();
01423
01424
01425
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
01457
01458
01459 QWidget::setAcceptDrops(b);
01460 }
01461
01462 void KDirOperator::setDropOptions(int options)
01463 {
01464 d->dropOptions = options;
01465
01466
01467
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
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
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
01542
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
01562
01563
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
01607
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
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
01634 emit currentIconSizeChanged(zoom);
01635 }
01636
01637 void KDirOperator::setDirLister(KDirLister *lister)
01638 {
01639 if (lister == d->dirLister)
01640 return;
01641
01642 delete d->dirModel;
01643 d->dirModel = 0;
01644
01645 delete d->proxyModel;
01646 d->proxyModel = 0;
01647
01648
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) {
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
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
01966 KActionMenu* viewMenu = new KActionMenu(i18n("&View"), this);
01967 d->actionCollection->addAction("view menu", viewMenu);
01968 viewMenu->addAction(shortAction);
01969 viewMenu->addAction(detailedAction);
01970
01971 viewMenu->addAction(treeAction);
01972 viewMenu->addAction(detailedTreeAction);
01973
01974
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
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
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
02059
02060
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
02082
02083
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
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
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
02188
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
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
02216
02217
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
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
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
02322
02323
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
02371
02372
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
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
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
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
02632 #include <dirent.h>
02633 bool KDirOperator::Private::isReadable(const KUrl& url)
02634 {
02635 if (!url.isLocalFile())
02636 return true;
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) {
02646 DIR *test;
02647 test = opendir(QFile::encodeName(ts));
02648 readable = (test != 0);
02649 if (test)
02650 closedir(test);
02651 }
02652 return readable;
02653 }
02654
02655 #include "kdiroperator.moc"