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