How to flip RadioButton? - qt

Is it possible to flip a RadioButton? By default the circle is aligned left and the text is aligned right. I'd like to position the text to the left and circle to the right. With LayoutMirroring.childrenInherit: true I position text to the left, but the circle is still on the left.
Column {
id: column1
x: -265
y: 219
width: 104
height: 45
spacing: 5
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true
ExclusiveGroup { id: diamTypes }
RadioButton { text: "one"; exclusiveGroup: diamTypes }
RadioButton { text: "two"; exclusiveGroup: diamTypes }
}

Add a Text item (with the desired name) within the RadioButton item and give a relative x and y position to it. Leave the text property of the RadioButton blank.
RadioButton {
id: radioButtonID
x: 319 // Button position
y: 46
Text {
x: -60 // Relative text position to the radio button
y: 3
text: "Radio Button"
font.pointSize: 8
color: "black"
}
}

Here's how to do it using widgets:
Inherit from QRadioButton, add a new QLabel for text, make the original QRadioButton::text empty, and adjust the padding. Like this:
QFont myFont;
QFontMetrics fm(myFont);
int indicatorPadding = WINDOW_WIDTH - 25;
this->setStyleSheet(QString("QRadioButton { "
"text-align: left; "
"padding-left: " + QString::number(indicatorPadding ) + "px; "
"} ")
);
int paddingLeft = indicatorPadding - RADIO_BTN_WIDTH - fm.width(radioText->text());
radioText->setStyleSheet("padding-top: 7px; padding-left: " + QString::number(paddingLeft) + ";");
Here is my full class for RadioButtons for RTL languages (it also aligns text accordingly):
my_radiobutton.h:
#ifndef MYRADIOBUTTON_H
#define MYRADIOBUTTON_H
#include <QRadioButton>
#include <QEvent>
#include <QLabel>
#include "constants.h"
class MyRadioButton : public QRadioButton
{
private:
QLabel* radioText = NULL;
public:
explicit MyRadioButton(QWidget *parent=0);
explicit MyRadioButton(const QString &text, QWidget *parent=0);
void setText(const QString &text);
QString text() const;
protected:
void alignText();
void changeEvent(QEvent * event);
};
#endif // MYRADIOBUTTON_H
my_radiobutton.cpp:
#include "my_radiobutton.h"
bool isRTL(); //returns true if RTL language, and false otherwise
MyRadioButton::MyRadioButton(QWidget *parent)
: QRadioButton(parent)
{
if(isRTL()){
radioText = new QLabel(this);
}
}
MyRadioButton::MyRadioButton(const QString &text, QWidget *parent)
: QRadioButton(text,parent)
{
if(isRTL()){
radioText = new QLabel(this);
}
}
void MyRadioButton::setText(const QString &text)
{
if(isRTL()){
QRadioButton::setText("");
if(radioText){
radioText->setText(text);
}
}
else{
QRadioButton::setText(text);
}
alignText();
}
QString MyRadioButton::text() const
{
if(isRTL() && radioText){
return radioText->text();
}
else{
return QRadioButton::text();
}
}
void MyRadioButton::alignText()
{
if(isRTL() && radioText){
QFont myFont;
QFontMetrics fm(myFont);
int indicatorPadding = WINDOW_WIDTH - 25;
this->setStyleSheet(QString("QRadioButton { "
"text-align: left; "
"padding-left: " + QString::number(indicatorPadding ) + "px; "
"} ")
);
int paddingLeft = indicatorPadding - RADIO_BTN_WIDTH - fm.width(radioText->text());
radioText->setStyleSheet("padding-top: " + QString::number(CENTER_OF_LINE) + "px; padding-left: " + QString::number(paddingLeft) + ";");
}
else{
this->setStyleSheet(QString("QRadioButton { "
"text-align: left; "
"padding-left: " TEXT_PADDING "px; "
"} ")
);
}
}
void MyRadioButton::changeEvent(QEvent * event)
{
if (event->type() == QEvent::LanguageChange){
alignText();
}
QWidget::changeEvent(event);
}
constants.h:
#define WINDOW_WIDTH 220
#define RADIO_BTN_WIDTH 10
#define CENTER_OF_LINE ((LINE_HEIGHT/2) - (FONT_SIZE/2)) // ==7
#define TEXT_PADDING STRINGIFY(10)
Result:

