File indexing completed on 2024-05-05 17:42:25

0001 /*
0002     This file is part of the KDE project
0003 
0004     SPDX-FileCopyrightText: 2007 Tobias Koenig <tokoe@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "kfiletreeview_p.h"
0010 
0011 #include <QContextMenuEvent>
0012 #include <QDir>
0013 #include <QMenu>
0014 #include <QUrl>
0015 
0016 #include <kdirlister.h>
0017 #include <kdirmodel.h>
0018 #include <kdirsortfilterproxymodel.h>
0019 #include <kfileitemdelegate.h>
0020 #include <klocalizedstring.h>
0021 #include <ktoggleaction.h>
0022 
0023 class KFileTreeView::Private
0024 {
0025 public:
0026     Private(KFileTreeView *parent)
0027         : q(parent)
0028     {
0029     }
0030 
0031     QUrl urlForProxyIndex(const QModelIndex &index) const;
0032 
0033     void activated(const QModelIndex &);
0034     void currentChanged(const QModelIndex &, const QModelIndex &);
0035     void expanded(const QModelIndex &);
0036 
0037     KFileTreeView *const q;
0038     KDirModel *mSourceModel = nullptr;
0039     KDirSortFilterProxyModel *mProxyModel = nullptr;
0040 };
0041 
0042 QUrl KFileTreeView::Private::urlForProxyIndex(const QModelIndex &index) const
0043 {
0044     const KFileItem item = mSourceModel->itemForIndex(mProxyModel->mapToSource(index));
0045 
0046     return !item.isNull() ? item.url() : QUrl();
0047 }
0048 
0049 void KFileTreeView::Private::activated(const QModelIndex &index)
0050 {
0051     const QUrl url = urlForProxyIndex(index);
0052     if (url.isValid()) {
0053         Q_EMIT q->activated(url);
0054     }
0055 }
0056 
0057 void KFileTreeView::Private::currentChanged(const QModelIndex &currentIndex, const QModelIndex &)
0058 {
0059     const QUrl url = urlForProxyIndex(currentIndex);
0060     if (url.isValid()) {
0061         Q_EMIT q->currentUrlChanged(url);
0062     }
0063 }
0064 
0065 void KFileTreeView::Private::expanded(const QModelIndex &baseIndex)
0066 {
0067     QModelIndex index = mProxyModel->mapFromSource(baseIndex);
0068 
0069     q->setExpanded(index, true);
0070     q->selectionModel()->clearSelection();
0071     q->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
0072     q->scrollTo(index);
0073 }
0074 
0075 KFileTreeView::KFileTreeView(QWidget *parent)
0076     : QTreeView(parent)
0077     , d(new Private(this))
0078 {
0079     d->mSourceModel = new KDirModel(this);
0080     d->mProxyModel = new KDirSortFilterProxyModel(this);
0081     d->mProxyModel->setSourceModel(d->mSourceModel);
0082 
0083     setModel(d->mProxyModel);
0084     setItemDelegate(new KFileItemDelegate(this));
0085     setLayoutDirection(Qt::LeftToRight);
0086 
0087     d->mSourceModel->dirLister()->openUrl(QUrl::fromLocalFile(QDir::root().absolutePath()), KDirLister::Keep);
0088 
0089     connect(this, &QAbstractItemView::activated, this, [this](const QModelIndex &index) {
0090         d->activated(index);
0091     });
0092 
0093     connect(selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex &current, const QModelIndex &previous) {
0094         d->currentChanged(current, previous);
0095     });
0096 
0097     connect(d->mSourceModel, &KDirModel::expand, this, [this](const QModelIndex &index) {
0098         d->expanded(index);
0099     });
0100 }
0101 
0102 KFileTreeView::~KFileTreeView()
0103 {
0104     delete d;
0105 }
0106 
0107 QUrl KFileTreeView::currentUrl() const
0108 {
0109     return d->urlForProxyIndex(currentIndex());
0110 }
0111 
0112 QUrl KFileTreeView::selectedUrl() const
0113 {
0114     if (!selectionModel()->hasSelection()) {
0115         return QUrl();
0116     }
0117 
0118     const QItemSelection selection = selectionModel()->selection();
0119     const QModelIndex firstIndex = selection.indexes().first();
0120 
0121     return d->urlForProxyIndex(firstIndex);
0122 }
0123 
0124 QList<QUrl> KFileTreeView::selectedUrls() const
0125 {
0126     QList<QUrl> urls;
0127 
0128     if (!selectionModel()->hasSelection()) {
0129         return urls;
0130     }
0131 
0132     const QModelIndexList indexes = selectionModel()->selection().indexes();
0133     foreach (const QModelIndex &index, indexes) {
0134         const QUrl url = d->urlForProxyIndex(index);
0135         if (url.isValid()) {
0136             urls.append(url);
0137         }
0138     }
0139 
0140     return urls;
0141 }
0142 
0143 QUrl KFileTreeView::rootUrl() const
0144 {
0145     return d->mSourceModel->dirLister()->url();
0146 }
0147 
0148 void KFileTreeView::setDirOnlyMode(bool enabled)
0149 {
0150     d->mSourceModel->dirLister()->setDirOnlyMode(enabled);
0151     d->mSourceModel->dirLister()->openUrl(d->mSourceModel->dirLister()->url());
0152 }
0153 
0154 void KFileTreeView::setShowHiddenFiles(bool enabled)
0155 {
0156     QUrl url = currentUrl();
0157     d->mSourceModel->dirLister()->setShowHiddenFiles(enabled);
0158     d->mSourceModel->dirLister()->openUrl(d->mSourceModel->dirLister()->url());
0159     setCurrentUrl(url);
0160 }
0161 
0162 void KFileTreeView::setCurrentUrl(const QUrl &url)
0163 {
0164     const QModelIndex baseIndex = d->mSourceModel->indexForUrl(url);
0165 
0166     if (!baseIndex.isValid()) {
0167         d->mSourceModel->expandToUrl(url);
0168         return;
0169     }
0170 
0171     const QModelIndex proxyIndex = d->mProxyModel->mapFromSource(baseIndex);
0172     selectionModel()->clearSelection();
0173     selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::SelectCurrent);
0174     scrollTo(proxyIndex);
0175 }
0176 
0177 void KFileTreeView::setRootUrl(const QUrl &url)
0178 {
0179     d->mSourceModel->dirLister()->openUrl(url);
0180 }
0181 
0182 void KFileTreeView::contextMenuEvent(QContextMenuEvent *event)
0183 {
0184     QMenu menu;
0185     KToggleAction *showHiddenAction = new KToggleAction(i18n("Show Hidden Folders"), &menu);
0186     showHiddenAction->setChecked(d->mSourceModel->dirLister()->showHiddenFiles());
0187     connect(showHiddenAction, &QAction::toggled, this, &KFileTreeView::setShowHiddenFiles);
0188 
0189     menu.addAction(showHiddenAction);
0190     menu.exec(event->globalPos());
0191 }
0192 
0193 bool KFileTreeView::showHiddenFiles() const
0194 {
0195     return d->mSourceModel->dirLister()->showHiddenFiles();
0196 }
0197 
0198 QSize KFileTreeView::sizeHint() const
0199 {
0200     // This size makes KDirSelectDialog pop up just under 800x600 by default :-)
0201     return QSize(680, 500);
0202 }
0203 
0204 #include "moc_kfiletreeview_p.cpp"