We're currently learning Qt Quick (with Qt 5.3 at the moment). QML and Qt are not very familiar to me. I'm looking for feedback on the code below.
It's not complete code. Ports.h and Ports.cpp are the model the GUI binds through. PortBase.qml and PulsePort.qml is a control used to represent that model. PortStatusPage.qml contains some of those controls.
Ports.h:
#ifndef PortBase_H
#define PortBase_H
#include <QObject>
class PortBasePrivate;
class PortBase : public QObject {
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(bool input READ isInput WRITE setIsInput NOTIFY inputChanged)
Q_PROPERTY(int status READ status WRITE setStatus NOTIFY statusChanged)
public:
explicit PortBase(QObject* p = 0);
signals:
void nameChanged(const QString& name);
void inputChanged(bool input);
void statusChanged(int status);
public:
QString name() const;
void setName(const QString& name);
bool isInput() const;
void setIsInput(bool isInput);
int status() const;
void setStatus(int status);
private:
PortBasePrivate* d_ptr;
Q_DECLARE_PRIVATE(PortBase)
Q_DISABLE_COPY(PortBase)
};
class PulsePort : public PortBase {
Q_OBJECT
public:
explicit PulsePort(QObject* p = 0) : PortBase(p) {}
enum Status {Normal, Active};
Q_ENUMS(Status)
};
class CTInput : public PortBase {
Q_OBJECT
public:
explicit CTInput(QObject* p = 0) : PortBase(p) {}
enum Status {Disconnected, Uncalibrated, Calibrated};
Q_ENUMS(Status)
};
#endif // PortBase_H
Ports.cpp:
#include "Ports.h"
#include <QQmlEngine>
class PortBasePrivate {
PortBase* q_ptr;
public:
PortBasePrivate(PortBase* qptr) : q_ptr(qptr) {}
QString Name;
bool IsInput;
int Status;
};
PortBase::PortBase( QObject *p) : QObject(p)
{
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
d_ptr = new PortBasePrivate(this);
}
QString PortBase::name() const {Q_D(const PortBase); return d->Name;}
void PortBase::setName(const QString &name)
{
Q_D(PortBase);
if (d->Name != name) {
d->Name = name;
emit nameChanged(name);
}
}
bool PortBase::isInput() const {Q_D(const PortBase); return d->IsInput;}
void PortBase::setIsInput(bool input)
{
Q_D(PortBase);
if (d->IsInput != input) {
d->IsInput = input;
emit inputChanged(input);
}
}
int PortBase::status() const {Q_D(const PortBase); return d->Status;}
void PortBase::setStatus(int status)
{
Q_D(PortBase);
if (d->Status != status) {
d->Status = status;
emit statusChanged(status);
}
}
PortBase.qml:
import QtQuick 2.0
Rectangle {
x: 0; y: 0
width: parent.width
height: parent.height
color: "transparent"
}
PulsePort.qml:
import QtQuick 2.0
import QtQuick.Layouts 1.1
import com.radianresearch.backend 1.0
ColumnLayout {
property var port: null
spacing: 0
LabelEx {
id: txt
text: port ? port.name : "NA";
anchors.horizontalCenter: parent.horizontalCenter
}
ImageAnimator {
id: imgScaler
source: port? "qrc:/images/rsrc/images/%1.png".arg(port.input ? "i2-48": "o2-48") : ""
anchors.horizontalCenter: parent.horizontalCenter
animate: port ? port.status == PulsePort.Active : false
}
}
PortStatusPage.qml:
import QtQuick 2.0
import "../controls"
import QtQuick.Layouts 1.1
PageBase {
Item {
anchors.centerIn: parent
width: parent.width * 80 / 100
height: parent.height * 90 / 100
Rectangle {
id: rctPulsePort
anchors.left: parent.left; anchors.right: parent.right
anchors.top: parent.top; height: parent.height * .40
border.color: "#00569B"; border.width: 1
LabelEx {
text: "Pusle Port"; font.bold: true
anchors.left: parent.left; anchors.leftMargin: 5
anchors.top: parent.top; anchors.topMargin: 2
}
RowLayout {
anchors.centerIn: parent
anchors.verticalCenterOffset: 5
spacing: 20
Repeater {
model: gBackend.pulsePortsCount
PULSEPort {
port: gBackend.getPulsePortAt(index)
}
}
}
}
Rectangle {
id: rctStatusBox
anchors.left: parent.left; anchors.right: parent.right
anchors.top: rctPulsePort.bottom; anchors.bottom: parent.bottom
anchors.topMargin: 10
border.color: "#00569B"; border.width: 1
LabelEx {
text: "CT Inputs"; font.bold: true
anchors.left: parent.left; anchors.leftMargin: 5
anchors.top: parent.top; anchors.topMargin: 2
}
RowLayout {
anchors.centerIn: parent
anchors.verticalCenterOffset: 5
spacing: 20
Repeater {
model: gBackend.ctInputsCount
CTInput {
ctInput: gBackend.getCTInputAt(index)
}
}
Behavior on width {
NumberAnimation { duration: 300 }
}
}
}
}
}