Commit fa56d686 authored by Leander Schulten's avatar Leander Schulten
Browse files

In every ModelView you can now sort the data by various properties

parent c224e8f1
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="511.626px" height="511.627px" viewBox="0 0 511.626 511.627" style="enable-background:new 0 0 511.626 511.627;"
xml:space="preserve">
<g>
<g>
<path d="M215.232,401.991h-54.818V9.136c0-2.663-0.854-4.856-2.568-6.567C156.133,0.859,153.946,0,151.279,0H96.461
c-2.663,0-4.856,0.855-6.567,2.568c-1.709,1.715-2.568,3.905-2.568,6.567v392.855H32.507c-4.184,0-7.039,1.902-8.563,5.708
c-1.525,3.621-0.856,6.95,1.997,9.996l91.361,91.365c2.096,1.707,4.281,2.562,6.567,2.562c2.474,0,4.664-0.855,6.567-2.562
l91.076-91.078c1.906-2.279,2.856-4.571,2.856-6.844c0-2.676-0.854-4.859-2.568-6.584
C220.086,402.847,217.9,401.991,215.232,401.991z"/>
<path d="M428.511,479.082h-70.808c-3.997,0-6.852,0.191-8.559,0.568l-4.001,0.571v-0.571l3.142-3.142
c2.848-3.419,4.853-5.896,5.996-7.409l105.344-151.331v-25.406H297.744v65.377h34.263v-32.832h66.236
c3.422,0,6.283-0.288,8.555-0.855c0.572,0,1.287-0.048,2.143-0.145c0.853-0.085,1.475-0.144,1.852-0.144v0.855l-3.142,2.574
c-1.704,1.711-3.713,4.273-5.995,7.706L296.31,485.934v25.693h166.734v-66.521h-34.54v33.976H428.511z"/>
<path d="M468.475,189.008L402.807,0h-46.25l-65.664,189.008h-19.979v30.264h81.933v-30.264h-21.409l13.419-41.112h69.381
l13.415,41.112H406.25v30.264h82.228v-30.264H468.475z M354.278,116.487l20.841-62.241c0.76-2.285,1.479-5.046,2.143-8.28
c0.66-3.236,0.996-4.949,0.996-5.139l0.855-5.708h1.143c0,0.761,0.191,2.664,0.562,5.708l3.433,13.418l20.554,62.241H354.278z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
https://www.flaticon.com/free-icon/sort-by-alphabet_25608#term=sort%20order&page=1&position=7
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="511.626px" height="511.627px" viewBox="0 0 511.626 511.627" style="enable-background:new 0 0 511.626 511.627;"
xml:space="preserve">
<g>
<g>
<path d="M215.232,401.991h-54.818V9.136c0-2.663-0.854-4.856-2.568-6.567C156.133,0.859,153.946,0,151.279,0H96.461
c-2.663,0-4.856,0.855-6.567,2.568c-1.709,1.715-2.568,3.905-2.568,6.567v392.855H32.507c-4.184,0-7.039,1.902-8.563,5.708
c-1.525,3.621-0.856,6.95,1.997,9.996l91.361,91.365c2.096,1.707,4.281,2.562,6.567,2.562c2.474,0,4.664-0.855,6.567-2.562
l91.076-91.078c1.906-2.279,2.856-4.571,2.856-6.844c0-2.676-0.854-4.859-2.568-6.584
C220.086,402.847,217.9,401.991,215.232,401.991z"/>
<path d="M468.475,481.361l-65.664-189.01h-46.25L290.9,481.364H270.92v30.263h81.934v-30.266h-21.412l13.418-41.11h69.381
l13.415,41.11H406.25v30.266h82.228v-30.266H468.475z M354.278,408.846l20.841-62.242c0.76-2.283,1.479-5.045,2.143-8.278
c0.66-3.234,0.996-4.948,0.996-5.137l0.855-5.715h1.143c0,0.767,0.191,2.669,0.562,5.715l3.433,13.415l20.554,62.242H354.278z"/>
<path d="M463.055,152.745h-34.537v33.975H357.71c-4.001,0-6.852,0.097-8.556,0.288l-4.004,0.854v-0.854l3.142-2.858
c2.851-3.422,4.853-5.896,5.996-7.421L459.632,25.41V0H297.754v65.387h34.259V32.552h66.232c3.426,0,6.283-0.288,8.56-0.859
c0.571,0,1.286-0.048,2.142-0.144c0.855-0.094,1.476-0.144,1.854-0.144v0.855l-3.141,2.568c-1.708,1.713-3.71,4.283-5.996,7.71
L296.32,193.569v25.697h166.735V152.745z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
https://www.flaticon.com/free-icon/sort-reverse-alphabetical-order_25378#term=sort%20order&page=1&position=9
......@@ -44,6 +44,7 @@
#include "test/testsampleclass.h"
#include "spotify/spotify.h"
#include "modules/dmxconsumer.h"
#include "sortedmodelview.h"
#include "updater.h"
int main(int argc, char *argv[])
......@@ -116,6 +117,7 @@ int main(int argc, char *argv[])
qmlRegisterType<DMXChannelFilter>("custom.licht",1,0,"DMXChannelFilter");
qmlRegisterType<CodeEditorHelper>("custom.licht",1,0,"CodeEditorHelper");
qmlRegisterType<ProgramBlockEditor>("custom.licht",1,0,"ProgramBlockEditor");
qmlRegisterType<SortedModelVectorView>("custom.licht",1,0,"SortedModelVectorView");
qRegisterMetaType<DMXChannelFilter::Operation>("Operation");
qmlRegisterUncreatableType<UserManagment>("custom.licht",1,0,"Permission","Singletone in c++");
qRegisterMetaType<UserManagment::Permission>("Permission");
......
......@@ -60,5 +60,17 @@
<file>qml/components/AskWhenRemovePopup.qml</file>
<file>qml/FFTGraphView.qml</file>
<file>qml/BarMapView.qml</file>
<file>icons/sort_order/sort-by-alphabet.svg</file>
<file>icons/sort_order/sort-by-alphabet_16px.png</file>
<file>icons/sort_order/sort-by-alphabet_24px.png</file>
<file>icons/sort_order/sort-by-alphabet_32px.png</file>
<file>icons/sort_order/sort-by-alphabet_64px.png</file>
<file>icons/sort_order/sort-by-alphabet_source</file>
<file>icons/sort_order/sort-reverse-alphabetical-order.svg</file>
<file>icons/sort_order/sort-reverse-alphabetical-order_16px.png</file>
<file>icons/sort_order/sort-reverse-alphabetical-order_24px.png</file>
<file>icons/sort_order/sort-reverse-alphabetical-order_32px.png</file>
<file>icons/sort_order/sort-reverse-alphabetical-order_64px.png</file>
<file>icons/sort_order/sort-reverse-alphabetical-order_source</file>
</qresource>
</RCC>
......@@ -10,6 +10,17 @@ ModelView{
addButton.text: "Add Prototype"
removeButton.text: "Remove Prototype"
sortModel: ListModel{
ListElement{
name: "Creation Date"
sortPropertyName: ""
}
ListElement{
name: "Name"
sortPropertyName: "name"
}
}
ListView{
clip:true
Layout.column: 2
......@@ -36,7 +47,7 @@ ModelView{
onTextChanged: modelData.name = text
}
}
model: modelView.currentModelData.channel
model: modelView.currentModelData ? modelView.currentModelData.channel : null
}
onAddClicked: ModelManager.addDevicePrototype("New DevicePrototype");
......
......@@ -19,6 +19,24 @@ ModelView{
addButton.text: "Add Device"
removeButton.text: "Remove Device"
property var placeOnMapCallback
sortModel: ListModel{
ListElement{
name: "Creation Date"
sortPropertyName: ""
}
ListElement{
name: "DMX Channel"
sortPropertyName: "startDMXChannel"
}
ListElement{
name: "Name"
sortPropertyName: "name"
}
ListElement{
name: "Prototype Name"
sortPropertyName: "prototype.name"
}
}
Text{
Layout.row: 2
......@@ -31,12 +49,12 @@ ModelView{
Layout.row: 2
Layout.column: 3
enabled: UserManagment.currentUser.havePermission(Permission.CHANGE_DEVICE_DMX_CHANNEL);
text: parent.currentModelData.startDMXChannel
text: parent.currentModelData ? parent.currentModelData.startDMXChannel : ""
validator: IntValidator{
bottom: 0
top:512
}
onTextChanged: parent.currentModelData.startDMXChannel = text.length?text:0
onTextChanged: if(parent.currentModelData) parent.currentModelData.startDMXChannel = text.length?text:0
}
Text{
Layout.row: 3
......@@ -48,7 +66,7 @@ ModelView{
Text{
Layout.row: 3
Layout.column: 3
text:parent.currentModelData.prototype.name
text: parent.currentModelData ? parent.currentModelData.prototype.name : ""
font.pixelSize: 15
TextUnderline{
extendetWidth:1
......@@ -72,9 +90,9 @@ ModelView{
TextInputField{
enabled: UserManagment.currentUser.havePermission(Permission.CHANGE_POSITION);
Layout.minimumWidth: 40
text:deviceModelView.currentModelData.position.x
text:deviceModelView.currentModelData ? deviceModelView.currentModelData.position.x : ""
validator: IntValidator{}
onTextChanged: deviceModelView.currentModelData.position.x = text.length?text:0
onTextChanged: if(deviceModelView.currentModelData) deviceModelView.currentModelData.position.x = text.length?text:0
}
Text{
Layout.leftMargin: 10
......@@ -84,12 +102,12 @@ ModelView{
TextInputField{
enabled: UserManagment.currentUser.havePermission(Permission.CHANGE_POSITION);
Layout.minimumWidth: 40
text: deviceModelView.currentItem ? deviceModelView.currentModelData.position.y : ""
text: deviceModelView.currentModelData ? deviceModelView.currentModelData.position.y : ""
validator: IntValidator{}
onTextChanged: deviceModelView.currentModelData.position.y = text.length?text:0
onTextChanged: if(deviceModelView.currentModelData) deviceModelView.currentModelData.position.y = text.length?text:0
}
Button{
visible: deviceModelView.currentItem ? deviceModelView.placeOnMapCallback && deviceModelView.currentModelData.position.x === -1 || deviceModelView.currentModelData.position.x === -1 : false
visible: deviceModelView.currentModelData ? deviceModelView.placeOnMapCallback && deviceModelView.currentModelData.position.x === -1 || deviceModelView.currentModelData.position.x === -1 : false
text: "Place on map"
onClicked: deviceModelView.placeOnMapCallback(deviceModelView.currentModelData)
height: implicitHeight - 15
......
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import custom.licht 1.0
import QtQuick.Controls.Material 2.3
import "components"
GridLayout{
......@@ -9,9 +11,11 @@ GridLayout{
rowSpacing: 5
columns: 4
rows: 4
id: root
signal addClicked()
signal removeClicked(var remove)
property alias model : listView.model
property alias model : sortedView.sourceModel
property var sortModel
property alias currentItem : listView.currentItem
property var currentModelData : listView.currentItem ? listView.currentItem.modelItemData : null
property alias addButton: buttonAdd
......@@ -29,7 +33,12 @@ GridLayout{
Layout.preferredWidth: Math.max(350,implicitWidth)
Layout.columnSpan: 2
Layout.rowSpan: parent.rows-1
clip: true
id:listView
model: SortedModelVectorView{
id: sortedView
}
delegate: ItemDelegate{
property var modelItemData: modelData
width: parent.width
......@@ -37,6 +46,50 @@ GridLayout{
onClicked: listView.currentIndex = index
}
headerPositioning: ListView.OverlayHeader
Component{
id: header
Pane {
Component.onCompleted: {
background.radius = 0;
}
width: listView.width
topPadding: 6
bottomPadding: 6
z: 2
Material.elevation: 4
RowLayout {
anchors.fill: parent
spacing: 8
Label{
text: "Sort by:"
}
ComboBox{
id: sortCommboBox
Layout.fillWidth: true
textRole: "name"
model: root.sortModel
property bool _firstTime: true
onCurrentIndexChanged: {
if(_firstTime){ // if we dont do that, we geht a weird bug that said we cant load a component (testet 5.12.3)
_firstTime = false;
return;
}
listView.model.sortPropertyName = model.get(currentIndex).sortPropertyName;
}
}
Button{
icon.source: sortedView.sortOrder === Qt.DescendingOrder ? "../icons/sort_order/sort-reverse-alphabetical-order.svg" : "../icons/sort_order/sort-by-alphabet.svg"
icon.color: Qt.rgba(.25,.25,.25,1)
onClicked: sortedView.sortOrder = sortedView.sortOrder === Qt.DescendingOrder ? Qt.AscendingOrder : Qt.DescendingOrder;
}
}
}
}
header: sortModel ? header : null
highlight: Rectangle{
color: "blue"
opacity: 0.7
......@@ -75,8 +128,8 @@ GridLayout{
Layout.column: 3
Layout.fillWidth: true
id:textName
text: listView.currentItem?currentModelData.name:""
onTextChanged: currentModelData.name = text
text: parent.currentModelData ? parent.currentModelData.name:""
onTextChanged: if(parent.currentModelData) parent.currentModelData.name = text
}
Label{
Layout.row: 1
......@@ -90,8 +143,8 @@ GridLayout{
Layout.column: 3
Layout.fillWidth: true
id:textDescription
text: listView.currentItem?currentModelData.description:""
onTextChanged: currentModelData.description = text
text: parent.currentModelData?parent.currentModelData.description:""
onTextChanged: if(parent.currentModelData) parent.currentModelData.description = text
}
......
......@@ -13,7 +13,20 @@ ModelView{
removeButton.text: "Remove Prototype"
onAddClicked: dialog.visible = true
onRemoveClicked: ModelManager.removeDmxProgramPrototype(remove);
sortModel: ListModel{
ListElement{
name: "Creation Date"
sortPropertyName: ""
}
ListElement{
name: "Name"
sortPropertyName: "name"
}
ListElement{
name: "Device Prototype"
sortPropertyName: "devicePrototype.name"
}
}
ListView{
clip:true
Layout.column: 2
......@@ -96,7 +109,7 @@ ModelView{
}
model: modelView.currentModelData.channelProgramms
model: modelView.currentModelData ? modelView.currentModelData.channelProgramms : null
}
......
......@@ -13,14 +13,23 @@ ModelView{
removeButton.text: "Remove Programm"
onAddClicked: ModelManager.addProgramm("New Programm");
onRemoveClicked: ModelManager.removeDmxProgram(remove);
sortModel: ListModel{
ListElement{
name: "Creation Date"
sortPropertyName: ""
}
ListElement{
name: "Name"
sortPropertyName: "name"
}
}
Label{
text: "Speed : "
}
TextInputField{
text: modelView.currentItem?modelView.currentModelData.speed:""
text: modelView.currentModelData ? modelView.currentModelData.speed:""
validator: DoubleValidator{}
onTextChanged: modelView.currentModelData.speed = text
onTextChanged: if(modelView.currentModelData) modelView.currentModelData.speed = text
}
Label{
text: "Time Distortion:"
......@@ -36,8 +45,8 @@ ModelView{
id:topTD
Layout.preferredHeight: 25
Layout.leftMargin: -10
checked: modelView.currentItem?modelView.currentModelData.timeDistortion.enabled:false
onCheckStateChanged: modelView.currentModelData.timeDistortion.enabled = checked
checked: modelView.currentModelData?modelView.currentModelData.timeDistortion.enabled:false
onCheckStateChanged: if(modelView.currentModelData) modelView.currentModelData.timeDistortion.enabled = checked
}
Label{
Layout.leftMargin: 6
......@@ -46,8 +55,8 @@ ModelView{
TextInputField{
Layout.fillWidth: true
validator: DoubleValidator{}
text: modelView.currentItem?modelView.currentModelData.timeDistortion.intervall:""
onTextChanged: {if(modelView.currentItem!==null)modelView.currentModelData.timeDistortion.intervall = text;}
text: modelView.currentModelData ? modelView.currentModelData.timeDistortion.intervall:""
onTextChanged: {if(modelView.currentModelData!==null)modelView.currentModelData.timeDistortion.intervall = text;}
}
Label{
Layout.leftMargin: 6
......@@ -58,8 +67,8 @@ ModelView{
Layout.rightMargin: 5
id:endTD
model:easingModel
currentIndex: modelView.currentItem?modelView.currentModelData.timeDistortion.distortionCurve.type:0
onCurrentIndexChanged: {if(modelView.currentItem!==null)modelView.currentModelData.timeDistortion.distortionCurve.type = currentIndex;}
currentIndex: modelView.currentModelData?modelView.currentModelData.timeDistortion.distortionCurve.type:0
onCurrentIndexChanged: {if(modelView.currentModelData!==null)modelView.currentModelData.timeDistortion.distortionCurve.type = currentIndex;}
}
Rectangle{
anchors.top: topTD.top
......@@ -133,7 +142,7 @@ ModelView{
}
}
model: modelView.currentItem?modelView.currentModelData.programs:null
model: modelView.currentModelData ? modelView.currentModelData.programs:null
highlight: Rectangle{
color: "blue"
opacity: 0.7
......
#include "sortedmodelview.h"
#include <dmx/device.h>
SortedModelVectorView::SortedModelVectorView(QObject *parent):QSortFilterProxyModel (parent)
{
// Used by Modelvector
setSortRole(Qt::UserRole + 1);
}
void SortedModelVectorView::setSortPropertyName(const QString &sortPropertyName){
this->sortPropertyName.clear();
sortPropertyNameAsStdStrings.clear();
for(const auto & s : sortPropertyName.split(".")){
if(s.isEmpty())
continue;
this->sortPropertyName.push_back(s);
sortPropertyNameAsStdStrings.push_back(s.toStdString());
}
sort(0);
invalidate();
if(!sortCalled){
sort();
}
}
QString SortedModelVectorView::getSortPropertyName() const{
......@@ -33,10 +39,19 @@ inline QVariant getValue(QObject * start, const std::vector<std::string> names){
return QVariant();
}
void SortedModelVectorView::setSortOrder(Qt::SortOrder order){
if(order != sortOrder){
sortOrder = order;
emit sortOrderChanged();
sort();
}
}
void SortedModelVectorView::sort(int column, Qt::SortOrder order){
//check if we can sort
if(sortPropertyName.empty()){
qWarning("For a SortedModelVectorView no sortPropertyName is set!");
if(sortPropertyNameAsStdStrings.empty()){
QSortFilterProxyModel::sort(column,order);
sortCalled = true;
return;
}
if(rowCount()<1)
......@@ -49,8 +64,9 @@ void SortedModelVectorView::sort(int column, Qt::SortOrder order){
if(auto p = value.value<QObject*>(); p != nullptr){
if(getValue(p,sortPropertyNameAsStdStrings).isValid()){
QSortFilterProxyModel::sort(column,order);
sortCalled = true;
}else{
qWarning("For a SortedModelVectorView the sortPropertyName does not exists!");
qWarning() << "For a SortedModelVectorView the sortPropertyName does not exists : " << getSortPropertyNameAsString();
}
}else{
qWarning("For a SortedModelVectorView the data for the current sortRole is not a QObject* !");
......@@ -58,7 +74,22 @@ void SortedModelVectorView::sort(int column, Qt::SortOrder order){
}
bool SortedModelVectorView::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const{
if(sortPropertyNameAsStdStrings.empty()){
return source_left.row() < source_right.row();
}
const auto left = getValue(source_left.data(sortRole()).value<QObject*>(),sortPropertyNameAsStdStrings);
const auto right = getValue(source_right.data(sortRole()).value<QObject*>(),sortPropertyNameAsStdStrings);
return left < right;
}
QString SortedModelVectorView::getSortPropertyNameAsString() const{
QString name;
for(const auto & s : sortPropertyName){
name += s;
name += ".";
}
if(name.isEmpty()){
return name;
}
return name.left(name.length()-1);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment