Qt - Use builtin translations - c++

I'm using Qt and want to translate the texts "natively" shown by Qt widgets. By "texts natively shown" I'm for instance referring to the ones shown in context menus for text edits (copy, paste, ...).
Here is what I've already done:
#include <QApplication>
#include <QDebug>
#include <QTranslator>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
if(translator.load("qt_fr.qm", QApplication::applicationDirPath())) {
qDebug() << a.installTranslator(&translator);
}
qDebug() << QFile::exists(QApplication::applicationDirPath() + "/qt_fr.qm"); // just to debug file existence
// MainWindow w; // not related to my question
// w.showMaximized(); // neither is this
return a.exec();
}
The qt_fr.qm file is located at path_to_qt/Qt5.6.2/5.6/mingw49_32/translations for Qt5.6.2 and MinGW users. I copy the said file to the running software directory but the translator always fails to load it. But when I use my own qm file (built from a .ts file using the Qt lupdate and lrelease tools), the qm file is properly loaded and installed.
Is there something I'm missing or doing wrong?

I think the problem may be that you haven't copied the complete message catalog. The following works for me on a Debian system, using the QM files in their standard locations:
#include <QApplication>
#include <QDebug>
#include <QLocale>
#include <QTranslator>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
const QString dir = "/usr/share/qt5/translations";
if (translator.load("qt_fr", dir)) {
qDebug() << "first load succeeded:"
<< "'Open' =>" << translator.translate("QShortcut", "Open");
}
if (translator.load(QLocale::French, "qt", "_", dir)) {
qDebug() << "second load succeeded:"
<< "'Open' =>" << translator.translate("QShortcut", "Open");
}
}
Output is
first load succeeded: 'Open' => "Ouvrir"
second load succeeded: 'Open' => "Ouvrir"
(I removed the .qm from the filename, as Qt will try that first, and I've also shown how to compose the filename from a specific locale object).
If we inspect the qt_fr.qm file using lconvert -of ts /usr/share/qt5/translations/qt_fr.qm, we can see it's just a very small file that incorporates other files by reference:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fr_FR">
<dependencies>
<dependency catalog="qtbase_fr"/>
<dependency catalog="qtscript_fr"/>
<dependency catalog="qtquick1_fr"/>
<dependency catalog="qtmultimedia_fr"/>
<dependency catalog="qtxmlpatterns_fr"/>
</dependencies>
</TS>
I think that the most likely cause of your symptoms is that one or more of the dependency files could not be loaded. You should ensure that all of those files area available in the same location that you copied qt_fr.qm to - or, if you only need the "base" translations, just copy qtbase_fr.qm, and change your translator.load() call appropriately.

Related

how to translate key shortcut

I cannot force QKeySequence::toString() to return translated shortcut representation despite the fact that it documentation suggests it should work. The docs say: "The strings, "Ctrl", "Shift", etc. are translated using QObject::tr() in the "QShortcut" context." but I am not completely sure what it means by shortcut context. I am probably doing something wrong...
Here is my example. To make it work, I need to copy qtbase_es.qm from Qt installation directory to my project build directory. When the translation is correctly loaded, the action in the menu correctly shows "Action Control+Intro" which is Spanish translation of the shortcut for "Action Ctrl+Enter". But the tooltip on the main window is still "Action (Ctrl+Enter)". I would expect it to be "Action (Control+Intro)", like in the menu. What am I doing wrong?
#include <QAction>
#include <QApplication>
#include <QDebug>
#include <QMainWindow>
#include <QMenuBar>
#include <QTranslator>
int main(int argc, char *argv[])
{
QTranslator spanish;
qDebug() << spanish.load("qtbase_es.qm"); // should return true if correctly loaded
QApplication a(argc, argv);
QApplication::installTranslator(&spanish);
QMainWindow w;
auto menu = new QMenu("Menu");
auto action = menu->addAction("Action");
action->setShortcutContext(Qt::ApplicationShortcut);
action->setShortcut(Qt::CTRL | Qt::Key_Enter);
w.menuBar()->addMenu(menu);
w.show();
QApplication::processEvents(); // I also tried this line but it is useless...
w.setToolTip(QString("%1 (%2)").arg(action->text(), action->shortcut().toString()));
qDebug() << action->shortcut().toString(); // WRONG: returns Ctrl+Enter but I expect Control+Intro
return a.exec();
}
The QShortcut::toString has a SequenceFormat parameter, defaulted to ProtableText. The documentation of the format states, that portable format is intended for e.g. writing to a file.
The native format is intended for displaying to the user, and only this format performs translations.
Try:
qDebug() << action->shortcut().toString(QKeySequence::NativeText);

running draw_polygon example in CGAl package in qt widget application

I try to following CGAL example in Qt widget application :
example
main.ccp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.ccp :
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/draw_polyhedron.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
void MainWindow::on_pushButton_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this,tr("Open .off model"), "/home", tr("*.off"));
draw_poly(fileName);
}
void MainWindow::draw_poly(QString fileName)
{
QByteArray inBytes;
const char *c;
inBytes = fileName.toUtf8();
c = inBytes.constData();
std::ifstream input(c);
if (!input || !(input >> mesh) || mesh.is_empty()) {
std::cerr << "Not a valid off file." << std::endl;
// return 1;
}
input >> mesh;
CGAL::draw(mesh);
}
when I ran it , it open dialog file to select .off file ,then it shows the following error:
QCoreApplication::exec: The event loop is already running
any help ,please ?
I'm using Qt5 in daily business, and once considered CGAL as possible application base (without going further into this direction – not yet). Hence, this question made me curious.
I digged through the source code of CGAL on github and found out why the error message
QCoreApplication::exec: The event loop is already running
occurs.
For this, I copied the relevant lines from CGAL on github: Polyhedron/include/CGAL/draw_polyhedron.h:
template<class Polyhedron, class ColorFunctor>
void draw(const Polyhedron& apoly,
const char* title,
bool nofill,
const ColorFunctor& fcolor)
{
#if defined(CGAL_TEST_SUITE)
bool cgal_test_suite=true;
#else
bool cgal_test_suite=false;
#endif
if (!cgal_test_suite)
{
int argc=1;
const char* argv[2]={"polyhedron_viewer","\0"};
QApplication app(argc,const_cast<char**>(argv));
SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
mainwindow(app.activeWindow(), apoly, title, nofill, fcolor);
mainwindow.show();
app.exec();
}
}
Looking at this source code, it becomes obvious that CGAL::draw() is a small ful-featured Qt application in itself which establishs its own QApplication instance. The OP in turn tried to embed the CGAL::draw() in her/his own Qt application. It is not allowed to instance any derivates of QCoreApplication more than once (according to Qt doc. of QApplication):
For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time.
(Emphasizing not mine.)
The CGAL doc. provides an (even shorter) example in Polyhedron/draw_polyhedron.cpp to do this right:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/draw_polyhedron.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
int main(int argc, char* argv[])
{
Polyhedron P;
std::ifstream in1((argc>1)?argv[1]:"data/cross.off");
in1 >> P;
CGAL::draw(P);
return EXIT_SUCCESS;
}
but there is no place to insert the QFileDialog at the right point.
Hence, CGAL::draw() is the wrong tool for what OP (probably) intends to do – embed CGAL polyhedron rendering into a Qt application. For this, it is necessary to use the things directly which are called somewhere inside of CGAL::draw().
So, this is what seems appropriate to me:
making SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> a (main or child) widget in OPs Qt application.
I then walked a bit through the github repo to find out from which Qt widget CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> is actually derived from and found the following inheritance:
CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
|
V
CGAL::Basic_viewer_qt
|
V
CGAL::QGLViewer
|
+--------------+--------------+
| |
V V
QOpenGLWidget QOpenGLFunctions
So, CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> can be used like any QWidget (which involves making it the main window). It can become as well the center widget of a QMainWindow which gets a menu bar/tool bar with the QAction to open the QFileDialog, request a file path, open a file stream with this file path, and load a mesh from this file stream.
There is another minor detail where I stumbled over: The CGAL::Polyhedron has to be given to the CGAL::SimplePolyhedronViewerQt in the constructor and by const reference. To consider this, it's IMHO necessary (after successful loading of mesh) to construct the CGAL::SimplePolyhedronViewerQt instance by new and set/add it to parent widget afterwards. If this is not acceptable it's probably necessary to go even deeper and replace the CGAL::SimplePolyhedronViewerQt by an own implementation, using the source code of the former as “cheat-sheet”.
This is how such an application could look like:
#include <fstream>
#include <QtWidgets>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/draw_polyhedron.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
CGAL::DefaultColorFunctorPolyhedron fColor;
Polyhedron mesh;
// setup UI
QMainWindow qWin;
QToolBar qToolbar;
QAction qCmdLoad(QString::fromUtf8("Load File..."));
qToolbar.addAction(&qCmdLoad);
qWin.addToolBar(&qToolbar);
qWin.show();
// install signal handlers
QObject::connect(&qCmdLoad, &QAction::triggered,
[&qWin, &mesh, &fColor]() {
const QString filePath = QFileDialog::getOpenFileName(
&qWin,
QString::fromUtf8("Open .off model"),
QString::fromUtf8("/home"),
QString::fromUtf8("*.off"));
if (filePath.isEmpty()) return;
std::ifstream fIn(filePath.toUtf8().data());
if (!(fIn >> mesh) || mesh.is_empty()) {
qDebug() << "Loading of" << filePath << "failed!";
return;
}
qWin.setCentralWidget(
new CGAL::SimplePolyhedronViewerQt<Polyhedron, CGAL::DefaultColorFunctorPolyhedron>(
&qWin, mesh, "Basic Polyhedron Viewer", false, fColor));
qWin.centralWidget()->show();
});
// runtime loop
return app.exec();
}
Please, take this with a “grain of salt” – I've no CGAL at hand and couldn't compile/test the above code.
CGAL::draw() already handles the Qt stuff. You are trying to open a mainwindow in another one. Just call CGAL::draw(mesh) in your main() function without anything else and it will work.
EDIT: Which is exactly what Sheff explained in a much more detailed way.