Go to the design view and set direction to "left to right".

RadioButtonStyle can also be used for the purpose. The alignment should be set up somehow:
RadioButton {
text: "bla-bla";
exclusiveGroup: diamTypes
style: RadioButtonStyle {
label: Label {
text: control.text
font.pointSize: 14
anchors.margins: 0
}
indicator: Rectangle {
implicitWidth: 16
implicitHeight: 16
radius: 9
border.color: control.activeFocus ? "darkblue" : "gray"
border.width: 1
Rectangle {
anchors.fill: parent
visible: control.checked
color: "#555"
radius: 9
anchors.margins: 4
}
}
}
}

you can do it easy:
RadioButton {
id: offlineMapParentBox
text: qsTr("radio button")
anchors.left: parent.left
LayoutMirroring.enabled: true
}
or if you work on left to right and right to left multilanguage app you can do it like below:
RadioButton {
id: offlineMapParentBox
text: qsTr("Offline Map")
anchors.left: parent.left
LayoutMirroring.enabled: isLeftToRight ? false : true
}
thanks

Related

"Unable to open file"

This is one of my first projects using QML: I started making a simple game character and a few rooms, and to make the walls'hitboxes I stored them all into a file and included a FileIO class I saw in this site, adapted to return the entire file instead of just one line.
The program, though, tells me it isn't able to open the file (I have put it in the project's directory)
//main.qml (ignore line 5)
import QtQuick 2.15
import QtQuick.Shapes 1.12
import FileIO 1.0
// Whats this? UwU a byzantiuwm?!?!!? UwU i wove byzantiuwm, especiwwawwy in the #memes channew wewe byzantiuwm is the tawk of ze town! OwO
Rectangle {
width: 639
height: 480
id: sus // I hate myself
color: "#00ff00"
Shape {
property string d: "S"
property int room: 1
id: player
x: xPos
y: yPos
z: 1
visible: true
property int xPos: 297
property int yPos: 219
parent: sus
width: 45
height: 45
focus: true
Keys.onPressed:
{
if(event.key === Qt.Key_Down){
yPos+=3; d="S"
}
if(event.key === Qt.Key_Up){
yPos-=3; d="N"
}
if(event.key === Qt.Key_Left){
xPos-=3; d="W"
}
if(event.key === Qt.Key_Right){
xPos+=3; d="E"
}
event.accepted = true;
}
ShapePath{
strokeColor: "transparent"
fillColor: "transparent"
PathLine{x:45 ;y: 0}
PathLine{x:45 ;y:45}
PathLine{x: 0 ;y:45}
}
Image {
id: sprite
parent: player
width: parent.width
height: parent.height
smooth: false
source: "Player/Player_" + player.d + ".png"
}
}
Image {
id: background
x: 0
y: 0
z: 0
width: 639
height: 480
visible: true
smooth: false
parent: sus
source: "Rooms/" + player.room + ".png"
fillMode: Image.Stretch
}
Shape {
id: wallHitBox
x: 0
y: 0
z: 50
width: sus.width
height: sus.height
//visible: false
FileIO{
id: fileReader
source: "Rooms/Hitboxes_or_something.txt"
onError: {console.log(msg)}
}
property var the: fileReader.read()
ShapePath{
strokeColor: "transparent"
fillColor: "blue" //"transparent"
PathSvg{
path: wallHitBox.the[player.room];
}
}
}
}
//fileio.cpp
#include "fileio.h"
#include <QFile>
#include <QTextStream>
FileIO::FileIO(QObject *parent) :
QObject(parent)
{
}
QVector<QString> FileIO::read()
{
if (mSource.isEmpty()){
emit error("source is empty");
return QVector<QString>();
}
QFile file(mSource);
QVector<QString> fileContent;
if ( file.open(QIODevice::ReadOnly) ) {
QString line;
QTextStream t( &file );
do {
line = t.readLine();
fileContent.resize(fileContent.size()+1);
fileContent[fileContent.size()] = line;
} while (!line.isNull());
file.close();
} else {
emit error("Unable to open the file");
return QVector<QString>();
}
return fileContent;
}
bool FileIO::write(const QString& data)
{
if (mSource.isEmpty())
return false;
QFile file(mSource);
if (!file.open(QFile::WriteOnly | QFile::Truncate))
return false;
QTextStream out(&file);
out << data;
file.close();
return true;
}
#define FILEIO_H
#include <QObject>
class FileIO : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(QString source
READ source
WRITE setSource
NOTIFY sourceChanged)
explicit FileIO(QObject *parent = 0);
Q_INVOKABLE QVector<QString> read();
Q_INVOKABLE bool write(const QString& data);
QString source() { return mSource; };
public slots:
void setSource(const QString& source) { mSource = source; };
signals:
void sourceChanged(const QString& source);
void error(const QString& msg);
private:
QString mSource;
};
#endif // FILEIO_H
Can someone please help me?

