Translation not working in Qt - c++

I have been all day long googling for a solution and changing my code, but no luck.
Basically, I have added translation to my app. It is working fine except here:
QString MainWindow::getMessage(Messages msg) {
static const char* const messages[] = {
QT_TR_NOOP("Setting power on"),
QT_TR_NOOP("Reading ID..."),
QT_TR_NOOP("Programming..."),
QT_TR_NOOP("Setting write-protect"),
QT_TR_NOOP("Finished ok"),
QT_TR_NOOP("PROGRAMMED OK"),
QT_TR_NOOP("ERROR!"),
QT_TR_NOOP("OK"),
QT_TR_NOOP("The programmer is not connected.\nPlease check the connection."),
QT_TR_NOOP("Disconnect the board, it is in short!!"),
QT_TR_NOOP("ERROR: Supply voltage too low (1 Volt is required, Measured: 0.0 Volt)."),
QT_TR_NOOP("Board is already programmed and write protected."),
QT_TR_NOOP("Check device connection or there is short."),
QT_TR_NOOP("Unknown error.")
};
return tr(messages[msg]);
}
However, I don't get the translation. The files for translation seems to be ok, the UI translations are applied fine.
I also tried this:
static const char* const messages[] = {
QT_TRANSLATE_NOOP("test", "Setting power on"),
QT_TRANSLATE_NOOP("test", "Reading ID..."),
QT_TRANSLATE_NOOP("test", "Programming..."),
QT_TRANSLATE_NOOP("test", "Setting write-protect"),
QT_TRANSLATE_NOOP("test", "Finished ok"),
QT_TRANSLATE_NOOP("test", "PROGRAMMED OK"),
QT_TRANSLATE_NOOP("test", "ERROR!"),
QT_TRANSLATE_NOOP("test", "OK"),
QT_TRANSLATE_NOOP("test", "The programmer is not connected.\nPlease check the connection."),
QT_TRANSLATE_NOOP("test", "Disconnect the board, it is in short!!"),
QT_TRANSLATE_NOOP("test", "ERROR: Supply voltage too low (1 Volt is required, Measured: 0.0 Volt)."),
QT_TRANSLATE_NOOP("test", "Board is already programmed and write protected."),
QT_TRANSLATE_NOOP("test", "Check device connection or there is short."),
QT_TRANSLATE_NOOP("test", "Unknown error.")
};
Then, I have a method to get the message:
QString MainWindow::getMessage(Messages msg) {
return qApp->translate("test", messages[msg]);
}
But it doesn't work either.
Any tips or suggestions?

I have found the real issue here.
Usually translators are installed at main.cpp, so the translator object remains in memory.
However, in my case, I was switching the translator after the user changes the language at settings dialog, using a local variable but void QCoreApplication::installTranslator ( QTranslator * translationFile ) [static] needs a pointer. That local variable is removed as soon as the function exits.
So, I declared a QTranslator object on my class, so it keeps in memory.

Maybe not applicable in this situation, but often people forget to place the Q_OBJECT macro in the class declaration. Resulting in (amongst others) tr() not working.

