QSettings weird behaviour on MacOS - c++

Using Qt 5.11.1 via homebrew on MacOS 10.13.6, I'm using QSettings in my application. This is a working program that I'm porting from Linux and Windows now to MacOS.
The issue I'm having on MacOS is that it'll save the file to /Users/michaelleonetti/Library/Preferences/com.sonarcloud.Sonarcloud Service.plist, which it's supposed to, on first program execution.
If I delete the file sometimes it comes back. Sometimes it doesn't. If I edit the plist file with Xcode and save it, the values I write in "have" won't be there.
I can't identify a rhyme or a reason to make it work.
I've created a minimal example:
#include <QSettings>
#include <iostream>
int main( int argc, char *argv[] )
{
{ // Scope
QSettings settings( QSettings::NativeFormat, QSettings::UserScope, "My Application Company", "My Application" );
if( settings.contains( "have" ) )
std::cout << "We have: " << settings.value( "have" ).toString().toStdString() << std::endl;
else
std::cout << "You do not have" << std::endl;
settings.setValue( "version", 10 );
std::cout << "Path is: " << settings.fileName().toStdString() << std::endl;
}
return( EXIT_SUCCESS );
}
Output:
$ ./src/reproduce
You do not have
Path is: /Users/michaelleonetti/Library/Preferences/com.my-application-company.My Application.plist
File check
$ cat "/Users/michaelleonetti/Library/Preferences/com.my-application-company.My Application.plist"
cat: /Users/michaelleonetti/Library/Preferences/com.my-application-company.My Application.plist: No such file or directory
How can I get this issue solved?

I think this is due to QSettings being implemented on top of Apple's CFPreferences database. This is expected behavior and the "fix" is to call CFPreferencesSynchronize()
Docs:
writes all pending changes to preference data to permanent storage,
and reads latest preference data from permanent storage
Luckily it appears that QT wraps this in its Mac implementation for QSettings and you should be able to call QSettings::sync() to do this in a platform agnostic way.
Basically you need to synchronize your settings before you will see any changes from external writes**. This is also why the file doesn't appear to always be rewritten (it should on application exit when things are automatically flushed).
Note that you will also need synchronize your settings from the external application by calling CFPreferencesSynchronize() within that application in order to see changes made by your QT app.
It also might be interesting to know that there is a command line utility available called defaults that you can use to perform syncronized writes from a shell script or terminal.
** This occurs naturally at certain points automatically.

Related

SQLite in C++: Cannot set single-threaded mode on start-time in a program using multi-thread compiled SQLite