QML Clip Custom Item

I made my own QQuickItem, which I draw using the updatePaintNode method (using the scenegraph). In a qml File I add this item as a child to a Rectangle:
Rectangle {
anchors.centerIn: parent
width: parent.width/2.
height: parent.height/2.
border.color: "#000000"
clip: true
MyItem {
id: myitem
anchors.centerIn: parent
width: parent.width
height: parent.height
MouseArea {
anchors.fill: parent
onWheel: {
if (wheel.modifiers & Qt.ControlModifier) {
parent.scale = parent.scale+ 0.2 * wheel.angleDelta.y / 120;
if (parent.scale < 1)
parent.scale = 1;
}
}
}
}
}
As you can see, I added a zoom function and set
clip: True
for the rectangle. However, when I zoom, my item is not clipped at the Rectangle but extends beyond it. What would be the correct way to do clipping?
Edit: Here is the content of the cpp file for MyItem
MyItem::MyItem(QQuickItem *parent): QQuickItem(parent)
{
setFlag(QQuickItem::ItemHasContents,true);
// code to initialize xdata, ydata, xmax, ymax
}
QSGNode *MyItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) {
QSGGeometryNode *mypath = static_cast<QSGGeometryNode*>(oldNode);
if(!mypath) {
mypath = new QSGGeometryNode;
mypath->setFlag(QSGNode::OwnsMaterial,true);
mypath->setFlag(QSGNode::OwnsGeometry,true);
}
QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(),_xdata.size());
QSGGeometry::Point2D *points = geometry->vertexDataAsPoint2D();
for(int i=0;i<_xdata.size();i++) {
points[i].x = _xdata[i]/_xmax*width();
points[i].y = _ydata[i]/_ymax*height();
}
geometry->setLineWidth(2);
geometry->setDrawingMode(GL_LINE_STRIP);
mypath->setGeometry(geometry);
QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
material->setColor(Qt::blue);
mypath->setMaterial(material);
return mypath;
}
and here is the header file:
#include <QQuickItem>
#include <vector>
class MyItem : public QQuickItem
{
Q_OBJECT
public:
MyItem(QQuickItem *parent = 0);
private:
std::vector<double> _xdata;
std::vector<double> _ydata;
double _xmax;
double _ymax;
signals:
public slots:
protected:
QSGNode * updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) override;
};

How to take a screen shot of the window and display it on an image using QML?

