[PATCH] sorted kfiletreeviews

Benjamin K. Stuhl benjamin.stuhl at colorado.edu
Sun Dec 2 18:58:01 GMT 2007


Hi Rafael,
  I saw you wrestling with this, so I thought I'd take a stab at it.
This patch works for me -- the important part is setting _k_expanded()
as a queued slot, so that the proxy model is updated before we try to
map the new index through it. Comments? OK to commit?

Enjoy,
-- BKS

Index: kdelibs/kfile/kfiletreeview.cpp
===================================================================
--- kdelibs/kfile/kfiletreeview.cpp     (revision 744111)
+++ kdelibs/kfile/kfiletreeview.cpp     (working copy)
@@ -25,6 +25,7 @@

 #include <kdirlister.h>
 #include <kdirmodel.h>
+#include <kdirsortfilterproxymodel.h>
 #include <kfileitemdelegate.h>
 #include <kurl.h>

@@ -32,64 +33,77 @@
 {
     public:
         Private(KFileTreeView *parent)
-            : mParent(parent)
+            : q(parent)
         {
         }

-        KUrl urlForIndex(const QModelIndex &index) const;
+        KUrl urlForProxyIndex(const QModelIndex &index) const;

         void _k_activated(const QModelIndex&);
         void _k_currentChanged(const QModelIndex&, const QModelIndex&);
         void _k_expanded(const QModelIndex&);

-        KFileTreeView *mParent;
-        KDirModel *mModel;
+        KFileTreeView *q;
+        KDirModel *mSourceModel;
+        KDirSortFilterProxyModel *mProxyModel;
 };

-KUrl KFileTreeView::Private::urlForIndex(const QModelIndex &index) const
+// we need to be able to queue model indicies, so declare it as a Qt metatype
+Q_DECLARE_METATYPE(QModelIndex)
+
+KUrl KFileTreeView::Private::urlForProxyIndex(const QModelIndex &index) const
 {
-    const KFileItem item = mModel->itemForIndex(index);
+    const KFileItem item = mSourceModel->itemForIndex(mProxyModel->mapToSource(index));

     return !item.isNull() ? item.url() : KUrl();
 }

 void KFileTreeView::Private::_k_activated(const QModelIndex &index)
 {
-    const KUrl url = urlForIndex(index);
+    const KUrl url = urlForProxyIndex(index);
     if (url.isValid())
-        emit mParent->activated(url);
+        emit q->activated(url);
 }

 void KFileTreeView::Private::_k_currentChanged(const QModelIndex &currentIndex, const QModelIndex&)
 {
-    const KUrl url = urlForIndex(currentIndex);
+    const KUrl url = urlForProxyIndex(currentIndex);
     if (url.isValid())
-        emit mParent->currentChanged(url);
+        emit q->currentChanged(url);
 }

-void KFileTreeView::Private::_k_expanded(const QModelIndex &index)
+void KFileTreeView::Private::_k_expanded(const QModelIndex &baseIndex)
 {
-    mParent->selectionModel()->clearSelection();
-    mParent->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
-    mParent->scrollTo(index);
+    QModelIndex index = mProxyModel->mapFromSource(baseIndex);
+
+    q->selectionModel()->clearSelection();
+    q->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
+    q->scrollTo(index);
 }

 KFileTreeView::KFileTreeView(QWidget *parent)
     : QTreeView(parent), d(new Private(this))
 {
-    d->mModel = new KDirModel(this);
+    d->mSourceModel = new KDirModel(this);
+    d->mProxyModel = new KDirSortFilterProxyModel(this);
+    d->mProxyModel->setSourceModel(d->mSourceModel);

-    setModel(d->mModel);
+    setModel(d->mProxyModel);
     setItemDelegate(new KFileItemDelegate(this));

-    d->mModel->dirLister()->openUrl(KUrl(QDir::root().absolutePath()), KDirLister::Keep);
+    d->mSourceModel->dirLister()->openUrl(KUrl(QDir::root().absolutePath()), KDirLister::Keep);

     connect(this, SIGNAL(activated(const QModelIndex&)),
             this, SLOT(_k_activated(const QModelIndex&)));
     connect(selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
             this, SLOT(_k_currentChanged(const QModelIndex&, const QModelIndex&)));
-    connect(d->mModel, SIGNAL(expand(const QModelIndex&)),
-            this, SLOT(_k_expanded(const QModelIndex&)));
+
+    // this must be a queued connection, because we need to be able to map indicies
+    // in it, and we can't do that until the expansion is complete
+    // QModelIndex is not registered by default, so do it here
+    qRegisterMetaType<QModelIndex>();
+    connect(d->mSourceModel, SIGNAL(expand(const QModelIndex&)),
+            this, SLOT(_k_expanded(const QModelIndex&)), Qt::QueuedConnection);
 }

 KFileTreeView::~KFileTreeView()
