QSettings value method returns wrong QString - qt

I have ordinrary text file with settings, which is generated by java application. Inside this file, there is a key db.url, which has value db.URL=jdbc\:mysql\://192.168.0.101\:3306/dbuser. I parse this file with QSettings class in QSettings::Native mode, everything is ok, but this db.URL gets messed up if I read it via value() method. Whatever I do (if I transform it into QString or QUrl), I get same result: jdbcmysql//192.,168.0.1013306/user. Why this key gets messed up?? I am using Qt 5.4 on Kubuntu 14.10 with kernel Linux desktop001 3.16.0-30-generic #40-Ubuntu SMP Mon Jan 12 22:06:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux. Here is a simple method that wrongly reads value of key:
QString UePOSSesttings::ueReadDbUrl() const
{
// QVariant dbUrl=this->value(UeDefaults::UeDbKeys::KEY_DB_URL);
return this->value(UeDefaults::UeDbKeys::KEY_DB_URL).toString();
}
and constants:
#ifndef UEDEFAULTS
#define UEDEFAULTS
#include <QString>
namespace UeDefaults
{
namespace UeDbKeys
{
static const QString KEY_DB_DRIVER="db.driver";
static const QString KEY_DB_PASSWORD="db.password";
static const QString KEY_DB_URL="db.URL";
static const QString KEY_DB_DRIVER_LIB="db.driverlib";
static const QString KEY_DB_ENGINE="db.engine";
static const QString KEY_DB_USER="db.user";
}
}
#endif // UEDEFAULTS

QSettings clears up the string from unsupported escape sequences, in this case \:. Remove \ slashes before reading the value or don't use QSettings for parsing unsupported file formats.
Perhaps not the most optimal solution but you could processes the settings file to escape all \: before reading it with QSettings.
QFile oldSettings("settings.txt");
oldSettings.open(QIODevice::ReadOnly);
QString data = QString::fromAscii(oldSettings.readAll().constData());
oldSettings.close();
data.replace("\\:", "\\\\:");
QFile newSettings("/tmp/settings.txt");
newSettings.open(QIODevice::WriteOnly);
newSettings.write(data.toAscii(), data.size());
newSettings.close();

I did it:
void UePOSSesttings::ueParseData(const QString& filename)
{
QFile settingsFile(filename);
QString data;
settingsFile.open(QIODevice::ReadOnly);
data=QString::fromLatin1(settingsFile.readAll().constData());
data.replace("\\:",
":");
this->ueSetParsedData(data);
qDebug() << this->ueParsedData();
settingsFile.close();
}
and now I get this url:
db.URL=jdbc:mysql://192.168.0.101:3306/dbuser
which is ok!

Related

Testing Qt application in Visual Studio - Qt files giving 'cannot open source file' error when including project files in test file

I'm trying to write tests for a Qt application in visual studio. I've added a new test project to the existing solution that has the project I'm wanting to test, and added a reference to said project as shown here. When I try to run a test file, I get errors saying 'cannot open source file "x"' for a bunch of Qt and Qt generated files like QWidget and 'ui_x.h' (x is a placeholder). I'm using Google Test, but the same issue occurs when using the 'Native Unit Test Project' option.
Image of problem
Settings.h
#pragma once
#include <string>
#include <QWidget>
#include <QSettings>
#include <QFileDialog>
#include "ui_Settings.h"
extern const std::string MODS_FOLDER_PATH;
extern const std::string PROFILE_PATH;
class Settings : public QWidget
{
Q_OBJECT
public:
Settings(QWidget *parent = Q_NULLPTR, QString testHook = "");
QString getModsFolderPath();
public slots:
void browseProfilePath();
void browseModsPath();
void openSettingsWidget();
signals:
void modsFolderPathChanged(const QString &newPath);
void profilePathChanged();
private:
Ui::Options ui;
QString testHook;
QString fileBrowser(QFileDialog::FileMode fileMode, const std::string = "");
bool changeFileSetting(QLineEdit * const settingInput, const std::string setting, const QString &fileName);
void loadValuesFromSettings();
};
test.cpp
#include "pch.h"
#include "../FileOverwriteManager/Settings.h"
TEST(TestCaseName, TestName) {
EXPECT_EQ(1, 1);
EXPECT_TRUE(true);
}
I had to edit the 'Additional Include Directories' under 'C/C++' in the test project's properties as suggested by user vahancho. If you only include the directories where the .h files are, i.e. C:\Qt\5.10.0\msvc2017_64\include\QtCore for qsettings.h, then it complains like so, so you have to also include one directory higher, i.e. C:\Qt\5.10.0\msvc2017_64\include\