I want to take a screen shot using the code
QImage img = currentView_->grabWindow();
and i want to display this screen shot on my GUI using QML.
How to do this ?
If you want to transfer an image from C++ to QML the best way I guess is QQuickImageProvider. The small example bellow is maybe a bit different from what you want but anyway:
QQuickImageProvider class:
#ifndef IMAGEPROVIDER_H
#define IMAGEPROVIDER_H
#include <QQuickImageProvider>
#include <QQuickView>
#include <QImage>
class ImageProvider : public QObject, public QQuickImageProvider
{
Q_OBJECT
public:
ImageProvider(QObject *parent = 0, Flags flags = Flags());
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
protected:
QMap<int, QImage> m_images;
public slots:
void makeScreenshot();
};
#endif // IMAGEPROVIDER_H
#include "imageprovider.h"
ImageProvider::ImageProvider(QObject *parent, Flags flags) :
QQuickImageProvider(QQmlImageProviderBase::Image, flags),
QObject(parent)
{
}
QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
bool ok = false;
QImage img = m_images[id.toInt(&ok)];
return img;
}
void ImageProvider::makeScreenshot()
{
QQuickWindow *view = static_cast<QQuickWindow *>(sender());
static int pos = 0;
QImage img = view->grabWindow();
m_images.insert(pos,img);
QVariant returnedValue;
QMetaObject::invokeMethod(view, "setImage",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, pos++));
}
Registering it in main.cpp:
QQmlApplicationEngine engine;
ImageProvider *imageProvider = new ImageProvider();
engine.addImageProvider(QLatin1String("screenshots"), imageProvider);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QQuickWindow *view = dynamic_cast<QQuickWindow *>(engine.rootObjects().at(0));
QObject::connect(view, SIGNAL(getScreenshot()),
imageProvider, SLOT(makeScreenshot()));
Usage:
import QtQuick 2.7
import QtQuick.Window 2.0
Window {
id:container
width: 600
height: 600
visible: true
signal getScreenshot()
Repeater {
model: 20
delegate: Rectangle {
x: Math.random() * 500
y: Math.random() * 500
width: Math.random() * 50 + 50
height: width
radius: width / 2
color: Qt.rgba(Math.random(),Math.random(),Math.random(),1)
}
}
Text {
id: txt
anchors.centerIn: parent
text: "Click me"
}
Rectangle {
id: rect
anchors.centerIn: parent
width: 0
height: 0
border.width: 5
border.color: "black"
Image {
id: img
anchors.fill: parent
anchors.margins: 5
source: ""
fillMode: Image.PreserveAspectFit
}
ParallelAnimation {
id: anim
PropertyAnimation {
property: "width"
target: rect
from: 0
to: 200
duration: 500
}
PropertyAnimation {
property: "height"
target: rect
from: 0
to: 200
duration: 500
}
}
}
MouseArea {
anchors.fill: parent
onClicked: {
txt.visible = false;
container.getScreenshot();
}
}
function setImage(id)
{
img.source = "image://screenshots/" + id;
anim.running = true;
}
}

QML TableView get data from specific cell (selected row + specific column)

