Skip to content

Commit 73aa47c

Browse files
committed
Initial commit of Gel.
This implements the bare bones of what I want this to do.
0 parents  commit 73aa47c

File tree

9 files changed

+699
-0
lines changed

9 files changed

+699
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2015 Cutehacks AS
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
Gel is a framework for storing JSON objects in a ListView compatible model.
2+
It offers more functionality than the builtin ListModel by offering support
3+
for sorting and filtering.
4+
5+
# Installation
6+
7+
Gel is available on qpm:
8+
9+
`qpm install com.cutehacks.gel`
10+
11+
# Usage
12+
13+
In your main.cpp:
14+
15+
```
16+
#include "com/cutehacks/gel/gel.h"
17+
18+
int main(int argc, char *argv[])
19+
{
20+
...
21+
22+
com::cutehacks::gel::registerEngine(&engine);
23+
24+
...
25+
}
26+
```
27+
28+
The above function will register two QML types with the QML engine which are documented
29+
below.
30+
31+
# API
32+
33+
## JsonListModel
34+
35+
A implementation of a model specifically designed for storing for JSON objects. The item
36+
has the following properties and functions:
37+
38+
### idAttribute : property string: "id"
39+
40+
Specifies the name of the property that should be used to uniquely identify
41+
this object within the model. Adding an object with the same value for this
42+
property will update the existing object instead of creating a new one.
43+
44+
### add(jsobject | jsarray | string | number | date) : function
45+
46+
Add a new JSON object or an array of objects to the model
47+
48+
### remove(jsobject | string | number | date) : function
49+
50+
Remove the specified object from the model.
51+
52+
### clear() : function
53+
54+
Remove all items from the model.
55+
56+
## Collection
57+
58+
An item for sorting an filtering a JsonListModel. The Collection itself does not
59+
store any data, but rather proxies the data stored inside the source model.
60+
61+
### model : JsonListModel
62+
63+
The model used to store the JSON objects for this collection.
64+
65+
### comparator : string | function
66+
67+
Specifies the comparator to use when sorting the collection.
68+
69+
* If a string is passed to this property, it refers to the property name that
70+
should be used for sorting.
71+
* If a function is passed to this property, it should have the following signature:
72+
73+
```
74+
function lessThan(a, b) {
75+
return a.value < b.value;
76+
}
77+
```
78+
79+
The function will receive two arguments that are JSON objects. The implementation of
80+
this function is responsible for comparing the two items and returning true if `a` is
81+
less than `b`; otherwise false.
82+
83+
### filter : function
84+
85+
A function indicating which items should be included in th resulting collection. The
86+
function should return true for items that should be included; otherwise false.
87+
88+
## Example
89+
90+
The following is an example of using the items:
91+
92+
```
93+
Collection {
94+
id: collection
95+
model: JsonListModel {
96+
id: jsonModel
97+
}
98+
filter: function(item) {
99+
return item.value.indexOf("foo") >= 0;
100+
}
101+
comparator: "value"
102+
}
103+
104+
```
105+
106+
The above snippet will sort a list of JSON objects based on the "value"
107+
property, but will only show objects whose "value" property contains the
108+
word "foo".

