Writing to file doesn’t work in Qt5/Qml - c++

for my QML project I need a simple IODevice to work with files so I took this one from Nokia Dev
But I tweaked it a little, for purposes of my work.
Reading from file works like a charm(this proves, that there is no “wrong path to file” problem”), but writing to file is broken, and I can’t find a reason why.
Here is the code:
fileio.h
#ifndef FILEIO_H
#define FILEIO_H
#include <QObject>
class FileIO : public QObject
{
Q_OBJECT
public:
explicit FileIO(QObject *parent = 0);
Q_INVOKABLE QString read(const QString& Url);
Q_INVOKABLE bool write(const QString& Url, QString data);
public slots:
signals:
void error(const QString& msg);
private:
QString mSource;
};
#endif // FILEIO_H
fileio.cpp
#include "fileio.h"
#include <QFile>
#include <QTextStream>
FileIO::FileIO(QObject *parent) :
QObject(parent)
{
}
QString FileIO::read(const QString& Url)
{
mSource = Url;
if (mSource.isEmpty()){
emit error("source is empty");
return QString();
}
QFile file(mSource);
QString fileContent;
if ( file.open(QIODevice::ReadOnly) ) {
QString line;
QTextStream t( &file );
t.setCodec("UTF-8");
do {
line = t.readLine();
fileContent += line;
} while (!line.isNull());
file.close();
} else {
emit error("Unable to open the file");
return QString();
}
return fileContent;
}
bool FileIO::write(const QString& Url, QString data)
{
mSource = Url;
if (mSource.isEmpty()){
emit error("source is empty");
return false;}
QFile file(mSource);
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
emit error("Error");
return false;}
QTextStream out(&file);
out << data;
//emit error("data:" + data); //This one was used to debug, Yet no errors were emmited when Write is called
file.close();
return true;
}
I needed my app to load settings from external file (I cant use QSettings, as I wish to give user access these settings by external script or through text editor when app is not launched). So for every setting I have a file with a single Utf-8 string, which is loaded into qml (smth like
property string interfacecolor1 : myFile.read("://settings/color1");
), and it works.
But I also want to change settings in qml
Example would be:
TextField{
id:fieldsurname
Layout.fillWidth: true
text: myFile.read("://settings/surname"); //Shows user current setting, works perfectly
onTextChanged: {console.log(fieldsurname.text); //I just check if textfield behaves as supposed, returns what I expect from it.
myFile.write("://settings/surname", fieldsurname.text); //Write text from textfield (it will be for an embeded platform, so I probably need to change setting every new char)
surname = myFile.read("://settings/surname"); //I write new setting to property from new text from file
console.log(myFile.read("://settings/surname")) //Returns an unchanged string
}
}
Also forgot to mention, that manualy editing files also works, settings are changed accordingly, app behaves as it should.
So the question is: What is wrong?
Ps: this is a duplicate of this question on qt-project but the question got burried, and I need an answer ASAP. Thanks in advance.

You can use QSettings to save the settings of your application :
QSettings settings("organizationName","applicationName");
settings.setValue("settings/surname",fieldsurname.text);
Or read them :
surname = settings.value("settings/surname","").toString();
But in case it is necessary to use files(You may want to import settings from other devices using files) You should note that the files in Qt resources are readonly. So you should first copy your file to some location if you want to change it:
QFile dfile("://settings/surname");
if (dfile.exists())
{
dfile.copy("./surname");
QFile::setPermissions("./surname",QFile::WriteOwner | QFile::ReadOwner);
}

Qrc files are read-only. You cannot write to them. You'll have to put the file into the real filesystem and read/write it from/to there.

Related

How to access a file with only the filepath as a string in Qt/C++?