QT4 > QT5 for QDesktopServices::storageLocation

I am trying to convert the following code to a QT5 version:
QString getSaveFileName(QWidget *parent, const QString &caption,
const QString &dir,
const QString &filter,
QString *selectedSuffixOut)
{
QString selectedFilter;
QString myDir;
if(dir.isEmpty()) // Default to user documents location
{
myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
}
else
But sadly I am getting the following error:
error: no member named 'storageLocation' in 'QDesktopServices'
myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
~~~~~~~~~~~~~~~~~~^
and
error: no member named 'DocumentsLocation' in 'QDesktopServices'
myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
~~~~~~~~~~~~~~~~~~^
Since Qt 5, storageLocation() and displayName() methods of QDesktopServices are replaced by functionality provided by the QStandardPaths class, so your myDir can be assigned like this:
myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);

QString containing printer command in hex

I am working on some printer driver and I am importing printer commands from command specification manual and for instance, printer command Print and Feed Paper has hexadecimal value of 0x0a:
#ifndef UECOMMANDSET_H
#define UECOMMANDSET_H
#include <QString>
namespace UeCommandSet
{
namespace TSM210
{
static const QString CMD_LF="\x0A";
} // namespace
} // namespace
#endif // UECOMMANDSET_H
Is this command representation corrent, i.e., will QString hold 0x0a value?
Yes, I tested it as follow:
static const QString CMD_LF= "\x0A";
qDebug() << CMD_LF.size();
qDebug() << (int)CMD_LF.at(0).toLatin1();
So, the first line gives 1, and second one gives 10 which is correct. Also you can use the following code to set CMD_LF to 0x0A
static const QString CMD_LF= "\n";

Qt Dynamic translation of dialog windows

