Skip to content

Commit 23a406e

Browse files
committed
GUI - Add UI language option
1 parent a396163 commit 23a406e

File tree

13 files changed

+759
-76
lines changed

13 files changed

+759
-76
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ app/gui/qt/moc_mainwindow.cpp
6161
app/gui/qt/moc_sonicpiudpserver.cpp
6262
app/gui/qt/qrc_SonicPi.cpp
6363
app/gui/qt/utils/ruby_help.h
64-
app/gui/qt/help/*.html
64+
app/gui/qt/utils/lang_list.h
65+
app/gui/qt/help
6566
app/gui/qt/help_files.qrc
6667
app/gui/qt/lang/*.qm
6768
app/gui/qt/qrc_help_files.cpp

app/gui/qt/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,16 @@ set(QT_SOURCES
101101
set(SOURCES
102102
${QTAPP_ROOT}/main.cpp
103103
${QTAPP_ROOT}/utils/scintilla_api.cpp
104+
${QTAPP_ROOT}/utils/sonic_pi_i18n.cpp
104105
${QTAPP_ROOT}/widgets/sonicpilog.cpp
105106
${QTAPP_ROOT}/widgets/sonicpilog.h
106107
${QTAPP_ROOT}/widgets/sonicpicontext.cpp
107108
${QTAPP_ROOT}/widgets/sonicpicontext.h
108109
${QTAPP_ROOT}/utils/scintilla_api.h
110+
${QTAPP_ROOT}/utils/sonic_pi_i18n.h
109111
${QTAPP_ROOT}/utils/ruby_help.h
112+
${QTAPP_ROOT}/utils/lang_list.h
113+
${QTAPP_ROOT}/utils/paths.h
110114
${QTAPP_ROOT}/model/settings.h
111115
)
112116

app/gui/qt/main.cpp

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
// notice is included.
1212
//++
1313

14+
#include <iostream>
15+
1416
#include <QApplication>
1517
#include <QSplashScreen>
1618
#include <QPixmap>
1719
#include <QBitmap>
1820
#include <QLabel>
19-
#include <QTranslator>
2021
#include <QLibraryInfo>
2122

2223
#include "mainwindow.h"
@@ -35,7 +36,7 @@
3536

3637
int main(int argc, char *argv[])
3738
{
38-
39+
std::cout << "Starting Sonic Pi..." << std::endl;
3940
#ifndef Q_OS_MAC
4041
Q_INIT_RESOURCE(SonicPi);
4142
#endif
@@ -49,16 +50,6 @@ int main(int argc, char *argv[])
4950

5051
qRegisterMetaType<SonicPiLog::MultiMessage>("SonicPiLog::MultiMessage");
5152

52-
QString systemLocale = QLocale::system().uiLanguages()[0].replace("-", "_");
53-
54-
QTranslator qtTranslator;
55-
qtTranslator.load("qt_" + systemLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
56-
app.installTranslator(&qtTranslator);
57-
58-
QTranslator translator;
59-
bool i18n = translator.load(QLatin1String("sonic-pi_") + systemLocale, QLatin1String(":/lang")) || systemLocale.startsWith("en") || systemLocale == "C";
60-
app.installTranslator(&translator);
61-
6253
app.setApplicationName(QObject::tr("Sonic Pi"));
6354
app.setStyle("gtk");
6455

@@ -75,7 +66,7 @@ int main(int argc, char *argv[])
7566
splash->show();
7667
splash->repaint();
7768
app.processEvents();
78-
MainWindow mainWin(app, i18n, splash);
69+
MainWindow mainWin(app, splash);
7970

8071
return app.exec();
8172
#elif _WIN32
@@ -109,7 +100,7 @@ int main(int argc, char *argv[])
109100
splash->show();
110101
splash->repaint();
111102
app.processEvents();
112-
MainWindow mainWin(app, i18n, splash);
103+
MainWindow mainWin(app, splash);
113104

114105
// Fix for full screen mode. See: https://doc.qt.io/qt-5/windows-issues.html#fullscreen-opengl-based-windows
115106
QWindowsWindowFunctions::setHasBorderInFullScreen(mainWin.windowHandle(), true);
@@ -139,9 +130,8 @@ int main(int argc, char *argv[])
139130
splashWindow->show();
140131
app.processEvents();
141132

142-
MainWindow mainWin(app, i18n, splashWindow);
133+
MainWindow mainWin(app, splashWindow);
143134
return app.exec();
144135

145136
#endif
146-
147137
}

app/gui/qt/mainwindow.cpp

Lines changed: 77 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
#include "widgets/sonicpilexer.h"
5353
#include "widgets/sonicpiscintilla.h"
5454

55+
#include "utils/sonic_pi_i18n.h"
56+
5557
#include "utils/borderlesslinksproxystyle.h"
5658

5759
// OSC stuff
@@ -79,6 +81,7 @@ using namespace oscpkt; // OSC specific stuff
7981
#include "widgets/sonicpilog.h"
8082

8183
#include "utils/ruby_help.h"
84+
#include "utils/paths.h"
8285

8386
#include "dpi.h"
8487

@@ -105,9 +108,9 @@ using namespace SonicPi;
105108
#endif
106109

107110
#ifdef Q_OS_MAC
108-
MainWindow::MainWindow(QApplication& app, bool i18n, QMainWindow* splash)
111+
MainWindow::MainWindow(QApplication& app, QMainWindow* splash)
109112
#else
110-
MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
113+
MainWindow::MainWindow(QApplication& app, QSplashScreen* splash)
111114
#endif
112115
{
113116
app.installEventFilter(this);
@@ -118,9 +121,6 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
118121

119122
this->piSettings = new SonicPiSettings();
120123

121-
this->splash = splash;
122-
this->i18n = i18n;
123-
124124
#ifdef QT_OLD_API
125125
sonicPiOSCServer = NULL;
126126
#else
@@ -153,7 +153,6 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
153153
version_num = 0;
154154
latest_version_num = 0;
155155
this->splash = splash;
156-
this->i18n = i18n;
157156
#ifdef QT_OLD_API
158157
guiID = QUuid::createUuid().toString();
159158
#endif
@@ -163,6 +162,10 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
163162
initPaths();
164163

165164
bool startupOK = false;
165+
this->sonicPii18n = new SonicPii18n(ROOT_PATH);
166+
this->ui_language = sonicPii18n->determineUILanguage(piSettings->language);
167+
std::cout << "Using language: " << ui_language.toUtf8().constData() << std::endl;
168+
this->i18n = sonicPii18n->loadTranslations(ui_language);
166169

167170
#ifdef QT_OLD_API
168171
// Clear out old tasks from previous sessions if they still exist
@@ -226,7 +229,7 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
226229
// The implementation of this method is dynamically generated and can
227230
// be found in ruby_help.h:
228231
std::cout << "[GUI] - initialising documentation window" << std::endl;
229-
initDocsWindow();
232+
initDocsWindow(ui_language);
230233

231234
//setup autocompletion
232235
autocomplete->loadSamples(sample_path);
@@ -375,9 +378,9 @@ bool MainWindow::initAndCheckPorts()
375378
}
376379
#endif
377380

378-
void MainWindow::initPaths()
379-
{
380-
QString root_path = rootPath();
381+
382+
void MainWindow::initPaths() {
383+
QString root_path = ROOT_PATH;
381384

382385
#ifdef QT_OLD_API
383386
#if defined(Q_OS_WIN)
@@ -541,7 +544,7 @@ void MainWindow::setupTheme()
541544
{
542545
// Syntax highlighting
543546
QString themeFilename = QDir::homePath() + QDir::separator() + ".sonic-pi" + QDir::separator() + "config" + QDir::separator() + "colour-theme.properties";
544-
this->theme = new SonicPiTheme(this, themeFilename, rootPath());
547+
this->theme = new SonicPiTheme(this, themeFilename, ROOT_PATH);
545548
}
546549

547550
void MainWindow::setupWindowStructure()
@@ -579,7 +582,8 @@ void MainWindow::setupWindowStructure()
579582
prefsWidget->setAllowedAreas(Qt::RightDockWidgetArea);
580583
prefsWidget->setFeatures(QDockWidget::DockWidgetClosable);
581584

582-
settingsWidget = new SettingsWidget(server_osc_cues_port, piSettings, this);
585+
settingsWidget = new SettingsWidget(server_osc_cues_port, i18n, piSettings, sonicPii18n, this);
586+
connect(settingsWidget, SIGNAL(uiLanguageChanged(QString)), this, SLOT(changeUILanguage(QString)));
583587
connect(settingsWidget, SIGNAL(volumeChanged(int)), this, SLOT(changeSystemPreAmp(int)));
584588
connect(settingsWidget, SIGNAL(mixerSettingsChanged()), this, SLOT(mixerSettingsChanged()));
585589
connect(settingsWidget, SIGNAL(midiSettingsChanged()), this, SLOT(toggleMidi()));
@@ -1279,20 +1283,6 @@ void MainWindow::toggleComment(SonicPiScintilla* ws)
12791283
sendOSC(msg);
12801284
}
12811285

1282-
QString MainWindow::rootPath()
1283-
{
1284-
// diversity is the spice of life
1285-
#if defined(Q_OS_MAC)
1286-
return QCoreApplication::applicationDirPath() + "/../Resources";
1287-
#elif defined(Q_OS_WIN)
1288-
// CMake builds, the exe is in build/debug/sonic-pi, etc.
1289-
// We should pass this to the build instead of wiring it up this way!
1290-
return QCoreApplication::applicationDirPath() + "/../../../../..";
1291-
#else
1292-
// On linux, CMake builds app into the build folder
1293-
return QCoreApplication::applicationDirPath() + "/../../../..";
1294-
#endif
1295-
}
12961286

12971287
#ifdef QT_OLD_API
12981288
void MainWindow::startRubyServer()
@@ -1336,7 +1326,7 @@ void MainWindow::startRubyServer()
13361326
// Register server pid for potential zombie clearing
13371327
QStringList regServerArgs;
13381328
#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
1339-
regServerArgs << QDir::toNativeSeparators(rootPath() + "/app/server/ruby/bin/task-register.rb") << QString::number(serverProcess->processId());
1329+
regServerArgs << QDir::toNativeSeparators(ROOT_PATH + "/app/server/ruby/bin/task-register.rb")<< QString::number(serverProcess->processId());
13401330
#endif
13411331
QProcess* regServerProcess = new QProcess();
13421332
regServerProcess->start(ruby_path, regServerArgs);
@@ -2179,6 +2169,43 @@ void MainWindow::changeSystemPreAmp(int val, int silent)
21792169
statusBar()->showMessage(tr("Updating System Volume..."), 2000);
21802170
}
21812171

2172+
// TODO: Implement real-time language switching
2173+
void MainWindow::changeUILanguage(QString lang) {
2174+
if (lang != piSettings->language) {
2175+
std::cout << "Current language: " << piSettings->language.toUtf8().constData() << std::endl;
2176+
std::cout << "New language selected: " << lang.toUtf8().constData() << std::endl;
2177+
QString old_lang = sonicPii18n->getNativeLanguageName(piSettings->language);
2178+
QString new_lang = sonicPii18n->getNativeLanguageName(lang);
2179+
2180+
// Load new language
2181+
//QString language = sonicPii18n->determineUILanguage(lang);
2182+
//sonicPii18n->loadTranslations(language);
2183+
//QString title_new = tr("Updated the UI language from %s to %s").arg();
2184+
2185+
QMessageBox msgBox(this);
2186+
msgBox.setText(QString(tr("You've selected a new language: %1")).arg(new_lang));
2187+
msgBox.setInformativeText(tr("Do you want to apply this language?\nApplying the new language will restart Sonic Pi."));
2188+
QPushButton *restartButton = msgBox.addButton(tr("Apply and Restart"), QMessageBox::ActionRole);
2189+
QPushButton *dismissButton = msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole);
2190+
msgBox.setDefaultButton(restartButton);
2191+
msgBox.setIcon(QMessageBox::Information);
2192+
msgBox.exec();
2193+
2194+
if (msgBox.clickedButton() == (QAbstractButton*)restartButton) {
2195+
piSettings->language = lang;
2196+
writeSettings();
2197+
restartApp();
2198+
//statusBar()->showMessage(tr("Updated UI language setting, please restart Sonic Pi to apply it"), 2000);
2199+
} else if (msgBox.clickedButton() == (QAbstractButton*)dismissButton) {
2200+
// Don't apply the new language settings
2201+
settingsWidget->updateSelectedUILanguage(piSettings->language);
2202+
}
2203+
2204+
// Load previously set language
2205+
//sonicPii18n->loadTranslations(ui_language);
2206+
}
2207+
}
2208+
21822209
void MainWindow::changeScopeKindVisibility(QString name)
21832210
{
21842211
foreach (QAction* action, scopeKindVisibilityMenu->actions())
@@ -3500,6 +3527,8 @@ void MainWindow::readSettings()
35003527
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "sonic-pi.net", "gui-settings");
35013528

35023529
// Read in preferences from previous session
3530+
piSettings->language = settings.value("prefs/language", "system_locale").toString();
3531+
35033532
piSettings->show_buttons = settings.value("prefs/show-buttons", true).toBool();
35043533
piSettings->show_tabs = settings.value("prefs/show-tabs", true).toBool();
35053534
piSettings->show_log = settings.value("prefs/show-log", true).toBool();
@@ -3549,6 +3578,7 @@ void MainWindow::writeSettings()
35493578
{
35503579
std::cout << "[GUI] - writing settings" << std::endl;
35513580
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "sonic-pi.net", "gui-settings");
3581+
settings.setValue("prefs/language", piSettings->language);
35523582
settings.setValue("pos", pos());
35533583
settings.setValue("size", size());
35543584
settings.setValue("first_time", 0);
@@ -3732,6 +3762,24 @@ void MainWindow::onExitCleanup()
37323762
#endif
37333763
}
37343764

3765+
void MainWindow::restartApp() {
3766+
QApplication* app = dynamic_cast<QApplication*>(parent());
3767+
statusBar()->showMessage(tr("Restarting Sonic Pi..."), 10000);
3768+
// Save settings and perform some cleanup
3769+
writeSettings();
3770+
onExitCleanup();
3771+
sleep(1);
3772+
std::cout << "Performing application restart... please wait..." << std::endl;
3773+
//this->hide(); // So it doesn't look like the app's frozen or crashed
3774+
sleep(4); // Allow cleanup to complete
3775+
// Create new process
3776+
QProcess process;
3777+
process.startDetached("sonic-pi", QStringList());
3778+
// Quit
3779+
app->exit(0);
3780+
exit(0);
3781+
}
3782+
37353783
#ifdef QT_OLD_API
37363784
void MainWindow::cleanupRunningProcesses()
37373785
{
@@ -4305,8 +4353,9 @@ SonicPiLog* MainWindow::GetIncomingPane() const
43054353
{
43064354
return incomingPane;
43074355
}
4308-
4356+
43094357
SonicPiTheme* MainWindow::GetTheme() const
43104358
{
43114359
return theme;
43124360
}
4361+

0 commit comments

Comments
 (0)