How to implement custom boolean widget for use with QDataWidgetMapper? - qt

What do I have to implement to make my own boolean widget for use with QDataWidgetMapper?
I have created a USER property that the mapper is, to my understanding, supposed to use.
The interaction with the database via QSqlTableModel using the (same) QDataWidgetMapper works with qt's own widgets, but does not seem to work with this widget I created.
Even though the widget works and displays database data, changing widget value does not change the value in the database. [correction: data from database is read to the widget state ok.]
Current header file:
#ifndef COMPENSATIONCONTROLCHECKABLE_H
#define COMPENSATIONCONTROLCHECKABLE_H
#include <QAbstractButton>
#include <QWidget>
namespace Ui {
class CompensationControlCheckable;
}
class CompensationControlCheckable : public QAbstractButton
{
Q_OBJECT
Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY compensationChanged USER true )
public:
explicit CompensationControlCheckable(QWidget *parent = 0);
~CompensationControlCheckable();
void setChecked(bool checkd);
const bool isChecked() const;
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
private slots:
void on_startCompensation_clicked();
void on_cancelCompensation_clicked();
signals:
void compensationChanged(bool);
void checked(bool);
private:
bool checkedValue;
Ui::CompensationControlCheckable *ui;
};
#endif // COMPENSATIONCONTROLCHECKABLE_H
Version 2, now I have removed checked overrides and instead call the QAbstractButton setChecked and isChecked in setCompensation and isCompensation, respectively. The constructor calls setCheckable(true);. This works exactly as above; reading from db ok, writing to db does not work:
#ifndef COMPENSATIONCONTROLCHECKABLE_H
#define COMPENSATIONCONTROLCHECKABLE_H
#include <QAbstractButton>
#include <QWidget>
namespace Ui {
class CompensationControlCheckable;
}
class CompensationControlCheckable : public QAbstractButton
{
Q_OBJECT
Q_PROPERTY(bool compensation READ isCompensation WRITE setCompensation NOTIFY compensationChanged USER true )
public:
explicit CompensationControlCheckable(QWidget *parent = 0);
~CompensationControlCheckable();
void setCompensation(bool checkd);
bool isCompensation() const;
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
private slots:
void on_startCompensation_clicked();
void on_cancelCompensation_clicked();
signals:
void compensationChanged(bool);
private:
bool compensationValue;
Ui::CompensationControlCheckable *ui;
};
#endif // COMPENSATIONCONTROLCHECKABLE_H

QDataWidgetMapper prefers to use the property with USER true for its mapping but there already one called checked in QAbstractButton use that property instead. You may need to call isCheckable(true) in the constructor;

Related

enable/disable widget using mousePressEvent/mouseReleaseEvent

