added some controls

This commit is contained in:
Dorian Zedler 2020-10-11 21:01:21 +02:00
parent fb1aeaf67c
commit 4d0e9bc74f
Signed by: dorian
GPG key ID: D3B255CB8BC7CD37
13 changed files with 582 additions and 22 deletions

View file

@ -11,10 +11,12 @@ TEMPLATE = app
SOURCES += \ SOURCES += \
main.cpp \ main.cpp \
omobidisplaybackend.cpp omobidisplaybackend.cpp \
omobidisplaytextmodel.cpp
HEADERS += \ HEADERS += \
omobidisplaybackend.h omobidisplaybackend.h \
omobidisplaytextmodel.h
RESOURCES += \ RESOURCES += \
ressources/qml/qml.qrc \ ressources/qml/qml.qrc \

@ -1 +1 @@
Subproject commit 60d10f056b53b1816bd97559ad2d7527bbc158a8 Subproject commit 0b053eaa88ffdcc0b32e533904e5e266b8e62fb3

View file

@ -4,6 +4,7 @@
#include <qbluetoothleuart.h> #include <qbluetoothleuart.h>
#include "omobidisplaybackend.h" #include "omobidisplaybackend.h"
#include "omobidisplaytextmodel.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@ -12,6 +13,7 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
qmlRegisterType<OmobiDisplayBackend>("de.itsblue.omobidisplayapp", 1, 0, "OmobiDisplayBackend"); qmlRegisterType<OmobiDisplayBackend>("de.itsblue.omobidisplayapp", 1, 0, "OmobiDisplayBackend");
qmlRegisterUncreatableType<OmobiDisplayTextModel>("de.itsblue.omobidisplayapp", 1, 0, "OmobiDisplayTextModel", "OmobiDisplayTextModel cannot be created");
QBluetoothLeUart::init(); QBluetoothLeUart::init();
QQuickStyle::setStyle("Material"); QQuickStyle::setStyle("Material");

View file