I was preparing a simpler source to upload here but now it is working fine! I rebooted my PC yesterday, you know, sometimes a reboot fixes everything (?).
Anyway, here is some source as it was requested. And by the way, I'm doing the translation on the fly, and by letting the user to choose the language (not by detecting locales):
This is main.cpp (nothing was added by me):
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
This is mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDir>
#include <QTranslator>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QDir d(":/translations/");
QStringList files = d.entryList(QStringList("*.qm"));
qDebug("There are %d files for translation", files.count());
// Now let's fill the combobox
this->ui->comboBox->clear();
for (int i = 0; i < files.count(); ++i) {
QTranslator translator;
translator.load(files[i], ":/translations/");
QString language = translator.translate("MainWindow",
"English");
this->ui->comboBox->addItem(language);
}
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_comboBox_currentIndexChanged(int index)
{
// Now, based on the new itemindex, let's change the translator
QString selectedLang = this->ui->comboBox->itemText(index);
QString language;
QDir d(":/translations/");
QStringList files = d.entryList(QStringList("*.qm"));
for (int i = 0; i < files.count(); ++i) {
QTranslator translator;
translator.load(files[i], ":/translations/");
language = translator.translate("MainWindow",
"English");
if (language == selectedLang) {
if (!qApp->installTranslator(&translator)) {
qDebug("ERROR INSTALLING TRANSLATOR !!!");
}
this->uiTranslate();
break;
}
}
}
/// This function translates all the UI texts:
void MainWindow::uiTranslate(void) {
this->setWindowTitle(tr("MainWindow"));
// Just for testing, also show all the messages
for (int i = 0; i < MSG_LAST; ++i) {
this->ui->textBrowser->append(this->getMessage((Messages)i));
}
}
QString MainWindow::getMessage(Messages idx) {
static const char* const messagesText[MSG_LAST] = {
QT_TR_NOOP("Hello!"),
QT_TR_NOOP("Bye bye"),
QT_TR_NOOP("Nice to meet you")
};
return (tr(messagesText[idx]));
}
in this test app, the UI just has a combobox and a text browser.
The combobox is filled with the languages included on the resource file.
When I change the combobox, the mainwindow title is changed and the messages are printed in the right language.
Thanks anyway!
Best regards,

Related

Implementing autofill for onlyfans login page with QWebEngine based app

I'm trying to implement autofill functionality in a Qt Webengine based app.
My approach is based off Viper browser's implementation: running script on page's loadFinished signal. The script run just looks up all the fields that can be populated and fills them as simple as elem.value = 'value'.
It works with simple example like e.g. my wifi router config page (which uses very simple logic for forms). But it doesn't work with e.g. https://onlyfans.com/ login page.
When I run my script I get JS errors like:
"js: Uncaught TypeError: Cannot set property 'value' of null".
The minimal example demonstrating the issue:
#include <QApplication>
#include <QObject>
#include <QTimer>
#include <QWebEngineView>
#include <QWebEnginePage>
#include <QWebEngineProfile>
#include <QWebEngineScript>
#include <QWebEngineScriptCollection>
const char* URL_ONLYFANS = "https://onlyfans.com/";
const char* URL_ROUTER = "http://192.168.0.1/";
const char* SCRIPT_ROUTER(R"(
document.querySelector('input[type=text]').value = 'admin';
document.querySelector('input[type=password]').value = 'mypass';
)");
const char* SCRIPT_ONLYFANS(R"(
document.querySelector('input[name=email]').value = "random#gmail.com";
document.querySelector('input[name=password]').value = "randompass";
)");
class Observer : public QObject
{
Q_OBJECT
public:
explicit Observer(QWebEnginePage *page): _page(page)
{}
public slots:
void onPageLoad(bool ok)
{
qDebug() << "Page loaded" << ok;
// Running script right away pretty much guarantees JS errors
// No JS errors if delay is >= 1500 ms:
QTimer::singleShot(1500, this, &Observer::runScript);
qDebug() << "Scheduled running script";
}
void runScript()
{
_page->runJavaScript(SCRIPT_ONLYFANS);
qDebug() << "Ran script";
}
private:
QWebEnginePage *_page{nullptr};
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWebEngineView view;
QWebEngineProfile profile;
QWebEnginePage page(&profile);
view.setPage(&page);
view.setUrl(QUrl(URL_ONLYFANS));
view.resize(1024, 750);
Observer observer(view.page());
QObject::connect(view.page(), &QWebEnginePage::loadFinished,
&observer, &Observer::onPageLoad);
/*
{
QWebEngineScript script;
script.setName("autofill");
script.setSourceCode(SCRIPT_ONLYFANS);
// Also tried `DocumentCreation` and `Deferred`, didn't work for Onlyfans
script.setInjectionPoint(QWebEngineScript::DocumentReady);
script.setRunsOnSubFrames(true);
script.setWorldId(QWebEngineScript::ApplicationWorld);
view.page()->scripts().insert(script);
}
*/
view.show();
return app.exec();
}
#include "main.moc"
As can be seen I tried to insert my scripts in two ways: on page's loadFinished signal (both immediately and with a time delay) and by inserting my script into page's scripts collection. I tried all available insertion points: DocumentCreation, DocumentReady and Deferred.
In all cases I get JS error shown above. Except for the case when I delay script execution by about 1500 ms, which is obviously a guess and is not robust.
I do understand that the elements I'm trying to set are probably not yet created, so I'd like some advice on how to properly time the script execution.

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.