I have a set of widgets to control a parameter in five similar places (or channels).
Now I can enable/disable each of these widgets using a pushbuttons, as follows.
connect(ui->pushButton_currOnOne, &QPushButton::clicked, ui->widget_currentOne, &CurrentButtonOne::setEnabled);
connect(ui->pushButton_currOnTwo, &QPushButton::clicked, ui->widget_currentTwo, &CurrentButtonOne::setEnabled);
connect(ui->pushButton_currOnThree, &QPushButton::clicked, ui->widget_currentThree, &CurrentButtonOne::setEnabled);
connect(ui->pushButton_currOnFour, &QPushButton::clicked, ui->widget_currentFour, &CurrentButtonOne::setEnabled);
connect(ui->pushButton_currOnFive, &QPushButton::clicked, ui->widget_currentFive, &CurrentButtonOne::setEnabled);
Can I use mousePressEvent/mouseReleaseEvent instead of using &QPushButton::clicked in the above scenario?
It will be very helpful if you could show me an example.
Thanks in advance
Some code to get you started.
mybutton.h:
#include <QObject>
#include <QPushButton>
#include <QMouseEvent>
class MyButton : public QPushButton
{
public:
explicit MyButton(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
private:
bool isPressed = false;
signals:
void myButtonPressed();
};
mybutton.cpp:
#include "mybutton.h"
MyButton::MyButton(QWidget *parent) : QPushButton(parent)
{
}
void MyButton::mousePressEvent(QMouseEvent *e)
{
isPressed = true;
emit myButtonPressed();
QPushButton::mousePressEvent(e);
}
void MyButton::mouseReleaseEvent(QMouseEvent *e)
{
isPressed = false;
QPushButton::mouseReleaseEvent(e);
}
I'm not sure, what exactly you are trying to achieve, but this idea should meet your needs.
You create a class, which inherits from QPushButton (or QAbstractButton) and override its mousePressEvent and mouseReleaseEvent. If you want some other widgets to react on this events, you emit signal and connect other widgets to that signal.

Calling C++ method from QML

HERE IS Qt PROJECT with minimal skeleton to show what is the problem (check console after you run that project)
http://uloz.to/xqxrXpdL/qtproject-zip
I try to call public slot from qml
Component.onCompleted: print(model.activate())
Still getting error:
TypeError: Property 'activate' of object QQmlDMObjectData(0x7fa35dd89eb0) is not a function
If i tried to call the method dynamically from C++, it works:
auto item = new TreeItem<MainMenuItem>(new MainMenuItem("kyklop"));
QMetaObject::invokeMethod(item, "activate");
If i try to access regular property of my TreeItemTemplateBackend class from qml (for instance level), it works, so problem is only if calling method. I am thinking it could be something with that subclass/template class.
Registering to qml:
qmlRegisterType<TreeItemTemplateBackend>("engine.ui", 1, 0, "TreeItemTemplateBackend");
qmlRegisterType<TreeItem<InspectorItem>>("engine.ui", 1, 0, "InspectorTreeItem");
qmlRegisterType<TreeItem<MainMenuItem>>("engine.ui", 1, 0, "MainMenuTreeItem");
TreeItem.h
#ifndef TREEITEM_H
#define TREEITEM_H
#include <QObject>
#include "TreeItemTemplateBackend.h"
template <typename T>
class TreeItem : public TreeItemTemplateBackend
{
public:
explicit TreeItem(QObject * parent = NULL);
explicit TreeItem(T * data, QObject * parent = NULL);
explicit TreeItem(TreeItem<T> & other);
void addChild(TreeItem<T> * child);
~TreeItem() {}
};
#endif // TREEITEM_H
TreeItemTemplateBackend.h
#ifndef TREEITEMTEMPLATEBACKEND_H
#define TREEITEMTEMPLATEBACKEND_H
#include <QList>
#include <QQmlListProperty>
class TreeItemTemplateBackend : public QObject
{
Q_OBJECT
Q_PROPERTY(QObject * data READ data WRITE setData NOTIFY dataChanged)
Q_PROPERTY(QQmlListProperty<TreeItemTemplateBackend> childs READ childs NOTIFY childsChanged)
Q_PROPERTY(int level READ level WRITE setLevel NOTIFY levelChanged)
public:
explicit TreeItemTemplateBackend(QObject * parent = NULL);
QObject * data() const;
void setData(QObject * data);
QQmlListProperty<TreeItemTemplateBackend> childs() const;
void addChild(TreeItemTemplateBackend * child);
int level() const;
void setLevel(int level);
void dump(QString propertyName) const;
~TreeItemTemplateBackend() {}
signals:
void activated();
void dataChanged();
void childsChanged();
void levelChanged();
public slots:
void activate(); // this is what i am trying to call
protected:
QObject * m_data;
QList<TreeItemTemplateBackend *> m_children;
int m_level;
static void append_function(QQmlListProperty<TreeItemTemplateBackend> * property, TreeItemTemplateBackend * item);
static TreeItemTemplateBackend * at_function(QQmlListProperty<TreeItemTemplateBackend> * property, int index);
static void clear_function(QQmlListProperty<TreeItemTemplateBackend> * property);
static int count_function(QQmlListProperty<TreeItemTemplateBackend> * property);
};
#endif // TREEITEMTEMPLATEBACKEND_H
QQmlDMObjectData is a wrapper for the actual object used in delegates. The original object is accessible via the property modelData, so model.modelData.activate() should work.
If you cal for it "method" and still you are use it as a method so convert it to the method:
...
public:
void Q_INVOKABLE activate();
...

QT signal with struct in parameter

I have the class :
class SupervisionManager : public QThread {
Q_OBJECT public:
explicit SupervisionManager(ComAds* com, ComRegEtat* comEt,
ComRegOrdonnanceur* comOrdo,
QObject *parent = 0);
~SupervisionManager();
protected:
virtual void run();
private:
void actionFromPlc();
ComRegEtat::Antichoc antichoc;
signals:
void majAntichoc(ComRegEtat::Antichoc&);
};
and the implementation:
void SupervisionManager::run() {
manage=true;
while(manage)
{
actionFromPlc();
usleep(5000);
}
}
void SupervisionManager::actionFromPlc() {
antichoc.SAS = false;
emit majAntichoc(antichoc);
}
And I connect this signal with :
connect(manager, SIGNAL(majAntichoc(ComRegEtat::Antichoc&)),
preparation, SLOT(affichageAntichoc(ComRegEtat::Antichoc&)));
How do to emit a signal with a struct in its parameter list?
I think I have to use a QSignalMapper but I don't understand how.
In absolutely same way as you emit other things..
ComRegEtat::Antichoc myStruct;
.. some initialisation code
emit majAntichoc(myStruct);
I dont know for sure about latest Qt (after they changed signals/slot be templates based), but before 'emit' was just empty define, so you should look on emit like on function call...
With my code, the slot isn't called whereas the signal is emitted.
I found the solution :
signals:
void majAntichoc(ComRegEtat::Antichoc *);
and
slot :
void affichageAntichoc(ComRegEtat::Antichoc *);
And I don't have to use a QSignalMapper.
Thanks

QLineEdit mouseEnter() and mouseExit() events

I want to subclass QLineEdit to add it some signals like mouseEnter() and mouseExit() to become informed when the mouse courser is over the widget and when leaves it.
I could write mouseEnter() like below.
class MyLineEdit:public QLineEdit{
//
// ..
//
protected:
void mouseMoveEvent(QMouseEvent *e);
signals:
void mouseEnter();
}
void MyLineEdit::mouseMoveEvent(QMouseEvent *e)
{
emit mouseEnter();
QLineEdit::mouseMoveEvent(e);
}
It works correctly.
How can I write mouseExit()?
leaveEvent is not a very good name!
#include <QtGui>
#include <QEvent>
class Editor : public QLineEdit
{
Q_OBJECT
public:
void leaveEvent(QEvent *);
signals:
void mouseLeave();
};
void Editor::leaveEvent(QEvent *e);
{
qDebug() << "Mouse has left the building..";
emit mouseLeave();
}

QT no matching function for call to 'MainWindow::connect()

I have MainWindow and QNAMRedirect classes and I am trying to compile program but getting compiler error.
Here is QNAMRedirect class:
class QNAMRedirect : public QObject
{
Q_OBJECT
public:
explicit QNAMRedirect(QObject *parent = 0);
~QNAMRedirect();
signals:
public slots:
void doRequest();
void replyFinished(QNetworkReply* reply);
signals:
void finished(QString);
private:
QPointer<QNetworkAccessManager> _qnam;
QUrl _originalUrl;
QUrl _urlRedirectedTo;
QNetworkAccessManager* createQNAM();
};
and here is MainWindow class:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_request_clicked();
private:
Ui::MainWindow *ui;
};
and i am trying to connect NAMRedirect::finished(QString) signal to QTextEdit widget in MainWindow this way:
void MainWindow::on_request_clicked()
{
QNAMRedirect urlGet(this);
QObject::connect(urlGet,SIGNAL(finished(QString)),ui->textEdit,SLOT(setText(QString)));
urlGet.doRequest();
}
but i am getting compiler error:
error: no matching function for call to 'MainWindow::connect(QNAMRedirect&, const char*, QTextEdit*&, const char*)'
how can i fix that?
The reason for the compile error is that the two objects you pass to the connect() function need to be pointers. So using &urlGet (instead of just urlGet) will fix your compile error. However, as soon as your function returns this object will go out of scope and be destroyed, so I suggest you change your function to look something more like this:
QNAMRedirect *urlGet = new QNAMRedirect( this )
QObject::connect(urlGet,SIGNAL(finished(QString)),ui->textEdit,SLOT(setText(QString)));
urlGet->doRequest();
You will, of course, need to take measure that you're not leaking memory here.

Resources