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,63 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+
4
+ // The Columns view's preview column edge: ui/ResizeHandle.qml over the edge, and on hover the Media040 board's move-horizontal mark beside the accent line.
5
+ Item {
6
+ id: root
7
+
8
+ // The preview column's left edge in the parent's pixels; the zone is centred on the hairline just left of it.
9
+ property int edge: 0
10
+ // True from the press to the release, so the line and mark stay up while the pointer is dragged off the zone.
11
+ property bool dragging: false
12
+ // The pointer's pixels left or right of where it pressed, on every move of a drag.
13
+ signal dragged(int shift)
14
+ signal grabbed()
15
+ signal released()
16
+ signal restored()
17
+
18
+ objectName: "previewEdge"
19
+ width: handle.width
20
+ x: root.edge - 1 - Math.floor(root.width / 2)
21
+
22
+ property real pressX: 0
23
+ // False from the press until the pointer is past the platform drag distance, so a click or a jitter keeps the stored width.
24
+ property bool pulled: false
25
+
26
+ ResizeHandle {
27
+ id: handle
28
+ anchors.fill: parent
29
+ hot: root.dragging
30
+ onPressed: function (mouse) {
31
+ root.pressX = handle.mapToItem(null, mouse.x, mouse.y).x
32
+ root.dragging = true
33
+ root.pulled = false
34
+ root.grabbed()
35
+ }
36
+ // The zone reports hover moves too, so only a held drag moves the edge.
37
+ onMoved: function (mouse) {
38
+ if (!root.dragging) return
39
+ var shift = Math.round(handle.mapToItem(null, mouse.x, mouse.y).x - root.pressX)
40
+ if (!root.pulled && Math.abs(shift) > Qt.styleHints.startDragDistance) root.pulled = true
41
+ if (root.pulled) root.dragged(shift)
42
+ }
43
+ onReleased: { root.dragging = false; root.released() }
44
+ onDoubleClicked: root.restored()
45
+ }
46
+
47
+ HoverHandler { id: hover }
48
+
49
+ // The mark is built with the line: left 12 px of the edge, top at the column's middle.
50
+ Loader {
51
+ x: root.edge - 12 - root.x
52
+ y: root.height / 2
53
+ width: 16
54
+ height: 16
55
+ active: hover.hovered || root.dragging
56
+ sourceComponent: Glyph {
57
+ anchors.fill: parent
58
+ name: "move-horizontal"
59
+ color: Theme.color.foreground
60
+ maxSize: 16
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,30 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+
4
+ // What the preview column states under the name: a tall kind's one compact line, or the table of every fact.
5
+ Item {
6
+ id: root
7
+
8
+ property bool compact: false
9
+ // ui/js/Facts.js compactLine: the Kind and the tail of the one line.
10
+ property var line: ({ kind: "", tail: "" })
11
+ property var rows: []
12
+
13
+ height: root.compact ? factsLine.height : factsTable.height
14
+
15
+ Flea.PreviewFactsLine {
16
+ id: factsLine
17
+ width: root.width
18
+ visible: root.compact
19
+ kind: root.line.kind
20
+ tail: root.line.tail
21
+ }
22
+
23
+ // An empty model while the line shows, so the hidden table builds no row.
24
+ Flea.FactsTable {
25
+ id: factsTable
26
+ width: root.width
27
+ visible: !root.compact
28
+ rows: root.compact ? [] : root.rows
29
+ }
30
+ }
@@ -0,0 +1,34 @@
1
+ import QtQuick
2
+
3
+ // The tall kinds' one facts line: the Kind elides at its end so the size and the count stay whole.
4
+ Item {
5
+ id: root
6
+
7
+ // The Kind, and the " · size · count" tail, as ui/js/Facts.js compactLine returns them.
8
+ property string kind: ""
9
+ property string tail: ""
10
+
11
+ // One row of the full table, so the line sits where its first row would.
12
+ height: Math.round(Theme.font.caption * 1.5)
13
+
14
+ Text {
15
+ id: kindText
16
+ width: Math.min(implicitWidth, Math.max(0, root.width - tailText.implicitWidth))
17
+ text: root.kind
18
+ color: Theme.color.foreground
19
+ font.family: Theme.font.family
20
+ font.pixelSize: Theme.font.caption
21
+ textFormat: Text.PlainText
22
+ elide: Text.ElideRight
23
+ }
24
+
25
+ Text {
26
+ id: tailText
27
+ anchors.left: kindText.right
28
+ text: root.tail
29
+ color: Theme.color.foreground
30
+ font.family: Theme.font.family
31
+ font.pixelSize: Theme.font.caption
32
+ textFormat: Text.PlainText
33
+ }
34
+ }
@@ -0,0 +1,233 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+ import Quickshell.Io
4
+ import "." as Flea
5
+ import "js/Markdown.js" as Markdown
6
+ import "js/Format.js" as Format
7
+ import "js/PreviewKeys.js" as PreviewKeys
8
+ import "js/Scroll.js" as Scroll
9
+
10
+ // Rebuilt passive HTML and source code share the frame and its scroll lane.
11
+ // The backend supplies only fixed whitelist tags and escaped text; never raw HTML.
12
+ Item {
13
+ id: root
14
+ property bool active: false
15
+ property string path: ""
16
+ property real size: 0
17
+ readonly property int byteCeiling: 1048576
18
+ readonly property int settleMs: 160
19
+ property int maxBytes: byteCeiling
20
+ property bool truncate: false
21
+ property real cornerRadius: Math.max(0, Style.cornerRadius - Theme.spacing.hairline)
22
+ property bool compact: false
23
+ property bool externalScrollBars: false
24
+ property var backend: null
25
+ property string slot: "column"
26
+ property string view: "rendered"
27
+ property bool wrap: false
28
+ readonly property string shownView: root.view === "source" ? "source" : "rendered"
29
+ readonly property bool sourceView: root.shownView === "source"
30
+ readonly property bool overSize: root.size > root.maxBytes
31
+ readonly property bool tooLarge: root.overSize || (root.sourceView && !!root.sourceCode && root.sourceCode.answer === "large")
32
+ readonly property bool binary: root.sourceView && !!root.sourceCode && root.sourceCode.answer === "binary"
33
+ readonly property int deviceWidth: Math.max(1, Math.round(root.width * Screen.devicePixelRatio))
34
+ readonly property int deviceHeight: root.slot === "look" ? Math.max(1, Math.ceil(root.height * root.deviceWidth / Math.max(1, root.width))) : 0
35
+ property int token: -1
36
+ property bool pending: false
37
+ property bool readFailed: false
38
+ property bool hasDrawn: false
39
+ property int imageToken: -1
40
+ property int total: 0
41
+ property string imageFile: ""
42
+ property string safeHtml: ""
43
+ property string pageTitle: ""
44
+ property int renderedWidth: 0
45
+ property real zoom: 1
46
+ property bool sourceBuilt: false
47
+ readonly property var sourceCode: sourceLoader.item
48
+ readonly property var viewport: root.sourceView ? (root.sourceCode ? root.sourceCode.viewport : null) : page
49
+ readonly property Item bodyItem: root.sourceView ? root.sourceCode : page
50
+ readonly property bool failed: root.sourceView ? root.readFailed || (!!root.sourceCode && root.sourceCode.answer === "failed")
51
+ : root.readFailed
52
+ readonly property bool contentReady: root.sourceView ? !!root.sourceCode && root.sourceCode.settled
53
+ : !root.pending && root.hasDrawn
54
+ readonly property bool firstScreen: root.failed || root.tooLarge || root.binary
55
+ || (root.sourceView ? !!root.sourceCode && root.sourceCode.firstScreen : root.contentReady)
56
+ readonly property bool loading: root.active && !root.firstScreen && (root.sourceView || !root.hasDrawn)
57
+ readonly property bool blank: root.tooLarge || root.binary
58
+ readonly property string status: root.tooLarge ? "This file is too large to preview."
59
+ : root.failed ? "This file could not be read." : root.firstScreen ? "ready" : "loading"
60
+ readonly property string lineLabel: Markdown.countLine(root.sourceView && root.sourceCode ? root.sourceCode.total : root.total)
61
+ readonly property real scrollY: root.viewport ? root.viewport.contentY : 0
62
+
63
+ function captureState(window, owner, pane, column) {
64
+ var bar = column ? null : pane.barGeometry()
65
+ var frame = column ? owner.frameItem : owner.panesItem.parent
66
+ var lane = scrollBars.item ? scrollBars.item.children[0] : null
67
+ return JSON.stringify({ path: root.path, view: root.shownView, ready: root.firstScreen,
68
+ visible: column ? owner.visible : owner.revealedOpen, state: root.status,
69
+ lines: root.sourceView && root.sourceCode ? root.sourceCode.total : root.total,
70
+ count: bar ? bar.lines.text : root.lineLabel, mark: bar ? bar.markName : "html", file: root.imageFile,
71
+ width: root.renderedWidth, deviceWidth: root.deviceWidth, y: root.scrollY, zoom: root.zoom,
72
+ facts: column ? owner.factsLine.kind + owner.factsLine.tail : "", frame: window.rectOf(frame),
73
+ column: column, window: { width: window.width, height: window.height }, radius: frame.radius,
74
+ hairline: frame.border.width, ringColor: String(frame.border.color), canvasColor: String(frame.color),
75
+ viewportHeight: root.viewport ? root.viewport.height : 0, contentHeight: root.viewport ? root.viewport.contentHeight : 0,
76
+ lane: lane ? { shown: lane.shown, visible: lane.visible, rect: window.rectOf(lane) } : null,
77
+ close: bar ? { hovered: bar.close.hovered, pressed: bar.close.pressed, focused: bar.close.keyboardFocused,
78
+ ring: bar.close.ringItem.visible, centre: window.centreOf(bar.close) } : null })
79
+ }
80
+ function cancel() {
81
+ settle.stop()
82
+ if (root.pending && root.backend && typeof root.backend.askHtml === "function")
83
+ root.backend.askHtml(root.slot, "", root.deviceWidth, true)
84
+ root.token = -1
85
+ root.pending = false
86
+ }
87
+ function schedule() {
88
+ if (!root.active || root.sourceView || root.tooLarge) { root.cancel(); return }
89
+ settle.restart()
90
+ }
91
+ function ask() {
92
+ if (!root.active || root.sourceView || root.tooLarge || root.width <= 0) return
93
+ if (!root.backend || typeof root.backend.askHtml !== "function") { root.readFailed = true; return }
94
+ root.readFailed = false
95
+ root.pending = true
96
+ root.token = root.backend.askHtml(root.slot, root.path, root.deviceWidth, false, root.deviceHeight)
97
+ }
98
+ function scrollBy(rows) {
99
+ var v = root.viewport
100
+ if (!v) return
101
+ var bounds = Scroll.limitsY(v)
102
+ v.contentY = Math.max(bounds.min, Math.min(bounds.max, v.contentY + rows * Theme.rowHeight))
103
+ }
104
+ function zoomBy(steps) { if (!root.sourceView) root.zoom = PreviewKeys.zoomStep(root.zoom, steps) }
105
+ function zoomFit() { root.zoom = 1 }
106
+ function endGap() { return root.viewport ? Math.max(0, root.viewport.contentHeight - root.viewport.height - root.viewport.contentY) : -1 }
107
+ function keepTop(top) {
108
+ var v = root.sourceView ? root.viewport : null
109
+ if (!v) return
110
+ v.forceLayout()
111
+ v.positionViewAtIndex(top, ListView.Beginning)
112
+ }
113
+ onWrapChanged: if (root.sourceView && root.viewport) Qt.callLater(root.keepTop, Math.max(0, root.viewport.indexAt(0, root.viewport.contentY + 1)))
114
+
115
+ onPathChanged: {
116
+ root.cancel()
117
+ root.hasDrawn = false
118
+ root.imageFile = ""
119
+ root.safeHtml = ""
120
+ root.total = 0
121
+ root.readFailed = false
122
+ root.zoom = 1
123
+ page.contentY = 0
124
+ root.schedule()
125
+ }
126
+ onActiveChanged: root.schedule()
127
+ onSourceViewChanged: {
128
+ if (root.sourceView) root.sourceBuilt = true
129
+ root.readFailed = false
130
+ root.schedule()
131
+ }
132
+ onBackendChanged: root.schedule()
133
+ // Inline text reflows locally; resizing does not reread or rebuild the file.
134
+ onTooLargeChanged: root.schedule()
135
+ Component.onCompleted: { root.sourceBuilt = root.sourceView; root.schedule() }
136
+ Component.onDestruction: {
137
+ root.cancel()
138
+ if (root.sourceCode) root.sourceCode.active = false
139
+ }
140
+ // Settle path/view changes before requesting a bounded read.
141
+ Timer { id: settle; interval: root.settleMs; onTriggered: root.ask() }
142
+ Connections {
143
+ target: root.backend
144
+ function onHtmlResult(message) {
145
+ if (!root.active || root.sourceView || message.slot !== root.slot || message.token !== root.token) return
146
+ root.pending = false
147
+ root.readFailed = message.state !== "ready"
148
+ if (!root.readFailed) {
149
+ root.total = message.total
150
+ root.renderedWidth = root.deviceWidth
151
+ root.pageTitle = message.title || ""
152
+ root.safeHtml = message.html || ""
153
+ root.hasDrawn = true
154
+ root.imageToken = message.token
155
+ }
156
+ }
157
+ }
158
+
159
+ Flickable {
160
+ id: page
161
+ anchors.fill: parent
162
+ clip: true
163
+ visible: !root.sourceView && !root.tooLarge && !root.failed
164
+ contentWidth: Math.max(width, picture.width)
165
+ contentHeight: picture.y + picture.height + Theme.spacing.gap
166
+ boundsBehavior: Flickable.StopAtBounds
167
+ property int currentIndex: -1
168
+ function forceLayout() {}
169
+ Text {
170
+ id: picture
171
+ x: Theme.spacing.gap
172
+ y: Theme.spacing.gap
173
+ width: Math.max(0, page.width - 2 * Theme.spacing.gap)
174
+ height: implicitHeight
175
+ // Only add our fixed presentation rules to the already sanitized tags.
176
+ // No source attributes, style sheets or resources are accepted.
177
+ text: root.safeHtml.replace(/<(h[1-6]|p|pre|blockquote|ul|ol)>/g,
178
+ '<$1 style="margin-top:0.6em;margin-bottom:0.6em">')
179
+ textFormat: Text.RichText
180
+ wrapMode: Text.Wrap
181
+ color: Theme.color.foreground
182
+ font.family: Theme.font.family
183
+ font.pixelSize: (root.compact ? Theme.font.bodySmall : Theme.font.body) * root.zoom
184
+ }
185
+ }
186
+
187
+ Loader {
188
+ anchors.fill: page
189
+ active: root.active && page.visible && root.cornerRadius > 0 && GraphicsInfo.api !== GraphicsInfo.Software
190
+ source: "HtmlClip.qml"
191
+ onLoaded: {
192
+ item.target = page
193
+ item.radius = Qt.binding(function () { return root.cornerRadius })
194
+ item.roundTop = root.slot !== "look"
195
+ }
196
+ }
197
+ FileView {
198
+ id: sourceFile
199
+ path: root.active && root.sourceView && root.truncate && !root.tooLarge ? root.path : ""
200
+ printErrors: false
201
+ onLoadFailed: root.readFailed = true
202
+ }
203
+ Loader {
204
+ id: sourceLoader
205
+ anchors.fill: parent
206
+ anchors.margins: root.compact ? Theme.spacing.gap : Theme.spacing.rowPaddingX
207
+ active: root.sourceBuilt
208
+ visible: root.sourceView
209
+ source: "CodeLines.qml"
210
+ onLoaded: {
211
+ item.backend = Qt.binding(function () { return root.backend })
212
+ item.path = Qt.binding(function () { return root.path })
213
+ item.fromText = Qt.binding(function () { return root.truncate })
214
+ item.text = Qt.binding(function () { return root.truncate && sourceFile.loaded ? sourceFile.text() : null })
215
+ item.slot = Qt.binding(function () { return root.slot })
216
+ item.active = Qt.binding(function () { return root.active && root.sourceView && !root.overSize })
217
+ item.numbered = true
218
+ item.scrolls = true
219
+ item.wrap = Qt.binding(function () { return root.wrap })
220
+ item.pixelSize = Qt.binding(function () { return root.compact ? Theme.font.caption : Theme.font.body })
221
+ }
222
+ }
223
+ Flea.FastScrollHandler { flickable: root.viewport; visible: !root.externalScrollBars }
224
+ Loader {
225
+ id: scrollBars
226
+ anchors.fill: parent
227
+ property var targetView: root.viewport
228
+ active: !root.externalScrollBars && root.viewport !== null
229
+ sourceComponent: Flea.ViewportScrollBars { flickable: parent.targetView }
230
+ }
231
+ Flea.LoadingState { anchors.fill: parent; visible: root.loading }
232
+ Flea.CodeRefusal { anchors.fill: parent; visible: false; binary: root.binary; failed: root.failed; tooLarge: root.tooLarge; markName: "html" }
233
+ }
@@ -0,0 +1,253 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+ import "." as Flea
4
+ import "js/Format.js" as Format
5
+ import "js/Kinds.js" as Kinds
6
+ import "js/PreviewKeys.js" as PreviewKeys
7
+ import "js/Scroll.js" as Scroll
8
+ import "js/Thumbs.js" as Thumbs
9
+
10
+ // The Quick Look's image pane, reached only through Preview.qml's Loader. It draws the file itself:
11
+ // the 256 px cache file the column draws would be an eightfold upscale on a surface this size.
12
+ Item {
13
+ id: root
14
+
15
+ // A zoomed picture runs past the surface's edges.
16
+ clip: true
17
+
18
+ property string path: ""
19
+
20
+ // A camera RAW is drawn through the copy of its embedded JPEG that Preview.qml's meta reply names, never itself; its picture area stops above the caption band.
21
+ readonly property bool raw: Kinds.isRaw(root.path)
22
+ property string embedded: ""
23
+ property bool embeddedAnswered: false
24
+ readonly property string drawPath: root.raw ? root.embedded : root.path
25
+ readonly property real areaHeight: root.raw ? root.height - Theme.chromeHeight : root.height
26
+
27
+ // Times the fit size, on the PDF's ladder; 1 is fit.
28
+ property real zoom: PreviewKeys.PDF_ZOOM_MIN
29
+ readonly property bool zoomed: root.zoom > PreviewKeys.PDF_ZOOM_MIN
30
+ // The zoom read against fit; fit itself carries no label.
31
+ readonly property string zoomLabel: root.zoomed ? "%1%".arg(Math.round(root.zoom * 100)) : ""
32
+ // The pannable viewport, the strip under it and the sharper layer, for Preview.qml's readers and the zoom suite.
33
+ readonly property alias viewport: flick
34
+ readonly property alias band: band
35
+ readonly property alias fullPicture: sharp
36
+ // Another file is a new subject: the next one opens at fit.
37
+ onPathChanged: root.zoom = PreviewKeys.PDF_ZOOM_MIN
38
+
39
+ // The viewport's centre point stays put across a step; a picture still decoding or refused does not zoom in.
40
+ function zoomTo(next) {
41
+ if (next === root.zoom || (next > PreviewKeys.PDF_ZOOM_MIN && picture.status !== Image.Ready)) return
42
+ var fx = (flick.contentX + flick.width / 2) / flick.contentWidth
43
+ var fy = (flick.contentY + flick.height / 2) / flick.contentHeight
44
+ root.zoom = next
45
+ flick.contentX = Scroll.bounded(fx * flick.contentWidth - flick.width / 2, flick.originX, flick.contentWidth, flick.width, flick.leftMargin, flick.rightMargin)
46
+ flick.contentY = Scroll.bounded(fy * flick.contentHeight - flick.height / 2, flick.originY, flick.contentHeight, flick.height, flick.topMargin, flick.bottomMargin)
47
+ }
48
+ function zoomBy(steps) { root.zoomTo(PreviewKeys.zoomStep(root.zoom, steps)) }
49
+ function zoomFit() { root.zoomTo(PreviewKeys.PDF_ZOOM_MIN) }
50
+
51
+ // The row's cache file, held by Quick Look while this decodes: drawn between the
52
+ // ground and the picture, so it is never hidden by one nor covers the other.
53
+ property string interimThumb: ""
54
+ property real interimX: 0
55
+ property real interimY: 0
56
+ property real interimWidth: 0
57
+ property real interimHeight: 0
58
+ property bool interimVisible: false
59
+ // Set from open while this row's thumbnail may still be asked for; it only gates failed.
60
+ property bool thumbPending: false
61
+ readonly property bool interimReady: interimPicture.status === Image.Ready
62
+
63
+ // The same name the media and PDF panes give their unreadable state, so Preview.qml tests one property; failed only with no thumbnail to stand in or coming, and a decoding one keeps loading.
64
+ readonly property bool failed: root.pictureFailed && !root.thumbPending && interimPicture.status !== Image.Ready && interimPicture.status !== Image.Loading
65
+ // Every state is terminal once an owed thumbnail has landed or been refused: a failed final waits on it first.
66
+ readonly property string status: {
67
+ if (root.failed) return "This image could not be read."
68
+ return (picture.status === Image.Ready || root.fallbackShown) ? "image" : "loading"
69
+ }
70
+ // Frames in a GIF, from the same reply; the picture moves only past one.
71
+ property int frames: 0
72
+ // The original's pixels for the thumbnail fit, from Preview.qml's meta reply; 0 while unknown.
73
+ property real origW: 0
74
+ property real origH: 0
75
+ // The turn of those pixels, so the caption names the picture as drawn.
76
+ property int origOrient: 1
77
+ // A 3D model is refused with no decode attempt: Qt has no plugin for it, and each attempt logs a warning.
78
+ readonly property bool decodable: !Kinds.isModel(root.path)
79
+ // The final refused, by a decode Error, at once for a file Qt cannot decode, or once a RAW answered with no copy; the thumbnail below stands in when it decoded.
80
+ readonly property bool pictureFailed: picture.status === Image.Error || (root.interimSettled && !root.decodable) || (root.raw && root.embeddedAnswered && root.embedded.length === 0)
81
+ readonly property bool fallbackShown: root.pictureFailed && root.interimReady
82
+ readonly property string name: root.path.substring(root.path.lastIndexOf("/") + 1)
83
+
84
+ // The pixmap reader decodes only the final, one request at a time; it waits a turn after the build because Preview.qml binds the path before the thumbnail.
85
+ property bool armed: false
86
+ readonly property bool interimSettled: root.armed && interimPicture.status !== Image.Loading
87
+ Timer {
88
+ running: true
89
+ interval: 0
90
+ onTriggered: root.armed = true
91
+ }
92
+
93
+ // The letterbox ground the video pane uses: a photo almost never matches the surface's proportions.
94
+ Rectangle {
95
+ anchors.fill: parent
96
+ color: Theme.color.background
97
+ }
98
+
99
+ // The cached thumbnail at once, sized to the final's rect by the caller; it stays as the picture at the column fit when the final cannot decode.
100
+ Image {
101
+ id: interimPicture
102
+ readonly property real ownFit: Thumbs.fitScale(root.width, root.areaHeight, implicitWidth, implicitHeight,
103
+ Thumbs.posterLimit(false, implicitWidth, implicitHeight, root.origW, root.origH))
104
+ x: root.fallbackShown ? Math.round((root.width - width) / 2) : root.interimX
105
+ y: root.fallbackShown ? Math.round((root.areaHeight - height) / 2) : root.interimY
106
+ width: root.fallbackShown ? implicitWidth * ownFit : root.interimWidth
107
+ height: root.fallbackShown ? implicitHeight * ownFit : root.interimHeight
108
+ // Only while the decode runs: a final with transparent pixels would show it through.
109
+ visible: root.interimVisible && root.status === "loading" || root.fallbackShown
110
+ source: root.interimThumb.length > 0 ? Format.fileUri(root.interimThumb) : ""
111
+ fillMode: Image.Stretch
112
+ // A cache thumbnail decodes on the GUI thread in about a millisecond: the reader cannot drop a running decode.
113
+ asynchronous: false
114
+ cache: false
115
+ }
116
+
117
+ // Stretch, in an item sized to the fit of what was decoded: Qt then decodes the exact fit and never enlarges
118
+ // in the decode, where Fit decoded a covering size (2099x3149 for a portrait photo, 34680x1156 for a 3000x100
119
+ // banner, measured). A small picture draws at its own size, centred; only an SVG keeps Fit, which Stretch would distort.
120
+ readonly property bool vector: /\.svgz?$/i.test(root.path)
121
+ // The drawn picture itself, for ui/Ipc.qml's previewPictureRect: the item is sized to the
122
+ // fit of what was decoded, so its rect is the picture and not the surface it is centred on.
123
+ readonly property Item pictureItem: root.fallbackShown ? interimPicture : picture
124
+
125
+ Image {
126
+ id: picture
127
+ readonly property real fit: Thumbs.fitScale(root.width, root.areaHeight, implicitWidth, implicitHeight, 1)
128
+ x: Math.round((flick.contentWidth - width) / 2 - flick.contentX)
129
+ y: Math.round((flick.contentHeight - height) / 2 - flick.contentY)
130
+ width: root.vector ? root.width * root.zoom : implicitWidth * fit * root.zoom
131
+ height: root.vector ? root.height * root.zoom : implicitHeight * fit * root.zoom
132
+ // The sharper layer takes over once it has a frame, so a transparent picture never shows two.
133
+ visible: picture.status === Image.Ready && !sharp.drawn && !(gif.item && gif.item.ready)
134
+ // Format.fileUri, not a concatenation: a # or a ? in the name would truncate a hand-built URI.
135
+ source: root.drawPath.length > 0 && root.decodable && root.interimSettled ? Format.fileUri(root.drawPath) : ""
136
+ fillMode: root.vector ? Image.PreserveAspectFit : Image.Stretch
137
+ // A phone keeps a portrait photo's turn in EXIF, and Qt leaves it unapplied unless asked.
138
+ autoTransform: true
139
+ asynchronous: true
140
+ cache: false
141
+ // Decoded no larger than the surface: the same 6016x3900 PNG is 94 MB of texture at full size
142
+ // and 8 MB bound to this box's 2099x1156 surface, measured, for 17 ms more decode.
143
+ // corner: a zero here means unbounded to Qt, so the floor is 1 and never 0.
144
+ sourceSize.width: Math.max(1, Math.round(root.width))
145
+ sourceSize.height: Math.max(1, Math.round(root.areaHeight))
146
+ }
147
+
148
+ // Past fit the fit picture is drawn scaled until this layer has a frame.
149
+ Flea.PreviewImageSharp {
150
+ id: sharp
151
+ base: picture
152
+ active: root.zoomed
153
+ want: root.vector ? Qt.size(Math.max(1, Math.round(root.width * root.zoom)), Math.max(1, Math.round(root.height * root.zoom))) : Qt.size(0, 0)
154
+ }
155
+
156
+ // An animated GIF moves once the still is drawn, in the still's rect at any zoom; it is built for that file alone.
157
+ Loader {
158
+ id: gif
159
+ x: picture.x
160
+ y: picture.y
161
+ width: picture.width
162
+ height: picture.height
163
+ active: root.frames > 1 && /\.gif$/i.test(root.path) && picture.status === Image.Ready
164
+ source: "PreviewAnimation.qml"
165
+ onLoaded: {
166
+ item.path = Qt.binding(function () { return root.path })
167
+ item.shown = Qt.binding(function () { return root.visible })
168
+ }
169
+ }
170
+
171
+ // The pan: a drag, the wheel and the knobs move contentX and contentY, and the pictures above follow them. At fit it is the whole surface and holds still; zoomed, it is the surface less the band.
172
+ Flickable {
173
+ id: flick
174
+ width: root.width
175
+ height: root.zoomed ? root.height - band.height : root.areaHeight
176
+ contentWidth: Math.max(flick.width, picture.width)
177
+ contentHeight: Math.max(flick.height, picture.height)
178
+ interactive: root.zoomed
179
+ boundsBehavior: Flickable.StopAtBounds
180
+
181
+ // The wheel and the knobs are built at the first step past fit and go at fit: the first frame at fit holds neither.
182
+ Loader {
183
+ parent: flick
184
+ anchors.fill: parent
185
+ active: root.zoomed
186
+ sourceComponent: Flea.PreviewImagePan {}
187
+ }
188
+ }
189
+
190
+ // The zoom as a number under the picture, a media strip tall with no divider; absent at fit, except that a RAW's fit says what is drawn.
191
+ readonly property bool captioned: root.raw && !root.zoomed && picture.status === Image.Ready
192
+ readonly property string caption: "Embedded preview \u00b7 %1 \u00d7 %2".arg(root.origOrient >= 5 ? root.origH : root.origW).arg(root.origOrient >= 5 ? root.origW : root.origH)
193
+ Rectangle {
194
+ id: band
195
+ visible: root.zoomed || root.captioned
196
+ anchors.left: parent.left
197
+ anchors.right: parent.right
198
+ anchors.bottom: parent.bottom
199
+ height: Theme.chromeHeight
200
+ color: root.zoomed ? Theme.color.surface : Theme.color.background
201
+
202
+ Text {
203
+ anchors.centerIn: parent
204
+ text: root.zoomed ? root.zoomLabel : root.caption
205
+ color: root.zoomed ? Theme.color.foreground : Theme.color.muted
206
+ font.family: Theme.font.family
207
+ font.pixelSize: Theme.font.caption
208
+ font.features: { "tnum": 1 }
209
+ textFormat: Text.PlainText
210
+ }
211
+ }
212
+
213
+ // A failed decode is a mark and a sentence, never a bare ground: the blank-frame class again otherwise.
214
+ Column {
215
+ anchors.centerIn: parent
216
+ width: parent.width - 2 * Theme.spacing.rowPaddingX
217
+ spacing: Theme.spacing.gap
218
+ visible: false // Failed previews remain blank.
219
+
220
+ Flea.Glyph {
221
+ anchors.horizontalCenter: parent.horizontalCenter
222
+ // A failure mark stands alone, so it takes the pane-state ceiling States.dc.html draws at 40.
223
+ maxSize: Theme.stateMarkSize
224
+ width: Theme.stateMarkSize
225
+ height: Theme.stateMarkSize
226
+ name: "alert"
227
+ color: Theme.color.error
228
+ }
229
+
230
+ Text {
231
+ width: parent.width
232
+ horizontalAlignment: Text.AlignHCenter
233
+ text: root.status
234
+ color: Theme.color.foreground
235
+ font.family: Theme.font.family
236
+ font.pixelSize: Theme.font.body
237
+ textFormat: Text.PlainText
238
+ wrapMode: Text.Wrap
239
+ }
240
+
241
+ // corner: a filename is arbitrary text, so PlainText, the same rule every name on this surface follows.
242
+ Text {
243
+ width: parent.width
244
+ horizontalAlignment: Text.AlignHCenter
245
+ text: root.name
246
+ color: Theme.color.muted
247
+ font.family: Theme.font.family
248
+ font.pixelSize: Theme.font.caption
249
+ textFormat: Text.PlainText
250
+ elide: Text.ElideMiddle
251
+ }
252
+ }
253
+ }
@@ -0,0 +1,13 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+
4
+ // The wheel and the two knobs of a zoomed picture; the Loader that builds this sits on the Flickable they drive.
5
+ Item {
6
+ id: root
7
+
8
+ readonly property Item viewport: root.parent ? root.parent.parent : null
9
+ anchors.fill: parent
10
+
11
+ Flea.FastScrollHandler { flickable: root.viewport }
12
+ Flea.ViewportScrollBars { flickable: root.viewport }
13
+ }
@@ -0,0 +1,32 @@
1
+ import QtQuick
2
+
3
+ // The sharper layer of a zoomed Quick Look picture: a raster's whole decode asked once, an SVG drawn again at each zoomed size.
4
+ Image {
5
+ id: root
6
+
7
+ // The fit picture this layer lies over: it takes that picture's file, rect and fill.
8
+ property Image base: null
9
+ // False at fit, where the layer holds no file and so no decode.
10
+ property bool active: false
11
+ // The decode size; 0x0 is the whole picture to Qt, which is what a raster asks for here.
12
+ property size want: Qt.size(0, 0)
13
+ // Set on the first frame and kept while a redraw loads, so the last frame holds; cleared when the layer is let go.
14
+ property bool drawn: false
15
+
16
+ x: root.base ? root.base.x : 0
17
+ y: root.base ? root.base.y : 0
18
+ width: root.base ? root.base.width : 0
19
+ height: root.base ? root.base.height : 0
20
+ visible: root.drawn
21
+ source: root.active && root.base ? root.base.source : ""
22
+ fillMode: root.base ? root.base.fillMode : Image.Stretch
23
+ autoTransform: true
24
+ asynchronous: true
25
+ cache: false
26
+ retainWhileLoading: true
27
+ sourceSize: root.want
28
+ onStatusChanged: {
29
+ if (root.status === Image.Ready) root.drawn = true
30
+ else if (root.status !== Image.Loading) root.drawn = false
31
+ }
32
+ }