flea-qml 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (637) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +511 -2
  3. package/THIRD-PARTY-NOTICES.md +29 -0
  4. package/demos/App.java +5 -0
  5. package/demos/Dockerfile +4 -0
  6. package/demos/Main.kt +3 -0
  7. package/demos/Program.cs +1 -0
  8. package/demos/README.md +12 -0
  9. package/demos/app.dart +3 -0
  10. package/demos/app.deb +0 -0
  11. package/demos/app.js +1 -0
  12. package/demos/backup.tar +0 -0
  13. package/demos/budget.xlsx +0 -0
  14. package/demos/build.sh +2 -0
  15. package/demos/bundle.zip +0 -0
  16. package/demos/clip.mp4 +0 -0
  17. package/demos/data.sqlite +0 -0
  18. package/demos/disk.iso +0 -0
  19. package/demos/engine.cpp +5 -0
  20. package/demos/firmware.bin +0 -0
  21. package/demos/flake.nix +4 -0
  22. package/demos/folder/inside.txt +1 -0
  23. package/demos/font.ttf +0 -0
  24. package/demos/index.html +5 -0
  25. package/demos/index.php +2 -0
  26. package/demos/init.lua +1 -0
  27. package/demos/letter.docx +0 -0
  28. package/demos/lib.rs +3 -0
  29. package/demos/main.c +6 -0
  30. package/demos/main.h +3 -0
  31. package/demos/math-and-diagrams.md +200 -0
  32. package/demos/notes.tar.gz +0 -0
  33. package/demos/notes.txt +3 -0
  34. package/demos/photo.png +0 -0
  35. package/demos/program +2 -0
  36. package/demos/report.pdf +32 -0
  37. package/demos/script.py +1 -0
  38. package/demos/server.go +7 -0
  39. package/demos/settings.json +4 -0
  40. package/demos/slides.pptx +0 -0
  41. package/demos/song.mp3 +0 -0
  42. package/demos/style.css +4 -0
  43. package/demos/tool.rb +1 -0
  44. package/demos/types.ts +2 -0
  45. package/docs/pele.md +23 -0
  46. package/docs/protocol.md +3420 -0
  47. package/docs/temml.md +63 -0
  48. package/index.js +107 -0
  49. package/package.json +34 -4
  50. package/src/archive.js +407 -0
  51. package/src/archiveops.js +728 -0
  52. package/src/backend.js +369 -0
  53. package/src/bulkrename.js +95 -0
  54. package/src/clip-host.js +76 -0
  55. package/src/clip.js +462 -0
  56. package/src/code.js +168 -0
  57. package/src/compare.js +74 -0
  58. package/src/create.js +128 -0
  59. package/src/dirsize.js +147 -0
  60. package/src/figure-svg.js +530 -0
  61. package/src/figure-thread.js +23 -0
  62. package/src/figure.js +132 -0
  63. package/src/find.js +55 -0
  64. package/src/flea.js +39 -0
  65. package/src/fsinfo.js +39 -0
  66. package/src/highlight.js +141 -0
  67. package/src/html.js +52 -0
  68. package/src/kinds.js +89 -0
  69. package/src/listing.js +130 -0
  70. package/src/markdown-html.js +317 -0
  71. package/src/mathml.js +186 -0
  72. package/src/menu.js +180 -0
  73. package/src/meta.js +135 -0
  74. package/src/office.js +810 -0
  75. package/src/order.js +100 -0
  76. package/src/peek.js +49 -0
  77. package/src/pele-wrapper.js +695 -0
  78. package/src/permissions.js +180 -0
  79. package/src/places.js +313 -0
  80. package/src/preview-language.js +10 -0
  81. package/src/terminal-server.js +95 -0
  82. package/src/terminal-shell.js +26 -0
  83. package/src/transfer.js +669 -0
  84. package/src/trash-record.js +41 -0
  85. package/src/trash.js +210 -0
  86. package/src/trashbrowse.js +327 -0
  87. package/src/uistate.js +393 -0
  88. package/src/uistore.js +168 -0
  89. package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
  90. package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
  91. package/src/vendor/LICENSES/MIT-katex.txt +21 -0
  92. package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
  93. package/src/vendor/LICENSES/MIT-pele.txt +40 -0
  94. package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
  95. package/src/vendor/LICENSES/MIT-temml.txt +21 -0
  96. package/src/vendor/pele.js +145 -0
  97. package/src/vendor/temml.mjs +14708 -0
  98. package/src/watch.js +98 -0
  99. package/src/wayland/client.js +109 -0
  100. package/src/wayland/protocol.js +55 -0
  101. package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
  102. package/src/wayland/protocols/wayland.xml +3248 -0
  103. package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
  104. package/src/wayland/resource-io.js +6 -0
  105. package/src/wayland/socket-discovery.js +26 -0
  106. package/src/wayland/transport-posix.js +120 -0
  107. package/src/wayland/transport-win32.js +11 -0
  108. package/src/wayland/transport.js +3 -0
  109. package/src/wayland/win32-resources.js +80 -0
  110. package/src/wayland/win32-wire.js +62 -0
  111. package/test/archive.test.js +80 -0
  112. package/test/bench-markdown-scroll.mjs +190 -0
  113. package/test/clip-host.test.js +113 -0
  114. package/test/code-preview.test.js +35 -0
  115. package/test/compare-ui-paths.test.js +24 -0
  116. package/test/compare.test.js +54 -0
  117. package/test/delete-trash.test.js +67 -0
  118. package/test/dirsize.test.js +138 -0
  119. package/test/file-ops.test.js +307 -0
  120. package/test/file-url.test.js +24 -0
  121. package/test/find-contents.test.js +161 -0
  122. package/test/find-input.test.js +66 -0
  123. package/test/fixtures/pele-parity.json +1006 -0
  124. package/test/highlight-launcher.test.js +35 -0
  125. package/test/html-preview.test.js +22 -0
  126. package/test/input.test.js +15 -0
  127. package/test/keymap.test.js +26 -0
  128. package/test/language-icons.test.js +36 -0
  129. package/test/launcher.test.js +51 -0
  130. package/test/manual-archive-here-ui.mjs +47 -0
  131. package/test/manual-code-scroll.mjs +28 -0
  132. package/test/manual-column-scroll.mjs +24 -0
  133. package/test/manual-compare-ui.mjs +20 -0
  134. package/test/manual-find-status.mjs +37 -0
  135. package/test/manual-folder-focus.mjs +63 -0
  136. package/test/manual-html-security.mjs +23 -0
  137. package/test/manual-html-ui.mjs +30 -0
  138. package/test/manual-syntax-preview.mjs +26 -0
  139. package/test/manual-terminal-lifecycle.mjs +42 -0
  140. package/test/manual-terminal-navigation.mjs +48 -0
  141. package/test/manual-terminal-ui.mjs +47 -0
  142. package/test/manual-trash-ui.mjs +86 -0
  143. package/test/markdown-diagrams.test.js +93 -0
  144. package/test/markdown-html.test.js +105 -0
  145. package/test/mathml.test.js +92 -0
  146. package/test/menu-transfer.test.js +57 -0
  147. package/test/office-preview.test.js +154 -0
  148. package/test/pele-parity.test.js +28 -0
  149. package/test/places.test.js +134 -0
  150. package/test/preview-keys.test.js +60 -0
  151. package/test/preview-language.test.js +22 -0
  152. package/test/status-filename.test.js +20 -0
  153. package/test/transfer-replace-merge.test.js +187 -0
  154. package/test/trash-address.test.js +23 -0
  155. package/test/trash-view.test.js +37 -0
  156. package/test/trashbrowse.test.js +135 -0
  157. package/ui/AboutFacts.qml +78 -0
  158. package/ui/ArchiveCards.qml +95 -0
  159. package/ui/ArchiveCompressDialog.qml +378 -0
  160. package/ui/ArchiveHereConfirm.qml +127 -0
  161. package/ui/ArchivePasswordDialog.qml +257 -0
  162. package/ui/Backend.qml +775 -0
  163. package/ui/BulkOldNames.qml +47 -0
  164. package/ui/BulkRenameDialog.qml +380 -0
  165. package/ui/CardFrame.qml +67 -0
  166. package/ui/CardScroll.qml +79 -0
  167. package/ui/CheckBox.qml +73 -0
  168. package/ui/ChromeBar.qml +360 -0
  169. package/ui/ChromeButton.qml +131 -0
  170. package/ui/ChromeModes.qml +43 -0
  171. package/ui/CodeLines.qml +256 -0
  172. package/ui/CodeRefusal.qml +52 -0
  173. package/ui/CollideConfirm.qml +147 -0
  174. package/ui/CollideHost.qml +167 -0
  175. package/ui/ColumnPane.qml +525 -0
  176. package/ui/ColumnRow.qml +380 -0
  177. package/ui/ColumnsArea.qml +594 -0
  178. package/ui/ColumnsLanding.qml +147 -0
  179. package/ui/CompareView.qml +321 -0
  180. package/ui/ContextMenu.qml +743 -0
  181. package/ui/ConvertDialog.qml +456 -0
  182. package/ui/CountedWorker.qml +7 -0
  183. package/ui/Crumb.qml +64 -0
  184. package/ui/CrumbDrop.qml +25 -0
  185. package/ui/CsvTable.qml +394 -0
  186. package/ui/CursorMark.qml +41 -0
  187. package/ui/DefaultClaim.qml +130 -0
  188. package/ui/DeviceLock.qml +47 -0
  189. package/ui/DeviceMounts.qml +540 -0
  190. package/ui/DialogButton.qml +150 -0
  191. package/ui/DialogField.qml +147 -0
  192. package/ui/DialogHeader.qml +31 -0
  193. package/ui/DialogScrim.qml +20 -0
  194. package/ui/DialogTitle.qml +37 -0
  195. package/ui/Divider.qml +9 -0
  196. package/ui/DropInto.qml +126 -0
  197. package/ui/DropTarget.qml +35 -0
  198. package/ui/DropboxMark.qml +60 -0
  199. package/ui/EmptyState.qml +150 -0
  200. package/ui/EscapeHint.qml +11 -0
  201. package/ui/FactsTable.qml +54 -0
  202. package/ui/FastScrollHandler.qml +476 -0
  203. package/ui/FatNamesConfirm.qml +157 -0
  204. package/ui/Favourites.qml +143 -0
  205. package/ui/FigureService.qml +120 -0
  206. package/ui/FileDrag.qml +267 -0
  207. package/ui/FilterStrip.qml +133 -0
  208. package/ui/FitMetrics.qml +22 -0
  209. package/ui/FlashDriveRows.qml +137 -0
  210. package/ui/FlashHost.qml +72 -0
  211. package/ui/FlashImageRow.qml +104 -0
  212. package/ui/FlashRunner.qml +119 -0
  213. package/ui/FlashStepRow.qml +172 -0
  214. package/ui/FlashStrip.qml +38 -0
  215. package/ui/FlashView.qml +397 -0
  216. package/ui/FleaMark.qml +88 -0
  217. package/ui/FlyoutFade.qml +23 -0
  218. package/ui/FontPane.qml +170 -0
  219. package/ui/Glass.qml +114 -0
  220. package/ui/GlassTagger.qml +59 -0
  221. package/ui/Glyph.qml +64 -0
  222. package/ui/GlyphSolid.qml +22 -0
  223. package/ui/GridArea.qml +664 -0
  224. package/ui/GridTile.qml +325 -0
  225. package/ui/GvfsBridge.qml +164 -0
  226. package/ui/Header.qml +433 -0
  227. package/ui/HoverTimers.qml +39 -0
  228. package/ui/HtmlClip.qml +30 -0
  229. package/ui/HtmlPane.qml +63 -0
  230. package/ui/HyprlandMark.qml +45 -0
  231. package/ui/Ipc.qml +1005 -0
  232. package/ui/IpcControls.qml +7 -0
  233. package/ui/IpcMenuState.qml +48 -0
  234. package/ui/IpcPreviewState.qml +185 -0
  235. package/ui/JumpPath.qml +51 -0
  236. package/ui/KeymapSheet.qml +561 -0
  237. package/ui/KeymapSheetResult.qml +89 -0
  238. package/ui/KindStack.qml +40 -0
  239. package/ui/LangMark.qml +51 -0
  240. package/ui/LangMarkLoader.qml +26 -0
  241. package/ui/List.qml +480 -0
  242. package/ui/LoadingState.qml +54 -0
  243. package/ui/LocalSend.qml +56 -0
  244. package/ui/LocalSendMark.qml +73 -0
  245. package/ui/MarkdownBlockView.qml +311 -0
  246. package/ui/MarkdownBlocks.qml +35 -0
  247. package/ui/MarkdownFigure.qml +254 -0
  248. package/ui/MarkdownImages.qml +72 -0
  249. package/ui/MarkdownList.qml +81 -0
  250. package/ui/MarkdownMathsText.qml +97 -0
  251. package/ui/MarkdownPane.qml +83 -0
  252. package/ui/MarkdownPictures.qml +41 -0
  253. package/ui/MarkdownQuote.qml +52 -0
  254. package/ui/MarkdownRemote.qml +82 -0
  255. package/ui/MarkdownSource.qml +155 -0
  256. package/ui/MarkdownTable.qml +222 -0
  257. package/ui/MarkdownTableScroll.qml +64 -0
  258. package/ui/MarkdownTableWheel.qml +126 -0
  259. package/ui/MarkdownText.qml +87 -0
  260. package/ui/MarkdownWorker.js +132 -0
  261. package/ui/MatchText.qml +99 -0
  262. package/ui/MediaSession.qml +38 -0
  263. package/ui/MediaSound.qml +26 -0
  264. package/ui/MediaStrip.qml +191 -0
  265. package/ui/MediaTrack.qml +36 -0
  266. package/ui/MediaVolume.qml +54 -0
  267. package/ui/MenuActionDialog.qml +396 -0
  268. package/ui/MenuEdgeFade.qml +24 -0
  269. package/ui/MenuHost.qml +227 -0
  270. package/ui/MenuRow.qml +351 -0
  271. package/ui/MountListing.qml +100 -0
  272. package/ui/NetworkDialog.qml +435 -0
  273. package/ui/NetworkForm.qml +426 -0
  274. package/ui/NetworkMounts.qml +913 -0
  275. package/ui/NetworkPlaces.qml +127 -0
  276. package/ui/OpenWithDialog.qml +613 -0
  277. package/ui/Opener.qml +95 -0
  278. package/ui/Pane.qml +1320 -0
  279. package/ui/PaneMenuActions.qml +527 -0
  280. package/ui/PanePath.qml +90 -0
  281. package/ui/PaneRail.qml +268 -0
  282. package/ui/PaneStates.qml +88 -0
  283. package/ui/PaneSwap.qml +339 -0
  284. package/ui/PaneWire.qml +601 -0
  285. package/ui/ParkedWait.qml +9 -0
  286. package/ui/PathEntry.qml +186 -0
  287. package/ui/PathJump.qml +400 -0
  288. package/ui/PdfViewer.qml +297 -0
  289. package/ui/PermissionsDialog.qml +658 -0
  290. package/ui/PermissionsHeadings.qml +31 -0
  291. package/ui/PhoneMounts.qml +67 -0
  292. package/ui/PickerAnswers.qml +75 -0
  293. package/ui/PickerBox.qml +26 -0
  294. package/ui/PickerChrome.qml +295 -0
  295. package/ui/PickerFilter.qml +97 -0
  296. package/ui/PickerGrid.qml +308 -0
  297. package/ui/PickerHeader.qml +28 -0
  298. package/ui/PickerLifecycle.qml +27 -0
  299. package/ui/PickerList.qml +218 -0
  300. package/ui/PickerListing.qml +149 -0
  301. package/ui/PickerPathBar.qml +127 -0
  302. package/ui/PickerPlaces.qml +189 -0
  303. package/ui/PickerRecent.qml +92 -0
  304. package/ui/PickerSave.qml +101 -0
  305. package/ui/PickerSelection.qml +155 -0
  306. package/ui/PickerWindow.qml +846 -0
  307. package/ui/PowerSectorsReader.qml +10 -0
  308. package/ui/PrebuildDriver.qml +146 -0
  309. package/ui/Preview.qml +1005 -0
  310. package/ui/PreviewAnimation.qml +24 -0
  311. package/ui/PreviewArchive.qml +91 -0
  312. package/ui/PreviewColumn.qml +553 -0
  313. package/ui/PreviewEdge.qml +63 -0
  314. package/ui/PreviewFacts.qml +30 -0
  315. package/ui/PreviewFactsLine.qml +34 -0
  316. package/ui/PreviewHtml.qml +233 -0
  317. package/ui/PreviewImage.qml +253 -0
  318. package/ui/PreviewImagePan.qml +13 -0
  319. package/ui/PreviewImageSharp.qml +32 -0
  320. package/ui/PreviewLines.qml +106 -0
  321. package/ui/PreviewMarkdown.qml +706 -0
  322. package/ui/PreviewMedia.qml +250 -0
  323. package/ui/PreviewPdf.qml +482 -0
  324. package/ui/PreviewScroll.qml +201 -0
  325. package/ui/PreviewSwap.qml +335 -0
  326. package/ui/PreviewText.qml +149 -0
  327. package/ui/ProtocolChip.qml +18 -0
  328. package/ui/QuickLookArchive.qml +41 -0
  329. package/ui/QuickLookBar.qml +103 -0
  330. package/ui/QuickLookPrepare.qml +355 -0
  331. package/ui/QuickLookSwap.qml +10 -0
  332. package/ui/QuickLookWarm.qml +65 -0
  333. package/ui/RailDrop.qml +155 -0
  334. package/ui/RailHeading.qml +19 -0
  335. package/ui/RailPlaces.qml +38 -0
  336. package/ui/RailTrashRow.qml +67 -0
  337. package/ui/RenameField.qml +353 -0
  338. package/ui/RendererRetry.qml +11 -0
  339. package/ui/ResizeHandle.qml +52 -0
  340. package/ui/Reveal.qml +54 -0
  341. package/ui/Row.qml +476 -0
  342. package/ui/RowDrag.qml +213 -0
  343. package/ui/RowDropTarget.qml +27 -0
  344. package/ui/RunCard.qml +286 -0
  345. package/ui/Scripts.qml +65 -0
  346. package/ui/SearchStrip.qml +232 -0
  347. package/ui/SelectionBand.qml +140 -0
  348. package/ui/SelectionPreview.qml +370 -0
  349. package/ui/SettingsFavourite.qml +122 -0
  350. package/ui/SettingsGroup.qml +96 -0
  351. package/ui/SettingsHint.qml +12 -0
  352. package/ui/SettingsMetrics.qml +29 -0
  353. package/ui/SettingsPane.qml +178 -0
  354. package/ui/SettingsPanel.qml +547 -0
  355. package/ui/SettingsRail.qml +128 -0
  356. package/ui/SettingsRow.qml +409 -0
  357. package/ui/SettingsRuler.qml +85 -0
  358. package/ui/SettingsSegment.qml +85 -0
  359. package/ui/ShareBrowser.qml +113 -0
  360. package/ui/ShareLink.qml +67 -0
  361. package/ui/ShelfPins.qml +101 -0
  362. package/ui/Sidebar.qml +728 -0
  363. package/ui/SidebarRow.qml +358 -0
  364. package/ui/Spinner.qml +60 -0
  365. package/ui/StableModel.qml +89 -0
  366. package/ui/StateMessage.qml +84 -0
  367. package/ui/StatusBar.qml +512 -0
  368. package/ui/StatusFileName.qml +27 -0
  369. package/ui/TabBar.qml +673 -0
  370. package/ui/TabDragGeometry.qml +60 -0
  371. package/ui/TagMenuMark.qml +52 -0
  372. package/ui/TagRailSection.qml +53 -0
  373. package/ui/TagSlot.qml +40 -0
  374. package/ui/TagState.qml +150 -0
  375. package/ui/TagSwatch.qml +28 -0
  376. package/ui/Taildrop.qml +86 -0
  377. package/ui/TailscaleMark.qml +50 -0
  378. package/ui/TerminalService.qml +69 -0
  379. package/ui/TerminalTab.qml +48 -0
  380. package/ui/TerminalTabs.qml +27 -0
  381. package/ui/Theme.qml +460 -0
  382. package/ui/ThemeColors.qml +43 -0
  383. package/ui/TransferCard.qml +239 -0
  384. package/ui/TrashConfirm.qml +129 -0
  385. package/ui/TrashDropHandler.qml +11 -0
  386. package/ui/TrashHost.qml +202 -0
  387. package/ui/TrashMonitor.qml +30 -0
  388. package/ui/TrashToolbar.qml +19 -0
  389. package/ui/TrashView.qml +492 -0
  390. package/ui/UnlockDialog.qml +450 -0
  391. package/ui/UnlockHost.qml +206 -0
  392. package/ui/UpdateCheck.qml +97 -0
  393. package/ui/UserDirs.qml +25 -0
  394. package/ui/ViewState.qml +565 -0
  395. package/ui/ViewportScrollBar.qml +195 -0
  396. package/ui/ViewportScrollBars.qml +25 -0
  397. package/ui/WebPreview.qml +33 -0
  398. package/ui/WebPreviewView.qml +26 -0
  399. package/ui/WindowBody.qml +829 -0
  400. package/ui/WindowDrag.qml +35 -0
  401. package/ui/boot/Commons/AudioNodes.qml +50 -0
  402. package/ui/boot/Commons/AudioNodesModel.js +96 -0
  403. package/ui/boot/Commons/Border.qml +243 -0
  404. package/ui/boot/Commons/BorderGeometry.js +373 -0
  405. package/ui/boot/Commons/Color.qml +258 -0
  406. package/ui/boot/Commons/I18n.qml +118 -0
  407. package/ui/boot/Commons/InputDevices.qml +112 -0
  408. package/ui/boot/Commons/InputMethodState.qml +38 -0
  409. package/ui/boot/Commons/IpcRegistry.qml +77 -0
  410. package/ui/boot/Commons/Numbers.js +19 -0
  411. package/ui/boot/Commons/Plural.js +91 -0
  412. package/ui/boot/Commons/ShellIpc.qml +12 -0
  413. package/ui/boot/Commons/Style.qml +561 -0
  414. package/ui/boot/Commons/Translations.qml +100 -0
  415. package/ui/boot/Commons/UntypedInput.qml +152 -0
  416. package/ui/boot/Commons/Util.qml +188 -0
  417. package/ui/boot/Commons/qmldir +13 -0
  418. package/ui/boot/LICENSE-omarchy +20 -0
  419. package/ui/boot/Ui/BackgroundMedia.qml +49 -0
  420. package/ui/boot/Ui/BarIconButton.qml +106 -0
  421. package/ui/boot/Ui/BarIconContent.qml +38 -0
  422. package/ui/boot/Ui/BarIndicator.qml +53 -0
  423. package/ui/boot/Ui/BarWidget.qml +50 -0
  424. package/ui/boot/Ui/BorderOverlay.qml +54 -0
  425. package/ui/boot/Ui/BorderSurface.qml +40 -0
  426. package/ui/boot/Ui/Button.qml +224 -0
  427. package/ui/boot/Ui/ButtonGroup.qml +131 -0
  428. package/ui/boot/Ui/ConfirmDialog.qml +134 -0
  429. package/ui/boot/Ui/CursorSurface.qml +42 -0
  430. package/ui/boot/Ui/Dropdown.qml +245 -0
  431. package/ui/boot/Ui/FilterInput.qml +26 -0
  432. package/ui/boot/Ui/IconContentBounds.qml +141 -0
  433. package/ui/boot/Ui/KeyboardPanel.qml +453 -0
  434. package/ui/boot/Ui/MultiSelect.qml +624 -0
  435. package/ui/boot/Ui/NumberField.qml +86 -0
  436. package/ui/boot/Ui/OpticalGlyph.qml +68 -0
  437. package/ui/boot/Ui/OverlayWindow.qml +102 -0
  438. package/ui/boot/Ui/Panel.qml +60 -0
  439. package/ui/boot/Ui/PanelActionButton.qml +105 -0
  440. package/ui/boot/Ui/PanelController.qml +16 -0
  441. package/ui/boot/Ui/PanelHero.qml +112 -0
  442. package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
  443. package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
  444. package/ui/boot/Ui/PanelSeparator.qml +19 -0
  445. package/ui/boot/Ui/PanelSlider.qml +156 -0
  446. package/ui/boot/Ui/PanelToolTip.qml +50 -0
  447. package/ui/boot/Ui/PluginBarApi.qml +89 -0
  448. package/ui/boot/Ui/PointerMoveGate.qml +54 -0
  449. package/ui/boot/Ui/PopupCard.qml +181 -0
  450. package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
  451. package/ui/boot/Ui/SearchableDropdown.qml +354 -0
  452. package/ui/boot/Ui/SizedImage.qml +125 -0
  453. package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
  454. package/ui/boot/Ui/TextField.qml +58 -0
  455. package/ui/boot/Ui/Toggle.qml +118 -0
  456. package/ui/boot/Ui/ToggleSwitch.qml +115 -0
  457. package/ui/boot/Ui/WidgetButton.qml +172 -0
  458. package/ui/boot/Ui/qmldir +41 -0
  459. package/ui/boot/fleatab.qml +50 -0
  460. package/ui/boot/picker.qml +39 -0
  461. package/ui/boot/shell.qml +131 -0
  462. package/ui/boot/tabtearoff.qml +51 -0
  463. package/ui/js/Anchor.js +379 -0
  464. package/ui/js/AnchorHold.js +162 -0
  465. package/ui/js/Archive.js +157 -0
  466. package/ui/js/ArchiveCard.js +44 -0
  467. package/ui/js/ArchiveOps.js +44 -0
  468. package/ui/js/BackReturn.js +118 -0
  469. package/ui/js/BulkRename.js +100 -0
  470. package/ui/js/Buttons.js +54 -0
  471. package/ui/js/ChromeKeys.js +116 -0
  472. package/ui/js/ClipMarks.js +73 -0
  473. package/ui/js/ClipSelection.js +67 -0
  474. package/ui/js/Clipboard.js +179 -0
  475. package/ui/js/Cloud.js +97 -0
  476. package/ui/js/CodeRuns.js +72 -0
  477. package/ui/js/Collide.js +212 -0
  478. package/ui/js/ColumnFit.js +28 -0
  479. package/ui/js/ColumnMenu.js +111 -0
  480. package/ui/js/Columns.js +298 -0
  481. package/ui/js/ColumnsCarry.js +103 -0
  482. package/ui/js/Compare.js +74 -0
  483. package/ui/js/Contrast.js +157 -0
  484. package/ui/js/ControlReader.js +42 -0
  485. package/ui/js/Convert.js +52 -0
  486. package/ui/js/CopyAs.js +52 -0
  487. package/ui/js/Crumbs.js +178 -0
  488. package/ui/js/Csv.js +231 -0
  489. package/ui/js/Density.js +44 -0
  490. package/ui/js/Devices.js +440 -0
  491. package/ui/js/DirSizes.js +180 -0
  492. package/ui/js/Drag.js +360 -0
  493. package/ui/js/DragOut.js +166 -0
  494. package/ui/js/DropDev.js +52 -0
  495. package/ui/js/Dropbox.js +41 -0
  496. package/ui/js/Eject.js +217 -0
  497. package/ui/js/Errors.js +188 -0
  498. package/ui/js/ExtThumbs.js +115 -0
  499. package/ui/js/Facts.js +402 -0
  500. package/ui/js/FigureDate.js +14 -0
  501. package/ui/js/Filter.js +285 -0
  502. package/ui/js/Find.js +46 -0
  503. package/ui/js/Flash.js +184 -0
  504. package/ui/js/FlashCard.js +79 -0
  505. package/ui/js/FlashEndings.js +125 -0
  506. package/ui/js/FlashPane.js +116 -0
  507. package/ui/js/FleaBin.js +12 -0
  508. package/ui/js/Focus.js +504 -0
  509. package/ui/js/FolderSorts.js +108 -0
  510. package/ui/js/FolderViews.js +44 -0
  511. package/ui/js/Format.js +314 -0
  512. package/ui/js/Fuzzy.js +141 -0
  513. package/ui/js/GlassTag.js +72 -0
  514. package/ui/js/Grid.js +33 -0
  515. package/ui/js/GridGeometry.js +90 -0
  516. package/ui/js/GridNames.js +153 -0
  517. package/ui/js/GvfsBridge.js +200 -0
  518. package/ui/js/HostClipboard.js +29 -0
  519. package/ui/js/Icons.js +218 -0
  520. package/ui/js/Input.js +50 -0
  521. package/ui/js/Jump.js +200 -0
  522. package/ui/js/KeyName.js +64 -0
  523. package/ui/js/Keymap.js +401 -0
  524. package/ui/js/Kinds.js +164 -0
  525. package/ui/js/LICENSES/ISC-lucide.txt +43 -0
  526. package/ui/js/LangMarkPaths.js +47 -0
  527. package/ui/js/LangMarks.js +120 -0
  528. package/ui/js/Lists.js +11 -0
  529. package/ui/js/LocalSend.js +39 -0
  530. package/ui/js/LockedMenu.js +63 -0
  531. package/ui/js/MakeDefault.js +186 -0
  532. package/ui/js/MarkBox.js +7 -0
  533. package/ui/js/Markdown.js +119 -0
  534. package/ui/js/MarkdownLists.js +86 -0
  535. package/ui/js/MarkdownMaths.js +58 -0
  536. package/ui/js/MarkdownPictures.js +32 -0
  537. package/ui/js/MarkdownPrepared.js +139 -0
  538. package/ui/js/MarkdownTableFit.js +34 -0
  539. package/ui/js/Marks.js +148 -0
  540. package/ui/js/Marquee.js +96 -0
  541. package/ui/js/Match.js +93 -0
  542. package/ui/js/Material.js +109 -0
  543. package/ui/js/MdBlocks.js +437 -0
  544. package/ui/js/MdBreak.js +71 -0
  545. package/ui/js/MdChunks.js +70 -0
  546. package/ui/js/MdContainer.js +137 -0
  547. package/ui/js/MdDocument.js +337 -0
  548. package/ui/js/MdEmph.js +97 -0
  549. package/ui/js/MdEntity.js +108 -0
  550. package/ui/js/MdEntityTable.js +223 -0
  551. package/ui/js/MdEscape.js +59 -0
  552. package/ui/js/MdFront.js +37 -0
  553. package/ui/js/MdHold.js +32 -0
  554. package/ui/js/MdHtml.js +307 -0
  555. package/ui/js/MdHtmlBlock.js +290 -0
  556. package/ui/js/MdHtmlHeading.js +53 -0
  557. package/ui/js/MdHtmlImage.js +179 -0
  558. package/ui/js/MdInline.js +154 -0
  559. package/ui/js/MdItems.js +212 -0
  560. package/ui/js/MdLeaf.js +309 -0
  561. package/ui/js/MdLink.js +196 -0
  562. package/ui/js/MdMath.js +67 -0
  563. package/ui/js/MdParagraphs.js +138 -0
  564. package/ui/js/MdRefs.js +232 -0
  565. package/ui/js/MdResolve.js +226 -0
  566. package/ui/js/MdRun.js +300 -0
  567. package/ui/js/MdUrl.js +226 -0
  568. package/ui/js/Menu.js +514 -0
  569. package/ui/js/MenuContext.js +85 -0
  570. package/ui/js/MenuFit.js +13 -0
  571. package/ui/js/MenuRefresh.js +74 -0
  572. package/ui/js/MenuWheel.js +35 -0
  573. package/ui/js/Messages.js +186 -0
  574. package/ui/js/Motion.js +16 -0
  575. package/ui/js/Mounts.js +320 -0
  576. package/ui/js/MouseNav.js +13 -0
  577. package/ui/js/Nav.js +329 -0
  578. package/ui/js/NetFs.js +26 -0
  579. package/ui/js/OpenWith.js +83 -0
  580. package/ui/js/Ops.js +585 -0
  581. package/ui/js/Palette.js +33 -0
  582. package/ui/js/PathBar.js +260 -0
  583. package/ui/js/Permissions.js +179 -0
  584. package/ui/js/Phones.js +112 -0
  585. package/ui/js/Picker.js +353 -0
  586. package/ui/js/PlaceMenu.js +96 -0
  587. package/ui/js/Places.js +265 -0
  588. package/ui/js/PreviewAsk.js +21 -0
  589. package/ui/js/PreviewKeys.js +155 -0
  590. package/ui/js/PreviewSettle.js +29 -0
  591. package/ui/js/PreviewSwap.js +101 -0
  592. package/ui/js/PropertyFacts.js +144 -0
  593. package/ui/js/Protocols.js +296 -0
  594. package/ui/js/QuickLookKinds.js +27 -0
  595. package/ui/js/QuickLookRect.js +24 -0
  596. package/ui/js/RailDrop.js +51 -0
  597. package/ui/js/RailKeys.js +87 -0
  598. package/ui/js/RailMenu.js +133 -0
  599. package/ui/js/Recent.js +135 -0
  600. package/ui/js/RecentMode.js +156 -0
  601. package/ui/js/Reload.js +60 -0
  602. package/ui/js/Renderer.js +9 -0
  603. package/ui/js/RunFile.js +143 -0
  604. package/ui/js/Scripts.js +28 -0
  605. package/ui/js/Scroll.js +304 -0
  606. package/ui/js/ScrollOff.js +69 -0
  607. package/ui/js/Search.js +478 -0
  608. package/ui/js/Selection.js +97 -0
  609. package/ui/js/Settings.js +476 -0
  610. package/ui/js/SettingsAbout.js +97 -0
  611. package/ui/js/SettingsShelf.js +52 -0
  612. package/ui/js/SheetKeys.js +42 -0
  613. package/ui/js/SheetQuery.js +281 -0
  614. package/ui/js/ShelfPile.js +27 -0
  615. package/ui/js/SlowClick.js +53 -0
  616. package/ui/js/SlowOp.js +6 -0
  617. package/ui/js/Sort.js +134 -0
  618. package/ui/js/Startup.js +63 -0
  619. package/ui/js/StateWords.js +17 -0
  620. package/ui/js/Status.js +238 -0
  621. package/ui/js/Swap.js +166 -0
  622. package/ui/js/TabMove.js +39 -0
  623. package/ui/js/Tabs.js +751 -0
  624. package/ui/js/Tags.js +134 -0
  625. package/ui/js/Taildrop.js +128 -0
  626. package/ui/js/Tap.js +180 -0
  627. package/ui/js/TextSize.js +107 -0
  628. package/ui/js/Thumbs.js +158 -0
  629. package/ui/js/Transfer.js +172 -0
  630. package/ui/js/Trash.js +84 -0
  631. package/ui/js/TrashDates.js +47 -0
  632. package/ui/js/TrashDrop.js +64 -0
  633. package/ui/js/UiState.js +438 -0
  634. package/ui/js/Unlock.js +152 -0
  635. package/ui/js/Update.js +130 -0
  636. package/ui/js/UserDirs.js +56 -0
  637. package/ui/qmldir +230 -0