QCompleter::activated disconnected after losing and gaining focus

I found a strange case which I do not understand. Maybe it is a Qt bug, maybe I am doing something wrong.
A header:
// File mylineedit.h
#pragma once
#include <QLineEdit>
#include <QDebug>
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit MyLineEdit(QWidget *parent = nullptr) : QLineEdit(parent) { }
public slots:
void onCompleterActivated(const QString& text) { qDebug() << "MyLineEdit" << text; }
};
And the main source file:
// File main.cpp
#include <QApplication>
#include <QWidget>
#include <QStringListModel>
#include <QCompleter>
#include <QVBoxLayout>
#include "mylineedit.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QLineEdit* lineEdit1 = new MyLineEdit();
QLineEdit* lineEdit2 = new MyLineEdit();
auto layout = new QVBoxLayout(&w);
layout->addWidget(lineEdit1);
layout->addWidget(lineEdit2);
lineEdit1->setCompleter(new QCompleter());
auto model = new QStringListModel(QStringList() << "A" << "B" << "C");
lineEdit1->completer()->setModel(model);
QObject::connect(lineEdit1->completer(), SIGNAL(activated(QString)), lineEdit1, SLOT(onCompleterActivated(QString)));
w.show();
return a.exec();
}
Once you run this, you can get a completer with values "A", "B", "C" in the first line edit. When you select any of these values, it will print the message to the console. This is correct. But then change focus to the other line edit and then back. Try picking "A", "B", "C" again. No message is printed out, the signal/slot seems disconnected. Any ideas?
Tested with MinGW 5.3.0 and MSVC 2015 using with Qt 5.9.2.
I modified your sample slightly and tried to reproduce the behavior you described but I couldn't:
#include <QtWidgets>
int main(int argc, char **argv)
{
qDebug() << "Qt Version: " << QT_VERSION_STR;
// main application
QApplication app(argc, argv);
// setup GUI
QWidget qWin;
QVBoxLayout qVBox;
QLineEdit qEdit1;
qVBox.addWidget(&qEdit1);
QCompleter qCompl1;
QStringListModel qComplModel(QStringList() << "A" << "B" << "C");
qCompl1.setModel(&qComplModel);
qEdit1.setCompleter(&qCompl1);
QLineEdit qEdit2;
qVBox.addWidget(&qEdit2);
qWin.setLayout(&qVBox);
qWin.show();
// install signal handlers
QObject::connect(&qCompl1,
static_cast<void(QCompleter::*)(const QString&)>(
&QCompleter::activated),
[](const QString &text)
{
qDebug() << "Activated: " << text;
});
// run-time loop
return app.exec();
}
The significant differences in my sample:
I used Qt5 style signal handlers (as I'm used to).
I didn't new the Qt widgets (as I'm used to when I write minimal samples).
For me, it's hard to believe that one of these changes makes your described issue unbroken.
I compiled and tested with VS2013, Qt 5.9.2 on Windows 10 (64 bit):
I did the following interactions:
click in qEdit1
type A and click on item A in the popup menu
Output:
Activated: "A"
I continued with:
click in qEdit2
type B
click in qEdit1
erase text, type B, and click on item B in the popup menu
Output:
Activated: "B"
It works like expected.
After some conversation, I had a look at woboq.org in the source code of QLineEdit:
The interesting part is in QLineEdit::focusOutEvent:
if (d->control->completer()) {
QObject::disconnect(d->control->completer(), 0, this, 0);
}
If I read this right, all signal handlers of QLineEdit (emitted by the set completer) are disconnected. I believe this is the reason for the observed issue. (Therefore, it works for lambdas and methods of other classes.)