collection.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include "collection.h"
2+
#include "jsonlistmodel.h"
3+
4+
Collection::Collection(QObject *parent) : QSortFilterProxyModel(parent)
5+
{
6+
sort(0);
7+
}
8+
9+
QJSValue Collection::comparator() const
10+
{
11+
return m_comparator;
12+
}
13+
14+
QJSValue Collection::filter() const
15+
{
16+
return m_filter;
17+
}
18+
19+
JsonListModel *Collection::model() const
20+
{
21+
return qobject_cast<JsonListModel*>(sourceModel());
22+
}
23+
24+
void Collection::setComparator(QJSValue comparator)
25+
{
26+
if (m_comparator.strictlyEquals(comparator))
27+
return;
28+
29+
m_comparator = comparator;
30+
updateModel();
31+
emit comparatorChanged(comparator);
32+
}
33+
34+
void Collection::setFilter(QJSValue filter)
35+
{
36+
if (m_filter.strictlyEquals(filter))
37+
return;
38+
39+
m_filter = filter;
40+
invalidateFilter();
41+
emit filterChanged(filter);
42+
}
43+
44+
void Collection::setModel(JsonListModel *model)
45+
{
46+
JsonListModel *oldModel = qobject_cast<JsonListModel*>(sourceModel());
47+
if (oldModel == model)
48+
return;
49+
50+
if (oldModel) {
51+
disconnect(oldModel, SIGNAL(roleAdded(QString)),
52+
this, SLOT(resetInternalData()));
53+
}
54+
55+
setSourceModel(model);
56+
updateModel();
57+
connect(model, SIGNAL(roleAdded(QString)), this, SLOT(roleAdded(QString)));
58+
59+
emit modelChanged(model);
60+
}
61+
62+
void Collection::roleAdded(QString)
63+
{
64+
resetInternalData();
65+
updateModel();
66+
}
67+
68+
void Collection::updateModel()
69+
{
70+
if (model() && m_comparator.isString()) {
71+
int role = model()->getRole(m_comparator.toString());
72+
setSortRole(role);
73+
}
74+
// sort(0);
75+
}
76+
77+
78+
bool Collection::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
79+
{
80+
if (m_filter.isCallable()) {
81+
QJSValue result = m_filter.call(QJSValueList() << model()->at(source_row));
82+
return result.toBool();
83+
} else {
84+
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
85+
}
86+
}
87+
88+
bool Collection::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
89+
{
90+
/*if (m_comparator.isString()) {
91+
QString compare = m_comparator.toString();
92+
QJSValue left = model()->at(source_left.row());
93+
QJSValue right = model()->at(source_right.row());
94+
95+
// TODO: Avoid variant?
96+
QVariant leftVal = left.property(compare).toVariant();
97+
QVariant rightVal = right.property(compare).toVariant();
98+
return leftVal < rightVal;
99+
} else */
100+
if (m_comparator.isCallable()) {
101+
QJSValue left = model()->at(source_left.row());
102+
QJSValue right = model()->at(source_right.row());
103+
QJSValue result = m_comparator.call(QJSValueList() << left << right);
104+
return result.toBool();
105+
} else {
106+
return QSortFilterProxyModel::lessThan(source_left, source_right);
107+
}
108+
}

collection.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#ifndef COLLECTION_H
2+
#define COLLECTION_H
3+
4+
#include <QtCore/QSortFilterProxyModel>
5+
#include <QtQml/QJSValue>
6+
7+
class JsonListModel;
8+
9+
class Collection : public QSortFilterProxyModel
10+
{
11+
Q_OBJECT
12+
13+
Q_PROPERTY(QJSValue comparator READ comparator WRITE setComparator NOTIFY comparatorChanged)
14+
Q_PROPERTY(QJSValue filter READ filter WRITE setFilter NOTIFY filterChanged)
15+
Q_PROPERTY(JsonListModel* model READ model WRITE setModel NOTIFY modelChanged)
16+
17+
public:
18+
Collection(QObject *parent = 0);
19+
20+
QJSValue comparator() const;
21+
QJSValue filter() const;
22+
JsonListModel *model() const;
23+
24+
public slots:
25+
void setComparator(QJSValue comparator);
26+
void setFilter(QJSValue filter);
27+
void setModel(JsonListModel* model);
28+
29+
private slots:
30+
void roleAdded(QString);
31+
32+
signals:
33+
void comparatorChanged(QJSValue comparator);
34+
void filterChanged(QJSValue filter);
35+
void modelChanged(JsonListModel* model);
36+
37+
protected:
38+
void updateModel();
39+
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
40+
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
41+
42+
private:
43+
mutable QJSValue m_comparator;
44+
mutable QJSValue m_filter;
45+
};
46+
47+
#endif // COLLECTION_H

