QSettings simple task not working - c++

I'm trying to use QSettings on my code but it's not working correctly. My code is:
In Mainwindow.h
QSettings settings
(I have declared before all setOrganizationName setOrganizationDomain
setApplicationName)
In Mainwindow.cpp
settings.setValue("smtp/email", "test");
qDebug() << settings.value("smtp/email").toString();
But the qDebug is returning me ""
I believe it's a simple use of QSettings but it's not working.

For efficiency, the changes may not be saved to permanent storage immediately. (You can always call sync() to commit your changes.)

Related

QT: How to download from url while pressing a button

I have this code:
QNetworkAccessManager man;
QNetworkRequest req(QUrl("URL"));
QString ua("HttpRequestDemo/0.1 (Win64) Qt/5.14.0");
req.setHeader(QNetworkRequest::UserAgentHeader, QVariant(ua));
QNetworkReply* reply = man.get(req);
QObject::connect(reply){
QByteArray read = reply->readLine();
QFile out("file.txt");
out.open(QIODevice::WriteOnly|QIODevice::Text);
out.write(read);
out.close();
})
This works on the main.cpp file, using the QCoreApplication, but I want to use the QApplication and download a specific data while pressing a button.
I put the same code on the on_pushButton_clicked() in the mainwindow.cpp file and it didn't even generate the file from the url.
The problem is that man and req go out of scope and are destroyed as soon as your on_pushButton_clicked() function returns, at which point the request probably hasn't even been sent yet.
You need to make sure that these objects outlive the current scope, either by making them members of the window class, or by allocating them on the heap and setting some QObject (maybe also the window class) as the parent.
The problem is that if you put the same code in a method like X you make QNetworkAccessManager a local variable that will be removed instantly that the connection is asynchronous. The solution is to make QNetworkAccessManager an attribute of the class.
*.h
private:
QNetworkAccessManager man;
*.cpp
void Klass::on_pushButton_clicked(){
QNetworkRequest req(QUrl("URL"));
QString ua("HttpRequestDemo/0.1 (Win64) Qt/5.14.2");
req.setHeader(QNetworkRequest::UserAgentHeader, QVariant(ua));
QNetworkReply* reply = man.get(req);
connect(reply, &QNetworkReply::finished, [&]() {
QByteArray read = reply->readAll();
QFile out("file.txt");
out.open(QIODevice::WriteOnly|QIODevice::Text);
out.write(read);
out.close();
reply->close();
reply->deleteLater();
})
}
If you are planning on potentially queuing very many downloads, I strongly recommend using libcurl in your Qt app. I was using QNetworkAccessManager to down 100+ financial quote files, and it would fail downloading ~ 1/3 of the time, and take a while to download. I switched to libcurl, and after figuring out how to get my crypto root certificates setup for https, it runs much faster, and almost never fails. I run it as a dll.
And yes, you will need to make sure the network manager, whether QNetworkManager or curl, doesn't go out of scope upon exiting the button handler. A more conventional pattern, although not necessarily better, is to either have a pointer to e.g. QNetworkManager in your parent class, and new it, or use a std::unique_ptr and std::make_unique (purportedly safer). Creating large objects on the stack can cause problems (in the old days, dare I say, stack overflows), and so is usually done on the heap. In this case, it's not very big, so it doesn't really matter. Alternatively, a form creating big objects might itself be created on the heap.

Directly executing a batch through clicked function in qt