I currently have the filepath of the file that I want to access as a string, but I'm not sure if Qt has a feature that allows you to access that file with only the filepath.
I'm saving the filepath to an INI file and I want to take that filepath to open the json file that is a part of that path. This is what I've tried so far - the code would go into openFile()
void saveFileLocation(QString filename)
{
QSettings *settings = new QSettings(Ve::Widgets::SettingsWindowWidget::INI_FILE, QSettings::IniFormat);
QDir dir;
QString filePath = dir.filePath(filename);
settings->setValue("projectFile", filePath);
on_menuRecent_Files_aboutToShow(filePath);
}
void openFile(QString filepath)
{
*insert code here*
}
void on_menuRecent_Files_aboutToShow(QString filePath)
{
QAction* openAction = ui->menuRecent_Files->addAction(filePath);
connect(openAction, SIGNAL(triggered()), this, SLOT(openFile(filePath)));
}
I want to implement an action option, that has text of the filepath, and when clicked, opens up the file that I want to access. Is there a Qt feature that allows you to do this?
Try this:
To open with system default associated application:
void openFile(QString filepath)
{
QDesktopServices::openUrl(QUrl::fromLocalFile( filepath ));
}
To open with specific application:
void openFile(QString filepath)
{
// open with notepad
QProcess::execute("notepad \""+ filepath +"\"");
}
Hope it helps you.

QSqlDatabase: How to avoid 'qt_sql_default_connection' still in use & duplicate connection related warning?

Sorry if this is a trivial question but I have been trying to build a small .ui that used QSQLITE as database and that uses QTableView to show 4 columns on a default database file as example.
I debugged the problem in every side, changed logical operations of the SQL and restructured the constructor in a more simple way but the error still stays.
After finishing to set up all parameters I am getting this error:
QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.
And
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.
I looked on several sources that describe this error such as this source, this other source. Also this was useful but still nothing happens. Official documentation suggests a "wrong" and "right" way to do that here. but the error still stays. After all these different options I brought back the code to a more concise way and I hope that someone can shed light on this issue.
Below the snipped of code:
mainwindow.h
private:
QString temporaryFolder;
dataInfo *mNewDatabaseImages;
QSqlTableModel *mNewTableImages;
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
temporaryFolder = "/home/to/Desktop/tempDBFolder/tmp.db";
QFile dbRem(temporaryFolder);
dbRem.remove();
mNewDatabaseImages = new dataInfo(this);
mNewDatabaseImages->initDataBase(temporaryFolder);
mNewDatabaseImages->confDataBase();
mNewTableImages = new QSqlTableModel(this, mNewDatabaseImages->getDatabase());
mNewTableImages->setTable("leftCamTable");
mNewTableImages->select();
ui->bookMarkTableView->setModel(mNewTableImages);
ui->bookMarkTableView->showColumn(true);
}
datainfo.h
#ifndef DATAINFO_H
#define DATAINFO_H
#include <QObject>
#include <QSqlDatabase>
#include "imageparam.h"
class dataInfo : public QObject
{
Q_OBJECT
public:
explicit dataInfo(QObject *parent = nullptr);
bool initDataBase(const QString &nameDB);
bool confDataBase();
bool addItem(ImageParam* imageItem);
QSqlDatabase getDatabase();
private:
QString mError;
QSqlDatabase mDBImages;
};
#endif // DATAINFO_H
datainfo.cpp
#include "datainfo.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QVariant>
#include <QMessageBox>
#define CREATE_TABLE \
" CREATE TABLE IF NOT EXISTS imageTable" \
" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL" \
" path1 TEXT NOT NULL" \
" path2 TEXT NOT NULL" \
" imageA BLOB NOT NULL" \
" imageB BLOB NOT NULL)"
dataInfo::dataInfo(QObject *parent) : QObject(parent)
{}
bool dataInfo::initDataBase(const QString &nameDB)
{
mDBImages = QSqlDatabase::addDatabase("QSQLITE");
mDBImages.setDatabaseName(nameDB);
bool ok = mDBImages.open();
if(!ok) {
mError = mDBImages.lastError().text();
qDebug() << mError;
}
return ok;
}
bool dataInfo::confDataBase()
{
QSqlQuery qry;
bool ok = qry.exec(CREATE_TABLE);
if(!ok) {
mError = qry.lastError().text();
}
return ok;
}
bool dataInfo::addItem(ImageParam *imageItem)
{
QSqlQuery qry;
qry.prepare("INSERT INTO imageTable (path1, path2, imageA, imageB)" \
" VALUES (?,?,?,?)");
qry.addBindValue(imageItem->path1());
qry.addBindValue(imageItem->path2());
qry.addBindValue(imageItem->image1());
qry.addBindValue(imageItem->image2());
bool ok = qry.exec();
if(!ok) {
mError = qry.lastError().text();
}
return ok;
}
QSqlDatabase dataInfo::getDatabase()
{
return mDBImages;
}
I looked also at this post that suggested to set a name to the databse first but I already do that in the function initDataBase(const QString &nameDB). Here the post that suggested the procedure, which is below:
db->setDatabaseName("name");
if(!db->open()) {
qDebug() << "Error opening ";
return false;
}
Please shed light on the possible solution.
Short answer
You should specify the database you want to run your QSqlQuery on, otherwise they will run on the default database. You can specify the database in QSqlQuery's constructor with
QSqlQuery query(QSqlDatabase::database("my-db"));
You are keeping a copy of the QSqlDatabase as a member of your dataInfo class, which will prevent it prevent closing properly. Instead, just use the static QSqlDatabase::database("name") when needed.
auto db = QSqlDatabase::database("my-db");
Details
Providing the right database to QSqlQuery
Change all your uses of QSqlQuery. For example for confDataBase:
bool dataInfo::confDataBase()
{
// Explicitly provide your database to the query
// Otherwise the default database is used
QSqlQuery qry(getDatabase());
bool ok = qry.exec(CREATE_TABLE);
if(!ok) {
mError = qry.lastError().text();
}
return ok;
}
Not keeping QSqlDatabase attributes
From the documentation:
Warning: It is highly recommended that you do not keep a copy of the QSqlDatabase around as a member of a class, as this will prevent the instance from being correctly cleaned up on shutdown. If you need to access an existing QSqlDatabase, it should be accessed with database(). If you chose to have a QSqlDatabase member variable, this needs to be deleted before the QCoreApplication instance is deleted, otherwise it may lead to undefined behavior.
Store your database's name in your class instead, and change your getDatabase to
dataInfo.cpp
bool dataInfo::initDataBase(const QString &nameDB)
{
// Save database's name
mDBName = nameDB;
// Use the database locally, without storing it
auto dbImages = QSqlDatabase::addDatabase("QSQLITE", nameDB);
bool ok = dbImages.open();
if(!ok) {
mError = dbImages.lastError().text();
qDebug() << mError;
}
return ok;
}
QSqlDatabase dataInfo::getDatabase()
{
return QSqlDatabase::database(mDBName);
}
dataInfo.h
private:
QString mError;
QString mDBName;
Qt's code generating the warning
To have a look at the actual code producing the error: https://code.woboq.org/qt5/qtbase/src/sql/kernel/qsqldatabase.cpp.html#170
invalidateDb is used when connections are added or removed, and will trigger the error if the reference count > 1. As you are holding onto one, this will trigger the error.

