Warning, /plasma/print-manager/src/kcm/ui/MakeModel.qml is written in an unsupported language. File is not indexed.
0001 /** 0002 SPDX-FileCopyrightText: 2023 Mike Noe <noeerover@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 import QtQuick 0007 import QtQuick.Layouts 0008 import QtQuick.Controls as QQC2 0009 import QtQuick.Dialogs as Dialogs 0010 import org.kde.kirigami as Kirigami 0011 import org.kde.kitemmodels as KSFM 0012 import org.kde.plasma.components as PComp 0013 import org.kde.plasma.extras as PlasmaExtras 0014 import org.kde.plasma.printmanager as PM 0015 0016 /* 0017 * PPD driver selection 0018 */ 0019 Kirigami.Dialog { 0020 id: root 0021 0022 property PM.PPDModel model 0023 property bool loading: true 0024 // ppd attributes for the make/model 0025 property var ppdData: ({}) 0026 0027 // make is the first level in the hierarchy of the model 0028 function getMakeIndex(make) { 0029 print("GETMAKE:", make) 0030 for (let i=0, len=model.rowCount(); i<len; ++i) { 0031 const val = model.data(model.index(i,0), Qt.DisplayRole).toString() 0032 if (val === make) 0033 return i 0034 } 0035 return -1 0036 } 0037 0038 // make/model is the second level 0039 // try to select based on CUPS pcfile *and* makemodel desc 0040 // preference to pcfile 0041 function getMakeModelIndex() { 0042 const file = ppdData.pcfile?.toLowerCase() 0043 const mm = ppdData.makeModel?.toLowerCase() 0044 print("GETMAKEMODEL pcfile:", file, ", mm:", mm) 0045 for (let i=0, len=printerModels.rowCount(); i<len; ++i) { 0046 const ndx = printerModels.mapToSource(printerModels.index(i,0)) 0047 const f = printerModels.sourceModel.data(ndx, PM.PPDModel.PPDName).toString() 0048 const m = printerModels.sourceModel.data(ndx, PM.PPDModel.PPDMakeAndModel).toString() 0049 if ((file && f && f.toLowerCase().includes(file)) | (mm && m && m.toLowerCase().includes(mm))) { 0050 return i 0051 } 0052 } 0053 return -1 0054 } 0055 0056 function setCurrentMakeModel(index = 0) { 0057 if (index === -1) { 0058 return 0059 } 0060 const ndx = printerModels.mapToSource(printerModels.index(index,0)) 0061 ppdData.makeModel = printerModels.sourceModel.data(ndx, PM.PPDModel.PPDMakeAndModel).toString() 0062 ppdData.file = printerModels.sourceModel.data(ndx, PM.PPDModel.PPDName).toString() 0063 } 0064 0065 function init() { 0066 if (ppdData.type === PM.PPDType.Manual) { 0067 rbFile.checked = true 0068 customFilename.text = ppdData.file 0069 } else { 0070 rbMake.checked = true 0071 0072 // Make/model list selections 0073 // Default to first in the list if there is no make 0074 if (ppdData.make === undefined) { 0075 ppdData.make = model.data(model.index(0,0), Qt.DisplayRole).toString() 0076 makesList.currentIndex = 0 0077 } else { 0078 makesList.currentIndex = getMakeIndex(ppdData.make) 0079 } 0080 makesList.positionViewAtIndex(makesList.currentIndex, ListView.Center) 0081 printerModels.invalidateFilter() 0082 // Select the printer model 0083 makeModelList.currentIndex = getMakeModelIndex() 0084 makeModelList.positionViewAtIndex(makeModelList.currentIndex, ListView.Center) 0085 setCurrentMakeModel(makeModelList.currentIndex) 0086 } 0087 0088 if (ppdData.makeModel === undefined) { 0089 title = i18nc("@title:window", "Select a printer make/model") 0090 } else { 0091 title = i18nc("@title:window", "Printer Driver (%1)", ppdData.makeModel) 0092 } 0093 0094 } 0095 0096 signal saveValues(var data) 0097 0098 title: i18nc("@title:window", "Printer Driver") 0099 0100 onLoadingChanged: { 0101 print("PPD Database Count:", model.rowCount()) 0102 if (!loading) { 0103 // empty ppdData means we're selecting new make/model 0104 if (Object.keys(ppdData).length === 0) { 0105 rbMake.checked = true 0106 ppdData.type = PM.PPDType.Custom 0107 ppdData.pcfile = "" 0108 makesList.currentIndex = 0 0109 makesList.positionViewAtBeginning() 0110 ppdData.make = model.data(model.index(0,0), Qt.DisplayRole).toString() 0111 if (ppdData.make.length > 0) { 0112 printerModels.invalidateFilter() 0113 setCurrentMakeModel() 0114 } 0115 } else { 0116 init() 0117 } 0118 } 0119 } 0120 0121 // Try to load PPDModel if empty 0122 Component.onCompleted: { 0123 if (model.rowCount() === 0) { 0124 model.load() 0125 } else { 0126 loading = false 0127 } 0128 } 0129 0130 Connections { 0131 target: model 0132 enabled: loading 0133 0134 function onLoaded() { 0135 loading = false 0136 } 0137 } 0138 0139 onClosed: destroy(10) 0140 0141 standardButtons: Kirigami.Dialog.NoButton 0142 0143 customFooterActions: [ 0144 Kirigami.Action { 0145 text: i18n("Save") 0146 enabled: !loading 0147 icon.name: "dialog-ok-symbolic" 0148 onTriggered: { 0149 if (rbFile.checked && customFilename.text.length === 0) { 0150 error.text = i18n("Select a PostScript Printer Description (PPD) file") 0151 error.visible = true 0152 fileButton.focus = true 0153 return 0154 } 0155 0156 if (rbMake.checked && makeModelList.currentIndex === -1) { 0157 error.text = i18n("Printer model is required. Please select a printer model.") 0158 error.visible = true 0159 makeModelList.focus = true 0160 return 0161 } 0162 0163 if (rbFile.checked) { 0164 ppdData.file = customFilename.text 0165 } 0166 saveValues(ppdData) 0167 root.close() 0168 } 0169 } 0170 ] 0171 0172 // Printer models are filtered by selected make and 0173 // optionally, by a second user filter 0174 KSFM.KSortFilterProxyModel { 0175 id: printerModels 0176 // This holds printer model lists, which are descendents 0177 // of the make items 0178 sourceModel: KSFM.KDescendantsProxyModel { 0179 sourceModel: root.model 0180 } 0181 0182 filterRowCallback: (source_row, source_parent) => { 0183 const make = sourceModel.data(sourceModel.index(source_row, 0, source_parent) 0184 , PM.PPDModel.PPDMake) 0185 if (filterString.length === 0) { 0186 return make === ppdData.make 0187 } 0188 0189 return make === ppdData.make 0190 && sourceModel.data(sourceModel.index(source_row, 0, source_parent) 0191 , PM.PPDModel.PPDMakeAndModel).toLowerCase().includes(filterString) 0192 } 0193 } 0194 0195 contentItem: ColumnLayout { 0196 spacing: Kirigami.Units.largeSpacing 0197 enabled: !loading 0198 0199 BannerWithTimer { 0200 id: error 0201 Layout.fillWidth: true 0202 } 0203 0204 QQC2.ButtonGroup { 0205 id: buttonGroup 0206 } 0207 0208 RowLayout { 0209 QQC2.RadioButton { 0210 id: rbMake 0211 text: i18nc("@option:radio", "Select Make and Model:") 0212 Layout.fillWidth: true 0213 onToggled: { 0214 if (checked) { 0215 ppdData.type = PM.PPDType.Custom 0216 } 0217 } 0218 QQC2.ButtonGroup.group: buttonGroup 0219 } 0220 0221 Kirigami.SearchField { 0222 enabled: rbMake.checked && makesList.count > 0 0223 placeholderText: i18nc("@info:placeholder", "Filter Models") 0224 onAccepted: { 0225 printerModels.filterString = text.toLowerCase() 0226 makeModelList.currentIndex = -1 0227 } 0228 } 0229 } 0230 0231 RowLayout { 0232 enabled: rbMake.checked 0233 0234 QQC2.ScrollView { 0235 Layout.fillHeight: true 0236 Layout.preferredWidth: Math.floor(root.width/3) 0237 clip: true 0238 0239 contentItem: ListView { 0240 id: makesList 0241 clip: true 0242 highlight: PlasmaExtras.Highlight {} 0243 highlightMoveDuration: 0 0244 highlightResizeDuration: 0 0245 0246 model: root.model 0247 0248 delegate: PComp.ItemDelegate { 0249 width: ListView.view.width 0250 text: model?.display 0251 icon.name: "system-user-prompt" 0252 0253 onClicked: { 0254 ListView.view.currentIndex = index 0255 ppdData.make = model.display 0256 printerModels.invalidateFilter() 0257 makeModelList.currentIndex = 0 0258 makeModelList.positionViewAtBeginning() 0259 setCurrentMakeModel() 0260 } 0261 } 0262 } 0263 } 0264 0265 QQC2.ScrollView { 0266 Layout.fillHeight: true 0267 Layout.fillWidth: true 0268 clip: true 0269 0270 contentItem: ListView { 0271 id: makeModelList 0272 clip: true 0273 highlight: PlasmaExtras.Highlight {} 0274 highlightMoveDuration: 0 0275 highlightResizeDuration: 0 0276 0277 PComp.BusyIndicator { 0278 running: loading 0279 visible: loading 0280 anchors.left: parent.left 0281 anchors.verticalCenter: parent.verticalCenter 0282 implicitWidth: Kirigami.Units.gridUnit * 6 0283 implicitHeight: Kirigami.Units.gridUnit * 6 0284 } 0285 0286 model: printerModels 0287 0288 delegate: PComp.ItemDelegate { 0289 width: ListView.view.width 0290 text: model?.ppdMakeModel 0291 icon.name: "printer-symbolic" 0292 0293 onClicked: { 0294 ListView.view.currentIndex = index 0295 ppdData.file = ppdName 0296 ppdData.makeModel = ppdMakeModel 0297 } 0298 } 0299 } 0300 } 0301 0302 } 0303 0304 QQC2.RadioButton { 0305 id: rbFile 0306 text: i18nc("@option:radio", "PPD file:") 0307 Layout.topMargin: Kirigami.Units.largeSpacing*3 0308 onToggled: { 0309 if (checked) { 0310 ppdData.type = PM.PPDType.Manual 0311 fileButton.focus = true 0312 } 0313 } 0314 QQC2.ButtonGroup.group: buttonGroup 0315 } 0316 0317 RowLayout { 0318 enabled: rbFile.checked 0319 0320 QQC2.TextField { 0321 id: customFilename 0322 readOnly: true 0323 Layout.fillWidth: true 0324 } 0325 0326 QQC2.Button { 0327 id: fileButton 0328 text: i18nc("@action:button", "Select PPD Fileā¦") 0329 icon.name: "folder-print-symbolic" 0330 onClicked: fileDlg.open() 0331 } 0332 0333 Dialogs.FileDialog { 0334 id: fileDlg 0335 acceptLabel: i18n("Select") 0336 nameFilters: [i18n("PostScript Printer Description Files (*.ppd)")] 0337 0338 onAccepted: customFilename.text = currentFile 0339 } 0340 } 0341 } 0342 0343 }