DefaultFontDialog.qml 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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. import QtQuick 2.2
  40. import QtQuick.Controls 1.2
  41. import QtQuick.Controls.Private 1.0
  42. import QtQuick.Controls.Styles 1.0
  43. import QtQuick.Dialogs 1.1
  44. import QtQuick.Dialogs.Private 1.1
  45. import QtQuick.Layouts 1.1
  46. import QtQuick.Window 2.1
  47. import "qml"
  48. AbstractFontDialog {
  49. id: root
  50. property alias font: content.externalFont
  51. property alias currentFont: content.font
  52. Rectangle {
  53. id: content
  54. SystemPalette { id: palette }
  55. implicitWidth: Math.min(root.__maximumDimension, Math.max(Screen.pixelDensity * 100, mainLayout.implicitWidth + outerSpacing * 2))
  56. implicitHeight: Math.min(root.__maximumDimension, Math.max(Screen.pixelDensity * 60, mainLayout.implicitHeight + outerSpacing * 2))
  57. property real spacing: 6
  58. property real outerSpacing: 12
  59. color: palette.window
  60. property font font: Qt.font({ family: "Helvetica", pointSize: 24, weight: Font.Normal })
  61. property font externalFont
  62. property string writingSystem
  63. property string writingSystemSample
  64. property var pointSizes
  65. onExternalFontChanged: {
  66. if (Component.status != Component.Ready)
  67. return
  68. if (content.font != content.externalFont) {
  69. font = externalFont
  70. wsComboBox.reset()
  71. fontListView.reset()
  72. weightListView.reset()
  73. }
  74. }
  75. Component.onCompleted: externalFontChanged()
  76. onWritingSystemSampleChanged: { sample.text = writingSystemSample; }
  77. Keys.onPressed: {
  78. event.accepted = true
  79. switch (event.key) {
  80. case Qt.Key_Return:
  81. case Qt.Key_Select:
  82. updateUponAccepted()
  83. break
  84. case Qt.Key_Escape:
  85. case Qt.Key_Back:
  86. reject()
  87. break
  88. default:
  89. // do nothing
  90. event.accepted = false
  91. break
  92. }
  93. }
  94. function updateUponAccepted() {
  95. root.font = content.font
  96. root.accept()
  97. }
  98. ColumnLayout {
  99. id: mainLayout
  100. anchors { fill: parent; margins: content.outerSpacing }
  101. spacing: content.spacing
  102. GridLayout {
  103. columnSpacing: content.spacing; rowSpacing: content.spacing
  104. columns: 3
  105. Label { id: fontNameLabel; Layout.fillWidth: true; text: qsTr("Font"); font.bold: true }
  106. Label { id: weightLabel; text: qsTr("Weight"); font.bold: true }
  107. Label { id: sizeLabel; text: qsTr("Size"); font.bold: true }
  108. TableView {
  109. id: fontListView
  110. focus: true
  111. Layout.fillWidth: true
  112. Layout.fillHeight: true
  113. Layout.preferredWidth: fontColumn.width
  114. headerVisible: false
  115. function reset() {
  116. fontModel.findIndex()
  117. content.pointSizes = fontModel.pointSizes()
  118. fontModel.findPointSizesIndex()
  119. }
  120. TableViewColumn{ id: fontColumn; role: "family"; title: qsTr("Font Family") }
  121. model: FontListModel {
  122. id: fontModel
  123. scalableFonts: root.scalableFonts
  124. nonScalableFonts: root.nonScalableFonts
  125. monospacedFonts: root.monospacedFonts
  126. proportionalFonts: root.proportionalFonts
  127. Component.onCompleted: fontListView.reset()
  128. onModelReset: { findIndex(); }
  129. function findIndex() {
  130. fontListView.selection.clear()
  131. if (fontModel.count <= 0 || fontListView.rowCount <= 0)
  132. return
  133. var currentRow = 0
  134. if (content.font.family != "") {
  135. for (var i = 0; i < fontModel.count; ++i) {
  136. if (content.font.family == fontModel.get(i).family) {
  137. currentRow = i
  138. break
  139. }
  140. }
  141. }
  142. content.font.family = fontModel.get(currentRow).family
  143. fontListView.selection.select(currentRow)
  144. fontListView.positionViewAtRow(currentRow, ListView.Contain)
  145. fontListView.clicked(currentRow)
  146. }
  147. function findPointSizesIndex() {
  148. pointSizesListView.selection.clear()
  149. if (content.pointSizes.length <= 0 || pointSizesListView.rowCount <= 0)
  150. return
  151. var currentRow = -1
  152. for (var i = 0; i < content.pointSizes.length; ++i) {
  153. if (content.font.pointSize == content.pointSizes[i]) {
  154. currentRow = i
  155. break
  156. }
  157. }
  158. if (currentRow != -1) {
  159. content.font.pointSize = content.pointSizes[currentRow]
  160. pointSizesListView.selection.select(currentRow)
  161. pointSizesListView.positionViewAtRow(currentRow, ListView.Contain)
  162. pointSizesListView.clicked(currentRow)
  163. }
  164. }
  165. }
  166. function select(row) {
  167. if (row == -1)
  168. return
  169. currentRow = row
  170. content.font.family = fontModel.get(row).family
  171. positionViewAtRow(row, ListView.Contain)
  172. }
  173. onClicked: select(row)
  174. onCurrentRowChanged: select(currentRow)
  175. }
  176. TableView {
  177. id: weightListView
  178. implicitWidth: (Component.status == Component.Ready) ? (weightColumn.width + content.outerSpacing) : (100)
  179. Layout.fillHeight: true
  180. Component.onCompleted: resizeColumnsToContents();
  181. headerVisible: false
  182. function reset() {
  183. weightModel.findIndex()
  184. }
  185. TableViewColumn { id: weightColumn; role: "name"; title: qsTr("Weight") }
  186. model: ListModel {
  187. id: weightModel
  188. ListElement { name: qsTr("Thin"); weight: Font.Thin }
  189. ListElement { name: qsTr("ExtraLight"); weight: Font.ExtraLight }
  190. ListElement { name: qsTr("Light"); weight: Font.Light }
  191. ListElement { name: qsTr("Normal"); weight: Font.Normal }
  192. ListElement { name: qsTr("Medium"); weight: Font.Medium }
  193. ListElement { name: qsTr("DemiBold"); weight: Font.DemiBold }
  194. ListElement { name: qsTr("Bold"); weight: Font.Bold }
  195. ListElement { name: qsTr("ExtraBold"); weight: Font.ExtraBold }
  196. ListElement { name: qsTr("Black"); weight: Font.Black }
  197. Component.onCompleted: weightListView.reset()
  198. function findIndex() {
  199. var currentRow = 1
  200. for (var i = 0; i < weightModel.count; ++i) {
  201. if (content.font.weight == weightModel.get(i).weight) {
  202. currentRow = i
  203. break
  204. }
  205. }
  206. content.font.weight = weightModel.get(currentRow).family
  207. weightListView.selection.select(currentRow)
  208. weightListView.positionViewAtRow(currentRow, ListView.Contain)
  209. weightListView.clicked(currentRow)
  210. }
  211. }
  212. function select(row) {
  213. if (row == -1)
  214. return
  215. currentRow = row
  216. content.font.weight = weightModel.get(row).weight
  217. positionViewAtRow(row, ListView.Contain)
  218. }
  219. onClicked: select(row)
  220. onCurrentRowChanged: select(currentRow)
  221. }
  222. ColumnLayout {
  223. SpinBox {
  224. id: pointSizeSpinBox;
  225. implicitWidth: (Component.status == Component.Ready) ? (psColumn.width + content.outerSpacing) : (80)
  226. value: content.font.pointSize
  227. decimals: 0
  228. minimumValue: 1
  229. maximumValue: 512
  230. onValueChanged: {
  231. content.font.pointSize = Number(value);
  232. updatePointSizesIndex();
  233. }
  234. function updatePointSizesIndex() {
  235. pointSizesListView.selection.clear()
  236. if (content.pointSizes.length <= 0 || pointSizesListView.rowCount <= 0)
  237. return
  238. var currentRow = -1
  239. for (var i = 0; i < content.pointSizes.length; ++i) {
  240. if (content.font.pointSize == content.pointSizes[i]) {
  241. currentRow = i
  242. break
  243. }
  244. }
  245. if (currentRow < 0)
  246. return
  247. content.font.pointSize = content.pointSizes[currentRow]
  248. pointSizesListView.selection.select(currentRow)
  249. pointSizesListView.positionViewAtRow(currentRow, ListView.Contain)
  250. pointSizesListView.clicked(currentRow)
  251. }
  252. }
  253. TableView {
  254. id: pointSizesListView
  255. Layout.fillHeight: true
  256. headerVisible: false
  257. implicitWidth: (Component.status == Component.Ready) ? (psColumn.width + content.outerSpacing) : (80)
  258. Component.onCompleted: resizeColumnsToContents();
  259. TableViewColumn{ id: psColumn; role: ""; title: qsTr("Size") }
  260. model: content.pointSizes
  261. property bool guard: false
  262. function select(row) {
  263. if (row == -1 || !guard)
  264. return
  265. currentRow = row
  266. content.font.pointSize = content.pointSizes[row]
  267. pointSizeSpinBox.value = content.pointSizes[row]
  268. positionViewAtRow(row, ListView.Contain)
  269. }
  270. onClicked: select(row)
  271. onCurrentRowChanged: {
  272. select(currentRow)
  273. if (!guard)
  274. guard = true
  275. }
  276. }
  277. }
  278. }
  279. RowLayout {
  280. spacing: content.spacing
  281. Layout.fillHeight: false
  282. ColumnLayout {
  283. spacing: content.spacing
  284. Layout.rowSpan: 3
  285. Label { id: optionsLabel; text: qsTr("Style"); font.bold: true }
  286. CheckBox {
  287. id: italicCheckBox
  288. text: qsTr("Italic")
  289. checked: content.font.italic
  290. onClicked: { content.font.italic = italicCheckBox.checked }
  291. }
  292. CheckBox {
  293. id: underlineCheckBox
  294. text: qsTr("Underline")
  295. checked: content.font.underline
  296. onClicked: { content.font.underline = underlineCheckBox.checked }
  297. }
  298. CheckBox {
  299. id: overlineCheckBox
  300. text: qsTr("Overline")
  301. checked: content.font.overline
  302. onClicked: { content.font.overline = overlineCheckBox.checked }
  303. }
  304. CheckBox {
  305. id: strikeoutCheckBox
  306. text: qsTr("Strikeout")
  307. checked: content.font.strikeout
  308. onClicked: { content.font.strikeout = strikeoutCheckBox.checked }
  309. }
  310. Item { Layout.fillHeight: true; } //spacer
  311. Label { id: writingSystemLabel; text: qsTr("Writing System"); font.bold: true }
  312. }
  313. ColumnLayout {
  314. Layout.rowSpan: 3
  315. spacing: content.spacing
  316. Layout.columnSpan: 2
  317. Layout.fillWidth: true
  318. Layout.fillHeight: true
  319. Label { id: sampleLabel; text: qsTr("Sample"); font.bold: true }
  320. Rectangle {
  321. clip: true
  322. Layout.fillWidth: true
  323. Layout.fillHeight: true
  324. implicitWidth: Math.min(360, sample.implicitWidth + parent.spacing)
  325. implicitHeight: Math.min(240, sample.implicitHeight + parent.spacing)
  326. color: "white"
  327. border.color: "#999"
  328. TextInput {
  329. id: sample
  330. activeFocusOnTab: true
  331. Accessible.name: text
  332. Accessible.role: Accessible.EditableText
  333. anchors.centerIn: parent
  334. font: content.font
  335. onFocusChanged: if (!focus && sample.text == "") sample.text = content.writingSystemSample
  336. renderType: Settings.isMobile ? Text.QtRendering : Text.NativeRendering
  337. }
  338. }
  339. }
  340. }
  341. RowLayout {
  342. id: buttonRow
  343. Layout.columnSpan: 3
  344. spacing: content.spacing
  345. ComboBox {
  346. id: wsComboBox
  347. function reset() {
  348. if (wsModel.count > 0) {
  349. currentIndex = 0
  350. }
  351. }
  352. textRole: "name"
  353. model: WritingSystemListModel {
  354. id: wsModel
  355. Component.onCompleted: wsComboBox.reset()
  356. }
  357. onCurrentIndexChanged: {
  358. if (currentIndex == -1)
  359. return
  360. content.writingSystem = wsModel.get(currentIndex).name
  361. fontModel.writingSystem = content.writingSystem
  362. content.writingSystemSample = wsModel.get(currentIndex).sample
  363. fontListView.reset()
  364. }
  365. }
  366. Item { Layout.fillWidth: true; } //spacer
  367. Button {
  368. text: qsTr("Cancel")
  369. onClicked: root.reject()
  370. }
  371. Button {
  372. text: qsTr("OK")
  373. onClicked: {
  374. content.updateUponAccepted()
  375. }
  376. }
  377. }
  378. }
  379. }
  380. }