Set renderer of QGraphicsSvgItem on preprocessed svg xml document very slow

I am using QGraphicsSvgItem subclass, that reads some content from a file, places content into a QDomDocument, does some initial processing, then sets the processed DOM onto a renderer.
During program processing, additional changes are required on a copy of pre-processed DOM, so the DOM is stored in class. After changes, the DOM is placed on renderer.
class MyGraphicsSvgItem : public QGraphicsSvgItem
{
public:
MyGraphicsSvgItem (QGraphicsItem *parent = 0):
QGraphicsSvgItem(parent),
_svgXML() {}
~MyGraphicsSvgItem () { delete renderer(); }
void CheckAndChangeSomeThings() {}
void LoadStuff (QString fileName)
{
QFile file(fileName);
file.open(QFile::ReadOnly | QFile::Text);
QTextStream in(&file);
QString svgContent = in.readAll();
file.close();
_svgXML.setContent(svgContent);
CheckAndChangeSomeThings(); // this modifies _svgXML
QByteArray _data = _svgXML.toByteArray();
setSharedRenderer(new QSvgRenderer(_data)); // very slow
}
void ChangeThingslater();
void ChangeSomeThingslater()
{
ChangeThingslater(); // this modifies _svgXML
renderer()->load(_svgXML.toByteArray()); // very slow - no file involved
}
protected:
QDomDocument _svgXML;
};
There seems to be a significant slow processing during the lines that assign the DOM to the renderer.
QByteArray _data = _svgXML.toByteArray();
setSharedRenderer(new QSvgRenderer(_data));
If I skip the DOM processing - if I set the renderer to the file - the code speeds up considerably:
Leaving all the code in, but replacing
setSharedRenderer(new QSvgRenderer(_data)); // VERY SLOW
with
setSharedRenderer(new QSvgRenderer(fileName)); // FAST
So it seems the bottleneck is loading the svg renderer from QByteArray.
I looked for alternatives... there is no mention of performance in documentation
QSvgRenderer::QSvgRenderer(const QString & filename, QObject * parent
= 0)
Constructs a new renderer with the given parent and loads the contents of the SVG file with the specified filename.
QSvgRenderer::QSvgRenderer(const QByteArray & contents, QObject *
parent = 0)
Constructs a new renderer with the given parent and loads
the SVG data from the byte array specified by contents.
QSvgRenderer::QSvgRenderer(QXmlStreamReader * contents, QObject *
parent = 0)
Constructs a new renderer with the given parent and loads
the SVG data using the stream reader specified by contents.
Looking in QXmlStreamReader Class, I find that its constructors are similar ! In addition, it says
In some cases it might also be a faster and more convenient alternative for use in applications that would otherwise use a DOM tree
I seem to be going in circles, and even though having already a well formed xml in the DOM, it seems I cannot take advantage of it !
What are my alternatives, to either loading the renderer from the pre-processed DOM, or to a different way of pre-processing the xml - using something other than DOM that the renderer can read fast ?
qt 4.8. c++
You can do all the DOM processing in a worker method that's executed on the thread queue using QtConcurrent::run.
You can use the QSvgRenderer directly in your item. Initialize it in the worker method, and load from QByteArray and not a file. You can then pass the renderer to the GUI thread and use it to render the graphics item by setting it on the QGraphicsSvgItem.
Caveats:
Since you create the renderer in a worker thread, you must move it to a null thread after you've done using it in the worker thread. Conversely, you must move it to the GUI thread once it has been received by the GUI thread.
Recall that moveToThread can only be called from the object's current thread, or any thread if thread() == 0.
In Qt 4.8, there's a bug in QGraphicsSvgItem::setSharedRenderer: it doesn't properly connect the renderer's repaintNeeded signal to its update method. The work around this to connect the signal manually to your own update slot.
This will prevent the GUI from getting blocked by the long processing.
Reentering the event loop, as you do, from within the item is a source of bugs and just a very bad idea from the design standpoint. Use the non-blocking API of the file dialog instead.
Below is an example that demonstrates this technique. It also displays a small spinner when the item is being loaded/processed. There's a simulated delay for this purpose.
#include <QGraphicsView>
#include <QGraphicsSvgItem>
#include <QGraphicsSceneMouseEvent>
#include <QFileDialog>
#include <QSvgRenderer>
#include <QDomDocument>
#include <QtConcurrentRun>
#include <QFutureWatcher>
#include <QThread>
#include <QApplication>
struct Thread : public QThread { using QThread::sleep; }; // Needed for Qt 4 only
class RendererGenerator {
QString m_fileName;
void process(QDomDocument &) {
Thread::sleep(3); /* let's pretend we process the DOM for a long time here */
}
QByteArray generate(const QByteArray & data) {
QDomDocument dom;
dom.setContent(data);
process(dom);
return dom.toByteArray();
}
public:
typedef QSvgRenderer * result_type;
RendererGenerator(const QString & fileName) : m_fileName(fileName) {}
QSvgRenderer * operator()() {
QFile file(m_fileName);
if (file.open(QIODevice::ReadOnly)) {
QByteArray data = file.readAll();
QScopedPointer<QSvgRenderer> renderer(new QSvgRenderer);
renderer->load(generate(data));
renderer->moveToThread(0);
return renderer.take();
}
return 0;
}
};
class UserSvgItem : public QGraphicsSvgItem {
Q_OBJECT
QSvgRenderer m_spinRenderer, * m_lastRenderer;
QScopedPointer<QSvgRenderer> m_renderer;
QFuture<QSvgRenderer*> m_future;
QFutureWatcher<QSvgRenderer*> m_watcher;
QGraphicsView * aView() const {
QList<QGraphicsView*> views = scene()->views();
return views.isEmpty() ? 0 : views.first();
}
Q_SLOT void update() { QGraphicsSvgItem::update(); }
void mousePressEvent(QGraphicsSceneMouseEvent * event) {
if (event->button() == Qt::LeftButton) askForFile();
}
void setRenderer(QSvgRenderer * renderer) {
if (m_lastRenderer) disconnect(m_lastRenderer, SIGNAL(repaintNeeded()), this, SLOT(update()));
setSharedRenderer(renderer);
m_lastRenderer = renderer;
connect(renderer, SIGNAL(repaintNeeded()), SLOT(update()));
if (aView()) aView()->centerOn(this);
}
void askForFile() {
QFileDialog * dialog = new QFileDialog(aView());
connect(dialog, SIGNAL(fileSelected(QString)), SLOT(loadFile(QString)));
dialog->setAcceptMode(QFileDialog::AcceptOpen);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
}
Q_SLOT void loadFile(const QString & file) {
if (m_future.isRunning()) return;
setRenderer(&m_spinRenderer);
m_future = QtConcurrent::run(RendererGenerator(file));
m_watcher.setFuture(m_future);
}
Q_SLOT void rendererReady() {
m_renderer.reset(m_future.result());
m_renderer->moveToThread(thread());
setRenderer(m_renderer.data());
}
public:
UserSvgItem(const QString & fileName = QString(), QGraphicsItem *parent = 0) :
QGraphicsSvgItem(fileName, parent), m_lastRenderer(0) {
connect(&m_watcher, SIGNAL(finished()), SLOT(rendererReady()));
setFlags(QGraphicsItem::ItemClipsToShape);
setCacheMode(QGraphicsItem::NoCache);
}
void setWaitAnimation(const QByteArray & data) { m_spinRenderer.load(data); }
};
namespace {
const char svgCircle[] =
"<svg height=\"100\" width=\"100\"><circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"3\" fill=\"red\" /></svg>";
const char svgRectangle[] =
"<svg width=\"400\" height=\"110\"><rect width=\"300\" height=\"100\" style=\"fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)\"></svg>";
const char svgThrobber[] =
"<svg width=\"16\" height=\"16\" viewBox=\"0 0 300 300\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"><path d=\"M 150,0 a 150,150 0 0,1 106.066,256.066 l -35.355,-35.355 a -100,-100 0 0,0 -70.711,-170.711 z\" fill=\"#3d7fe6\"><animateTransform attributeName=\"transform\" attributeType=\"XML\" type=\"rotate\" from=\"0 150 150\" to=\"360 150 150\" begin=\"0s\" dur=\"1s\" fill=\"freeze\" repeatCount=\"indefinite\" /></path></svg>";
void write(const char * str, const QString & fileName) {
QFile out(fileName);
if (out.open(QIODevice::WriteOnly | QIODevice::Truncate)) out.write(str);
}
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
write(svgRectangle, "rectangle.svg"); // Put svg resources into the working directory
write(svgCircle, "circle.svg");
QGraphicsScene scene;
UserSvgItem item("circle.svg");
QGraphicsView view(&scene);
scene.addItem(&item);
item.setWaitAnimation(QByteArray::fromRawData(svgThrobber, sizeof(svgThrobber)-1));
view.show();
return app.exec();
}
#include "main.moc"

