Creating an Efficient Function - c++

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.

Related

QstringList to Qstring conversion issues

I am working on VS2015 with qt framework. In my source code, I have a function for printing in the GUI screen.
This function is called each time something needs to be printed.
It goes like this.
void Trial::Print_MessageBox(QString string)
{
ui.MessagesScreen->appendPlainText(string);
Cursor_Messagebox.movePosition(QTextCursor::End);
ui.MessagesScreen->setTextCursor(Cursor_Messagebox);
ui.MessagesScreen->ensureCursorVisible();
}
// Output in MessageBox
void Trial::Print_MessageBox(QFlags<QNetworkInterface::InterfaceFlag> flags)
{
QString str = QString("Flag %1").arg(flags);
ui.MessagesScreen->appendPlainText(str);
}
The above function has no problems and running well.
Now I am trying to read a text file. This has set of values in no order or size. An example for this:
231, 54, 4 \n
47777, 2211, 676, 9790, 34236, 7898\n
1, 3\n
Objective is to convert these into integers (line by line) and print them in the GUI and also send them (line by line) to other system. So I tried to do it with the following.
void Trial::ReadFile_Data()
{
QFile file("input.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
Print_MessageBox("Error in reading File");
return;
}
QTextStream in(&file);
while (!in.atEnd())
{
QString line = in.readLine();
Print_MessageBox(line);
int conv = line.toInt();
QString str = QString("%1 %2").arg("Values are: ").arg(conv);
Print_MessageBox(str);
QStringList fields = line.split(",");
}
file.close();
}
When I print the "line", it is just printing the same values as in the file. When I do the conversion and printing, I get an error (which is expected) Now I try to remove "," with the help of split then I get QstringList which I cannot use as I have the Qstring function to print(this cant be changed)
I am not getting any pointers from here. Please help me out as this is bugging me since long time.
Just simple...
QStringList::const_iterator constIterator;
for (constIterator = fonts.constBegin(); constIterator != fonts.constEnd();
++constIterator) {
cout << (*constIterator).toLocal8Bit().constData() << endl;
}
where fonts is your QStringlist
Your question reduces to "How do I iterate over a QStringList".
Like this:
// C++11
for (auto field : fields) Print_messageBox(field);
// C++98
foreach (QString field, fields) Print_messageBox(field);
See here for information about how foreach a.k.a Q_FOREACH was implemented.

using QProcess->setReadChannelMode(QProcess::MergedChannels) and using QProcess->readall()

It's my first time to ask question on stackoverflow. And I'm a chinese girl, if my description about this problem has so much grammar error that you can't understand it easyly, I'm so sorry.
Below is my question:
headerfile:
class AdbDriver : public QObject
{
Q_OBJECT
private:
QString PnPutilPath_;
QProcess *process_;
public:
explicit AdbDriver(QObject *parent = 0);
~AdbDriver();
void installDriver();
};
AdbDriver::AdbDriver(QObject *parent):QObject(parent){
PnPutilPath_ = qgetenv("WINDIR") + "\\sysnative\\pnputil.exe";
process_ = new QProcess();
process_->setReadChannelMode(QProcess::MergedChannels);
process_->setStandardOutputFile("E:/log.txt");
}
sourcefile:
AdbDriver::~AdbDriver(){
delete process_;
}
void AdbDriver::installDriver(){
QFile file(PnPutilPath_);
if(file.exists()){
qDebug()<<"pnputil.exe exist";
QString generaladbDriver = "E:/driver_androidusb/generaladb.inf";
qDebug()<<"the programming include driver:"<<generaladbDriver;
QFile file(generaladbDriver);
if(file.exists()){
qDebug()<<"yes, the driver is right in bihu package";
}
else{
qDebug()<<"loss driver in bihu package";
}
QStringList arguments;
arguments<<"-i"<<"-a"<<generaladbDriver;
process_->start(PnPutilPath_, arguments);
while(!process_->waitForStarted()){
qDebug()<<"wait";
}
qDebug()<<"while out";
process_->waitForReadyRead();
qDebug()<<"start";
// qDebug()<<process_->readAll();
process_->close();
}
else{
qDebug()<<"sorry, your computer has no tool pnputil.exe.";
}
}
when i Commented out code
qDebug()<<process_->readAll();
and use
process_->setReadChannelMode(QProcess::MergedChannels);
process_->setStandardOutputFile("E:/log.txt");
it works properly.But if i use
qDebug()<<process_->readAll();
instead of
process_->setReadChannelMode(QProcess::MergedChannels);
process_->setStandardOutputFile("E:/log.txt");
it will be wrong. what's the reason?
According to Qt document, both setReadChannelMode and setStandardOutputFile have to be called before QProcess::start to take effect, so replacing
qDebug() << process_->readAll();
with
process_->setReadChannelMode(QProcess::MergedChannels);
process_->setStandardOutputFile("E:/log.txt");
is same as just commenting out qDebug() << process_->readAll();.
So I guess the child process does not output anything, so process_->readAll() will block, and the program halts.
(你看一下E:/log.txt有没有内容,估计是process_->readAll()阻塞了)

Writing to file doesn’t work in Qt5/Qml

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.

reading a file into Qt

I wrote a Program in Qt 5.2.1 that writes some data into a file and now I want to read it and display it. ( in a text edit or any other widget)
Here is my code ( the part I thought is relevant ) -
But i don't get the desires result ... could you look into it and tell me what i an doing wrong
void MainWindow::on_Search_clicked()
{
QString name ;
name = ui->Search_name->text();
QFile readfile("data.txt");
if(!readfile.open(QIODevice::ReadOnly))
{
qDebug() << "error opening file: " << readfile.error();
return;
}
QTextStream instream(&readfile);
QString line = instream.readLine();
// ui->text is a QPlainTextEdit*
ui->text->insertPlainText(line);
readfile.close();
return;
}
You should use
void QPlainTextEdit::appendPlainText ( const QString & text ) [slot]
method, link.

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.