Skip to content

Commit

Permalink
Merge pull request #2604 from SunderB/patch-localeOption
Browse files Browse the repository at this point in the history
GUI: Add UI language option
  • Loading branch information
samaaron committed May 24, 2021
2 parents a7612c8 + 767e3aa commit ef24bc7
Show file tree
Hide file tree
Showing 20 changed files with 1,075 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ app/gui/qt/moc_mainwindow.cpp
app/gui/qt/moc_sonicpiudpserver.cpp
app/gui/qt/qrc_SonicPi.cpp
app/gui/qt/utils/ruby_help.h
app/gui/qt/utils/lang_list.h
app/gui/qt/help/*.html
app/gui/qt/help_files.qrc
app/gui/qt/lang/*.qm
Expand Down
3 changes: 3 additions & 0 deletions app/gui/qt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,15 @@ set(QT_SOURCES
set(SOURCES
${QTAPP_ROOT}/main.cpp
${QTAPP_ROOT}/utils/scintilla_api.cpp
${QTAPP_ROOT}/utils/sonicpi_i18n.cpp
${QTAPP_ROOT}/widgets/sonicpilog.cpp
${QTAPP_ROOT}/widgets/sonicpilog.h
${QTAPP_ROOT}/widgets/sonicpicontext.cpp
${QTAPP_ROOT}/widgets/sonicpicontext.h
${QTAPP_ROOT}/utils/scintilla_api.h
${QTAPP_ROOT}/utils/sonicpi_i18n.h
${QTAPP_ROOT}/utils/ruby_help.h
${QTAPP_ROOT}/utils/lang_list.h
${QTAPP_ROOT}/model/settings.h
)

Expand Down
22 changes: 6 additions & 16 deletions app/gui/qt/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
// notice is included.
//++

#include <iostream>

#include <QApplication>
#include <QSplashScreen>
#include <QPixmap>
#include <QBitmap>
#include <QLabel>
#include <QTranslator>
#include <QLibraryInfo>

#include "mainwindow.h"
Expand All @@ -35,7 +36,7 @@

int main(int argc, char *argv[])
{

std::cout << "Starting Sonic Pi..." << std::endl;
#ifndef Q_OS_MAC
Q_INIT_RESOURCE(SonicPi);
#endif
Expand All @@ -49,16 +50,6 @@ int main(int argc, char *argv[])

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

QString systemLocale = QLocale::system().uiLanguages()[0].replace("-", "_");

QTranslator qtTranslator;
qtTranslator.load("qt_" + systemLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);

QTranslator translator;
bool i18n = translator.load(QLatin1String("sonic-pi_") + systemLocale, QLatin1String(":/lang")) || systemLocale.startsWith("en") || systemLocale == "C";
app.installTranslator(&translator);

app.setApplicationName(QObject::tr("Sonic Pi"));
app.setStyle("gtk");

Expand All @@ -75,7 +66,7 @@ int main(int argc, char *argv[])
splash->show();
splash->repaint();
app.processEvents();
MainWindow mainWin(app, i18n, splash);
MainWindow mainWin(app, splash);

return app.exec();
#elif _WIN32
Expand Down Expand Up @@ -109,7 +100,7 @@ int main(int argc, char *argv[])
splash->show();
splash->repaint();
app.processEvents();
MainWindow mainWin(app, i18n, splash);
MainWindow mainWin(app, splash);

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

MainWindow mainWin(app, i18n, splashWindow);
MainWindow mainWin(app, splashWindow);
return app.exec();

#endif

}
107 changes: 102 additions & 5 deletions app/gui/qt/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
#include "widgets/sonicpilexer.h"
#include "widgets/sonicpiscintilla.h"

#include "utils/sonicpi_i18n.h"

#include "utils/borderlesslinksproxystyle.h"
#include "visualizer/scope_window.h"

Expand Down Expand Up @@ -89,9 +91,9 @@ using namespace std::chrono;
using namespace SonicPi;

#ifdef Q_OS_MAC
MainWindow::MainWindow(QApplication& app, bool i18n, QMainWindow* splash)
MainWindow::MainWindow(QApplication& app, QMainWindow* splash)
#else
MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
MainWindow::MainWindow(QApplication& app, QSplashScreen* splash)
#endif
{
app.installEventFilter(this);
Expand All @@ -103,7 +105,6 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
this->piSettings = new SonicPiSettings();

this->splash = splash;
this->i18n = i18n;

// API and Client
m_spClient = std::make_shared<QtAPIClient>(this);
Expand All @@ -126,7 +127,6 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
version_num = 0;
latest_version_num = 0;
this->splash = splash;
this->i18n = i18n;
QString settings_path = sonicPiConfigPath() + QDir::separator() + "gui-settings.ini";

gui_settings = new QSettings(settings_path, QSettings::IniFormat);
Expand All @@ -139,6 +139,19 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
m_spAPI->Init(rootPath().toStdString());
guiID = QString::fromStdString(m_spAPI->GetGuid());

this->sonicPii18n = new SonicPii18n(rootPath());
std::cout << "[GUI] - Language setting: " << piSettings->language.toUtf8().constData() << std::endl;
std::cout << "[GUI] - System language: " << QLocale::system().name().toStdString() << std::endl;
this->ui_language = sonicPii18n->determineUILanguage(piSettings->language);
std::cout << "[GUI] - Using language: " << ui_language.toUtf8().constData() << std::endl;
this->i18n = sonicPii18n->loadTranslations(ui_language);

if(i18n) {
std::cout << "[GUI] - translations available " << std::endl;
} else {
std::cout << "[GUI] - translations unavailable (using EN)" << std::endl;
}

std::cout << "[GUI] - hiding main window" << std::endl;
hide();

Expand Down Expand Up @@ -212,6 +225,11 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
toggleOSCServer(1);

app.setActiveWindow(tabs->currentWidget());

if (!i18n) {
showLanguageLoadingError();
}

showWelcomeScreen();
}

Expand Down Expand Up @@ -348,7 +366,8 @@ void MainWindow::setupWindowStructure()
prefsWidget->setAllowedAreas(Qt::RightDockWidgetArea);
prefsWidget->setFeatures(QDockWidget::DockWidgetClosable);

settingsWidget = new SettingsWidget(m_spAPI->GetPort(SonicPiPortId::server_osc_cues), piSettings, this);
settingsWidget = new SettingsWidget(m_spAPI->GetPort(SonicPiPortId::server_osc_cues), i18n, piSettings, sonicPii18n, this);
connect(settingsWidget, SIGNAL(restartApp()), this, SLOT(restartApp()));
connect(settingsWidget, SIGNAL(volumeChanged(int)), this, SLOT(changeSystemPreAmp(int)));
connect(settingsWidget, SIGNAL(mixerSettingsChanged()), this, SLOT(mixerSettingsChanged()));
connect(settingsWidget, SIGNAL(midiSettingsChanged()), this, SLOT(toggleMidi()));
Expand Down Expand Up @@ -1216,6 +1235,18 @@ void MainWindow::startupError(QString msg)
// TODO: Add format error to API
}

void MainWindow::showLanguageLoadingError() {
QMessageBox msgBox(this);
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText(QString(tr("Failed to load translations for language: %1")).arg(sonicPii18n->getNativeLanguageName(this->ui_language)));
msgBox.setInformativeText(tr("Falling back to English. Sorry about this.") + "\n" + tr("Please consider reporting a bug at") + "\nhttp://github.com/sonic-pi-net/sonic-pi/issues");

QPushButton *okButton = msgBox.addButton(tr("OK"), QMessageBox::AcceptRole);
msgBox.setDefaultButton(okButton);

msgBox.exec();
}

void MainWindow::replaceBuffer(QString id, QString content, int line, int index, int first_line)
{
SonicPiScintilla* ws = filenameToWorkspace(id.toStdString());
Expand Down Expand Up @@ -2880,6 +2911,39 @@ void MainWindow::createToolBar()
viewMenu->addAction(focusHelpListingAct);
viewMenu->addAction(focusHelpDetailsAct);
viewMenu->addAction(focusErrorsAct);

languageMenu = menuBar()->addMenu(tr("Language"));
QStringList available_languages = sonicPii18n->getAvailableLanguages();

langActionGroup = new QActionGroup(this);
langActionGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive);

QSignalMapper *signalMapper = new QSignalMapper(this);

for (size_t i = 0; i < available_languages.length(); i += 1) {
bool is_current_lang = (available_languages[i] == piSettings->language);

QAction *langAct = new QAction(sonicPii18n->getNativeLanguageName(available_languages[i]), this);
langAct->setCheckable(true);
langAct->setChecked(is_current_lang);

connect(langAct, SIGNAL(triggered()), signalMapper, SLOT(map()));
signalMapper->setMapping(langAct, i);

langActionGroup->addAction(langAct);
languageMenu->addAction(langAct);

if (i == 0) { // add separator after System language
languageMenu->addSeparator();
}
}

connect(signalMapper, SIGNAL(mappedInt(int)), settingsWidget, SLOT(updateUILanguage(int)));
connect(settingsWidget, SIGNAL(uiLanguageChanged(QString)), this, SLOT(updateSelectedUILanguageAction(QString)));
}

void MainWindow::updateSelectedUILanguageAction(QString lang) {
langActionGroup->actions()[sonicPii18n->getAvailableLanguages().indexOf(lang)]->setChecked(true);
}

QString MainWindow::readFile(QString name)
Expand Down Expand Up @@ -3074,6 +3138,7 @@ void MainWindow::readSettings()
std::cout << "[GUI] - reading settings" << std::endl;

// Read in preferences from previous session
piSettings->language = gui_settings->value("prefs/language", "system_language").toString();
piSettings->show_buttons = gui_settings->value("prefs/show-buttons", true).toBool();
piSettings->show_tabs = gui_settings->value("prefs/show-tabs", true).toBool();
piSettings->show_log = gui_settings->value("prefs/show-log", true).toBool();
Expand All @@ -3100,6 +3165,7 @@ void MainWindow::readSettings()
piSettings->show_scope_labels = gui_settings->value("prefs/scope/show-labels", false).toBool();
piSettings->show_cues = gui_settings->value("prefs/show_cues", true).toBool();
QString styleName = gui_settings->value("prefs/theme", "").toString();

piSettings->themeStyle = theme->themeNameToStyle(styleName);
piSettings->show_autocompletion = gui_settings->value("prefs/show-autocompletion", true).toBool();
piSettings->show_context = gui_settings->value("prefs/show-context", true).toBool();
Expand All @@ -3121,10 +3187,13 @@ void MainWindow::restoreScopeState(std::vector<QString> names)
void MainWindow::writeSettings()
{
std::cout << "[GUI] - writing settings" << std::endl;

gui_settings->setValue("pos", pos());
gui_settings->setValue("size", size());
gui_settings->setValue("first_time", 0);

gui_settings->setValue("prefs/language", piSettings->language);

gui_settings->setValue("prefs/midi-default-channel", piSettings->midi_default_channel);
gui_settings->setValue("prefs/midi-enable", piSettings->midi_enabled);
gui_settings->setValue("prefs/osc-public", piSettings->osc_public);
Expand Down Expand Up @@ -3172,6 +3241,9 @@ void MainWindow::writeSettings()
gui_settings->setValue("docsplitState", docsplit->saveState());
gui_settings->setValue("windowState", saveState());
gui_settings->setValue("windowGeom", saveGeometry());

// Force Qt to write the settings to the ini file
gui_settings->sync();
}

void MainWindow::loadFile(const QString& fileName, SonicPiScintilla*& text)
Expand Down Expand Up @@ -3261,6 +3333,31 @@ void MainWindow::onExitCleanup()
}
}

void MainWindow::restartApp() {
QApplication* app = dynamic_cast<QApplication*>(parent());
statusBar()->showMessage(tr("Restarting Sonic Pi..."), 10000);

// Save settings and perform some cleanup
writeSettings();
onExitCleanup();
std::cout << "Performing application restart..." << std::endl;

// Create new process
QStringList args = qApp->arguments();
args.removeFirst();
QProcess process;
bool restart_success = process.startDetached(qApp->arguments()[0], args);
if (restart_success) {
std::cout << "Successfully restarted sonic-pi" << std::endl;
} else {
std::cout << "Failed to restart sonic-pi" << std::endl;
}

// Quit
app->exit(0);
exit(0);
}

void MainWindow::heartbeatOSC()
{
// Message msg("/gui-heartbeat");
Expand Down
17 changes: 14 additions & 3 deletions app/gui/qt/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <vector>
#include <memory>


#include <QDate>
#include <QMainWindow>
#include <QFuture>
Expand All @@ -34,6 +35,7 @@
#include "config.h"

class QAction;
class QActionGroup;
class QMenu;
class QToolBar;
class QLineEdit;
Expand Down Expand Up @@ -67,6 +69,7 @@ class InfoWidget;
class SettingsWidget;
class Scope;
class ScintillaAPI;
class SonicPii18n;
class SonicPiLog;
class SonicPiScintilla;
class SonicPiTheme;
Expand All @@ -91,9 +94,9 @@ class MainWindow : public QMainWindow

public:
#if defined(Q_OS_MAC)
MainWindow(QApplication &ref, bool i18n, QMainWindow* splash);
MainWindow(QApplication &ref, QMainWindow* splash);
#else
MainWindow(QApplication &ref, bool i18n, QSplashScreen* splash);
MainWindow(QApplication &ref, QSplashScreen* splash);
#endif

SonicPiLog* GetOutputPane() const;
Expand All @@ -118,6 +121,8 @@ class MainWindow : public QMainWindow

bool loaded_workspaces;
QString hash_salt;
QString ui_language;


protected:
void closeEvent(QCloseEvent *event);
Expand All @@ -132,6 +137,7 @@ class MainWindow : public QMainWindow

private slots:

void updateSelectedUILanguageAction(QString lang);
void updateContext(int line, int index);
void updateContextWithCurrentWs();
void docLinkClicked(const QUrl &url);
Expand Down Expand Up @@ -178,6 +184,7 @@ class MainWindow : public QMainWindow
void help();
void toggleHelpIcon();
void onExitCleanup();
void restartApp();
void toggleRecording();
void toggleRecordingOnIcon();
void changeSystemPreAmp(int val, int silent=0);
Expand Down Expand Up @@ -229,6 +236,7 @@ class MainWindow : public QMainWindow
void splashClose();
void setMessageBoxStyle();
void startupError(QString msg);
void showLanguageLoadingError();
void tabNext();
void tabPrev();
void tabGoto(int index);
Expand Down Expand Up @@ -327,11 +335,13 @@ class MainWindow : public QMainWindow
QString rootPath();

void addUniversalCopyShortcuts(QTextEdit *te);
void updateTranslatedUIText();

QMenu *liveMenu, *codeMenu, *audioMenu, *displayMenu, *viewMenu, *ioMenu, *ioMidiInMenu, *ioMidiOutMenu, *ioMidiOutChannelMenu, *localIpAddressesMenu, *themeMenu, *scopeKindVisibilityMenu;
QMenu *liveMenu, *codeMenu, *audioMenu, *displayMenu, *viewMenu, *ioMenu, *ioMidiInMenu, *ioMidiOutMenu, *ioMidiOutChannelMenu, *localIpAddressesMenu, *themeMenu, *scopeKindVisibilityMenu, *languageMenu;

QSettings *gui_settings;
SonicPiSettings *piSettings;
SonicPii18n *sonicPii18n;

bool focusMode;
QCheckBox *startup_error_reported;
Expand Down Expand Up @@ -380,6 +390,7 @@ class MainWindow : public QMainWindow

QAction *exitAct, *runAct, *stopAct, *saveAsAct, *loadFileAct, *recAct, *textAlignAct, *textIncAct, *textDecAct, *scopeAct, *infoAct, *helpAct, *prefsAct, *focusEditorAct, *focusLogsAct, *focusContextAct, *focusCuesAct, *focusPreferencesAct, *focusHelpListingAct, *focusHelpDetailsAct, *focusErrorsAct, *showLineNumbersAct, *showAutoCompletionAct, *showContextAct, *audioSafeAct, *audioTimingGuaranteesAct, *enableExternalSynthsAct, *mixerInvertStereoAct, *mixerForceMonoAct, *midiEnabledAct, *enableOSCServerAct, *allowRemoteOSCAct, *showLogAct, *showCuesAct, *logAutoScrollAct, *logCuesAct, *logSynthsAct, *clearOutputOnRunAct, *autoIndentOnRunAct, *showButtonsAct, *showTabsAct, *fullScreenAct, *lightThemeAct, *darkThemeAct, *proLightThemeAct, *proDarkThemeAct, *highContrastThemeAct, *showScopeLabelsAct;
QShortcut *runSc, *stopSc, *saveAsSc, *loadFileSc, *recSc, *textAlignSc, *textIncSc, *textDecSc, *scopeSc, *infoSc, *helpSc, *prefsSc, *focusEditorSc, *focusLogsSc, *focusContextSc, *focusCuesSc, *focusPreferencesSc, *focusHelpListingSc, *focusHelpDetailsSc, *focusErrorsSc;
QActionGroup *langActionGroup;

SettingsWidget *settingsWidget;

Expand Down
Loading

0 comments on commit ef24bc7

Please sign in to comment.