QFile -- not reopening in text editor

There are two slots for open & close in my gui.
When i open a file its content are shown in text editor, then i press close button changes are save to file.
But Now when i again press, open & reload the same file. Nothing is shown in text editor, blank editor.
Why file is not reloading ?
private:
Ui::MainWindow *ui;
QFile file;
QTextStream out;
QString url; // the url of the file
void MainWindow::on_actionOpen_triggered()
{
QString openfileurl = QFileDialog::getOpenFileName();
if(openfileurl.isEmpty() || openfileurl == url) return;
file.setFileName(openfileurl);
//if(file.open(QIODevice::ReadOnly|QIODevice::Text))
if(file.open(QIODevice::ReadWrite|QIODevice::Text))
{
url = openfileurl;
ui->textEdit->setPlainText(QString::fromUtf8(file.readAll()));
}
//Set file to -- Qtextstream
out.setDevice(&file);
}
void MainWindow::on_actionClose_triggered()
{
//Set file to -- Qtextstream
out << ui->textEdit->toPlainText();
file.close();
ui->textEdit->clear();
}
Try this way
void MainWindow::on_actionClose_triggered()
{
//Set file to -- Qtextstream
out << ui->textEdit->toPlainText();
file.close();
ui->textEdit->clear();
uri.clear();
}
I think you should clear uri before make this check:
if(openfileurl.isEmpty() || openfileurl == url) return;
It will blowup when openfileurl == url. And it will do it definitely sure if you didn't cleared the uri. And here you are:
reload the same file
...with the same content... so, the if statement goes true and returns that's why the code below is not executing the second time.