So I'm trying to have my "button" directly execute a Batch file, important here is that I don't want it to show me a dialogue and make me chose the path, which is the problem I'm having right now with the following code
void MainWindow::on_pushButton_clicked()
{
QString filename=QFileDialog::getOpenFileName(
this,
tr("Open File"),
"C://",
"All files (*.*);;Text File (*.txt);;Music file (*.mp3)");
}
I think this is probably really simple, but i can't get it, I'm not even learning c++ at the moment but my boss asked me to create something out of my scope (wants me to create a GUI for a batch file and have them interact) and I thought of this approach, which is just creating a GUI that executes it.
I've looked at this question: asked to execute an external program with Qt
but they don't talk about how the file path can directly be added into the code, or if I should even be using Qprocess and how, and if I can pass it through "clicked" function.
I'm really inexperienced, all of the code above I got with the help of the internet, but I really don't know how to program using c++
so could someone please be kind enough to show me how a file path can be added to the code, assuming it's in C:\Users\name_goes_here\Downloads
I'd really appreciate it :D
I'd recommend using QProcess for anything "execute external program" with Qt.
You could do it like this:
void MainWindow::on_pushButton_clicked()
{
QProcess process;
process.start("C:/Users/name_goes_here/Downloads/yourfile.bat");
process.waitForFinished(); // Assuming that you do want to wait for it to finish before the code execution resumes
}
Note the "/" in the path. Only Windows uses the messed up "\" for path separation, which would require you to write "C:\\Users\\.." in any string in C++ as "\" needs to be escaped.
Luckily, Qt uses "/" as the universal separator and translates it to whatever the OS needs as required. So you should just use "/" whenever working with Qt.
This is from the Qt documentation:
Qt uses "/" as a universal directory separator in the same way that "/" is used as a path separator in URLs. If you always use "/" as a directory separator, Qt will translate your paths to conform to the underlying operating system.
And finally, if you don't know how to code in C++, shouldn't you be learning that first instead of trying to execute batch files from within a library as complex as Qt? Sounds like you're trying to do too many new things at once.
This is fairly simple merging your source and the one you linked:
void MainWindow::on_pushButton_clicked()
{
QProcess::execute(
QString::fromLatin1(
"cmd.exe /c C:\\Users\\name_goes_here\\Downloads\\file.bat"));
}
Notes:
I used QProcess::execute() instead of QProcess::start() to make things even simpler.
To achieve execution of the batch file, I pass it to cmd32.exe as this is the interpreter which is responsible.
As MCVE testQProcessBatch.cc:
// Qt header:
#include <QtWidgets>
void on_pushButton_clicked()
{
#if 0 // WORKS:
QProcess::execute(
QString::fromUtf8("cmd.exe /c C:\\Users\\Scheff\\Downloads\\testBatch.bat"));
#else // WORKS AS WELL:
QProcess::execute(
QString::fromUtf8("C:\\Users\\Scheff\\Downloads\\testBatch.bat"));
#endif // 0
}
int main(int argc, char **argv)
{
qDebug() << "Version:" << QT_VERSION_STR;
// main application
QApplication app(argc, argv);
QMainWindow qWin;
QPushButton qBtn(QString::fromLatin1("Start cmd"));
qWin.setCentralWidget(&qBtn);
qWin.show();
QObject::connect(&qBtn, &QPushButton::clicked,
&on_pushButton_clicked);
// run application
return app.exec();
}
and the test batch file testBatch.bat:
echo "This is testBatch.bat"
pause
Tested with VS2013 on Windows 10:
Thanks for contributing guys!
I tried using the QProcess method but I think I'm too inexperienced when it comes to figuring out problems associated with it (which I did face when using this method). the CMD route is probably good but I also thought it was too difficult and both of these methods didn't work for me.
Here's what I have now (thanks to Detonar and ymoreau) and and it seems to be doing the job, this might not be the most optimal approach, but it worked for me!
I included QDesktopServices and QUrl
void MainWindow::on_pushButton_clicked()
{
QString filename="C:\\Users\\Name_goes_here\\Downloads\\test.bat";(
this);
hide(); //optional
QDesktopServices::openUrl(QUrl("file:///"+filename,QUrl::TolerantMode));
}

QML type from C++ Plugin signaling only once

I have a C++ plugin that watches for file changes with QFileSystemWatcher and connects it's fileChanged signal with a custom QML type slot like this:
//In the custom QML type constructor
QObject::connect(&this->_watcher, SIGNAL(fileChanged(QString)),
this, SLOT(fileChangedSlot(QString)));
The slot function:
void CustomQMLTypeClass::fileChangedSlot(QString file)
{
Q_UNUSED(file);
emit fileChanged();
}
In the QML side:
CustomQMLType{
fileUri: "some/file/path/file.format"
onFileChanged: console.log("File changed")
}
While running the program all goes right, but when I do, i.e.:
echo "sth" >> some/file/path/file.format
More than once, the notification is only triggered once. Why? O.o
Apparently the problem is with QFileSystemWatcher, it sometimes worked and some others don't.
As I can handle the cost, my quick solution was to alter the slot:
void CustomQMLTypeClass::fileChangedSlot(QString &file)
{
_watcher.removePath(file);
_watcher.addPath(file);
emit fileChanged();
}
Now it works as expected but don't know why and couldn't get to understand neither with QFileSystemWatcher's source. Finally I decided KDE's KDirWatch is way better.

QT Creator Main.cpp MainWindow.cpp

