I have made the following changes intended for : CE:MW:Shared / nemo-qml-plugins
Please review and accept or decline. BOSS has already run some checks on this request. See the "Messages from BOSS" section below. https://build.pub.meego.com//request/show/5594 Thank You, Robin Burchell [This message was auto-generated] --- Request # 5594: Messages from BOSS: State: review at 2012-08-12T21:15:00 by bossbot Reviews: accepted by bossbot : Prechecks succeeded. new for CE-maintainers : Please replace this text with a review and approve/reject the review (not the SR). BOSS will take care of the rest Changes: submit: home:w00t:branches:CE:MW:Shared / nemo-qml-plugins -> CE:MW:Shared / nemo-qml-plugins changes files: -------------- --- nemo-qml-plugins.changes +++ nemo-qml-plugins.changes @@ -0,0 +1,8 @@ +* Sun Aug 12 2012 Robin Burchell <[email protected]> - 0.0.5 +- folderlistmodel: New plugin from qmlfilemuncher code (by Robin) +- folderlistmodel: Add properties for permissions to folderlistmodel (by Petri Gerdt) +- folderlistmodel: API to customise display of folderlistmodel (by Robin) +- folderlistmodel: Ignore repeated path change requests in folderlistmodel (by Robin) +- contacts: Added lookup for Person by phone number (by Tom Swindell) +- contacts: Provide basic import/export functionality + old: ---- nemo-qml-plugins-0.0.4.tar.bz2 new: ---- 0001-fix-defaults-for-variables.patch nemo-qml-plugins-0.0.5.tar.bz2 spec files: ----------- --- nemo-qml-plugins.spec +++ nemo-qml-plugins.spec @@ -9,13 +9,14 @@ # << macros Summary: Nemo QML plugins source package. -Version: 0.0.4 +Version: 0.0.5 Release: 1 Group: System/Libraries License: BSD URL: https://github.com/nemomobile/nemo-qml-plugins Source0: %{name}-%{version}.tar.bz2 Source100: nemo-qml-plugins.yaml +Patch0: 0001-fix-defaults-for-variables.patch BuildRequires: pkgconfig(QtCore) >= 4.7.0 BuildRequires: pkgconfig(QtDeclarative) BuildRequires: pkgconfig(QtGui) @@ -45,10 +46,19 @@ %description qrencode A QML QR encoder plugin +%package folderlistmodel +Summary: Folder list model for QML applications +Group: System/Libraries + +%description folderlistmodel +A model providing a view of the filesystem for QML applications + %prep %setup -q -n %{name} +# 0001-fix-defaults-for-variables.patch +%patch0 -p1 # >> setup # << setup @@ -90,3 +100,9 @@ %{_libdir}/qt4/imports/org/nemomobile/qrencode/* # >> files qrencode # << files qrencode + +%files folderlistmodel +%defattr(-,root,root,-) +%{_libdir}/qt4/imports/org/nemomobile/folderlistmodel/* +# >> files folderlistmodel +# << files folderlistmodel other changes: -------------- ++++++ 0001-fix-defaults-for-variables.patch (new) --- 0001-fix-defaults-for-variables.patch +++ 0001-fix-defaults-for-variables.patch @@ -0,0 +1,28 @@ +From e10ee2fb051146ec7e2256352eac4f1814f970d7 Mon Sep 17 00:00:00 2001 +From: Robin Burchell <[email protected]> +Date: Sun, 12 Aug 2012 22:08:40 +0200 +Subject: [PATCH] fix defaults for variables + +--- + folderlistmodel/dirmodel.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/folderlistmodel/dirmodel.cpp b/folderlistmodel/dirmodel.cpp +index e1b3542..afefa89 100644 +--- a/folderlistmodel/dirmodel.cpp ++++ b/folderlistmodel/dirmodel.cpp +@@ -88,7 +88,10 @@ private: + QString mPathName; + }; + +-DirModel::DirModel(QObject *parent) : QAbstractListModel(parent) ++DirModel::DirModel(QObject *parent) ++ : QAbstractListModel(parent) ++ , mAwaitingResults(false) ++ , mShowDirectories(true) + { + mNameFilters = QStringList() << "*"; + +-- +1.7.11.2 + ++++++ nemo-qml-plugins-0.0.4.tar.bz2 -> nemo-qml-plugins-0.0.5.tar.bz2 --- README +++ README @@ -15,3 +15,6 @@ - contacts: offers an API similar to QtMobility.contacts, except without the fail +- qrencode: QR encoder API, using qrencode library. + +- folderlistmodel: threaded (and faster) version of Qt.labs.folderlistmodel --- contacts/seasidepeoplemodel.cpp +++ contacts/seasidepeoplemodel.cpp @@ -33,6 +33,8 @@ #include <QFile> #include <QVector> +#include <QDesktopServices> + #include <QContactAddress> #include <QContactAvatar> #include <QContactThumbnail> @@ -55,7 +57,9 @@ #include <QContactManagerEngine> #include <QVersitReader> +#include <QVersitWriter> #include <QVersitContactImporter> +#include <QVersitContactExporter> #include "seasideperson.h" #include "seasidepeoplemodel.h" @@ -138,6 +142,16 @@ return person; } +SeasidePerson *SeasidePeopleModel::personByPhoneNumber(const QString &msisdn) const +{ + QString normalizedNumber = SeasidePeopleModelPriv::normalizePhoneNumber(msisdn); + + if(normalizedNumber.isEmpty() || !priv->phoneNumbersToContactIds.contains(normalizedNumber)) return NULL; + + QContactLocalId localId = priv->phoneNumbersToContactIds.value(normalizedNumber); + return priv->idToContact.value(localId); +} + void SeasidePeopleModel::removePerson(SeasidePerson *person) { qDebug() << Q_FUNC_INFO << "Removing " << person; @@ -189,6 +203,7 @@ return; } + // TODO: thread QVersitReader reader(&vcf); reader.startReading(); reader.waitForFinished(); @@ -205,6 +220,45 @@ qDebug() << Q_FUNC_INFO << "Imported " << newContacts.size() << " contacts " << " from " << path; } +QString SeasidePeopleModel::exportContacts() const +{ + QVersitContactExporter exporter; + + QList<QContact> contacts; + contacts.reserve(priv->contactIds.size()); + + foreach (const QContactLocalId &contactId, priv->contactIds) { + SeasidePerson *p = personById(contactId); + contacts.append(p->contact()); + } + + if (!exporter.exportContacts(contacts)) { + qWarning() << Q_FUNC_INFO << "Failed to export contacts: " << exporter.errorMap(); + return QString(); + } + + QFile + vcard(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation) + + QDir::separator() + + QDateTime::currentDateTime().toString("ss_mm_hh_dd_mm_yyyy") + + ".vcf"); + + if (!vcard.open(QIODevice::WriteOnly)) { + qWarning() << "Cannot open " << vcard.fileName(); + return QString(); + } + + QVersitWriter writer(&vcard); + if (!writer.startWriting(exporter.documents())) { + qWarning() << Q_FUNC_INFO << "Can't start writing vcards " << writer.error(); + return QString(); + } + + // TODO: thread + writer.waitForFinished(); + return vcard.fileName(); +} + QContactManager *SeasidePeopleModel::manager() const { return priv->manager; --- contacts/seasidepeoplemodel.h +++ contacts/seasidepeoplemodel.h @@ -69,8 +69,10 @@ Q_INVOKABLE bool savePerson(SeasidePerson *person); Q_INVOKABLE SeasidePerson *personByRow(int row) const; Q_INVOKABLE SeasidePerson *personById(int id) const; + Q_INVOKABLE SeasidePerson *personByPhoneNumber(const QString &msisdn) const; Q_INVOKABLE void removePerson(SeasidePerson *person); Q_INVOKABLE void importContacts(const QString &path); + Q_INVOKABLE QString exportContacts() const; QContactManager *manager() const; --- contacts/seasidepeoplemodel_p.cpp +++ contacts/seasidepeoplemodel_p.cpp @@ -67,9 +67,18 @@ dataReset(); } +QString SeasidePeopleModelPriv::normalizePhoneNumber(const QString &msisdn) +{ + // TODO:Possibly be more efficient here. + QString normalized = msisdn; + normalized.replace(QRegExp("[^0-9]"), ""); + return normalized.right(7); +} + void SeasidePeopleModelPriv::addContacts(const QList<QContact> contactsList, int size) { foreach (const QContact &contact, contactsList) { + SeasidePerson *person = new SeasidePerson(contact); //qDebug() << Q_FUNC_INFO << "Adding contact " << contact.id() << " local " << contact.localId(); QContactLocalId id = contact.localId(); @@ -78,7 +87,15 @@ contactIds.push_back(id); idToIndex.insert(id, size++); } - idToContact.insert(id, new SeasidePerson(contact)); + idToContact.insert(id, person); + + // Create normalized numbers -> contact id map. + foreach(const QString &sourcePhoneNumber, person->phoneNumbers()) { + QString normalizedPhoneNumber = SeasidePeopleModelPriv::normalizePhoneNumber(sourcePhoneNumber); + if(phoneNumbersToContactIds.contains(normalizedPhoneNumber)) continue; // Ignore duplicates, first-come-first-serve. + + phoneNumbersToContactIds.insert(normalizedPhoneNumber, contact.localId()); + } } } @@ -283,6 +300,7 @@ foreach (const QContact &changedContact, changedContactsList) { qDebug() << Q_FUNC_INFO << "Fetched changed contact " << changedContact.id(); + QContactLocalId id = changedContact.localId(); int index =idToIndex.value(changedContact.localId()); if (index < min) @@ -293,7 +311,31 @@ // FIXME: this looks like it may be wrong, // could lead to multiple entries - idToContact[changedContact.localId()]->setContact(changedContact); + idToContact[id]->setContact(changedContact); + + // TODO: use normalized number from qtcontacts-tracker/mobility + SeasidePerson *person = idToContact[id]; + foreach(const QString &msisdn, person->phoneNumbers()) { + QString normalizedPhoneNumber = SeasidePeopleModelPriv::normalizePhoneNumber(msisdn); + + if(!phoneNumbersToContactIds.contains(normalizedPhoneNumber)) { + phoneNumbersToContactIds.insert(normalizedPhoneNumber, id); + } + } + + foreach(const QString &phoneNumber, phoneNumbersToContactIds.keys()) { + bool remove = true; + foreach(const QString &msisdn, person->phoneNumbers()) { + QString normalizedPhoneNumber = SeasidePeopleModelPriv::normalizePhoneNumber(msisdn); + if(phoneNumber == normalizedPhoneNumber) { + remove = false; + break; + } + } + if(remove) { + phoneNumbersToContactIds.remove(phoneNumber); + } + } } // FIXME: unfortunate that we can't easily identify what changed @@ -326,6 +368,12 @@ delete idToContact.take(id); idToIndex.remove(id); + + foreach(const QString &phoneNumber, phoneNumbersToContactIds.keys()) { + QContactLocalId cId = phoneNumbersToContactIds.value(phoneNumber); + if(cId = id) phoneNumbersToContactIds.remove(phoneNumber); + } + q->endRemoveRows(); } fixIndexMap(); @@ -364,6 +412,7 @@ qDeleteAll(idToContact); idToContact.clear(); idToIndex.clear(); + phoneNumbersToContactIds.clear(); addContacts(contactsList, size); --- contacts/seasidepeoplemodel_p.h +++ contacts/seasidepeoplemodel_p.h @@ -37,12 +37,14 @@ QList<QContactLocalId> contactIds; QMap<QContactLocalId, int> idToIndex; QMap<QContactLocalId, SeasidePerson *> idToContact; + QMap<QString, QContactLocalId> phoneNumbersToContactIds; QVector<QStringList> data; QStringList headers; LocaleUtils *localeHelper; QContactGuid currentGuid; QList<QContact> contactsPendingSave; + static QString normalizePhoneNumber(const QString &msisdn); void addContacts(const QList<QContact> contactsList, int size); void fixIndexMap(); --- contacts/seasideproxymodel.h +++ contacts/seasideproxymodel.h @@ -58,6 +58,11 @@ SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel()); return model->personById(id); } + Q_INVOKABLE SeasidePerson *personByPhoneNumber(const QString &msisdn) const + { + SeasidePeopleModel *model = static_cast<SeasidePeopleModel*>(sourceModel()); + return model->personByPhoneNumber(msisdn); + } Q_INVOKABLE void removePerson(SeasidePerson *person) { SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel()); @@ -68,6 +73,11 @@ SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel()); model->importContacts(path); } + Q_INVOKABLE QString exportContacts() + { + SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel()); + return model->exportContacts(); + } signals: void countChanged(); --- folderlistmodel +++ folderlistmodel +(directory) --- folderlistmodel/dirmodel.cpp +++ folderlistmodel/dirmodel.cpp @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2012 Robin Burchell <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#include <QDirIterator> +#include <QDir> +#include <QDebug> +#include <QDateTime> +#include <QUrl> + +#include <errno.h> +#include <string.h> + +#include "dirmodel.h" +#include "ioworkerthread.h" + +Q_GLOBAL_STATIC(IOWorkerThread, ioWorkerThread); + +class DirListWorker : public IORequest +{ + Q_OBJECT +public: + DirListWorker(const QString &pathName) + : mPathName(pathName) + { } + + void run() + { + qDebug() << Q_FUNC_INFO << "Running on: " << QThread::currentThreadId(); + + QDir tmpDir = QDir(mPathName); + QDirIterator it(tmpDir); + QVector<QFileInfo> directoryContents; + + while (it.hasNext()) { + it.next(); + + // skip hidden files + if (it.fileName()[0] == QLatin1Char('.')) + continue; + + directoryContents.append(it.fileInfo()); + if (directoryContents.count() >= 50) { + emit itemsAdded(directoryContents); + + // clear() would force a deallocation, micro-optimisation + directoryContents.erase(directoryContents.begin(), directoryContents.end()); + } + } + + // last batch + emit itemsAdded(directoryContents); + + //std::sort(directoryContents.begin(), directoryContents.end(), DirModel::fileCompare); + } + +signals: + void itemsAdded(const QVector<QFileInfo> &files); + +private: + QString mPathName; +}; + +DirModel::DirModel(QObject *parent) : QAbstractListModel(parent) +{ + mNameFilters = QStringList() << "*"; + + QHash<int, QByteArray> roles = roleNames(); + roles.insert(FileNameRole, QByteArray("fileName")); + roles.insert(CreationDateRole, QByteArray("creationDate")); + roles.insert(ModifiedDateRole, QByteArray("modifiedDate")); + roles.insert(FileSizeRole, QByteArray("fileSize")); + roles.insert(IconSourceRole, QByteArray("iconSource")); + roles.insert(FilePathRole, QByteArray("filePath")); + roles.insert(IsDirRole, QByteArray("isDir")); + roles.insert(IsFileRole, QByteArray("isFile")); + roles.insert(IsReadableRole, QByteArray("isReadable")); + roles.insert(IsWritableRole, QByteArray("isWritable")); + roles.insert(IsExecutableRole, QByteArray("isExecutable")); + setRoleNames(roles); + + // populate reverse mapping + QHash<int, QByteArray>::ConstIterator it = roles.constBegin(); + for (;it != roles.constEnd(); ++it) + mRoleMapping.insert(it.value(), it.key()); + + // make sure we cover all roles +// Q_ASSERT(roles.count() == IsFileRole - FileNameRole); +} + +QVariant DirModel::data(int row, const QByteArray &stringRole) const +{ + QHash<QByteArray, int>::ConstIterator it = mRoleMapping.constFind(stringRole); + + if (it == mRoleMapping.constEnd()) + return QVariant(); + + return data(index(row, 0), *it); +} + +QVariant DirModel::data(const QModelIndex &index, int role) const +{ + if (role < FileNameRole || role > IsExecutableRole) { + qWarning() << Q_FUNC_INFO << "Got an out of range role: " << role; + return QVariant(); + } + + if (index.row() < 0 || index.row() >= mDirectoryContents.count()) { + qWarning() << "Attempted to access out of range row: " << index.row(); + return QVariant(); + } + + if (index.column() != 0) + return QVariant(); + + const QFileInfo &fi = mDirectoryContents.at(index.row()); + + switch (role) { + case FileNameRole: + return fi.fileName(); + case CreationDateRole: + return fi.created(); + case ModifiedDateRole: + return fi.lastModified(); + case FileSizeRole: { + qint64 kb = fi.size() / 1024; + if (kb < 1) + return QString::number(fi.size()) + " bytes"; + else if (kb < 1024) + return QString::number(kb) + " kb"; + + kb /= 1024; + return QString::number(kb) + "mb"; + } + case IconSourceRole: { + const QString &fileName = fi.fileName(); + + if (fi.isDir()) + return "image://theme/icon-m-common-directory"; + + if (fileName.endsWith(".jpg", Qt::CaseInsensitive) || + fileName.endsWith(".png", Qt::CaseInsensitive)) { + return "image://nemoThumbnail/" + fi.filePath(); + } + + return "image://theme/icon-m-content-document"; + } + case FilePathRole: + return fi.filePath(); + case IsDirRole: + return fi.isDir(); + case IsFileRole: + return !fi.isDir(); + case IsReadableRole: + return fi.isReadable(); + case IsWritableRole: + return fi.isWritable(); + case IsExecutableRole: + return fi.isExecutable(); + default: + // this should not happen, ever + Q_ASSERT(false); + qWarning() << Q_FUNC_INFO << "Got an unknown role: " << role; + return QVariant(); + } +} + +void DirModel::setPath(const QString &pathName) +{ + if (pathName.isEmpty()) + return; + + if (mAwaitingResults) { + // TODO: handle the case where pathName != our current path, cancel old + // request, start a new one + qDebug() << Q_FUNC_INFO << "Ignoring path change request, request already running"; + return; + } + + mAwaitingResults = true; + emit awaitingResultsChanged(); + qDebug() << Q_FUNC_INFO << "Changing to " << pathName << " on " << QThread::currentThreadId(); + + beginResetModel(); + mDirectoryContents.clear(); + endResetModel(); + + // TODO: we need to set a spinner active before we start getting results from DirListWorker + DirListWorker *dlw = new DirListWorker(pathName); + connect(dlw, SIGNAL(itemsAdded(QVector<QFileInfo>)), SLOT(onItemsAdded(QVector<QFileInfo>))); + ioWorkerThread()->addRequest(dlw); + + mCurrentDir = pathName; + emit pathChanged(); +} + +static bool fileCompare(const QFileInfo &a, const QFileInfo &b) +{ + if (a.isDir() && !b.isDir()) + return true; + + if (b.isDir() && !a.isDir()) + return false; + + return QString::localeAwareCompare(a.fileName(), b.fileName()) < 0; +} + +void DirModel::onItemsAdded(const QVector<QFileInfo> &newFiles) +{ + qDebug() << Q_FUNC_INFO << "Got new files: " << newFiles.count(); + + if (mAwaitingResults) { + qDebug() << Q_FUNC_INFO << "No longer awaiting results"; + mAwaitingResults = false; + emit awaitingResultsChanged(); + } + + foreach (const QFileInfo &fi, newFiles) { + if (!mShowDirectories && fi.isDir()) + continue; + + bool doAdd = true; + foreach (const QString &nameFilter, mNameFilters) { + // TODO: using QRegExp for wildcard matching is slow + QRegExp re(nameFilter, Qt::CaseInsensitive, QRegExp::Wildcard); + if (!re.exactMatch(fi.fileName())) { + doAdd = false; + break; + } + } + + if (!doAdd) + continue; + + QVector<QFileInfo>::Iterator it = qLowerBound(mDirectoryContents.begin(), + mDirectoryContents.end(), + fi, + fileCompare); + + if (it == mDirectoryContents.end()) { + beginInsertRows(QModelIndex(), mDirectoryContents.count(), mDirectoryContents.count()); + mDirectoryContents.append(fi); + endInsertRows(); + } else { + int idx = it - mDirectoryContents.begin(); + beginInsertRows(QModelIndex(), idx, idx); + mDirectoryContents.insert(it, fi); + endInsertRows(); + } + } +} + +void DirModel::rm(const QStringList &paths) +{ + // TODO: handle directory deletions? + bool error = false; + + foreach (const QString &path, paths) { + error |= QFile::remove(path); + + if (error) { + qWarning() << Q_FUNC_INFO << "Failed to remove " << path; + error = false; + } + } + + // TODO: just remove removed items; don't reload the entire model + refresh(); +} + +bool DirModel::rename(int row, const QString &newName) +{ + qDebug() << Q_FUNC_INFO << "Renaming " << row << " to " << newName; + Q_ASSERT(row >= 0 && row < mDirectoryContents.count()); + if (row < 0 || row >= mDirectoryContents.count()) { + qWarning() << Q_FUNC_INFO << "Out of bounds access"; + return false; + } + + const QFileInfo &fi = mDirectoryContents.at(row); + + if (!fi.isDir()) { + QFile f(fi.absoluteFilePath()); + bool retval = f.rename(fi.absolutePath() + QDir::separator() + newName); + + if (!retval) + qDebug() << Q_FUNC_INFO << "Rename returned error code: " << f.error() << f.errorString(); + else + refresh(); + // TODO: just change the affected item... ^^ + + return retval; + } else { + QDir d(fi.absoluteFilePath()); + bool retval = d.rename(fi.absoluteFilePath(), fi.absolutePath() + QDir::separator() + newName); + + // QDir has no way to detect what went wrong. woohoo! + + // TODO: just change the affected item... + refresh(); + + return retval; + } + + // unreachable (we hope) + Q_ASSERT(false); + return false; +} + +void DirModel::mkdir(const QString &newDir) +{ + qDebug() << Q_FUNC_INFO << "Creating new folder " << newDir << " to " << mCurrentDir; + + QDir dir(mCurrentDir); + bool retval = dir.mkdir(newDir); + if (!retval) { + const char *errorStr = strerror(errno); + qDebug() << Q_FUNC_INFO << "Error creating new directory: " << errno << " (" << errorStr << ")"; + emit error("Error creating new folder", errorStr); + } else { + refresh(); + } +} + +bool DirModel::showDirectories() const +{ + return mShowDirectories; +} + +void DirModel::setShowDirectories(bool showDirectories) +{ + mShowDirectories = showDirectories; + refresh(); + emit showDirectoriesChanged(); +} + +QStringList DirModel::nameFilters() const +{ + return mNameFilters; +} + +void DirModel::setNameFilters(const QStringList &nameFilters) +{ + mNameFilters = nameFilters; + refresh(); + emit nameFiltersChanged(); +} + +bool DirModel::awaitingResults() const +{ + return mAwaitingResults; +} + +// for dirlistworker +#include "dirmodel.moc" --- folderlistmodel/dirmodel.h +++ folderlistmodel/dirmodel.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2012 Robin Burchell <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#ifndef DIRMODEL_H +#define DIRMODEL_H + +#include <QAbstractListModel> +#include <QFileInfo> +#include <QVector> +#include <QStringList> + +#include "iorequest.h" + +class DirModel : public QAbstractListModel +{ + Q_OBJECT + + enum Roles { + FileNameRole = Qt::UserRole, + CreationDateRole, + ModifiedDateRole, + FileSizeRole, + IconSourceRole, + FilePathRole, + IsDirRole, + IsFileRole, + IsReadableRole, + IsWritableRole, + IsExecutableRole + }; + +public: + DirModel(QObject *parent = 0); + + int rowCount(const QModelIndex &index) const + { + if (index.parent() != QModelIndex()) + return 0; + + return mDirectoryContents.count(); + } + + // TODO: this won't be safe if the model can change under the holder of the row + Q_INVOKABLE QVariant data(int row, const QByteArray &stringRole) const; + + QVariant data(const QModelIndex &index, int role) const; + + Q_INVOKABLE void refresh() + { + // just some syntactical sugar really + setPath(path()); + } + + Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged); + inline QString path() const { return mCurrentDir; } + + Q_PROPERTY(bool awaitingResults READ awaitingResults NOTIFY awaitingResultsChanged); + bool awaitingResults() const; + + void setPath(const QString &pathName); + + Q_INVOKABLE void rm(const QStringList &paths); + + Q_INVOKABLE bool rename(int row, const QString &newName); + + Q_INVOKABLE void mkdir(const QString &newdir); + + Q_PROPERTY(bool showDirectories READ showDirectories WRITE setShowDirectories NOTIFY showDirectoriesChanged) + bool showDirectories() const; + void setShowDirectories(bool showDirectories); + + Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged) + QStringList nameFilters() const; + void setNameFilters(const QStringList &nameFilters); + +public slots: + void onItemsAdded(const QVector<QFileInfo> &newFiles); + +signals: + void awaitingResultsChanged(); + void nameFiltersChanged(); + void showDirectoriesChanged(); + void pathChanged(); + void error(const QString &errorTitle, const QString &errorMessage); + +private: + QStringList mNameFilters; + bool mShowDirectories; + bool mAwaitingResults; + QString mCurrentDir; + QVector<QFileInfo> mDirectoryContents; + QHash<QByteArray, int> mRoleMapping; +}; + + +#endif // DIRMODEL_H --- folderlistmodel/folderlistmodel.pro +++ folderlistmodel/folderlistmodel.pro @@ -0,0 +1,25 @@ +TARGET = nemofolderlistmodel +PLUGIN_IMPORT_PATH = org/nemomobile/folderlistmodel + +SOURCES += plugin.cpp \ + dirmodel.cpp \ + iorequest.cpp \ + iorequestworker.cpp \ + ioworkerthread.cpp + +HEADERS += dirmodel.h \ + iorequest.h \ + iorequestworker.h \ + ioworkerthread.h + +# do not edit below here, move this to a shared .pri? +TEMPLATE = lib +CONFIG += qt plugin hide_symbols +QT += declarative + +target.path = $$[QT_INSTALL_IMPORTS]/$$PLUGIN_IMPORT_PATH +INSTALLS += target + +qmldir.files += $$PWD/qmldir +qmldir.path += $$[QT_INSTALL_IMPORTS]/$$$$PLUGIN_IMPORT_PATH +INSTALLS += qmldir --- folderlistmodel/iorequest.cpp +++ folderlistmodel/iorequest.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 Robin Burchell <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#include "iorequest.h" + +IORequest::IORequest() : QObject() +{ +} --- folderlistmodel/iorequest.h +++ folderlistmodel/iorequest.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2012 Robin Burchell <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#ifndef IOREQUEST_H +#define IOREQUEST_H + +#include <QObject> + +class IORequest : public QObject +{ + Q_OBJECT +public: + explicit IORequest(); + +public: + virtual void run() = 0; + +private: + // hide this because IORequest should *NOT* be parented directly + using QObject::setParent; +}; + +#endif // IOREQUEST_H --- folderlistmodel/iorequestworker.cpp +++ folderlistmodel/iorequestworker.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2012 Robin Burchell <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#include <QMutexLocker> +#include <QDebug> + +#include "iorequestworker.h" +#include "iorequest.h" + +/*! + Lives on an IOWorkerThread. + + Responsible for running IORequest jobs on the thread instance, and + disposing of their resources once they are done. + */ +IORequestWorker::IORequestWorker() + : QThread() + , mTimeToQuit(false) +{ +} + +void IORequestWorker::addRequest(IORequest *request) +{ + request->moveToThread(this); + + // TODO: queue requests so we run the most important one first + QMutexLocker lock(&mMutex); + mRequests.append(request); + + // wake run() + mWaitCondition.wakeOne(); +} + +void IORequestWorker::run() +{ + forever { + QMutexLocker lock(&mMutex); + + if (mTimeToQuit) + return; + + if (mRequests.empty()) + mWaitCondition.wait(&mMutex); + + while (!mRequests.isEmpty()) { + IORequest *request = mRequests.takeFirst(); + + lock.unlock(); + + request->run(); + request->deleteLater(); + + lock.relock(); + } + } +} + +void IORequestWorker::exit() +{ + qDebug() << Q_FUNC_INFO << "Quitting"; + QMutexLocker lock(&mMutex); + mTimeToQuit = true; + mWaitCondition.wakeOne(); +} --- folderlistmodel/iorequestworker.h +++ folderlistmodel/iorequestworker.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012 Robin Burchell <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#ifndef IOREQUESTWORKER_H +#define IOREQUESTWORKER_H + +#include <QObject> +#include <QThread> +#include <QMutex> +#include <QWaitCondition> + +#include "iorequest.h" + +class IORequestWorker : public QThread +{ + Q_OBJECT +public: + explicit IORequestWorker(); + + void addRequest(IORequest *request); + + void run(); + + void exit(); + +private: + QMutex mMutex; + QWaitCondition mWaitCondition; + QList<IORequest *> mRequests; + bool mTimeToQuit; +}; + +#endif // IOREQUESTWORKER_H --- folderlistmodel/ioworkerthread.cpp +++ folderlistmodel/ioworkerthread.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 Robin Burchell <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#include "ioworkerthread.h" + + +/*! + Hosts a thread, lives on the main thread. + + Responsible for relaying interaction between the main thread and an IOWorkerThread. + */ +IOWorkerThread::IOWorkerThread(QObject *parent) : + QObject(parent) +{ + mWorker.start(QThread::IdlePriority); +} + +/*! + Destroys an IOWorkerThread instance. + */ +IOWorkerThread::~IOWorkerThread() +{ + mWorker.exit(); + mWorker.wait(); +} + +/*! + Attempts an asynchronous attempt to start a \a request. + + If the request may be run, it is queued, and true is returned, otherwise, false. + */ +bool IOWorkerThread::addRequest(IORequest *request) +{ + mWorker.addRequest(request); + return true; +} --- folderlistmodel/ioworkerthread.h +++ folderlistmodel/ioworkerthread.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2012 Robin Burchell <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#ifndef IOWORKERTHREAD_H +#define IOWORKERTHREAD_H + +#include <QObject> +#include <QThread> + +#include "iorequestworker.h" + +class IOWorkerThread : public QObject +{ + Q_OBJECT +public: + explicit IOWorkerThread(QObject *parent = 0); + virtual ~IOWorkerThread(); + bool addRequest(IORequest *request); + +private: + IORequestWorker mWorker; +}; + +#endif // IOWORKERTHREAD_H --- folderlistmodel/plugin.cpp +++ folderlistmodel/plugin.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2012 Robin Burchell <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#include <QtGlobal> +#include <QtDeclarative> +#include <QDeclarativeEngine> +#include <QDeclarativeExtensionPlugin> + +#include "dirmodel.h" + +Q_DECLARE_METATYPE(QVector<QFileInfo>) + +class Q_DECL_EXPORT NemoFolderListModelPlugin : public QDeclarativeExtensionPlugin +{ +public: + virtual ~NemoFolderListModelPlugin() { } + + void initializeEngine(QDeclarativeEngine *engine, const char *uri) + { + Q_ASSERT(uri == QLatin1String("org.nemomobile.folderlistmodel")); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(uri == QLatin1String("org.nemomobile.folderlistmodel")); + qRegisterMetaType<QVector<QFileInfo> >(); + qmlRegisterType<DirModel>(uri, 1, 0, "FolderListModel"); + } +}; + +Q_EXPORT_PLUGIN2(nemofolderlistmodel, NemoFolderListModelPlugin); + --- folderlistmodel/qmldir +++ folderlistmodel/qmldir @@ -0,0 +1 @@ +plugin nemofolderlistmodel --- nemo-qml-plugins.pro +++ nemo-qml-plugins.pro @@ -1,2 +1,5 @@ TEMPLATE = subdirs -SUBDIRS += thumbnailer contacts qrencoder +SUBDIRS += thumbnailer \ + contacts \ + qrencoder \ + folderlistmodel ++++++ nemo-qml-plugins.yaml --- nemo-qml-plugins.yaml +++ nemo-qml-plugins.yaml @@ -2,10 +2,12 @@ Summary: Nemo QML plugins source package. Group: System/Libraries Description: Do not install this, install the subpackaged plugins. -Version: 0.0.4 +Version: 0.0.5 Release: 1 Sources: - "%{name}-%{version}.tar.bz2" +Patches: + - 0001-fix-defaults-for-variables.patch License: BSD URL: https://github.com/nemomobile/nemo-qml-plugins Configure: none @@ -39,4 +41,10 @@ Files: - "%{_libdir}/qt4/imports/org/nemomobile/qrencode/*" + - Name: folderlistmodel + Summary: Folder list model for QML applications + Group: System/Libraries + Description: A model providing a view of the filesystem for QML applications + Files: + - "%{_libdir}/qt4/imports/org/nemomobile/folderlistmodel/*"
