From b324f520fb566141263821c5692843ee525e93bd Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Wed, 19 Jun 2013 17:38:06 +0200 Subject: [PATCH] qt5 port of DirModel --- src/declarativeimports/CMakeLists.txt | 1 + .../dirmodel/CMakeLists.txt | 20 ++ src/declarativeimports/dirmodel/dirmodel.cpp | 201 ++++++++++++++++++ src/declarativeimports/dirmodel/dirmodel.h | 91 ++++++++ .../dirmodel/dirmodelplugin.cpp | 33 +++ .../dirmodel/dirmodelplugin.h | 35 +++ src/declarativeimports/dirmodel/qmldir | 2 + 7 files changed, 383 insertions(+) create mode 100644 src/declarativeimports/dirmodel/CMakeLists.txt create mode 100644 src/declarativeimports/dirmodel/dirmodel.cpp create mode 100644 src/declarativeimports/dirmodel/dirmodel.h create mode 100644 src/declarativeimports/dirmodel/dirmodelplugin.cpp create mode 100644 src/declarativeimports/dirmodel/dirmodelplugin.h create mode 100644 src/declarativeimports/dirmodel/qmldir diff --git a/src/declarativeimports/CMakeLists.txt b/src/declarativeimports/CMakeLists.txt index 8313ee8ec..5f903362c 100644 --- a/src/declarativeimports/CMakeLists.txt +++ b/src/declarativeimports/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(core) +add_subdirectory(dirmodel) add_subdirectory(draganddrop) add_subdirectory(krunnermodel) add_subdirectory(qtextracomponents) diff --git a/src/declarativeimports/dirmodel/CMakeLists.txt b/src/declarativeimports/dirmodel/CMakeLists.txt new file mode 100644 index 000000000..99ee17f21 --- /dev/null +++ b/src/declarativeimports/dirmodel/CMakeLists.txt @@ -0,0 +1,20 @@ +project(dirmodel) + +set(dirmodel_SRCS + dirmodel.cpp + dirmodelplugin.cpp + ) + + +add_library(dirmodelplugin SHARED ${dirmodel_SRCS}) +target_link_libraries(dirmodelplugin + ${QT_QTCORE_LIBRARY} + ${Qt5Qml_LIBRARIES} + ${KDE4_KIO_LIBS} + KDE4__kde4support + ) + +install(TARGETS dirmodelplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/dirmodel) +install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/dirmodel) + +#add_subdirectory(test) diff --git a/src/declarativeimports/dirmodel/dirmodel.cpp b/src/declarativeimports/dirmodel/dirmodel.cpp new file mode 100644 index 000000000..8d6c0b5f6 --- /dev/null +++ b/src/declarativeimports/dirmodel/dirmodel.cpp @@ -0,0 +1,201 @@ +/* + Copyright (C) 20111 Marco Martin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +*/ + +#include "dirmodel.h" + +#include +#include + +#include +#include +#include +#include +#include + + +DirModel::DirModel(QObject *parent) + : KDirModel(parent), + m_screenshotSize(180, 120) +{ + KMimeType::List mimeList = KMimeType::allMimeTypes(); + + m_mimeTypes << "inode/directory"; + foreach (KMimeType::Ptr mime, mimeList) { + if (mime->name().startsWith(QLatin1String("image/"))) { + m_mimeTypes << mime->name(); + } + } + + //TODO: configurable mime filter + //dirLister()->setMimeFilter(m_mimeTypes); + + QHashroleNames; + roleNames[Qt::DisplayRole] = "display"; + roleNames[Qt::DecorationRole] = "decoration"; + roleNames[UrlRole] = "url"; + roleNames[MimeTypeRole] = "mimeType"; + roleNames[Thumbnail] = "thumbnail"; + setRoleNames(roleNames); + + m_previewTimer = new QTimer(this); + m_previewTimer->setSingleShot(true); + connect(m_previewTimer, SIGNAL(timeout()), + this, SLOT(delayedPreview())); + + //using the same cache of the engine, they index both by url + m_imageCache = new KImageCache("plasma_engine_preview", 10485760); + + connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SIGNAL(countChanged())); + connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SIGNAL(countChanged())); + connect(this, SIGNAL(modelReset()), + this, SIGNAL(countChanged())); +} + +DirModel::~DirModel() +{ + delete m_imageCache; +} + +QString DirModel::url() const +{ + return dirLister()->url().toString(); +} + +void DirModel::setUrl(const QString& url) +{ + if (url.isEmpty()) { + return; + } + if (dirLister()->url().path() == url) { + dirLister()->updateDirectory(QUrl(url)); + return; + } + + beginResetModel(); + dirLister()->openUrl(QUrl(url)); + endResetModel(); + emit urlChanged(); +} + +int DirModel::indexForUrl(const QString &url) const +{ + QModelIndex index = KDirModel::indexForUrl(QUrl(url)); + return index.row(); +} + +QVariantMap DirModel::get(int i) const +{ + QModelIndex modelIndex = index(i, 0); + + KFileItem item = itemForIndex(modelIndex); + QString url = item.url().toString(); + QString mimeType = item.mimetype(); + + QVariantMap ret; + ret.insert("url", QVariant(url)); + ret.insert("mimeType", QVariant(mimeType)); + + return ret; +} + +QVariant DirModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + switch (role) { + case UrlRole: { + KFileItem item = itemForIndex(index); + return item.url().toString(); + } + case MimeTypeRole: { + KFileItem item = itemForIndex(index); + return item.mimetype(); + } + case Thumbnail: { + KFileItem item = itemForIndex(index); + QImage preview = QImage(m_screenshotSize, QImage::Format_ARGB32_Premultiplied); + + if (m_imageCache->findImage(item.url().toString(), &preview)) { + return preview; + } + + m_previewTimer->start(100); + const_cast(this)->m_filesToPreview[item.url()] = QPersistentModelIndex(index); + } + default: + return KDirModel::data(index, role); + } +} + +void DirModel::delayedPreview() +{ + QHash::const_iterator i = m_filesToPreview.constBegin(); + + KFileItemList list; + + while (i != m_filesToPreview.constEnd()) { + QUrl file = i.key(); + QPersistentModelIndex index = i.value(); + + + if (!m_previewJobs.contains(file) && file.isValid()) { + list.append(KFileItem(file, QString(), 0)); + m_previewJobs.insert(file, QPersistentModelIndex(index)); + } + + ++i; + } + + if (list.size() > 0) { + KIO::PreviewJob* job = KIO::filePreview(list, m_screenshotSize); + job->setIgnoreMaximumSize(true); + kDebug() << "Created job" << job; + connect(job, SIGNAL(gotPreview(KFileItem,QPixmap)), + this, SLOT(showPreview(KFileItem,QPixmap))); + connect(job, SIGNAL(failed(KFileItem)), + this, SLOT(previewFailed(KFileItem))); + } + + m_filesToPreview.clear(); +} + +void DirModel::showPreview(const KFileItem &item, const QPixmap &preview) +{ + QPersistentModelIndex index = m_previewJobs.value(item.url()); + m_previewJobs.remove(item.url()); + + if (!index.isValid()) { + return; + } + + m_imageCache->insertImage(item.url().toString(), preview.toImage()); + //kDebug() << "preview size:" << preview.size(); + emit dataChanged(index, index); +} + +void DirModel::previewFailed(const KFileItem &item) +{ + m_previewJobs.remove(item.url()); +} + +#include "moc_dirmodel.cpp" diff --git a/src/declarativeimports/dirmodel/dirmodel.h b/src/declarativeimports/dirmodel/dirmodel.h new file mode 100644 index 000000000..a27d3e4d9 --- /dev/null +++ b/src/declarativeimports/dirmodel/dirmodel.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 20111 Marco Martin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +*/ + +#ifndef DIRMODEL_H +#define DIRMODEL_H + +#include +#include +#include + +class QTimer; + +class KImageCache; + +/** + * This class provides a QML binding to KDirModel + * Provides an easy way to navigate a filesystem from within QML + * + * @author Marco Martin + */ +class DirModel : public KDirModel +{ + Q_OBJECT + + /** + * @property string The url we want to browse. it may be an absolute path or a correct url of any protocol KIO supports + */ + Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) + + /** + * @property count Total number of rows + */ + Q_PROPERTY(int count READ count NOTIFY countChanged) + +public: + enum Roles { + UrlRole = Qt::UserRole + 1, + MimeTypeRole = Qt::UserRole + 2, + Thumbnail = Qt::UserRole + 3 + }; + + DirModel(QObject* parent=0); + virtual ~DirModel(); + + void setUrl(const QString& url); + QString url() const; + + QVariant data(const QModelIndex &index, int role) const; + int count() const {return rowCount();} + + Q_INVOKABLE int indexForUrl(const QString &url) const; + + Q_INVOKABLE QVariantMap get(int index) const; + +protected Q_SLOTS: + void showPreview(const KFileItem &item, const QPixmap &preview); + void previewFailed(const KFileItem &item); + void delayedPreview(); + +Q_SIGNALS: + void countChanged(); + void urlChanged(); + +private: + QStringList m_mimeTypes; + + //previews + QTimer *m_previewTimer; + QHash m_filesToPreview; + QSize m_screenshotSize; + QHash m_previewJobs; + KImageCache* m_imageCache; +}; + +#endif // DIRMODEL_H diff --git a/src/declarativeimports/dirmodel/dirmodelplugin.cpp b/src/declarativeimports/dirmodel/dirmodelplugin.cpp new file mode 100644 index 000000000..2702a711c --- /dev/null +++ b/src/declarativeimports/dirmodel/dirmodelplugin.cpp @@ -0,0 +1,33 @@ +/* + * Copyright 2012 by Marco Martin + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "dirmodelplugin.h" +#include "dirmodel.h" + +#include + + +void DirModelPlugin::registerTypes(const char *uri) +{ + Q_ASSERT(uri == QLatin1String("org.kde.dirmodel")); + qmlRegisterType(uri, 0, 1, "DirModel"); +} + +#include "moc_dirmodelplugin.cpp" + diff --git a/src/declarativeimports/dirmodel/dirmodelplugin.h b/src/declarativeimports/dirmodel/dirmodelplugin.h new file mode 100644 index 000000000..b881aa4e0 --- /dev/null +++ b/src/declarativeimports/dirmodel/dirmodelplugin.h @@ -0,0 +1,35 @@ +/* + * Copyright 2012 by Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef DIRMODELPLUGIN_H +#define DIRMODELPLUGIN_H + +#include + + +class DirModelPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + void registerTypes(const char *uri); +}; + +#endif diff --git a/src/declarativeimports/dirmodel/qmldir b/src/declarativeimports/dirmodel/qmldir new file mode 100644 index 000000000..2f26e1719 --- /dev/null +++ b/src/declarativeimports/dirmodel/qmldir @@ -0,0 +1,2 @@ +plugin dirmodelplugin +