• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.10.4 API Reference
  • KDE Home
  • Contact Us
 

KFile

  • kfile
kdiroperator.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  Copyright (C) 1999,2000 Stephan Kulow <coolo@kde.org>
3  1999,2000,2001,2002,2003 Carsten Pfeiffer <pfeiffer@kde.org>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "kdiroperator.h"
22 #include <kprotocolmanager.h>
23 #include "kdirmodel.h"
24 #include "kdiroperatordetailview_p.h"
25 #include "kdirsortfilterproxymodel.h"
26 #include "kfileitem.h"
27 #include "kfilemetapreview.h"
28 #include "kpreviewwidgetbase.h"
29 #include "knewfilemenu.h"
30 
31 #include <config-kfile.h>
32 
33 #include <unistd.h>
34 
35 #include <QtCore/QDir>
36 #include <QtCore/QRegExp>
37 #include <QtCore/QTimer>
38 #include <QtCore/QAbstractItemModel>
39 #include <QtGui/QApplication>
40 #include <QtGui/QDialog>
41 #include <QtGui/QHeaderView>
42 #include <QtGui/QLabel>
43 #include <QtGui/QLayout>
44 #include <QtGui/QListView>
45 #include <QtGui/QMouseEvent>
46 #include <QtGui/QTreeView>
47 #include <QtGui/QPushButton>
48 #include <QtGui/QProgressBar>
49 #include <QtGui/QScrollBar>
50 #include <QtGui/QSplitter>
51 #include <QtGui/QWheelEvent>
52 
53 #include <kaction.h>
54 #include <kapplication.h>
55 #include <kdebug.h>
56 #include <kdialog.h>
57 #include <kdirlister.h>
58 #include <kfileitemdelegate.h>
59 #include <kicon.h>
60 #include <kinputdialog.h>
61 #include <klocale.h>
62 #include <kmessagebox.h>
63 #include <kmenu.h>
64 #include <kstandardaction.h>
65 #include <kio/job.h>
66 #include <kio/deletejob.h>
67 #include <kio/copyjob.h>
68 #include <kio/jobuidelegate.h>
69 #include <kio/jobclasses.h>
70 #include <kio/netaccess.h>
71 #include <kio/previewjob.h>
72 #include <kio/renamedialog.h>
73 #include <kfilepreviewgenerator.h>
74 #include <krun.h>
75 #include <kpropertiesdialog.h>
76 #include <kstandardshortcut.h>
77 #include <kde_file.h>
78 #include <kactioncollection.h>
79 #include <ktoggleaction.h>
80 #include <kactionmenu.h>
81 #include <kconfiggroup.h>
82 #include <kdeversion.h>
83 
84 
85 template class QHash<QString, KFileItem>;
86 
87 // QDir::SortByMask is not only undocumented, it also omits QDir::Type which is another
88 // sorting mode.
89 static const int QDirSortMask = QDir::SortByMask | QDir::Type;
90 
95 class KDirOperatorIconView : public QListView
96 {
97 public:
98  KDirOperatorIconView(KDirOperator *dirOperator, QWidget *parent = 0);
99  virtual ~KDirOperatorIconView();
100 
101 protected:
102  virtual QStyleOptionViewItem viewOptions() const;
103  virtual void dragEnterEvent(QDragEnterEvent* event);
104  virtual void mousePressEvent(QMouseEvent *event);
105  virtual void wheelEvent(QWheelEvent *event);
106 
107 private:
108  KDirOperator *ops;
109 };
110 
111 KDirOperatorIconView::KDirOperatorIconView(KDirOperator *dirOperator, QWidget *parent) :
112  QListView(parent),
113  ops(dirOperator)
114 {
115  setViewMode(QListView::IconMode);
116  setFlow(QListView::TopToBottom);
117  setResizeMode(QListView::Adjust);
118  setSpacing(0);
119  setMovement(QListView::Static);
120  setDragDropMode(QListView::DragOnly);
121  setVerticalScrollMode(QListView::ScrollPerPixel);
122  setHorizontalScrollMode(QListView::ScrollPerPixel);
123  setEditTriggers(QAbstractItemView::NoEditTriggers);
124  setWordWrap(true);
125  setIconSize(QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall));
126 }
127 
128 KDirOperatorIconView::~KDirOperatorIconView()
129 {
130 }
131 
132 QStyleOptionViewItem KDirOperatorIconView::viewOptions() const
133 {
134  QStyleOptionViewItem viewOptions = QListView::viewOptions();
135  viewOptions.showDecorationSelected = true;
136  viewOptions.decorationPosition = ops->decorationPosition();
137  if (viewOptions.decorationPosition == QStyleOptionViewItem::Left) {
138  viewOptions.displayAlignment = Qt::AlignLeft | Qt::AlignVCenter;
139  } else {
140  viewOptions.displayAlignment = Qt::AlignCenter;
141  }
142 
143  return viewOptions;
144 }
145 
146 void KDirOperatorIconView::dragEnterEvent(QDragEnterEvent* event)
147 {
148  if (event->mimeData()->hasUrls()) {
149  event->acceptProposedAction();
150  }
151 }
152 
153 void KDirOperatorIconView::mousePressEvent(QMouseEvent *event)
154 {
155  if (!indexAt(event->pos()).isValid()) {
156  const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
157  if (!(modifiers & Qt::ShiftModifier) && !(modifiers & Qt::ControlModifier)) {
158  clearSelection();
159  }
160  }
161 
162  QListView::mousePressEvent(event);
163 }
164 
165 void KDirOperatorIconView::wheelEvent(QWheelEvent *event)
166 {
167  QListView::wheelEvent(event);
168 
169  // apply the vertical wheel event to the horizontal scrollbar, as
170  // the items are aligned from left to right
171  if (event->orientation() == Qt::Vertical) {
172  QWheelEvent horizEvent(event->pos(),
173  event->delta(),
174  event->buttons(),
175  event->modifiers(),
176  Qt::Horizontal);
177  QApplication::sendEvent(horizontalScrollBar(), &horizEvent);
178  }
179 }
180 
181 void KDirOperator::keyPressEvent(QKeyEvent *e)
182 {
183  if (!(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )) {
184  QWidget::keyPressEvent(e);
185  }
186 }
187 
188 class KDirOperator::Private
189 {
190 public:
191  Private( KDirOperator *parent );
192  ~Private();
193 
194  enum InlinePreviewState {
195  ForcedToFalse = 0,
196  ForcedToTrue,
197  NotForced
198  };
199 
200  // private methods
201  bool checkPreviewInternal() const;
202  void checkPath(const QString &txt, bool takeFiles = false);
203  bool openUrl(const KUrl &url, KDirLister::OpenUrlFlags flags = KDirLister::NoFlags);
204  int sortColumn() const;
205  Qt::SortOrder sortOrder() const;
206  void updateSorting(QDir::SortFlags sort);
207 
208  static bool isReadable(const KUrl &url);
209 
210  KFile::FileView allViews();
211 
212  // private slots
213  void _k_slotDetailedView();
214  void _k_slotSimpleView();
215  void _k_slotTreeView();
216  void _k_slotDetailedTreeView();
217  void _k_slotToggleHidden(bool);
218  void _k_togglePreview(bool);
219  void _k_toggleInlinePreviews(bool);
220  void _k_slotOpenFileManager();
221  void _k_slotSortByName();
222  void _k_slotSortBySize();
223  void _k_slotSortByDate();
224  void _k_slotSortByType();
225  void _k_slotSortReversed(bool doReverse);
226  void _k_slotToggleDirsFirst();
227  void _k_slotToggleIgnoreCase();
228  void _k_slotStarted();
229  void _k_slotProgress(int);
230  void _k_slotShowProgress();
231  void _k_slotIOFinished();
232  void _k_slotCanceled();
233  void _k_slotRedirected(const KUrl&);
234  void _k_slotProperties();
235  void _k_slotActivated(const QModelIndex&);
236  void _k_slotSelectionChanged();
237  void _k_openContextMenu(const QPoint&);
238  void _k_triggerPreview(const QModelIndex&);
239  void _k_showPreview();
240  void _k_slotSplitterMoved(int, int);
241  void _k_assureVisibleSelection();
242  void _k_synchronizeSortingState(int, Qt::SortOrder);
243  void _k_slotChangeDecorationPosition();
244  void _k_slotExpandToUrl(const QModelIndex&);
245  void _k_slotItemsChanged();
246  void _k_slotDirectoryCreated(const KUrl&);
247 
248  void updateListViewGrid();
249  int iconSizeForViewType(QAbstractItemView *itemView) const;
250 
251  // private members
252  KDirOperator *parent;
253  QStack<KUrl*> backStack;
254  QStack<KUrl*> forwardStack;
255 
256  QModelIndex lastHoveredIndex;
257 
258  KDirLister *dirLister;
259  KUrl currUrl;
260 
261  KCompletion completion;
262  KCompletion dirCompletion;
263  bool completeListDirty;
264  QDir::SortFlags sorting;
265  QStyleOptionViewItem::Position decorationPosition;
266 
267  QSplitter *splitter;
268 
269  QAbstractItemView *itemView;
270  KDirModel *dirModel;
271  KDirSortFilterProxyModel *proxyModel;
272 
273  KFileItemList pendingMimeTypes;
274 
275  // the enum KFile::FileView as an int
276  int viewKind;
277  int defaultView;
278 
279  KFile::Modes mode;
280  QProgressBar *progressBar;
281 
282  KPreviewWidgetBase *preview;
283  KUrl previewUrl;
284  int previewWidth;
285 
286  bool dirHighlighting;
287  bool onlyDoubleClickSelectsFiles;
288  QString lastURL; // used for highlighting a directory on cdUp
289  QTimer *progressDelayTimer;
290  int dropOptions;
291 
292  KActionMenu *actionMenu;
293  KActionCollection *actionCollection;
294 
295  KNewFileMenu *newFileMenu;
296 
297  KConfigGroup *configGroup;
298 
299  KFilePreviewGenerator *previewGenerator;
300 
301  bool showPreviews;
302  int iconsZoom;
303 
304  bool isSaving;
305 
306  KActionMenu *decorationMenu;
307  KToggleAction *leftAction;
308  KUrl::List itemsToBeSetAsCurrent;
309  bool shouldFetchForItems;
310  InlinePreviewState inlinePreviewState;
311 };
312 
313 KDirOperator::Private::Private(KDirOperator *_parent) :
314  parent(_parent),
315  dirLister(0),
316  decorationPosition(QStyleOptionViewItem::Left),
317  splitter(0),
318  itemView(0),
319  dirModel(0),
320  proxyModel(0),
321  progressBar(0),
322  preview(0),
323  previewUrl(),
324  previewWidth(0),
325  dirHighlighting(false),
326  onlyDoubleClickSelectsFiles(!KGlobalSettings::singleClick()),
327  progressDelayTimer(0),
328  dropOptions(0),
329  actionMenu(0),
330  actionCollection(0),
331  newFileMenu(0),
332  configGroup(0),
333  previewGenerator(0),
334  showPreviews(false),
335  iconsZoom(0),
336  isSaving(false),
337  decorationMenu(0),
338  leftAction(0),
339  shouldFetchForItems(false),
340  inlinePreviewState(NotForced)
341 {
342 }
343 
344 KDirOperator::Private::~Private()
345 {
346  delete itemView;
347  itemView = 0;
348 
349  // TODO:
350  // if (configGroup) {
351  // itemView->writeConfig(configGroup);
352  // }
353 
354  qDeleteAll(backStack);
355  qDeleteAll(forwardStack);
356  delete preview;
357  preview = 0;
358 
359  delete proxyModel;
360  proxyModel = 0;
361  delete dirModel;
362  dirModel = 0;
363  dirLister = 0; // deleted by KDirModel
364  delete configGroup;
365  configGroup = 0;
366 
367  delete progressDelayTimer;
368  progressDelayTimer = 0;
369 }
370 
371 KDirOperator::KDirOperator(const KUrl& _url, QWidget *parent) :
372  QWidget(parent),
373  d(new Private(this))
374 {
375  d->splitter = new QSplitter(this);
376  d->splitter->setChildrenCollapsible(false);
377  connect(d->splitter, SIGNAL(splitterMoved(int,int)),
378  this, SLOT(_k_slotSplitterMoved(int,int)));
379 
380  d->preview = 0;
381 
382  d->mode = KFile::File;
383  d->viewKind = KFile::Simple;
384 
385  if (_url.isEmpty()) { // no dir specified -> current dir
386  QString strPath = QDir::currentPath();
387  strPath.append(QChar('/'));
388  d->currUrl = KUrl();
389  d->currUrl.setProtocol(QLatin1String("file"));
390  d->currUrl.setPath(strPath);
391  } else {
392  d->currUrl = _url;
393  if (d->currUrl.protocol().isEmpty())
394  d->currUrl.setProtocol(QLatin1String("file"));
395 
396  d->currUrl.addPath("/"); // make sure we have a trailing slash!
397  }
398 
399  // We set the direction of this widget to LTR, since even on RTL desktops
400  // viewing directory listings in RTL mode makes people's head explode.
401  // Is this the correct place? Maybe it should be in some lower level widgets...?
402  setLayoutDirection(Qt::LeftToRight);
403  setDirLister(new KDirLister());
404 
405  connect(&d->completion, SIGNAL(match(QString)),
406  SLOT(slotCompletionMatch(QString)));
407 
408  d->progressBar = new QProgressBar(this);
409  d->progressBar->setObjectName("d->progressBar");
410  d->progressBar->adjustSize();
411  d->progressBar->move(2, height() - d->progressBar->height() - 2);
412 
413  d->progressDelayTimer = new QTimer(this);
414  d->progressDelayTimer->setObjectName(QLatin1String("d->progressBar delay timer"));
415  connect(d->progressDelayTimer, SIGNAL(timeout()),
416  SLOT(_k_slotShowProgress()));
417 
418  d->completeListDirty = false;
419 
420  // action stuff
421  setupActions();
422  setupMenu();
423 
424  d->sorting = QDir::NoSort; //so updateSorting() doesn't think nothing has changed
425  d->updateSorting(QDir::Name | QDir::DirsFirst);
426 
427  setFocusPolicy(Qt::WheelFocus);
428 }
429 
430 KDirOperator::~KDirOperator()
431 {
432  resetCursor();
433  disconnect(d->dirLister, 0, this, 0);
434  delete d;
435 }
436 
437 
438 void KDirOperator::setSorting(QDir::SortFlags spec)
439 {
440  d->updateSorting(spec);
441 }
442 
443 QDir::SortFlags KDirOperator::sorting() const
444 {
445  return d->sorting;
446 }
447 
448 bool KDirOperator::isRoot() const
449 {
450 #ifdef Q_WS_WIN
451  if (url().isLocalFile()) {
452  const QString path = url().toLocalFile();
453  if (path.length() == 3)
454  return (path[0].isLetter() && path[1] == ':' && path[2] == '/');
455  return false;
456  } else
457 #endif
458  return url().path() == QString(QLatin1Char('/'));
459 }
460 
461 KDirLister *KDirOperator::dirLister() const
462 {
463  return d->dirLister;
464 }
465 
466 void KDirOperator::resetCursor()
467 {
468  if (qApp)
469  QApplication::restoreOverrideCursor();
470  d->progressBar->hide();
471 }
472 
473 void KDirOperator::sortByName()
474 {
475  d->updateSorting((d->sorting & ~QDirSortMask) | QDir::Name);
476 }
477 
478 void KDirOperator::sortBySize()
479 {
480  d->updateSorting((d->sorting & ~QDirSortMask) | QDir::Size);
481 }
482 
483 void KDirOperator::sortByDate()
484 {
485  d->updateSorting((d->sorting & ~QDirSortMask) | QDir::Time);
486 }
487 
488 void KDirOperator::sortByType()
489 {
490  d->updateSorting((d->sorting & ~QDirSortMask) | QDir::Type);
491 }
492 
493 void KDirOperator::sortReversed()
494 {
495  // toggle it, hence the inversion of current state
496  d->_k_slotSortReversed(!(d->sorting & QDir::Reversed));
497 }
498 
499 void KDirOperator::toggleDirsFirst()
500 {
501  d->_k_slotToggleDirsFirst();
502 }
503 
504 void KDirOperator::toggleIgnoreCase()
505 {
506  if (d->proxyModel != 0) {
507  Qt::CaseSensitivity cs = d->proxyModel->sortCaseSensitivity();
508  cs = (cs == Qt::CaseSensitive) ? Qt::CaseInsensitive : Qt::CaseSensitive;
509  d->proxyModel->setSortCaseSensitivity(cs);
510  }
511 }
512 
513 void KDirOperator::updateSelectionDependentActions()
514 {
515  const bool hasSelection = (d->itemView != 0) &&
516  d->itemView->selectionModel()->hasSelection();
517  d->actionCollection->action("trash")->setEnabled(hasSelection);
518  d->actionCollection->action("delete")->setEnabled(hasSelection);
519  d->actionCollection->action("properties")->setEnabled(hasSelection);
520 }
521 
522 void KDirOperator::setPreviewWidget(KPreviewWidgetBase *w)
523 {
524  const bool showPreview = (w != 0);
525  if (showPreview) {
526  d->viewKind = (d->viewKind | KFile::PreviewContents);
527  } else {
528  d->viewKind = (d->viewKind & ~KFile::PreviewContents);
529  }
530 
531  delete d->preview;
532  d->preview = w;
533 
534  if (w) {
535  d->splitter->addWidget(w);
536  }
537 
538  KToggleAction *previewAction = static_cast<KToggleAction*>(d->actionCollection->action("preview"));
539  previewAction->setEnabled(showPreview);
540  previewAction->setChecked(showPreview);
541  setView(static_cast<KFile::FileView>(d->viewKind));
542 }
543 
544 KFileItemList KDirOperator::selectedItems() const
545 {
546  KFileItemList itemList;
547  if (d->itemView == 0) {
548  return itemList;
549  }
550 
551  const QItemSelection selection = d->proxyModel->mapSelectionToSource(d->itemView->selectionModel()->selection());
552 
553  const QModelIndexList indexList = selection.indexes();
554  foreach(const QModelIndex &index, indexList) {
555  KFileItem item = d->dirModel->itemForIndex(index);
556  if (!item.isNull()) {
557  itemList.append(item);
558  }
559  }
560 
561  return itemList;
562 }
563 
564 bool KDirOperator::isSelected(const KFileItem &item) const
565 {
566  if ((item.isNull()) || (d->itemView == 0)) {
567  return false;
568  }
569 
570  const QModelIndex dirIndex = d->dirModel->indexForItem(item);
571  const QModelIndex proxyIndex = d->proxyModel->mapFromSource(dirIndex);
572  return d->itemView->selectionModel()->isSelected(proxyIndex);
573 }
574 
575 int KDirOperator::numDirs() const
576 {
577  return (d->dirLister == 0) ? 0 : d->dirLister->directories().count();
578 }
579 
580 int KDirOperator::numFiles() const
581 {
582  return (d->dirLister == 0) ? 0 : d->dirLister->items().count() - numDirs();
583 }
584 
585 KCompletion * KDirOperator::completionObject() const
586 {
587  return const_cast<KCompletion *>(&d->completion);
588 }
589 
590 KCompletion *KDirOperator::dirCompletionObject() const
591 {
592  return const_cast<KCompletion *>(&d->dirCompletion);
593 }
594 
595 KActionCollection * KDirOperator::actionCollection() const
596 {
597  return d->actionCollection;
598 }
599 
600 KFile::FileView KDirOperator::Private::allViews() {
601  return static_cast<KFile::FileView>(KFile::Simple | KFile::Detail | KFile::Tree | KFile::DetailTree);
602 }
603 
604 void KDirOperator::Private::_k_slotDetailedView()
605 {
606  KFile::FileView view = static_cast<KFile::FileView>((viewKind & ~allViews()) | KFile::Detail);
607  parent->setView(view);
608 }
609 
610 void KDirOperator::Private::_k_slotSimpleView()
611 {
612  KFile::FileView view = static_cast<KFile::FileView>((viewKind & ~allViews()) | KFile::Simple);
613  parent->setView(view);
614 }
615 
616 void KDirOperator::Private::_k_slotTreeView()
617 {
618  KFile::FileView view = static_cast<KFile::FileView>((viewKind & ~allViews()) | KFile::Tree);
619  parent->setView(view);
620 }
621 
622 void KDirOperator::Private::_k_slotDetailedTreeView()
623 {
624  KFile::FileView view = static_cast<KFile::FileView>((viewKind & ~allViews()) | KFile::DetailTree);
625  parent->setView(view);
626 }
627 
628 void KDirOperator::Private::_k_slotToggleHidden(bool show)
629 {
630  dirLister->setShowingDotFiles(show);
631  parent->updateDir();
632  _k_assureVisibleSelection();
633 }
634 
635 void KDirOperator::Private::_k_togglePreview(bool on)
636 {
637  if (on) {
638  viewKind = viewKind | KFile::PreviewContents;
639  if (preview == 0) {
640  preview = new KFileMetaPreview(parent);
641  actionCollection->action("preview")->setChecked(true);
642  splitter->addWidget(preview);
643  }
644 
645  preview->show();
646 
647  QMetaObject::invokeMethod(parent, "_k_assureVisibleSelection", Qt::QueuedConnection);
648  if (itemView != 0) {
649  const QModelIndex index = itemView->selectionModel()->currentIndex();
650  if (index.isValid()) {
651  _k_triggerPreview(index);
652  }
653  }
654  } else if (preview != 0) {
655  viewKind = viewKind & ~KFile::PreviewContents;
656  preview->hide();
657  }
658 }
659 
660 void KDirOperator::Private::_k_toggleInlinePreviews(bool show)
661 {
662  if (showPreviews == show) {
663  return;
664  }
665 
666  showPreviews = show;
667 
668  if (!previewGenerator) {
669  return;
670  }
671 
672  previewGenerator->setPreviewShown(show);
673 
674  if (!show) {
675  // remove all generated previews
676  QAbstractItemModel *model = dirModel;
677  for (int i = 0; i < model->rowCount(); ++i) {
678  QModelIndex index = model->index(i, 0);
679  const KFileItem item = dirModel->itemForIndex(index);
680  const_cast<QAbstractItemModel*>(index.model())->setData(index, KIcon(item.iconName()), Qt::DecorationRole);
681  }
682  }
683 }
684 
685 void KDirOperator::Private::_k_slotOpenFileManager()
686 {
687  new KRun(currUrl, parent);
688 }
689 
690 void KDirOperator::Private::_k_slotSortByName()
691 {
692  parent->sortByName();
693 }
694 
695 void KDirOperator::Private::_k_slotSortBySize()
696 {
697  parent->sortBySize();
698 }
699 
700 void KDirOperator::Private::_k_slotSortByDate()
701 {
702  parent->sortByDate();
703 }
704 
705 void KDirOperator::Private::_k_slotSortByType()
706 {
707  parent->sortByType();
708 }
709 
710 void KDirOperator::Private::_k_slotSortReversed(bool doReverse)
711 {
712  QDir::SortFlags s = sorting & ~QDir::Reversed;
713  if (doReverse) {
714  s |= QDir::Reversed;
715  }
716  updateSorting(s);
717 }
718 
719 void KDirOperator::Private::_k_slotToggleDirsFirst()
720 {
721  QDir::SortFlags s = (sorting ^ QDir::DirsFirst);
722  updateSorting(s);
723 }
724 
725 void KDirOperator::Private::_k_slotToggleIgnoreCase()
726 {
727  // TODO: port to Qt4's QAbstractItemView
728  /*if ( !d->fileView )
729  return;
730 
731  QDir::SortFlags sorting = d->fileView->sorting();
732  if ( !KFile::isSortCaseInsensitive( sorting ) )
733  d->fileView->setSorting( sorting | QDir::IgnoreCase );
734  else
735  d->fileView->setSorting( sorting & ~QDir::IgnoreCase );
736  d->sorting = d->fileView->sorting();*/
737 }
738 
739 void KDirOperator::mkdir()
740 {
741  d->newFileMenu->setPopupFiles(url());
742  d->newFileMenu->setViewShowsHiddenFiles(showHiddenFiles());
743  d->newFileMenu->createDirectory();
744 }
745 
746 bool KDirOperator::mkdir(const QString& directory, bool enterDirectory)
747 {
748  // Creates "directory", relative to the current directory (d->currUrl).
749  // The given path may contain any number directories, existent or not.
750  // They will all be created, if possible.
751 
752  bool writeOk = false;
753  bool exists = false;
754  KUrl url(d->currUrl);
755 
756  const QStringList dirs = directory.split('/', QString::SkipEmptyParts);
757  QStringList::ConstIterator it = dirs.begin();
758 
759  for (; it != dirs.end(); ++it) {
760  url.addPath(*it);
761  exists = KIO::NetAccess::exists(url, KIO::NetAccess::DestinationSide, this);
762  writeOk = !exists && KIO::NetAccess::mkdir(url, this);
763  }
764 
765  if (exists) { // url was already existent
766  KMessageBox::sorry(d->itemView, i18n("A file or folder named %1 already exists.", url.pathOrUrl()));
767  } else if (!writeOk) {
768  KMessageBox::sorry(d->itemView, i18n("You do not have permission to "
769  "create that folder."));
770  } else if (enterDirectory) {
771  setUrl(url, true);
772  }
773 
774  return writeOk;
775 }
776 
777 KIO::DeleteJob * KDirOperator::del(const KFileItemList& items,
778  QWidget *parent,
779  bool ask, bool showProgress)
780 {
781  if (items.isEmpty()) {
782  KMessageBox::information(parent,
783  i18n("You did not select a file to delete."),
784  i18n("Nothing to Delete"));
785  return 0L;
786  }
787 
788  if (parent == 0) {
789  parent = this;
790  }
791 
792  KUrl::List urls;
793  QStringList files;
794  foreach (const KFileItem &item, items) {
795  const KUrl url = item.url();
796  urls.append(url);
797  files.append(url.pathOrUrl());
798  }
799 
800  bool doIt = !ask;
801  if (ask) {
802  int ret;
803  if (items.count() == 1) {
804  ret = KMessageBox::warningContinueCancel(parent,
805  i18n("<qt>Do you really want to delete\n <b>'%1'</b>?</qt>" ,
806  files.first()),
807  i18n("Delete File"),
808  KStandardGuiItem::del(),
809  KStandardGuiItem::cancel(), "AskForDelete");
810  } else
811  ret = KMessageBox::warningContinueCancelList(parent,
812  i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", items.count()),
813  files,
814  i18n("Delete Files"),
815  KStandardGuiItem::del(),
816  KStandardGuiItem::cancel(), "AskForDelete");
817  doIt = (ret == KMessageBox::Continue);
818  }
819 
820  if (doIt) {
821  KIO::JobFlags flags = showProgress ? KIO::DefaultFlags : KIO::HideProgressInfo;
822  KIO::DeleteJob *job = KIO::del(urls, flags);
823  job->ui()->setWindow(this);
824  job->ui()->setAutoErrorHandlingEnabled(true);
825  return job;
826  }
827 
828  return 0L;
829 }
830 
831 void KDirOperator::deleteSelected()
832 {
833  const KFileItemList list = selectedItems();
834  if (!list.isEmpty()) {
835  del(list, this);
836  }
837 }
838 
839 KIO::CopyJob * KDirOperator::trash(const KFileItemList& items,
840  QWidget *parent,
841  bool ask, bool showProgress)
842 {
843  if (items.isEmpty()) {
844  KMessageBox::information(parent,
845  i18n("You did not select a file to trash."),
846  i18n("Nothing to Trash"));
847  return 0L;
848  }
849 
850  KUrl::List urls;
851  QStringList files;
852  foreach (const KFileItem &item, items) {
853  const KUrl url = item.url();
854  urls.append(url);
855  files.append(url.pathOrUrl());
856  }
857 
858  bool doIt = !ask;
859  if (ask) {
860  int ret;
861  if (items.count() == 1) {
862  ret = KMessageBox::warningContinueCancel(parent,
863  i18n("<qt>Do you really want to trash\n <b>'%1'</b>?</qt>" ,
864  files.first()),
865  i18n("Trash File"),
866  KGuiItem(i18nc("to trash", "&Trash"), "user-trash"),
867  KStandardGuiItem::cancel(), "AskForTrash");
868  } else
869  ret = KMessageBox::warningContinueCancelList(parent,
870  i18np("translators: not called for n == 1", "Do you really want to trash these %1 items?", items.count()),
871  files,
872  i18n("Trash Files"),
873  KGuiItem(i18nc("to trash", "&Trash"), "user-trash"),
874  KStandardGuiItem::cancel(), "AskForTrash");
875  doIt = (ret == KMessageBox::Continue);
876  }
877 
878  if (doIt) {
879  KIO::JobFlags flags = showProgress ? KIO::DefaultFlags : KIO::HideProgressInfo;
880  KIO::CopyJob *job = KIO::trash(urls, flags);
881  job->ui()->setWindow(this);
882  job->ui()->setAutoErrorHandlingEnabled(true);
883  return job;
884  }
885 
886  return 0L;
887 }
888 
889 KFilePreviewGenerator *KDirOperator::previewGenerator() const
890 {
891  return d->previewGenerator;
892 }
893 
894 void KDirOperator::setInlinePreviewShown(bool show)
895 {
896  d->inlinePreviewState = show ? Private::ForcedToTrue : Private::ForcedToFalse;
897 }
898 
899 bool KDirOperator::isInlinePreviewShown() const
900 {
901  return d->showPreviews;
902 }
903 
904 int KDirOperator::iconsZoom() const
905 {
906  return d->iconsZoom;
907 }
908 
909 void KDirOperator::setIsSaving(bool isSaving)
910 {
911  d->isSaving = isSaving;
912 }
913 
914 bool KDirOperator::isSaving() const
915 {
916  return d->isSaving;
917 }
918 
919 void KDirOperator::trashSelected()
920 {
921  if (d->itemView == 0) {
922  return;
923  }
924 
925  if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {
926  deleteSelected();
927  return;
928  }
929 
930  const KFileItemList list = selectedItems();
931  if (!list.isEmpty()) {
932  trash(list, this);
933  }
934 }
935 
936 void KDirOperator::setIconsZoom(int _value)
937 {
938  if (d->iconsZoom == _value) {
939  return;
940  }
941 
942  int value = _value;
943  value = qMin(100, value);
944  value = qMax(0, value);
945 
946  d->iconsZoom = value;
947 
948  if (d->configGroup && d->inlinePreviewState == Private::NotForced) {
949  if (qobject_cast<QListView*>(d->itemView)) {
950  d->configGroup->writeEntry("listViewIconSize", d->iconsZoom);
951  } else {
952  d->configGroup->writeEntry("detailedViewIconSize", d->iconsZoom);
953  }
954  }
955 
956  if (!d->previewGenerator) {
957  return;
958  }
959 
960  const int maxSize = KIconLoader::SizeEnormous - KIconLoader::SizeSmall;
961  const int val = (maxSize * value / 100) + KIconLoader::SizeSmall;
962  d->itemView->setIconSize(QSize(val, val));
963  d->updateListViewGrid();
964  d->previewGenerator->updatePreviews();
965 
966  emit currentIconSizeChanged(value);
967 }
968 
969 void KDirOperator::close()
970 {
971  resetCursor();
972  d->pendingMimeTypes.clear();
973  d->completion.clear();
974  d->dirCompletion.clear();
975  d->completeListDirty = true;
976  d->dirLister->stop();
977 }
978 
979 void KDirOperator::Private::checkPath(const QString &, bool /*takeFiles*/) // SLOT
980 {
981 #if 0
982  // copy the argument in a temporary string
983  QString text = _txt;
984  // it's unlikely to happen, that at the beginning are spaces, but
985  // for the end, it happens quite often, I guess.
986  text = text.trimmed();
987  // if the argument is no URL (the check is quite fragil) and it's
988  // no absolute path, we add the current directory to get a correct url
989  if (text.find(':') < 0 && text[0] != '/')
990  text.insert(0, d->currUrl);
991 
992  // in case we have a selection defined and someone patched the file-
993  // name, we check, if the end of the new name is changed.
994  if (!selection.isNull()) {
995  int position = text.lastIndexOf('/');
996  ASSERT(position >= 0); // we already inserted the current d->dirLister in case
997  QString filename = text.mid(position + 1, text.length());
998  if (filename != selection)
999  selection.clear();
1000  }
1001 
1002  KUrl u(text); // I have to take care of entered URLs
1003  bool filenameEntered = false;
1004 
1005  if (u.isLocalFile()) {
1006  // the empty path is kind of a hack
1007  KFileItem i("", u.toLocalFile());
1008  if (i.isDir())
1009  setUrl(text, true);
1010  else {
1011  if (takeFiles)
1012  if (acceptOnlyExisting && !i.isFile())
1013  warning("you entered an invalid URL");
1014  else
1015  filenameEntered = true;
1016  }
1017  } else
1018  setUrl(text, true);
1019 
1020  if (filenameEntered) {
1021  filename_ = u.url();
1022  emit fileSelected(filename_);
1023 
1024  QApplication::restoreOverrideCursor();
1025 
1026  accept();
1027  }
1028 #endif
1029  kDebug(kfile_area) << "TODO KDirOperator::checkPath()";
1030 }
1031 
1032 void KDirOperator::setUrl(const KUrl& _newurl, bool clearforward)
1033 {
1034  KUrl newurl;
1035 
1036  if (!_newurl.isValid())
1037  newurl.setPath(QDir::homePath());
1038  else
1039  newurl = _newurl;
1040 
1041  newurl.adjustPath( KUrl::AddTrailingSlash );
1042 #ifdef Q_WS_WIN
1043  QString pathstr = QDir::fromNativeSeparators(newurl.toLocalFile());
1044 #else
1045  QString pathstr = newurl.path();
1046 #endif
1047  newurl.setPath(pathstr);
1048 
1049  // already set
1050  if (newurl.equals(d->currUrl, KUrl::CompareWithoutTrailingSlash))
1051  return;
1052 
1053  if (!Private::isReadable(newurl)) {
1054  // maybe newurl is a file? check its parent directory
1055  newurl.setPath(newurl.directory(KUrl::ObeyTrailingSlash));
1056  if (newurl.equals(d->currUrl, KUrl::CompareWithoutTrailingSlash))
1057  return; // parent is current dir, nothing to do (fixes #173454, too)
1058  KIO::UDSEntry entry;
1059  bool res = KIO::NetAccess::stat(newurl, entry, this);
1060  KFileItem i(entry, newurl);
1061  if ((!res || !Private::isReadable(newurl)) && i.isDir()) {
1062  resetCursor();
1063  KMessageBox::error(d->itemView,
1064  i18n("The specified folder does not exist "
1065  "or was not readable."));
1066  return;
1067  } else if (!i.isDir()) {
1068  return;
1069  }
1070  }
1071 
1072  if (clearforward) {
1073  // autodelete should remove this one
1074  d->backStack.push(new KUrl(d->currUrl));
1075  qDeleteAll(d->forwardStack);
1076  d->forwardStack.clear();
1077  }
1078 
1079  d->lastURL = d->currUrl.url(KUrl::RemoveTrailingSlash);
1080  d->currUrl = newurl;
1081 
1082  pathChanged();
1083  emit urlEntered(newurl);
1084 
1085  // enable/disable actions
1086  QAction* forwardAction = d->actionCollection->action("forward");
1087  forwardAction->setEnabled(!d->forwardStack.isEmpty());
1088 
1089  QAction* backAction = d->actionCollection->action("back");
1090  backAction->setEnabled(!d->backStack.isEmpty());
1091 
1092  QAction* upAction = d->actionCollection->action("up");
1093  upAction->setEnabled(!isRoot());
1094 
1095  d->openUrl(newurl);
1096 }
1097 
1098 void KDirOperator::updateDir()
1099 {
1100  QApplication::setOverrideCursor(Qt::WaitCursor);
1101  d->dirLister->emitChanges();
1102  QApplication::restoreOverrideCursor();
1103 }
1104 
1105 void KDirOperator::rereadDir()
1106 {
1107  pathChanged();
1108  d->openUrl(d->currUrl, KDirLister::Reload);
1109 }
1110 
1111 
1112 bool KDirOperator::Private::openUrl(const KUrl& url, KDirLister::OpenUrlFlags flags)
1113 {
1114  const bool result = KProtocolManager::supportsListing(url) && dirLister->openUrl(url, flags);
1115  if (!result) // in that case, neither completed() nor canceled() will be emitted by KDL
1116  _k_slotCanceled();
1117 
1118  return result;
1119 }
1120 
1121 int KDirOperator::Private::sortColumn() const
1122 {
1123  int column = KDirModel::Name;
1124  if (KFile::isSortByDate(sorting)) {
1125  column = KDirModel::ModifiedTime;
1126  } else if (KFile::isSortBySize(sorting)) {
1127  column = KDirModel::Size;
1128  } else if (KFile::isSortByType(sorting)) {
1129  column = KDirModel::Type;
1130  } else {
1131  Q_ASSERT(KFile::isSortByName(sorting));
1132  }
1133 
1134  return column;
1135 }
1136 
1137 Qt::SortOrder KDirOperator::Private::sortOrder() const
1138 {
1139  return (sorting & QDir::Reversed) ? Qt::DescendingOrder :
1140  Qt::AscendingOrder;
1141 }
1142 
1143 void KDirOperator::Private::updateSorting(QDir::SortFlags sort)
1144 {
1145  kDebug(kfile_area) << "changing sort flags from" << sorting << "to" << sort;
1146  if (sort == sorting) {
1147  return;
1148  }
1149 
1150  if ((sorting ^ sort) & QDir::DirsFirst) {
1151  // The "Folders First" setting has been changed.
1152  // We need to make sure that the files and folders are really re-sorted.
1153  // Without the following intermediate "fake resorting",
1154  // QSortFilterProxyModel::sort(int column, Qt::SortOrder order)
1155  // would do nothing because neither the column nor the sort order have been changed.
1156  Qt::SortOrder tmpSortOrder = (sortOrder() == Qt::AscendingOrder ? Qt::DescendingOrder : Qt::AscendingOrder);
1157  proxyModel->sort(sortOrder(), tmpSortOrder);
1158  proxyModel->setSortFoldersFirst(sort & QDir::DirsFirst);
1159  }
1160 
1161  sorting = sort;
1162  parent->updateSortActions();
1163  proxyModel->sort(sortColumn(), sortOrder());
1164 
1165  // TODO: The headers from QTreeView don't take care about a sorting
1166  // change of the proxy model hence they must be updated the manually.
1167  // This is done here by a qobject_cast, but it would be nicer to:
1168  // - provide a signal 'sortingChanged()'
1169  // - connect KDirOperatorDetailView() with this signal and update the
1170  // header internally
1171  QTreeView* treeView = qobject_cast<QTreeView*>(itemView);
1172  if (treeView != 0) {
1173  QHeaderView* headerView = treeView->header();
1174  headerView->blockSignals(true);
1175  headerView->setSortIndicator(sortColumn(), sortOrder());
1176  headerView->blockSignals(false);
1177  }
1178 
1179  _k_assureVisibleSelection();
1180 }
1181 
1182 // Protected
1183 void KDirOperator::pathChanged()
1184 {
1185  if (d->itemView == 0)
1186  return;
1187 
1188  d->pendingMimeTypes.clear();
1189  //d->fileView->clear(); TODO
1190  d->completion.clear();
1191  d->dirCompletion.clear();
1192 
1193  // it may be, that we weren't ready at this time
1194  QApplication::restoreOverrideCursor();
1195 
1196  // when KIO::Job emits finished, the slot will restore the cursor
1197  QApplication::setOverrideCursor(Qt::WaitCursor);
1198 
1199  if (!Private::isReadable(d->currUrl)) {
1200  KMessageBox::error(d->itemView,
1201  i18n("The specified folder does not exist "
1202  "or was not readable."));
1203  if (d->backStack.isEmpty())
1204  home();
1205  else
1206  back();
1207  }
1208 }
1209 
1210 void KDirOperator::Private::_k_slotRedirected(const KUrl& newURL)
1211 {
1212  currUrl = newURL;
1213  pendingMimeTypes.clear();
1214  completion.clear();
1215  dirCompletion.clear();
1216  completeListDirty = true;
1217  emit parent->urlEntered(newURL);
1218 }
1219 
1220 // Code pinched from kfm then hacked
1221 void KDirOperator::back()
1222 {
1223  if (d->backStack.isEmpty())
1224  return;
1225 
1226  d->forwardStack.push(new KUrl(d->currUrl));
1227 
1228  KUrl *s = d->backStack.pop();
1229 
1230  setUrl(*s, false);
1231  delete s;
1232 }
1233 
1234 // Code pinched from kfm then hacked
1235 void KDirOperator::forward()
1236 {
1237  if (d->forwardStack.isEmpty())
1238  return;
1239 
1240  d->backStack.push(new KUrl(d->currUrl));
1241 
1242  KUrl *s = d->forwardStack.pop();
1243  setUrl(*s, false);
1244  delete s;
1245 }
1246 
1247 KUrl KDirOperator::url() const
1248 {
1249  return d->currUrl;
1250 }
1251 
1252 void KDirOperator::cdUp()
1253 {
1254  KUrl tmp(d->currUrl);
1255  tmp.cd(QLatin1String(".."));
1256  setUrl(tmp, true);
1257 }
1258 
1259 void KDirOperator::home()
1260 {
1261  KUrl u;
1262  u.setPath(QDir::homePath());
1263  setUrl(u, true);
1264 }
1265 
1266 void KDirOperator::clearFilter()
1267 {
1268  d->dirLister->setNameFilter(QString());
1269  d->dirLister->clearMimeFilter();
1270  checkPreviewSupport();
1271 }
1272 
1273 void KDirOperator::setNameFilter(const QString& filter)
1274 {
1275  d->dirLister->setNameFilter(filter);
1276  checkPreviewSupport();
1277 }
1278 
1279 QString KDirOperator::nameFilter() const
1280 {
1281  return d->dirLister->nameFilter();
1282 }
1283 
1284 void KDirOperator::setMimeFilter(const QStringList& mimetypes)
1285 {
1286  d->dirLister->setMimeFilter(mimetypes);
1287  checkPreviewSupport();
1288 }
1289 
1290 QStringList KDirOperator::mimeFilter() const
1291 {
1292  return d->dirLister->mimeFilters();
1293 }
1294 
1295 void KDirOperator::setNewFileMenuSupportedMimeTypes(const QStringList& mimeTypes)
1296 {
1297  d->newFileMenu->setSupportedMimeTypes(mimeTypes);
1298 }
1299 
1300 QStringList KDirOperator::newFileMenuSupportedMimeTypes() const
1301 {
1302  return d->newFileMenu->supportedMimeTypes();
1303 }
1304 
1305 bool KDirOperator::checkPreviewSupport()
1306 {
1307  KToggleAction *previewAction = static_cast<KToggleAction*>(d->actionCollection->action("preview"));
1308 
1309  bool hasPreviewSupport = false;
1310  KConfigGroup cg(KGlobal::config(), ConfigGroup);
1311  if (cg.readEntry("Show Default Preview", true))
1312  hasPreviewSupport = d->checkPreviewInternal();
1313 
1314  previewAction->setEnabled(hasPreviewSupport);
1315  return hasPreviewSupport;
1316 }
1317 
1318 void KDirOperator::activatedMenu(const KFileItem &item, const QPoint &pos)
1319 {
1320  Q_UNUSED(item);
1321  updateSelectionDependentActions();
1322 
1323  d->newFileMenu->setPopupFiles(url());
1324  d->newFileMenu->setViewShowsHiddenFiles(showHiddenFiles());
1325  d->newFileMenu->checkUpToDate();
1326 
1327  emit contextMenuAboutToShow( item, d->actionMenu->menu() );
1328 
1329  d->actionMenu->menu()->exec(pos);
1330 }
1331 
1332 void KDirOperator::changeEvent(QEvent *event)
1333 {
1334  QWidget::changeEvent(event);
1335 }
1336 
1337 bool KDirOperator::eventFilter(QObject *watched, QEvent *event)
1338 {
1339  Q_UNUSED(watched);
1340 
1341  // If we are not hovering any items, check if there is a current index
1342  // set. In that case, we show the preview of that item.
1343  switch(event->type()) {
1344  case QEvent::MouseMove: {
1345  if (d->preview && !d->preview->isHidden()) {
1346  const QModelIndex hoveredIndex = d->itemView->indexAt(d->itemView->viewport()->mapFromGlobal(QCursor::pos()));
1347 
1348  if (d->lastHoveredIndex == hoveredIndex)
1349  return QWidget::eventFilter(watched, event);
1350 
1351  d->lastHoveredIndex = hoveredIndex;
1352 
1353  const QModelIndex focusedIndex = d->itemView->selectionModel() ? d->itemView->selectionModel()->currentIndex()
1354  : QModelIndex();
1355 
1356  if (!hoveredIndex.isValid() && focusedIndex.isValid() &&
1357  d->itemView->selectionModel()->isSelected(focusedIndex) &&
1358  (d->lastHoveredIndex != focusedIndex)) {
1359  const QModelIndex sourceFocusedIndex = d->proxyModel->mapToSource(focusedIndex);
1360  const KFileItem item = d->dirModel->itemForIndex(sourceFocusedIndex);
1361  if (!item.isNull()) {
1362  d->preview->showPreview(item.url());
1363  }
1364  }
1365  }
1366  }
1367  break;
1368  case QEvent::MouseButtonRelease: {
1369  if (d->preview != 0 && !d->preview->isHidden()) {
1370  const QModelIndex hoveredIndex = d->itemView->indexAt(d->itemView->viewport()->mapFromGlobal(QCursor::pos()));
1371  const QModelIndex focusedIndex = d->itemView->selectionModel() ? d->itemView->selectionModel()->currentIndex()
1372  : QModelIndex();
1373 
1374  if (((!focusedIndex.isValid()) ||
1375  !d->itemView->selectionModel()->isSelected(focusedIndex)) &&
1376  (!hoveredIndex.isValid())) {
1377  d->preview->clearPreview();
1378  }
1379  }
1380  }
1381  break;
1382  case QEvent::Wheel: {
1383  QWheelEvent *evt = static_cast<QWheelEvent*>(event);
1384  if (evt->modifiers() & Qt::ControlModifier) {
1385  if (evt->delta() > 0) {
1386  setIconsZoom(d->iconsZoom + 10);
1387  } else {
1388  setIconsZoom(d->iconsZoom - 10);
1389  }
1390  return true;
1391  }
1392  }
1393  break;
1394  default:
1395  break;
1396  }
1397 
1398  return QWidget::eventFilter(watched, event);
1399 }
1400 
1401 bool KDirOperator::Private::checkPreviewInternal() const
1402 {
1403  const QStringList supported = KIO::PreviewJob::supportedMimeTypes();
1404  // no preview support for directories?
1405  if (parent->dirOnlyMode() && supported.indexOf("inode/directory") == -1)
1406  return false;
1407 
1408  QStringList mimeTypes = dirLister->mimeFilters();
1409  const QStringList nameFilter = dirLister->nameFilter().split(' ', QString::SkipEmptyParts);
1410 
1411  if (mimeTypes.isEmpty() && nameFilter.isEmpty() && !supported.isEmpty())
1412  return true;
1413  else {
1414  QRegExp r;
1415  r.setPatternSyntax(QRegExp::Wildcard); // the "mimetype" can be "image/*"
1416 
1417  if (!mimeTypes.isEmpty()) {
1418  QStringList::ConstIterator it = supported.begin();
1419 
1420  for (; it != supported.end(); ++it) {
1421  r.setPattern(*it);
1422 
1423  QStringList result = mimeTypes.filter(r);
1424  if (!result.isEmpty()) { // matches! -> we want previews
1425  return true;
1426  }
1427  }
1428  }
1429 
1430  if (!nameFilter.isEmpty()) {
1431  // find the mimetypes of all the filter-patterns
1432  QStringList::const_iterator it1 = nameFilter.begin();
1433  for (; it1 != nameFilter.end(); ++it1) {
1434  if ((*it1) == "*") {
1435  return true;
1436  }
1437 
1438  KMimeType::Ptr mt = KMimeType::findByPath(*it1, 0, true /*fast mode, no file contents exist*/);
1439  if (!mt)
1440  continue;
1441  QString mime = mt->name();
1442 
1443  // the "mimetypes" we get from the PreviewJob can be "image/*"
1444  // so we need to check in wildcard mode
1445  QStringList::ConstIterator it2 = supported.begin();
1446  for (; it2 != supported.end(); ++it2) {
1447  r.setPattern(*it2);
1448  if (r.indexIn(mime) != -1) {
1449  return true;
1450  }
1451  }
1452  }
1453  }
1454  }
1455 
1456  return false;
1457 }
1458 
1459 QAbstractItemView* KDirOperator::createView(QWidget* parent, KFile::FileView viewKind)
1460 {
1461  QAbstractItemView *itemView = 0;
1462  if (KFile::isDetailView(viewKind) || KFile::isTreeView(viewKind) || KFile::isDetailTreeView(viewKind)) {
1463  KDirOperatorDetailView *detailView = new KDirOperatorDetailView(parent);
1464  detailView->setViewMode(viewKind);
1465  itemView = detailView;
1466  } else {
1467  itemView = new KDirOperatorIconView(this, parent);
1468  }
1469 
1470  return itemView;
1471 }
1472 
1473 void KDirOperator::setAcceptDrops(bool b)
1474 {
1475  // TODO:
1476  //if (d->fileView)
1477  // d->fileView->widget()->setAcceptDrops(b);
1478  QWidget::setAcceptDrops(b);
1479 }
1480 
1481 void KDirOperator::setDropOptions(int options)
1482 {
1483  d->dropOptions = options;
1484  // TODO:
1485  //if (d->fileView)
1486  // d->fileView->setDropOptions(options);
1487 }
1488 
1489 void KDirOperator::setView(KFile::FileView viewKind)
1490 {
1491  bool preview = (KFile::isPreviewInfo(viewKind) || KFile::isPreviewContents(viewKind));
1492 
1493  if (viewKind == KFile::Default) {
1494  if (KFile::isDetailView((KFile::FileView)d->defaultView)) {
1495  viewKind = KFile::Detail;
1496  } else if (KFile::isTreeView((KFile::FileView)d->defaultView)) {
1497  viewKind = KFile::Tree;
1498  } else if (KFile::isDetailTreeView((KFile::FileView)d->defaultView)) {
1499  viewKind = KFile::DetailTree;
1500  } else {
1501  viewKind = KFile::Simple;
1502  }
1503 
1504  const KFile::FileView defaultViewKind = static_cast<KFile::FileView>(d->defaultView);
1505  preview = (KFile::isPreviewInfo(defaultViewKind) || KFile::isPreviewContents(defaultViewKind))
1506  && d->actionCollection->action("preview")->isEnabled();
1507  }
1508 
1509  d->viewKind = static_cast<int>(viewKind);
1510  viewKind = static_cast<KFile::FileView>(d->viewKind);
1511 
1512  QAbstractItemView *newView = createView(this, viewKind);
1513  setView(newView);
1514 
1515  d->_k_togglePreview(preview);
1516 }
1517 
1518 QAbstractItemView * KDirOperator::view() const
1519 {
1520  return d->itemView;
1521 }
1522 
1523 KFile::Modes KDirOperator::mode() const
1524 {
1525  return d->mode;
1526 }
1527 
1528 void KDirOperator::setMode(KFile::Modes mode)
1529 {
1530  if (d->mode == mode)
1531  return;
1532 
1533  d->mode = mode;
1534 
1535  d->dirLister->setDirOnlyMode(dirOnlyMode());
1536 
1537  // reset the view with the different mode
1538  if (d->itemView != 0)
1539  setView(static_cast<KFile::FileView>(d->viewKind));
1540 }
1541 
1542 void KDirOperator::setView(QAbstractItemView *view)
1543 {
1544  if (view == d->itemView) {
1545  return;
1546  }
1547 
1548  // TODO: do a real timer and restart it after that
1549  d->pendingMimeTypes.clear();
1550  const bool listDir = (d->itemView == 0);
1551 
1552  if (d->mode & KFile::Files) {
1553  view->setSelectionMode(QAbstractItemView::ExtendedSelection);
1554  } else {
1555  view->setSelectionMode(QAbstractItemView::SingleSelection);
1556  }
1557 
1558  QItemSelectionModel *selectionModel = 0;
1559  if ((d->itemView != 0) && d->itemView->selectionModel()->hasSelection()) {
1560  // remember the selection of the current item view and apply this selection
1561  // to the new view later
1562  const QItemSelection selection = d->itemView->selectionModel()->selection();
1563  selectionModel = new QItemSelectionModel(d->proxyModel, this);
1564  selectionModel->select(selection, QItemSelectionModel::Select);
1565  }
1566 
1567  setFocusProxy(0);
1568  delete d->itemView;
1569  d->itemView = view;
1570  d->itemView->setModel(d->proxyModel);
1571  setFocusProxy(d->itemView);
1572 
1573  view->viewport()->installEventFilter(this);
1574 
1575  KFileItemDelegate *delegate = new KFileItemDelegate(d->itemView);
1576  d->itemView->setItemDelegate(delegate);
1577  d->itemView->viewport()->setAttribute(Qt::WA_Hover);
1578  d->itemView->setContextMenuPolicy(Qt::CustomContextMenu);
1579  d->itemView->setMouseTracking(true);
1580  //d->itemView->setDropOptions(d->dropOptions);
1581 
1582  // first push our settings to the view, then listen for changes from the view
1583  QTreeView* treeView = qobject_cast<QTreeView*>(d->itemView);
1584  if (treeView) {
1585  QHeaderView* headerView = treeView->header();
1586  headerView->setSortIndicator(d->sortColumn(), d->sortOrder());
1587  connect(headerView, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
1588  this, SLOT(_k_synchronizeSortingState(int,Qt::SortOrder)));
1589  }
1590 
1591  connect(d->itemView, SIGNAL(activated(QModelIndex)),
1592  this, SLOT(_k_slotActivated(QModelIndex)));
1593  connect(d->itemView, SIGNAL(customContextMenuRequested(QPoint)),
1594  this, SLOT(_k_openContextMenu(QPoint)));
1595  connect(d->itemView, SIGNAL(entered(QModelIndex)),
1596  this, SLOT(_k_triggerPreview(QModelIndex)));
1597 
1598  updateViewActions();
1599  d->splitter->insertWidget(0, d->itemView);
1600 
1601  d->splitter->resize(size());
1602  d->itemView->show();
1603 
1604  if (listDir) {
1605  QApplication::setOverrideCursor(Qt::WaitCursor);
1606  d->openUrl(d->currUrl);
1607  }
1608 
1609  if (selectionModel != 0) {
1610  d->itemView->setSelectionModel(selectionModel);
1611  QMetaObject::invokeMethod(this, "_k_assureVisibleSelection", Qt::QueuedConnection);
1612  }
1613 
1614  connect(d->itemView->selectionModel(),
1615  SIGNAL(currentChanged(QModelIndex,QModelIndex)),
1616  this, SLOT(_k_triggerPreview(QModelIndex)));
1617  connect(d->itemView->selectionModel(),
1618  SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1619  this, SLOT(_k_slotSelectionChanged()));
1620 
1621  // if we cannot cast it to a QListView, disable the "Icon Position" menu. Note that this check
1622  // needs to be done here, and not in createView, since we can be set an external view
1623  d->decorationMenu->setEnabled(qobject_cast<QListView*>(d->itemView));
1624 
1625  d->shouldFetchForItems = qobject_cast<QTreeView*>(view);
1626  if (d->shouldFetchForItems) {
1627  connect(d->dirModel, SIGNAL(expand(QModelIndex)), this, SLOT(_k_slotExpandToUrl(QModelIndex)));
1628  } else {
1629  d->itemsToBeSetAsCurrent.clear();
1630  }
1631 
1632  const bool previewForcedToTrue = d->inlinePreviewState == Private::ForcedToTrue;
1633  const bool previewShown = d->inlinePreviewState == Private::NotForced ? d->showPreviews : previewForcedToTrue;
1634  d->previewGenerator = new KFilePreviewGenerator(d->itemView);
1635  const int maxSize = KIconLoader::SizeEnormous - KIconLoader::SizeSmall;
1636  const int val = (maxSize * d->iconsZoom / 100) + KIconLoader::SizeSmall;
1637  d->itemView->setIconSize(previewForcedToTrue ? QSize(KIconLoader::SizeHuge, KIconLoader::SizeHuge) : QSize(val, val));
1638  d->previewGenerator->setPreviewShown(previewShown);
1639  d->actionCollection->action("inline preview")->setChecked(previewShown);
1640 
1641  // ensure we change everything needed
1642  d->_k_slotChangeDecorationPosition();
1643 
1644  emit viewChanged(view);
1645 
1646  const int zoom = previewForcedToTrue ? (KIconLoader::SizeHuge - KIconLoader::SizeSmall + 1) * 100 / maxSize : d->iconSizeForViewType(view);
1647 
1648  // this will make d->iconsZoom be updated, since setIconsZoom slot will be called
1649  emit currentIconSizeChanged(zoom);
1650 }
1651 
1652 void KDirOperator::setDirLister(KDirLister *lister)
1653 {
1654  if (lister == d->dirLister) // sanity check
1655  return;
1656 
1657  delete d->dirModel;
1658  d->dirModel = 0;
1659 
1660  delete d->proxyModel;
1661  d->proxyModel = 0;
1662 
1663  //delete d->dirLister; // deleted by KDirModel already, which took ownership
1664  d->dirLister = lister;
1665 
1666  d->dirModel = new KDirModel();
1667  d->dirModel->setDirLister(d->dirLister);
1668  d->dirModel->setDropsAllowed(KDirModel::DropOnDirectory);
1669 
1670  d->shouldFetchForItems = qobject_cast<QTreeView*>(d->itemView);
1671  if (d->shouldFetchForItems) {
1672  connect(d->dirModel, SIGNAL(expand(QModelIndex)), this, SLOT(_k_slotExpandToUrl(QModelIndex)));
1673  } else {
1674  d->itemsToBeSetAsCurrent.clear();
1675  }
1676 
1677  d->proxyModel = new KDirSortFilterProxyModel(this);
1678  d->proxyModel->setSourceModel(d->dirModel);
1679 
1680  d->dirLister->setAutoUpdate(true);
1681  d->dirLister->setDelayedMimeTypes(true);
1682 
1683  QWidget* mainWidget = topLevelWidget();
1684  d->dirLister->setMainWindow(mainWidget);
1685  kDebug(kfile_area) << "mainWidget=" << mainWidget;
1686 
1687  connect(d->dirLister, SIGNAL(percent(int)),
1688  SLOT(_k_slotProgress(int)));
1689  connect(d->dirLister, SIGNAL(started(KUrl)), SLOT(_k_slotStarted()));
1690  connect(d->dirLister, SIGNAL(completed()), SLOT(_k_slotIOFinished()));
1691  connect(d->dirLister, SIGNAL(canceled()), SLOT(_k_slotCanceled()));
1692  connect(d->dirLister, SIGNAL(redirection(KUrl)),
1693  SLOT(_k_slotRedirected(KUrl)));
1694  connect(d->dirLister, SIGNAL(newItems(KFileItemList)), SLOT(_k_slotItemsChanged()));
1695  connect(d->dirLister, SIGNAL(itemsDeleted(KFileItemList)), SLOT(_k_slotItemsChanged()));
1696  connect(d->dirLister, SIGNAL(itemsFilteredByMime(KFileItemList)), SLOT(_k_slotItemsChanged()));
1697  connect(d->dirLister, SIGNAL(clear()), SLOT(_k_slotItemsChanged()));
1698 }
1699 
1700 void KDirOperator::selectDir(const KFileItem &item)
1701 {
1702  setUrl(item.targetUrl(), true);
1703 }
1704 
1705 void KDirOperator::selectFile(const KFileItem &item)
1706 {
1707  QApplication::restoreOverrideCursor();
1708 
1709  emit fileSelected(item);
1710 }
1711 
1712 void KDirOperator::highlightFile(const KFileItem &item)
1713 {
1714  if ((d->preview != 0 && !d->preview->isHidden()) && !item.isNull()) {
1715  d->preview->showPreview(item.url());
1716  }
1717 
1718  emit fileHighlighted(item);
1719 }
1720 
1721 void KDirOperator::setCurrentItem(const QString& url)
1722 {
1723  kDebug(kfile_area);
1724 
1725  KFileItem item = d->dirLister->findByUrl(url);
1726  if (d->shouldFetchForItems && item.isNull()) {
1727  d->itemsToBeSetAsCurrent << url;
1728  d->dirModel->expandToUrl(url);
1729  return;
1730  }
1731 
1732  setCurrentItem(item);
1733 }
1734 
1735 void KDirOperator::setCurrentItem(const KFileItem& item)
1736 {
1737  kDebug(kfile_area);
1738 
1739  if (!d->itemView) {
1740  return;
1741  }
1742 
1743  QItemSelectionModel *selModel = d->itemView->selectionModel();
1744  if (selModel) {
1745  selModel->clear();
1746  if (!item.isNull()) {
1747  const QModelIndex dirIndex = d->dirModel->indexForItem(item);
1748  const QModelIndex proxyIndex = d->proxyModel->mapFromSource(dirIndex);
1749  selModel->setCurrentIndex(proxyIndex, QItemSelectionModel::Select);
1750  }
1751  }
1752 }
1753 
1754 void KDirOperator::setCurrentItems(const QStringList& urls)
1755 {
1756  kDebug(kfile_area);
1757 
1758  if (!d->itemView) {
1759  return;
1760  }
1761 
1762  KFileItemList itemList;
1763  foreach (const QString &url, urls) {
1764  KFileItem item = d->dirLister->findByUrl(url);
1765  if (d->shouldFetchForItems && item.isNull()) {
1766  d->itemsToBeSetAsCurrent << url;
1767  d->dirModel->expandToUrl(url);
1768  continue;
1769  }
1770  itemList << item;
1771  }
1772 
1773  setCurrentItems(itemList);
1774 }
1775 
1776 void KDirOperator::setCurrentItems(const KFileItemList& items)
1777 {
1778  kDebug(kfile_area);
1779 
1780  if (d->itemView == 0) {
1781  return;
1782  }
1783 
1784  QItemSelectionModel *selModel = d->itemView->selectionModel();
1785  if (selModel) {
1786  selModel->clear();
1787  QModelIndex proxyIndex;
1788  foreach (const KFileItem &item, items) {
1789  if (!item.isNull()) {
1790  const QModelIndex dirIndex = d->dirModel->indexForItem(item);
1791  proxyIndex = d->proxyModel->mapFromSource(dirIndex);
1792  selModel->select(proxyIndex, QItemSelectionModel::Select);
1793  }
1794  }
1795  if (proxyIndex.isValid()) {
1796  selModel->setCurrentIndex(proxyIndex, QItemSelectionModel::NoUpdate);
1797  }
1798  }
1799 }
1800 
1801 QString KDirOperator::makeCompletion(const QString& string)
1802 {
1803  if (string.isEmpty()) {
1804  d->itemView->selectionModel()->clear();
1805  return QString();
1806  }
1807 
1808  prepareCompletionObjects();
1809  return d->completion.makeCompletion(string);
1810 }
1811 
1812 QString KDirOperator::makeDirCompletion(const QString& string)
1813 {
1814  if (string.isEmpty()) {
1815  d->itemView->selectionModel()->clear();
1816  return QString();
1817  }
1818 
1819  prepareCompletionObjects();
1820  return d->dirCompletion.makeCompletion(string);
1821 }
1822 
1823 void KDirOperator::prepareCompletionObjects()
1824 {
1825  if (d->itemView == 0) {
1826  return;
1827  }
1828 
1829  if (d->completeListDirty) { // create the list of all possible completions
1830  const KFileItemList itemList = d->dirLister->items();
1831  foreach (const KFileItem &item, itemList) {
1832  d->completion.addItem(item.name());
1833  if (item.isDir()) {
1834  d->dirCompletion.addItem(item.name());
1835  }
1836  }
1837  d->completeListDirty = false;
1838  }
1839 }
1840 
1841 void KDirOperator::slotCompletionMatch(const QString& match)
1842 {
1843  setCurrentItem(match);
1844  emit completion(match);
1845 }
1846 
1847 void KDirOperator::setupActions()
1848 {
1849  d->actionCollection = new KActionCollection(this);
1850  d->actionCollection->setObjectName("KDirOperator::actionCollection");
1851 
1852  d->actionMenu = new KActionMenu(i18n("Menu"), this);
1853  d->actionCollection->addAction("popupMenu", d->actionMenu);
1854 
1855  QAction* upAction = d->actionCollection->addAction(KStandardAction::Up, "up", this, SLOT(cdUp()));
1856  upAction->setText(i18n("Parent Folder"));
1857 
1858  d->actionCollection->addAction(KStandardAction::Back, "back", this, SLOT(back()));
1859 
1860  d->actionCollection->addAction(KStandardAction::Forward, "forward", this, SLOT(forward()));
1861 
1862  QAction* homeAction = d->actionCollection->addAction(KStandardAction::Home, "home", this, SLOT(home()));
1863  homeAction->setText(i18n("Home Folder"));
1864 
1865  KAction* reloadAction = d->actionCollection->addAction(KStandardAction::Redisplay, "reload", this, SLOT(rereadDir()));
1866  reloadAction->setText(i18n("Reload"));
1867  reloadAction->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Reload));
1868 
1869  KAction* mkdirAction = new KAction(i18n("New Folder..."), this);
1870  d->actionCollection->addAction("mkdir", mkdirAction);
1871  mkdirAction->setIcon(KIcon(QLatin1String("folder-new")));
1872  connect(mkdirAction, SIGNAL(triggered(bool)), this, SLOT(mkdir()));
1873 
1874  KAction* trash = new KAction(i18n("Move to Trash"), this);
1875  d->actionCollection->addAction("trash", trash);
1876  trash->setIcon(KIcon("user-trash"));
1877  trash->setShortcuts(KShortcut(Qt::Key_Delete));
1878  connect(trash, SIGNAL(triggered(bool)), SLOT(trashSelected()));
1879 
1880  KAction* action = new KAction(i18n("Delete"), this);
1881  d->actionCollection->addAction("delete", action);
1882  action->setIcon(KIcon("edit-delete"));
1883  action->setShortcuts(KShortcut(Qt::SHIFT + Qt::Key_Delete));
1884  connect(action, SIGNAL(triggered(bool)), this, SLOT(deleteSelected()));
1885 
1886  // the sort menu actions
1887  KActionMenu *sortMenu = new KActionMenu(i18n("Sorting"), this);
1888  d->actionCollection->addAction("sorting menu", sortMenu);
1889 
1890  KToggleAction *byNameAction = new KToggleAction(i18n("By Name"), this);
1891  d->actionCollection->addAction("by name", byNameAction);
1892  connect(byNameAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortByName()));
1893 
1894  KToggleAction *bySizeAction = new KToggleAction(i18n("By Size"), this);
1895  d->actionCollection->addAction("by size", bySizeAction);
1896  connect(bySizeAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortBySize()));
1897 
1898  KToggleAction *byDateAction = new KToggleAction(i18n("By Date"), this);
1899  d->actionCollection->addAction("by date", byDateAction);
1900  connect(byDateAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortByDate()));
1901 
1902  KToggleAction *byTypeAction = new KToggleAction(i18n("By Type"), this);
1903  d->actionCollection->addAction("by type", byTypeAction);
1904  connect(byTypeAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortByType()));
1905 
1906  KToggleAction *descendingAction = new KToggleAction(i18n("Descending"), this);
1907  d->actionCollection->addAction("descending", descendingAction);
1908  connect(descendingAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSortReversed(bool)));
1909 
1910  KToggleAction *dirsFirstAction = new KToggleAction(i18n("Folders First"), this);
1911  d->actionCollection->addAction("dirs first", dirsFirstAction);
1912  connect(dirsFirstAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotToggleDirsFirst()));
1913 
1914  QActionGroup* sortGroup = new QActionGroup(this);
1915  byNameAction->setActionGroup(sortGroup);
1916  bySizeAction->setActionGroup(sortGroup);
1917  byDateAction->setActionGroup(sortGroup);
1918  byTypeAction->setActionGroup(sortGroup);
1919 
1920  d->decorationMenu = new KActionMenu(i18n("Icon Position"), this);
1921  d->actionCollection->addAction("decoration menu", d->decorationMenu);
1922 
1923  d->leftAction = new KToggleAction(i18n("Next to File Name"), this);
1924  d->actionCollection->addAction("decorationAtLeft", d->leftAction);
1925  connect(d->leftAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotChangeDecorationPosition()));
1926 
1927  KToggleAction *topAction = new KToggleAction(i18n("Above File Name"), this);
1928  d->actionCollection->addAction("decorationAtTop", topAction);
1929  connect(topAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotChangeDecorationPosition()));
1930 
1931  d->decorationMenu->addAction(d->leftAction);
1932  d->decorationMenu->addAction(topAction);
1933 
1934  QActionGroup* decorationGroup = new QActionGroup(this);
1935  d->leftAction->setActionGroup(decorationGroup);
1936  topAction->setActionGroup(decorationGroup);
1937 
1938  KToggleAction *shortAction = new KToggleAction(i18n("Short View"), this);
1939  d->actionCollection->addAction("short view", shortAction);
1940  shortAction->setIcon(KIcon(QLatin1String("view-list-icons")));
1941  connect(shortAction, SIGNAL(triggered()), SLOT(_k_slotSimpleView()));
1942 
1943  KToggleAction *detailedAction = new KToggleAction(i18n("Detailed View"), this);
1944  d->actionCollection->addAction("detailed view", detailedAction);
1945  detailedAction->setIcon(KIcon(QLatin1String("view-list-details")));
1946  connect(detailedAction, SIGNAL(triggered()), SLOT(_k_slotDetailedView()));
1947 
1948  KToggleAction *treeAction = new KToggleAction(i18n("Tree View"), this);
1949  d->actionCollection->addAction("tree view", treeAction);
1950  treeAction->setIcon(KIcon(QLatin1String("view-list-tree")));
1951  connect(treeAction, SIGNAL(triggered()), SLOT(_k_slotTreeView()));
1952 
1953  KToggleAction *detailedTreeAction = new KToggleAction(i18n("Detailed Tree View"), this);
1954  d->actionCollection->addAction("detailed tree view", detailedTreeAction);
1955  detailedTreeAction->setIcon(KIcon(QLatin1String("view-list-tree")));
1956  connect(detailedTreeAction, SIGNAL(triggered()), SLOT(_k_slotDetailedTreeView()));
1957 
1958  QActionGroup* viewGroup = new QActionGroup(this);
1959  shortAction->setActionGroup(viewGroup);
1960  detailedAction->setActionGroup(viewGroup);
1961  treeAction->setActionGroup(viewGroup);
1962  detailedTreeAction->setActionGroup(viewGroup);
1963 
1964  KToggleAction *showHiddenAction = new KToggleAction(i18n("Show Hidden Files"), this);
1965  d->actionCollection->addAction("show hidden", showHiddenAction);
1966  connect(showHiddenAction, SIGNAL(toggled(bool)), SLOT(_k_slotToggleHidden(bool)));
1967 
1968  KToggleAction *previewAction = new KToggleAction(i18n("Show Aside Preview"), this);
1969  d->actionCollection->addAction("preview", previewAction);
1970  connect(previewAction, SIGNAL(toggled(bool)),
1971  SLOT(_k_togglePreview(bool)));
1972 
1973  KToggleAction *inlinePreview = new KToggleAction(KIcon("view-preview"),
1974  i18n("Show Preview"), this);
1975  d->actionCollection->addAction("inline preview", inlinePreview);
1976  connect(inlinePreview, SIGNAL(toggled(bool)), SLOT(_k_toggleInlinePreviews(bool)));
1977 
1978  KAction *fileManager = new KAction(i18n("Open File Manager"), this);
1979  d->actionCollection->addAction("file manager", fileManager);
1980  fileManager->setIcon(KIcon(QLatin1String("system-file-manager")));
1981  connect(fileManager, SIGNAL(triggered()), SLOT(_k_slotOpenFileManager()));
1982 
1983  action = new KAction(i18n("Properties"), this);
1984  d->actionCollection->addAction("properties", action);
1985  action->setIcon(KIcon("document-properties"));
1986  action->setShortcut(KShortcut(Qt::ALT + Qt::Key_Return));
1987  connect(action, SIGNAL(triggered(bool)), this, SLOT(_k_slotProperties()));
1988 
1989  // the view menu actions
1990  KActionMenu* viewMenu = new KActionMenu(i18n("&View"), this);
1991  d->actionCollection->addAction("view menu", viewMenu);
1992  viewMenu->addAction(shortAction);
1993  viewMenu->addAction(detailedAction);
1994  // Comment following lines to hide the extra two modes
1995  viewMenu->addAction(treeAction);
1996  viewMenu->addAction(detailedTreeAction);
1997  // TODO: QAbstractItemView does not offer an action collection. Provide
1998  // an interface to add a custom action collection.
1999 
2000  d->newFileMenu = new KNewFileMenu(d->actionCollection, "new", this);
2001  connect(d->newFileMenu, SIGNAL(directoryCreated(KUrl)), this, SLOT(_k_slotDirectoryCreated(KUrl)));
2002 
2003  d->actionCollection->addAssociatedWidget(this);
2004  foreach (QAction* action, d->actionCollection->actions())
2005  action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
2006 }
2007 
2008 void KDirOperator::setupMenu()
2009 {
2010  setupMenu(SortActions | ViewActions | FileActions);
2011 }
2012 
2013 void KDirOperator::setupMenu(int whichActions)
2014 {
2015  // first fill the submenus (sort and view)
2016  KActionMenu *sortMenu = static_cast<KActionMenu*>(d->actionCollection->action("sorting menu"));
2017  sortMenu->menu()->clear();
2018  sortMenu->addAction(d->actionCollection->action("by name"));
2019  sortMenu->addAction(d->actionCollection->action("by size"));
2020  sortMenu->addAction(d->actionCollection->action("by date"));
2021  sortMenu->addAction(d->actionCollection->action("by type"));
2022  sortMenu->addSeparator();
2023  sortMenu->addAction(d->actionCollection->action("descending"));
2024  sortMenu->addAction(d->actionCollection->action("dirs first"));
2025 
2026  // now plug everything into the popupmenu
2027  d->actionMenu->menu()->clear();
2028  if (whichActions & NavActions) {
2029  d->actionMenu->addAction(d->actionCollection->action("up"));
2030  d->actionMenu->addAction(d->actionCollection->action("back"));
2031  d->actionMenu->addAction(d->actionCollection->action("forward"));
2032  d->actionMenu->addAction(d->actionCollection->action("home"));
2033  d->actionMenu->addSeparator();
2034  }
2035 
2036  if (whichActions & FileActions) {
2037  d->actionMenu->addAction(d->actionCollection->action("new"));
2038  if (d->currUrl.isLocalFile() && !(QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
2039  d->actionMenu->addAction(d->actionCollection->action("trash"));
2040  }
2041  KConfigGroup cg(KGlobal::config(), QLatin1String("KDE"));
2042  const bool del = !d->currUrl.isLocalFile() ||
2043  (QApplication::keyboardModifiers() & Qt::ShiftModifier) ||
2044  cg.readEntry("ShowDeleteCommand", false);
2045  if (del) {
2046  d->actionMenu->addAction(d->actionCollection->action("delete"));
2047  }
2048  d->actionMenu->addSeparator();
2049  }
2050 
2051  if (whichActions & SortActions) {
2052  d->actionMenu->addAction(sortMenu);
2053  if (!(whichActions & ViewActions)) {
2054  d->actionMenu->addSeparator();
2055  }
2056  }
2057 
2058  if (whichActions & ViewActions) {
2059  d->actionMenu->addAction(d->actionCollection->action("view menu"));
2060  d->actionMenu->addSeparator();
2061  }
2062 
2063  if (whichActions & FileActions) {
2064  d->actionMenu->addAction(d->actionCollection->action("file manager"));
2065  d->actionMenu->addAction(d->actionCollection->action("properties"));
2066  }
2067 }
2068 
2069 void KDirOperator::updateSortActions()
2070 {
2071  if (KFile::isSortByName(d->sorting)) {
2072  d->actionCollection->action("by name")->setChecked(true);
2073  } else if (KFile::isSortByDate(d->sorting)) {
2074  d->actionCollection->action("by date")->setChecked(true);
2075  } else if (KFile::isSortBySize(d->sorting)) {
2076  d->actionCollection->action("by size")->setChecked(true);
2077  } else if (KFile::isSortByType(d->sorting)) {
2078  d->actionCollection->action("by type")->setChecked(true);
2079  }
2080  d->actionCollection->action("descending")->setChecked(d->sorting & QDir::Reversed);
2081  d->actionCollection->action("dirs first")->setChecked(d->sorting & QDir::DirsFirst);
2082 }
2083 
2084 void KDirOperator::updateViewActions()
2085 {
2086  KFile::FileView fv = static_cast<KFile::FileView>(d->viewKind);
2087 
2088  //QAction *separateDirs = d->actionCollection->action("separate dirs");
2089  //separateDirs->setChecked(KFile::isSeparateDirs(fv) &&
2090  // separateDirs->isEnabled());
2091 
2092  d->actionCollection->action("short view")->setChecked(KFile::isSimpleView(fv));
2093  d->actionCollection->action("detailed view")->setChecked(KFile::isDetailView(fv));
2094  d->actionCollection->action("tree view")->setChecked(KFile::isTreeView(fv));
2095  d->actionCollection->action("detailed tree view")->setChecked(KFile::isDetailTreeView(fv));
2096 }
2097 
2098 void KDirOperator::readConfig(const KConfigGroup& configGroup)
2099 {
2100  d->defaultView = 0;
2101  QString viewStyle = configGroup.readEntry("View Style", "Simple");
2102  if (viewStyle == QLatin1String("Detail")) {
2103  d->defaultView |= KFile::Detail;
2104  } else if (viewStyle == QLatin1String("Tree")) {
2105  d->defaultView |= KFile::Tree;
2106  } else if (viewStyle == QLatin1String("DetailTree")) {
2107  d->defaultView |= KFile::DetailTree;
2108  } else {
2109  d->defaultView |= KFile::Simple;
2110  }
2111  //if (configGroup.readEntry(QLatin1String("Separate Directories"),
2112  // DefaultMixDirsAndFiles)) {
2113  // d->defaultView |= KFile::SeparateDirs;
2114  //}
2115  if (configGroup.readEntry(QLatin1String("Show Preview"), false)) {
2116  d->defaultView |= KFile::PreviewContents;
2117  }
2118 
2119  d->previewWidth = configGroup.readEntry(QLatin1String("Preview Width"), 100);
2120 
2121  if (configGroup.readEntry(QLatin1String("Show hidden files"),
2122  DefaultShowHidden)) {
2123  d->actionCollection->action("show hidden")->setChecked(true);
2124  d->dirLister->setShowingDotFiles(true);
2125  }
2126 
2127  QDir::SortFlags sorting = QDir::Name;
2128  if (configGroup.readEntry(QLatin1String("Sort directories first"),
2129  DefaultDirsFirst)) {
2130  sorting |= QDir::DirsFirst;
2131  }
2132  QString name = QLatin1String("Name");
2133  QString sortBy = configGroup.readEntry(QLatin1String("Sort by"), name);
2134  if (sortBy == name) {
2135  sorting |= QDir::Name;
2136  } else if (sortBy == QLatin1String("Size")) {
2137  sorting |= QDir::Size;
2138  } else if (sortBy == QLatin1String("Date")) {
2139  sorting |= QDir::Time;
2140  } else if (sortBy == QLatin1String("Type")) {
2141  sorting |= QDir::Type;
2142  }
2143  if (configGroup.readEntry(QLatin1String("Sort reversed"), DefaultSortReversed)) {
2144  sorting |= QDir::Reversed;
2145  }
2146  d->updateSorting(sorting);
2147 
2148  if (d->inlinePreviewState == Private::NotForced) {
2149  d->showPreviews = configGroup.readEntry(QLatin1String("Previews"), false);
2150  }
2151  QStyleOptionViewItem::Position pos = (QStyleOptionViewItem::Position) configGroup.readEntry(QLatin1String("Decoration position"), (int) QStyleOptionViewItem::Left);
2152  setDecorationPosition(pos);
2153 }
2154 
2155 void KDirOperator::writeConfig(KConfigGroup& configGroup)
2156 {
2157  QString sortBy = QLatin1String("Name");
2158  if (KFile::isSortBySize(d->sorting)) {
2159  sortBy = QLatin1String("Size");
2160  } else if (KFile::isSortByDate(d->sorting)) {
2161  sortBy = QLatin1String("Date");
2162  } else if (KFile::isSortByType(d->sorting)) {
2163  sortBy = QLatin1String("Type");
2164  }
2165 
2166  configGroup.writeEntry(QLatin1String("Sort by"), sortBy);
2167 
2168  configGroup.writeEntry(QLatin1String("Sort reversed"),
2169  d->actionCollection->action("descending")->isChecked());
2170 
2171  configGroup.writeEntry(QLatin1String("Sort directories first"),
2172  d->actionCollection->action("dirs first")->isChecked());
2173 
2174  // don't save the preview when an application specific preview is in use.
2175  bool appSpecificPreview = false;
2176  if (d->preview) {
2177  KFileMetaPreview *tmp = dynamic_cast<KFileMetaPreview*>(d->preview);
2178  appSpecificPreview = (tmp == 0);
2179  }
2180 
2181  if (!appSpecificPreview) {
2182  KToggleAction *previewAction = static_cast<KToggleAction*>(d->actionCollection->action("preview"));
2183  if (previewAction->isEnabled()) {
2184  bool hasPreview = previewAction->isChecked();
2185  configGroup.writeEntry(QLatin1String("Show Preview"), hasPreview);
2186 
2187  if (hasPreview) {
2188  // remember the width of the preview widget
2189  QList<int> sizes = d->splitter->sizes();
2190  Q_ASSERT(sizes.count() == 2);
2191  configGroup.writeEntry(QLatin1String("Preview Width"), sizes[1]);
2192  }
2193  }
2194  }
2195 
2196  configGroup.writeEntry(QLatin1String("Show hidden files"),
2197  d->actionCollection->action("show hidden")->isChecked());
2198 
2199  KFile::FileView fv = static_cast<KFile::FileView>(d->viewKind);
2200  QString style;
2201  if (KFile::isDetailView(fv))
2202  style = QLatin1String("Detail");
2203  else if (KFile::isSimpleView(fv))
2204  style = QLatin1String("Simple");
2205  else if (KFile::isTreeView(fv))
2206  style = QLatin1String("Tree");
2207  else if (KFile::isDetailTreeView(fv))
2208  style = QLatin1String("DetailTree");
2209  configGroup.writeEntry(QLatin1String("View Style"), style);
2210 
2211  if (d->inlinePreviewState == Private::NotForced) {
2212  configGroup.writeEntry(QLatin1String("Previews"), d->showPreviews);
2213  }
2214 
2215  configGroup.writeEntry(QLatin1String("Decoration position"), (int) d->decorationPosition);
2216 }
2217 
2218 void KDirOperator::resizeEvent(QResizeEvent *)
2219 {
2220  // resize the splitter and assure that the width of
2221  // the preview widget is restored
2222  QList<int> sizes = d->splitter->sizes();
2223  const bool hasPreview = (sizes.count() == 2);
2224 
2225  d->splitter->resize(size());
2226  sizes = d->splitter->sizes();
2227 
2228  const bool restorePreviewWidth = hasPreview && (d->previewWidth != sizes[1]);
2229  if (restorePreviewWidth) {
2230  const int availableWidth = sizes[0] + sizes[1];
2231  sizes[0] = availableWidth - d->previewWidth;
2232  sizes[1] = d->previewWidth;
2233  d->splitter->setSizes(sizes);
2234  }
2235  if (hasPreview) {
2236  d->previewWidth = sizes[1];
2237  }
2238 
2239  if (d->progressBar->parent() == this) {
2240  // might be reparented into a statusbar
2241  d->progressBar->move(2, height() - d->progressBar->height() - 2);
2242  }
2243 }
2244 
2245 void KDirOperator::setOnlyDoubleClickSelectsFiles(bool enable)
2246 {
2247  d->onlyDoubleClickSelectsFiles = enable;
2248  // TODO: port to Qt4's QAbstractItemModel
2249  //if (d->itemView != 0) {
2250  // d->itemView->setOnlyDoubleClickSelectsFiles(enable);
2251  //}
2252 }
2253 
2254 bool KDirOperator::onlyDoubleClickSelectsFiles() const
2255 {
2256  return d->onlyDoubleClickSelectsFiles;
2257 }
2258 
2259 void KDirOperator::Private::_k_slotStarted()
2260 {
2261  progressBar->setValue(0);
2262  // delay showing the progressbar for one second
2263  progressDelayTimer->setSingleShot(true);
2264  progressDelayTimer->start(1000);
2265 }
2266 
2267 void KDirOperator::Private::_k_slotShowProgress()
2268 {
2269  progressBar->raise();
2270  progressBar->show();
2271  QApplication::flush();
2272 }
2273 
2274 void KDirOperator::Private::_k_slotProgress(int percent)
2275 {
2276  progressBar->setValue(percent);
2277  // we have to redraw this as fast as possible
2278  if (progressBar->isVisible())
2279  QApplication::flush();
2280 }
2281 
2282 
2283 void KDirOperator::Private::_k_slotIOFinished()
2284 {
2285  progressDelayTimer->stop();
2286  _k_slotProgress(100);
2287  progressBar->hide();
2288  emit parent->finishedLoading();
2289  parent->resetCursor();
2290 
2291  if (preview) {
2292  preview->clearPreview();
2293  }
2294 }
2295 
2296 void KDirOperator::Private::_k_slotCanceled()
2297 {
2298  emit parent->finishedLoading();
2299  parent->resetCursor();
2300 }
2301 
2302 QProgressBar * KDirOperator::progressBar() const
2303 {
2304  return d->progressBar;
2305 }
2306 
2307 void KDirOperator::clearHistory()
2308 {
2309  qDeleteAll(d->backStack);
2310  d->backStack.clear();
2311  d->actionCollection->action("back")->setEnabled(false);
2312 
2313  qDeleteAll(d->forwardStack);
2314  d->forwardStack.clear();
2315  d->actionCollection->action("forward")->setEnabled(false);
2316 }
2317 
2318 void KDirOperator::setEnableDirHighlighting(bool enable)
2319 {
2320  d->dirHighlighting = enable;
2321 }
2322 
2323 bool KDirOperator::dirHighlighting() const
2324 {
2325  return d->dirHighlighting;
2326 }
2327 
2328 bool KDirOperator::dirOnlyMode() const
2329 {
2330  return dirOnlyMode(d->mode);
2331 }
2332 
2333 bool KDirOperator::dirOnlyMode(uint mode)
2334 {
2335  return ((mode & KFile::Directory) &&
2336  (mode & (KFile::File | KFile::Files)) == 0);
2337 }
2338 
2339 void KDirOperator::Private::_k_slotProperties()
2340 {
2341  if (itemView == 0) {
2342  return;
2343  }
2344 
2345  const KFileItemList list = parent->selectedItems();
2346  if (!list.isEmpty()) {
2347  KPropertiesDialog dialog(list, parent);
2348  dialog.exec();
2349  }
2350 }
2351 
2352 void KDirOperator::Private::_k_slotActivated(const QModelIndex& index)
2353 {
2354  const QModelIndex dirIndex = proxyModel->mapToSource(index);
2355  KFileItem item = dirModel->itemForIndex(dirIndex);
2356 
2357  const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
2358  if (item.isNull() || (modifiers & Qt::ShiftModifier) || (modifiers & Qt::ControlModifier))
2359  return;
2360 
2361  if (item.isDir()) {
2362  parent->selectDir(item);
2363  } else {
2364  parent->selectFile(item);
2365  }
2366 }
2367 
2368 void KDirOperator::Private::_k_slotSelectionChanged()
2369 {
2370  if (itemView == 0) {
2371  return;
2372  }
2373 
2374  // In the multiselection mode each selection change is indicated by
2375  // emitting a null item. Also when the selection has been cleared, a
2376  // null item must be emitted.
2377  const bool multiSelectionMode = (itemView->selectionMode() == QAbstractItemView::ExtendedSelection);
2378  const bool hasSelection = itemView->selectionModel()->hasSelection();
2379  if (multiSelectionMode || !hasSelection) {
2380  KFileItem nullItem;
2381  parent->highlightFile(nullItem);
2382  }
2383  else {
2384  KFileItem selectedItem = parent->selectedItems().first();
2385  parent->highlightFile(selectedItem);
2386  }
2387 }
2388 
2389 void KDirOperator::Private::_k_openContextMenu(const QPoint& pos)
2390 {
2391  const QModelIndex proxyIndex = itemView->indexAt(pos);
2392  const QModelIndex dirIndex = proxyModel->mapToSource(proxyIndex);
2393  KFileItem item = dirModel->itemForIndex(dirIndex);
2394 
2395  if (item.isNull())
2396  return;
2397 
2398  parent->activatedMenu(item, QCursor::pos());
2399 }
2400 
2401 void KDirOperator::Private::_k_triggerPreview(const QModelIndex& index)
2402 {
2403  if ((preview != 0 && !preview->isHidden()) && index.isValid() && (index.column() == KDirModel::Name)) {
2404  const QModelIndex dirIndex = proxyModel->mapToSource(index);
2405  const KFileItem item = dirModel->itemForIndex(dirIndex);
2406 
2407  if (item.isNull())
2408  return;
2409 
2410  if (!item.isDir()) {
2411  previewUrl = item.url();
2412  _k_showPreview();
2413  } else {
2414  preview->clearPreview();
2415  }
2416  }
2417 }
2418 
2419 void KDirOperator::Private::_k_showPreview()
2420 {
2421  if (preview != 0) {
2422  preview->showPreview(previewUrl);
2423  }
2424 }
2425 
2426 void KDirOperator::Private::_k_slotSplitterMoved(int, int)
2427 {
2428  const QList<int> sizes = splitter->sizes();
2429  if (sizes.count() == 2) {
2430  // remember the width of the preview widget (see KDirOperator::resizeEvent())
2431  previewWidth = sizes[1];
2432  }
2433 }
2434 
2435 void KDirOperator::Private::_k_assureVisibleSelection()
2436 {
2437  if (itemView == 0) {
2438  return;
2439  }
2440 
2441  QItemSelectionModel* selModel = itemView->selectionModel();
2442  if (selModel->hasSelection()) {
2443  const QModelIndex index = selModel->currentIndex();
2444  itemView->scrollTo(index, QAbstractItemView::EnsureVisible);
2445  _k_triggerPreview(index);
2446  }
2447 }
2448 
2449 
2450 void KDirOperator::Private::_k_synchronizeSortingState(int logicalIndex, Qt::SortOrder order)
2451 {
2452  QDir::SortFlags newSort = sorting & ~(QDirSortMask | QDir::Reversed);
2453 
2454  switch (logicalIndex) {
2455  case KDirModel::Name:
2456  newSort |= QDir::Name;
2457  break;
2458  case KDirModel::Size:
2459  newSort |= QDir::Size;
2460  break;
2461  case KDirModel::ModifiedTime:
2462  newSort |= QDir::Time;
2463  break;
2464  case KDirModel::Type:
2465  newSort |= QDir::Type;
2466  break;
2467  default:
2468  Q_ASSERT(false);
2469  }
2470 
2471  if (order == Qt::DescendingOrder) {
2472  newSort |= QDir::Reversed;
2473  }
2474 
2475  updateSorting(newSort);
2476 
2477  QMetaObject::invokeMethod(parent, "_k_assureVisibleSelection", Qt::QueuedConnection);
2478 }
2479 
2480 void KDirOperator::Private::_k_slotChangeDecorationPosition()
2481 {
2482  if (!itemView) {
2483  return;
2484  }
2485 
2486  QListView *view = qobject_cast<QListView*>(itemView);
2487 
2488  if (!view) {
2489  return;
2490  }
2491 
2492  const bool leftChecked = actionCollection->action("decorationAtLeft")->isChecked();
2493 
2494  if (leftChecked) {
2495  decorationPosition = QStyleOptionViewItem::Left;
2496  view->setFlow(QListView::TopToBottom);
2497  } else {
2498  decorationPosition = QStyleOptionViewItem::Top;
2499  view->setFlow(QListView::LeftToRight);
2500  }
2501 
2502  updateListViewGrid();
2503 
2504  itemView->update();
2505 }
2506 
2507 void KDirOperator::Private::_k_slotExpandToUrl(const QModelIndex &index)
2508 {
2509  QTreeView *treeView = qobject_cast<QTreeView*>(itemView);
2510 
2511  if (!treeView) {
2512  return;
2513  }
2514 
2515  const KFileItem item = dirModel->itemForIndex(index);
2516 
2517  if (item.isNull()) {
2518  return;
2519  }
2520 
2521  if (!item.isDir()) {
2522  const QModelIndex proxyIndex = proxyModel->mapFromSource(index);
2523 
2524  KUrl::List::Iterator it = itemsToBeSetAsCurrent.begin();
2525  while (it != itemsToBeSetAsCurrent.end()) {
2526  const KUrl url = *it;
2527  if (url.isParentOf(item.url())) {
2528  const KFileItem _item = dirLister->findByUrl(url);
2529  if (!_item.isNull() && _item.isDir()) {
2530  const QModelIndex _index = dirModel->indexForItem(_item);
2531  const QModelIndex _proxyIndex = proxyModel->mapFromSource(_index);
2532  treeView->expand(_proxyIndex);
2533 
2534  // if we have expanded the last parent of this item, select it
2535  if (item.url().directory() == url.path(KUrl::RemoveTrailingSlash)) {
2536  treeView->selectionModel()->select(proxyIndex, QItemSelectionModel::Select);
2537  }
2538  }
2539  it = itemsToBeSetAsCurrent.erase(it);
2540  } else {
2541  ++it;
2542  }
2543  }
2544  } else if (!itemsToBeSetAsCurrent.contains(item.url())) {
2545  itemsToBeSetAsCurrent << item.url();
2546  }
2547 }
2548 
2549 void KDirOperator::Private::_k_slotItemsChanged()
2550 {
2551  completeListDirty = true;
2552 }
2553 
2554 void KDirOperator::Private::updateListViewGrid()
2555 {
2556  if (!itemView) {
2557  return;
2558  }
2559 
2560  QListView *view = qobject_cast<QListView*>(itemView);
2561 
2562  if (!view) {
2563  return;
2564  }
2565 
2566  const bool leftChecked = actionCollection->action("decorationAtLeft")->isChecked();
2567 
2568  if (leftChecked) {
2569  view->setGridSize(QSize());
2570  KFileItemDelegate *delegate = qobject_cast<KFileItemDelegate*>(view->itemDelegate());
2571  if (delegate) {
2572  delegate->setMaximumSize(QSize());
2573  }
2574  } else {
2575  const QFontMetrics metrics(itemView->viewport()->font());
2576  int size = itemView->iconSize().height() + metrics.height() * 2;
2577  // some heuristics for good looking. let's guess width = height * (3 / 2) is nice
2578  view->setGridSize(QSize(size * (3.0 / 2.0), size + metrics.height()));
2579  KFileItemDelegate *delegate = qobject_cast<KFileItemDelegate*>(view->itemDelegate());
2580  if (delegate) {
2581  delegate->setMaximumSize(QSize(size * (3.0 / 2.0), size + metrics.height()));
2582  }
2583  }
2584 }
2585 
2586 int KDirOperator::Private::iconSizeForViewType(QAbstractItemView *itemView) const
2587 {
2588  if (!itemView || !configGroup) {
2589  return 0;
2590  }
2591 
2592  if (qobject_cast<QListView*>(itemView)) {
2593  return configGroup->readEntry("listViewIconSize", 0);
2594  } else {
2595  return configGroup->readEntry("detailedViewIconSize", 0);
2596  }
2597 }
2598 
2599 void KDirOperator::setViewConfig(KConfigGroup& configGroup)
2600 {
2601  delete d->configGroup;
2602  d->configGroup = new KConfigGroup(configGroup);
2603 }
2604 
2605 KConfigGroup* KDirOperator::viewConfigGroup() const
2606 {
2607  return d->configGroup;
2608 }
2609 
2610 void KDirOperator::setShowHiddenFiles(bool s)
2611 {
2612  d->actionCollection->action("show hidden")->setChecked(s);
2613 }
2614 
2615 bool KDirOperator::showHiddenFiles() const
2616 {
2617  return d->actionCollection->action("show hidden")->isChecked();
2618 }
2619 
2620 QStyleOptionViewItem::Position KDirOperator::decorationPosition() const
2621 {
2622  return d->decorationPosition;
2623 }
2624 
2625 void KDirOperator::setDecorationPosition(QStyleOptionViewItem::Position position)
2626 {
2627  d->decorationPosition = position;
2628  const bool decorationAtLeft = d->decorationPosition == QStyleOptionViewItem::Left;
2629  d->actionCollection->action("decorationAtLeft")->setChecked(decorationAtLeft);
2630  d->actionCollection->action("decorationAtTop")->setChecked(!decorationAtLeft);
2631 }
2632 
2633 // ### temporary code
2634 #include <dirent.h>
2635 bool KDirOperator::Private::isReadable(const KUrl& url)
2636 {
2637  if (!url.isLocalFile())
2638  return true; // what else can we say?
2639 
2640  KDE_struct_stat buf;
2641 #ifdef Q_WS_WIN
2642  QString ts = url.toLocalFile();
2643 #else
2644  QString ts = url.path(KUrl::AddTrailingSlash);
2645 #endif
2646  bool readable = (KDE::stat(ts, &buf) == 0);
2647  if (readable) { // further checks
2648  DIR *test;
2649  test = opendir(QFile::encodeName(ts)); // we do it just to test here
2650  readable = (test != 0);
2651  if (test)
2652  closedir(test);
2653  }
2654  return readable;
2655 }
2656 
2657 void KDirOperator::Private::_k_slotDirectoryCreated(const KUrl& url)
2658 {
2659  parent->setUrl(url, true);
2660 }
2661 
2662 #include "kdiroperator.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jun 1 2013 20:23:52 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KFile

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

kdelibs-4.10.4 API Reference

Skip menu "kdelibs-4.10.4 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal