Properties combination in Qt stylesheet - c++

I wrote Qt4 (or Qt5) class MyButton and defined two boolean properties, like this:
#include <QPushButton>
class MyButton : QPushButton
{
Q_OBJECT
Q_PROPERTY(bool property_1 READ property_1)
Q_PROPERTY(bool property_2 READ property_2)
public:
explicit MyButton(QWidget *parent = 0);
...
}
Now I want to customize application stylesheet in external file so that in different combinations of this properties MyButton has different background color. Separately this works well:
MyButton[property_1="true"] { background-color: black }
MyButton[property_2="true"] { background-color: white }
So the question is: how to combine few properties in the same condition with "and", "or" and "not" operations?

Finally I got the solution. The idea is the same as CSS attribute selection.
Thus property_1="true" AND property_2="true" condition is:
MyButton[property_1="true"][property_2="true"] { background-color: green; }

Related

QTextEdit how to clear the text when user typed in somethin Qt c++

I'm building gui for address ip and broadcast address calculator. And i have 3 objects in my mainwindow.ui - textEdit (you type your ip address into it), textEdit_2 (you type your subnet mask address into it), plainTextEdit (just a welcome box). This is my mainwindow.cpp.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
QString users_mask;
QString users_ip;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setStyleSheet("background-color: #484848;");
ui->textEdit->setStyleSheet("border: 1px solid white; color: gray;");
ui->textEdit->setPlainText("Enter ip address");
ui->textEdit_2->setPlainText("Enter mask address here");
ui->textEdit_2->setStyleSheet("border: 1px solid white; color: gray;");
ui->plainTextEdit->setPlainText("Welcome to the ip address calculator!");
ui->plainTextEdit->setStyleSheet("border: 1px #484848; color: #FFFFFF;");
ui->plainTextEdit->setEnabled(false);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::get(){
users_ip = ui->textEdit->toPlainText();
users_mask = ui->textEdit_2->toPlainText();
}
void MainWindow::on_calculate_clicked()
{
get();
qDebug()<<users_ip<<" -- "<<users_mask;
}
now i want the textEdit and textEdit_2 to be cleared whenever a user type something. and is there a function or smth that will allow doing that?
You're looking for the placeholderText property, but you're using the wrong widget :) Use QLineEdit instead for those address inputs. placeholderText is the hint you want shown before user begins their input.
QTextEdit is a widget meant for general multi-line text editing, and what you're trying to do is a single-line input.
You should also give the widgets self-descriptive names. Instead of having to write textEdit (you type your ip address into it) you could just name that widget ipAddress and you wouldn't need to explain anything to anyone (much less yourself in a couple months of not looking at the code).

QML: Refresh issue while receivinig C++ signals passed from C++