QTextObjectInterface with Qml TextEdit (QQuickTextEdit)

I registred handler for simple QTextObjectInterface, that draws just 10x10 red rectangle.
When i used QTextEdit in normal QWidget app, it worked.
When i used QQuickTextEdit (TextEdit qml component) in Qt Quick app, it doesn't worked (nothing is drawed, but the rectangle in TextEdit is reserved, because when i change cursor position, i notice that there is something, but just empty space, nothing is drawed.
The QTextObjectInterface intrinsicSize method is called (that explains why i see there is empty space 10x10), but the drawObject method isn't.
I did some research and i found that actually the problem is probably here:
QQuickTextEdit.cpp from Qt 5.3.0 sources (line 1821)
QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) {
.
.
.
if (textFrame->firstPosition() > textFrame->lastPosition()
&& textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
updateNodeTransform(node, d->document->documentLayout()->frameBoundingRect(textFrame).topLeft());
const int pos = textFrame->firstPosition() - 1;
ProtectedLayoutAccessor *a = static_cast<ProtectedLayoutAccessor *>(d->document->documentLayout());
QTextCharFormat format = a->formatAccessor(pos);
QTextBlock block = textFrame->firstCursorPosition().block();
node->m_engine->setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
node->m_engine->addTextObject(QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document,
pos, textFrame->frameFormat().position());
nodeStart = pos;
}
it never reaches the point where node->m_engine->addTextObject is called.
It is because
this part of if condition textFrame->firstPosition() > textFrame->lastPosition() is evaluated to false.
I tried std::cout the firstPostion and the lastPosition when i established the context and firstPosition is 0, lastPosition is 1.
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTextDocument>
#include <QQuickTextDocument>
#include <iostream>
#include <QTextCursor>
#include <QTextBlock>
#include <QPainter>
#include <QAbstractTextDocumentLayout>
#include <QTextCharFormat>
#include "qmlcomponentspace.h"
#include <QTextEdit>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QTextDocument * doc = engine.rootObjects().first()->findChild<QObject *>("editor")->property("textDocument").value<QQuickTextDocument *>()->textDocument();
QTextCursor cur(doc);
int objectType = QTextFormat::UserObject + 1000;
QmlComponentSpace * component = new QmlComponentSpace();
doc->documentLayout()->registerHandler(objectType, component);
QTextCharFormat fmt;
fmt.setObjectType(objectType);
fmt.setForeground(Qt::red);
fmt.setBackground(Qt::red);
cur.movePosition(QTextCursor::End);
cur.insertText(QString(QChar::ObjectReplacementCharacter), fmt);
std::cout << "FIRST:" << doc->rootFrame()->firstPosition() << std::endl;
std::cout << "END:" << doc->rootFrame()->lastPosition() << std::endl;
return app.exec();
}
What i am missing?
The documentation says at
http://doc.qt.io/qt-5/qquicktextdocument.html#details
Warning: The QTextDocument provided is used internally by Qt Quick elements to provide text manipulation primitives. You are not allowed to perform any modification of the internal state of the QTextDocument. If you do, the element in question may stop functioning or crash.

Get system username in Qt

