SettingsPanel.qml 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. import QtQml 2.15
  2. import QtQuick 2.15
  3. import QtQuick.Controls 2.15
  4. import QtQuick.Layouts 1.3
  5. import StandardOfIron 1.0
  6. Item {
  7. id: root
  8. signal cancelled()
  9. anchors.fill: parent
  10. z: 25
  11. Keys.onPressed: function(event) {
  12. if (event.key === Qt.Key_Escape) {
  13. root.cancelled();
  14. event.accepted = true;
  15. }
  16. }
  17. Component.onCompleted: {
  18. forceActiveFocus();
  19. }
  20. Rectangle {
  21. anchors.fill: parent
  22. color: Theme.dim
  23. }
  24. Rectangle {
  25. id: container
  26. width: Math.min(parent.width * 0.6, 700)
  27. height: Math.min(parent.height * 0.8, 600)
  28. anchors.centerIn: parent
  29. radius: Theme.radiusPanel
  30. color: Theme.panelBase
  31. border.color: Theme.panelBr
  32. border.width: 1
  33. opacity: 0.98
  34. ColumnLayout {
  35. anchors.fill: parent
  36. anchors.margins: Theme.spacingXLarge
  37. spacing: Theme.spacingLarge
  38. RowLayout {
  39. Layout.fillWidth: true
  40. spacing: Theme.spacingMedium
  41. Label {
  42. text: qsTr("Settings")
  43. color: Theme.textMain
  44. font.pointSize: Theme.fontSizeHero
  45. font.bold: true
  46. Layout.fillWidth: true
  47. }
  48. StyledButton {
  49. text: qsTr("Close")
  50. buttonStyle: "secondary"
  51. onClicked: root.cancelled()
  52. }
  53. }
  54. Rectangle {
  55. Layout.fillWidth: true
  56. Layout.preferredHeight: 1
  57. color: Theme.border
  58. }
  59. ScrollView {
  60. Layout.fillWidth: true
  61. Layout.fillHeight: true
  62. clip: true
  63. ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
  64. ScrollBar.vertical.policy: ScrollBar.AsNeeded
  65. ColumnLayout {
  66. width: container.width - Theme.spacingXLarge * 2
  67. spacing: Theme.spacingLarge
  68. ColumnLayout {
  69. Layout.fillWidth: true
  70. spacing: Theme.spacingMedium
  71. Label {
  72. text: qsTr("Audio Settings")
  73. color: Theme.textMain
  74. font.pointSize: Theme.fontSizeLarge
  75. font.bold: true
  76. }
  77. Rectangle {
  78. Layout.fillWidth: true
  79. Layout.preferredHeight: 2
  80. color: Theme.border
  81. opacity: 0.5
  82. }
  83. GridLayout {
  84. Layout.fillWidth: true
  85. columns: 2
  86. rowSpacing: Theme.spacingMedium
  87. columnSpacing: Theme.spacingMedium
  88. Label {
  89. text: qsTr("Master Volume:")
  90. color: Theme.textSub
  91. font.pointSize: Theme.fontSizeMedium
  92. }
  93. RowLayout {
  94. Layout.fillWidth: true
  95. spacing: Theme.spacingSmall
  96. Slider {
  97. id: masterVolumeSlider
  98. Layout.fillWidth: true
  99. from: 0
  100. to: 100
  101. value: 100
  102. stepSize: 1
  103. onValueChanged: {
  104. if (typeof game !== 'undefined' && game.audioSystem)
  105. game.audioSystem.setMasterVolume(value / 100);
  106. }
  107. }
  108. Label {
  109. text: Math.round(masterVolumeSlider.value) + "%"
  110. color: Theme.textSub
  111. font.pointSize: Theme.fontSizeMedium
  112. Layout.minimumWidth: 45
  113. }
  114. }
  115. Label {
  116. text: qsTr("Music Volume:")
  117. color: Theme.textSub
  118. font.pointSize: Theme.fontSizeMedium
  119. }
  120. RowLayout {
  121. Layout.fillWidth: true
  122. spacing: Theme.spacingSmall
  123. Slider {
  124. id: musicVolumeSlider
  125. Layout.fillWidth: true
  126. from: 0
  127. to: 100
  128. value: 100
  129. stepSize: 1
  130. onValueChanged: {
  131. if (typeof game !== 'undefined' && game.audioSystem)
  132. game.audioSystem.setMusicVolume(value / 100);
  133. }
  134. }
  135. Label {
  136. text: Math.round(musicVolumeSlider.value) + "%"
  137. color: Theme.textSub
  138. font.pointSize: Theme.fontSizeMedium
  139. Layout.minimumWidth: 45
  140. }
  141. }
  142. Label {
  143. text: qsTr("SFX Volume:")
  144. color: Theme.textSub
  145. font.pointSize: Theme.fontSizeMedium
  146. }
  147. RowLayout {
  148. Layout.fillWidth: true
  149. spacing: Theme.spacingSmall
  150. Slider {
  151. id: sfxVolumeSlider
  152. Layout.fillWidth: true
  153. from: 0
  154. to: 100
  155. value: 100
  156. stepSize: 1
  157. onValueChanged: {
  158. if (typeof game !== 'undefined' && game.audioSystem)
  159. game.audioSystem.setSoundVolume(value / 100);
  160. }
  161. }
  162. Label {
  163. text: Math.round(sfxVolumeSlider.value) + "%"
  164. color: Theme.textSub
  165. font.pointSize: Theme.fontSizeMedium
  166. Layout.minimumWidth: 45
  167. }
  168. }
  169. Label {
  170. text: qsTr("Voice Volume:")
  171. color: Theme.textSub
  172. font.pointSize: Theme.fontSizeMedium
  173. }
  174. RowLayout {
  175. Layout.fillWidth: true
  176. spacing: Theme.spacingSmall
  177. Slider {
  178. id: voiceVolumeSlider
  179. Layout.fillWidth: true
  180. from: 0
  181. to: 100
  182. value: 100
  183. stepSize: 1
  184. onValueChanged: {
  185. if (typeof game !== 'undefined' && game.audioSystem)
  186. game.audioSystem.setVoiceVolume(value / 100);
  187. }
  188. }
  189. Label {
  190. text: Math.round(voiceVolumeSlider.value) + "%"
  191. color: Theme.textSub
  192. font.pointSize: Theme.fontSizeMedium
  193. Layout.minimumWidth: 45
  194. }
  195. }
  196. }
  197. }
  198. Rectangle {
  199. Layout.fillWidth: true
  200. Layout.preferredHeight: 1
  201. color: Theme.border
  202. }
  203. ColumnLayout {
  204. Layout.fillWidth: true
  205. spacing: Theme.spacingMedium
  206. Label {
  207. text: qsTr("Graphics Settings")
  208. color: Theme.textMain
  209. font.pointSize: Theme.fontSizeLarge
  210. font.bold: true
  211. }
  212. Rectangle {
  213. Layout.fillWidth: true
  214. Layout.preferredHeight: 2
  215. color: Theme.border
  216. opacity: 0.5
  217. }
  218. GridLayout {
  219. Layout.fillWidth: true
  220. columns: 2
  221. rowSpacing: Theme.spacingMedium
  222. columnSpacing: Theme.spacingMedium
  223. Label {
  224. text: qsTr("Graphics Quality:")
  225. color: Theme.textSub
  226. font.pointSize: Theme.fontSizeMedium
  227. }
  228. StyledComboBox {
  229. id: graphicsQualityComboBox
  230. Layout.fillWidth: true
  231. model: typeof graphicsSettings !== 'undefined' ? graphicsSettings.quality_options : ["Low", "Medium", "High", "Ultra"]
  232. currentIndex: typeof graphicsSettings !== 'undefined' ? graphicsSettings.quality_level : 1
  233. onActivated: function(index) {
  234. if (typeof graphicsSettings !== 'undefined')
  235. graphicsSettings.quality_level = index;
  236. }
  237. }
  238. Label {
  239. text: typeof graphicsSettings !== 'undefined' ? graphicsSettings.get_quality_description() : ""
  240. color: Theme.textSub
  241. font.pointSize: Theme.fontSizeSmall
  242. opacity: 0.7
  243. wrapMode: Text.WordWrap
  244. Layout.columnSpan: 2
  245. Layout.fillWidth: true
  246. }
  247. }
  248. }
  249. Rectangle {
  250. Layout.fillWidth: true
  251. Layout.preferredHeight: 1
  252. color: Theme.border
  253. }
  254. ColumnLayout {
  255. Layout.fillWidth: true
  256. spacing: Theme.spacingMedium
  257. Label {
  258. text: qsTr("Language")
  259. color: Theme.textMain
  260. font.pointSize: Theme.fontSizeLarge
  261. font.bold: true
  262. }
  263. Rectangle {
  264. Layout.fillWidth: true
  265. Layout.preferredHeight: 2
  266. color: Theme.border
  267. opacity: 0.5
  268. }
  269. GridLayout {
  270. Layout.fillWidth: true
  271. columns: 2
  272. rowSpacing: Theme.spacingMedium
  273. columnSpacing: Theme.spacingMedium
  274. Label {
  275. text: qsTr("Select Language:")
  276. color: Theme.textSub
  277. font.pointSize: Theme.fontSizeMedium
  278. }
  279. StyledComboBox {
  280. id: languageComboBox
  281. Layout.fillWidth: true
  282. model: typeof languageManager !== 'undefined' ? languageManager.availableLanguages : []
  283. currentIndex: {
  284. if (typeof languageManager === 'undefined')
  285. return 0;
  286. var idx = languageManager.availableLanguages.indexOf(languageManager.currentLanguage);
  287. return idx >= 0 ? idx : 0;
  288. }
  289. displayText: {
  290. if (typeof languageManager === 'undefined' || !currentText)
  291. return "";
  292. return languageManager.languageDisplayName(currentText);
  293. }
  294. onActivated: function(index) {
  295. if (typeof languageManager !== 'undefined' && currentText)
  296. languageManager.setLanguage(currentText);
  297. }
  298. delegateText: function(data) {
  299. return typeof languageManager !== 'undefined' ? languageManager.languageDisplayName(data) : data;
  300. }
  301. }
  302. Label {
  303. text: qsTr("Language changes apply immediately")
  304. color: Theme.textSub
  305. font.pointSize: Theme.fontSizeSmall
  306. opacity: 0.7
  307. Layout.columnSpan: 2
  308. }
  309. }
  310. }
  311. Rectangle {
  312. Layout.fillWidth: true
  313. Layout.preferredHeight: 1
  314. color: Theme.border
  315. }
  316. ColumnLayout {
  317. Layout.fillWidth: true
  318. spacing: Theme.spacingMedium
  319. Label {
  320. text: qsTr("About")
  321. color: Theme.textMain
  322. font.pointSize: Theme.fontSizeLarge
  323. font.bold: true
  324. }
  325. Rectangle {
  326. Layout.fillWidth: true
  327. Layout.preferredHeight: 2
  328. color: Theme.border
  329. opacity: 0.5
  330. }
  331. ColumnLayout {
  332. Layout.fillWidth: true
  333. spacing: Theme.spacingSmall
  334. Label {
  335. text: qsTr("Standard of Iron - RTS Game")
  336. color: Theme.textMain
  337. font.pointSize: Theme.fontSizeMedium
  338. font.bold: true
  339. }
  340. Label {
  341. text: qsTr("Version 1.0.0")
  342. color: Theme.textSub
  343. font.pointSize: Theme.fontSizeSmall
  344. }
  345. Rectangle {
  346. Layout.fillWidth: true
  347. Layout.preferredHeight: 1
  348. color: Theme.border
  349. opacity: 0.3
  350. Layout.topMargin: Theme.spacingSmall
  351. Layout.bottomMargin: Theme.spacingSmall
  352. }
  353. Label {
  354. text: qsTr("Third-Party Software")
  355. color: Theme.textMain
  356. font.pointSize: Theme.fontSizeMedium
  357. font.bold: true
  358. }
  359. Label {
  360. text: qsTr("This game uses the Qt framework, licensed under the GNU Lesser General Public License v3 (LGPL v3).")
  361. color: Theme.textSub
  362. font.pointSize: Theme.fontSizeSmall
  363. wrapMode: Text.WordWrap
  364. Layout.fillWidth: true
  365. }
  366. Label {
  367. text: qsTr("Qt is dynamically linked, allowing you to replace Qt libraries with your own versions.")
  368. color: Theme.textSub
  369. font.pointSize: Theme.fontSizeSmall
  370. wrapMode: Text.WordWrap
  371. Layout.fillWidth: true
  372. }
  373. Label {
  374. text: "<a href='https://www.gnu.org/licenses/lgpl-3.0.html'>LGPL v3 License</a> | <a href='https://www.qt.io'>Qt Website</a>"
  375. color: Theme.textSub
  376. font.pointSize: Theme.fontSizeSmall
  377. textFormat: Text.RichText
  378. onLinkActivated: function(link) {
  379. Qt.openUrlExternally(link);
  380. }
  381. MouseArea {
  382. anchors.fill: parent
  383. acceptedButtons: Qt.NoButton
  384. cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
  385. }
  386. }
  387. }
  388. }
  389. }
  390. }
  391. }
  392. }
  393. }