I'm currently working on my project for my Master thesis in Mechatronics/Robotics. The goal of y project is to read in a .stl-File and calculate the path for an industrial robot.
Till now everything worked fine for me, but now my professor wants me to develop a GUI, because till now I was just using the command window and wrote all parameters manual. Now I'm working with Qt Creator and developed a simple GUI for my project.
In this interface I got a RadioButton for ascii files. In order my functions work I have to determine if the user is entering a ascii file or an binary file. But here's my first problem. In the command window I just check the argv[] for the string "-ascii". If the user enters this, a flag is set to false.
if(0 == strcmp(argv[i], "-ascii")) {
isBinaryFormat = false;
}
Now I just want to do the same int the GUI. If the RadioButton is checked flag is set to false. So I wrote the following in the main.cpp file
if(ui->radioButton->isChecked()) {
isBinaryFormat = false;
}
But ui is unknown in the main function. After searching for help on google I just found tutorials writing the code in the mainwindow.cpp file. But how can I send the information form the mainwindow file to my main function in the main.cpp file.
A second question would be, if I use the QFileDialog::getOpenFilename method, how can I hand the file name to my other functions. The idea is, the user selects a file anywhere on his PC, and the program opens the file and processes it. But here I got the same problem. I can brows for a file, but how can I transfer the information from the mainwindow.cpp to my main.cpp.
I'm thankful for any help I get. Very grateful a lonely coder
First of all you don't write UI Code in the main.cpp.
You write it where the MainWindow Class is so in MainWindow.cpp and MainWindow.h.
Then your ui-> will work because it then has access to that namespace.
I don't see why you would have functions in Main.cpp?
Without seeing more code you're not likely to get an answer to that.
If you want to use external functions in your classes either declare the methods in the class directly or create a new file like global_function.h and .cpp which you can include in your class. ( don't forget the header guards )
Also shouldn't that code look like this:
if(!ui->radioButton->isChecked())
{
isBinaryFormat = false;
}
because of:
If the RadioButton is checked flag is set to false.
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
"/home",
tr("Images (*.png *.xpm *.jpg)"));
getOpenFileName( ) will return a string containing the path and filename of the selected file which you can pass to your functions then.
Please read some more about how to use Qt.
It's not just about the files, there's a class, too. Learn about them. Solution is to add a getter to your MainWindow class that will return whether the radioButton is checked:
class MainWindow : public QMainWindow
{
public:
// optionally, move implementation in the source file
bool isBinaryFormatChecked() const
{
return ui->radioButton->isChecked();
}
// other stuff ...
};
And then you can access it in your main like window.isBinaryFormatChecked() orwindow->isBinaryFormatChecked() depending on whether you have a pointer or not. Another way would be to make ui in your MainWindow public, so you could access the whole user interface, but that breaks proper encapsulation.
I think you need to go through a few of the (excellent in my opinion) examples supplied with Qt before attempting to integrate your already working console code.
Essentially you really don't want to do that check in the main.cpp, but if you must you could have it in a public function of the mainwindow and call that from your main.cpp file. But then that doesn't really make sense as you don't want to check whether the appropriate radio button is set until the user inputs something. You're going to have to read up on event based programming.

qt5 designer, using fileopen, displaying file path in lineedit, is there an issue doing it this way?

just started using qt,
looked through docs, google, examples, etc.. trying to find simple examples(working mind you)
that showed how to do (imho) simple things, by themselves.
well i stumbled upon my answer and i was wondering if this approach would cause an issue later as the code becomes more complex.
there are more includes than needed for this example, but this is direct from working code.
mainwindow.h:
i added
private slots:
void vpkButton_clicked();
and after
Ui::MainWindow *ui;
i added
QLineEdit *vpkPathTxt;
in mainwindow.cpp:
after
ui->setupUi(this);
i added
connect( this->ui->vpkButton, SIGNAL( clicked() ), this, SLOT(vpkButton_clicked()) );
to connect my ui button to the proper slot, the issue was getting the string from vpkButton_clicked() to display in the line edit i made in the designer,
what ended up working for me was adding this next:
vpkPathTxt = this->ui->vpkPathTxt;
the function in my main.cpp became very easy:
(QString declarations at top outside voids)
void MainWindow::vpkButton_clicked()
{
vpkName = QFileDialog::getOpenFileName(this,
tr("Open VPK File"), "~/", tr("VPK Files (*_dir.vpk)"));
vpkPathTxt->setText(vpkName);
qDebug() << vpkName;
}
the reason i am ask is because it seems a little too easy to be reliable, and the fact that i havent seen it done like this,
any input welcome
thankyou
One problem with your slot is that you don't consider the case where the user discards the "open file" dialog. In this case, the function QFileDialog::getOpenFileName returns a null QString, so you should only proceed with your logic if the return value was not a null string:
if (!vpkName.isNull()) {
...
}
The second problem is as follows and I made some assumptions since I don't see your full code:
I guess you want to load a file using the file name the user has chosen in the dialog. But you set the file name in the line edit too, which the user can edit by hand. I also guess that the actual file loading happens in a different step (i.e. after clicking another button), so after the user has edited the file name by hand in the line edit it won't be the same than in your local variable vpkName.
When loading the file I'd read the contents of the line edit instead of the variable vpkName so the edit made by hand will be respected.
A different method is to also watch for editing of the line edit and reflect the changes in your variable too. Then it will be ok to read the variable instead of the line edit when loading the file later on.