I have QML TableView with QSqlQueryModel. I need to select any row and get data from every column of table to separate TextField.
Here is abonentstable.h:
#pragma once
#include <QObject>
#include <QSqlQueryModel>
class AbonentsSqlModel : public QSqlQueryModel
{
Q_OBJECT
public:
explicit AbonentsSqlModel(QObject *parent = 0);
void setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase());
QVariant data(const QModelIndex &index, int role) const;
QHash<int, QByteArray> roleNames() const { return m_roleNames; }
private:
void generateRoleNames();
QHash<int, QByteArray> m_roleNames;
};
abonentstable.cpp:
#include "abonentstable.h"
#include <QSqlRecord>
#include <QSqlField>
AbonentsSqlModel::AbonentsSqlModel(QObject *parent) : QSqlQueryModel(parent)
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("data_base.sqlite");
db.open();
}
void AbonentsSqlModel::setQuery(const QString &query, const QSqlDatabase &db)
{
QSqlQueryModel::setQuery(query, db);
generateRoleNames();
}
void AbonentsSqlModel::generateRoleNames()
{
m_roleNames.clear();
for( int i = 0; i < record().count(); i ++) {
m_roleNames.insert(Qt::UserRole + i + 1, record().fieldName(i).toUtf8());
}
}
QVariant AbonentsSqlModel::data(const QModelIndex &index, int role) const
{
QVariant value;
if(role < Qt::UserRole) {
value = QSqlQueryModel::data(index, role);
}
else {
int columnIdx = role - Qt::UserRole - 1;
QModelIndex modelIndex = this->index(index.row(), columnIdx);
value = QSqlQueryModel::data(modelIndex, Qt::DisplayRole);
}
return value;
}
Table.qml:
TableView {
id: table
model: abonents
....
TableViewColumn {
delegate: Text {
text: " " + model.name + " " + model.surname
font.pointSize: 20
}
width: 575
}
TableViewColumn {
delegate: Text {
text: " " + model.phone
font.pointSize: 20
}
width: 575
}
TableViewColumn {
delegate: Text {
text: " " + model.ip_address
font.pointSize: 20
}
width: 525
}
}
And some text fields:
TextField {
id: leftText
}
TextField {
id: centerText
}
TextField {
id: rightText
}
This sqlite table has 4 columns, and I need to get data from selected row to those text fields: 2 columns to left, 1 to center and 1 to right.
When the user clicks a valid row it is emitted the clicked(int row) signal. Then, you can get the values for that row, format the text depending on your requirements and set the values in the three TextField. For example, in your case:
TableView {
id: table
model: abonents
... (your TableViewColumn components) ...
onClicked: {
leftText.text = abonents.get(row).name + " " + libraryModel.get(row).surname;
centerText.text = abonents.get(row).phone;
rightText.text = abonents.get(row).ip_address;
}
}
Please, let me please use my own answer to show you a complete example:
import QtQuick 2.2
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
ApplicationWindow {
id: window
visible: true
title: "Table View Example"
TableView {
y: 70
width: 500
TableViewColumn {
role: "title"
title: "Title"
width: 100
}
TableViewColumn {
role: "author"
title: "Author"
width: 100
}
TableViewColumn{
width: 300
delegate: Text {
text: model.title + " " + model.author
font.family: "Courier New"
font.pixelSize: 18
color: "red"
}
}
onClicked: {
leftText.text = libraryModel.get(row).title + " " + libraryModel.get(row).author;
centerText.text = libraryModel.get(row).title;
rightText.text = libraryModel.get(row).author;
}
model: libraryModel
ListModel {
id: libraryModel
ListElement {
title: "A Masterpiece"
author: "Gabriel"
}
ListElement {
title: "Brilliance"
author: "Jens"
}
ListElement {
title: "Outstanding"
author: "Frederik"
}
}
}
TextField {
id: leftText
}
TextField {
id: centerText
anchors.left: leftText.right
}
TextField {
id: rightText
anchors.left: centerText.right
}
}

Qt/QML: Is it allowed to have a model view as a delegate?