Hi i have bee playing recently with Qt for mobile development. I started simple using all the code in C++ (given that I have more experience with it) and now I'm starting to use QML. In my app I have a QQuickWidget in the ui where I display a map. The goal is simple to center the map every time the phone emits the coordinates.
This is how I set up my QML
ui->quickWidget->setSource(QUrl("qrc:/geom_map.qml"));
and this is my QML file
Rectangle {
width: 300
height: 300
visible: true
Plugin {
id: osmPlugin
name: "esri"
// specify plugin parameters if necessary
// PluginParameter {
// name:
// value:
// }
}
Map {
id: map
anchors.fill: parent
plugin: osmPlugin
center: QtPositioning.coordinate(51.0, -114.0)
zoomLevel: 10
activeMapType: map.supportedMapTypes[1] // This selects the type of map to display
}
I declared a class to handle the sending of the coordinates to the QML and setup a connection on the QML for receiving the signal
#ifndef COORDUPDATE_H
#define COORDUPDATE_H
#include <QObject>
#include <QVariant>
class coordUpdate : public QObject
{
Q_OBJECT
public:
explicit coordUpdate(QObject *parent = nullptr);
// Q_INVOKABLE void sendupd(double xcoord, double ycoord);
private:
signals:
void sendCoord(QVariant xcoord,QVariant ycoord);
private slots:
public slots:
void sendupd(double xcoord, double ycoord);
};
#endif // COORDUPDATE_H
#include "coordupdate.h"
#include <QDebug>
coordUpdate::coordUpdate(QObject *parent) :
QObject(parent)
{
}
void coordUpdate::sendupd(double xcoord,double ycoord){
emit sendCoord(xcoord,ycoord);
qDebug() << "signal emitted";
}
The problem I'm having is that if I call
void MainWindow::setGPSLocation(QGeoPositionInfo geoPositionInfo)
{
statusBar()->showMessage("Updating position...",1000);
QString text="Location=unknown";
if (geoPositionInfo.isValid())
{
// get the current location coordinates
QGeoCoordinate geoCoordinate = geoPositionInfo.coordinate();
// transform coordinates to lat/lon
qreal latitude = geoCoordinate.latitude();
qreal longitude = geoCoordinate.longitude();
qreal altitude = geoCoordinate.altitude();
double lon = longitude;
double lat = latitude;
//on position updated we also need to record the data
coordUpdate upd;
ui->quickWidget->rootContext()->setContextProperty("updcoord",&upd);
ui->quickWidget->setSource(QUrl("qrc:/geom_map.qml"));
upd.sendupd(longitude,latitude);
qDebug() << "reading coordinates" << longitude << latitude;
}
}
Then the coordinates get updated but the whole thing gets refreshed. Is there a better way to update the information sent to the QML file? I know I would better developing in QML exclusively but I very interested in the use of QQuickWiget for the time being.
I'm not asking how to connect a signal from C++ to QML. The code does that. What I was asking was how to properly update the map with the information passed. I already read the documentation. Unfortunately not much of the documentation focus on QQuickWidgets but rather have a main class instantiated with QQmlEngine.
As described here http://doc.qt.io/qt-5/qtqml-cppintegration-overview.html, you have basically three ways to integrate C++ with QML code :
Expose your C++ class to QML ( properties, signals, slots..) and register it as an instanciable QML type
Same as 1 but register it as a singleton type so it is instantiated by the QML engine, not explicitly in the QML code
Same as 1 but make it available to QML via context properties for example, in this case, you create the instance of your class on the C++ side of your application
Solved it by moving the Connections inside the Map and redefining in the mainwindow.cpp and mainwindow.h the way the QML is instantiated. That way the map is refreshed properly every time the QML captures the signal.
Added to mainwindow.cpp
private:
coordUpdate *upd;
Changed
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->startU->setDisabled(true);
setupLogging();
setupGPS();
coordUpdate upd;
ui->quickWidget->rootContext()->setContextProperty("updcoord",upd);
ui->quickWidget->setSource(QUrl("qrc:/geom_map.qml"));
}
to
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->startU->setDisabled(true);
setupLogging();
setupGPS();
upd = new coordUpdate;
ui->quickWidget->rootContext()->setContextProperty("updcoord",upd);
ui->quickWidget->setSource(QUrl("qrc:/geom_map.qml"));
}
and in the QML
Rectangle {
width: 300
height: 300
visible: true
Plugin {
id: osmPlugin
name: "esri"
}
Map {
id: map
anchors.fill: parent
plugin: osmPlugin
// center: QtPositioning.coordinate(y, x)
zoomLevel: 15
activeMapType: map.supportedMapTypes[1] // This selects thetype of mapa to display
MapCircle {
id:circle
center: QtPositioning.coordinate(y, x)
radius: 50
color: 'red'
}
// Create connections with c++
Connections // Define actions for custom slots
{
id:cppConnection
target: updcoord
onSendCoord: {
// To access signal parameter, name the parameter
console.log("signal received",ycoord,xcoord)
circle.center = QtPositioning.coordinate(ycoord,xcoord)
}
}
}
}

How to make the text of a QComboBox bold, but not the list items?

