ModernPlaylistPage.qml 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. import QtQuick 2.15
  2. import QtQuick.Controls 2.15
  3. import QtQuick.Layouts 1.15
  4. import DuneWeaver 1.0
  5. import "../components"
  6. import "../components" as Components
  7. Page {
  8. id: page
  9. property var backend: null
  10. property var stackView: null
  11. property var mainWindow: null
  12. // State management for navigation
  13. property bool showingPlaylistDetail: false
  14. property string selectedPlaylist: ""
  15. property var selectedPlaylistData: null
  16. property var currentPlaylistPatterns: []
  17. // Playlist execution settings
  18. property real pauseTime: backend ? backend.pauseBetweenPatterns : 0
  19. property string clearPattern: "adaptive"
  20. property string runMode: "single"
  21. property bool shuffle: false
  22. PlaylistModel {
  23. id: playlistModel
  24. }
  25. // Update patterns when playlist selection changes
  26. onSelectedPlaylistChanged: {
  27. if (selectedPlaylist) {
  28. currentPlaylistPatterns = playlistModel.getPatternsForPlaylist(selectedPlaylist)
  29. console.log("Loaded patterns for", selectedPlaylist + ":", currentPlaylistPatterns)
  30. } else {
  31. currentPlaylistPatterns = []
  32. }
  33. }
  34. // Debug playlist loading
  35. Component.onCompleted: {
  36. console.log("ModernPlaylistPage completed, playlist count:", playlistModel.rowCount())
  37. console.log("showingPlaylistDetail:", showingPlaylistDetail)
  38. }
  39. // Function to navigate to playlist detail
  40. function showPlaylistDetail(playlistName, playlistData) {
  41. selectedPlaylist = playlistName
  42. selectedPlaylistData = playlistData
  43. showingPlaylistDetail = true
  44. }
  45. // Function to go back to playlist list
  46. function showPlaylistList() {
  47. showingPlaylistDetail = false
  48. selectedPlaylist = ""
  49. selectedPlaylistData = null
  50. }
  51. Rectangle {
  52. anchors.fill: parent
  53. color: Components.ThemeManager.backgroundColor
  54. }
  55. // Playlist List View (shown by default)
  56. Rectangle {
  57. id: playlistListView
  58. anchors.fill: parent
  59. color: Components.ThemeManager.backgroundColor
  60. visible: !showingPlaylistDetail
  61. ColumnLayout {
  62. anchors.fill: parent
  63. spacing: 0
  64. // Header
  65. Rectangle {
  66. Layout.fillWidth: true
  67. Layout.preferredHeight: 50
  68. color: Components.ThemeManager.surfaceColor
  69. // Bottom border
  70. Rectangle {
  71. anchors.bottom: parent.bottom
  72. width: parent.width
  73. height: 1
  74. color: Components.ThemeManager.borderColor
  75. }
  76. RowLayout {
  77. anchors.fill: parent
  78. anchors.leftMargin: 15
  79. anchors.rightMargin: 10
  80. ConnectionStatus {
  81. backend: page.backend
  82. Layout.rightMargin: 8
  83. }
  84. Label {
  85. text: "Playlists"
  86. font.pixelSize: 18
  87. font.bold: true
  88. color: Components.ThemeManager.textPrimary
  89. }
  90. Label {
  91. text: playlistModel.rowCount() + " playlists"
  92. font.pixelSize: 12
  93. color: Components.ThemeManager.textTertiary
  94. }
  95. Item {
  96. Layout.fillWidth: true
  97. }
  98. }
  99. }
  100. // Playlist List
  101. ListView {
  102. Layout.fillWidth: true
  103. Layout.fillHeight: true
  104. Layout.margins: 15
  105. model: playlistModel
  106. spacing: 12
  107. clip: true
  108. ScrollBar.vertical: ScrollBar {
  109. active: true
  110. policy: ScrollBar.AsNeeded
  111. }
  112. delegate: Rectangle {
  113. width: ListView.view.width
  114. height: 80
  115. color: Components.ThemeManager.surfaceColor
  116. radius: 12
  117. border.color: Components.ThemeManager.borderColor
  118. border.width: 1
  119. // Press animation
  120. scale: mouseArea.pressed ? 0.98 : 1.0
  121. Behavior on scale {
  122. NumberAnimation { duration: 100; easing.type: Easing.OutQuad }
  123. }
  124. RowLayout {
  125. anchors.fill: parent
  126. anchors.margins: 20
  127. spacing: 15
  128. // Icon
  129. Rectangle {
  130. Layout.preferredWidth: 40
  131. Layout.preferredHeight: 40
  132. radius: 20
  133. color: Components.ThemeManager.darkMode ? "#1e3a5f" : "#e3f2fd"
  134. Text {
  135. anchors.centerIn: parent
  136. text: "♪"
  137. font.pixelSize: 18
  138. color: "#2196F3"
  139. }
  140. }
  141. // Playlist info
  142. Column {
  143. Layout.fillWidth: true
  144. spacing: 4
  145. Label {
  146. text: model.name
  147. font.pixelSize: 16
  148. font.bold: true
  149. color: Components.ThemeManager.textPrimary
  150. elide: Text.ElideRight
  151. width: parent.width
  152. }
  153. Label {
  154. text: model.itemCount + " patterns"
  155. color: Components.ThemeManager.textSecondary
  156. font.pixelSize: 12
  157. }
  158. }
  159. // Arrow
  160. Text {
  161. text: "▶"
  162. font.pixelSize: 16
  163. color: Components.ThemeManager.textTertiary
  164. }
  165. }
  166. MouseArea {
  167. id: mouseArea
  168. anchors.fill: parent
  169. onClicked: {
  170. showPlaylistDetail(model.name, model)
  171. }
  172. }
  173. }
  174. // Empty state
  175. Rectangle {
  176. anchors.fill: parent
  177. color: "transparent"
  178. visible: playlistModel.rowCount() === 0
  179. Column {
  180. anchors.centerIn: parent
  181. spacing: 15
  182. Text {
  183. text: "♪"
  184. color: Components.ThemeManager.placeholderText
  185. font.pixelSize: 64
  186. anchors.horizontalCenter: parent.horizontalCenter
  187. }
  188. Label {
  189. text: "No playlists found"
  190. anchors.horizontalCenter: parent.horizontalCenter
  191. color: Components.ThemeManager.textSecondary
  192. font.pixelSize: 18
  193. }
  194. Label {
  195. text: "Create playlists to organize\\nyour pattern collections"
  196. anchors.horizontalCenter: parent.horizontalCenter
  197. color: Components.ThemeManager.textTertiary
  198. font.pixelSize: 14
  199. horizontalAlignment: Text.AlignHCenter
  200. }
  201. }
  202. }
  203. }
  204. }
  205. }
  206. // Playlist Detail View (shown when a playlist is selected)
  207. Rectangle {
  208. id: playlistDetailView
  209. anchors.fill: parent
  210. color: Components.ThemeManager.backgroundColor
  211. visible: showingPlaylistDetail
  212. ColumnLayout {
  213. anchors.fill: parent
  214. spacing: 0
  215. // Header with back button
  216. Rectangle {
  217. Layout.fillWidth: true
  218. Layout.preferredHeight: 50
  219. color: Components.ThemeManager.surfaceColor
  220. // Bottom border
  221. Rectangle {
  222. anchors.bottom: parent.bottom
  223. width: parent.width
  224. height: 1
  225. color: Components.ThemeManager.borderColor
  226. }
  227. RowLayout {
  228. anchors.fill: parent
  229. anchors.leftMargin: 15
  230. anchors.rightMargin: 10
  231. spacing: 10
  232. ConnectionStatus {
  233. backend: page.backend
  234. Layout.rightMargin: 8
  235. }
  236. Button {
  237. text: "← Back"
  238. font.pixelSize: 14
  239. flat: true
  240. onClicked: showPlaylistList()
  241. contentItem: Text {
  242. text: parent.text
  243. font: parent.font
  244. color: Components.ThemeManager.textPrimary
  245. horizontalAlignment: Text.AlignHCenter
  246. verticalAlignment: Text.AlignVCenter
  247. }
  248. }
  249. Label {
  250. text: selectedPlaylist
  251. font.pixelSize: 18
  252. font.bold: true
  253. color: Components.ThemeManager.textPrimary
  254. Layout.fillWidth: true
  255. elide: Text.ElideRight
  256. }
  257. Label {
  258. text: currentPlaylistPatterns.length + " patterns"
  259. font.pixelSize: 12
  260. color: Components.ThemeManager.textTertiary
  261. }
  262. }
  263. }
  264. // Content - Pattern list on left, controls on right
  265. Item {
  266. Layout.fillWidth: true
  267. Layout.fillHeight: true
  268. Row {
  269. anchors.fill: parent
  270. spacing: 0
  271. // Left side - Pattern List (40% of width)
  272. Rectangle {
  273. width: parent.width * 0.4
  274. height: parent.height
  275. color: Components.ThemeManager.surfaceColor
  276. ColumnLayout {
  277. anchors.fill: parent
  278. anchors.margins: 15
  279. spacing: 10
  280. Label {
  281. text: "Patterns"
  282. font.pixelSize: 14
  283. font.bold: true
  284. color: Components.ThemeManager.textPrimary
  285. }
  286. ScrollView {
  287. Layout.fillWidth: true
  288. Layout.fillHeight: true
  289. clip: true
  290. ListView {
  291. id: patternListView
  292. width: parent.width
  293. model: currentPlaylistPatterns
  294. spacing: 6
  295. delegate: Rectangle {
  296. width: patternListView.width
  297. height: 35
  298. color: index % 2 === 0 ? Components.ThemeManager.cardColor : Components.ThemeManager.surfaceColor
  299. radius: 6
  300. border.color: Components.ThemeManager.borderColor
  301. border.width: 1
  302. RowLayout {
  303. anchors.fill: parent
  304. anchors.margins: 10
  305. spacing: 8
  306. Label {
  307. text: (index + 1) + "."
  308. font.pixelSize: 11
  309. color: Components.ThemeManager.textSecondary
  310. Layout.preferredWidth: 25
  311. }
  312. Label {
  313. text: modelData
  314. font.pixelSize: 11
  315. color: Components.ThemeManager.textPrimary
  316. Layout.fillWidth: true
  317. elide: Text.ElideRight
  318. }
  319. }
  320. }
  321. }
  322. }
  323. // Empty playlist message
  324. Rectangle {
  325. Layout.fillWidth: true
  326. Layout.fillHeight: true
  327. color: "transparent"
  328. visible: currentPlaylistPatterns.length === 0
  329. Column {
  330. anchors.centerIn: parent
  331. spacing: 10
  332. Text {
  333. text: "♪"
  334. font.pixelSize: 32
  335. color: Components.ThemeManager.placeholderText
  336. anchors.horizontalCenter: parent.horizontalCenter
  337. }
  338. Label {
  339. text: "Empty playlist"
  340. anchors.horizontalCenter: parent.horizontalCenter
  341. color: Components.ThemeManager.textSecondary
  342. font.pixelSize: 14
  343. }
  344. }
  345. }
  346. }
  347. }
  348. // Divider
  349. Rectangle {
  350. width: 1
  351. height: parent.height
  352. color: Components.ThemeManager.borderColor
  353. }
  354. // Right side - Full height controls (60% of width)
  355. Rectangle {
  356. width: parent.width * 0.6 - 1
  357. height: parent.height
  358. color: Components.ThemeManager.surfaceColor
  359. ColumnLayout {
  360. anchors.fill: parent
  361. anchors.margins: 15
  362. spacing: 15
  363. Label {
  364. text: "Playlist Controls"
  365. font.pixelSize: 16
  366. font.bold: true
  367. color: Components.ThemeManager.textPrimary
  368. }
  369. // Main execution buttons
  370. RowLayout {
  371. Layout.fillWidth: true
  372. spacing: 10
  373. // Play Playlist button
  374. Rectangle {
  375. Layout.fillWidth: true
  376. Layout.preferredHeight: 45
  377. radius: 8
  378. color: playMouseArea.pressed ? "#1e40af" : "#2563eb"
  379. Text {
  380. anchors.centerIn: parent
  381. text: "Play Playlist"
  382. color: "white"
  383. font.pixelSize: 14
  384. font.bold: true
  385. }
  386. MouseArea {
  387. id: playMouseArea
  388. anchors.fill: parent
  389. onClicked: {
  390. if (backend) {
  391. console.log("Playing playlist:", selectedPlaylist, "with settings:", {
  392. pauseTime: pauseTime,
  393. clearPattern: clearPattern,
  394. runMode: runMode,
  395. shuffle: shuffle
  396. })
  397. backend.executePlaylist(selectedPlaylist, pauseTime, clearPattern, runMode, shuffle)
  398. // Navigate to execution page
  399. console.log("🎵 Navigating to execution page after playlist start")
  400. if (mainWindow) {
  401. console.log("🎵 Setting shouldNavigateToExecution = true")
  402. mainWindow.shouldNavigateToExecution = true
  403. } else {
  404. console.log("🎵 ERROR: mainWindow is null, cannot navigate")
  405. }
  406. }
  407. }
  408. }
  409. }
  410. // Shuffle toggle button
  411. Rectangle {
  412. Layout.preferredWidth: 60
  413. Layout.preferredHeight: 45
  414. radius: 8
  415. color: shuffle ? "#2563eb" : "#6b7280"
  416. Text {
  417. anchors.centerIn: parent
  418. text: "⇄"
  419. color: "white"
  420. font.pixelSize: 16
  421. }
  422. MouseArea {
  423. id: shuffleMouseArea
  424. anchors.fill: parent
  425. onClicked: {
  426. shuffle = !shuffle
  427. console.log("Shuffle toggled:", shuffle)
  428. }
  429. }
  430. }
  431. }
  432. // Settings section
  433. Rectangle {
  434. Layout.fillWidth: true
  435. Layout.fillHeight: true
  436. Layout.minimumHeight: 250
  437. radius: 10
  438. color: Components.ThemeManager.cardColor
  439. border.color: Components.ThemeManager.borderColor
  440. border.width: 1
  441. ColumnLayout {
  442. anchors.fill: parent
  443. anchors.margins: 15
  444. spacing: 15
  445. Label {
  446. text: "Settings"
  447. font.pixelSize: 14
  448. font.bold: true
  449. color: Components.ThemeManager.textPrimary
  450. }
  451. // Scrollable settings content
  452. ScrollView {
  453. Layout.fillWidth: true
  454. Layout.fillHeight: true
  455. clip: true
  456. ScrollBar.vertical.policy: ScrollBar.AsNeeded
  457. ColumnLayout {
  458. width: parent.width
  459. spacing: 15
  460. // Run mode
  461. Column {
  462. Layout.fillWidth: true
  463. spacing: 8
  464. Label {
  465. text: "Run Mode:"
  466. font.pixelSize: 12
  467. color: Components.ThemeManager.textSecondary
  468. font.bold: true
  469. }
  470. RowLayout {
  471. width: parent.width
  472. spacing: 15
  473. RadioButton {
  474. id: singleModeRadio
  475. text: "Single"
  476. font.pixelSize: 11
  477. checked: runMode === "single"
  478. onCheckedChanged: {
  479. if (checked) runMode = "single"
  480. }
  481. contentItem: Text {
  482. text: parent.text
  483. font: parent.font
  484. color: Components.ThemeManager.textPrimary
  485. verticalAlignment: Text.AlignVCenter
  486. leftPadding: parent.indicator.width + parent.spacing
  487. }
  488. }
  489. RadioButton {
  490. id: loopModeRadio
  491. text: "Loop"
  492. font.pixelSize: 11
  493. checked: runMode === "loop"
  494. onCheckedChanged: {
  495. if (checked) runMode = "loop"
  496. }
  497. contentItem: Text {
  498. text: parent.text
  499. font: parent.font
  500. color: Components.ThemeManager.textPrimary
  501. verticalAlignment: Text.AlignVCenter
  502. leftPadding: parent.indicator.width + parent.spacing
  503. }
  504. }
  505. }
  506. }
  507. // Pause Between Patterns
  508. Column {
  509. Layout.fillWidth: true
  510. spacing: 15
  511. Label {
  512. text: "Pause between patterns:"
  513. font.pixelSize: 12
  514. color: Components.ThemeManager.textSecondary
  515. font.bold: true
  516. }
  517. // Touch-friendly button row for pause options
  518. RowLayout {
  519. id: pauseGrid
  520. Layout.fillWidth: true
  521. spacing: 8
  522. property string currentSelection: backend ? backend.getCurrentPauseOption() : "0s"
  523. // 0s button
  524. Rectangle {
  525. Layout.preferredWidth: 60
  526. Layout.preferredHeight: 40
  527. color: pauseGrid.currentSelection === "0s" ? Components.ThemeManager.selectedBackground : Components.ThemeManager.buttonBackground
  528. border.color: pauseGrid.currentSelection === "0s" ? Components.ThemeManager.selectedBorder : Components.ThemeManager.buttonBorder
  529. border.width: 2
  530. radius: 8
  531. Label {
  532. anchors.centerIn: parent
  533. text: "0s"
  534. font.pixelSize: 12
  535. font.bold: true
  536. color: pauseGrid.currentSelection === "0s" ? "white" : Components.ThemeManager.textPrimary
  537. }
  538. MouseArea {
  539. anchors.fill: parent
  540. onClicked: {
  541. if (backend) {
  542. backend.setPauseByOption("0s")
  543. pauseGrid.currentSelection = "0s"
  544. pauseTime = 0
  545. }
  546. }
  547. }
  548. }
  549. // 1 min button
  550. Rectangle {
  551. Layout.preferredWidth: 60
  552. Layout.preferredHeight: 40
  553. color: pauseGrid.currentSelection === "1 min" ? Components.ThemeManager.selectedBackground : Components.ThemeManager.buttonBackground
  554. border.color: pauseGrid.currentSelection === "1 min" ? Components.ThemeManager.selectedBorder : Components.ThemeManager.buttonBorder
  555. border.width: 2
  556. radius: 8
  557. Label {
  558. anchors.centerIn: parent
  559. text: "1m"
  560. font.pixelSize: 12
  561. font.bold: true
  562. color: pauseGrid.currentSelection === "1 min" ? "white" : Components.ThemeManager.textPrimary
  563. }
  564. MouseArea {
  565. anchors.fill: parent
  566. onClicked: {
  567. if (backend) {
  568. backend.setPauseByOption("1 min")
  569. pauseGrid.currentSelection = "1 min"
  570. pauseTime = 60
  571. }
  572. }
  573. }
  574. }
  575. // 5 min button
  576. Rectangle {
  577. Layout.preferredWidth: 60
  578. Layout.preferredHeight: 40
  579. color: pauseGrid.currentSelection === "5 min" ? Components.ThemeManager.selectedBackground : Components.ThemeManager.buttonBackground
  580. border.color: pauseGrid.currentSelection === "5 min" ? Components.ThemeManager.selectedBorder : Components.ThemeManager.buttonBorder
  581. border.width: 2
  582. radius: 8
  583. Label {
  584. anchors.centerIn: parent
  585. text: "5m"
  586. font.pixelSize: 12
  587. font.bold: true
  588. color: pauseGrid.currentSelection === "5 min" ? "white" : Components.ThemeManager.textPrimary
  589. }
  590. MouseArea {
  591. anchors.fill: parent
  592. onClicked: {
  593. if (backend) {
  594. backend.setPauseByOption("5 min")
  595. pauseGrid.currentSelection = "5 min"
  596. pauseTime = 300
  597. }
  598. }
  599. }
  600. }
  601. // 15 min button
  602. Rectangle {
  603. Layout.preferredWidth: 60
  604. Layout.preferredHeight: 40
  605. color: pauseGrid.currentSelection === "15 min" ? Components.ThemeManager.selectedBackground : Components.ThemeManager.buttonBackground
  606. border.color: pauseGrid.currentSelection === "15 min" ? Components.ThemeManager.selectedBorder : Components.ThemeManager.buttonBorder
  607. border.width: 2
  608. radius: 8
  609. Label {
  610. anchors.centerIn: parent
  611. text: "15m"
  612. font.pixelSize: 12
  613. font.bold: true
  614. color: pauseGrid.currentSelection === "15 min" ? "white" : Components.ThemeManager.textPrimary
  615. }
  616. MouseArea {
  617. anchors.fill: parent
  618. onClicked: {
  619. if (backend) {
  620. backend.setPauseByOption("15 min")
  621. pauseGrid.currentSelection = "15 min"
  622. pauseTime = 900
  623. }
  624. }
  625. }
  626. }
  627. // 30 min button
  628. Rectangle {
  629. Layout.preferredWidth: 60
  630. Layout.preferredHeight: 40
  631. color: pauseGrid.currentSelection === "30 min" ? Components.ThemeManager.selectedBackground : Components.ThemeManager.buttonBackground
  632. border.color: pauseGrid.currentSelection === "30 min" ? Components.ThemeManager.selectedBorder : Components.ThemeManager.buttonBorder
  633. border.width: 2
  634. radius: 8
  635. Label {
  636. anchors.centerIn: parent
  637. text: "30m"
  638. font.pixelSize: 12
  639. font.bold: true
  640. color: pauseGrid.currentSelection === "30 min" ? "white" : Components.ThemeManager.textPrimary
  641. }
  642. MouseArea {
  643. anchors.fill: parent
  644. onClicked: {
  645. if (backend) {
  646. backend.setPauseByOption("30 min")
  647. pauseGrid.currentSelection = "30 min"
  648. pauseTime = 1800
  649. }
  650. }
  651. }
  652. }
  653. // 1 hour button
  654. Rectangle {
  655. Layout.preferredWidth: 60
  656. Layout.preferredHeight: 40
  657. color: pauseGrid.currentSelection === "1 hour" ? Components.ThemeManager.selectedBackground : Components.ThemeManager.buttonBackground
  658. border.color: pauseGrid.currentSelection === "1 hour" ? Components.ThemeManager.selectedBorder : Components.ThemeManager.buttonBorder
  659. border.width: 2
  660. radius: 8
  661. Label {
  662. anchors.centerIn: parent
  663. text: "1h"
  664. font.pixelSize: 12
  665. font.bold: true
  666. color: pauseGrid.currentSelection === "1 hour" ? "white" : Components.ThemeManager.textPrimary
  667. }
  668. MouseArea {
  669. anchors.fill: parent
  670. onClicked: {
  671. if (backend) {
  672. backend.setPauseByOption("1 hour")
  673. pauseGrid.currentSelection = "1 hour"
  674. pauseTime = 3600
  675. }
  676. }
  677. }
  678. }
  679. // Update selection when backend changes
  680. Connections {
  681. target: backend
  682. function onPauseBetweenPatternsChanged(pause) {
  683. if (backend) {
  684. pauseGrid.currentSelection = backend.getCurrentPauseOption()
  685. pauseTime = backend.pauseBetweenPatterns
  686. }
  687. }
  688. }
  689. }
  690. }
  691. // Clear pattern
  692. Column {
  693. Layout.fillWidth: true
  694. spacing: 8
  695. Label {
  696. text: "Clear Pattern:"
  697. font.pixelSize: 12
  698. color: Components.ThemeManager.textSecondary
  699. font.bold: true
  700. }
  701. GridLayout {
  702. width: parent.width
  703. columns: 2
  704. columnSpacing: 10
  705. rowSpacing: 5
  706. RadioButton {
  707. text: "Adaptive"
  708. font.pixelSize: 11
  709. checked: clearPattern === "adaptive"
  710. onCheckedChanged: {
  711. if (checked) clearPattern = "adaptive"
  712. }
  713. contentItem: Text {
  714. text: parent.text
  715. font: parent.font
  716. color: Components.ThemeManager.textPrimary
  717. verticalAlignment: Text.AlignVCenter
  718. leftPadding: parent.indicator.width + parent.spacing
  719. }
  720. }
  721. RadioButton {
  722. text: "Clear Center"
  723. font.pixelSize: 11
  724. checked: clearPattern === "clear_center"
  725. onCheckedChanged: {
  726. if (checked) clearPattern = "clear_center"
  727. }
  728. contentItem: Text {
  729. text: parent.text
  730. font: parent.font
  731. color: Components.ThemeManager.textPrimary
  732. verticalAlignment: Text.AlignVCenter
  733. leftPadding: parent.indicator.width + parent.spacing
  734. }
  735. }
  736. RadioButton {
  737. text: "Clear Edge"
  738. font.pixelSize: 11
  739. checked: clearPattern === "clear_perimeter"
  740. onCheckedChanged: {
  741. if (checked) clearPattern = "clear_perimeter"
  742. }
  743. contentItem: Text {
  744. text: parent.text
  745. font: parent.font
  746. color: Components.ThemeManager.textPrimary
  747. verticalAlignment: Text.AlignVCenter
  748. leftPadding: parent.indicator.width + parent.spacing
  749. }
  750. }
  751. RadioButton {
  752. text: "None"
  753. font.pixelSize: 11
  754. checked: clearPattern === "none"
  755. onCheckedChanged: {
  756. if (checked) clearPattern = "none"
  757. }
  758. contentItem: Text {
  759. text: parent.text
  760. font: parent.font
  761. color: Components.ThemeManager.textPrimary
  762. verticalAlignment: Text.AlignVCenter
  763. leftPadding: parent.indicator.width + parent.spacing
  764. }
  765. }
  766. }
  767. }
  768. }
  769. }
  770. }
  771. }
  772. }
  773. }
  774. }
  775. }
  776. }
  777. }
  778. }