Creating an Efficient Function

I am a beginner in my fourth week learning C++; I had been working on CodeBlocks, but due to my interest in making GUIs I switched to Qt Creator. Back in CodeBlocks I had created a function that would avoid all the repetition in the code below, only changing the "TXT FILE". However, with Qt Creator's "specialized" C++ I am having trouble making sense of how to create a function to avoid all this repetition.
Any ideas? (I'm too far into this Qt project to go back to CodeBlocks.)
The "TXT FILE" changes depending on which RadioButton the user selects.
void MovierRec::on_searchButton_clicked()
{
int randomValue = qrand() % 100;
QList<QString> titles;
if(ui->modernButton->isChecked())
{
QFile myfile(":/classics.txt");
if (myfile.open(QIODevice::ReadOnly))
{
QTextStream in(&myfile);
while (!in.atEnd())
{
QString line = in.readLine();
titles.append(line);
}
myfile.close();
ui->textBrowser->setPlainText (titles[randomValue]);
}
}
else if(ui->romanceButton->isChecked())
{
QFile myfile(":/romance.txt");
if (myfile.open(QIODevice::ReadOnly))
{
QTextStream in(&myfile);
while (!in.atEnd())
{
QString line = in.readLine();
titles.append(line);
}
myfile.close();
ui->textBrowser->setPlainText (titles[randomValue]);
}
}
else if(ui->scifiButton->isChecked())
{
QFile myfile(":/scifi.txt");
if (myfile.open(QIODevice::ReadOnly))
{
QTextStream in(&myfile);
while (!in.atEnd())
{
QString line = in.readLine();
//titles.append(line);
}
myfile.close();
ui->textBrowser->setPlainText (titles[randomValue]);
}
}
This is generic programming issue, could refactor code in a better way:
// I didn't dig into every line of the code. just provide the refactor idea here
void getTitle(const QString& file_name, QList<QString>& titles;)
{
QFile myfile(file_name);
if (myfile.open(QIODevice::ReadOnly))
{
QTextStream in(&myfile);
while (!in.atEnd())
{
QString line = in.readLine();
titles.append(line);
}
myfile.close();
}
}
void MovierRec::on_searchButton_clicked()
{
int randomValue = qrand() % 100;
QList<QString> titles;
if(ui->modernButton->isChecked())
{
getTitle("classics.txt", titles);
}
else if(ui->romanceButton->isChecked())
{
getTitle("romance.txt", titles);
}
else if(ui->scifiButton->isChecked())
{
getTitle("scifi.txt", titles);
}
ui->textBrowser->setPlainText(titles[randomValue]); // move the dup action to the end
}
QT is well known for Signals and Slots. Each button can be connected to a slot. For Example in your case. You can connect each radio button to a slot. in order to do that, Open ur GUI form, right click on the radio button and select "Go To Slot", and select the slot you want to connect to.
This will create an empty function in ur .cpp file.
Now write your code for that button. And this function is called only when that particular Button is pressed/clicked .
example:
void ClassA::on_radioButton_clicked()
{
// write your code inside this function for , when this button is checked
}
I hope this will help you solve your issue. If you have other query , please provide more information.