We have a longstanding convention in our UI that items are shown in bold when they have been changed but the change is not yet committed. Strangely, until now we haven't used any combo boxes, but I have a use for one now and need to implement this behaviour. So I need to programmatically bold (and later un-bold) the text displayed by a closed combo box. However, I don't want to bold the entire list of items in the pop-up. I could accept bolding the selected item in the list if that's easier.
I've seen lots of answers doing almost this, but usually trying to modify the list items rather than the button. I've tried variations on most of them; unfortunately I didn't keep records of what I tried. For what it's worth, my code currently looks like:
myCombo->setStyleSheet(
"QComboBox {font-weight: bold;} "
"QComboBox QAbstractItemView::item {font-weight: normal;}"
);
This turns the button bold, but also the list items. The same behaviour is seen when I apply the normal weight just to the QAbstractItemView without the ::item, and when I tried a different technique based on :open and :closed on the QComboBox.
I will say I'm fairly new to Qt. I am using Qt5 on Fedora 26, but will be deploying to CentOS 7.
It seems that setting the font-style in QComboBox overrides the view's (and it shouldn't, IMHO).
But, when I tried to explicitly set a view to the combo box, this way:
view = new QListView();
myCombo->setView(view);
the stylesheet posted by the OP suddenly worked.
By the way, the new view is different from the original (e.g. has a white background, etc) and I guess the OP isn't happy with that. One could go on styling it, of course, but one would rather prefer a ready to use view, with a consistent style.
Inspecting the default QComboBox view:
QComboBox * combo = new QComboBox();
qDebug() << combo->view();
yelds this:
QComboBoxListView(0x2091880)
So, there is a specific QComboBoxListView class, which is nowhere to be found in documentation and is defined in qcombobox_p.h, not a file one could include, really, but at least we can understand where the issue come from, in the viewOptions overridden method:
QStyleOptionViewItem option = QListView::viewOptions();
option.showDecorationSelected = true;
if (combo)
option.font = combo->font(); // <--- here
return option;
That combo is a private pointer to QComboBox, initialized in construction:
QComboBoxListView(QComboBox *cmb = 0) : combo(cmb) {}
which will always override the view options font with its own.
Let's have a copy of the QComboBoxListView class, edited and renamed:
comboitemview.h
#ifndef COMBOITEMVIEW_H
#define COMBOITEMVIEW_H
#include <QListView>
#include <QComboBox>
class ComboItemView : public QListView
{
Q_OBJECT
QComboBox * _box;
public:
ComboItemView(QComboBox *box);
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
QStyleOptionViewItem viewOptions() const;
};
#endif // COMBOITEMVIEW_H
comboitemview.cpp
#include "comboitemview.h"
#include <QPaintEvent>
#include <QPainter>
ComboItemView::ComboItemView(QComboBox * box = 0) : _box(box){}
void ComboItemView::paintEvent(QPaintEvent *event)
{
if (_box)
{
QStyleOptionComboBox opt;
opt.initFrom(_box);
opt.editable = _box->isEditable();
if (_box->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, _box))
{
QStyleOptionMenuItem menuOpt;
menuOpt.initFrom(this);
menuOpt.palette = palette();
menuOpt.state = QStyle::State_None;
menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
menuOpt.menuRect = event->rect();
menuOpt.maxIconWidth = 0;
menuOpt.tabWidth = 0;
QPainter p(viewport());
_box->style()->drawControl(QStyle::CE_MenuEmptyArea, &menuOpt, &p, this);
}
}
QListView::paintEvent(event);
}
void ComboItemView::resizeEvent(QResizeEvent *event)
{
resizeContents(viewport()->width(), contentsSize().height());
QListView::resizeEvent(event);
}
QStyleOptionViewItem ComboItemView::viewOptions() const
{
QStyleOptionViewItem option = QListView::viewOptions();
option.showDecorationSelected = true;
return option;
}
And finally use it to style the view font:
myCombo->setView(new ComboItemView(myCombo));
myCombo->setStyleSheet(
"QComboBox {font-weight: bold;} "
"QComboBox QAbstractItemView {font-weight: normal;}"
);

Qt QML Singleton Intellisense

