diff --git a/src/qml/Dialogs/SettingsDialog.qml b/src/qml/Dialogs/SettingsDialog.qml new file mode 100644 index 0000000..5360d34 --- /dev/null +++ b/src/qml/Dialogs/SettingsDialog.qml @@ -0,0 +1,161 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.3 +import QtQuick.Dialogs 1.3 +import QtQuick.Layouts 1.14 +import QtQuick.Window 2.2 +import player 1.0 + +Dialog { + id: settingsDialog + title: translate.getTranslation("SETTINGS", i18n.language) + height: Math.max(480, childrenRect.height) + width: 720 + modality: Qt.NonModal + ScrollView { + id: content + height: parent.height + width: parent.width + clip: true + ScrollBar.vertical.policy: ScrollBar.AlwaysOn + Item { + id: settingsContent + implicitHeight: childrenRect.height + implicitWidth: childrenRect.width + ColumnLayout { + Text { + height: 30 + text: translate.getTranslation("LANGUAGE", i18n.language) + verticalAlignment: Text.AlignVCenter + } + LanguageSettings { Layout.leftMargin: 30 } + Text { + height: 30 + text: translate.getTranslation("APPEARANCE", i18n.language) + verticalAlignment: Text.AlignVCenter + } + CheckBox { + checked: appearance.titleOnlyOnFullscreen + onClicked: appearance.titleOnlyOnFullscreen = !appearance.titleOnlyOnFullscreen + text: translate.getTranslation("TITLE_ONLY_ON_FULLSCREEN", i18n.language) + Layout.leftMargin: 30 + } + CheckBox { + checked: appearance.clickToPause + onClicked: appearance.clickToPause = !appearance.clickToPause + text: translate.getTranslation("CLICK_TO_PAUSE", i18n.language) + Layout.leftMargin: 30 + } + CheckBox { + checked: appearance.doubleTapToSeek + onClicked: appearance.doubleTapToSeek = !appearance.doubleTapToSeek + text: translate.getTranslation("DOUBLE_TAP_TO_SEEK", i18n.language) + Layout.leftMargin: 30 + } + Item { + Layout.leftMargin: 30 + Layout.bottomMargin: 10 + height: 30 + Text { + id: seekByLabel + height: 30 + text: translate.getTranslation("DOUBLE_TAP_TO_SEEK_BY", i18n.language) + verticalAlignment: Text.AlignVCenter + } + TextField { + id: seekBy + anchors.left: seekByLabel.right + anchors.leftMargin: 10 + validator: IntValidator {} + inputMethodHints: Qt.ImhFormattedNumbersOnly + text: appearance.doubleTapToSeekBy + function setSeekBy() { + appearance.doubleTapToSeekBy = parseInt(seekBy.text) + } + onEditingFinished: setSeekBy() + } + } + Item { + height: 30 + Layout.bottomMargin: 10 + Layout.leftMargin: 30 + Text { + id: fontLabel + height: 30 + text: translate.getTranslation("FONT", i18n.language) + verticalAlignment: Text.AlignVCenter + } + TextField { + id: fontInput + anchors.left: fontLabel.right + anchors.leftMargin: 10 + text: appearance.fontName + function setFont() { + appearance.fontName = fontInput.text + } + onEditingFinished: setFont() + } + } + Item { + Layout.leftMargin: 30 + Layout.bottomMargin: 10 + height: 30 + Text { + id: subtitlesFontSizeLabel + height: 30 + text: translate.getTranslation("SUBTITLES_FONT_SIZE", i18n.language) + verticalAlignment: Text.AlignVCenter + } + TextField { + id: subtitlesFontSizeInput + anchors.left: subtitlesFontSizeLabel.right + anchors.leftMargin: 10 + validator: IntValidator {} + inputMethodHints: Qt.ImhFormattedNumbersOnly + text: appearance.subtitlesFontSize + function setSubtitlesFontSize() { + appearance.subtitlesFontSize = parseInt(subtitlesFontSizeInput.text) + } + onEditingFinished: setSubtitlesFontSize() + } + } + Item { + Layout.leftMargin: 30 + Layout.bottomMargin: 10 + height: 30 + Text { + id: uiFadeTimeLabel + height: 30 + text: translate.getTranslation("UI_FADE_TIME", i18n.language) + verticalAlignment: Text.AlignVCenter + } + TextField { + id: uiFadeTimeInput + anchors.left: uiFadeTimeLabel.right + anchors.leftMargin: 10 + validator: IntValidator { bottom: 0 } + inputMethodHints: Qt.ImhFormattedNumbersOnly + text: appearance.uiFadeTimer + function setUIFadeTime() { + appearance.uiFadeTimer = parseInt(uiFadeTimeInput.text) + } + onEditingFinished: setUIFadeTime() + } + } + } + } + + } + + Component.onCompleted: { + settingsDialog.open() + } + Connections { + target: settingsDialog + onAccepted: { + seekBy.setSeekBy() + fontInput.setFont() + subtitlesFontSizeInput.setSubtitlesFontSize() + uiFadeTimeInput.setUIFadeTime() + } + } +} diff --git a/src/qml/Dialogs/SettingsItems/LanguageSettings.qml b/src/qml/Dialogs/SettingsItems/LanguageSettings.qml new file mode 100644 index 0000000..a187240 --- /dev/null +++ b/src/qml/Dialogs/SettingsItems/LanguageSettings.qml @@ -0,0 +1,30 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.3 +import "translations.js" as Translations + +ComboBox { + id: languageSelector + height: 30 + editable: false + pressed: true + model: Object.values(Translations.languages) + delegate: ItemDelegate { + height: 25 + width: languageSelector.width + contentItem: Text { + text: modelData + color: "#21be2b" + font: languageSelector.font + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + highlighted: languageSelector.highlightedIndex === index + } + onActivated: { + console.warn(currentText) + i18n.language = Object.keys(Translations.languages).find(key => Translations.languages[key] === currentText) + } + Component.onCompleted: { + currentIndex = languageSelector.indexOfValue(Translations.languages[i18n.language]) + } +} diff --git a/src/qml/MainMenu.qml b/src/qml/MainMenu.qml index 8218581..db49a6a 100644 --- a/src/qml/MainMenu.qml +++ b/src/qml/MainMenu.qml @@ -116,6 +116,10 @@ MenuBar { id: playlistDialog } + SettingsDialog { + id: settingsDialog + } + delegate: MenuBarItem { id: menuBarItem @@ -469,6 +473,13 @@ MenuBar { } } Action { + text: translate.getTranslation("SETTINGS", i18n.language) + onTriggered: { + settingsDialog.open() + } + } + Action { + // Pretty sure for legal reasons this is needed unless I buy a Qt License text: translate.getTranslation("ABOUT_QT", i18n.language) onTriggered: { utils.launchAboutQt() diff --git a/src/qml/Utils/Translator.qml b/src/qml/Utils/Translator.qml index 8e0d061..bb15918 100644 --- a/src/qml/Utils/Translator.qml +++ b/src/qml/Utils/Translator.qml @@ -9,6 +9,9 @@ Item { return "TranslationNotFound" } var text = String(Translations.translations[i18n.language][code]) + if (text == "undefined"){ + console.warn(code, "missing for language", language) + } var args = Array.prototype.slice.call(arguments, 1) var i = 0 return text.replace(/%s/g, function () { diff --git a/src/qml/Utils/translations.js b/src/qml/Utils/translations.js index 8f11f68..e3902b0 100644 --- a/src/qml/Utils/translations.js +++ b/src/qml/Utils/translations.js @@ -1,13 +1,19 @@ +var languages = { + "english": "English", + "spanish": "Español", + "german": "Deutsch", + "french": "Française", + "italian": "Italiano", + "russian": "Русский", + "norwegian": "Norwegian", +} + var translations = { english: { - SAVE_SCREENSHOT: "Save screenshot to", OPEN_FILE: "Open file", URL_FILE_PATH: "URL / File Path", FILE_MENU: "File", OPEN_URL: "Open URL", - SCREENSHOT: "Screenshot", - SCREENSHOT_WITHOUT_SUBTITLES: "Screenshot w/o Subtitles", - FULL_SCREENSHOT: "Full Screenshot", EXIT: "Exit", PLAYBACK: "Playback", PLAY_PAUSE: "Play/Pause", @@ -42,19 +48,24 @@ var translations = { TOGGLE_ALWAYS_ON_TOP: "Toggle Always On Top", DISABLE_TRACK: "Disable Track", AUDIO_DEVICES: "Audio Devices", - UPDATE: "Update", PLAYLIST_MENU: "Playlist Menu", - THEME: "Theme" + THEME: "Theme", + SETTINGS: "Settings", + LANGUAGE: "Language", + APPEARANCE: "Appearance", + TITLE_ONLY_ON_FULLSCREEN: "Show title when only in fullscreen", + CLICK_TO_PAUSE: "Tap/Click to pause", + DOUBLE_TAP_TO_SEEK: "Double Tap/Click to seek", + DOUBLE_TAP_TO_SEEK_BY: "Seek by", + FONT: "Font", + SUBTITLES_FONT_SIZE: "Subtitles Font Size", + UI_FADE_TIME: "UI Fade Time (ms)" }, spanish: { - SAVE_SCREENSHOT: "Guardar captura en", OPEN_FILE: "Abrir archivo", URL_FILE_PATH: "URL / Dirección de archivo", FILE_MENU: "Archivo", OPEN_URL: "Abrir URL", - SCREENSHOT: "Captura", - SCREENSHOT_WITHOUT_SUBTITLES: "Captura sin subtítulos", - FULL_SCREENSHOT: "Captura a pantalla completa", EXIT: "Salir", PLAYBACK: "Volver a reproducir", PLAY_PAUSE: "Reproducir/Pausar", @@ -90,14 +101,10 @@ var translations = { DISABLE_TRACK: "Eliminar pista" }, german: { - SAVE_SCREENSHOT: "Bildschirmfoto speichern nach", OPEN_FILE: "Datei öffnen", URL_FILE_PATH: "URL / Datei Pfad", FILE_MENU: "Datei", OPEN_URL: "URL öffnen", - SCREENSHOT: "Bildschirmfoto", - SCREENSHOT_WITHOUT_SUBTITLES: "Bildschirmfoto ohne Untertitel", - FULL_SCREENSHOT: "Voll Bildschirmfoto", EXIT: "Beenden", PLAYBACK: "Wiedergabe", PLAY_PAUSE: "Wiedergabe/Pause", @@ -133,14 +140,10 @@ var translations = { DISABLE_TRACK: "Spur deaktivieren" }, french: { - SAVE_SCREENSHOT: "Enregistrer la capture d'écran dans", OPEN_FILE: "Ouvrir le fichier", URL_FILE_PATH: "URL / Chemin du fichier", FILE_MENU: "Fichier", OPEN_URL: "Ouvrir l'URL", - SCREENSHOT: "Captude d'écran", - SCREENSHOT_WITHOUT_SUBTITLES: "Capture d'écran sans sous-titres", - FULL_SCREENSHOT: "Capture d'écran complète", EXIT: "Fermer", PLAYBACK: "Lecture", PLAY_PAUSE: "Jouer/Mettre en pause", @@ -174,17 +177,15 @@ var translations = { TITLE: "Titre", TOGGLE_ALWAYS_ON_TOP: "Toujours au-dessu", DISABLE_TRACK: "Désactiver la piste", - AUDIO_DEVICES: "Périphériques audio" + AUDIO_DEVICES: "Périphériques audio", + PLAYLIST_MENU: "Menu de la liste de lecture", + THEME: "Thème" }, italian: { - SAVE_SCREENSHOT: "Salva schermata", OPEN_FILE: "Apri file", URL_FILE_PATH: "URL / Percorso file", FILE_MENU: "File", OPEN_URL: "Apri URL", - SCREENSHOT: "Cattura schermata", - SCREENSHOT_WITHOUT_SUBTITLES: "Cattura schermata senza Sottotitoli", - FULL_SCREENSHOT: "Cattura schermata completa", EXIT: "Esci", PLAYBACK: "Riproduzione", PLAY_PAUSE: "Play/Pausa", @@ -221,14 +222,10 @@ var translations = { AUDIO_DEVICES: "Dispositivi audio" }, russian: { - SAVE_SCREENSHOT: "Сохранить снимок экрана...", OPEN_FILE: "Открыть...", URL_FILE_PATH: "Ввести URL / путь к файлу...", FILE_MENU: "Файл", OPEN_URL: "Открыть URL...", - SCREENSHOT: "Сделать снимок экрана...", - SCREENSHOT_WITHOUT_SUBTITLES: "Сделать снимок экрана без субтитров...", - FULL_SCREENSHOT: "Сделать полный скриншот окна", EXIT: "Выход", PLAYBACK: "Воспроизведение", PLAY_PAUSE: "Воспроизвести/Остановить", @@ -259,17 +256,14 @@ var translations = { TOGGLE_NYAN_CAT: "Нян-кот", ABOUT: "О программе", ABOUT_QT: "О используемой версии Qt...", - TITLE: "Заголовок" + TITLE: "Заголовок", + SETTINGS: "Настройки" }, norwegian: { - SAVE_SCREENSHOT: "Lagre Skjermdump Til", OPEN_FILE: "Åpne Fil", URL_FILE_PATH: "Lenke / Filbane", FILE_MENU: "Fil", OPEN_URL: "Åpne lenke", - SCREENSHOT: "Skjermdump", - SCREENSHOT_WITHOUT_SUBTITLES: "Skjermdump Uten Undertekster", - FULL_SCREENSHOT: "Full Skjermdump", EXIT: "Avslutt", PLAYBACK: "Avspilling", PLAY_PAUSE: "Spill/Pause", diff --git a/src/qml/main.qml b/src/qml/main.qml index af97bdf..c2eafa6 100644 --- a/src/qml/main.qml +++ b/src/qml/main.qml @@ -8,8 +8,8 @@ Window { id: mainWindow title: "KittehPlayer" visible: true - width: 720 - height: 480 + width: Math.min(720, Screen.width) + height: Math.min(480, Screen.height) property int virtualHeight: Screen.height * appearance.scaleFactor property int virtualWidth: Screen.width * appearance.scaleFactor property bool onTop: false diff --git a/src/qml/qml.qrc b/src/qml/qml.qrc index 63a38fd..abcc0b4 100644 --- a/src/qml/qml.qrc +++ b/src/qml/qml.qrc @@ -33,6 +33,8 @@ Items/ThumbnailProcess.qml Items/TitleProcess.qml Items/CustomMenuItem.qml + Dialogs/SettingsDialog.qml + Dialogs/SettingsItems/LanguageSettings.qml Dialogs/PlaylistDialog.qml icons/YouTube/play.svg icons/YouTube/pause.svg diff --git a/version b/version index d00491f..d8263ee 100644 --- a/version +++ b/version @@ -1 +1 @@ -1 +2 \ No newline at end of file