Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce tagging to sort office documents #58

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ find_package(Qt5Gui REQUIRED)
find_package(Qt5DBus REQUIRED)
find_package(Qt5LinguistTools REQUIRED)
find_package(QtSparql REQUIRED)
find_package(Qt5Sql REQUIRED)
find_package(Booster REQUIRED)

include(cmake/QtTranslationWithID.cmake)
Expand All @@ -36,6 +37,9 @@ set(sailfishoffice_SRCS
main.cpp
dbusadaptor.cpp
models/filtermodel.cpp
models/tagsthread.cpp
models/trackertagprovider.cpp
models/taglistmodel.cpp
models/documentlistmodel.cpp
models/documentproviderlistmodel.cpp
models/documentprovider.cpp
Expand All @@ -44,6 +48,8 @@ set(sailfishoffice_SRCS

set(sailfishoffice_QML_SRCS
qml/CoverPage.qml
qml/Tag.qml
qml/TagsSelector.qml
qml/FileListPage.qml
qml/Main.qml
qml/CoverFileItem.qml
Expand All @@ -60,7 +66,7 @@ set(sailfishoffice_TS_SRCS
create_translation(engen_qm_file ${CMAKE_BINARY_DIR}/sailfish-office.ts ${sailfishoffice_TS_SRCS})

add_executable(sailfish-office ${sailfishoffice_SRCS} ${engen_qm_file})
qt5_use_modules(sailfish-office Widgets Quick DBus)
qt5_use_modules(sailfish-office Widgets Quick DBus Sql)
target_link_libraries(sailfish-office stdc++ ${QT_LIBRARIES} ${BOOSTER_LIBRARY} ${QTSPARQL_LIBRARY})

install(TARGETS sailfish-office DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
Expand Down
3 changes: 3 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <MDeclarativeCache>

#include "config.h"
#include "models/taglistmodel.h"
#include "models/filtermodel.h"
#include "models/documentlistmodel.h"
#include "models/trackerdocumentprovider.h"
Expand Down Expand Up @@ -66,6 +67,8 @@ QSharedPointer<QQuickView> createView(const QString &file)
qmlRegisterType<DocumentListModel>("Sailfish.Office.Files", 1, 0, "DocumentListModel");
qmlRegisterType<DocumentProviderListModel>("Sailfish.Office.Files", 1, 0, "DocumentProviderListModel");
qmlRegisterType<TrackerDocumentProvider>("Sailfish.Office.Files", 1, 0, "TrackerDocumentProvider");
qmlRegisterType<TagListModel>("Sailfish.Office.Files", 1, 0, "TagListModel");
qmlRegisterType<TagFilterModel>("Sailfish.Office.Files", 1, 0, "TagFilterModel");
qmlRegisterType<FilterModel>("Sailfish.Office.Files", 1, 0, "FilterModel");
qmlRegisterInterface<DocumentProvider>("DocumentProvider");

Expand Down
101 changes: 98 additions & 3 deletions models/documentlistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "documentlistmodel.h"

#include <QDir>
#include <QSet>

struct DocumentListModelEntry
{
Expand Down Expand Up @@ -47,15 +48,25 @@ class DocumentListModel::Private
}
QList<DocumentListModelEntry> entries;
QHash<int, QByteArray> roles;
TagsThread *tagsThread; // To delegate tag storage with SQL backend.
TrackerTagProvider trackerTag;
TagListModel tagsModel; // A QML list of all tags.
QHash<QString, QSet<QString>> tags; // The association tag <-> [set of filenames]
};

DocumentListModel::DocumentListModel(QObject *parent)
: QAbstractListModel(parent), d(new Private)
{
// d->tagsThread = new TagsThread(this);
// connect(d->tagsThread, &TagsThread::jobFinished,
// this, &DocumentListModel::jobFinished);
connect(&d->trackerTag, &TrackerTagProvider::tagLoaded,
this, &DocumentListModel::tagLoaded);
}

DocumentListModel::~DocumentListModel()
{
// delete d->tagsThread;
}

QVariant DocumentListModel::data(const QModelIndex &index, int role) const
Expand Down Expand Up @@ -84,6 +95,63 @@ QVariant DocumentListModel::data(const QModelIndex &index, int role) const

return QVariant();
}
void DocumentListModel::notifyForPath(const QString &path)
{
int row = 0;
for (QList<DocumentListModelEntry>::iterator entry = d->entries.begin();
entry != d->entries.end(); entry++) {
if (path == entry->filePath) {
dataChanged(index(row), index(row));
return;
}
row += 1;
}
}
bool DocumentListModel::hasTag(int row, const QString &tag) const
{
if (row < 0 && row >= d->entries.count())
return false;

return hasTag(d->entries.at(row).filePath, tag);
}
bool DocumentListModel::hasTag(const QString &path, const QString &tag) const
{
return d->tags.value(tag).contains(path);
}
void DocumentListModel::addTag(const QString &path, const QString &tag)
{
QSet<QString> &files = d->tags[tag];
if (files.contains(path))
return; // This path has already this tag.

files.insert(path);
// TagsThreadJob *job = new TagsThreadJob(path, TagsThreadJob::TaskAddTags);
// job->tags.append(tag);
// d->tagsThread->queueJob(job);
d->trackerTag.addTag(path, tag);
d->tagsModel.addItem(tag);
notifyForPath(path);
}
void DocumentListModel::removeTag(const QString &path, const QString &tag)
{
QSet<QString> &files = d->tags[tag];
if (!files.contains(path))
return; // This path has not this tag.

files.remove(path);
if (files.empty())
d->tags.remove(tag);
// TagsThreadJob *job = new TagsThreadJob(path, TagsThreadJob::TaskRemoveTags);
// job->tags.append(tag);
// d->tagsThread->queueJob(job);
d->trackerTag.removeTag(path, tag);
d->tagsModel.removeItem(tag);
notifyForPath(path);
}
TagListModel* DocumentListModel::tags() const
{
return &d->tagsModel;
}

int DocumentListModel::rowCount(const QModelIndex& parent) const
{
Expand Down Expand Up @@ -129,6 +197,8 @@ void DocumentListModel::addItem(QString name, QString path, QString type, int si
entry.fileRead = lastRead;
entry.mimeType = mimeType;
entry.documentClass = static_cast<DocumentClass>(mimeTypeToDocumentClass(mimeType));
d->trackerTag.loadTags(path);
//d->tagsThread->queueJob(new TagsThreadJob(path, TagsThreadJob::TaskLoadTags));

int index = 0;
for (; index < d->entries.count(); ++index) {
Expand All @@ -145,9 +215,7 @@ void DocumentListModel::removeItemsDirty()
{
for (int index=0; index < d->entries.count(); index++) {
if (d->entries.at(index).dirty) {
beginRemoveRows(QModelIndex(), index, index);
d->entries.removeAt(index);
endRemoveRows();
removeAt(index);
}
}
}
Expand All @@ -156,6 +224,7 @@ void DocumentListModel::removeItemsDirty()
void DocumentListModel::removeAt(int index)
{
if (index > -1 && index < d->entries.count()) {
// d->tagsThread->cancelJobsForPath(d->entries.at(index).filePath);
beginRemoveRows(QModelIndex(), index, index);
d->entries.removeAt(index);
endRemoveRows();
Expand All @@ -164,11 +233,37 @@ void DocumentListModel::removeAt(int index)

void DocumentListModel::clear()
{
// d->tagsThread->cancelAllJobs();
beginResetModel();
d->entries.clear();
endResetModel();
}

void DocumentListModel::jobFinished(TagsThreadJob *job)
{
if (job->task == TagsThreadJob::TaskLoadTags) {
for (QList<QString>::const_iterator tag = job->tags.begin();
tag != job->tags.end(); tag++) {
QSet<QString> &files = d->tags[*tag];
files.insert(job->path);
d->tagsModel.addItem(*tag);
}
notifyForPath(job->path);
}
job->deleteLater();
}

void DocumentListModel::tagLoaded(const QString &path, const QList<QString> &tags)
{
for (QList<QString>::const_iterator tag = tags.begin();
tag != tags.end(); tag++) {
QSet<QString> &files = d->tags[*tag];
files.insert(path);
d->tagsModel.addItem(*tag);
}
notifyForPath(path);
}

int DocumentListModel::mimeTypeToDocumentClass(QString mimeType) const
{
DocumentClass documentClass = UnknownDocument;
Expand Down
20 changes: 20 additions & 0 deletions models/documentlistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@
#include <QAbstractListModel>
#include <qdatetime.h>

#include "tagsthread.h"
#include "trackertagprovider.h"
#include "taglistmodel.h"

class DocumentListModelPrivate;

class DocumentListModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(TagListModel* tags READ tags NOTIFY tagsChanged)
public:
enum DocumentClass {
UnknownDocument,
Expand Down Expand Up @@ -64,11 +69,26 @@ class DocumentListModel : public QAbstractListModel
void removeAt(int index);
void clear();

TagListModel* tags() const;

Q_INVOKABLE int mimeTypeToDocumentClass(QString mimeType) const;
bool hasTag(int row, const QString &tag) const;
Q_INVOKABLE bool hasTag(const QString &path, const QString &tag) const;
Q_INVOKABLE void addTag(const QString &path, const QString &tag);
Q_INVOKABLE void removeTag(const QString &path, const QString &tag);

private Q_SLOTS:
void jobFinished(TagsThreadJob* job);
void tagLoaded(const QString &path, const QList<QString> &tags);

Q_SIGNALS:
void tagsChanged();

private:
class Private;
const QScopedPointer<Private> d;

void notifyForPath(const QString &path);
};

#endif // DOCUMENTLISTMODEL_H
33 changes: 33 additions & 0 deletions models/filtermodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,36 @@ DocumentListModel* FilterModel::sourceModel() const
{
return static_cast<DocumentListModel*>(QSortFilterProxyModel::sourceModel());
}

bool FilterModel::tagFiltered() const
{
return !tags.empty();
}
bool FilterModel::hasTag(const QString &tag) const
{
return tags.contains(tag);
}
void FilterModel::addTag(const QString &tag)
{
tags.insert(tag);
invalidateFilter();
emit tagFilteringChanged();
}
void FilterModel::removeTag(const QString &tag)
{
tags.remove(tag);
invalidateFilter();
emit tagFilteringChanged();
}
bool FilterModel::filterAcceptsRow(int source_row, const QModelIndex & source_parent) const
{
bool ret;

ret = true;
for (QSet<QString>::const_iterator it = tags.begin();
it != tags.end() && ret; it++) {
ret = sourceModel()->hasTag(source_row, *it);
}

return ret && QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
12 changes: 12 additions & 0 deletions models/filtermodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#ifndef FILTERMODEL_H
#define FILTERMODEL_H

#include <QSet>
#include <QSortFilterProxyModel>

#include "documentlistmodel.h"
Expand All @@ -27,18 +28,29 @@ class FilterModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(DocumentListModel *sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged)
Q_PROPERTY(bool tagFiltered READ tagFiltered NOTIFY tagFilteringChanged)
public:
FilterModel(QObject *parent = 0);
~FilterModel();

virtual bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const;

public:
DocumentListModel* sourceModel() const;
bool tagFiltered() const;

public Q_SLOTS:
void setSourceModel(DocumentListModel *model);
bool hasTag(const QString &tag) const;
void addTag(const QString &tag);
void removeTag(const QString &tag);

Q_SIGNALS:
void sourceModelChanged();
void tagFilteringChanged();

private:
QSet<QString> tags;
};

#endif // FILTERMODEL_H
Loading