@ -3,11 +3,13 @@
OmobiDisplayBackend::OmobiDisplayBackend(QObject *parent) : QObject(parent) OmobiDisplayBackend::OmobiDisplayBackend(QObject *parent) : QObject(parent)
{ {
this->ble = new QBluetoothLeUart(); this->ble = new QBluetoothLeUart();
this->displayTextModel = new OmobiDisplayTextModel(this);
connect(this->ble, &QBluetoothLeUart::stateChanged, this, &OmobiDisplayBackend::handleBluetoothStateChange); connect(this->ble, &QBluetoothLeUart::stateChanged, this, &OmobiDisplayBackend::handleBluetoothStateChange);
connect(this->ble, &QBluetoothLeUart::foundNewDevice, this, &OmobiDisplayBackend::handleFoundNewDevice); connect(this->ble, &QBluetoothLeUart::foundNewDevice, this, &OmobiDisplayBackend::handleFoundNewDevice);
connect(this->ble, &QBluetoothLeUart::dataReceived, this, &OmobiDisplayBackend::DataHandler); connect(this->ble, &QBluetoothLeUart::dataReceived, this, &OmobiDisplayBackend::DataHandler);
connect(this->ble, &QBluetoothLeUart::connectedToDevice, this, &OmobiDisplayBackend::handleBluetoothDeviceConected); connect(this->ble, &QBluetoothLeUart::connectedToDevice, this, &OmobiDisplayBackend::handleBluetoothDeviceConected);
connect(this->displayTextModel, &OmobiDisplayTextModel::dataChanged, this, &OmobiDisplayBackend::handleDisplayTextModelDataChanged);
this->setState(Idle); this->setState(Idle);
this->ble->startScanningForDevices(); this->ble->startScanningForDevices();
@ -46,7 +48,6 @@ void OmobiDisplayBackend::handleBluetoothStateChange(QBluetoothLeUart::Bluetooth
} }
case QBluetoothLeUart::Connected: case QBluetoothLeUart::Connected:
{ {
this->setState(Connected);
break; break;
} }
} }
@ -54,6 +55,13 @@ void OmobiDisplayBackend::handleBluetoothStateChange(QBluetoothLeUart::Bluetooth
void OmobiDisplayBackend::handleBluetoothDeviceConected() { void OmobiDisplayBackend::handleBluetoothDeviceConected() {
this->ble->sendData("Hallihallo ich bin Julia Mueller"); this->ble->sendData("Hallihallo ich bin Julia Mueller");
// get the existing model data!
// TODO: implement some communication!
QString currentDisplayText = "[[],[]]";
this->setState(Connected);
} }
void OmobiDisplayBackend::handleFoundNewDevice(QBluetoothLeUartDevice* device) { void OmobiDisplayBackend::handleFoundNewDevice(QBluetoothLeUartDevice* device) {
@ -66,10 +74,20 @@ void OmobiDisplayBackend::DataHandler(const QString &s){
} }
void OmobiDisplayBackend::handleDisplayTextModelDataChanged() {
qDebug() << "MODEL DATA CHANGED!";
}
QBluetoothLeUart* OmobiDisplayBackend::getBleController() { QBluetoothLeUart* OmobiDisplayBackend::getBleController() {
return this->ble; return this->ble;
} }
OmobiDisplayTextModel* OmobiDisplayBackend::getDisplayTextModel() {
return this->displayTextModel;
}
OmobiDisplayBackend::OmobiDisplayAppState OmobiDisplayBackend::getState() { OmobiDisplayBackend::OmobiDisplayAppState OmobiDisplayBackend::getState() {
return this->state; return this->state;
} }

View file

@ -3,12 +3,15 @@
#include <QObject> #include <QObject>
#include <qbluetoothleuart.h> #include <qbluetoothleuart.h>
#include <omobidisplaytextmodel.h>
class OmobiDisplayBackend : public QObject class OmobiDisplayBackend : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QBluetoothLeUart* bleController READ getBleController NOTIFY bleControllerChanged) Q_PROPERTY(QBluetoothLeUart* bleController READ getBleController NOTIFY bleControllerChanged)
Q_PROPERTY(OmobiDisplayAppState state READ getState WRITE setState NOTIFY stateChanged) Q_PROPERTY(OmobiDisplayAppState state READ getState WRITE setState NOTIFY stateChanged)
Q_PROPERTY(OmobiDisplayTextModel* displayTextModel READ getDisplayTextModel NOTIFY displayTextModelChanged)
public: public:
explicit OmobiDisplayBackend(QObject *parent = nullptr); explicit OmobiDisplayBackend(QObject *parent = nullptr);
@ -24,11 +27,13 @@ public:
private: private:
OmobiDisplayAppState state; OmobiDisplayAppState state;
QBluetoothLeUart *ble; QBluetoothLeUart *ble;
OmobiDisplayTextModel* displayTextModel;
public slots: public slots:
Q_INVOKABLE void startScanning(); Q_INVOKABLE void startScanning();
Q_INVOKABLE QBluetoothLeUart* getBleController(); Q_INVOKABLE QBluetoothLeUart* getBleController();
Q_INVOKABLE OmobiDisplayAppState getState(); Q_INVOKABLE OmobiDisplayAppState getState();
Q_INVOKABLE OmobiDisplayTextModel* getDisplayTextModel();
private slots: private slots:
void handleBluetoothStateChange(QBluetoothLeUart::BluetoothLeUartState state); void handleBluetoothStateChange(QBluetoothLeUart::BluetoothLeUartState state);
@ -36,11 +41,14 @@ private slots:
void DataHandler(const QString &s); void DataHandler(const QString &s);
void handleBluetoothDeviceConected(); void handleBluetoothDeviceConected();
void handleDisplayTextModelDataChanged();
void setState(OmobiDisplayAppState state); void setState(OmobiDisplayAppState state);
signals: signals:
void stateChanged(); void stateChanged();
void bleControllerChanged(); void bleControllerChanged();
void displayTextModelChanged();
}; };

