52
52
#include " widgets/sonicpilexer.h"
53
53
#include " widgets/sonicpiscintilla.h"
54
54
55
+ #include " utils/sonicpi_i18n.h"
56
+
55
57
#include " utils/borderlesslinksproxystyle.h"
56
58
#include " visualizer/scope_window.h"
57
59
@@ -89,9 +91,9 @@ using namespace std::chrono;
89
91
using namespace SonicPi ;
90
92
91
93
#ifdef Q_OS_MAC
92
- MainWindow::MainWindow (QApplication& app, bool i18n, QMainWindow* splash)
94
+ MainWindow::MainWindow (QApplication& app, QMainWindow* splash)
93
95
#else
94
- MainWindow::MainWindow (QApplication& app, bool i18n, QSplashScreen* splash)
96
+ MainWindow::MainWindow (QApplication& app, QSplashScreen* splash)
95
97
#endif
96
98
{
97
99
app.installEventFilter (this );
@@ -103,7 +105,6 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
103
105
this ->piSettings = new SonicPiSettings ();
104
106
105
107
this ->splash = splash;
106
- this ->i18n = i18n;
107
108
108
109
// API and Client
109
110
m_spClient = std::make_shared<QtAPIClient>(this );
@@ -126,7 +127,6 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
126
127
version_num = 0 ;
127
128
latest_version_num = 0 ;
128
129
this ->splash = splash;
129
- this ->i18n = i18n;
130
130
QString settings_path = sonicPiConfigPath () + QDir::separator () + " gui-settings.ini" ;
131
131
132
132
gui_settings = new QSettings (settings_path, QSettings::IniFormat);
@@ -139,6 +139,19 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
139
139
m_spAPI->Init (rootPath ().toStdString ());
140
140
guiID = QString::fromStdString (m_spAPI->GetGuid ());
141
141
142
+ this ->sonicPii18n = new SonicPii18n (rootPath ());
143
+ std::cout << " [GUI] - Language setting: " << piSettings->language .toUtf8 ().constData () << std::endl;
144
+ std::cout << " [GUI] - System language: " << QLocale::system ().name ().toStdString () << std::endl;
145
+ this ->ui_language = sonicPii18n->determineUILanguage (piSettings->language );
146
+ std::cout << " [GUI] - Using language: " << ui_language.toUtf8 ().constData () << std::endl;
147
+ this ->i18n = sonicPii18n->loadTranslations (ui_language);
148
+
149
+ if (i18n) {
150
+ std::cout << " [GUI] - translations available " << std::endl;
151
+ } else {
152
+ std::cout << " [GUI] - translations unavailable (using EN)" << std::endl;
153
+ }
154
+
142
155
std::cout << " [GUI] - hiding main window" << std::endl;
143
156
hide ();
144
157
@@ -212,6 +225,11 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
212
225
toggleOSCServer (1 );
213
226
214
227
app.setActiveWindow (tabs->currentWidget ());
228
+
229
+ if (!i18n) {
230
+ showLanguageLoadingError ();
231
+ }
232
+
215
233
showWelcomeScreen ();
216
234
}
217
235
@@ -348,7 +366,8 @@ void MainWindow::setupWindowStructure()
348
366
prefsWidget->setAllowedAreas (Qt::RightDockWidgetArea);
349
367
prefsWidget->setFeatures (QDockWidget::DockWidgetClosable);
350
368
351
- settingsWidget = new SettingsWidget (m_spAPI->GetPort (SonicPiPortId::server_osc_cues), piSettings, this );
369
+ settingsWidget = new SettingsWidget (m_spAPI->GetPort (SonicPiPortId::server_osc_cues), i18n, piSettings, sonicPii18n, this );
370
+ connect (settingsWidget, SIGNAL (restartApp ()), this , SLOT (restartApp ()));
352
371
connect (settingsWidget, SIGNAL (volumeChanged (int )), this , SLOT (changeSystemPreAmp (int )));
353
372
connect (settingsWidget, SIGNAL (mixerSettingsChanged ()), this , SLOT (mixerSettingsChanged ()));
354
373
connect (settingsWidget, SIGNAL (midiSettingsChanged ()), this , SLOT (toggleMidi ()));
@@ -1216,6 +1235,18 @@ void MainWindow::startupError(QString msg)
1216
1235
// TODO: Add format error to API
1217
1236
}
1218
1237
1238
+ void MainWindow::showLanguageLoadingError () {
1239
+ QMessageBox msgBox (this );
1240
+ msgBox.setIcon (QMessageBox::Warning);
1241
+ msgBox.setText (QString (tr (" Failed to load translations for language: %1" )).arg (sonicPii18n->getNativeLanguageName (this ->ui_language )));
1242
+ msgBox.setInformativeText (tr (" Falling back to English. Sorry about this." ) + " \n " + tr (" Please consider reporting a bug at" ) + " \n http://github.com/sonic-pi-net/sonic-pi/issues" );
1243
+
1244
+ QPushButton *okButton = msgBox.addButton (tr (" OK" ), QMessageBox::AcceptRole);
1245
+ msgBox.setDefaultButton (okButton);
1246
+
1247
+ msgBox.exec ();
1248
+ }
1249
+
1219
1250
void MainWindow::replaceBuffer (QString id, QString content, int line, int index, int first_line)
1220
1251
{
1221
1252
SonicPiScintilla* ws = filenameToWorkspace (id.toStdString ());
@@ -2880,6 +2911,39 @@ void MainWindow::createToolBar()
2880
2911
viewMenu->addAction (focusHelpListingAct);
2881
2912
viewMenu->addAction (focusHelpDetailsAct);
2882
2913
viewMenu->addAction (focusErrorsAct);
2914
+
2915
+ languageMenu = menuBar ()->addMenu (tr (" Language" ));
2916
+ QStringList available_languages = sonicPii18n->getAvailableLanguages ();
2917
+
2918
+ langActionGroup = new QActionGroup (this );
2919
+ langActionGroup->setExclusionPolicy (QActionGroup::ExclusionPolicy::Exclusive);
2920
+
2921
+ QSignalMapper *signalMapper = new QSignalMapper (this );
2922
+
2923
+ for (size_t i = 0 ; i < available_languages.length (); i += 1 ) {
2924
+ bool is_current_lang = (available_languages[i] == piSettings->language );
2925
+
2926
+ QAction *langAct = new QAction (sonicPii18n->getNativeLanguageName (available_languages[i]), this );
2927
+ langAct->setCheckable (true );
2928
+ langAct->setChecked (is_current_lang);
2929
+
2930
+ connect (langAct, SIGNAL (triggered ()), signalMapper, SLOT (map ()));
2931
+ signalMapper->setMapping (langAct, i);
2932
+
2933
+ langActionGroup->addAction (langAct);
2934
+ languageMenu->addAction (langAct);
2935
+
2936
+ if (i == 0 ) { // add separator after System language
2937
+ languageMenu->addSeparator ();
2938
+ }
2939
+ }
2940
+
2941
+ connect (signalMapper, SIGNAL (mappedInt (int )), settingsWidget, SLOT (updateUILanguage (int )));
2942
+ connect (settingsWidget, SIGNAL (uiLanguageChanged (QString)), this , SLOT (updateSelectedUILanguageAction (QString)));
2943
+ }
2944
+
2945
+ void MainWindow::updateSelectedUILanguageAction (QString lang) {
2946
+ langActionGroup->actions ()[sonicPii18n->getAvailableLanguages ().indexOf (lang)]->setChecked (true );
2883
2947
}
2884
2948
2885
2949
QString MainWindow::readFile (QString name)
@@ -3074,6 +3138,7 @@ void MainWindow::readSettings()
3074
3138
std::cout << " [GUI] - reading settings" << std::endl;
3075
3139
3076
3140
// Read in preferences from previous session
3141
+ piSettings->language = gui_settings->value (" prefs/language" , " system_language" ).toString ();
3077
3142
piSettings->show_buttons = gui_settings->value (" prefs/show-buttons" , true ).toBool ();
3078
3143
piSettings->show_tabs = gui_settings->value (" prefs/show-tabs" , true ).toBool ();
3079
3144
piSettings->show_log = gui_settings->value (" prefs/show-log" , true ).toBool ();
@@ -3100,6 +3165,7 @@ void MainWindow::readSettings()
3100
3165
piSettings->show_scope_labels = gui_settings->value (" prefs/scope/show-labels" , false ).toBool ();
3101
3166
piSettings->show_cues = gui_settings->value (" prefs/show_cues" , true ).toBool ();
3102
3167
QString styleName = gui_settings->value (" prefs/theme" , " " ).toString ();
3168
+
3103
3169
piSettings->themeStyle = theme->themeNameToStyle (styleName);
3104
3170
piSettings->show_autocompletion = gui_settings->value (" prefs/show-autocompletion" , true ).toBool ();
3105
3171
piSettings->show_context = gui_settings->value (" prefs/show-context" , true ).toBool ();
@@ -3121,10 +3187,13 @@ void MainWindow::restoreScopeState(std::vector<QString> names)
3121
3187
void MainWindow::writeSettings ()
3122
3188
{
3123
3189
std::cout << " [GUI] - writing settings" << std::endl;
3190
+
3124
3191
gui_settings->setValue (" pos" , pos ());
3125
3192
gui_settings->setValue (" size" , size ());
3126
3193
gui_settings->setValue (" first_time" , 0 );
3127
3194
3195
+ gui_settings->setValue (" prefs/language" , piSettings->language );
3196
+
3128
3197
gui_settings->setValue (" prefs/midi-default-channel" , piSettings->midi_default_channel );
3129
3198
gui_settings->setValue (" prefs/midi-enable" , piSettings->midi_enabled );
3130
3199
gui_settings->setValue (" prefs/osc-public" , piSettings->osc_public );
@@ -3172,6 +3241,9 @@ void MainWindow::writeSettings()
3172
3241
gui_settings->setValue (" docsplitState" , docsplit->saveState ());
3173
3242
gui_settings->setValue (" windowState" , saveState ());
3174
3243
gui_settings->setValue (" windowGeom" , saveGeometry ());
3244
+
3245
+ // Force Qt to write the settings to the ini file
3246
+ gui_settings->sync ();
3175
3247
}
3176
3248
3177
3249
void MainWindow::loadFile (const QString& fileName, SonicPiScintilla*& text)
@@ -3261,6 +3333,31 @@ void MainWindow::onExitCleanup()
3261
3333
}
3262
3334
}
3263
3335
3336
+ void MainWindow::restartApp () {
3337
+ QApplication* app = dynamic_cast <QApplication*>(parent ());
3338
+ statusBar ()->showMessage (tr (" Restarting Sonic Pi..." ), 10000 );
3339
+
3340
+ // Save settings and perform some cleanup
3341
+ writeSettings ();
3342
+ onExitCleanup ();
3343
+ std::cout << " Performing application restart..." << std::endl;
3344
+
3345
+ // Create new process
3346
+ QStringList args = qApp->arguments ();
3347
+ args.removeFirst ();
3348
+ QProcess process;
3349
+ bool restart_success = process.startDetached (qApp->arguments ()[0 ], args);
3350
+ if (restart_success) {
3351
+ std::cout << " Successfully restarted sonic-pi" << std::endl;
3352
+ } else {
3353
+ std::cout << " Failed to restart sonic-pi" << std::endl;
3354
+ }
3355
+
3356
+ // Quit
3357
+ app->exit (0 );
3358
+ exit (0 );
3359
+ }
3360
+
3264
3361
void MainWindow::heartbeatOSC ()
3265
3362
{
3266
3363
// Message msg("/gui-heartbeat");
0 commit comments