I am creating a Qt application and I added dynamic translation (I followed the example at http://www.qtcentre.org/wiki/index.php?title=Dynamic_translation_in_Qt4_applications) with a QCombobox which lists different languages. It works well but the problem is that I don't see how to translate dynamically the text in the dialog windows (for example YES and NO buttons).
In the main.cpp, before executing the app, I have :
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
a.installTranslator(&qtTranslator);
which translate the dialog Windows in the user system language but I would like to do it dynamically like the rest of my app.
Here are the code of the example :
application.h :
#ifndef APPLICATION_H
#include <QApplication>
#include <QHash>
#include <QStringList>
class QDir;
class QTranslator;
typedef QHash<QString, QTranslator*> Translators;
class Application : public QApplication
{
Q_OBJECT
public:
explicit Application(int& argc, char* argv[]);
~Application();
static void loadTranslations(const QString& dir);
static void loadTranslations(const QDir& dir);
static const QStringList availableLanguages();
public slots:
static void setLanguage(const QString& locale);
private:
static QTranslator* current;
static Translators translators;
//static QTranslator* qtTranslator;//test to translate dialog windows
};
#endif // APPLICATION_H
application.cpp :
#include <QDir>
#include <QFileInfo>
#include <QTranslator>
#include <QLibraryInfo>
#include "application.h"
QTranslator* Application::current = 0;
//QTranslator* Application::qtTranslator = 0;//test to translate dialog windows
Translators Application::translators;
Application::Application(int& argc, char* argv[])
: QApplication(argc, argv)
{
}
Application::~Application()
{
}
void Application::loadTranslations(const QString& dir)
{
loadTranslations(QDir(dir));
QString locale = QLocale::system().name().section('_', 0, 0);
QString language=locale+ "_" + locale;
if(!QFile::exists(":Localization/Localization/"+language+".qm"))//if system language is not available, load english version
setLanguage("en_en");
else
setLanguage(language);
}
void Application::loadTranslations(const QDir& dir)
{
// <language>_<country>.qm
QString filter = "*_*.qm";
QDir::Filters filters = QDir::Files | QDir::Readable;
QDir::SortFlags sort = QDir::Name;
QFileInfoList entries = dir.entryInfoList(QStringList() << filter, filters, sort);
foreach (QFileInfo file, entries)
{
// pick country and language out of the file name
QStringList parts = file.baseName().split("_");
QString language = parts.at(parts.count() - 2);
QString country = parts.at(parts.count() - 1);
// construct and load translator
QTranslator* translator = new QTranslator(instance());
if (translator->load(file.absoluteFilePath()))
{
QString locale = language + "_" + country;
translators.insert(locale, translator);
}
}
}
const QStringList Application::availableLanguages()
{
// the content won't get copied thanks to implicit sharing and constness
return QStringList(translators.keys());
}
void Application::setLanguage(const QString& locale)
{
//test to translate dialog windows
/*
QTranslator qtTranslator;
QString qTLocale=locale.mid(0,2);
qtTranslator->load("qt_"+ qTLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
installTranslator(qtTranslator);
//*/
// remove previous
if (current)
{
removeTranslator(current);
}
// install new
current = translators.value(locale, 0);
if (current)
{
installTranslator(current);
}
}
I added the lines commented with "//test to translate dialog Windows" to try the dynamic translation of the dialog Windows but it doesn't work (no error at compilation but the application isn't launched with error message "the program stopped suddenly", I am on Qt Creator). Thanks!
So I finally got this to work after having the same problems. There are two things which were wrong in my case:
Name of the qt translation file:
QTranslator qtTranslator;
qtTranslator.load("qt_de"); // worked in older qt versions
qtTranslator.load("qtbase_de"); // works for qt5.2
a.installTranslator(&qtTranslator);
Have the correct parent for the QMessageBox. This is obvious after you think about it but pretty easy to miss.
QMessageBox::information(someChildOfMainWindow, ...);
For the latter, if you happen to be in a class which is a QObject but not a QWidget you can also use the following code to access your MainWindow from anywhere:
QMainWindow* mw = 0;
foreach(QWidget* widget, QApplication::topLevelWidgets()) {
if(widget->objectName() == "<your-main-window-class-name-here>") {
mw = qobject_cast<QMainWindow>(widget);
}
}
Ok Sébastian Lange, so finally I created the box and didn't use the static ones (
QMessageBox::question(..) for example)
QMessageBox quitMessageBox;
quitMessageBox.setWindowTitle(tr("Quit"));
quitMessageBox.setWindowIcon(QIcon("myIcon.jpg"));
quitMessageBox.setIcon(QMessageBox::Question);
quitMessageBox.setText(tr("Quit the application?"));
quitMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
quitMessageBox.setDefaultButton(QMessageBox::No);
quitMessageBox.button(QMessageBox::Yes)->setText(tr("Yes"));
quitMessageBox.button(QMessageBox::No)->setText(tr("No"));
And then
quitMessageBox.exec();
Like that it's ok. Thanks again!
When providing buttons for the dialog use
tr("Yes")
as for default dialogs, the created .ts-language file (to be edited via QtLinguist) should have default translations included.
The tr() marks the given argument to be translated. This concludes to if you do not know what will be written on a given label, you cannot translate it...

Qt: Simple Example for Quazip

I built the quazip library. I need a simple example that shows how to unzip a zip File. For example.
Quazip zipFile( QFile("test.zip") );
zipFile.unzip();
Tests shown in quazip is little bit confusing. I searched for a brief amount of time to find an example and I wasn't able to find one.
Here is a quick example showing how to read the files. You will need to make some modifications to the code in the loop to write the data to a file or perform whatever operations your application requires:
QuaZip zip("zipFile.zip");
zip.open(QuaZip::mdUnzip);
QuaZipFile file(&zip);
for(bool f=zip.goToFirstFile(); f; f=zip.goToNextFile()) {
file.open(QIODevice::ReadOnly);
//same functionality as QIODevice::readData() -- data is a char*, maxSize is qint64
file.readData(data,maxSize);
//do something with the data
file.close();
}
zip.close();
You can use static functions of the class JlCompress. It's very easy to use.
Static Public Member Functions
static bool compressFile (QString fileCompressed, QString file)
static bool compressFiles (QString fileCompressed, QStringList files)
static bool compressDir (QString fileCompressed, QString dir=QString(), bool recursive=true)
static QString extractFile (QString fileCompressed, QString fileName, QString fileDest=QString())
static QStringList extractFiles (QString fileCompressed, QStringList files, QString dir=QString())
static QStringList extractDir (QString fileCompressed, QString dir=QString())
static QStringList getFileList (QString fileCompressed)
Source: http://quazip.sourceforge.net/classJlCompress.html

Resources