View file

@ -0,0 +1,117 @@
#include "omobidisplaytextmodel.h"
OmobiDisplayTextModel::OmobiDisplayTextModel(QObject* parent) : QAbstractListModel(parent)
{
QMap<int, QVariant> sampleText1 = {
{ TextRole, "itsblue.de" },
{ ActiveRole, true },
{ RuntimeRole, 20 },
{ ColorRole, "blue" },
{ AlignmentRole, "center" },
{ ScrollRole, true },
{ ScrollCountRole, 20 }
};
QMap<int, QVariant> sampleText2 = {
{ TextRole, "Das ist ein tolles Display" },
{ ActiveRole, false },
{ RuntimeRole, 10 },
{ ColorRole, "green" },
{ AlignmentRole, "left" },
{ ScrollRole, true },
{ ScrollCountRole, 10 }
};
this->texts.append(sampleText1);
this->texts.append(sampleText2);
}
int OmobiDisplayTextModel::rowCount(const QModelIndex &) const
{
return this->texts.length();
}
QVariant OmobiDisplayTextModel::data(const QModelIndex &index, int role) const
{
if (index.row() < rowCount())
if(this->texts[index.row()].contains(role))
return this->texts[index.row()][role];
return QVariant();
}
QHash<int, QByteArray> OmobiDisplayTextModel::roleNames() const
{
static const QHash<int, QByteArray> roles {
{ TextRole, "text" },
{ ActiveRole, "active" },
{ RuntimeRole, "runtime" },
{ ColorRole, "color" },
{ AlignmentRole, "alignment" },
{ ScrollRole, "scroll" },
{ ScrollCountRole, "scrollCount" }
};
return roles;
}
void OmobiDisplayTextModel::append(
QString text,
bool active,
unsigned int runtime,
QString color,
QString alignment,
bool scroll,
unsigned int scrollCount
) {
QMap<int, QVariant> roles = {
{ TextRole, text },
{ ActiveRole, active },
{ RuntimeRole, runtime },
{ ColorRole, color },
{ AlignmentRole, alignment },
{ ScrollRole, scroll },
{ ScrollCountRole, scrollCount }
};
this->append(roles);
}
void OmobiDisplayTextModel::append(const QMap<int, QVariant> &roles) {
int row = this->texts.length();
this->beginInsertRows(QModelIndex(), row, row);
this->texts.insert(row, roles);
this->endInsertRows();
}
bool OmobiDisplayTextModel::setData(const QModelIndex &index, const QVariant &value, int role) {
if (index.row() >= rowCount() || !this->texts[index.row()].contains(role))
return false;
if(this->texts[index.row()][role] == value)
return true;
this->texts[index.row()][role] = value;
emit dataChanged(index, index);
return QAbstractItemModel::setData(index, value, role);
}
void OmobiDisplayTextModel::remove(int row)
{
if (row < 0 || row >= this->rowCount())
return;
beginRemoveRows(QModelIndex(), row, row);
this->texts.removeAt(row);
endRemoveRows();
}
void OmobiDisplayTextModel::clear() {
for(int i = 0; i < this->texts.length(); i++)
this->remove(i);
}
QString OmobiDisplayTextModel::getAsJson() {
}

View file

