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