@@ -99,7 +113,7 @@

 KUrl KFileTreeView::currentUrl() const
 {
-    return d->urlForIndex(currentIndex());
+    return d->urlForProxyIndex(currentIndex());
 }

 KUrl KFileTreeView::selectedUrl() const
@@ -110,7 +124,7 @@
     const QItemSelection selection = selectionModel()->selection();
     const QModelIndex firstIndex = selection.indexes().first();

-    return d->urlForIndex(firstIndex);
+    return d->urlForProxyIndex(firstIndex);
 }

 KUrl::List KFileTreeView::selectedUrls() const
@@ -122,7 +136,7 @@

     const QModelIndexList indexes = selectionModel()->selection().indexes();
     foreach (const QModelIndex index, indexes) {
-        const KUrl url = d->urlForIndex(index);
+        const KUrl url = d->urlForProxyIndex(index);
         if (url.isValid())
             urls.append(url);
     }
@@ -132,37 +146,39 @@

 KUrl KFileTreeView::rootUrl() const
 {
-    return d->mModel->dirLister()->url();
+    return d->mSourceModel->dirLister()->url();
 }

 void KFileTreeView::setDirOnlyMode(bool enabled)
 {
-    d->mModel->dirLister()->setDirOnlyMode(enabled);
-    d->mModel->dirLister()->openUrl(d->mModel->dirLister()->url());
+    d->mSourceModel->dirLister()->setDirOnlyMode(enabled);
+    d->mSourceModel->dirLister()->openUrl(d->mSourceModel->dirLister()->url());
 }

 void KFileTreeView::setShowHiddenFiles(bool enabled)
 {
-    d->mModel->dirLister()->setShowingDotFiles(enabled);
-    d->mModel->dirLister()->openUrl(d->mModel->dirLister()->url());
+    d->mSourceModel->dirLister()->setShowingDotFiles(enabled);
+    d->mSourceModel->dirLister()->openUrl(d->mSourceModel->dirLister()->url());
 }

 void KFileTreeView::setCurrentUrl(const KUrl &url)
 {
-    QModelIndex index = d->mModel->indexForUrl(url);
+    QModelIndex baseIndex = d->mSourceModel->indexForUrl(url);

-    if (!index.isValid()) {
-        d->mModel->expandToUrl(url);
+    if (!baseIndex.isValid()) {
+        d->mSourceModel->expandToUrl(url);
         return;
     }
+
+    QModelIndex proxyIndex = d->mProxyModel->mapFromSource(baseIndex);
     selectionModel()->clearSelection();
-    selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
-    scrollTo(index);
+    selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::SelectCurrent);
+    scrollTo(proxyIndex);
 }

 void KFileTreeView::setRootUrl(const KUrl &url)
 {
-    d->mModel->dirLister()->openUrl(url);
+    d->mSourceModel->dirLister()->openUrl(url);
 }

 #include "kfiletreeview.moc"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20071202/f219f530/attachment.sig>


More information about the kde-core-devel mailing list