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
547550void 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
12981288void 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?\n Applying 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+
21822209void 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
37363784void MainWindow::cleanupRunningProcesses ()
37373785{
@@ -4305,8 +4353,9 @@ SonicPiLog* MainWindow::GetIncomingPane() const
43054353{
43064354 return incomingPane;
43074355}
4308-
4356+
43094357SonicPiTheme* MainWindow::GetTheme () const
43104358{
43114359 return theme;
43124360}
4361+
0 commit comments