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