diff --git a/playground/models/CMakeLists.txt b/playground/models/CMakeLists.txt new file mode 100644 index 00000000..af17bb84 --- /dev/null +++ b/playground/models/CMakeLists.txt @@ -0,0 +1,8 @@ +############################################################################ +# QSkinny - Copyright (C) The authors +# SPDX-License-Identifier: BSD-3-Clause +############################################################################ + +qsk_add_example(models Window.h Window.cpp QskDataControlMapper.cpp QskDataControlMapper.h main.cpp) + +target_link_libraries(models PRIVATE Qt::Sql) \ No newline at end of file diff --git a/playground/models/QskDataControlMapper.cpp b/playground/models/QskDataControlMapper.cpp new file mode 100644 index 00000000..cc3fff1e --- /dev/null +++ b/playground/models/QskDataControlMapper.cpp @@ -0,0 +1,78 @@ +// +// Created by aldo on 27/01/21. +// + +#include "QskDataControlMapper.h" + +QskDataControlMapper::QskDataControlMapper() : m(nullptr){ + +} + +void QskDataControlMapper::addMapping(QskControl *widget, int section) { + if(widget) + addMapping(widget,section,widget->metaObject()->userProperty().name()); +} + +void QskDataControlMapper::addMapping(QskControl *widget, int section, const QByteArray &propertyName) { + Item item; + item.control=widget; + item.section=section; + item.property=propertyName; + item.index=m->index(currentIndex.row(),section); + items.append(item); +} + +void QskDataControlMapper::setModel(QAbstractItemModel *model) { + m=model; + currentIndex=QModelIndex(); + if(m) { + connect(m,&QAbstractItemModel::dataChanged,this, + &QskDataControlMapper::_dataChanged); + } +} + +bool QskDataControlMapper::qContainsIndex(const QModelIndex & idx, const QModelIndex & topLeft, const QModelIndex & bottomRight) +{ + return idx.row() >= topLeft.row() && idx.row() <= bottomRight.row() + && idx.column() >= topLeft.column() && idx.column() <= bottomRight.column(); +} + +void QskDataControlMapper::_dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector &) +{ + for (auto& x : items) { + if (qContainsIndex(x.index, topLeft, bottomRight)) { + populate(x); + } + } +} + +void QskDataControlMapper::populate(QskDataControlMapper::Item & x) +{ + x.control->setProperty(x.property, + m->index(currentIndex.row(),x.section).data(Qt::EditRole)); +} + +void QskDataControlMapper::populate() +{ + for (auto& x : items) { + populate(x); + } +} + +void QskDataControlMapper::submit() { + if(!m) + return; + for(auto & x : items) { + m->setData(m->index(currentIndex.row(), x.section), + x.control->property(x.property)); + } +} + +void QskDataControlMapper::setCurrentIndex(int index) { + if(!m) + return; + currentIndex=m->index(index,0); + populate(); +} + +#include "moc_QskDataControlMapper.cpp" diff --git a/playground/models/QskDataControlMapper.h b/playground/models/QskDataControlMapper.h new file mode 100644 index 00000000..3d20dab5 --- /dev/null +++ b/playground/models/QskDataControlMapper.h @@ -0,0 +1,54 @@ +#ifndef QSKDATACONTROLMAPPER_H +#define QSKDATACONTROLMAPPER_H + +#include +#include + +class QskDataControlMapper : public QObject { + Q_OBJECT + +private: + + struct Item; + +public: + + QskDataControlMapper(); + + void addMapping(QskControl* widget, int section); + void addMapping(QskControl* widget, int section, const QByteArray &propertyName); + + void setModel(QAbstractItemModel* model); + + static bool qContainsIndex(const QModelIndex &idx, const QModelIndex &topLeft, + const QModelIndex &bottomRight); + + void _dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &); + + void populate(QskDataControlMapper::Item & x); + + void populate (); + + void submit(); + + void setCurrentIndex(int index); + +private: + + QList items; + + QAbstractItemModel* m; + QPersistentModelIndex currentIndex; + + struct Item { + QPointer control; + int section; + QByteArray property; + QPersistentModelIndex index; + }; + +}; + + + +#endif //QSKDATACONTROLMAPPER_H \ No newline at end of file diff --git a/playground/models/Window.cpp b/playground/models/Window.cpp new file mode 100644 index 00000000..2fa19a15 --- /dev/null +++ b/playground/models/Window.cpp @@ -0,0 +1,67 @@ +/****************************************************************************** + * QSkinny - Copyright (C) The authors + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "Window.h" + +#include "QskSpinBox.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include + +Window::Window( ) + +{ + auto db = QSqlDatabase::addDatabase("QSQLITE"); + db.setDatabaseName(":memory:"); + db.open(); + QSqlQuery q(db); + q.exec("create table test(id integer,value text);"); + q.exec("insert into test (id,value) values (1,'HELLO');"); + q.exec("insert into test (id,value) values (2,'WORLD');"); + + auto table = new QSqlTableModel (nullptr,db); + table->setTable( "test" ); + table->select(); + + auto txt = new QskTextInput(); + auto spin = new QskSpinBox(); + + auto mapper = new QskDataControlMapper(); + mapper->setModel(table); + /* + Not needed if we set USER true for the corresponding Q_PROPERTY in QskBoundedInput and QskTextInput + maybe could be done also for other controls + mapper->addMapping(spin, 0,"value"); + mapper->addMapping(txt, 1, "text"); + */ + mapper->addMapping(spin, 0); // needs USER=true for value in QskBoundedInput + mapper->addMapping(txt, 1); // needs USER=true for text in QskTextInput + + mapper->setCurrentIndex(0); + + auto v = new QskLinearBox(Qt::Vertical); + v->addSpacer( 0,100 ); + v->addItem( spin ); + v->addItem( txt ); + addItem(v); + auto h = new QskLinearBox(Qt::Horizontal); + auto prev = new QskPushButton("<",h); + auto next = new QskPushButton(">",h); + connect(prev,&QskPushButton::clicked,[=]() { mapper->setCurrentIndex( 0 ); }); + connect(next,&QskPushButton::clicked,[=]() { mapper->setCurrentIndex( 1 ); }); + v->addItem(h); + v->addSpacer( 0,100 ); +} + + +#include "moc_Window.cpp" diff --git a/playground/models/Window.h b/playground/models/Window.h new file mode 100644 index 00000000..2ededbbc --- /dev/null +++ b/playground/models/Window.h @@ -0,0 +1,22 @@ +/****************************************************************************** + * QSkinny - Copyright (C) The authors + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#pragma once + +#include +#include + +class QskDialogButtonBox; +class QskLinearBox; + +class Window : public QskWindow +{ + Q_OBJECT + + public: + Window(); + + +}; diff --git a/playground/models/main.cpp b/playground/models/main.cpp new file mode 100644 index 00000000..5b0476bb --- /dev/null +++ b/playground/models/main.cpp @@ -0,0 +1,35 @@ +/****************************************************************************** + * QSkinny - Copyright (C) The authors + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "Window.h" + +#include + +#include +#include + +#include + +int main( int argc, char* argv[] ) +{ +#ifdef ITEM_STATISTICS + QskObjectCounter counter( true ); +#endif + + QGuiApplication app( argc, argv ); + + SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts ); + + Window window; + window.resize( 600, 400 ); + + auto focusIndicator = new QskFocusIndicator(); + focusIndicator->setObjectName( "FocusIndicator" ); + + window.addItem( focusIndicator ); + window.show(); + + return app.exec(); +}