Warning, /multimedia/kid3/src/qml/app/SettingsPage.qml is written in an unsupported language. File is not indexed.

0001 /**
0002  * \file SettingsPage.qml
0003  * Settings page.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 16 Feb 2015
0008  *
0009  * Copyright (C) 2015-2019  Urs Fleisch
0010  *
0011  * This program is free software; you can redistribute it and/or modify
0012  * it under the terms of the GNU Lesser General Public License as published by
0013  * the Free Software Foundation; version 3.
0014  *
0015  * This program is distributed in the hope that it will be useful,
0016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018  * GNU Lesser General Public License for more details.
0019  *
0020  * You should have received a copy of the GNU Lesser General Public License
0021  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0022  */
0023 
0024 import QtQuick 2.11
0025 import QtQuick.Controls 2.4
0026 
0027 AbstractSettingsPage {
0028   id: settingsPage
0029 
0030   title: qsTr("Settings")
0031   model: [
0032     SettingsElement { name: qsTr("Tags") },
0033     SettingsElement { name: qsTr("Files") },
0034     SettingsElement { name: qsTr("Plugins") },
0035     SettingsElement { name: qsTr("Appearance") }
0036   ]
0037   onClicked: pageStack.push(
0038                [ tagsPage, filesPage, pluginsPage, appearancePage ][index])
0039   Component {
0040     id: tagsPage
0041     AbstractSettingsPage {
0042       property QtObject tagCfg: configs.tagConfig()
0043       property QtObject fmtCfg: configs.tagFormatConfig()
0044       title: qsTr("Tags")
0045       visible: false
0046       model: [
0047         SettingsElement {
0048           name: qsTr("Mark truncated fields")
0049           onActivated: function() { value = tagCfg.markTruncations; }
0050           onDeactivated: function() { tagCfg.markTruncations = value; }
0051         },
0052         SettingsElement {
0053           name: qsTr("ID3v1 text encoding")
0054           dropDownModel: configs.tagConfig().getTextCodecNames()
0055           onActivated: function() { value = tagCfg.textEncodingV1Index; }
0056           onDeactivated: function() { tagCfg.textEncodingV1Index = value; }
0057         },
0058         SettingsElement {
0059           name: qsTr("ID3v2 text encoding")
0060           dropDownModel: configs.tagConfig().getTextEncodingNames()
0061           onActivated: function() { value = tagCfg.textEncoding; }
0062           onDeactivated: function() { tagCfg.textEncoding = value; }
0063         },
0064         SettingsElement {
0065           name: qsTr("Use track/total number of tracks format")
0066           onActivated: function() { value = tagCfg.enableTotalNumberOfTracks; }
0067           onDeactivated: function() { tagCfg.enableTotalNumberOfTracks = value; }
0068         },
0069         SettingsElement {
0070           name: qsTr("Genre as text instead of numeric string")
0071           onActivated: function() { value = tagCfg.genreNotNumeric; }
0072           onDeactivated: function() { tagCfg.genreNotNumeric = value; }
0073         },
0074         SettingsElement {
0075           name: qsTr("WAV files with lowercase id3 chunk")
0076           onActivated: function() { value = tagCfg.lowercaseId3RiffChunk; }
0077           onDeactivated: function() { tagCfg.lowercaseId3RiffChunk = value; }
0078         },
0079         SettingsElement {
0080           name: qsTr("Version used for new ID3v2 tags")
0081           dropDownModel: configs.tagConfig().getId3v2VersionNames()
0082           onActivated: function() { value = tagCfg.id3v2Version; }
0083           onDeactivated: function() { tagCfg.id3v2Version = value; }
0084         },
0085         SettingsElement {
0086           name: qsTr("Track number digits")
0087           onActivated: function() { value = tagCfg.trackNumberDigits; }
0088           onDeactivated: function() { tagCfg.trackNumberDigits = value; }
0089         },
0090         SettingsElement {
0091           name: qsTr("Ogg/Vorbis comment field name")
0092           dropDownModel: configs.tagConfig().getCommentNames()
0093           onActivated: function() {
0094             value = dropDownModel.indexOf(tagCfg.commentName)
0095           }
0096           onDeactivated: function() {
0097             tagCfg.commentName = dropDownModel[value]
0098           }
0099         },
0100         SettingsElement {
0101           name: qsTr("Ogg/Vorbis picture field name")
0102           dropDownModel: configs.tagConfig().getPictureNames()
0103           onActivated: function() { value = tagCfg.pictureNameIndex; }
0104           onDeactivated: function() { tagCfg.pictureNameIndex = value; }
0105         },
0106         SettingsElement {
0107           name: qsTr("RIFF track number field name")
0108           dropDownModel: configs.tagConfig().getRiffTrackNames()
0109           onActivated: function() {
0110             value = dropDownModel.indexOf(tagCfg.riffTrackName)
0111           }
0112           onDeactivated: function() {
0113             tagCfg.riffTrackName = dropDownModel[value]
0114           }
0115         },
0116         SettingsElement {
0117           name: qsTr("Mark if picture larger than maximum size")
0118           onActivated: function() { value = tagCfg.markOversizedPictures; }
0119           onDeactivated: function() { tagCfg.markOversizedPictures = value; }
0120         },
0121         SettingsElement {
0122           name: qsTr("Picture maximum size (bytes)")
0123           onActivated: function() { value = tagCfg.maximumPictureSize; }
0124           onDeactivated: function() { tagCfg.maximumPictureSize = value; }
0125         },
0126         SettingsElement {
0127           name: qsTr("Show only custom genres")
0128           onActivated: function() { value = tagCfg.onlyCustomGenres; }
0129           onDeactivated: function() { tagCfg.onlyCustomGenres = value; }
0130           onEdit: function() {
0131             stringListEditPage.title = qsTr("Custom Genres")
0132             stringListEditPage.onActivated = function() {
0133               stringListEditPage.setElements(tagCfg.customGenres)
0134             }
0135             stringListEditPage.onDeactivated = function() {
0136               tagCfg.customGenres = stringListEditPage.getElements()
0137             }
0138             page.StackView.view.push(stringListEditPage)
0139           }
0140         },
0141         SettingsElement {
0142           name: qsTr("Case conversion")
0143           dropDownModel: configs.tagFormatConfig().getCaseConversionNames()
0144           onActivated: function() { value = fmtCfg.caseConversion; }
0145           onDeactivated: function() { fmtCfg.caseConversion = value; }
0146         },
0147         SettingsElement {
0148           name: qsTr("Locale")
0149           dropDownModel: configs.tagFormatConfig().getLocaleNames()
0150           onActivated: function() {
0151             var idx = dropDownModel.indexOf(fmtCfg.localeName)
0152             value = idx === -1 ? 0 : idx
0153           }
0154           onDeactivated: function() {
0155             fmtCfg.localeName = value > 0 ? dropDownModel[value] : ""
0156           }
0157         },
0158         SettingsElement {
0159           name: qsTr("String replacement")
0160           onActivated: function() { value = fmtCfg.strRepEnabled; }
0161           onDeactivated: function() { fmtCfg.strRepEnabled = value; }
0162           onEdit: function() {
0163             mapEditPage.title = qsTr("String Replacement")
0164             mapEditPage.onActivated = function() {
0165               mapEditPage.setElements(fmtCfg.strRepMap)
0166             }
0167             mapEditPage.onDeactivated = function() {
0168               fmtCfg.strRepMap = mapEditPage.getElements()
0169             }
0170             page.StackView.view.push(mapEditPage)
0171           }
0172         },
0173         SettingsElement {
0174           name: qsTr("Custom frames")
0175           onEdit: function() {
0176             stringListEditPage.title = qsTr("Custom Frames")
0177             stringListEditPage.onActivated = function() {
0178               stringListEditPage.setElements(
0179                     tagCfg.customFrameNamesToDisplayNames(tagCfg.customFrames))
0180             }
0181             stringListEditPage.onDeactivated = function() {
0182               tagCfg.customFrames = tagCfg.customFrameNamesFromDisplayNames(
0183                     stringListEditPage.getElements())
0184             }
0185             page.StackView.view.push(stringListEditPage)
0186           }
0187         },
0188         SettingsElement {
0189           name: qsTr("Quick access frames")
0190           onEdit: function() {
0191             page.StackView.view.push(quickAccessFramesPage)
0192           }
0193         }
0194       ]
0195       StackView.onActivated: activateAll()
0196       StackView.onDeactivated: deactivateAll()
0197     }
0198   }
0199   Component {
0200     id: filesPage
0201     AbstractSettingsPage {
0202       property QtObject fileCfg: configs.fileConfig()
0203       property QtObject fmtCfg: configs.filenameFormatConfig()
0204       title: qsTr("Files")
0205       visible: false
0206       model: [
0207         SettingsElement {
0208           name: qsTr("Load last-opened files")
0209           onActivated: function() { value = fileCfg.loadLastOpenedFile; }
0210           onDeactivated: function() { fileCfg.loadLastOpenedFile = value; }
0211         },
0212         SettingsElement {
0213           name: qsTr("Preserve file timestamp")
0214           onActivated: function() { value = fileCfg.preserveTime; }
0215           onDeactivated: function() { fileCfg.preserveTime = value; }
0216         },
0217         SettingsElement {
0218           name: qsTr("Mark changes")
0219           onActivated: function() { value = fileCfg.markChanges; }
0220           onDeactivated: function() { fileCfg.markChanges = value; }
0221         },
0222         SettingsElement {
0223           name: qsTr("Automatically apply format")
0224           onActivated: function() { value = fmtCfg.formatWhileEditing; }
0225           onDeactivated: function() { fmtCfg.formatWhileEditing = value; }
0226         },
0227         SettingsElement {
0228           name: qsTr("Use for playlist and folder names")
0229           onActivated: function() { value = fmtCfg.useForOtherFileNames; }
0230           onDeactivated: function() { fmtCfg.useForOtherFileNames = value; }
0231         },
0232         SettingsElement {
0233           name: qsTr("Use maximum length")
0234           onActivated: function() { value = fmtCfg.enableMaximumLength; }
0235           onDeactivated: function() { fmtCfg.enableMaximumLength = value; }
0236         },
0237         SettingsElement {
0238           name: qsTr("Maximum length")
0239           onActivated: function() { value = fmtCfg.maximumLength; }
0240           onDeactivated: function() { fmtCfg.maximumLength = value; }
0241         },
0242         SettingsElement {
0243           name: qsTr("Case conversion")
0244           dropDownModel: configs.filenameFormatConfig().getCaseConversionNames()
0245           onActivated: function() { value = fmtCfg.caseConversion; }
0246           onDeactivated: function() { fmtCfg.caseConversion = value; }
0247         },
0248         SettingsElement {
0249           name: qsTr("Locale")
0250           dropDownModel: configs.filenameFormatConfig().getLocaleNames()
0251           onActivated: function() {
0252             var idx = dropDownModel.indexOf(fmtCfg.localeName)
0253             value = idx === -1 ? 0 : idx
0254           }
0255           onDeactivated: function() {
0256             fmtCfg.localeName = value > 0 ? dropDownModel[value] : ""
0257           }
0258         },
0259         SettingsElement {
0260           name: qsTr("String replacement")
0261           onActivated: function() { value = fmtCfg.strRepEnabled; }
0262           onDeactivated: function() { fmtCfg.strRepEnabled = value; }
0263           onEdit: function() {
0264             mapEditPage.title = qsTr("String Replacement")
0265             mapEditPage.onActivated = function() {
0266               mapEditPage.setElements(fmtCfg.strRepMap)
0267             }
0268             mapEditPage.onDeactivated = function() {
0269               fmtCfg.strRepMap = mapEditPage.getElements()
0270             }
0271             page.StackView.view.push(mapEditPage)
0272           }
0273         },
0274         SettingsElement {
0275           name: qsTr("Filename for cover")
0276           onActivated: function() { value = fileCfg.defaultCoverFileName; }
0277           onDeactivated: function() { fileCfg.defaultCoverFileName = value; }
0278         },
0279         SettingsElement {
0280           name: qsTr("Playlist text encoding")
0281           dropDownModel: configs.fileConfig().getTextCodecNames()
0282           onActivated: function() { value = fileCfg.textEncodingIndex; }
0283           onDeactivated: function() { fileCfg.textEncodingIndex = value; }
0284         },
0285         SettingsElement {
0286           name: qsTr("To filename format")
0287           dropDownModel: configs.fileConfig().toFilenameFormats
0288           width: constants.gu(51)
0289           onActivated: function() {
0290             value = dropDownModel.indexOf(fileCfg.toFilenameFormat)
0291           }
0292           onDeactivated: function() {
0293             fileCfg.toFilenameFormat = dropDownModel[value]
0294           }
0295           onEdit: function() {
0296             stringListEditPage.title = qsTr("Filename from Tag")
0297             stringListEditPage.onActivated = function() {
0298               stringListEditPage.setElements(dropDownModel)
0299               stringListEditPage.currentIndex = value
0300             }
0301             stringListEditPage.onDeactivated = function() {
0302               var lst = stringListEditPage.getElements()
0303               configs.fileConfig().toFilenameFormats = lst
0304               configs.fileConfig().toFilenameFormat =
0305                   lst[stringListEditPage.currentIndex]
0306             }
0307             page.StackView.view.push(stringListEditPage)
0308           }
0309         },
0310         SettingsElement {
0311           name: qsTr("From filename format")
0312           dropDownModel: configs.fileConfig().fromFilenameFormats
0313           width: constants.gu(51)
0314           onActivated: function() {
0315             value = dropDownModel.indexOf(fileCfg.fromFilenameFormat)
0316           }
0317           onDeactivated: function() {
0318             fileCfg.fromFilenameFormat = dropDownModel[value]
0319           }
0320           onEdit: function() {
0321             stringListEditPage.title = qsTr("Tag from Filename")
0322             stringListEditPage.onActivated = function() {
0323               stringListEditPage.setElements(dropDownModel)
0324               stringListEditPage.currentIndex = value
0325             }
0326             stringListEditPage.onDeactivated = function() {
0327               var lst = stringListEditPage.getElements()
0328               configs.fileConfig().fromFilenameFormats = lst
0329               configs.fileConfig().fromFilenameFormat =
0330                   lst[stringListEditPage.currentIndex]
0331             }
0332             page.StackView.view.push(stringListEditPage)
0333           }
0334         }
0335       ]
0336       StackView.onActivated: activateAll()
0337       StackView.onDeactivated: deactivateAll()
0338     }
0339   }
0340   Component {
0341     id: pluginsPage
0342     AbstractSettingsPage {
0343       title: qsTr("Plugins")
0344       visible: false
0345       StackView.onActivated: {
0346         var tagCfg = configs.tagConfig()
0347         var importCfg = configs.importConfig()
0348         var disabledTagPlugins, disabledImportPlugins, i, name
0349         disabledTagPlugins = tagCfg.disabledPlugins
0350         disabledImportPlugins = importCfg.disabledPlugins
0351         for (i = 0; i < model.length; ++i) {
0352           name = model[i].name
0353           model[i].value =
0354               disabledTagPlugins.indexOf(name) === -1 &&
0355               disabledImportPlugins.indexOf(name) === -1
0356         }
0357       }
0358       StackView.onDeactivated: {
0359         var tagCfg = configs.tagConfig()
0360         var importCfg = configs.importConfig()
0361         var disabledTagPlugins, disabledImportPlugins, i, name
0362         var availableTagPlugins = tagCfg.availablePlugins
0363         var availableImportPlugins = importCfg.availablePlugins
0364         disabledTagPlugins = []
0365         disabledImportPlugins = []
0366         for (i = 0; i < model.length; ++i) {
0367           if (model[i].value === false) {
0368             name = model[i].name
0369             if (availableTagPlugins.indexOf(name) !== -1) {
0370               disabledTagPlugins.push(name)
0371             } else if (availableImportPlugins.indexOf(name) !== -1) {
0372               disabledImportPlugins.push(name)
0373             }
0374           }
0375         }
0376         tagCfg.disabledPlugins = disabledTagPlugins
0377         importCfg.disabledPlugins = disabledImportPlugins
0378       }
0379       Component.onCompleted: {
0380         // A deep copy is necessary in QtQuick 2 because of QTBUG-33149
0381         // (concat does not work with QStringList) and to avoid modification of
0382         // the original list in the config.
0383         var availablePlugins = configs.tagConfig().availablePlugins.slice()
0384         availablePlugins = availablePlugins.concat(
0385                configs.importConfig().availablePlugins)
0386         var settingsModel = []
0387         var elementComponent = Qt.createComponent("SettingsElement.qml")
0388         for (var i = 0; i < availablePlugins.length; ++i) {
0389           var elementObj = elementComponent.createObject(pluginsPage)
0390           elementObj.name = availablePlugins[i]
0391           settingsModel.push(elementObj)
0392         }
0393         model = settingsModel
0394       }
0395     }
0396   }
0397   Component {
0398     id: appearancePage
0399     AbstractSettingsPage {
0400       property QtObject mainWindowCfg: configs.mainWindowConfig()
0401       title: qsTr("Appearance")
0402       visible: false
0403       model: [
0404         SettingsElement {
0405           name: qsTr("Language")
0406           dropDownModel: [qsTr("System")]
0407             .concat(configs.mainWindowConfig().availableLanguages())
0408           onActivated: function() {
0409             value = mainWindowCfg.language
0410                 ? dropDownModel.indexOf(mainWindowCfg.language) : 0
0411           }
0412           onDeactivated: function() {
0413             mainWindowCfg.language = value > 0 ? dropDownModel[value] : ""
0414           }
0415         },
0416         SettingsElement {
0417           name: qsTr("Theme")
0418           dropDownModel: configs.mainWindowConfig().getQtQuickStyleNames()
0419           onActivated: function() {
0420             value = dropDownModel.indexOf(mainWindowCfg.qtQuickStyle)
0421           }
0422           onDeactivated: function() {
0423             mainWindowCfg.qtQuickStyle = dropDownModel[value]
0424           }
0425         }
0426       ]
0427       StackView.onActivated: activateAll()
0428       StackView.onDeactivated: deactivateAll()
0429     }
0430   }
0431 
0432   Component {
0433     id: quickAccessFramesPage
0434     AbstractSettingsPage {
0435       title: qsTr("Quick Access Frames")
0436       visible: false
0437       StackView.onActivated: {
0438         var nameSelection = configs.tagConfig().selectedQuickAccessFrames()
0439         var len = Math.min(model.length, nameSelection.length), i
0440         for (i = 0; i < len; ++i) {
0441           model[i].name = nameSelection[i].name
0442           model[i].value = nameSelection[i].selected
0443           model[i].data = nameSelection[i].type
0444         }
0445       }
0446       StackView.onDeactivated: {
0447         var tagCfg = configs.tagConfig()
0448         var nameSelection = tagCfg.selectedQuickAccessFrames()
0449         var len = Math.min(model.length, nameSelection.length), i
0450         for (i = 0; i < len; ++i) {
0451           nameSelection[i].name = model[i].name
0452           nameSelection[i].selected = model[i].value
0453           nameSelection[i].type = model[i].data
0454         }
0455         tagCfg.setSelectedQuickAccessFrames(nameSelection)
0456         app.applyChangedConfiguration()
0457       }
0458       Component.onCompleted: {
0459         var nameSelection = configs.tagConfig().selectedQuickAccessFrames()
0460         var settingsModel = []
0461         var elementComponent = Qt.createComponent("SettingsElement.qml")
0462         for (var i = 0; i < nameSelection.length; ++i) {
0463           var elementObj = elementComponent.createObject(quickAccessFramesPage)
0464           elementObj.name = nameSelection[i].name
0465           settingsModel.push(elementObj)
0466         }
0467         model = settingsModel
0468       }
0469     }
0470   }
0471 
0472   StringListEditPage {
0473     id: stringListEditPage
0474     property var onActivated
0475     property var onDeactivated
0476     visible: false
0477     StackView.onActivated: this.onActivated()
0478     StackView.onDeactivated: this.onDeactivated()
0479   }
0480   MapEditPage {
0481     id: mapEditPage
0482     property var onActivated
0483     property var onDeactivated
0484     visible: false
0485     StackView.onActivated: this.onActivated()
0486     StackView.onDeactivated: this.onDeactivated()
0487   }
0488 }