I'm trying to set single-threaded mode on start-time in a program using multi-thread compiled SQLite. Here's the code:
#include <iostream>
#include <sqlite3.h>
using namespace std;
int main() {
cout << "threadsafe: " << sqlite3_threadsafe() << endl;
int mode = SQLITE_CONFIG_SINGLETHREAD;
sqlite3_shutdown();
int res = sqlite3_config(mode);
if (res) {
cout << "failed to set threading mode, error code: " + to_string(res);
} else {
cout << "threading mode successfully set to " + to_string(mode);
}
sqlite3_initialize();
cout << endl;
return 0;
}
// command used to compile and run
// g++ repro.cpp -o repro.out -lsqlite3 && ./repro.out
The output is:
threadsafe: 2
failed to set threading mode, error code: 21
Now, from what I understand from here and other SQLite docs, the compile-time mode determines whether the mutexes code exists in the compiled files of SQLite. On the other hand, start-time and run-time settings either tell the program to use/omit mutexes code(if it's present obviously).
Now, if I get 2 as a result of sqlite3_threadsafe() call, it means the SQLite code has been compiled in the multi-threaded mode. That means that the mutex code is compiled and available. However, in order to care for the performance, I'd like to tell the program to skip the mutexes code as I'm going to use SQLite only on one thread. To do this, I followed the docs and used sqlite3_config() with the option SQLITE_CONFIG_SINGLETHREAD. This didn't work and I got the result 21 from the call. The error code means SQLITE_MISUSE. I got to this SO answer so I put the config call between sqlite3_shutdown andsqlite3_initialize. This didn't work.
I'm not sure why this doesn't work, in the linked doc they say:
It is not possible to downgrade an individual database connection to single-thread mode
But it's about an individual connection and I'm trying to get this working for all of the SQLite calls in the program. I couldn't find an answer on the docs or the Internet. Am I missing something?
EDIT: sorry, forgot to put versions:
mac os: 11.2.3
Apple clang version 12.0.5
sqlite3: 3.32.3

Running the command line dot program from a Qt application generates no output, what is wrong?

I have an app that generates a dependencies.dot file which I then want to convert to an SVG image.
When I do that from a simple application like so:
int main(int argc, char * argv[])
{
system("dot -Tsvg ../BUILD/dependencies.dot > ../BUILD/dependencies.svg");
return 0;
}
It works great. The SVG image is present and working.
When I instead run it from my Qt application, the SVG file is created (by the shell), but it remains empty.
Any idea what could prevent dot from outputting data to its stdout?
Just in case, I also tried a cat to send the input through stdin instead of a filename:
system("cat ../BUILD/dependencies.dot | dot -Tsvg > ../BUILD/dependencies.svg");
And that didn't make any differences.
Also using the full path (/usr/bin/dot) did not help either.
Another test, I tried to use popen() and the first fread() immediately returns 0 (i.e. the mark of EOF).
It may not be Qt, but something is interacting with dot's ability to do anything. Any pointers on why that is would be wonderful.
Maybe an important note? I start my app. from a console, so stdin, stdout and stderr should all work as expected. I actually can see debug logs appearing there and other apps seem to work just as expected (i.e. My Qt app. can successfully run make, for example).
Here is an example of the resulting SVG (when I don't run it from within my Qt app):
For reference, the source code can be found on github. This is part of the snapbuilder. A tool that I use to run a build on launchpad. It's still incomplete, but it's getting there.
https://github.com/m2osw/snapcpp/tree/master/snapbuilder
The specific function to look for: project::generate_svg().
I still have no clue what side effect Qt has on system() that the dot command would fail. However, if using my own fork() + execve(), then it works.
I wanted a new process class for my environment, so I implemented that. This newer version is using FIFOs or directly opening closing files that it passes to the process.
...
// write the script in `std::stringstream dot` then:
//
std::string script(dot.str());
g_dot_process = std::make_shared<cppprocess::process>("dependencies");
g_dot_process->set_command("/usr/bin/dot");
g_dot_process->add_argument("-Tsvg");
g_dot_process->add_input(cppprocess::buffer_t(script.data(),
script.data() + script.length()));
g_dot_process->set_capture_output();
g_dot_process->set_output_capture_done(output_captured);
g_dot_process->start(); // TODO: check return value for errors
...
// and in output_captured()
//
void snap_builder::svg_ready(std::string const & svg)
{
std::string const svg_filename(...);
{
std::ofstream out;
out.open(svg_filename);
if(!out.is_open())
{
std::cerr << "error: \n";
return;
}
out.write(svg.c_str(), svg.size());
}
dependency_tree->load(QString::fromUtf8(svg_filename.c_str()));
}
Now the dot file is generated and displayed as expected.
This is rather strange since most everything else I've done with a simple system() call works as expected. There must be something about stdin or stdout that makes dot not do its work.

Get the running file name: argv[0] vs boost::filesystem::current_path()

I am trying to get the current running file name in C++. I wrote a simple code that uses both argv[0] and boost current_path() method. The file is compiled into executable file mainWindow.
#include "boost/filesystem.hpp"
int main(int argc, char* argv[])
{
boost::filesystem::path full_path( boost::filesystem::current_path() );
std::cout << full_path.string() << "\n";
std::cout << argv[0] << "\n\n";
return 0;
}
Interestingly the output of each method is different.
argv[0] output is:
../VENTOS/src/loggingWindow/mainWindow
current_path() output is:
/home/mani/Desktop/VENTOS_Redpine
I am not running my program (mainWindow) directly from the terminal. Another application is calling my program and I guess that's why the output is different. Am I right on this?
My second question is: Without using the argv[0] option and relying only on the boost filesystem methods, how can I get the same result as argv[0]?
argv[0] only contains the command used to execute the the program. This may contain the path. It may contain a relative path. It may contain no path at all. It might not even contain the executable name thanks to symlinks etc.... It might even be empty if the hosting system chooses to provide nothing. It can't be trusted, so you don't want to use this as a basis for evaluating other methods.
boost::filesystem::current_path fails you because it only returns the current working directory. This may or may not be the location of the executable because it depends on the directory from which the program was run and whether or not the working directory has been changed by the program. To be honest I'm not sure if there is a sure-fire way to get the process name and path from Boost. There wasn't a few years ago, but time has a way of marching on, you know?
There are a slew of questions covering how to get the executable and path (Finding current executable's path without /proc/self/exe looks promising but is stale. That time marching thing again.) but all are platform-specific you may have to do some ifdef or linker wizardry to make this work.

Can I see the program output in Qt-Creator?

I am writing a simple OpenGL program with Qt Creator which basically creates a QGLWidget, shows it, and runs the application loop. I usually like debugging more with diagnostic messages turned on and off by preprocessor symbols that using an actual debugger and watches etc. In Qt Creator we have a tab called Application Output, but all I see there is "Starting xxx.exe. xxx.exe exited with code 0". No output from either std::cout or std::cerr. Now I know I could start my application from cmd.exe (yes, I am using Windows, love it :P) and see the output there but I wish I could see the output directly from the IDE. Is that possible? Thanks
Usually the Application Output pane works fine. Are you sure that you would see the output from cmd.exe (have you actually tried?)? It's usually turned off for UI applications to avoid console windows from popping up. Try CONFIG += console. Also check if you see qDebug() messages in the Application Output.
simply #include <QDebug>
and then use qDebug instead of cout like
qDebug() << "you just clicked ok";
also this works
#include <QTextStream>
QTextStream out(stdout);
out << "\nHello World!\n";
adding CONFIG += console in the .pro file didn't work for me. I wonder why?
i just discovered that i've to add "endl;" for cout to work like
cout << "print this" << endl;
Alternatively, you can check the "run in console" setting in the Project->Run options. This will open a new console window and display all console output there (if CONFIG += console is used of course).
I know that this answer do not answer the original question, but since when searching for "No application output" we found this answer...
See the following answer: https://stackoverflow.com/a/26325743/808101
This only apply to qDebug() and similar functions (not direct output to stdout/stderr).
In my case, I have to set QT_ASSUME_STDERR_HAS_CONSOLE environment variable to 1 in QtCreator in order to see qDebug() messages inside "Application Output" window.
Try:
Tools -> Options
Under the "General" tab of "Environment" change the terminal entry from:
x-terminal-emulator -e
to
xterm -e

How to output to the console in C++/Windows

When using iostream in C++ on Linux, it displays the program output in the terminal, but in Windows, it just saves the output to a stdout.txt file. How can I, in Windows, make the output appear in the console?
Since you mentioned stdout.txt I google'd it to see what exactly would create a stdout.txt; normally, even with a Windows app, console output goes to the allocated console, or nowhere if one is not allocated.
So, assuming you are using SDL (which is the only thing that brought up stdout.txt), you should follow the advice here. Either freopen stdout and stderr with "CON", or do the other linker/compile workarounds there.
In case the link gets broken again, here is exactly what was referenced from libSDL:
How do I avoid creating stdout.txt and stderr.txt?
"I believe inside the Visual C++ project that comes with SDL there is a SDL_nostdio target > you can build which does what you want(TM)."
"If you define "NO_STDIO_REDIRECT" and recompile SDL, I think it will fix the problem." > > (Answer courtesy of Bill Kendrick)
For debugging in Visual Studio you can print to the debug console:
OutputDebugStringW(L"My output string.");
If you have a none-console Windows application, you can create a console with the AllocConsole function. Once created, you can write to it using the normal std::cout methods.
If you're using Visual Studio you need to modify the project property:
Configuration Properties -> Linker -> System -> SubSystem.
This should be set to: Console (/SUBSYSTEM:CONSOLE)
Also you should change your WinMain to be this signature:
int main(int argc, char **argv)
{
//...
return 0;
}
The AllocConsole Windows API function will create a console window for your application.
If you're using Visual Studio, it should work just fine!
Here's a code example:
#include <iostream>
using namespace std;
int main (int) {
cout << "This will print to the console!" << endl;
}
Make sure you chose a Win32 console application when creating a new project. Still you can redirect the output of your project to a file by using the console switch (>>). This will actually redirect the console pipe away from the stdout to your file. (for example, myprog.exe >> myfile.txt).
I wish I'm not mistaken!
Whether to use subsystem:console or subsystem:windows kind of depends on whether how you want to start your application:
If you use subsystem:console, then you get all of the stdout written to the terminal. The trouble is that if you start the application from the Start Menu/Desktop, you (by default) get a console appearing as well as the application window (which can look pretty ugly).
If you use subsystem:windows, you won't get stdout/stderr even if you run the application from a DOS window, Cygwin, or other terminal.
If you want the middle way which is to output to the terminal IF the application was started in a terminal, then follow the link that Luke provided in his solution (http://dslweb.nwnexus.com/~ast/dload/guicon.htm)
For reference, I ran into this problem with an application that I want to run in either normal Windows mode or batch mode (that is, as part of a script) depending on command-line switches. The whole differentiation between console and Windows applications is a bit bizarre to Unix folks!
First off, what compiler or dev environment are you using? If Visual Studio, you need to make a console application project to get console output.
Second,
std::cout << "Hello World" << std::endl;
should work in any C++ console application.
Your application must be compiled as a Windows console application.
There is a good solution
if (AllocConsole() == 0)
{
// Handle error here. Use ::GetLastError() to get the error.
}
// Redirect CRT standard input, output and error handles to the console window.
FILE * pNewStdout = nullptr;
FILE * pNewStderr = nullptr;
FILE * pNewStdin = nullptr;
::freopen_s(&pNewStdout, "CONOUT$", "w", stdout);
::freopen_s(&pNewStderr, "CONOUT$", "w", stderr);
::freopen_s(&pNewStdin, "CONIN$", "r", stdin);
// Clear the error state for all of the C++ standard streams. Attempting to accessing the streams before they refer
// to a valid target causes the stream to enter an error state. Clearing the error state will fix this problem,
// which seems to occur in newer version of Visual Studio even when the console has not been read from or written
// to yet.
std::cout.clear();
std::cerr.clear();
std::cin.clear();
std::wcout.clear();
std::wcerr.clear();
std::wcin.clear();
I assume you're using some version of Visual Studio? In windows, std::cout << "something"; should write something to a console window IF your program is setup in the project settings as a console program.
If using MinGW, add an option, -Wl,subsystem,console or -mconsole.
You don't necessarily need to make any changes to your code (nor to change the SUBSYSTEM type). If you wish, you also could simply pipe stdout and stderr to a console application (a Windows version of cat works well).