Skip to content

Commit

Permalink
GUI - Add UI language option
Browse files Browse the repository at this point in the history
  • Loading branch information
SunderB committed Feb 13, 2021
1 parent a396163 commit c9df4aa
Show file tree
Hide file tree
Showing 13 changed files with 537 additions and 57 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ 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/help/*.html
app/gui/qt/utils/lang_list.h
app/gui/qt/help
app/gui/qt/help_files.qrc
app/gui/qt/lang/*.qm
app/gui/qt/qrc_help_files.cpp
Expand Down
4 changes: 4 additions & 0 deletions app/gui/qt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,16 @@ set(QT_SOURCES
set(SOURCES
${QTAPP_ROOT}/main.cpp
${QTAPP_ROOT}/utils/scintilla_api.cpp
${QTAPP_ROOT}/utils/sonic_pi_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/sonic_pi_i18n.h
${QTAPP_ROOT}/utils/ruby_help.h
${QTAPP_ROOT}/utils/lang_list.h
${QTAPP_ROOT}/utils/paths.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

}
105 changes: 77 additions & 28 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/sonic_pi_i18n.h"

#include "utils/borderlesslinksproxystyle.h"

// OSC stuff
Expand Down Expand Up @@ -79,6 +81,7 @@ using namespace oscpkt; // OSC specific stuff
#include "widgets/sonicpilog.h"

#include "utils/ruby_help.h"
#include "utils/paths.h"

#include "dpi.h"

Expand All @@ -105,9 +108,9 @@ using namespace SonicPi;
#endif

#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 @@ -118,9 +121,6 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)

this->piSettings = new SonicPiSettings();

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

#ifdef QT_OLD_API
sonicPiOSCServer = NULL;
#else
Expand Down Expand Up @@ -153,7 +153,6 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
version_num = 0;
latest_version_num = 0;
this->splash = splash;
this->i18n = i18n;
#ifdef QT_OLD_API
guiID = QUuid::createUuid().toString();
#endif
Expand All @@ -163,6 +162,10 @@ MainWindow::MainWindow(QApplication& app, bool i18n, QSplashScreen* splash)
initPaths();

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

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

//setup autocompletion
autocomplete->loadSamples(sample_path);
Expand Down Expand Up @@ -375,9 +378,9 @@ bool MainWindow::initAndCheckPorts()
}
#endif

void MainWindow::initPaths()
{
QString root_path = rootPath();

void MainWindow::initPaths() {
QString root_path = ROOT_PATH;

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

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

settingsWidget = new SettingsWidget(server_osc_cues_port, piSettings, this);
settingsWidget = new SettingsWidget(server_osc_cues_port, i18n, piSettings, sonicPii18n, this);
connect(settingsWidget, SIGNAL(uiLanguageChanged(QString)), this, SLOT(changeUILanguage(QString)));
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 @@ -1279,20 +1283,6 @@ void MainWindow::toggleComment(SonicPiScintilla* ws)
sendOSC(msg);
}

QString MainWindow::rootPath()
{
// diversity is the spice of life
#if defined(Q_OS_MAC)
return QCoreApplication::applicationDirPath() + "/../Resources";
#elif defined(Q_OS_WIN)
// CMake builds, the exe is in build/debug/sonic-pi, etc.
// We should pass this to the build instead of wiring it up this way!
return QCoreApplication::applicationDirPath() + "/../../../../..";
#else
// On linux, CMake builds app into the build folder
return QCoreApplication::applicationDirPath() + "/../../../..";
#endif
}

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

// TODO: Implement real-time language switching
void MainWindow::changeUILanguage(QString lang) {
if (lang != piSettings->language) {
std::cout << "Current language: " << piSettings->language.toUtf8().constData() << std::endl;
std::cout << "New language selected: " << lang.toUtf8().constData() << std::endl;
QString old_lang = sonicPii18n->getNativeLanguageName(piSettings->language);
QString new_lang = sonicPii18n->getNativeLanguageName(lang);

// Load new language
//QString language = sonicPii18n->determineUILanguage(lang);
//sonicPii18n->loadTranslations(language);
//QString title_new = tr("Updated the UI language from %s to %s").arg();

QMessageBox msgBox(this);
msgBox.setText(QString(tr("You've selected a new language: %1")).arg(new_lang));
msgBox.setInformativeText(tr("Do you want to apply this language?\nApplying the new language will restart Sonic Pi."));
QPushButton *restartButton = msgBox.addButton(tr("Apply and Restart"), QMessageBox::ActionRole);
QPushButton *dismissButton = msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole);
msgBox.setDefaultButton(restartButton);
msgBox.setIcon(QMessageBox::Information);
msgBox.exec();

if (msgBox.clickedButton() == (QAbstractButton*)restartButton) {
piSettings->language = lang;
writeSettings();
restartApp();
//statusBar()->showMessage(tr("Updated UI language setting, please restart Sonic Pi to apply it"), 2000);
} else if (msgBox.clickedButton() == (QAbstractButton*)dismissButton) {
// Don't apply the new language settings
settingsWidget->updateSelectedUILanguage(piSettings->language);
}

// Load previously set language
//sonicPii18n->loadTranslations(ui_language);
}
}

void MainWindow::changeScopeKindVisibility(QString name)
{
foreach (QAction* action, scopeKindVisibilityMenu->actions())
Expand Down Expand Up @@ -3500,6 +3527,8 @@ void MainWindow::readSettings()
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "sonic-pi.net", "gui-settings");

// Read in preferences from previous session
piSettings->language = settings.value("prefs/language", "system_locale").toString();

piSettings->show_buttons = settings.value("prefs/show-buttons", true).toBool();
piSettings->show_tabs = settings.value("prefs/show-tabs", true).toBool();
piSettings->show_log = settings.value("prefs/show-log", true).toBool();
Expand Down Expand Up @@ -3549,6 +3578,7 @@ void MainWindow::writeSettings()
{
std::cout << "[GUI] - writing settings" << std::endl;
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "sonic-pi.net", "gui-settings");
settings.setValue("prefs/language", piSettings->language);
settings.setValue("pos", pos());
settings.setValue("size", size());
settings.setValue("first_time", 0);
Expand Down Expand Up @@ -3732,6 +3762,24 @@ void MainWindow::onExitCleanup()
#endif
}

void MainWindow::restartApp() {
QApplication* app = dynamic_cast<QApplication*>(parent());
statusBar()->showMessage(tr("Restarting Sonic Pi..."), 10000);
// Save settings and perform some cleanup
writeSettings();
onExitCleanup();
sleep(1);
std::cout << "Performing application restart... please wait..." << std::endl;
//this->hide(); // So it doesn't look like the app's frozen or crashed
sleep(4); // Allow cleanup to complete
// Create new process
QProcess process;
process.startDetached("sonic-pi", QStringList());
// Quit
app->exit(0);
exit(0);
}

#ifdef QT_OLD_API
void MainWindow::cleanupRunningProcesses()
{
Expand Down Expand Up @@ -4305,8 +4353,9 @@ SonicPiLog* MainWindow::GetIncomingPane() const
{
return incomingPane;
}

SonicPiTheme* MainWindow::GetTheme() const
{
return theme;
}

Loading

0 comments on commit c9df4aa

Please sign in to comment.