Is it possible to have a model view (such as ListView or GridView) in a delegate of another model view?
I'm using a ListView (LV1) whose delegate also has a ListView (LV2). Everything before and after LV2 is displayed correctly (and that's in the delegate of LV1). However, nothing is shown in LV1.
My model is from this: http://qt-project.org/wiki/How_to_use_a_QSqlQueryModel_in_QML . I suppose that the SQL query is correct since it returns the correct information when ran externally to Qt. According to debug messages, that all queries is clearly executed.
I have two queries, one being updated with the other. That works good.
Figure #1 shows the debug messages, and it points out that the QML does call the data function and information is indeed returned from the database.
Figure #2 shows the QML window at the time of figure #1: we can clearly see that the layout is messed up and nothing is shown.
Verbatim #1 is the QML code.
Verbatim #2 is an excerpt of the main which shows that I connect the main model to the secondary model though a signal called updateBindings.
Verbatim #3 is my updated SqlQueryModel. The main difference with the tutorial is the signal and slots.
Verbatim #4 is for reference, since this class is used in verbatim #3.
Any input is valued, I've been struggling with this for a few days now. Thanks.
Verbatim #1 (QML):
import QtQuick 1.1
import "Styles"
Rectangle {
id : window;
width : 750
height : 500
signal searchSignal(string msg)
signal resetSignal()
property variant subtypes: {"S":"Status (digital)", "V":"Value (analog)"}
property variant phases: {'66': 'Final Mass Properties', '67': 'Final Thruster Aignment/Solar Array Inst.', '60': 'Final Functional Performance', '114': 'Maneuver (Wheel Mode) Overlay (LTO)', '88': 'Troubleshooting Test Phase 9', '89': 'Troubleshooting Test Phase 10', '111': 'Battery 1 Reconditioning Overlay (LTO)', '110': 'Battery Recharge Overlay (LTO)', '113': 'Maneuver (SK Mode) Overlay (LTO)', '112': 'Battery 2 Reconditioning Overlay (LTO)', '68': 'Flight Battery Functional', '83': 'Troubleshooting Test Phase 4', '80': 'Troubleshooting Test Phase 1', '81': 'Troubleshooting Test Phase 2', '86': 'Troubleshooting Test Phase 7', '87': 'Troubleshooting Test Phase 8', '84': 'Troubleshooting Test Phase 5', '85': 'Troubleshooting Test Phase 6', '24': 'Post T/V Performance ( Ambient)', '26': 'Alignments - Pre Dynamics', '27': 'Antenna Installation', '20': 'Cold (Equinox) Functional Plateau', '21': 'Transition Monitor (cold to hot)', '22': 'Hot ( Winter Solstice)', '82': 'Troubleshooting Test Phase 3', '28': 'Solar Array Installation', '40': 'CATR', '41': 'ESD (PFM Only)', '1': 'North Panel Electrical integration', '3': 'SSM/Bus Module Electrical Integration', '2': 'South Panel Electrical integration', '5': 'South and bus Electrical Integration', '4': 'North and Bus Electrical integration', '6': 'S/C Electrical Integration', '75': 'Hazardous Processing Facility Operations', '39': 'Final Alignment Verif. CATR Preps', '77': 'Launch Complex Performance', '76': 'HPF Payload testing', '108': 'Lunar Eclipse Event Overlay (LTO)', '109': 'Battery Discharge Overlay (LTO)', '70': 'Launch Base Functional Performance', '102': 'On Orbit', '103': 'Station Keeping', '100': 'Prime Shift Orbit Raising', '101': 'Off Shift Orbit Raising', '106': 'Quiescent Non-Eclipse State of Health (LTO)', '107': 'Earth Eclipse Season Overlay (LTO)', '104': 'Eclipse', '105': 'Post Eclipse', '10': 'Panel RF Testing', '13': 'Integrated System Reference Performance', '12': 'End to End Satting', '15': 'Transition Monitoring (Ambient to Hot Solstice)', '14': 'Pre Thermal Vacuum performance (Ambient)', '16': 'Summer Solstice Functional Plateau', '18': 'Transition Monitoring (Hot to Cold)', '31': 'Sine Vibration', '30': 'Acoustic Vibration', '36': 'Post Dynamics Performance', '35': 'Deployments', '34': 'Launch Vehicle Adapter Fit Check', '65': 'Propulsion Global Helium'}
ListView {
anchors.fill: parent
focus: true
highlightRangeMode: ListView.StrictlyEnforceRange
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem
model: tcModel
delegate: Component {
Item {
id: item
width: window.width; height: window.height
Flickable {
id: mainScrollView
contentHeight: parent.height
contentWidth: parent.width
anchors.fill: parent
clip: true
focus: true
interactive: true
Column{
id: dataCol
spacing: 10
/* Buttons */
Row{
width: window.width
Button{
text: "Go"
action.onClicked: searchSignal("TLM_NO LIKE '" + num.text + "%'")
bgColor: "lightgreen"
width: window.width/10; height: window.width/30
}
Button{
text: "Reset"
action.onClicked: resetSignal()
bgColor: "lightgrey"
width: window.width/10; height: window.width/30
}
}
/* */
Grid{
columns: 5
spacing: 10
Text {
text: "Mnemonic"
font.bold: true
}
Text {
text: "Name"
font.bold: true
}
Text {
text: "Type"
font.bold: true
}
Text {
text: "Subtype"
font.bold: true
}
Text {
text: "Category"
font.bold: true
}
/* NEW LINE */
TextEdit {
id: num
text: TLM_NO
}
Text {
text: TLM_NAME
}
Text {
text: TLM_TYPE
}
Text {
text: (SUBTYPE ? subtypes[SUBTYPE] : "Unknown")
}
Text {
text: TLM_CATEGO
}
} /* End grid */
Separator{}
Text{
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: "<u>Limits</u>"
id: limitLabel
}
/* Limits */
ListView {
//anchors.top: limitLabel.bottom
header:
Row{
height: 30
clip: true
anchors.margins: 4
Text {
text: "Phase name"
font.bold: true
}
Text {
text: "Red low"
font.bold: true
}
Text {
text: "Yellow low"
font.bold: true
}
Text {
text: "Yellow high"
font.bold: true
}
Text {
text: "Red high"
font.bold: true
}
}
delegate: Item {
id: delegate
width: delegate.ListView.view.width;
height: 30
clip: true
anchors.margins: 4
Row {
anchors.margins: 4
anchors.fill: parent
spacing: 4;
Text {
text: PHASE_NO?phases[PHASE_NO]:"N/A"
}
Text {
text: CRIT_LO?CRIT_LO:"N/A"
}
Text {
text: NOM_LO?NOM_LO:"N/A"
}
Text {
text: NOM_HI?NOM_HI:"N/A"
}
Text {
text: CRIT_HI?CRIT_HI:"N/A"
}
}
}
model: limitModel
height: window.height / 3
} /* End limits grid view*/
Separator{}
Text{
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: "end limits"
}
}/* End column*/
}
}
}
}
}
Verbatim #2 (main.cpp , excerpt):
/* Let's create all the models associated with this given user form.*/
/* We need the viewer to connect all the signals and to set context properties.*/
QmlApplicationViewer viewer;
SqlQueryModel *mainModel;
QList<SqlQueryModel*>::iterator umIt;
QHash<QString, SqlQueryModel*> modelCnx = QHash<QString, SqlQueryModel*>();
for(umIt = selectedUF.userModels.begin(); umIt != selectedUF.userModels.end(); umIt++){
SqlQueryModel *model = *umIt;
/* Let's go through each binding of the UserModel and connect create the bindings in the model. */
model->exec();
viewer.rootContext()->setContextProperty(model->modelName, model);
/* If this is the selected search model, let's save it to connect the signals later. */
if (model->modelName == selectedUF.searchModel){
mainModel = model;
}else{
QObject::connect(mainModel, SIGNAL(bindedValueChanged(QString, QString, QVariant)),
model, SLOT(updateBindings(QString,QString,QVariant)));
}
}
viewer.setMainQmlFile(QString("qml/" + selectedUF.qml));
QObject::connect((QObject*)viewer.rootObject(), SIGNAL(searchSignal(QString)),
mainModel, SLOT(search(QString)));
QObject::connect((QObject*)viewer.rootObject(), SIGNAL(resetSignal()),
mainModel, SLOT(reset()));
viewer.showExpanded();
return app->exec();
Verbatim #3 (sqlquerymodel.cpp):
#include "sqlquerymodel.h"
SqlQueryModel::SqlQueryModel(QObject *parent) :
QSqlQueryModel(parent)
{
this->modelName = "";
this->query = "";
bindings = QHash<QString, QList<ModelBinding> >();
}
void SqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db)
{
if(query.length() == 0){
this->query = query;
}
QSqlQueryModel::setQuery(query, db);
generateRoleNames();
QSqlError le = this->lastError();
if (le.isValid()){
QString errMsg("Query was:\n%1\n\nError:\n%2");
QMessageBox::critical(0, "Query error", errMsg.arg(query).arg(le.text()));
return;
}
}
void SqlQueryModel::setQuery(const QSqlQuery &query)
{
QSqlQueryModel::setQuery(query);
generateRoleNames();
QSqlError le = this->lastError();
if (le.isValid()){
QString errMsg("Query was:\n%1\n\nError:\n%2");
qDebug() << errMsg.arg(query.lastQuery()).arg(le.text());
/* We're not using a MessageBox because it causes a segfault for some reason. */
//QMessageBox::critical(0, "Query error", errMsg.arg(query.lastQuery()).arg(le.text()));
return;
}
}
/**
* #brief SqlQueryModel::exec This function prepares and executes the query.
*/
void SqlQueryModel::exec()
{
qDebug() << "Executing query on model" << this->modelName;
/* Let's create a QSqlQuery. It will store the query and we'll bind values to it.*/
QSqlQuery sQuery;
/* If we initialize the query with the string, then we CANNOT use bind (won't work and won't show any error).*/
sQuery.prepare(this->query);
/** Now, let's go through all the models associated to this instance.
* For each of them, we'll bind its value. Note that we're avoiding making a copy by using the adresses
* cf. : http://stackoverflow.com/questions/17106243/qt-iterator-not-accessing-the-correct-object
**/
QHash<QString, QList<ModelBinding> >::iterator bindingsIt;
for (bindingsIt = bindings.begin(); bindingsIt != bindings.end(); bindingsIt++){
QList<ModelBinding>::iterator eachBindingIt;
QList<ModelBinding>& curBinding = *bindingsIt;
for(eachBindingIt = curBinding.begin(); eachBindingIt != curBinding.end(); eachBindingIt++){
ModelBinding& binding = *eachBindingIt;
binding.bindToQuery(&sQuery);
}
}
/* Let's not forget to execute this query, or nothing will be displayed in the QML. */
sQuery.exec();
qDebug() << "----------------";
qDebug() << sQuery.lastQuery();
QMapIterator<QString, QVariant> i(sQuery.boundValues());
while (i.hasNext()) {
i.next();
qDebug() << i.key().toAscii().data() << "="
<< i.value().toString().toAscii().data();
}
qDebug() << "----------------";
this->setQuery(sQuery);
}
void SqlQueryModel::generateRoleNames()
{
QHash<int, QByteArray> roleNames;
for( int i = 0; i < record().count(); i++) {
roleNames[Qt::UserRole + i + 1] = record().fieldName(i).toAscii();
}
qDebug() << "Generating role names for" << modelName;
setRoleNames(roleNames);
}
void SqlQueryModel::search(QString str){
QString nQuery (query);
nQuery.append(" WHERE ").append(str);
qDebug() << "Set query to: " << nQuery;
this->setQuery(nQuery);
QSqlError le = this->lastError();
if (le.isValid()){
QString errMsg("An error occurred while loading the file.\n\nQuery was:\n%1\n\nError:\n%2");
QMessageBox::critical(0, "Database error", errMsg.arg(nQuery).arg(le.text()));
}
}
QVariant SqlQueryModel::data(const QModelIndex &index, int role) const
{
QVariant value = QSqlQueryModel::data(index, role);
if(role < Qt::UserRole){
value = QSqlQueryModel::data(index, role);
}else{
int columnIdx = role - Qt::UserRole - 1;
QModelIndex modelIndex = this->index(index.row(), columnIdx);
value = QSqlQueryModel::data(modelIndex, Qt::DisplayRole);
qDebug() << modelName << ":" << record().fieldName(columnIdx) << "=" << value;
emit bindedValueChanged(modelName, record().fieldName(columnIdx), value);
}
return value;
}
void SqlQueryModel::reset()
{
qDebug() << "Resetting original SQL query to: " << query;
this->setQuery(query);
}
void SqlQueryModel::updateBindings(QString modelName, QString col, QVariant val)
{
/** Now, let's go through all the models associated to this instance.
* We're going to see if the new signal we got is used for this model (for model name and column name).
* If so, we'll assigned it and then we'll execute this query by calling exec().
**/
bool anyValueChanged = false;
QHash<QString, QList<ModelBinding> >::iterator bindingsIt;
for (bindingsIt = bindings.begin(); bindingsIt != bindings.end(); bindingsIt++){
QList<ModelBinding>::iterator eachBindingIt;
QList<ModelBinding>& curBinding = *bindingsIt;
for(eachBindingIt = curBinding.begin(); eachBindingIt != curBinding.end(); eachBindingIt++){
ModelBinding& binding = *eachBindingIt;
if(bindingsIt.key() == modelName && binding.column == col){
binding.value = val;
anyValueChanged = true;
}
}
}
if (anyValueChanged){
this->exec();
}
}
Verbatim #4 (modelbinding.cpp):
#include "modelbinding.h"
ModelBinding::ModelBinding(QString placeholder, QString column, QVariant value)
{
this->placeholder = placeholder;
this->column = column;
this->value = value;
}
void ModelBinding::bindToQuery(QSqlQuery *sQuery)
{
sQuery->bindValue(placeholder, value);
}
The item in your base ListView delegate is sized to the window's height and width. I believe this would effectively hide any other delegates from the root level ListView because the first delegate would take up the entire screen.

Resources