@@ -0,0 +1,525 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+ import qs.Ui
4
+ import "." as Flea
5
+ import "js/ClipMarks.js" as ClipMarks
6
+ import "js/Filter.js" as Filter
7
+ import "js/ExtThumbs.js" as ExtThumbs
8
+ import "js/Scroll.js" as Scroll
9
+ import "js/ScrollOff.js" as ScrollOff
10
+ import "js/Tap.js" as Tap
11
+ import "js/Thumbs.js" as Thumbs
12
+ import "js/DirSizes.js" as DirSizes
13
+ import "js/Sort.js" as Sort
14
+ import "js/DragOut.js" as DragOut
15
+ import "js/DropDev.js" as DropDev
16
+
17
+ // One Miller column: a scrolling list of ColumnRows over either a peeked directory or the pane's
18
+ // own listing window. It owns no state; the area above it decides which row is which.
19
+ Item {
20
+ id: root
21
+
22
+ // [{n, d, i}], from a peek or from the pane's own held window.
23
+ property var rows: []
24
+ property bool loadingRows: false
25
+ signal loadingShown(bool shown)
26
+ // The row this column's cursor is on, as an absolute index; -1 when this column has no cursor.
27
+ property int selectedIndex: -1
28
+ // The one row drawn as this column's cursor; a cursor move touches two delegates, not every live one.
29
+ Flea.CursorMark { id: cursorMark; row: root.selectedIndex }
30
+ // The row named here is the one the trail passes through: lifted like a hover, never accented.
31
+ property string liftedName: ""
32
+ // The pane whose listing this column draws, or null for a peek. Only that one column has a
33
+ // selection to paint, and pane.isSelected reads selectionVersion, so the delegate follows it.
34
+ property var pane: null
35
+ // The window pane plus this peek column's directory, device and writability, for a drag from its rows; null on the pane's own column.
36
+ property var peekSource: null
37
+ // A column that is not the active one reads back.
38
+ property bool dim: false
39
+ // The mode of a denied peek, or -1 when this column's directory was read and its rows are true.
40
+ property int lockedMode: -1
41
+ // Whether zero rows here means empty: false while a peek is still out, because a pending peek answers zero rows too, and false for the pane's own listing, whose empty answer is the hero ui/shell.qml lays over the area.
42
+ property bool drawsEmpty: false
43
+ // True when this column draws its size cell, the same flag its rows read as showSize.
44
+ readonly property bool showsSize: root.pane !== null && root.pane !== undefined
45
+ // Parked rows the active column built ahead of the next landing; only the pane's own column has a pane, so only it prebuilds.
46
+ readonly property Flea.PrebuildDriver prebuild: Flea.PrebuildDriver {
47
+ view: root.viewport
48
+ model: stable
49
+ pane: root.pane
50
+ limit: stable.warmRows
51
+ park: function (cell) { cell.live = false; cell.visible = false }
52
+ adopt: function (cell) { cell.live = true; cell.visible = true; cursorMark.place(cell) }
53
+ }
54
+ // One character budget for a row without the chevron, so a column lays its names out once.
55
+ readonly property int nameBudgetPlain: Theme.bodyAdvance > 0 ? Math.max(0, Math.floor((Scroll.contentWidth(root.width, Theme.spacing.rowPaddingX) - Theme.spacing.rowPaddingX - Theme.iconSize - Theme.spacing.gap - Theme.spacing.rowPaddingX - (root.showsSize ? Theme.column.size + 2 * Theme.spacing.gap : 0)) / Theme.bodyAdvance)) : -1
56
+ // The same terms plus the chevron slot, for the chosen directory alone.
57
+ readonly property int nameBudgetChevron: Theme.bodyAdvance > 0 ? Math.max(0, Math.floor((Scroll.contentWidth(root.width, Theme.spacing.rowPaddingX) - Theme.spacing.rowPaddingX - Theme.iconSize - Theme.spacing.gap - Theme.spacing.rowPaddingX - Theme.font.caption - (root.showsSize ? Theme.column.size + 2 * Theme.spacing.gap : 0)) / Theme.bodyAdvance)) : -1
58
+ // True for every shown pane but the rightmost one; the line sits on the pane edge and changes no width.
59
+ property bool showDivider: false
60
+ // Empty short-circuits before the library, the same rule ui/List.qml carries.
61
+ property bool clipEmpty: ClipMarks.isEmpty(root.pane ? root.pane.clipboard : null)
62
+ // The short-circuit above is the only release while empty, so a cut of a large directory frees its lookup here.
63
+ onClipEmptyChanged: { if (root.clipEmpty) ClipMarks.release() }
64
+
65
+ // isDir says which of the two things a neighbour column's row is: a directory the pane opens as
66
+ // its own listing, or a file it hands to the opener. See keys.toml's [[pointer]] table.
67
+ signal activated(string name, bool isDir)
68
+ signal picked(int index, int tapCount, int modifiers, bool onName)
69
+ // A row press, so the columns view can stop the slow-click timer before a
70
+ // hold past the interval fires while the button is still down.
71
+ signal rowPressed(int index)
72
+ // The row under a right click. Only the column carrying the pane's own listing answers it, because a peeked column's rows are another directory's and every menu action addresses the pane's cursor.
73
+ signal menuRequested(int index, var eventPoint)
74
+ // A right click that landed on no row, which only the pane's own column can answer for the same
75
+ // reason: the background menu acts on the directory being shown and a peek is not that directory.
76
+ signal backgroundMenuRequested(var eventPoint)
77
+ // A right click on a peek's row: the peek's directory becomes the listing with this row as the cursor, and the menu opens there.
78
+ signal neighbourMenuRequested(string name)
79
+ // A right click on a peek's empty space: the peek's drawn directory becomes the listing, and the background menu opens there once its rows land.
80
+ signal neighbourBackgroundRequested(var eventPoint)
81
+ // A middle click on a directory row, in any of the three columns: ui/js/Tap.js tappedTab opens it in
82
+ // a new tab, and ui/ColumnsArea.qml supplies which directory this column is showing.
83
+ signal tabRequested(var row)
84
+ // The thumbnail plan for this column's viewport, computed here and written by the pane, the grid's own contract.
85
+ signal thumbsApplied(var work)
86
+ signal dirSizesApplied(var ask)
87
+
88
+ // The listArea contract ui/ColumnsArea.qml drives the middle column through; the view is private.
89
+ function positionViewAtIndex(index, mode) { view.positionViewAtIndex(index, mode) }
90
+ function itemAtIndex(index) { return view.itemAtIndex(index) }
91
+ function contentY() { return view.contentY }
92
+ // The scrolling list itself, for the anchor that puts the view back after a re-list; see ui/js/AnchorHold.js.
93
+ readonly property alias viewport: view
94
+ // A platform drag in flight, so a slow click never renames off one; ui/ColumnsArea.qml reads it.
95
+ readonly property bool fileDragActive: dragSession.Drag.active
96
+ // Cursor keeps three rows context above and below; wheel path follows viewport margin-free; click context 0 never moves list.
97
+ function showCursor(viewIndex, context) {
98
+ // The column's own rowTotal falls back to its rows with no pane, the same fallback its model uses.
99
+ var to = ScrollOff.cursorY(view, viewIndex, root.rowTotal, Theme.fileRowHeight, context)
100
+ if (to !== null)
101
+ view.contentY = to
102
+ }
103
+ readonly property alias scrollBar: verticalScroll
104
+ function restartSettle() { settle.restart() }
105
+ function restartCoalesce() { coalesce.restart() }
106
+ function primeSettle() { settle.interval = root.pane.firstSettleMs }
107
+
108
+ function visibleRange() {
109
+ var visibleRows = Math.max(1, Math.ceil(view.height / Theme.fileRowHeight))
110
+ var fallback = Thumbs.viewport(view.contentY - view.originY, Theme.fileRowHeight, visibleRows, view.count)
111
+ if (root.pane && root.pane.renamingIndex >= 0) {
112
+ var first = view.indexAt(0, view.contentY)
113
+ var last = view.indexAt(0, view.contentY + view.height - 1)
114
+ first = first < 0 ? fallback.first : first
115
+ return {first: first, last: last < 0 ? Math.min(view.count - 1, first + visibleRows) : last}
116
+ }
117
+ return fallback
118
+ }
119
+
120
+ // The visible folder rows of a peek column that name no device, which a drag entering the pane asks the backend for.
121
+ function dropAsks() {
122
+ if (!root.visible || !root.peekSource) return []
123
+ var range = root.visibleRange()
124
+ return DropDev.folderAsks(root.rows, root.peekSource.dir, range.first, range.last, root.peekSource.pane)
125
+ }
126
+
127
+ // The active column uses List/Grid's integer model and refills only around its viewport.
128
+ function requestIfDrifted() {
129
+ if (root.pane === null || !root.visible || root.pane.listInFlight
130
+ || root.pane.total === 0 || root.pane.shown !== null)
131
+ return
132
+ var range = root.visibleRange()
133
+ var heldEnd = root.pane.held + root.pane.rows.length
134
+ if (root.pane.rows.length === 0
135
+ || (range.first - root.pane.held < root.pane.refetchMargin && root.pane.held > 0)
136
+ || (heldEnd - range.last < root.pane.refetchMargin && heldEnd < root.pane.total))
137
+ root.pane.backend.window(Math.max(0, range.first - root.pane.buffer), root.pane.windowSize)
138
+ }
139
+
140
+ // The viewport's rows and no more, rule 1: the same plan the list and the grid run, over this column's own scroll position.
141
+ function requestThumbs() {
142
+ // visible is effective visibility, so the column kept alive under another view plans nothing against the shared state.
143
+ if (root.pane === null || !root.visible || root.pane.total === 0 || root.pane.listInFlight || !root.pane.storageKnown)
144
+ return
145
+ var range = root.visibleRange()
146
+ var span = Filter.span(root.pane.shown, range.first, range.last)
147
+ var work = Filter.cut(Thumbs.plan(root.pane.thumbState, root.pane.rows, root.pane.held,
148
+ span.first, span.last, ViewState.thumbnailMode), root.pane.shown, root.pane.thumbState)
149
+ // Only the loaded preview owns an off-viewport request; manual cursor movement asks nothing extra.
150
+ work.drop = work.drop.filter(function (index) { return index !== root.pane.previewIndex })
151
+ root.pane.backend.thumbcancel(work.drop)
152
+ work.cacheOnly = ExtThumbs.cacheOnly(root.pane.storageClass, ViewState.preview)
153
+ root.pane.backend.thumb(work.ask, work.cacheOnly)
154
+ if (work.ask.length > 0) settle.interval = root.pane.settleMs
155
+ root.thumbsApplied(work)
156
+ }
157
+
158
+ // The same viewport plan the list runs, over this column's own scroll position. Only the active
159
+ // column can ask: dirsize resolves against st.listing, which a peeked row has no index in.
160
+ function requestDirSizes() {
161
+ // Folder sizes are measured only when the user asks: a ⚖️ click, see Pane.measureDirs.
162
+ return
163
+ if (root.pane === null || !root.visible || root.pane.total === 0 || root.pane.listInFlight)
164
+ return
165
+ // The active column always draws its size, so only the class gate applies here.
166
+ if (!DirSizes.wantsSizes("columns", [], root.pane.storageClass, root.pane.storageKnown))
167
+ return
168
+ var range = root.visibleRange()
169
+ var span = Filter.span(root.pane.shown, range.first, range.last)
170
+ var ask = Filter.keep(DirSizes.plan(root.pane.dirSizeState, root.pane.rows, root.pane.held,
171
+ span.first, span.last, ViewState.thumbnailMode), root.pane.shown)
172
+ if (ask.length > 0) {
173
+ root.pane.backend.dirsize(ask)
174
+ settle.interval = root.pane.settleMs
175
+ }
176
+ root.dirSizesApplied(ask)
177
+ }
178
+
179
+ Connections {
180
+ target: ViewState
181
+ function onThumbnailModeChanged() { if (root.visible) settle.restart() }
182
+ }
183
+
184
+ Timer {
185
+ id: coalesce
186
+ interval: root.pane ? root.pane.coalesceMs : 0
187
+ repeat: false
188
+ onTriggered: root.requestIfDrifted()
189
+ }
190
+
191
+ Timer {
192
+ id: settle
193
+ interval: root.pane ? root.pane.settleMs : 120
194
+ repeat: false
195
+ onTriggered: { root.requestThumbs(); root.requestDirSizes() }
196
+ }
197
+ onRowsChanged: if (root.pane !== null) settle.restart()
198
+ // A column with no pane is a peek the user is not working in, so it keeps fewer unseen rows than the pane's cacheRows: 4 (ui/Pane.qml).
199
+ readonly property int bareCacheRows: 2
200
+ // No pane yet: the column's own rows are the listing, the same fallback its model uses.
201
+ readonly property int rowTotal: root.pane ? root.pane.shownTotal : root.rows.length
202
+ // The count a hidden column keeps its rows for, -1 once another reached it; the model compares counts, so no handler order builds a row.
203
+ property int keptTotal: -1
204
+ // Where a dropped column stands: the top a new count leaves, then each cursor move contained as showCursor does.
205
+ property real heldY: 0
206
+ Component.onCompleted: root.keptTotal = root.rowTotal
207
+ onRowTotalChanged: { root.keptTotal = root.visible ? root.rowTotal : -1; root.heldY = 0 }
208
+ onVisibleChanged: {
209
+ // A dropped column builds its rows on the frame that shows it, standing where a kept one would.
210
+ if (root.visible && root.keptTotal !== root.rowTotal) {
211
+ root.keptTotal = root.rowTotal
212
+ verticalScroll.settling = true
213
+ view.contentY = view.originY + root.heldY
214
+ verticalScroll.settling = false
215
+ }
216
+ if (root.visible && root.pane !== null) { coalesce.restart(); settle.restart() }
217
+ }
218
+ onHeightChanged: if (root.visible && root.pane !== null) { coalesce.restart(); settle.restart() }
219
+
220
+ Flea.FileDrag {
221
+ id: dragSession
222
+ pane: root.pane
223
+ peekSource: root.peekSource
224
+ }
225
+
226
+ // Only the active column owns this directory; neighboring peek floors cannot target its listing.
227
+ Flea.DropInto {
228
+ anchors.fill: parent
229
+ enabled: root.pane !== null && !root.pane.trash.opened && root.pane.searchMode === ""
230
+ pane: root.pane
231
+ dest: root.pane ? root.pane.dropPath : ""
232
+ refuseLoading: DragOut.refuseLoading(root.pane && root.pane.listInFlight, false, false)
233
+ destDev: root.pane && root.pane.backend && !root.pane.listInFlight ? root.pane.backend.dirDev : 0
234
+ }
235
+
236
+ // flea-qml: every column carries the list's own titles, so the columns view (and its preview
237
+ // column) never loses them: Name in each, and on the pane's own column the ⚖️ that measures
238
+ // every folder and the Size title over the size cells. Name and Size sort as the list's do.
239
+ Item {
240
+ id: columnHeader
241
+ anchors.top: parent.top
242
+ anchors.left: parent.left
243
+ width: root.width
244
+ height: Theme.chromeHeight
245
+ // The rows keep the scroll lane clear; the titles over them keep it too, the fill spans it.
246
+ readonly property real lane: root.width - Scroll.contentWidth(root.width, Theme.spacing.rowPaddingX)
247
+ readonly property bool own: root.pane !== null && root.pane !== undefined
248
+ readonly property string sortBy: own && root.pane.backend ? root.pane.backend.sortBy : ""
249
+ readonly property bool sortDesc: own && root.pane.backend ? root.pane.backend.sortDesc : false
250
+ function title(label, key) { return columnHeader.sortBy === key ? Sort.title(label, columnHeader.sortDesc) : label }
251
+ Rectangle { anchors.fill: parent; color: Style.normalFill }
252
+ PanelSectionHeader {
253
+ id: columnName
254
+ anchors.left: parent.left
255
+ anchors.leftMargin: Theme.spacing.rowPaddingX + Theme.iconSize + Theme.spacing.gap
256
+ anchors.right: columnScale.visible ? columnScale.left : parent.right
257
+ anchors.rightMargin: columnScale.visible ? Theme.spacing.gap : columnHeader.lane + Theme.spacing.rowPaddingX
258
+ anchors.verticalCenter: parent.verticalCenter
259
+ text: columnHeader.title("Name", "name")
260
+ elide: Text.ElideRight
261
+ TapHandler { enabled: columnHeader.own; onTapped: Sort.column(root.pane, "name") }
262
+ }
263
+ Text {
264
+ id: columnScale
265
+ anchors.right: columnSize.left
266
+ anchors.rightMargin: Theme.spacing.gap
267
+ anchors.verticalCenter: parent.verticalCenter
268
+ visible: root.showsSize
269
+ text: DirSizes.UNMEASURED
270
+ textFormat: Text.PlainText
271
+ font.pixelSize: columnName.font.pixelSize
272
+ HoverHandler { cursorShape: Qt.PointingHandCursor }
273
+ TapHandler { onTapped: root.pane.measureAllDirs() }
274
+ }
275
+ PanelSectionHeader {
276
+ id: columnSize
277
+ anchors.right: parent.right
278
+ anchors.rightMargin: columnHeader.lane + Theme.spacing.rowPaddingX + Theme.spacing.gap
279
+ anchors.verticalCenter: parent.verticalCenter
280
+ visible: root.showsSize
281
+ text: columnHeader.title("Size", "size")
282
+ horizontalAlignment: Text.AlignRight
283
+ TapHandler { onTapped: Sort.column(root.pane, "size") }
284
+ }
285
+ }
286
+
287
+ ListView {
288
+ id: view
289
+ // The shared pane owns selection and arrow navigation, including after rename.
290
+ keyNavigationEnabled: false
291
+ anchors.top: columnHeader.bottom
292
+ anchors.left: parent.left
293
+ anchors.right: parent.right
294
+ anchors.bottom: parent.bottom
295
+
296
+ model: Flea.StableModel { id: stable; view: view; total: root.visible || root.keptTotal === root.rowTotal ? root.rowTotal : 0; keptRows: true
297
+ warm: root.pane !== null && view.visible && root.pane.searchMode.length > 0 && root.pane.swap.searchWarm === true; warmRows: Math.floor((view.height + view.cacheBuffer) / Theme.fileRowHeight) + 1 }
298
+ clip: true
299
+ // The pane's cache rows, as ui/List.qml takes them: Qt's default 320 px builds about 12 unseen rows into every landing.
300
+ cacheBuffer: Theme.fileRowHeight * (root.pane ? root.pane.cacheRows : root.bareCacheRows)
301
+ boundsBehavior: Flickable.StopAtBounds
302
+ onContentYChanged: if (root.pane !== null) { coalesce.start(); settle.restart() }
303
+ onCountChanged: root.prebuild.landed()
304
+ // The error line's growth lands in contentHeight after layout, so the row is contained once then, never on a later scroll's estimate.
305
+ onContentHeightChanged: if (root.containRenameError) { root.containRenameError = false; view.positionViewAtIndex(root.renameViewIndex, ListView.Contain) }
306
+ reuseItems: true
307
+
308
+ // G7 needs an empty press target below the final row even when a long column fills the viewport.
309
+ footer: Item {
310
+ width: Scroll.contentWidth(view.width, Theme.spacing.rowPaddingX)
311
+ height: root.pane ? Theme.spacing.rowPaddingY : 0
312
+ }
313
+
314
+ Flea.FastScrollHandler {
315
+ parent: view
316
+ flickable: view
317
+ }
318
+
319
+ Flea.ViewportScrollBar {
320
+ id: verticalScroll
321
+ parent: view
322
+ anchors { top: parent.top; right: parent.right }
323
+ flickable: view
324
+ }
325
+
326
+ Flea.SelectionBand {
327
+ parent: view
328
+ pane: root.pane
329
+ flickable: view
330
+ }
331
+
332
+ // Empty space below the last row, the same rule ui/List.qml carries: the pane's own column answers at once while a peek navigates to its drawn directory first and opens its menu once the rows land.
333
+ TapHandler {
334
+ acceptedButtons: Qt.RightButton
335
+ onTapped: function (eventPoint) {
336
+ if (!Tap.onBackground(view, eventPoint))
337
+ return
338
+ if (root.pane !== null)
339
+ root.backgroundMenuRequested(eventPoint)
340
+ else
341
+ root.neighbourBackgroundRequested(eventPoint)
342
+ }
343
+ }
344
+
345
+ delegate: Flea.ColumnRow {
346
+ id: cell
347
+ required property int index
348
+ // Parked while pooled (ColumnRow.live): a parked value reads itself back, so parking re-runs nothing that draws.
349
+ readonly property int listingIndex: !cell.live ? -1 : root.pane ? Filter.at(root.pane.shown, index) : index
350
+ // Filed by listing row in the column's cursor mark, which sets cursor; see ui/CursorMark.qml.
351
+ property int markRow: -1
352
+ // Built ahead of a landing past the shown rows: parked hidden until the landing adopts it.
353
+ property bool prebuilt: false
354
+ Component.onCompleted: if (!root.prebuild.built(cell)) cursorMark.place(cell)
355
+ Component.onDestruction: root.prebuild.gone(cell)
356
+ ListView.onReused: root.prebuild.adoptCell(cell)
357
+ onListingIndexChanged: cursorMark.place(cell)
358
+ // Each column keeps the scroll lane clear, the same rule ui/List.qml follows.
359
+ width: Scroll.contentWidth(view.width, Theme.spacing.rowPaddingX)
360
+ paintWidth: view.width
361
+ // A shrunk listing subscripts out of range under a delegate not yet released, and QML
362
+ // hands that back as undefined; every row reader in the tree tests against a real null.
363
+ row: !cell.live ? cell.row : root.pane ? root.pane.rowFor(listingIndex) : root.rows[index] !== undefined ? root.rows[index] : null
364
+ thumb: !cell.live ? cell.thumb : root.pane !== null && Thumbs.allowed(row, ViewState.thumbnailMode) ? root.pane.thumbFor(listingIndex) : ""
365
+ showSize: root.showsSize
366
+ dirSize: !cell.live ? cell.dirSize : root.pane !== null ? DirSizes.cellFor(root.pane.dirSizeState, listingIndex) : null
367
+ pane: root.pane
368
+ // The clipboard mark is looked up only on the pane's own column, and never while it is empty.
369
+ clipMark: !cell.live ? cell.clipMark : root.clipEmpty ? "" : (root.pane !== null ? ClipMarks.markForRow(root.pane, cell.row ? cell.row.n : "", root.pane.clipboard) : "")
370
+ // The list and the grid both mark a selection member apart from the cursor; so does this.
371
+ selected: cell.live && root.pane !== null && root.pane.isSelected(listingIndex)
372
+ dropTarget: dragSession.dropIndex >= 0 && listingIndex === dragSession.dropIndex
373
+ dropCopying: dragSession.dragCopy
374
+ dropLinking: dragSession.dragLink
375
+ // Read off the normalised row above: subscripting rows again hands a shrunk listing's undefined to a bool.
376
+ lifted: !cell.live ? cell.lifted : root.liftedName.length > 0 && row !== null && row.n === root.liftedName
377
+ dim: cell.live ? root.dim && !lifted : cell.dim
378
+ // The renaming row is always the cursor row; it hides its own name under the editor, as ui/Row.qml does.
379
+ renaming: cell.cursor && root.renaming
380
+ errorGrowth: cell.cursor && root.renameErrorHeight > 0 ? Math.max(root.renameErrorHeight, renameLoader.y + renameLoader.height - root.renameTop - Theme.fileRowHeight) : 0
381
+ // The column's own budget, so no row measures its own text to elide it.
382
+ nameBudget: cell.showChevron ? root.nameBudgetChevron : root.nameBudgetPlain
383
+
384
+ TapHandler {
385
+ id: tap
386
+ acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
387
+ // A held press must still tap on release.
388
+ longPressThreshold: 0
389
+ // A press held past the interval must not fire while the button
390
+ // is still down; ColumnsArea stops the pane's timer from onRowPressed.
391
+ onPressedChanged: if (pressed) root.rowPressed(cell.listingIndex)
392
+ onTapped: function (eventPoint, button) {
393
+ if (root.pane !== null) {
394
+ if (cell.listingIndex < 0 || !cell.row) return
395
+ if (button === Qt.MiddleButton)
396
+ root.tabRequested(cell.row)
397
+ else if (button === Qt.RightButton)
398
+ root.menuRequested(cell.listingIndex, eventPoint)
399
+ else if (cell.onSizeCell(eventPoint.position)) {
400
+ if (tap.tapCount === 1) root.pane.measureDirs([cell.listingIndex])
401
+ } else
402
+ root.picked(cell.listingIndex, tap.tapCount, tap.point.modifiers, Tap.onName(cell.nameItem(), cell, eventPoint.position, false))
403
+ return
404
+ }
405
+ if (button === Qt.RightButton && root.rows[index]) {
406
+ root.neighbourMenuRequested(root.rows[index].n)
407
+ return
408
+ }
409
+ var verb = Tap.tappedColumn(root.rows[index], button, tap.tapCount)
410
+ if (verb === "openTab")
411
+ root.tabRequested(root.rows[index])
412
+ else if (verb.length > 0)
413
+ root.activated(root.rows[index].n, verb === "reveal")
414
+ }
415
+ }
416
+
417
+ Flea.RowDrag {
418
+ session: dragSession
419
+ listingIndex: cell.listingIndex
420
+ row: cell.row
421
+ }
422
+ }
423
+ }
424
+
425
+ // A denied peek answers zero rows, the exact count an empty directory answers, so a locked column draws States.dc.html's Locked tile rather than reading as an empty one.
426
+ Flea.StateMessage {
427
+ anchors.fill: parent
428
+ listingState: root.lockedMode >= 0 ? "locked" : "ready"
429
+ lockedMode: root.lockedMode
430
+ total: root.rows.length
431
+ }
432
+
433
+ // The column boundary, one per pane and never one per row; an inactive Loader builds no pane so draws none.
434
+ Flea.Divider {
435
+ anchors.right: parent.right
436
+ anchors.top: parent.top
437
+ anchors.bottom: parent.bottom
438
+ visible: root.showDivider
439
+ }
440
+
441
+ // corner: one editor for this column, never one inside each row. A delegate binding that follows
442
+ // the pane's renamingIndex costs this column its keys, measured on the box: the comma that opens
443
+ // Settings stopped reaching ui/js/Focus.js, which case_overlays catches. An overlay follows no
444
+ // delegate, so the keys are safe by construction and only the active column ever draws one.
445
+ readonly property int renameViewIndex: root.pane !== null && root.pane.renamingIndex >= 0
446
+ ? Filter.viewOf(root.pane.shown, root.pane.renamingIndex) : -1
447
+ readonly property bool renaming: root.renameViewIndex >= 0
448
+ // What ui/Pane.qml's renameEditor() hands ui/Ipc.qml, the shape a list delegate hands it.
449
+ readonly property Item editorField: renameLoader.item as Item
450
+ readonly property string editorText: renameLoader.item ? renameLoader.item.current : ""
451
+ function commitEditor() { return renameLoader.item ? renameLoader.item.commit() : false }
452
+
453
+ // The span ColumnRow draws its name in, one gap after the mark to one gap before its size cell, and nothing beyond it.
454
+ readonly property real renameLeft: Theme.spacing.rowPaddingX + Theme.iconSize + Theme.spacing.gap
455
+ // Read when the editor is built, as its name is, because rowFor answers only once the row is held.
456
+ function renamingFolder() {
457
+ var row = root.pane ? root.pane.rowFor(root.pane.renamingIndex) : null
458
+ return !!row && row.d === true
459
+ }
460
+ // The renaming row is the cursor row, so a folder carries its chevron, and the size cell sits left of it as ColumnRow anchors both.
461
+ readonly property real renameRight: Theme.spacing.rowPaddingX + (renameLoader.item !== null && root.renamingFolder() ? Theme.font.caption : 0)
462
+ + (root.showsSize ? 2 * Theme.spacing.gap + Theme.column.size : 0)
463
+ readonly property real renameWidth: Math.max(0, Scroll.contentWidth(view.width, Theme.spacing.rowPaddingX) - root.renameLeft - root.renameRight)
464
+ readonly property real renameTop: root.renameViewIndex * Theme.fileRowHeight
465
+ // The editor owns its height, one line box; the column centres it in the row on whole pixels.
466
+ readonly property real renameY: root.renameTop + Math.round((Theme.fileRowHeight - (renameLoader.item ? renameLoader.item.fieldHeight : 0)) / 2)
467
+ readonly property real renameErrorHeight: renameLoader.item ? renameLoader.item.errorHeight : 0
468
+ // Set when an error line appears or changes height, and spent by the view's next contentHeight change.
469
+ property bool containRenameError: false
470
+ onRenameErrorHeightChanged: root.containRenameError = root.renameErrorHeight > 0
471
+
472
+ Loader {
473
+ id: renameLoader
474
+ parent: view.contentItem
475
+ // Loaded only while a rename is open: a RenameField built beside every row reports its own
476
+ // hide at creation, and that hide is an abandon.
477
+ active: root.renaming
478
+ // The editor leaves focus in this ListView, which eats Up and Down, so this pane's columns area takes it back in any view.
479
+ onActiveChanged: if (!active && view.focus && root.pane && root.pane.columnsArea) root.pane.columnsArea.focus = true
480
+ x: root.renameLeft
481
+ y: root.renameY
482
+ width: root.renameWidth
483
+ z: 2
484
+ sourceComponent: Flea.RenameField {
485
+ height: implicitHeight
486
+ pane: root.pane
487
+ errorSpan: Math.max(0, root.renameWidth + root.renameRight - Theme.spacing.rowPaddingX)
488
+ name: root.pane && root.pane.rowFor(root.pane.renamingIndex)
489
+ ? String(root.pane.rowFor(root.pane.renamingIndex).n).split("/").pop() : ""
490
+ onCommitted: function (newName) { root.pane.commitRename(newName) }
491
+ onAbandoned: root.pane.renamingIndex = -1
492
+ }
493
+ }
494
+
495
+ // For ui/Ipc.qml's columnChildEmpty readers: the tile's state and its mark's box.
496
+ readonly property Item emptyItem: emptyTile
497
+ Loader {
498
+ anchors.fill: parent
499
+ active: root.loadingRows
500
+ sourceComponent: Flea.LoadingState {
501
+ heldOff: true
502
+ onShownChanged: root.loadingShown(shown)
503
+ Component.onCompleted: if (shown) root.loadingShown(true)
504
+ }
505
+ }
506
+ // The same hero the list draws, per the operator: a peeked empty directory animates like the pane's own.
507
+ Flea.EmptyState {
508
+ id: emptyTile
509
+ anchors.fill: parent
510
+ visible: root.drawsEmpty && root.rows.length === 0 && root.lockedMode < 0
511
+ }
512
+
513
+ // Cursor can move off screen through keyboard, so column follows it with context.
514
+ // Selection ensures whole row (context 0); showRow spent margin, second margin would move clicked row.
515
+ onSelectedIndexChanged: {
516
+ root.prebuild.kick()
517
+ if (root.selectedIndex < 0)
518
+ return
519
+ var at = root.pane ? Filter.viewOf(root.pane.shown, root.selectedIndex) : root.selectedIndex
520
+ if (root.visible || root.keptTotal === root.rowTotal)
521
+ root.showCursor(at, 0)
522
+ else
523
+ root.heldY = ScrollOff.containY(at * Theme.fileRowHeight, Theme.fileRowHeight, root.heldY, view.height)
524
+ }
525
+ }