@ -0,0 +1,58 @@
#ifndef OMOBIDISPLAYTEXTMODEL_H
#define OMOBIDISPLAYTEXTMODEL_H
#include <QAbstractListModel>
#include <QObject>
#include <QColor>
#include <QDebug>
class OmobiDisplayTextModel : public QAbstractListModel
{
Q_OBJECT
public:
friend class OmobiDisplayBackend;
enum QBluetoothLeUartDeviceModelRole {
TextRole = Qt::DisplayRole,
ActiveRole,
RuntimeRole,
ColorRole,
AlignmentRole,
ScrollRole,
ScrollCountRole
};
Q_ENUM(QBluetoothLeUartDeviceModelRole)
int rowCount(const QModelIndex & = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
QHash<int, QByteArray> roleNames() const;
Q_INVOKABLE void append(
QString text,
bool active,
unsigned int runtime,
QString color,
QString alignment,
bool scroll,
unsigned int scrollCount
);
void append(const QMap<int, QVariant> &roles);
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
Q_INVOKABLE void remove(int row);
protected:
OmobiDisplayTextModel(QObject* parent = nullptr);
void reloadFromJson(QString json);
QString getAsJson();
void clear();
private:
QList<QMap<int, QVariant>> texts;
};
#endif // OMOBIDISPLAYTEXTMODEL_H

View file

@ -0,0 +1,93 @@
import QtQuick 2.0
import QtQuick.Controls 2.0
ItemDelegate {
id: control
property bool expanded: false
property Component expandedComponent: Component {
Rectangle {
implicitHeight: 100
color: "red"
}
}
height: 70 + expandedItemContainer.height
contentItem: Item {}
state: expanded ? "open":"closed"
Item {
id: expandedItemContainer
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
margins: 5
}
clip: true
height: control.state === "open" && expandedItemLoader.status === Loader.Ready && expandedItemLoader.item !== undefined ? expandedItemLoader.item.implicitHeight:0
Behavior on height {
NumberAnimation {
duration: 200
}
}
Loader {
id: expandedItemLoader
anchors.centerIn: parent
width: parent.width
onEnabledChanged: {
if(enabled){
sourceComponent = control.expandedComponent
}
else {
hideDelayPa.start()
}
}
anchors.fill: parent
PauseAnimation {
id: hideDelayPa
duration: 200
onRunningChanged: {
if(!running && !expandedItemLoader.enabled){
expandedItemLoader.sourceComponent = undefined
}
}
}
}
}
states: [
State {
name: "closed"
PropertyChanges {
target: expandedItemLoader
enabled: false
}
},
State {
name: "opened"
PropertyChanges {
target: expandedItemLoader
enabled: true
}
}
]
}

View file

@ -7,22 +7,7 @@ import de.itsblue.bluetoothleuart 1.0
Page { Page {
id: root id: root
ColumnLayout { DisplayTextModelListView {
anchors.fill: parent anchors.fill: parent
anchors.margins: 10
TextField {
id: newTextInput
Layout.fillWidth: true
Layout.preferredHeight: 50
}
Button {
Layout.fillWidth: true
onClicked: {
backend.bleController.sendData(newTextInput.text)
}
}
} }
} }

View file

@ -0,0 +1,52 @@
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
CollapsableItemDelegate {
id: control
expandedComponent: Component {
Item {
implicitHeight: 200
RowLayout {
anchors.fill: parent
TextField {
id: textTextInput
Layout.preferredWidth: parent.width
Layout.preferredHeight: 50
text: model.text
}
Button {
Layout.preferredWidth: parent.width
Layout.preferredHeight: 50
text: "apply"
onClicked: {
model.text = textTextInput.text
}
}
}
}
}
Text {
id: labelText
anchors {
top: parent.top
left: parent.left
right: parent.right
margins: 5
}
height: 70 - 2 * anchors.margins
verticalAlignment: Text.AlignVCenter
font.pixelSize: height * 0.4
text: model.text
}
}

View file

