1/**************************************************************************** 2** 3** Copyright (C) 2016 The Qt Company Ltd. 4** Contact: https://www.qt.io/licensing/ 5** 6** This file is part of the Qt Quick Dialogs module of the Qt Toolkit. 7** 8** $QT_BEGIN_LICENSE:LGPL$ 9** Commercial License Usage 10** Licensees holding valid commercial Qt licenses may use this file in 11** accordance with the commercial license agreement provided with the 12** Software or, alternatively, in accordance with the terms contained in 13** a written agreement between you and The Qt Company. For licensing terms 14** and conditions see https://www.qt.io/terms-conditions. For further 15** information use the contact form at https://www.qt.io/contact-us. 16** 17** GNU Lesser General Public License Usage 18** Alternatively, this file may be used under the terms of the GNU Lesser 19** General Public License version 3 as published by the Free Software 20** Foundation and appearing in the file LICENSE.LGPL3 included in the 21** packaging of this file. Please review the following information to 22** ensure the GNU Lesser General Public License version 3 requirements 23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24** 25** GNU General Public License Usage 26** Alternatively, this file may be used under the terms of the GNU 27** General Public License version 2.0 or (at your option) the GNU General 28** Public license version 3 or any later version approved by the KDE Free 29** Qt Foundation. The licenses are as published by the Free Software 30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31** included in the packaging of this file. Please review the following 32** information to ensure the GNU General Public License requirements will 33** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34** https://www.gnu.org/licenses/gpl-3.0.html. 35** 36** $QT_END_LICENSE$ 37** 38****************************************************************************/ 39 40import QtQuick 2.2 41import QtQuick.Controls 1.2 42import QtQuick.Controls.Private 1.0 43import QtQuick.Controls.Styles 1.0 44import QtQuick.Dialogs 1.1 45import QtQuick.Dialogs.Private 1.1 46import QtQuick.Layouts 1.1 47import QtQuick.Window 2.1 48import "qml" 49 50AbstractFontDialog { 51 id: root 52 53 property alias font: content.externalFont 54 property alias currentFont: content.font 55 56 Rectangle { 57 id: content 58 SystemPalette { id: palette } 59 60 implicitWidth: Math.min(root.__maximumDimension, Math.max(Screen.pixelDensity * 100, mainLayout.implicitWidth + outerSpacing * 2)) 61 implicitHeight: Math.min(root.__maximumDimension, Math.max(Screen.pixelDensity * 60, mainLayout.implicitHeight + outerSpacing * 2)) 62 property real spacing: 6 63 property real outerSpacing: 12 64 color: palette.window 65 66 property font font: Qt.font({ family: "Helvetica", pointSize: 24, weight: Font.Normal }) 67 property font externalFont 68 property string writingSystem 69 property string writingSystemSample 70 property var pointSizes 71 72 onExternalFontChanged: { 73 if (Component.status != Component.Ready) 74 return 75 76 if (content.font != content.externalFont) { 77 font = externalFont 78 wsComboBox.reset() 79 fontListView.reset() 80 weightListView.reset() 81 } 82 } 83 84 Component.onCompleted: externalFontChanged() 85 86 onWritingSystemSampleChanged: { sample.text = writingSystemSample; } 87 88 Keys.onPressed: { 89 event.accepted = true 90 switch (event.key) { 91 case Qt.Key_Return: 92 case Qt.Key_Select: 93 updateUponAccepted() 94 break 95 case Qt.Key_Escape: 96 case Qt.Key_Back: 97 reject() 98 break 99 default: 100 // do nothing 101 event.accepted = false 102 break 103 } 104 } 105 106 function updateUponAccepted() { 107 root.font = content.font 108 root.accept() 109 } 110 111 ColumnLayout { 112 id: mainLayout 113 anchors { fill: parent; margins: content.outerSpacing } 114 spacing: content.spacing 115 116 GridLayout { 117 columnSpacing: content.spacing; rowSpacing: content.spacing 118 columns: 3 119 120 Label { id: fontNameLabel; Layout.fillWidth: true; text: qsTr("Font"); font.bold: true } 121 Label { id: weightLabel; text: qsTr("Weight"); font.bold: true } 122 Label { id: sizeLabel; text: qsTr("Size"); font.bold: true } 123 TableView { 124 id: fontListView 125 focus: true 126 Layout.fillWidth: true 127 Layout.fillHeight: true 128 Layout.preferredWidth: fontColumn.width 129 headerVisible: false 130 function reset() { 131 fontModel.findIndex() 132 content.pointSizes = fontModel.pointSizes() 133 fontModel.findPointSizesIndex() 134 } 135 TableViewColumn{ id: fontColumn; role: "family"; title: qsTr("Font Family") } 136 model: FontListModel { 137 id: fontModel 138 scalableFonts: root.scalableFonts 139 nonScalableFonts: root.nonScalableFonts 140 monospacedFonts: root.monospacedFonts 141 proportionalFonts: root.proportionalFonts 142 Component.onCompleted: fontListView.reset() 143 onModelReset: { findIndex(); } 144 function findIndex() { 145 fontListView.selection.clear() 146 if (fontModel.count <= 0 || fontListView.rowCount <= 0) 147 return 148 149 var currentRow = 0 150 if (content.font.family != "") { 151 for (var i = 0; i < fontModel.count; ++i) { 152 if (content.font.family == fontModel.get(i).family) { 153 currentRow = i 154 break 155 } 156 } 157 } 158 content.font.family = fontModel.get(currentRow).family 159 fontListView.selection.select(currentRow) 160 fontListView.positionViewAtRow(currentRow, ListView.Contain) 161 fontListView.clicked(currentRow) 162 } 163 function findPointSizesIndex() { 164 pointSizesListView.selection.clear() 165 if (content.pointSizes.length <= 0 || pointSizesListView.rowCount <= 0) 166 return 167 168 var currentRow = -1 169 for (var i = 0; i < content.pointSizes.length; ++i) { 170 if (content.font.pointSize == content.pointSizes[i]) { 171 currentRow = i 172 break 173 } 174 } 175 if (currentRow != -1) { 176 content.font.pointSize = content.pointSizes[currentRow] 177 pointSizesListView.selection.select(currentRow) 178 pointSizesListView.positionViewAtRow(currentRow, ListView.Contain) 179 pointSizesListView.clicked(currentRow) 180 } 181 } 182 } 183 function select(row) { 184 if (row == -1) 185 return 186 currentRow = row 187 content.font.family = fontModel.get(row).family 188 positionViewAtRow(row, ListView.Contain) 189 } 190 onClicked: select(row) 191 onCurrentRowChanged: select(currentRow) 192 } 193 TableView { 194 id: weightListView 195 implicitWidth: (Component.status == Component.Ready) ? (weightColumn.width + content.outerSpacing) : (100) 196 Layout.fillHeight: true 197 Component.onCompleted: resizeColumnsToContents(); 198 headerVisible: false 199 function reset() { 200 weightModel.findIndex() 201 } 202 TableViewColumn { id: weightColumn; role: "name"; title: qsTr("Weight") } 203 model: ListModel { 204 id: weightModel 205 ListElement { name: qsTr("Thin"); weight: Font.Thin } 206 ListElement { name: qsTr("ExtraLight"); weight: Font.ExtraLight } 207 ListElement { name: qsTr("Light"); weight: Font.Light } 208 ListElement { name: qsTr("Normal"); weight: Font.Normal } 209 ListElement { name: qsTr("Medium"); weight: Font.Medium } 210 ListElement { name: qsTr("DemiBold"); weight: Font.DemiBold } 211 ListElement { name: qsTr("Bold"); weight: Font.Bold } 212 ListElement { name: qsTr("ExtraBold"); weight: Font.ExtraBold } 213 ListElement { name: qsTr("Black"); weight: Font.Black } 214 Component.onCompleted: weightListView.reset() 215 function findIndex() { 216 var currentRow = 1 217 for (var i = 0; i < weightModel.count; ++i) { 218 if (content.font.weight == weightModel.get(i).weight) { 219 currentRow = i 220 break 221 } 222 } 223 content.font.weight = weightModel.get(currentRow).family 224 weightListView.selection.select(currentRow) 225 weightListView.positionViewAtRow(currentRow, ListView.Contain) 226 weightListView.clicked(currentRow) 227 } 228 } 229 function select(row) { 230 if (row == -1) 231 return 232 currentRow = row 233 content.font.weight = weightModel.get(row).weight 234 positionViewAtRow(row, ListView.Contain) 235 } 236 onClicked: select(row) 237 onCurrentRowChanged: select(currentRow) 238 } 239 ColumnLayout { 240 SpinBox { 241 id: pointSizeSpinBox; 242 implicitWidth: (Component.status == Component.Ready) ? (psColumn.width + content.outerSpacing) : (80) 243 value: content.font.pointSize 244 decimals: 0 245 minimumValue: 1 246 maximumValue: 512 247 onValueChanged: { 248 content.font.pointSize = Number(value); 249 updatePointSizesIndex(); 250 } 251 function updatePointSizesIndex() { 252 pointSizesListView.selection.clear() 253 if (content.pointSizes.length <= 0 || pointSizesListView.rowCount <= 0) 254 return 255 var currentRow = -1 256 for (var i = 0; i < content.pointSizes.length; ++i) { 257 if (content.font.pointSize == content.pointSizes[i]) { 258 currentRow = i 259 break 260 } 261 } 262 if (currentRow < 0) 263 return 264 content.font.pointSize = content.pointSizes[currentRow] 265 pointSizesListView.selection.select(currentRow) 266 pointSizesListView.positionViewAtRow(currentRow, ListView.Contain) 267 pointSizesListView.clicked(currentRow) 268 } 269 } 270 TableView { 271 id: pointSizesListView 272 Layout.fillHeight: true 273 headerVisible: false 274 implicitWidth: (Component.status == Component.Ready) ? (psColumn.width + content.outerSpacing) : (80) 275 Component.onCompleted: resizeColumnsToContents(); 276 TableViewColumn{ id: psColumn; role: ""; title: qsTr("Size") } 277 model: content.pointSizes 278 property bool guard: false 279 function select(row) { 280 if (row == -1 || !guard) 281 return 282 currentRow = row 283 content.font.pointSize = content.pointSizes[row] 284 pointSizeSpinBox.value = content.pointSizes[row] 285 positionViewAtRow(row, ListView.Contain) 286 } 287 onClicked: select(row) 288 onCurrentRowChanged: { 289 select(currentRow) 290 if (!guard) 291 guard = true 292 } 293 } 294 } 295 } 296 297 RowLayout { 298 spacing: content.spacing 299 Layout.fillHeight: false 300 ColumnLayout { 301 spacing: content.spacing 302 Layout.rowSpan: 3 303 Label { id: optionsLabel; text: qsTr("Style"); font.bold: true } 304 CheckBox { 305 id: italicCheckBox 306 text: qsTr("Italic") 307 checked: content.font.italic 308 onClicked: { content.font.italic = italicCheckBox.checked } 309 } 310 CheckBox { 311 id: underlineCheckBox 312 text: qsTr("Underline") 313 checked: content.font.underline 314 onClicked: { content.font.underline = underlineCheckBox.checked } 315 } 316 CheckBox { 317 id: overlineCheckBox 318 text: qsTr("Overline") 319 checked: content.font.overline 320 onClicked: { content.font.overline = overlineCheckBox.checked } 321 } 322 CheckBox { 323 id: strikeoutCheckBox 324 text: qsTr("Strikeout") 325 checked: content.font.strikeout 326 onClicked: { content.font.strikeout = strikeoutCheckBox.checked } 327 } 328 Item { Layout.fillHeight: true; } //spacer 329 Label { id: writingSystemLabel; text: qsTr("Writing System"); font.bold: true } 330 } 331 332 ColumnLayout { 333 Layout.rowSpan: 3 334 spacing: content.spacing 335 Layout.columnSpan: 2 336 Layout.fillWidth: true 337 Layout.fillHeight: true 338 Label { id: sampleLabel; text: qsTr("Sample"); font.bold: true } 339 340 Rectangle { 341 clip: true 342 Layout.fillWidth: true 343 Layout.fillHeight: true 344 implicitWidth: Math.min(360, sample.implicitWidth + parent.spacing) 345 implicitHeight: Math.min(240, sample.implicitHeight + parent.spacing) 346 color: "white" 347 border.color: "#999" 348 TextInput { 349 id: sample 350 activeFocusOnTab: true 351 Accessible.name: text 352 Accessible.role: Accessible.EditableText 353 anchors.centerIn: parent 354 font: content.font 355 onFocusChanged: if (!focus && sample.text == "") sample.text = content.writingSystemSample 356 renderType: Settings.isMobile ? Text.QtRendering : Text.NativeRendering 357 } 358 } 359 } 360 } 361 362 RowLayout { 363 id: buttonRow 364 Layout.columnSpan: 3 365 spacing: content.spacing 366 ComboBox { 367 id: wsComboBox 368 function reset() { 369 if (wsModel.count > 0) { 370 currentIndex = 0 371 } 372 } 373 textRole: "name" 374 model: WritingSystemListModel { 375 id: wsModel 376 Component.onCompleted: wsComboBox.reset() 377 } 378 onCurrentIndexChanged: { 379 if (currentIndex == -1) 380 return 381 382 content.writingSystem = wsModel.get(currentIndex).name 383 fontModel.writingSystem = content.writingSystem 384 content.writingSystemSample = wsModel.get(currentIndex).sample 385 fontListView.reset() 386 } 387 } 388 Item { Layout.fillWidth: true; } //spacer 389 Button { 390 text: qsTr("Cancel") 391 onClicked: root.reject() 392 } 393 Button { 394 text: qsTr("OK") 395 onClicked: { 396 content.updateUponAccepted() 397 } 398 } 399 } 400 } 401 } 402} 403 404