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
package/ui/Row.qml ADDED
@@ -0,0 +1,476 @@
1
+ import QtQuick
2
+ import Quickshell
3
+ import qs.Commons
4
+ import "js/Columns.js" as Columns
5
+ import "js/DirSizes.js" as DirSizes
6
+ import "js/Format.js" as Format
7
+ import "js/Icons.js" as Icons
8
+ import "js/LangMarks.js" as LangMarks
9
+ import "js/Match.js" as Match
10
+ import "js/Recent.js" as Recent
11
+ import "." as Flea
12
+
13
+ Item {
14
+ id: root
15
+
16
+ property var row: null
17
+ function dateStamp() { if (root.row && root.row.trash) { var n=Date.parse(root.row.trash.deleted); return isFinite(n) ? n/1000 : null }; return root.row ? (root.row.used === undefined ? root.row.m : root.row.used) : null }
18
+ property bool cursor: false
19
+ property bool paneFocused: true
20
+ property bool dualMode: false
21
+ readonly property real markSlot: root.dualMode ? Theme.markSize : Theme.iconSize
22
+ readonly property real sizeWidth: root.dualMode ? Theme.dualColumn.size : Theme.column.size
23
+ property bool hovered: false
24
+ property string thumb: ""
25
+ property bool selected: false
26
+ // List.qml derives it per visible row, so an empty clipboard costs nothing.
27
+ property string clipMark: ""
28
+ // True while a strip explains the run, so the highlight content builds with the strip and no keystroke pays for it.
29
+ property bool markArmed: false
30
+ // True from the turn after a search strip's first frame, so the location layout builds hidden and an answer only shows it.
31
+ property bool locateArmed: false
32
+ // The mark's own size: 12 px in the muted role, 9 px after the name, per the board.
33
+ readonly property int clipPx: Theme.clipMarkSize
34
+ // The per-response dictionary row.k indexes into; List.qml hands down the same array every row of one response shares.
35
+ property var kindNames: []
36
+ // The row is its own rename editor while this is true, per the States artboard.
37
+ property bool renaming: false
38
+ property var renamePane: null
39
+ // The folder under a drag right now, per States.dc.html "Drop target"; List.qml's delegate binds it.
40
+ property bool dropTarget: false
41
+ // Whether that drop would copy, so the label can say which; the status bar says the rest.
42
+ property bool dropCopying: false
43
+ property bool dropLinking: false
44
+ // A directory's recursive size, resolved by index in List.qml the same way thumb already is; null until it arrives.
45
+ property var dirSize: null
46
+ // The picker's rows start one slot further in for its check; the window's own leave this at zero.
47
+ property real leadingSlot: 0
48
+ // The picker's second difference: SendPicker.html's narrow date column and its compact form.
49
+ property bool compactDate: false
50
+ property bool foregroundMetadata: false
51
+ readonly property real dateWidth: root.dualMode ? Theme.dualColumn.date : root.compactDate ? Theme.column.pickerDate : Theme.column.date
52
+ // The picker's third: it hides the columns its own board does not draw, and the window's own set stays ViewState's.
53
+ property var hiddenCols: ViewState.hiddenCols
54
+ // Non-empty while a search or filter is narrowing the listing: the run to paint, and the switch to the search column set.
55
+ property string searchQuery: ""
56
+ // Which of the two is narrowing. A filter keeps the ordinary columns, because its rows are this directory's own and their names are plain names, not paths.
57
+ property bool filtering: false
58
+ // Search and Recent split the path into a base name and location; see docs/protocol.md "search".
59
+ property bool recenting: false
60
+ readonly property bool searching: !root.filtering && root.searchQuery.length > 0 && root.row !== null && root.row.n.length > 0
61
+ readonly property bool locating: root.searching || root.recenting
62
+ readonly property string displayName: Match.rowName(root.row, root.locating)
63
+ // FleaWindow.html and ThemeRoles.html both spell it "shell -> /usr/share/omarchy".
64
+ readonly property string linkMark: root.row && root.row.l ? " -> " + root.row.l : ""
65
+ // The name, then a link's target; a folder carries no slash, its glyph and the folders-first order already say it.
66
+ readonly property string decoratedName: root.displayName + root.linkMark
67
+ readonly property string locationText: root.locating && root.row ? (root.recenting ? Recent.locationUnder(root.row.trash ? root.row.trash.original.replace(/^\//, "") : root.row.n, Quickshell.env("HOME") || "") : Match.location(root.row.n)) : ""
68
+ // flea-qml: a content search's match, "line: text", shown before the location; empty otherwise.
69
+ readonly property string matchText: root.searching && root.row && root.row.g ? root.row.g.l + ": " + root.row.g.t : ""
70
+ readonly property var nameRun: Match.run(root.displayName, root.searchQuery)
71
+ // Assigned by List.qml's shared budgets; -2 keeps the local geometry default for PickerList and drop-target rows.
72
+ property int assignedNameBudget: -2
73
+ property real paintWidth: 0 // Caller view width; fills paint to it under the lane, content keeps rowWidth.
74
+ // Local measured geometry for PickerList, drop targets and unlaid rows; a function so ordinary rows pay no floor.
75
+ function localNameBudget() { return Theme.bodyAdvance > 0 && name.width > 0 ? Math.floor(name.width / Theme.bodyAdvance) : -1 }
76
+ // Ordinary List rows share; drop targets keep local measured geometry with the label's own reserve.
77
+ readonly property int nameBudget: root.dropTarget ? root.localNameBudget() : (root.assignedNameBudget > -2 ? root.assignedNameBudget : root.localNameBudget())
78
+ readonly property string elidedName: root.nameRun.start < 0 && root.nameBudget >= 0 ? Format.middleElide(root.decoratedName, root.nameBudget) : root.decoratedName
79
+ // A long name would otherwise hide the location entirely, and the location is what tells two matches apart.
80
+ readonly property real nameShare: Theme.searchNameShare
81
+ // What the name and location share: the row less its padding, the mark, their own gap, and the size column while it is drawn.
82
+ readonly property real searchSlot: Math.max(0, root.width - 2 * Theme.spacing.rowPaddingX - root.markSlot - 2 * Theme.spacing.gap
83
+ - (root.sizeShown ? root.sizeWidth + Theme.spacing.gap : 0))
84
+
85
+ // The columns this row's width affords. A column that is not drawn takes neither its width nor its gap, so the chain collapses onto its right neighbour.
86
+ property var assignedCols: null // Set by List.qml; null keeps the local default below.
87
+ readonly property var cols: root.assignedCols !== null ? root.assignedCols : root.recenting ? Theme.columns(root.width, root.hiddenCols, root.dateWidth, true, root.dualMode) : root.dualMode ? Theme.dualColumns(root.width, root.hiddenCols) : Theme.columns(root.width, root.hiddenCols, root.dateWidth)
88
+ readonly property bool modeShown: !root.locating && root.cols.mode
89
+ readonly property bool sizeShown: root.cols.size
90
+ readonly property bool dateShown: (!root.searching || root.recenting) && root.cols.date
91
+ readonly property bool kindShown: !root.locating && root.cols.kind
92
+
93
+ // A lifted row is the cursor, the pointer, or a selection member; all three take the same fill treatment, per qui Minimal.
94
+ property bool lifted: root.cursor || root.hovered || root.selected || root.dropTarget
95
+ // The OEM derives its secondary ink from the foreground rather than reading a separate palette key.
96
+ readonly property color dim: Theme.color.metadata
97
+ // One ink serves four cells, lifts metadata to foreground and carries cut dim without child opacity.
98
+ readonly property color cellInk: Util.alpha(root.lifted || root.foregroundMetadata ? Theme.color.foreground : root.dim, root.dimOpacity)
99
+ // A cut row dims its content, never the state fills, and every dimmed child reads this one value.
100
+ readonly property real dimOpacity: root.clipMark === "scissors" ? Theme.disabledOpacity : 1
101
+ // One helper, so each dimmed colour multiplies the cut without a second binding.
102
+ function dimmed(base) { return Util.alpha(base, root.dimOpacity) }
103
+ // A thumbnail path is not a thumbnail: the cache file can be evicted between the pane's answer
104
+ // and the decode, and a row whose Image failed to load has to be marked by its kind instead.
105
+ readonly property bool thumbDrawn: root.thumb.length > 0 && thumbImage.status !== Image.Error
106
+ // One filename lookup; only a mapped row without a thumbnail builds the mark's Loader.
107
+ readonly property string langSlug: ViewState.langMarks ? LangMarks.slugForRow(root.row) : ""
108
+ property var langLoader: null
109
+ function syncLangMark() { LangMarks.syncMark(root, icon, Qt.resolvedUrl("LangMarkLoader.qml"), Component.Ready) }
110
+ onLangSlugChanged: root.syncLangMark()
111
+ onThumbDrawnChanged: root.syncLangMark()
112
+
113
+ // The editor sits inside the row's own height at every density; only an error line below it adds to it.
114
+ implicitHeight: root.renaming && renameLoader.item ? Theme.fileRowHeight + renameLoader.item.errorHeight : Theme.fileRowHeight
115
+ implicitWidth: parent ? parent.width : 0
116
+
117
+ Accessible.role: Accessible.ListItem
118
+ Accessible.name: root.displayName
119
+ // The compact form drops the clock, so the picker's rows carry the whole stamp here instead; this tree has no tooltip.
120
+ Accessible.description: root.compactDate && root.dateStamp() !== null ? Format.date(root.dateStamp()) : ""
121
+
122
+ Rectangle {
123
+ width: root.paintWidth > 0 ? root.paintWidth : parent.width
124
+ height: parent.height
125
+ // The cursor uses accent ink; marked rows keep the OEM's distinct selection rung, muted to the selected rung in a pane without focus.
126
+ color: root.cursor && root.paneFocused ? Style.selectedAccentFill
127
+ : root.selected ? (root.paneFocused ? Style.selectionFill : Style.selectedFill)
128
+ : root.hovered ? Style.hoverFill
129
+ : "transparent"
130
+ }
131
+
132
+ // Twice the hairline, thick enough to read as a cursor mark against the row edge.
133
+ Rectangle {
134
+ width: Theme.spacing.hairline * 2
135
+ height: parent.height
136
+ color: !root.cursor ? "transparent" : root.paneFocused ? Theme.color.accent : Theme.color.mutedFrame
137
+ }
138
+
139
+ // One Loader for the drop frame, the drop label and the clip mark, so a row at rest builds none.
140
+ Loader {
141
+ id: dropLoader
142
+ active: root.dropTarget || (root.clipMark.length > 0 && !root.renaming && !root.searching)
143
+ anchors.fill: parent
144
+ onActiveChanged: dropLoader.setSource(dropLoader.active ? Qt.resolvedUrl("RowDropTarget.qml") : "", { row: root })
145
+ Component.onCompleted: if (dropLoader.active) dropLoader.setSource(Qt.resolvedUrl("RowDropTarget.qml"), { row: root })
146
+ onStatusChanged: if (status === Loader.Error) throw new Error("RowDropTarget.qml did not load: Loader status " + status)
147
+ }
148
+
149
+ // A thumbnail is a decoded image and stays one; the icon beside it is a native mark. The two
150
+ // share this slot and exactly one is visible, chosen by whether the pane holds a thumbnail path.
151
+ Image {
152
+ id: thumbImage
153
+ visible: root.thumbDrawn
154
+ opacity: root.dimOpacity
155
+ anchors.left: parent.left
156
+ anchors.leftMargin: Theme.spacing.rowPaddingX + root.leadingSlot
157
+ anchors.verticalCenter: parent.verticalCenter
158
+ width: root.markSlot
159
+ height: root.markSlot
160
+ // Sized on purpose, see AGENTS.md "The thumbnail decode arm": it caps the themed icon and saves 158 KB a thumbnail.
161
+ sourceSize.width: root.markSlot
162
+ sourceSize.height: root.markSlot
163
+ fillMode: Image.PreserveAspectFit
164
+ // A synchronous decode on the UI thread would land inside a scrolled frame.
165
+ asynchronous: true
166
+ source: root.iconSource()
167
+ }
168
+
169
+ Glyph {
170
+ id: icon
171
+ visible: !root.thumbDrawn && root.langSlug === ""
172
+ anchors.left: parent.left
173
+ anchors.leftMargin: Theme.spacing.rowPaddingX + root.leadingSlot
174
+ anchors.verticalCenter: parent.verticalCenter
175
+ width: root.markSlot
176
+ height: root.markSlot
177
+ name: root.row ? Icons.glyphForRow(root.row.i, root.row.p) : Icons.FALLBACK
178
+ color: root.dimmed(root.dualMode ? (root.cursor && root.paneFocused ? Theme.color.accent : Theme.color.mutedFrame) : root.lifted ? Theme.color.foreground : Theme.color.metadataFrame)
179
+ }
180
+
181
+ // What the row actually draws, so a test catches the binding being cut and not only the lookup.
182
+ readonly property alias iconUrl: thumbImage.source
183
+ // Whether it actually opened, because a URL a test can read is not proof that Qt could load it.
184
+ readonly property alias iconStatus: thumbImage.status
185
+ readonly property int namePx: name.pixelSize
186
+ // The thumbnail's own box, for ui/Ipc.qml's rowThumbRect: pixels are counted inside it and not in the name.
187
+ readonly property Item thumbItem: thumbImage
188
+ // The glyph name actually bound, the same alias idiom as iconUrl, for the icon-path test case.
189
+ readonly property alias glyphName: icon.name
190
+
191
+ // ui/List.qml's click-away commit reaches the open editor through this, and reads back whether
192
+ // a commit really happened: an abandon must not leave renameKeepsPointerRow standing.
193
+ function commitEditor() { return renameLoader.item ? renameLoader.item.commit() : false }
194
+
195
+ // What the editor holds right now, for tests/ui.sh through ui/Ipc.qml's renameEditorText.
196
+ readonly property string editorText: renameLoader.item ? renameLoader.item.current : ""
197
+ readonly property Item editorField: renameLoader.item as Item
198
+
199
+ signal renameCommitted(string newName)
200
+ signal renameAbandoned()
201
+
202
+ // Built only while renaming; a Loader destroys it without a hide, so RenameField's begun guard owns the abandon.
203
+ Loader {
204
+ id: renameLoader
205
+ active: root.renaming
206
+ // The label slot on whole pixels: a dual pane's width and mark slot are fractional, and the frame is a hairline.
207
+ x: Math.round(icon.x + icon.width) + Theme.spacing.gap
208
+ y: Math.round((root.height - renameLoader.height) / 2)
209
+ width: Math.round(mode.x - (root.modeShown ? Theme.spacing.gap : 0)) - x
210
+ sourceComponent: Flea.RenameField {
211
+ height: implicitHeight
212
+ pane: root.renamePane
213
+ viewport: root.ListView.view
214
+ name: root.displayName
215
+ onCommitted: function (newName) { root.renameCommitted(newName) }
216
+ onAbandoned: root.renameAbandoned()
217
+ }
218
+ }
219
+
220
+ // corner: a filename is arbitrary text, so PlainText everywhere; MatchText draws its runs the same way.
221
+ MatchText {
222
+ id: name
223
+ visible: !root.locating && !root.renaming
224
+ anchors.left: icon.right
225
+ anchors.leftMargin: Theme.spacing.gap
226
+ anchors.right: mode.left
227
+ anchors.rightMargin: (root.modeShown ? Theme.spacing.gap : 0) + (root.clipMark.length > 0 ? Theme.spacing.gap + root.clipPx : 0) + (root.dropTarget ? root.dropExtra() : 0)
228
+ anchors.verticalCenter: parent.verticalCenter
229
+ text: root.elidedName
230
+ // Hidden while the row locates, or may at its next key, so it builds no mark beside the drawn one; a filter's own run still draws.
231
+ matchStart: root.locating || (root.locateArmed && !root.filtering) ? -1 : root.nameRun.start
232
+ matchLength: root.nameRun.length
233
+ armed: root.markArmed && !root.locating
234
+ color: root.dimmed(root.nameColor())
235
+ accent: root.dimmed(Theme.color.accent)
236
+ elideMiddle: true
237
+ }
238
+
239
+ // One lazy path split: Recent reserves Location; search keeps the inline name share.
240
+ Loader {
241
+ id: locatingLoader
242
+ active: root.locating || root.locateArmed
243
+ visible: root.locating
244
+ anchors.left: icon.right
245
+ anchors.leftMargin: Theme.spacing.gap
246
+ anchors.right: size.left
247
+ anchors.rightMargin: root.sizeShown && !root.dualMode ? Theme.spacing.gap : 0
248
+ anchors.top: parent.top
249
+ anchors.bottom: parent.bottom
250
+ sourceComponent: Item {
251
+ readonly property var owner: parent.parent
252
+ property alias location: location
253
+ MatchText {
254
+ id: searchName
255
+ anchors.left: parent.left
256
+ anchors.verticalCenter: parent.verticalCenter
257
+ width: root.recenting ? Math.max(0, parent.width - (parent.owner.cols.location ? Theme.column.location + Theme.spacing.gap : 0)) : Math.min(implicitWidth, root.searchSlot * parent.owner.nameShare)
258
+ text: root.decoratedName
259
+ matchStart: root.nameRun.start
260
+ matchLength: root.nameRun.length
261
+ armed: root.markArmed || root.locateArmed
262
+ color: root.dimmed(root.nameColor())
263
+ accent: root.dimmed(Theme.color.accent)
264
+ // A search base name keeps its extension the same way a list name does.
265
+ elideMiddle: true
266
+ }
267
+
268
+ Text {
269
+ id: location
270
+ visible: !parent.owner.recenting || parent.owner.cols.location
271
+ anchors.left: searchName.right
272
+ anchors.leftMargin: parent.owner.recenting && !parent.owner.cols.location ? 0 : Theme.spacing.gap
273
+ anchors.right: parent.right
274
+ anchors.verticalCenter: parent.verticalCenter
275
+ // A content search leads with the matched text, so the location gives way first.
276
+ text: root.matchText.length > 0 ? root.matchText + (root.locationText.length > 0 ? " " + root.locationText : "") : root.locationText
277
+ color: root.cellInk
278
+ font.family: Theme.font.family
279
+ font.pixelSize: Theme.font.caption
280
+ elide: root.matchText.length > 0 ? Text.ElideRight : Text.ElideLeft
281
+ textFormat: Text.PlainText
282
+ }
283
+ }
284
+ }
285
+
286
+ // The four metadata cells bind straight to the row; a hidden column holds no text, because a laid-out Text costs memory drawn or not.
287
+ Text {
288
+ id: mode
289
+ anchors.right: size.left
290
+ anchors.rightMargin: (root.row && root.row.shown ? Theme.tagSlotWidth + Theme.spacing.gap : 0) + (root.sizeShown && !root.dualMode ? Theme.spacing.gap : 0)
291
+ anchors.verticalCenter: parent.verticalCenter
292
+ visible: root.modeShown && !root.dropTarget
293
+ width: root.modeShown ? Theme.column.mode : 0
294
+ text: root.modeShown && root.row ? Format.permissions(root.row.p) : ""
295
+ color: root.cellInk
296
+ font.family: Theme.font.family
297
+ font.pixelSize: Theme.font.caption
298
+ elide: Text.ElideRight
299
+ textFormat: Text.PlainText
300
+ }
301
+ // A tagged row mounts its swatches (ui/TagSlot.qml) on first need and keeps them; an untagged row builds nothing.
302
+ property var tagItem: null
303
+ onRowChanged: {
304
+ var names = root.row ? root.row.tg : undefined
305
+ if (root.tagItem !== null) root.tagItem.tags = names || []
306
+ else if (names !== undefined) root.tagItem = Qt.createComponent("TagSlot.qml").createObject(root, { tags: names, after: mode })
307
+ }
308
+ Text {
309
+ id: size
310
+ anchors.right: modified.left
311
+ anchors.rightMargin: root.dateShown && !root.dualMode ? Theme.spacing.gap : 0
312
+ anchors.verticalCenter: parent.verticalCenter
313
+ visible: root.sizeShown && !root.dropTarget
314
+ width: root.sizeShown ? root.sizeWidth : 0
315
+ text: root.sizeShown && root.row ? root.sizeText() : ""
316
+ color: root.cellInk
317
+ font.family: Theme.font.family
318
+ font.pixelSize: Theme.font.caption
319
+ horizontalAlignment: Text.AlignRight
320
+ // A narrow cell loses the ⚖️ before any digit of the size.
321
+ elide: Text.ElideLeft
322
+ textFormat: Text.PlainText
323
+ }
324
+ Text {
325
+ id: modified
326
+ anchors.right: kind.left
327
+ anchors.rightMargin: root.kindShown ? Theme.spacing.gap : 0
328
+ anchors.verticalCenter: parent.verticalCenter
329
+ visible: root.dateShown && !root.dropTarget
330
+ width: root.dateShown ? root.dateWidth : 0
331
+ text: root.dateShown ? root.dateText() : ""
332
+ // Short-circuit on the switch first, so with the switch off no row enters the library.
333
+ color: (root.dateShown && ViewState.highlightToday && Format.isRecent(root.dateStamp(), ViewState.todayStart)) ? root.dimmed(Theme.color.foreground) : root.cellInk
334
+ font.family: Theme.font.family
335
+ font.pixelSize: Theme.font.caption
336
+ horizontalAlignment: Text.AlignRight
337
+ elide: Text.ElideRight
338
+ textFormat: Text.PlainText
339
+ }
340
+ Text {
341
+ id: kind
342
+ anchors.right: parent.right
343
+ anchors.rightMargin: Theme.spacing.rowPaddingX
344
+ anchors.verticalCenter: parent.verticalCenter
345
+ visible: root.kindShown && !root.dropTarget
346
+ width: root.kindShown ? Theme.column.kind : 0
347
+ text: root.kindShown && root.row ? root.kindText() : ""
348
+ color: root.cellInk
349
+ font.family: Theme.font.family
350
+ font.pixelSize: Theme.font.caption
351
+ elide: Text.ElideRight
352
+ textFormat: Text.PlainText
353
+ }
354
+
355
+ // A row not yet fetched is dimmed rather than blank, so scrolling reads as loading.
356
+ Rectangle {
357
+ visible: root.row === null
358
+ anchors.left: icon.right
359
+ anchors.leftMargin: Theme.spacing.gap
360
+ anchors.verticalCenter: parent.verticalCenter
361
+ width: parent.width * 0.3
362
+ height: Theme.font.caption
363
+ color: Theme.color.mutedFrame
364
+ opacity: 0.2
365
+ }
366
+
367
+ // What the tests read, built from the same values the row renders, see AGENTS.md "Testing".
368
+ function describe() {
369
+ return root.row
370
+ ? root.row.n + "|" + (root.row.d ? "dir" : "file") + "|" + Format.size(root.row.s)
371
+ : "loading"
372
+ }
373
+
374
+ // The thumbnail Image's source; empty means the row draws its Glyph instead, see the slot above.
375
+ function iconSource() {
376
+ if (!root.row || root.thumb.length === 0) {
377
+ return ""
378
+ }
379
+ // A regenerated thumbnail keeps its path, so the source mtime is the only thing that moves Qt's cache key.
380
+ return Format.fileUri(root.thumb) + "?m=" + root.row.m
381
+ }
382
+
383
+ // A directory's own row.s is its dirent size, not the walk's, so this reads root.dirSize instead, see docs/protocol.md "dirsized".
384
+ function sizeText() {
385
+ // A link's own st_size is the length of its target path, which is not a size anyone means.
386
+ if (Format.isSymlink(root.row.p))
387
+ return "link"
388
+ if (!root.row.d) {
389
+ return Format.size(root.row.s)
390
+ }
391
+ return DirSizes.folderText(root.dirSize, root.row)
392
+ }
393
+
394
+ // A folder's Size cell takes a click: measure it (src/dirsize.js). The whole cell is the target,
395
+ // since the text inside it is right-aligned and short.
396
+ function onSizeCell(point) {
397
+ if (!root.row || !root.row.d || Format.isSymlink(root.row.p) || !size.visible || size.width <= 0) return false
398
+ var at = size.mapFromItem(root, point.x, point.y)
399
+ return at.x >= 0 && at.x < size.width && at.y >= -size.y && at.y < root.height - size.y
400
+ }
401
+
402
+ // The window's one stamp, or the picker's compact three; both are cell text and nothing more.
403
+ function dateText() {
404
+ if (!root.row) {
405
+ return ""
406
+ }
407
+ var stamp = root.dateStamp()
408
+ if (stamp === null) {
409
+ return "--"
410
+ }
411
+ return root.compactDate ? Format.compactDate(stamp) : Format.date(stamp)
412
+ }
413
+
414
+ // row.k indexes root.kindNames; an index past its bounds (a row held over from an older listing) reads as empty, never a crash.
415
+ function kindText() {
416
+ if (!root.row || root.row.k === undefined) {
417
+ return ""
418
+ }
419
+ var text = root.kindNames[root.row.k]
420
+ return text !== undefined ? text : ""
421
+ }
422
+
423
+ // Semantic colour is reserved for symlink and executable, and a lifted row gives it up for contrast.
424
+ function nameColor() {
425
+ if (!root.row) {
426
+ return Theme.color.muted
427
+ }
428
+ if (root.lifted) {
429
+ return Theme.color.foreground
430
+ }
431
+ if (Format.isSymlink(root.row.p)) {
432
+ return Theme.color.symlink
433
+ }
434
+ // corner: a directory carries the execute bits, so it claims foreground before that test.
435
+ if (root.row.d) {
436
+ return Theme.color.foreground
437
+ }
438
+ if (root.row.x !== false && Format.isExecutable(root.row.p)) {
439
+ return Theme.color.executable
440
+ }
441
+ return Theme.color.foreground
442
+ }
443
+
444
+ // The drawn columns and cells, shared with Header's geometry seam.
445
+ function columnSet() { return Columns.names(root.cols) }
446
+ function cell(key) {
447
+ switch (key) {
448
+ case "location": return locatingLoader.item ? locatingLoader.item.location : null
449
+ case "mode": return mode
450
+ case "size": return size
451
+ case "date": return modified
452
+ case "kind": return kind
453
+ }
454
+ return null
455
+ }
456
+
457
+ // Test seams as functions, so no row at rest binds to drop geometry.
458
+ function dropBuilt() { return root.dropTarget && dropLoader.item !== null }
459
+ function dropLabelLeft() { return root.dropTarget && dropLoader.item ? dropLoader.item.label.x : -1 }
460
+ function dropLabelText() { return root.dropTarget && dropLoader.item ? dropLoader.item.label.text : "" }
461
+ function nameRight() { return name.x + name.width }
462
+ // The clip mark's right edge, so the drop phase reads the drawn mark and not the name.
463
+ function clipRight() { var m = dropLoader.item ? dropLoader.item.mark : null; if (!m || !m.visible || m.width <= 0) return -1; return m.x + m.width }
464
+ // The drawn name and mark, so a dim check reads colours and not an opacity.
465
+ function nameItem() { return name }
466
+ function markColor() { return icon.color }
467
+ // Extra beyond the column gap, so a fitting name keeps its width while a long one clears the label.
468
+ function dropExtra() {
469
+ if (!root.dropTarget || !dropLoader.item) return 0
470
+ var labelW = dropLoader.item.label.implicitWidth
471
+ var hidden = root.width - Theme.spacing.rowPaddingX - mode.x
472
+ var base = root.modeShown ? Theme.spacing.gap : 0
473
+ var need = labelW + Theme.spacing.gap - hidden - base
474
+ return need > 0 ? need : 0
475
+ }
476
+ }