How to set OffTheRecord profile for QWebEngineView?

How to setup OffTheRecord profile for QWebEngineView?
I use QT5.10 for Linux.
I am going to use it in embedded environment with read-only filesystem and I need to prevent WebEngine writing files and creating folders in filesystem.
#include <QApplication>
#include <QWebEngineView>
#include <QWebEngineSettings>
#include <QWebEngineProfile>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QWebEngineView view;
auto profile = view.page()->profile();
profile->setHttpCacheType(QWebEngineProfile::MemoryHttpCache);
profile->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);
//profile->setPersistentStoragePath(nullptr);
std::cout << "StoragePath: " << profile->persistentStoragePath().toStdString() << std::endl;
std::cout << "isOffTheRecord: " << profile->isOffTheRecord() << std::endl;
profile->settings()->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); // Since Qt5.7
profile->settings()->setAttribute(QWebEngineSettings::XSSAuditingEnabled, false);
view.setUrl(QUrl(QStringLiteral("http://localhost/index.html")));
view.resize(1920, 1080);
view.show();
return a.exec();
}
Try this configuration:
First of all, disable any possible cookie. Use setPersistentCookiesPolicy and set it to NoPersistentCookies
If you can write in to a given folder, try to save all temporal files in a secure storage:
auto *profile = QWebEngineProfile::defaultProfile();
profile->setCachePath("yourfolder");
profile->setPersistentStoragePath("yourfolder");
This should give you the control of all the temporal files that are generated by the Web Engine.
If not, taking a look in to Qt repo, you can see that the variable that manage this state is controlled in BrowserContextAdapter, this variable is set up to false, if the storage path is empty while creating the browser context.
So if you create your own QWebEngineProfile with an empty QString as path and use it as default profile:
QWebEngineProfile* profile = new QWebEngineProfile(QString(), parent)
std::cout << "isOffTheRecord: " << profile->isOffTheRecord() << std::endl; // Should return true
This can be done easily if you use it to create any single QWebEnginePage manually using this profile and set it in your QWebEngineView using setPage:
engineview->setPage(new QWebEnginePage(profile, parent));
The documentation for QWebEngineProfile's default constructor states:
Constructs a new off-the-record profile with the parent parent.
An off-the-record profile leaves no record on the local machine, and
has no persistent data or cache. Thus, the HTTP cache can only be in
memory and the cookies can only be non-persistent. Trying to change
these settings will have no effect.
Once you've created a default QWebEngineProfile, pass it to a QWebEnginePage and set that as the page in your QWebEngineView.
Here's a simple example that compiles and runs (tested on Mac OS):
#include <QApplication>
#include <QWebEngineView>
#include <QWebEngineSettings>
#include <QWebEnginePage>
#include <QWebEngineProfile>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWebEngineView view;
QWebEngineProfile profile;
QWebEnginePage page(&profile);
qDebug() << "StoragePath:" << profile.persistentStoragePath();
qDebug() << "isOffTheRecord:" << profile.isOffTheRecord();
view.setPage(&page);
view.setUrl(QUrl(QStringLiteral("http://www.stackoverflow.com/")));
view.show();
return a.exec();
}
When running the above you should see this appear in standard out:
StoragePath: ""
isOffTheRecord: true