com_cutehacks_gel.pri

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
HEADERS += \
3+
$$PWD/jsonlistmodel.h \
4+
$$PWD/collection.h \
5+
$$PWD/gel.h
6+
7+
SOURCES += \
8+
$$PWD/jsonlistmodel.cpp \
9+
$$PWD/collection.cpp

gel.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#ifndef GEL_H
2+
#define GEL_H
3+
4+
#ifdef QPM_USE_NS
5+
6+
#undef _GET_OVERRIDE
7+
#undef _QPM_BEGIN_NAMESPACE_1
8+
#undef _QPM_BEGIN_NAMESPACE_2
9+
#undef _QPM_BEGIN_NAMESPACE_2
10+
#undef _QPM_BEGIN_NAMESPACE_4
11+
#undef QPM_BEGIN_NAMESPACE
12+
#undef _QPM_END_NAMESPACE_1
13+
#undef _QPM_END_NAMESPACE_2
14+
#undef _QPM_END_NAMESPACE_2
15+
#undef _QPM_END_NAMESPACE_4
16+
#undef QPM_END_NAMESPACE
17+
18+
#define _GET_OVERRIDE(_1, _2, _3, _4, NAME, ...) NAME
19+
20+
#define _QPM_BEGIN_NAMESPACE_1(a) \
21+
namespace a {
22+
#define _QPM_BEGIN_NAMESPACE_2(a, b) \
23+
_QPM_BEGIN_NAMESPACE_1(a) namespace b {
24+
#define _QPM_BEGIN_NAMESPACE_3(a, b, c) \
25+
_QPM_BEGIN_NAMESPACE_2(a, b) namespace c {
26+
#define _QPM_BEGIN_NAMESPACE_4(a, b, c, d) \
27+
_QPM_BEGIN_NAMESPACE_3(a, b, c) namespace d {
28+
29+
#define QPM_BEGIN_NAMESPACE(...) _GET_OVERRIDE(__VA_ARGS__, \
30+
_QPM_BEGIN_NAMESPACE_4, \
31+
_QPM_BEGIN_NAMESPACE_3, \
32+
_QPM_BEGIN_NAMESPACE_2, \
33+
_QPM_BEGIN_NAMESPACE_1)(__VA_ARGS__)
34+
35+
#define _QPM_END_NAMESPACE_1 };
36+
#define _QPM_END_NAMESPACE_2 } };
37+
#define _QPM_END_NAMESPACE_3 } } };
38+
#define _QPM_END_NAMESPACE_4 } } } };
39+
40+
#define QPM_END_NAMESPACE(...) _GET_OVERRIDE(__VA_ARGS__, \
41+
_QPM_END_NAMESPACE_4, \
42+
_QPM_END_NAMESPACE_3, \
43+
_QPM_END_NAMESPACE_2, \
44+
_QPM_END_NAMESPACE_1)
45+
46+
#else
47+
#define QPM_BEGIN_NAMESPACE(...)
48+
#define QPM_END_NAMESPACE(...)
49+
#endif // QPM_USE_NS
50+
51+
#include <QtQml>
52+
#include "jsonlistmodel.h"
53+
#include "collection.h"
54+
55+
QPM_BEGIN_NAMESPACE(com, cutehacks, gel)
56+
57+
void registerEngine(QQmlEngine *engine)
58+
{
59+
qmlRegisterType<JsonListModel>("com.cutehacks.gel", 1, 0, "JsonListModel");
60+
qmlRegisterType<Collection>("com.cutehacks.gel", 1, 0, "Collection");
61+
}
62+
63+
QPM_END_NAMESPACE(com, cutehacks, gel)
64+
65+
#endif // GEL_H
66+

0 commit comments

Comments
 (0)