so, mutig geworden, geht es nun weiter, ohne boost.signals um vor Überraschungen sicher zu sein bzw. an der falschen Stelle zu suchen
Nun soll die App dynamisch die Language ändern können, dazu habe ich das SDI Programm geändert
Code: Alles auswählen
void MainWindow::init()
{
...
createActions();
...
retranslateStrings();
...
}
void MainWindow::createActions()
{
newAct = new QAction(this);
newAct->setIcon(QIcon(":/images/new.png"));
connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
openAct = new QAction(this);
....
}
void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
....
createLangMenu();
....
}
QStringList MainWindow::findAppLangFiles()
{
appLangPath = qApp->applicationDirPath() + "/i18n";
QDir appLangDir(appLangPath);
if(!appLangDir.exists()) {
QMessageBox::warning(0, tr("Language Support Missing"),
tr("Unable to find application\n"
"specific directory for language files."));
}
QStringList langFiles =
appLangDir.entryList(QStringList("*.qm"), QDir::Files, QDir::Name);
for(QStringList::iterator i = langFiles.begin(); i != langFiles.end(); ++i) {
*i = appLangDir.filePath(*i);
langFileMap[languageName(*i)] = *i; // XXX displaced OO
}
return langFiles;
}
QString MainWindow::languageName(const QString &langFile)
{
QTranslator translator;
translator.load(langFile);
return translator.translate("MainWindow", defaultLang.toLatin1());
}
void MainWindow::switchLanguage(QAction *act)
{
qDebug() << "Switch Language, load " << langFileMap[act->text()];
QTranslator translator;
translator.load(langFileMap[act->text()]);
qApp->installTranslator(&translator);
}
void MainWindow::createLangMenu()
{
langMenu = menuBar()->addMenu(tr("&Language"));
langActGrp = new QActionGroup(this);
QStringList langFiles = findAppLangFiles();
for (int i = 0; i != langFiles.size(); ++i) {
QString lang = languageName(langFiles[i]);
QAction *langAct = new QAction(lang, langActGrp);
langAct->setCheckable(true);
langAct->setChecked(lang == defaultLang);
langAct->setActionGroup(langActGrp);
#if 1
langMenu->addAction(langAct);
#else // XXX Doesn't work! Why???
langAct->setMenu(langMenu);
#endif
}
connect(langActGrp, SIGNAL(triggered(QAction *)),
this, SLOT(switchLanguage(QAction *)));
}
void MainWindow::retranslateStrings()
{
newAct->setText(tr("&New"));
newAct->setShortcut(tr("Ctrl+N", "New"));
newAct->setStatusTip(tr("Create a new file"));
openAct->setText(tr("&Open..."));
...
foreach(QAction *action, langActGrp->actions())
action->setStatusTip(tr("Changes to Language to %1").arg(action->text()));
}
void MainWindow::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
qDebug() << "got LanguageChange event";
retranslateStrings();
} else {
QMainWindow::changeEvent(e);
}
}
const QString MainWindow::defaultLang(tr("English", "translated Language Name"));
Leider klappt das Translate beim Language Wechsel nicht, obwohl lt. qDebug alles relevante aufgerufen wird.
Wie kann ich die Menüs im nachhinein neu texten? Früher bei QT3 konnte man IDs vergeben .... Das gleiche Problem betrifft die Tool- und Statusbar. Wie bekomme ich QMessageBox::{warning|...} in anderen Sprachen hin?
Ich habe eine Hashmap für Language zu qm mapping eingeführt, hier im source etwas deplaziert aber wirksam. Ich könnte es in eigene Fkt. werfen, allerdings werden dann einige Variablen nochmals abgefragt konkret languageName(). Gibt's andere Möglichkeiten?
Müssen die anderen Widgets, zB FindDlg, ebenfalls die event Funktion überschreiben und FindDlg::retranslateStrings() aufrufen? Alle DialogTexte in einer Klasse zu behalten, wie das einige Bsp. von qt mH. des Context machen, halte ich für zu umständlich; Jede Klasse sollte ihren eigenen retranslateStrings() member haben.
Zuletzt, was ist der Unterschied zu langMenu->addAction(langAct) und langAct->setMenu(langMenu)? Bei ersteren erscheint das menu, beim letzteren nicht.
Viele Grüße
Olaf