Qt QML, they do work, but no intellisense in QML references. Can I achieve intellisense?
pragma Singleton
import QtQuick 2.0
import QtQuick.Window 2.3
Item {
property int iMode: 0
property bool bSwapLeftRight: false
Registering it:
qmlRegisterSingletonType(QUrl(QLatin1String("qrc:/GlobalSettings.qml")), "ncs.global", 1, 0, "SingletonSettings" );
Second example;:
ctxt->setContextProperty("someModel", QVariant::fromValue(ownModel));
ctxt->setContextProperty("globalControl", QVariant::fromValue(globalControl.Get()));
First one i achieve IntelliSense in QML whilst using, the second one is the singleton, I do not achieve IntelliSense. Planning to expose some c++ defined enums to QML through this one, but looses value when no IntelliSense is provided..
Question is basically, do Qt Quick and Creator support IntelliSense for singleton classes ? Worthwhile investigating further?
Adding some more details, main question is NOT about enum's, but IntelliSense (auto-complete):
A few snippets:
main.cpp:
//Regular Pointer
SomeModel* ownModel = new SomeModel();
//Custom Singleton implementation
GlobalControlSP globalControl = GlobalControl::GetInstance();
//I did not really want this line. GlobalControl should be singleton, how would this be threated?
qmlRegisterType<GlobalControl>("ncs.global", 1, 0, "Global");
//Registering a "Pragma Singleton" file, Intellisense do not work
qmlRegisterSingletonType(QUrl(QLatin1String("qrc:/GlobalSettings.qml")), "ncs.global", 1, 0, "SingletonSettings" );
QQmlApplicationEngine engine;
QQmlContext* ctxt = engine.rootContext();
//Regular context property, not singleton. Intellisense works
ctxt->setContextProperty("ownModel", QVariant::fromValue(ownModel));
//Registering the singleton as context property, Intellisense do not work
ctxt->setContextProperty("globalControl", QVariant::fromValue(globalControl.Get()));
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
globalcontrol.h:
class GlobalControl : public QObject,
{
Q_OBJECT
Q_PROPERTY(QString backcolor READ backcolor NOTIFY backcolorChanged)
....
public:
GlobalControl(QObject *parent = nullptr);
QString backcolor() const { return m_backColor; }
....
enum EnButton
{
DEVICE_START,
DEVICE_IR,
.....
};
Q_ENUM(EnButton)
public slots:
void changeMode(int mode);
void buttonPressed(int button);
some qml file:
//This implementation works:
NcsButton {
property int valuent
id:ir
text: qsTr("IR")
width: 66 * widthScaling
Layout.row: 4
Layout.column: 1
fontColor: bIr ? valueColor : textColor
onClicked: {
globalControl.buttonPressed(Global.DEVICE_IR)
//This does not work:
NcsButton {
id:ir
text: qsTr("IR")
width: 66 * widthScaling
Layout.row: 4
Layout.column: 1
fontColor: bIr ? valueColor : textColor
onClicked: {
globalControl.buttonPressed(globalControl.DEVICE_IR)
Solution or workaround:
For QML defined singleton, add to Qt compiler QML library a generated file
..\..\..\bin\qmlplugindump -relocatable ncs.global 1.0 > plugins.qmltypes
For c++ registered singleton, make a "fake" pointer of normal class type. Register. To retrieve the enum from same singleton class, create a UncreatableType:
GlobalControlSP globalControlOrig = GlobalControl::GetInstance();
GlobalControl* globalControl = globalControlOrig.Get();
ctxt->setContextProperty("globalControl", QVariant::fromValue(globalControl));
qmlRegisterUncreatableType<GlobalControl>("ncs.global", 1, 0, "Global", "Singleton");

Qt 5.2 QObject::connect: Cannot connect (null)::

I'm a noob - not good with QML or C++ yet, but getting there. I seem to have hit a stumbling block I can't get past. I'm receiving the following error in my attempt to run a build and I'm not sure what I missed in my code...
**QObject::connect: Cannot connect (null)::buttonClicked_enable() to TLA_Funcs::sys_enable()
**
I've looked through the other versions of the question here and it seems that I have my code correct, but I still get the error. Can someone take a peek? Here's the relevant sample of my code (the rest is too long and I left out the guts of the function - too long).
QML Code:
Rectangle {
id: main
width: 800
height: 600
color: "#abcfe9"
border.width: 4
border.color: "#000000"
signal buttonClicked_enable()
Button {
id: enable
x: 628
y: 55
text: "ENABLE"
onClicked:buttonClicked_enable()
}
//....
}
My class header:
#ifndef TLA_FUNCS_H
#define TLA_FUNCS_H
#include <QObject>
class TLA_Funcs : public QObject
{
Q_OBJECT
public:
explicit TLA_Funcs(QObject *parent = 0);
signals:
public slots:
Q_INVOKABLE void sys_enable(){return ;}
private:
};
#endif
And in my main.cpp file:
#include "TLA_Funcs.h"
TLA_Funcs::TLA_Funcs(QObject *parent) :
QObject(parent)
{
}
int main (int argc, char*argv[]) {
QGuiApplication app(argc, argv);
QQuickView *view = new QQuickView(QUrl("main.qml"));
view->show();
QQuickItem *item = view->rootObject();
TLA_Funcs *funcs = new TLA_Funcs();
QObject::connect(item, SIGNAL(buttonClicked_enable()), funcs, SLOT(sys_enable()));
}
I've defined the signals in the parent rectangle, and in the button code I've tried using:
onClicked:main.buttonClicked_enable()
as well as:
onClicked: {
buttonClicked_enable()
TLA_Funcs.sys_enable()
}
That didn't help either. I also tried defining the functions under "signal" in the class, but that made more of a mess. Can someone at least point me in the right direction, and keep in mind, I'm still a noob... Thanks All!!!
Problem Solved: there was an error in the .pro file. I copied the code into a new project and it worked correctly 100%. Thanks all for the help!