- finished implementing protocol
- added Initializing and Loading states - added color picker
This commit is contained in:
parent
6fbae42867
commit
ce6d436c85
13 changed files with 518 additions and 116 deletions
|
@ -4,12 +4,17 @@ OmobiDisplayBackend::OmobiDisplayBackend(QObject *parent) : QObject(parent)
|
|||
{
|
||||
this->ble = new QBluetoothLeUart();
|
||||
this->displayTextModel = new OmobiDisplayTextModel(this);
|
||||
this->textSetsBuffer.clear();
|
||||
this->displayBrightness = -1;
|
||||
this->waitingCommands = 0;
|
||||
|
||||
connect(this->ble, &QBluetoothLeUart::stateChanged, this, &OmobiDisplayBackend::handleBluetoothStateChange);
|
||||
connect(this->ble, &QBluetoothLeUart::foundNewDevice, this, &OmobiDisplayBackend::handleFoundNewDevice);
|
||||
connect(this->ble, &QBluetoothLeUart::dataReceived, this, &OmobiDisplayBackend::DataHandler);
|
||||
connect(this->ble, &QBluetoothLeUart::dataReceived, this, &OmobiDisplayBackend::handleBluetoothDataReceived);
|
||||
connect(this->ble, &QBluetoothLeUart::connectedToDevice, this, &OmobiDisplayBackend::handleBluetoothDeviceConected);
|
||||
connect(this->displayTextModel, &OmobiDisplayTextModel::dataChanged, this, &OmobiDisplayBackend::handleDisplayTextModelDataChanged);
|
||||
connect(this->displayTextModel, &OmobiDisplayTextModel::rowsInserted, this, &OmobiDisplayBackend::handleDisplayTextModelRowsInserted);
|
||||
connect(this->displayTextModel, &OmobiDisplayTextModel::rowsRemoved, this, &OmobiDisplayBackend::handleDisplayTextModelRowsRemoved);
|
||||
|
||||
this->setState(Idle);
|
||||
this->ble->startScanningForDevices();
|
||||
|
@ -54,96 +59,145 @@ void OmobiDisplayBackend::handleBluetoothStateChange(QBluetoothLeUart::Bluetooth
|
|||
}
|
||||
|
||||
void OmobiDisplayBackend::handleBluetoothDeviceConected() {
|
||||
this->ble->sendData("GET_TEXTS");
|
||||
this->ble->sendData("GET_BRIGHTNESS");
|
||||
this->setState(Initing);
|
||||
|
||||
// get the existing model data!
|
||||
// TODO: implement some communication!
|
||||
|
||||
QString currentDisplayText = "[[],[]]";
|
||||
|
||||
this->setState(Connected);
|
||||
// tell display to send over existing model data
|
||||
this->sendBluetoothCommand(GetAllTextSetsCommand);
|
||||
this->sendBluetoothCommand(GetDisplayBrightnessCommand);
|
||||
}
|
||||
|
||||
void OmobiDisplayBackend::handleFoundNewDevice(QBluetoothLeUartDevice* device) {
|
||||
qDebug() << "Found a device: name: " << device->getName() << " address: " << device->getAddress();
|
||||
}
|
||||
|
||||
void OmobiDisplayBackend::DataHandler(QString s){
|
||||
qDebug() << "New data: " << s;
|
||||
if(s.startsWith("GET_TEXTS:")) {
|
||||
void OmobiDisplayBackend::handleDisplayTextModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) {
|
||||
|
||||
qDebug() << "Data changed: topLeft: " << topLeft << " bottomRight: " << bottomRight << " roles: " << roles;
|
||||
|
||||
for(int role : roles)
|
||||
this->updateDisplayTextSetParameter(topLeft.row(), role);
|
||||
}
|
||||
|
||||
void OmobiDisplayBackend::handleDisplayTextModelRowsInserted(const QModelIndex &parent, int first, int last) {
|
||||
qDebug() << "Rows inserted: parent: " << parent << " first: " << first << " last " << last;
|
||||
for(int i = 0; i < OmobiDisplayTextModel::OmobiDisplayTextModelRoleCount; i++) {
|
||||
this->updateDisplayTextSetParameter(first, i);
|
||||
}
|
||||
}
|
||||
|
||||
void OmobiDisplayBackend::handleDisplayTextModelRowsRemoved(const QModelIndex &parent, int first, int last) {
|
||||
qDebug() << "Rows removed: parent: " << parent << " first: " << first << " last " << last;
|
||||
// Setting Text to "" will delete the item
|
||||
this->updateDisplayTextSetParameter(first, OmobiDisplayTextModel::TextRole, "");
|
||||
}
|
||||
|
||||
|
||||
void OmobiDisplayBackend::sendBluetoothCommand(OmobiDisplayCommand command, QVariant data) {
|
||||
QVariantMap commandMap = {
|
||||
{"header", command},
|
||||
{"data", data}
|
||||
};
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromVariant(commandMap);
|
||||
|
||||
qDebug() << "Sending command: \n" << qPrintable(doc.toJson(QJsonDocument::Indented));
|
||||
|
||||
this->waitingCommands ++;
|
||||
|
||||
if(this->state == Connected)
|
||||
this->setState(Loading);
|
||||
|
||||
this->ble->sendData(doc.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
void OmobiDisplayBackend::handleBluetoothDataReceived(QString s){
|
||||
qDebug() << "New data: \n" << qPrintable(s);
|
||||
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(s.replace("GET_TEXTS:", "").toUtf8(), &parseError);
|
||||
QJsonDocument doc = QJsonDocument::fromJson(s.toUtf8(), &parseError);
|
||||
|
||||
if(parseError.error != QJsonParseError::NoError)
|
||||
return;
|
||||
|
||||
QList<QMap<int, QVariant>> texts;
|
||||
OmobiDisplayCommand header = OmobiDisplayCommand(doc.toVariant().toMap()["header"].toInt());
|
||||
QVariantMap data = doc.toVariant().toMap()["data"].toMap();
|
||||
OmobiDisplayStatusCode status = OmobiDisplayStatusCode(doc.toVariant().toMap()["status"].toInt());
|
||||
|
||||
for(QVariant textMap : doc.toVariant().toList()) {
|
||||
QMap<int, QVariant> text;
|
||||
switch (header) {
|
||||
case GetAllTextSetsCommand: {
|
||||
// indicates that all existing txt sets have been sent over after GetAllTextSetsCommand was called
|
||||
if(status != Success)
|
||||
// TODO: handle error
|
||||
break;
|
||||
|
||||
static const QMap<QString, int> keyTranslations {
|
||||
{ "text", OmobiDisplayTextModel::TextRole },
|
||||
{ "active", OmobiDisplayTextModel::ActiveRole },
|
||||
{ "runtime", OmobiDisplayTextModel::RuntimeRole },
|
||||
{ "color", OmobiDisplayTextModel::ColorRole },
|
||||
{ "alignment", OmobiDisplayTextModel::AlignmentRole },
|
||||
{ "scroll", OmobiDisplayTextModel::ScrollRole },
|
||||
{ "scrollSpeed", OmobiDisplayTextModel::ScrollSpeedRole },
|
||||
{ "scrollCount", OmobiDisplayTextModel::ScrollCountRole },
|
||||
{ "index", OmobiDisplayTextModel::IndexRole }
|
||||
};
|
||||
this->displayTextModel->maximumTextLength = data["maximumTextLength"].toInt();
|
||||
this->displayTextModel->maximumTextSets = data["maximumTextSets"].toInt();
|
||||
|
||||
for(QString key : textMap.toMap().keys()) {
|
||||
if(keyTranslations.contains(key)) {
|
||||
if(key == "color") {
|
||||
QVariantMap colorMap = textMap.toMap()[key].toMap();
|
||||
QColor color(colorMap["r"].toInt(), colorMap["g"].toInt(), colorMap["b"].toInt());
|
||||
text.insert(keyTranslations[key], color.name());
|
||||
this->displayTextModel->setTexts(this->textSetsBuffer);
|
||||
this->textSetsBuffer.clear();
|
||||
|
||||
this->refreshLoadingState();
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
text.insert(keyTranslations[key], textMap.toMap()[key]);
|
||||
case GetTextSetParameterCommand: {
|
||||
|
||||
int index = data["index"].toInt();
|
||||
|
||||
if(index < 0)
|
||||
return;
|
||||
|
||||
if(this->textSetsBuffer.length() <= index)
|
||||
this->textSetsBuffer.append(QMap<int, QVariant>());
|
||||
|
||||
int parameter = data["parameter"].toInt();
|
||||
|
||||
if(!this->textSetsBuffer[index].contains(parameter))
|
||||
this->textSetsBuffer[index].insert(parameter, QVariant());
|
||||
|
||||
this->textSetsBuffer[index][parameter] = data["value"].toString();
|
||||
|
||||
if(this->state != Initing)
|
||||
this->refreshLoadingState();
|
||||
|
||||
break;
|
||||
}
|
||||
case GetDisplayBrightnessCommand: {
|
||||
this->setDisplayBrightness(data["displayBrightness"].toInt());
|
||||
this->refreshLoadingState();
|
||||
break;
|
||||
}
|
||||
case SetTextSetParameterCommand: {
|
||||
// TODO: Error handling
|
||||
this->refreshLoadingState();
|
||||
break;
|
||||
}
|
||||
case SetDisplayBrightnessCommand: {
|
||||
// TODO: Error handling
|
||||
this->refreshLoadingState();
|
||||
break;
|
||||
}
|
||||
|
||||
texts.append(text);
|
||||
}
|
||||
|
||||
this->displayTextModel->setTexts(texts);
|
||||
}
|
||||
else if(s.startsWith("GET_BRIGHTNESS:")) {
|
||||
this->displayBrightness = s.replace("GET_BRIGHTNESS:", "").toInt();
|
||||
emit this->displayBrightnessChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OmobiDisplayBackend::handleDisplayTextModelDataChanged() {
|
||||
void OmobiDisplayBackend::updateDisplayTextSetParameter(int index, int parameter) {
|
||||
this->updateDisplayTextSetParameter(index, parameter, this->displayTextModel->data(index, parameter).toString());
|
||||
}
|
||||
|
||||
QVariantList textList;
|
||||
void OmobiDisplayBackend::updateDisplayTextSetParameter(int index, int parameter, QString value) {
|
||||
if(this->state == Initing)
|
||||
return;
|
||||
qDebug() << "Updating data at index: " << index << " parameter: " << parameter << " and value: " << value;
|
||||
|
||||
for(QMap<int, QVariant> text : this->displayTextModel->getTexts()) {
|
||||
QVariantHash textMap;
|
||||
QVariantMap dataMap = {
|
||||
{"index", index},
|
||||
{"parameter", parameter},
|
||||
{"value", value}
|
||||
};
|
||||
|
||||
for(int key : text.keys()) {
|
||||
if(key == OmobiDisplayTextModel::ColorRole) {
|
||||
QColor color = QColor(text[key].toString());
|
||||
color = color.toRgb();
|
||||
QVariantMap colorMap = {{"r", color.red()}, {"g", color.green()}, {"b", color.blue()}};
|
||||
}
|
||||
else
|
||||
textMap.insert(this->displayTextModel->roleNames()[key], text[key]);
|
||||
}
|
||||
|
||||
textList.append(textMap);
|
||||
}
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromVariant(textList);
|
||||
|
||||
qDebug() << doc.toJson(QJsonDocument::Indented);
|
||||
|
||||
this->ble->sendData("SET_TEXTS:" + doc.toJson(QJsonDocument::Compact));
|
||||
this->sendBluetoothCommand(SetTextSetParameterCommand, dataMap);
|
||||
}
|
||||
|
||||
QBluetoothLeUart* OmobiDisplayBackend::getBleController() {
|
||||
|
@ -159,6 +213,20 @@ OmobiDisplayBackend::OmobiDisplayAppState OmobiDisplayBackend::getState() {
|
|||
return this->state;
|
||||
}
|
||||
|
||||
void OmobiDisplayBackend::refreshLoadingState() {
|
||||
if(this->state != Initing && this->state != Loading)
|
||||
return;
|
||||
|
||||
qDebug() << "Refreshing loading state! Waiting: " << this->waitingCommands;
|
||||
|
||||
if(this->waitingCommands <= 1) {
|
||||
this->waitingCommands = 0;
|
||||
this->setState(Connected);
|
||||
}
|
||||
else
|
||||
this->waitingCommands--;
|
||||
}
|
||||
|
||||
void OmobiDisplayBackend::setState(OmobiDisplayAppState state) {
|
||||
if(state == this->state)
|
||||
return;
|
||||
|
@ -166,6 +234,8 @@ void OmobiDisplayBackend::setState(OmobiDisplayAppState state) {
|
|||
this->state = state;
|
||||
emit this->stateChanged();
|
||||
|
||||
qDebug() << "Now in " << state << " state";
|
||||
|
||||
if(this->state == Idle)
|
||||
this->ble->startScanningForDevices();
|
||||
}
|
||||
|
@ -180,7 +250,7 @@ void OmobiDisplayBackend::setDisplayBrightness(int brightness) {
|
|||
|
||||
this->displayBrightness = brightness;
|
||||
|
||||
this->ble->sendData("SET_BRIGHTNESS:" + QString::number(this->displayBrightness));
|
||||
this->sendBluetoothCommand(SetDisplayBrightnessCommand, this->displayBrightness);
|
||||
|
||||
emit this->displayBrightnessChanged();
|
||||
}
|
||||
|
|
|
@ -23,24 +23,31 @@ public:
|
|||
Scanning,
|
||||
ReadyToConnect,
|
||||
Connecting,
|
||||
Connected
|
||||
Initing,
|
||||
Connected,
|
||||
Loading
|
||||
};
|
||||
Q_ENUM(OmobiDisplayAppState)
|
||||
|
||||
typedef struct text_set_t
|
||||
{
|
||||
const char text[5];
|
||||
uint time_ms;
|
||||
uint color;
|
||||
bool text_scroll;
|
||||
uint text_scroll_pass;
|
||||
bool active;
|
||||
} text_set_t;
|
||||
|
||||
private:
|
||||
enum OmobiDisplayCommand {
|
||||
GetAllTextSetsCommand = 10,
|
||||
GetTextSetParameterCommand = 11,
|
||||
GetDisplayBrightnessCommand = 12,
|
||||
SetTextSetParameterCommand = 20,
|
||||
SetDisplayBrightnessCommand = 21
|
||||
};
|
||||
|
||||
enum OmobiDisplayStatusCode {
|
||||
Success = 200,
|
||||
DisplayControllerError = 501
|
||||
};
|
||||
|
||||
OmobiDisplayAppState state;
|
||||
QBluetoothLeUart *ble;
|
||||
OmobiDisplayTextModel* displayTextModel;
|
||||
int waitingCommands;
|
||||
QList<QMap<int, QVariant>> textSetsBuffer;
|
||||
int displayBrightness;
|
||||
|
||||
public slots:
|
||||
|
@ -54,11 +61,18 @@ public slots:
|
|||
private slots:
|
||||
void handleBluetoothStateChange(QBluetoothLeUart::BluetoothLeUartState state);
|
||||
void handleFoundNewDevice(QBluetoothLeUartDevice* device);
|
||||
void DataHandler(QString s);
|
||||
void handleBluetoothDeviceConected();
|
||||
|
||||
void handleDisplayTextModelDataChanged();
|
||||
void handleDisplayTextModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
|
||||
void handleDisplayTextModelRowsInserted(const QModelIndex &parent, int first, int last);
|
||||
void handleDisplayTextModelRowsRemoved(const QModelIndex &parent, int first, int last);
|
||||
|
||||
void sendBluetoothCommand(OmobiDisplayCommand command, QVariant data = QVariant());
|
||||
void handleBluetoothDataReceived(QString s);
|
||||
void updateDisplayTextSetParameter(int index, int parameter);
|
||||
void updateDisplayTextSetParameter(int index, int parameter, QString value);
|
||||
|
||||
void refreshLoadingState();
|
||||
void setState(OmobiDisplayAppState state);
|
||||
|
||||
signals:
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
OmobiDisplayTextModel::OmobiDisplayTextModel(QObject* parent) : QAbstractListModel(parent)
|
||||
{
|
||||
this->maximumTextSets = 0;
|
||||
this->maximumTextLength = 0;
|
||||
|
||||
connect(this, &OmobiDisplayTextModel::rowsInserted, this, &OmobiDisplayTextModel::rowCountChanged);
|
||||
connect(this, &OmobiDisplayTextModel::rowsRemoved, this, &OmobiDisplayTextModel::rowCountChanged);
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,11 +17,19 @@ int OmobiDisplayTextModel::rowCount(const QModelIndex &) const
|
|||
|
||||
QVariant OmobiDisplayTextModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() < rowCount()) {
|
||||
return this->data(index.row(), role);
|
||||
}
|
||||
|
||||
QVariant OmobiDisplayTextModel::data(int row, int role) const {
|
||||
if (row < rowCount()) {
|
||||
if(this->texts[row].contains(role)) {
|
||||
if(role == IndexRole)
|
||||
return index.row();
|
||||
else if(this->texts[index.row()].contains(role))
|
||||
return this->texts[index.row()][role];
|
||||
return row;
|
||||
|
||||
QVariant value = this->texts[row][role];
|
||||
value.convert(this->roleDataTypes[OmobiDisplayTextModelRole(role)]);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -48,10 +61,13 @@ void OmobiDisplayTextModel::append(
|
|||
unsigned int scrollCount
|
||||
) {
|
||||
|
||||
// the current Maximum is 5
|
||||
if(this->texts.length() >= 5)
|
||||
// check length maximums
|
||||
if(this->texts.length() >= this->maximumTextSets)
|
||||
return;
|
||||
|
||||
if(text.length() > this->maximumTextLength)
|
||||
text = text.left(this->maximumTextLength);
|
||||
|
||||
QMap<int, QVariant> roles = {
|
||||
{ TextRole, text },
|
||||
{ ActiveRole, active },
|
||||
|
@ -80,11 +96,16 @@ bool OmobiDisplayTextModel::setData(const QModelIndex &index, const QVariant &va
|
|||
if(this->texts[index.row()][role] == value)
|
||||
return true;
|
||||
|
||||
if(role == TextRole && value.toString().length() > this->maximumTextLength)
|
||||
this->texts[index.row()][role] = value.toString().left(this->maximumTextLength);
|
||||
else
|
||||
this->texts[index.row()][role] = value;
|
||||
|
||||
emit dataChanged(index, index);
|
||||
qDebug() << "setting index: " << index << " role: " << role << " value " << value;
|
||||
|
||||
return QAbstractItemModel::setData(index, value, role);
|
||||
emit dataChanged(index, index, QVector<int>({role}));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OmobiDisplayTextModel::remove(int row)
|
||||
|
@ -117,3 +138,15 @@ bool OmobiDisplayTextModel::setTexts(QList<QMap<int, QVariant>> texts) {
|
|||
QList<QMap<int, QVariant>> OmobiDisplayTextModel::getTexts() {
|
||||
return this->texts;
|
||||
}
|
||||
|
||||
QMap<int, QVariant> OmobiDisplayTextModel::getText(const QModelIndex &index) {
|
||||
if (index.row() < this->rowCount())
|
||||
return this->texts[index.row()];
|
||||
|
||||
return QMap<int, QVariant>();
|
||||
}
|
||||
|
||||
|
||||
int OmobiDisplayTextModel::getMaximumTextSets() {
|
||||
return this->maximumTextSets;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
class OmobiDisplayTextModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
|
||||
Q_PROPERTY(int maximumTextSets READ getMaximumTextSets NOTIFY maximumTextSetsChanged)
|
||||
|
||||
public:
|
||||
friend class OmobiDisplayBackend;
|
||||
|
||||
|
@ -21,21 +24,21 @@ public:
|
|||
ScrollRole,
|
||||
ScrollSpeedRole,
|
||||
ScrollCountRole,
|
||||
IndexRole
|
||||
IndexRole,
|
||||
OmobiDisplayTextModelRoleCount
|
||||
};
|
||||
Q_ENUM(OmobiDisplayTextModelRole)
|
||||
|
||||
|
||||
enum text_align_t
|
||||
enum OmobiDisplayTextAlignment
|
||||
{
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
AlignRignt
|
||||
};
|
||||
|
||||
|
||||
int rowCount(const QModelIndex & = QModelIndex()) const;
|
||||
Q_INVOKABLE int rowCount(const QModelIndex & = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant data(int i, int role = Qt::DisplayRole) const;
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
|
||||
Q_INVOKABLE void append(
|
||||
|
@ -54,16 +57,38 @@ public:
|
|||
|
||||
Q_INVOKABLE void remove(int row);
|
||||
|
||||
Q_INVOKABLE int getMaximumTextSets();
|
||||
|
||||
protected:
|
||||
OmobiDisplayTextModel(QObject* parent = nullptr);
|
||||
|
||||
bool setTexts(QList<QMap<int, QVariant>> json);
|
||||
QList<QMap<int, QVariant>> getTexts();
|
||||
QMap<int, QVariant> getText(const QModelIndex &index);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
QList<QMap<int, QVariant>> texts;
|
||||
|
||||
int maximumTextSets;
|
||||
int maximumTextLength;
|
||||
|
||||
const QMap<OmobiDisplayTextModelRole, QVariant::Type> roleDataTypes = {
|
||||
{TextRole, QVariant::String},
|
||||
{ActiveRole, QVariant::Bool},
|
||||
{RuntimeRole, QVariant::Int},
|
||||
{ColorRole, QVariant::String},
|
||||
{AlignmentRole, QVariant::Int},
|
||||
{ScrollRole, QVariant::Bool},
|
||||
{ScrollSpeedRole, QVariant::Int},
|
||||
{ScrollCountRole, QVariant::Int},
|
||||
{IndexRole, QVariant::Int}
|
||||
};
|
||||
|
||||
signals:
|
||||
void rowCountChanged();
|
||||
void maximumTextSetsChanged();
|
||||
};
|
||||
|
||||
#endif // OMOBIDISPLAYTEXTMODEL_H
|
||||
|
|
92
OmobiDisplayApp/ressources/qml/ColorPicker.qml
Normal file
92
OmobiDisplayApp/ressources/qml/ColorPicker.qml
Normal file
|
@ -0,0 +1,92 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls.Material 2.0
|
||||
|
||||
Rectangle {
|
||||
id: control
|
||||
|
||||
property string value: ""
|
||||
property string currentColor: rgbToHex(redSlider.value, greenSlider.value, blueSlider.value)
|
||||
property bool isDarkColor: control.checkIsDarkColor(value)
|
||||
|
||||
implicitHeight: width
|
||||
|
||||
onValueChanged: {
|
||||
var rgb = hexToRgb(value)
|
||||
|
||||
redSlider.value = rgb.r
|
||||
greenSlider.value = rgb.g
|
||||
blueSlider.value = rgb.b
|
||||
}
|
||||
|
||||
onCurrentColorChanged: {
|
||||
value = currentColor
|
||||
}
|
||||
|
||||
function rgbToHex(r, g, b) {
|
||||
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
||||
}
|
||||
|
||||
function hexToRgb(hex) {
|
||||
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result ? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
b: parseInt(result[3], 16)
|
||||
} : null;
|
||||
}
|
||||
|
||||
function checkIsDarkColor(color) {
|
||||
var temp = Qt.darker(color, 1) //Force conversion to color QML type object
|
||||
var a = 1 - ( 0.299 * temp.r + 0.587 * temp.g + 0.114 * temp.b);
|
||||
return temp.a > 0 && a >= 0.3
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: parent.height * 0.5
|
||||
color: control.currentColor
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: redSlider
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
from: 0
|
||||
to: 255
|
||||
stepSize: 1
|
||||
|
||||
Material.accent: Material.Red
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: greenSlider
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
from: 0
|
||||
to: 255
|
||||
stepSize: 1
|
||||
|
||||
Material.accent: Material.Green
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: blueSlider
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
from: 0
|
||||
to: 255
|
||||
stepSize: 1
|
||||
|
||||
Material.accent: Material.Blue
|
||||
}
|
||||
|
||||
}
|
||||
}
|
89
OmobiDisplayApp/ressources/qml/ColorPickerDelegate.qml
Normal file
89
OmobiDisplayApp/ressources/qml/ColorPickerDelegate.qml
Normal file
|
@ -0,0 +1,89 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.9
|
||||
import QtQuick.Controls.Material 2.0
|
||||
|
||||
ItemDelegate {
|
||||
id: control
|
||||
|
||||
property string value: ""
|
||||
|
||||
onClicked: {
|
||||
colorPicker.value = value
|
||||
textEditDialog.open()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
right: nextPageIconText.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
rightMargin: control.padding
|
||||
}
|
||||
|
||||
width: parent.width * 0.15
|
||||
height: parent.height * 0.6
|
||||
radius: height * 0.1
|
||||
|
||||
color: control.value === "" ? "transparent":control.value
|
||||
|
||||
border.width: 2
|
||||
border.color: control.value === "" ? "lightgrey":control.value
|
||||
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
anchors.margins: parent.height * 0.1
|
||||
|
||||
font.pixelSize: height * 0.5
|
||||
fontSizeMode: Text.Fit
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
color: colorPicker.isDarkColor && control.value !== "" ? "white":"black"
|
||||
|
||||
text: value === "" ? "Not set": value
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: nextPageIconText
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
rightMargin: control.padding
|
||||
}
|
||||
|
||||
font.pixelSize: parent.height * 0.5
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
text: ">"
|
||||
}
|
||||
|
||||
Dialog {
|
||||
id: textEditDialog
|
||||
parent: Overlay.overlay
|
||||
|
||||
x: (parent.width - width) / 2
|
||||
y: (parent.height - height) / 2
|
||||
|
||||
width: parent.width * 0.9
|
||||
|
||||
Material.theme: control.Material.theme
|
||||
Material.accent: control.Material.accent
|
||||
modal: true
|
||||
|
||||
title: control.text
|
||||
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
|
||||
contentItem: ColorPicker {
|
||||
id: colorPicker
|
||||
value: control.value
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
control.value = colorPicker.value
|
||||
}
|
||||
}
|
||||
}
|
|
@ -77,6 +77,10 @@ ItemDelegate {
|
|||
checked: index === control.currentIndex
|
||||
ButtonGroup.group: buttonGroup
|
||||
text: modelData
|
||||
onClicked: {
|
||||
control.currentIndex = index
|
||||
textEditDialog.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,10 +89,6 @@ ItemDelegate {
|
|||
listView.model = control.model
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
control.currentText = buttonGroup.checkedButton.text
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: buttonGroup
|
||||
}
|
||||
|
|
|
@ -166,6 +166,20 @@ Page {
|
|||
statusText: "trying to connect..."
|
||||
working: true
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: OmobiDisplayBackend.Initing
|
||||
|
||||
PropertyChanges {
|
||||
target: availableDevicesListView
|
||||
enabled: false
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: root
|
||||
statusText: "loading data..."
|
||||
working: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -64,4 +64,50 @@ Page {
|
|||
clip: true
|
||||
}
|
||||
}
|
||||
|
||||
Dialog {
|
||||
id: loadingDialog
|
||||
|
||||
property bool shouldBeOpen: false
|
||||
|
||||
onShouldBeOpenChanged: {
|
||||
if(shouldBeOpen)
|
||||
open()
|
||||
else
|
||||
close()
|
||||
}
|
||||
|
||||
parent: Overlay.overlay
|
||||
|
||||
x: (parent.width - width) / 2
|
||||
y: (parent.height - height) / 2
|
||||
|
||||
closePolicy: Popup.NoAutoClose
|
||||
modal: true
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
BusyIndicator {
|
||||
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.alignment: Layout.Center
|
||||
text: qsTr("loading...")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: OmobiDisplayBackend.Connected
|
||||
},
|
||||
State {
|
||||
name: OmobiDisplayBackend.Loading
|
||||
|
||||
PropertyChanges {
|
||||
target: loadingDialog
|
||||
shouldBeOpen: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ ListView {
|
|||
height: implicitHeight * 1.3
|
||||
width: height
|
||||
|
||||
enabled: control.model.rowCount < control.model.maximumTextSets
|
||||
|
||||
Material.background: Material.accent
|
||||
|
||||
text: ""
|
||||
|
|
|
@ -28,8 +28,8 @@ Dialog {
|
|||
editingModel.active = activeSwitch.checked
|
||||
editingModel.text = textTextField.value
|
||||
editingModel.runtime = runtimeSpinBox.value
|
||||
editingModel.color = colorComboBox.currentText
|
||||
editingModel.alignment = alignmentComboBox.currentText
|
||||
editingModel.color = colorColorPicker.value
|
||||
editingModel.alignment = alignmentComboBox.currentIndex
|
||||
editingModel.scroll = scrollSwitch.checked
|
||||
editingModel.scrollSpeed = scrollSpeedSpinBox.value
|
||||
editingModel.scrollCount = scrollCountSpinBox.value
|
||||
|
@ -38,7 +38,7 @@ Dialog {
|
|||
editingModel.append(textTextField.value,
|
||||
activeSwitch.checked,
|
||||
runtimeSpinBox.value,
|
||||
colorComboBox.currentText,
|
||||
colorColorPicker.value,
|
||||
alignmentComboBox.currentText,
|
||||
scrollSwitch.checked,
|
||||
scrollSpeedSpinBox.value,
|
||||
|
@ -88,10 +88,9 @@ Dialog {
|
|||
text: qsTr("Runtime (in s)")
|
||||
}
|
||||
|
||||
ComboBoxDelegate {
|
||||
id: colorComboBox
|
||||
ColorPickerDelegate {
|
||||
id: colorColorPicker
|
||||
Layout.fillWidth: true
|
||||
model: ["white", "blue", "red", "green"]
|
||||
text: qsTr("Color")
|
||||
}
|
||||
|
||||
|
@ -163,8 +162,8 @@ Dialog {
|
|||
activeSwitch.checked = editingModel.active
|
||||
textTextField.value = editingModel.text
|
||||
runtimeSpinBox.value = editingModel.runtime
|
||||
colorComboBox.currentIndex = colorComboBox.model.indexOf(editingModel.color)
|
||||
alignmentComboBox.currentIndex = alignmentComboBox.model.indexOf(editingModel.alignment)
|
||||
colorColorPicker.value = editingModel.color
|
||||
alignmentComboBox.currentIndex = editingModel.alignment
|
||||
scrollSwitch.checked = editingModel.scroll
|
||||
scrollSpeedSpinBox.value = editingModel.scrollSpeed
|
||||
scrollCountSpinBox.value = editingModel.scrollCount
|
||||
|
@ -183,7 +182,7 @@ Dialog {
|
|||
activeSwitch.checked = true
|
||||
textTextField.value = ""
|
||||
runtimeSpinBox.value = 0
|
||||
colorComboBox.currentIndex = 0
|
||||
colorColorPicker.value = ""
|
||||
alignmentComboBox.currentIndex = 0
|
||||
scrollSwitch.checked = false
|
||||
scrollSpeedSpinBox.value = 5
|
||||
|
|
|
@ -54,7 +54,7 @@ ApplicationWindow {
|
|||
mainStack.replace(currentComponent)
|
||||
}
|
||||
|
||||
//initialItem: connectedPageComp
|
||||
initialItem: connectedPageComp
|
||||
|
||||
Component {
|
||||
id: connectPageComp
|
||||
|
@ -104,12 +104,28 @@ ApplicationWindow {
|
|||
}
|
||||
},
|
||||
|
||||
State {
|
||||
name: OmobiDisplayBackend.Initing
|
||||
PropertyChanges {
|
||||
target: mainStack
|
||||
currentComponent: connectPageComp
|
||||
}
|
||||
},
|
||||
|
||||
State {
|
||||
name: OmobiDisplayBackend.Connected
|
||||
PropertyChanges {
|
||||
target: mainStack
|
||||
currentComponent: connectedPageComp
|
||||
}
|
||||
},
|
||||
|
||||
State {
|
||||
name: OmobiDisplayBackend.Loading
|
||||
PropertyChanges {
|
||||
target: mainStack
|
||||
currentComponent: connectedPageComp
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -11,5 +11,7 @@
|
|||
<file>NextPageDelegate.qml</file>
|
||||
<file>SpinBoxDelegate.qml</file>
|
||||
<file>ComboBoxDelegate.qml</file>
|
||||
<file>ColorPickerDelegate.qml</file>
|
||||
<file>ColorPicker.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
Loading…
Reference in a new issue