vc++ + QT translation of UI is not working

I have a project with QT in vc++ and I need to locate the string in the UI to different languages. I created a UI through the QTdesigner in the visual studio add in of visual studio 2012 and also I have installed the QT plugin to use the Qt features as well.
I have created a .pro file and added:
SOURCES += main.cpp
TRANSLATIONS += languagefileqt_es.ts
After I generate a linguist file SOURCES emminensmultiportqt_es.ts and it detected correctly all the strings in my IU. After that, I generate the .qm file using the release function of Qtlinguist.
My resources file is:
<RCC>
<qresource prefix="MyAppQT">
<file>languagefileqt_es.qm</file>
</qresource>
</RCC>
Then I have added this to my main.cpp:
QTranslator translator;
bool loaded = translator.load("languagefileqt_es");
qDebug() << "loaded " << loaded;
a.installTranslator(&translator);
And loaded returns true in all the cases. My problem is that the UI is not translated when the application is executed. It is weird because it has no effect.
Any clue about what I am missing or what could I check out?
Thanks a lot
Are you sure, that "languagefileqt_es" is the correct name of your language file? I would expect "languagefileqt_es.qm" instead.
Are you sure that you are loading from the correct directory? Unless you are loading from an internal compiled-in resource (:/languagefileqt_es.qm) you should refer to an absolute path to make sure, that you load the correct thing.
I discovered what was the problem. thanks #Jens for try to help.
I think I commit a mistake of not knowing how the translating mechanism was working. In my main.cpp I had:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindowQT w;
QTranslator translator;
bool loaded = translator.load("languagefileqt_es");
qDebug() << "loaded " << loaded;
a.installTranslator(&translator);
w.show();
return a.exec();
}
But I realized that if I execute
qDebug() << QApplication::translate("MainWindowQTClass", "...BOARDING", 0);
after the loading process it will return the string translated correctly. So I change the definition of my UI after the internationalization and it worked. Apparently, translation is done in a function called retranslateUi() which is called in the constructor.
The correct main.cpp should be:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
bool loaded = translator.load("languagefileqt_es");
qDebug() << "loaded " << loaded;
a.installTranslator(&translator);
MainWindowQT w;
w.show();
return a.exec();
}