Is there any cross platform way to get the current username in a Qt C++ program?
I've crawled the internet and the documentation for a solution, but the only thing I find are OS dependent system calls.
I was actually thinking about it a couple of days ago, and I came to the conclusion of having different alternatives, each with its own trade-off, namely:
Environment variables using qgetenv.
The advantage of this solution would be that it is really easy to implement. The drawback is that if the environment variable is set to something else, this solution is completely unreliable then.
#include <QString>
#include <QDebug>
int main()
{
QString name = qgetenv("USER");
if (name.isEmpty())
name = qgetenv("USERNAME");
qDebug() << name;
return 0;
}
Home location with QStandardPaths
The advantage is that, it is relatively easy to implement, but then again, it can go unreliable easily since it is valid to use different username and "entry" in the user home location.
#include <QStandardPaths>
#include <QStringList>
#include <QDebug>
#include <QDir>
int main()
{
QStringList homePath = QStandardPaths::standardLocations(QStandardPaths::HomeLocation);
qDebug() << homePath.first().split(QDir::separator()).last();
return 0;
}
Run external processes and use platform specific APIs
This is probably the most difficult to implement, but on the other hand, this seems to be the most reliable as it cannot be changed under the application so easily like with the environment variable or home location tricks. On Linux, you would use QProcess to invoke the usual whoami command, and on Windows, you would use the GetUserName WinAPI for this purpose.
#include <QCoreApplication>
#include <QProcess>
#include <QDebug>
int main(int argc, char **argv)
{
// Strictly pseudo code!
#ifdef Q_OS_WIN
char acUserName[MAX_USERNAME];
DWORD nUserName = sizeof(acUserName);
if (GetUserName(acUserName, &nUserName))
qDebug << acUserName;
return 0;
#elif Q_OS_UNIX
QCoreApplication coreApplication(argc, argv);
QProcess process;
QObject::connect(&process, &QProcess::finished, [&coreApplication, &process](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug() << process.readAllStandardOutput();
coreApplication.quit();
});
process.start("whoami");
return coreApplication.exec();
#endif
}
Summary: I would personally go for the last variant since, even though it is the most difficult to implement, that is the most reliable.
There is no way to get the current username with Qt.
However, you can read this links :
http://www.qtcentre.org/threads/12965-Get-user-name
http://qt-project.org/forums/viewthread/11951
I think the best method is :
#include <stdlib.h>
getenv("USER"); ///for MAc or Linux
getenv("USERNAME"); //for windows
EDIT : You can use qgetenv instead of getenv.
In QT5 and up it is possible to do the following :
QString userName = QDir::home().dirName();
`QDir::home() returns the user's home directory.
You can use qEnvironmentVariable
QString sysUsername = qEnvironmentVariable("USER");
if (sysUsername.isEmpty()) sysUsername = qEnvironmentVariable("USERNAME");
Also you can use QProcessEnvironment like this:
QProcessEnvironmentenv = QProcessEnvironment::systemEnviroment();
QString username = env.value("USER");
There is a way to get the current windows username with Qt. Here it is
mainwindow.ui
This is the form ui
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>
#include <QDir>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->getUser();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::getUser()
{
QProcess *username = new QProcess();
QStringList cmdParamaters, split;
QString clean1, clean2, clean3,userName;
int cutOff, strLen;
cmdParamaters << "/c"<<"\"%USERPROFILE%\"";
username->setProcessChannelMode(QProcess::MergedChannels);
username->start("cmd.exe",cmdParamaters);
username->waitForFinished();
QString vusername (username->readAllStandardOutput());
cutOff = vusername.indexOf("'", 1);
ui->label_2->setText(vusername);
clean1 = vusername.left(cutOff);
ui->label_3->setText(clean1);
clean2 = clean1.remove(0,3);
strLen = clean2.length();
ui->label_4->setText(clean2);
clean3 = clean2.left(strLen-2);
split = clean3.split("\\");
userName = split[2]; //This is the current system username
ui->label_5->setText(userName);
delete username;
}
Output:
Code output