@ -0,0 +1,220 @@
import QtQuick 2.0
import QtQuick.Controls 2.9
import QtQuick.Layouts 1.0
import de.itsblue.omobidisplayapp 1.0
import QtQuick.Controls.Material 2.0
ListView {
id: control
model: backend.displayTextModel
delegate: DisplayTextDelegate {
id: delegate
width: control.width
onClicked: {
popup.edit(model)
}
}
RoundButton {
anchors {
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
bottomMargin: height * 0.25
}
height: parent.width * 0.15
width: height
text: ""
onClicked: popup.add()
Text {
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: height * 0.4
text: "+"
}
}
Dialog {
id: popup
property bool editing
property var editingModel
parent: Overlay.overlay
x: (parent.width - width) / 2
y: (parent.height - height) / 2
width: parent.width * 0.6
title: editing ? "Edit item" : "New item"
standardButtons: Dialog.Ok | Dialog.Cancel
modal: true
onAccepted: {
if(editing) {
editingModel.active = activeSwitch.checked
editingModel.text = textTextField.text
editingModel.runtime = runtimeSpinBox.value
editingModel.color = colorComboBox.currentText
editingModel.alignment = alignmentComboBox.currentText
editingModel.scroll = scrollSwitch.checked
editingModel.scrollCount = scrollCountSpinBox.value
}
else {
control.model.append(textTextField.text,
activeSwitch.checked,
runtimeSpinBox.value,
colorComboBox.currentText,
alignmentComboBox.currentText,
scrollSwitch.checked,
scrollCountSpinBox.value
)
}
}
contentItem: GridLayout {
property int rowHeight: 50
columns: 2
columnSpacing: 10
Label {
font.bold: true
text: "Active:"
}
Switch {
id: activeSwitch
Layout.fillWidth: true
}
Label {
font.bold: true
text: "Text:"
}
TextField {
id: textTextField
Layout.fillWidth: true
}
Label {
font.bold: true
text: "Runtime (in s):"
}
SpinBox {
id: runtimeSpinBox
Layout.fillWidth: true
}
Label {
font.bold: true
text: "Color:"
}
ComboBox {
id: colorComboBox
Layout.fillWidth: true
model: ["white", "blue", "red", "green"]
}
Label {
font.bold: true
text: "Alignment:"
}
ComboBox {
id: alignmentComboBox
Layout.fillWidth: true
model: ["left", "center", "right"]
}
Label {
font.bold: true
text: "Scroll:"
}
Switch {
id: scrollSwitch
Layout.fillWidth: true
}
Label {
font.bold: true
text: "Scroll count:"
}
SpinBox {
id: scrollCountSpinBox
Layout.fillWidth: true
}
Button {
visible: popup.editing
Layout.preferredWidth: parent.width * 0.5
Layout.alignment: Layout.Center
Material.background: Material.Red
Material.foreground: "white"
text: "delete"
onClicked: {
control.model.remove(0)
popup.close()
}
}
}
function edit(model) {
editingModel = model
editing = true
reset()
activeSwitch.checked = editingModel.active
textTextField.text = editingModel.text
runtimeSpinBox.value = editingModel.runtime
colorComboBox.currentIndex = colorComboBox.model.indexOf(editingModel.color)
alignmentComboBox.currentIndex = alignmentComboBox.model.indexOf(editingModel.alignment)
scrollSwitch.checked = editingModel.scroll
scrollCountSpinBox.value = editingModel.scrollCount
open()
}
function add() {
editing = false
reset()
open()
}
function reset() {
activeSwitch.checked = false
textTextField.text = ""
runtimeSpinBox.value = 0
colorComboBox.currentIndex = 0
alignmentComboBox.currentIndex = 0
scrollSwitch.checked = false
scrollCountSpinBox.value = 0
}
}
}

View file

@ -47,10 +47,12 @@ ApplicationWindow {
property Component currentComponent property Component currentComponent
onCurrentComponentChanged: { onCurrentComponentChanged: {
if(currentComponent != currentItem) //if(currentComponent != currentItem)
mainStack.replace(currentComponent) //mainStack.replace(currentComponent)
} }
initialItem: connectedPageComp
Component { Component {
id: connectPageComp id: connectPageComp
ConnectPage { ConnectPage {

View file

@ -3,5 +3,8 @@
<file>main.qml</file> <file>main.qml</file>
<file>ConnectPage.qml</file> <file>ConnectPage.qml</file>
<file>ConnectedPage.qml</file> <file>ConnectedPage.qml</file>
<file>DisplayTextDelegate.qml</file>
<file>CollapsableItemDelegate.qml</file>
<file>DisplayTextModelListView.qml</file>
</qresource> </qresource>
</RCC> </RCC>