Reading from and writing to file in The Qt Resource System (qt 5.0.2)

I have the code below. I am using Qt_5_0_2_MSVC2012_64bit-Release. I am not able to read the file. I get the debug error message of "Cannot open file for reading".There is some problem for me with resource files. Any idea how I can fix it? Thanks!
#include <QCoreApplication>
#include <QFile>
#include <QString>
#include <QDebug>
#include <QTextStream>
#include <QResource>
#include <QIODevice>
void Read(QString Filename){
QFile mFile(Filename);
if(!mFile.open(QFile::ReadOnly | QFile::Text)){
qDebug() << "could not open file for read";
return;
}
QTextStream in(&mFile);
QString mText = in.readAll();
qDebug() << mText;
mFile.close();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Read(":/MyFiles/myfile.txt");
return a.exec();
}
I had same problem. The Error string was "Unknown error". Solution was to add INCLUDEPATH += . from #gatto's answer and run commands from menu:
1. Build -> Clean all
2. Build -> Run qmake
3. Build -> Rebuild All
test.pro:
TEMPLATE = app
TARGET = test
INCLUDEPATH += .
# Input
SOURCES += main.cpp
RESOURCES += test.qrc
test.qrc:
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>MyFiles/myfile.txt</file>
</qresource>
</RCC>
main.cpp is from your question. Works fine.
That said, if you still have the problem, you should post minimal Qt project (including .pro and .qrc files), that has the error.