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.
- package/LICENSE +22 -0
- package/README.md +511 -2
- package/THIRD-PARTY-NOTICES.md +29 -0
- package/demos/App.java +5 -0
- package/demos/Dockerfile +4 -0
- package/demos/Main.kt +3 -0
- package/demos/Program.cs +1 -0
- package/demos/README.md +12 -0
- package/demos/app.dart +3 -0
- package/demos/app.deb +0 -0
- package/demos/app.js +1 -0
- package/demos/backup.tar +0 -0
- package/demos/budget.xlsx +0 -0
- package/demos/build.sh +2 -0
- package/demos/bundle.zip +0 -0
- package/demos/clip.mp4 +0 -0
- package/demos/data.sqlite +0 -0
- package/demos/disk.iso +0 -0
- package/demos/engine.cpp +5 -0
- package/demos/firmware.bin +0 -0
- package/demos/flake.nix +4 -0
- package/demos/folder/inside.txt +1 -0
- package/demos/font.ttf +0 -0
- package/demos/index.html +5 -0
- package/demos/index.php +2 -0
- package/demos/init.lua +1 -0
- package/demos/letter.docx +0 -0
- package/demos/lib.rs +3 -0
- package/demos/main.c +6 -0
- package/demos/main.h +3 -0
- package/demos/math-and-diagrams.md +200 -0
- package/demos/notes.tar.gz +0 -0
- package/demos/notes.txt +3 -0
- package/demos/photo.png +0 -0
- package/demos/program +2 -0
- package/demos/report.pdf +32 -0
- package/demos/script.py +1 -0
- package/demos/server.go +7 -0
- package/demos/settings.json +4 -0
- package/demos/slides.pptx +0 -0
- package/demos/song.mp3 +0 -0
- package/demos/style.css +4 -0
- package/demos/tool.rb +1 -0
- package/demos/types.ts +2 -0
- package/docs/pele.md +23 -0
- package/docs/protocol.md +3420 -0
- package/docs/temml.md +63 -0
- package/index.js +107 -0
- package/package.json +34 -4
- package/src/archive.js +407 -0
- package/src/archiveops.js +728 -0
- package/src/backend.js +369 -0
- package/src/bulkrename.js +95 -0
- package/src/clip-host.js +76 -0
- package/src/clip.js +462 -0
- package/src/code.js +168 -0
- package/src/compare.js +74 -0
- package/src/create.js +128 -0
- package/src/dirsize.js +147 -0
- package/src/figure-svg.js +530 -0
- package/src/figure-thread.js +23 -0
- package/src/figure.js +132 -0
- package/src/find.js +55 -0
- package/src/flea.js +39 -0
- package/src/fsinfo.js +39 -0
- package/src/highlight.js +141 -0
- package/src/html.js +52 -0
- package/src/kinds.js +89 -0
- package/src/listing.js +130 -0
- package/src/markdown-html.js +317 -0
- package/src/mathml.js +186 -0
- package/src/menu.js +180 -0
- package/src/meta.js +135 -0
- package/src/office.js +810 -0
- package/src/order.js +100 -0
- package/src/peek.js +49 -0
- package/src/pele-wrapper.js +695 -0
- package/src/permissions.js +180 -0
- package/src/places.js +313 -0
- package/src/preview-language.js +10 -0
- package/src/terminal-server.js +95 -0
- package/src/terminal-shell.js +26 -0
- package/src/transfer.js +669 -0
- package/src/trash-record.js +41 -0
- package/src/trash.js +210 -0
- package/src/trashbrowse.js +327 -0
- package/src/uistate.js +393 -0
- package/src/uistore.js +168 -0
- package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
- package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
- package/src/vendor/LICENSES/MIT-katex.txt +21 -0
- package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
- package/src/vendor/LICENSES/MIT-pele.txt +40 -0
- package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
- package/src/vendor/LICENSES/MIT-temml.txt +21 -0
- package/src/vendor/pele.js +145 -0
- package/src/vendor/temml.mjs +14708 -0
- package/src/watch.js +98 -0
- package/src/wayland/client.js +109 -0
- package/src/wayland/protocol.js +55 -0
- package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
- package/src/wayland/protocols/wayland.xml +3248 -0
- package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
- package/src/wayland/resource-io.js +6 -0
- package/src/wayland/socket-discovery.js +26 -0
- package/src/wayland/transport-posix.js +120 -0
- package/src/wayland/transport-win32.js +11 -0
- package/src/wayland/transport.js +3 -0
- package/src/wayland/win32-resources.js +80 -0
- package/src/wayland/win32-wire.js +62 -0
- package/test/archive.test.js +80 -0
- package/test/bench-markdown-scroll.mjs +190 -0
- package/test/clip-host.test.js +113 -0
- package/test/code-preview.test.js +35 -0
- package/test/compare-ui-paths.test.js +24 -0
- package/test/compare.test.js +54 -0
- package/test/delete-trash.test.js +67 -0
- package/test/dirsize.test.js +138 -0
- package/test/file-ops.test.js +307 -0
- package/test/file-url.test.js +24 -0
- package/test/find-contents.test.js +161 -0
- package/test/find-input.test.js +66 -0
- package/test/fixtures/pele-parity.json +1006 -0
- package/test/highlight-launcher.test.js +35 -0
- package/test/html-preview.test.js +22 -0
- package/test/input.test.js +15 -0
- package/test/keymap.test.js +26 -0
- package/test/language-icons.test.js +36 -0
- package/test/launcher.test.js +51 -0
- package/test/manual-archive-here-ui.mjs +47 -0
- package/test/manual-code-scroll.mjs +28 -0
- package/test/manual-column-scroll.mjs +24 -0
- package/test/manual-compare-ui.mjs +20 -0
- package/test/manual-find-status.mjs +37 -0
- package/test/manual-folder-focus.mjs +63 -0
- package/test/manual-html-security.mjs +23 -0
- package/test/manual-html-ui.mjs +30 -0
- package/test/manual-syntax-preview.mjs +26 -0
- package/test/manual-terminal-lifecycle.mjs +42 -0
- package/test/manual-terminal-navigation.mjs +48 -0
- package/test/manual-terminal-ui.mjs +47 -0
- package/test/manual-trash-ui.mjs +86 -0
- package/test/markdown-diagrams.test.js +93 -0
- package/test/markdown-html.test.js +105 -0
- package/test/mathml.test.js +92 -0
- package/test/menu-transfer.test.js +57 -0
- package/test/office-preview.test.js +154 -0
- package/test/pele-parity.test.js +28 -0
- package/test/places.test.js +134 -0
- package/test/preview-keys.test.js +60 -0
- package/test/preview-language.test.js +22 -0
- package/test/status-filename.test.js +20 -0
- package/test/transfer-replace-merge.test.js +187 -0
- package/test/trash-address.test.js +23 -0
- package/test/trash-view.test.js +37 -0
- package/test/trashbrowse.test.js +135 -0
- package/ui/AboutFacts.qml +78 -0
- package/ui/ArchiveCards.qml +95 -0
- package/ui/ArchiveCompressDialog.qml +378 -0
- package/ui/ArchiveHereConfirm.qml +127 -0
- package/ui/ArchivePasswordDialog.qml +257 -0
- package/ui/Backend.qml +775 -0
- package/ui/BulkOldNames.qml +47 -0
- package/ui/BulkRenameDialog.qml +380 -0
- package/ui/CardFrame.qml +67 -0
- package/ui/CardScroll.qml +79 -0
- package/ui/CheckBox.qml +73 -0
- package/ui/ChromeBar.qml +360 -0
- package/ui/ChromeButton.qml +131 -0
- package/ui/ChromeModes.qml +43 -0
- package/ui/CodeLines.qml +256 -0
- package/ui/CodeRefusal.qml +52 -0
- package/ui/CollideConfirm.qml +147 -0
- package/ui/CollideHost.qml +167 -0
- package/ui/ColumnPane.qml +525 -0
- package/ui/ColumnRow.qml +380 -0
- package/ui/ColumnsArea.qml +594 -0
- package/ui/ColumnsLanding.qml +147 -0
- package/ui/CompareView.qml +321 -0
- package/ui/ContextMenu.qml +743 -0
- package/ui/ConvertDialog.qml +456 -0
- package/ui/CountedWorker.qml +7 -0
- package/ui/Crumb.qml +64 -0
- package/ui/CrumbDrop.qml +25 -0
- package/ui/CsvTable.qml +394 -0
- package/ui/CursorMark.qml +41 -0
- package/ui/DefaultClaim.qml +130 -0
- package/ui/DeviceLock.qml +47 -0
- package/ui/DeviceMounts.qml +540 -0
- package/ui/DialogButton.qml +150 -0
- package/ui/DialogField.qml +147 -0
- package/ui/DialogHeader.qml +31 -0
- package/ui/DialogScrim.qml +20 -0
- package/ui/DialogTitle.qml +37 -0
- package/ui/Divider.qml +9 -0
- package/ui/DropInto.qml +126 -0
- package/ui/DropTarget.qml +35 -0
- package/ui/DropboxMark.qml +60 -0
- package/ui/EmptyState.qml +150 -0
- package/ui/EscapeHint.qml +11 -0
- package/ui/FactsTable.qml +54 -0
- package/ui/FastScrollHandler.qml +476 -0
- package/ui/FatNamesConfirm.qml +157 -0
- package/ui/Favourites.qml +143 -0
- package/ui/FigureService.qml +120 -0
- package/ui/FileDrag.qml +267 -0
- package/ui/FilterStrip.qml +133 -0
- package/ui/FitMetrics.qml +22 -0
- package/ui/FlashDriveRows.qml +137 -0
- package/ui/FlashHost.qml +72 -0
- package/ui/FlashImageRow.qml +104 -0
- package/ui/FlashRunner.qml +119 -0
- package/ui/FlashStepRow.qml +172 -0
- package/ui/FlashStrip.qml +38 -0
- package/ui/FlashView.qml +397 -0
- package/ui/FleaMark.qml +88 -0
- package/ui/FlyoutFade.qml +23 -0
- package/ui/FontPane.qml +170 -0
- package/ui/Glass.qml +114 -0
- package/ui/GlassTagger.qml +59 -0
- package/ui/Glyph.qml +64 -0
- package/ui/GlyphSolid.qml +22 -0
- package/ui/GridArea.qml +664 -0
- package/ui/GridTile.qml +325 -0
- package/ui/GvfsBridge.qml +164 -0
- package/ui/Header.qml +433 -0
- package/ui/HoverTimers.qml +39 -0
- package/ui/HtmlClip.qml +30 -0
- package/ui/HtmlPane.qml +63 -0
- package/ui/HyprlandMark.qml +45 -0
- package/ui/Ipc.qml +1005 -0
- package/ui/IpcControls.qml +7 -0
- package/ui/IpcMenuState.qml +48 -0
- package/ui/IpcPreviewState.qml +185 -0
- package/ui/JumpPath.qml +51 -0
- package/ui/KeymapSheet.qml +561 -0
- package/ui/KeymapSheetResult.qml +89 -0
- package/ui/KindStack.qml +40 -0
- package/ui/LangMark.qml +51 -0
- package/ui/LangMarkLoader.qml +26 -0
- package/ui/List.qml +480 -0
- package/ui/LoadingState.qml +54 -0
- package/ui/LocalSend.qml +56 -0
- package/ui/LocalSendMark.qml +73 -0
- package/ui/MarkdownBlockView.qml +311 -0
- package/ui/MarkdownBlocks.qml +35 -0
- package/ui/MarkdownFigure.qml +254 -0
- package/ui/MarkdownImages.qml +72 -0
- package/ui/MarkdownList.qml +81 -0
- package/ui/MarkdownMathsText.qml +97 -0
- package/ui/MarkdownPane.qml +83 -0
- package/ui/MarkdownPictures.qml +41 -0
- package/ui/MarkdownQuote.qml +52 -0
- package/ui/MarkdownRemote.qml +82 -0
- package/ui/MarkdownSource.qml +155 -0
- package/ui/MarkdownTable.qml +222 -0
- package/ui/MarkdownTableScroll.qml +64 -0
- package/ui/MarkdownTableWheel.qml +126 -0
- package/ui/MarkdownText.qml +87 -0
- package/ui/MarkdownWorker.js +132 -0
- package/ui/MatchText.qml +99 -0
- package/ui/MediaSession.qml +38 -0
- package/ui/MediaSound.qml +26 -0
- package/ui/MediaStrip.qml +191 -0
- package/ui/MediaTrack.qml +36 -0
- package/ui/MediaVolume.qml +54 -0
- package/ui/MenuActionDialog.qml +396 -0
- package/ui/MenuEdgeFade.qml +24 -0
- package/ui/MenuHost.qml +227 -0
- package/ui/MenuRow.qml +351 -0
- package/ui/MountListing.qml +100 -0
- package/ui/NetworkDialog.qml +435 -0
- package/ui/NetworkForm.qml +426 -0
- package/ui/NetworkMounts.qml +913 -0
- package/ui/NetworkPlaces.qml +127 -0
- package/ui/OpenWithDialog.qml +613 -0
- package/ui/Opener.qml +95 -0
- package/ui/Pane.qml +1320 -0
- package/ui/PaneMenuActions.qml +527 -0
- package/ui/PanePath.qml +90 -0
- package/ui/PaneRail.qml +268 -0
- package/ui/PaneStates.qml +88 -0
- package/ui/PaneSwap.qml +339 -0
- package/ui/PaneWire.qml +601 -0
- package/ui/ParkedWait.qml +9 -0
- package/ui/PathEntry.qml +186 -0
- package/ui/PathJump.qml +400 -0
- package/ui/PdfViewer.qml +297 -0
- package/ui/PermissionsDialog.qml +658 -0
- package/ui/PermissionsHeadings.qml +31 -0
- package/ui/PhoneMounts.qml +67 -0
- package/ui/PickerAnswers.qml +75 -0
- package/ui/PickerBox.qml +26 -0
- package/ui/PickerChrome.qml +295 -0
- package/ui/PickerFilter.qml +97 -0
- package/ui/PickerGrid.qml +308 -0
- package/ui/PickerHeader.qml +28 -0
- package/ui/PickerLifecycle.qml +27 -0
- package/ui/PickerList.qml +218 -0
- package/ui/PickerListing.qml +149 -0
- package/ui/PickerPathBar.qml +127 -0
- package/ui/PickerPlaces.qml +189 -0
- package/ui/PickerRecent.qml +92 -0
- package/ui/PickerSave.qml +101 -0
- package/ui/PickerSelection.qml +155 -0
- package/ui/PickerWindow.qml +846 -0
- package/ui/PowerSectorsReader.qml +10 -0
- package/ui/PrebuildDriver.qml +146 -0
- package/ui/Preview.qml +1005 -0
- package/ui/PreviewAnimation.qml +24 -0
- package/ui/PreviewArchive.qml +91 -0
- package/ui/PreviewColumn.qml +553 -0
- package/ui/PreviewEdge.qml +63 -0
- package/ui/PreviewFacts.qml +30 -0
- package/ui/PreviewFactsLine.qml +34 -0
- package/ui/PreviewHtml.qml +233 -0
- package/ui/PreviewImage.qml +253 -0
- package/ui/PreviewImagePan.qml +13 -0
- package/ui/PreviewImageSharp.qml +32 -0
- package/ui/PreviewLines.qml +106 -0
- package/ui/PreviewMarkdown.qml +706 -0
- package/ui/PreviewMedia.qml +250 -0
- package/ui/PreviewPdf.qml +482 -0
- package/ui/PreviewScroll.qml +201 -0
- package/ui/PreviewSwap.qml +335 -0
- package/ui/PreviewText.qml +149 -0
- package/ui/ProtocolChip.qml +18 -0
- package/ui/QuickLookArchive.qml +41 -0
- package/ui/QuickLookBar.qml +103 -0
- package/ui/QuickLookPrepare.qml +355 -0
- package/ui/QuickLookSwap.qml +10 -0
- package/ui/QuickLookWarm.qml +65 -0
- package/ui/RailDrop.qml +155 -0
- package/ui/RailHeading.qml +19 -0
- package/ui/RailPlaces.qml +38 -0
- package/ui/RailTrashRow.qml +67 -0
- package/ui/RenameField.qml +353 -0
- package/ui/RendererRetry.qml +11 -0
- package/ui/ResizeHandle.qml +52 -0
- package/ui/Reveal.qml +54 -0
- package/ui/Row.qml +476 -0
- package/ui/RowDrag.qml +213 -0
- package/ui/RowDropTarget.qml +27 -0
- package/ui/RunCard.qml +286 -0
- package/ui/Scripts.qml +65 -0
- package/ui/SearchStrip.qml +232 -0
- package/ui/SelectionBand.qml +140 -0
- package/ui/SelectionPreview.qml +370 -0
- package/ui/SettingsFavourite.qml +122 -0
- package/ui/SettingsGroup.qml +96 -0
- package/ui/SettingsHint.qml +12 -0
- package/ui/SettingsMetrics.qml +29 -0
- package/ui/SettingsPane.qml +178 -0
- package/ui/SettingsPanel.qml +547 -0
- package/ui/SettingsRail.qml +128 -0
- package/ui/SettingsRow.qml +409 -0
- package/ui/SettingsRuler.qml +85 -0
- package/ui/SettingsSegment.qml +85 -0
- package/ui/ShareBrowser.qml +113 -0
- package/ui/ShareLink.qml +67 -0
- package/ui/ShelfPins.qml +101 -0
- package/ui/Sidebar.qml +728 -0
- package/ui/SidebarRow.qml +358 -0
- package/ui/Spinner.qml +60 -0
- package/ui/StableModel.qml +89 -0
- package/ui/StateMessage.qml +84 -0
- package/ui/StatusBar.qml +512 -0
- package/ui/StatusFileName.qml +27 -0
- package/ui/TabBar.qml +673 -0
- package/ui/TabDragGeometry.qml +60 -0
- package/ui/TagMenuMark.qml +52 -0
- package/ui/TagRailSection.qml +53 -0
- package/ui/TagSlot.qml +40 -0
- package/ui/TagState.qml +150 -0
- package/ui/TagSwatch.qml +28 -0
- package/ui/Taildrop.qml +86 -0
- package/ui/TailscaleMark.qml +50 -0
- package/ui/TerminalService.qml +69 -0
- package/ui/TerminalTab.qml +48 -0
- package/ui/TerminalTabs.qml +27 -0
- package/ui/Theme.qml +460 -0
- package/ui/ThemeColors.qml +43 -0
- package/ui/TransferCard.qml +239 -0
- package/ui/TrashConfirm.qml +129 -0
- package/ui/TrashDropHandler.qml +11 -0
- package/ui/TrashHost.qml +202 -0
- package/ui/TrashMonitor.qml +30 -0
- package/ui/TrashToolbar.qml +19 -0
- package/ui/TrashView.qml +492 -0
- package/ui/UnlockDialog.qml +450 -0
- package/ui/UnlockHost.qml +206 -0
- package/ui/UpdateCheck.qml +97 -0
- package/ui/UserDirs.qml +25 -0
- package/ui/ViewState.qml +565 -0
- package/ui/ViewportScrollBar.qml +195 -0
- package/ui/ViewportScrollBars.qml +25 -0
- package/ui/WebPreview.qml +33 -0
- package/ui/WebPreviewView.qml +26 -0
- package/ui/WindowBody.qml +829 -0
- package/ui/WindowDrag.qml +35 -0
- package/ui/boot/Commons/AudioNodes.qml +50 -0
- package/ui/boot/Commons/AudioNodesModel.js +96 -0
- package/ui/boot/Commons/Border.qml +243 -0
- package/ui/boot/Commons/BorderGeometry.js +373 -0
- package/ui/boot/Commons/Color.qml +258 -0
- package/ui/boot/Commons/I18n.qml +118 -0
- package/ui/boot/Commons/InputDevices.qml +112 -0
- package/ui/boot/Commons/InputMethodState.qml +38 -0
- package/ui/boot/Commons/IpcRegistry.qml +77 -0
- package/ui/boot/Commons/Numbers.js +19 -0
- package/ui/boot/Commons/Plural.js +91 -0
- package/ui/boot/Commons/ShellIpc.qml +12 -0
- package/ui/boot/Commons/Style.qml +561 -0
- package/ui/boot/Commons/Translations.qml +100 -0
- package/ui/boot/Commons/UntypedInput.qml +152 -0
- package/ui/boot/Commons/Util.qml +188 -0
- package/ui/boot/Commons/qmldir +13 -0
- package/ui/boot/LICENSE-omarchy +20 -0
- package/ui/boot/Ui/BackgroundMedia.qml +49 -0
- package/ui/boot/Ui/BarIconButton.qml +106 -0
- package/ui/boot/Ui/BarIconContent.qml +38 -0
- package/ui/boot/Ui/BarIndicator.qml +53 -0
- package/ui/boot/Ui/BarWidget.qml +50 -0
- package/ui/boot/Ui/BorderOverlay.qml +54 -0
- package/ui/boot/Ui/BorderSurface.qml +40 -0
- package/ui/boot/Ui/Button.qml +224 -0
- package/ui/boot/Ui/ButtonGroup.qml +131 -0
- package/ui/boot/Ui/ConfirmDialog.qml +134 -0
- package/ui/boot/Ui/CursorSurface.qml +42 -0
- package/ui/boot/Ui/Dropdown.qml +245 -0
- package/ui/boot/Ui/FilterInput.qml +26 -0
- package/ui/boot/Ui/IconContentBounds.qml +141 -0
- package/ui/boot/Ui/KeyboardPanel.qml +453 -0
- package/ui/boot/Ui/MultiSelect.qml +624 -0
- package/ui/boot/Ui/NumberField.qml +86 -0
- package/ui/boot/Ui/OpticalGlyph.qml +68 -0
- package/ui/boot/Ui/OverlayWindow.qml +102 -0
- package/ui/boot/Ui/Panel.qml +60 -0
- package/ui/boot/Ui/PanelActionButton.qml +105 -0
- package/ui/boot/Ui/PanelController.qml +16 -0
- package/ui/boot/Ui/PanelHero.qml +112 -0
- package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
- package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
- package/ui/boot/Ui/PanelSeparator.qml +19 -0
- package/ui/boot/Ui/PanelSlider.qml +156 -0
- package/ui/boot/Ui/PanelToolTip.qml +50 -0
- package/ui/boot/Ui/PluginBarApi.qml +89 -0
- package/ui/boot/Ui/PointerMoveGate.qml +54 -0
- package/ui/boot/Ui/PopupCard.qml +181 -0
- package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
- package/ui/boot/Ui/SearchableDropdown.qml +354 -0
- package/ui/boot/Ui/SizedImage.qml +125 -0
- package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
- package/ui/boot/Ui/TextField.qml +58 -0
- package/ui/boot/Ui/Toggle.qml +118 -0
- package/ui/boot/Ui/ToggleSwitch.qml +115 -0
- package/ui/boot/Ui/WidgetButton.qml +172 -0
- package/ui/boot/Ui/qmldir +41 -0
- package/ui/boot/fleatab.qml +50 -0
- package/ui/boot/picker.qml +39 -0
- package/ui/boot/shell.qml +131 -0
- package/ui/boot/tabtearoff.qml +51 -0
- package/ui/js/Anchor.js +379 -0
- package/ui/js/AnchorHold.js +162 -0
- package/ui/js/Archive.js +157 -0
- package/ui/js/ArchiveCard.js +44 -0
- package/ui/js/ArchiveOps.js +44 -0
- package/ui/js/BackReturn.js +118 -0
- package/ui/js/BulkRename.js +100 -0
- package/ui/js/Buttons.js +54 -0
- package/ui/js/ChromeKeys.js +116 -0
- package/ui/js/ClipMarks.js +73 -0
- package/ui/js/ClipSelection.js +67 -0
- package/ui/js/Clipboard.js +179 -0
- package/ui/js/Cloud.js +97 -0
- package/ui/js/CodeRuns.js +72 -0
- package/ui/js/Collide.js +212 -0
- package/ui/js/ColumnFit.js +28 -0
- package/ui/js/ColumnMenu.js +111 -0
- package/ui/js/Columns.js +298 -0
- package/ui/js/ColumnsCarry.js +103 -0
- package/ui/js/Compare.js +74 -0
- package/ui/js/Contrast.js +157 -0
- package/ui/js/ControlReader.js +42 -0
- package/ui/js/Convert.js +52 -0
- package/ui/js/CopyAs.js +52 -0
- package/ui/js/Crumbs.js +178 -0
- package/ui/js/Csv.js +231 -0
- package/ui/js/Density.js +44 -0
- package/ui/js/Devices.js +440 -0
- package/ui/js/DirSizes.js +180 -0
- package/ui/js/Drag.js +360 -0
- package/ui/js/DragOut.js +166 -0
- package/ui/js/DropDev.js +52 -0
- package/ui/js/Dropbox.js +41 -0
- package/ui/js/Eject.js +217 -0
- package/ui/js/Errors.js +188 -0
- package/ui/js/ExtThumbs.js +115 -0
- package/ui/js/Facts.js +402 -0
- package/ui/js/FigureDate.js +14 -0
- package/ui/js/Filter.js +285 -0
- package/ui/js/Find.js +46 -0
- package/ui/js/Flash.js +184 -0
- package/ui/js/FlashCard.js +79 -0
- package/ui/js/FlashEndings.js +125 -0
- package/ui/js/FlashPane.js +116 -0
- package/ui/js/FleaBin.js +12 -0
- package/ui/js/Focus.js +504 -0
- package/ui/js/FolderSorts.js +108 -0
- package/ui/js/FolderViews.js +44 -0
- package/ui/js/Format.js +314 -0
- package/ui/js/Fuzzy.js +141 -0
- package/ui/js/GlassTag.js +72 -0
- package/ui/js/Grid.js +33 -0
- package/ui/js/GridGeometry.js +90 -0
- package/ui/js/GridNames.js +153 -0
- package/ui/js/GvfsBridge.js +200 -0
- package/ui/js/HostClipboard.js +29 -0
- package/ui/js/Icons.js +218 -0
- package/ui/js/Input.js +50 -0
- package/ui/js/Jump.js +200 -0
- package/ui/js/KeyName.js +64 -0
- package/ui/js/Keymap.js +401 -0
- package/ui/js/Kinds.js +164 -0
- package/ui/js/LICENSES/ISC-lucide.txt +43 -0
- package/ui/js/LangMarkPaths.js +47 -0
- package/ui/js/LangMarks.js +120 -0
- package/ui/js/Lists.js +11 -0
- package/ui/js/LocalSend.js +39 -0
- package/ui/js/LockedMenu.js +63 -0
- package/ui/js/MakeDefault.js +186 -0
- package/ui/js/MarkBox.js +7 -0
- package/ui/js/Markdown.js +119 -0
- package/ui/js/MarkdownLists.js +86 -0
- package/ui/js/MarkdownMaths.js +58 -0
- package/ui/js/MarkdownPictures.js +32 -0
- package/ui/js/MarkdownPrepared.js +139 -0
- package/ui/js/MarkdownTableFit.js +34 -0
- package/ui/js/Marks.js +148 -0
- package/ui/js/Marquee.js +96 -0
- package/ui/js/Match.js +93 -0
- package/ui/js/Material.js +109 -0
- package/ui/js/MdBlocks.js +437 -0
- package/ui/js/MdBreak.js +71 -0
- package/ui/js/MdChunks.js +70 -0
- package/ui/js/MdContainer.js +137 -0
- package/ui/js/MdDocument.js +337 -0
- package/ui/js/MdEmph.js +97 -0
- package/ui/js/MdEntity.js +108 -0
- package/ui/js/MdEntityTable.js +223 -0
- package/ui/js/MdEscape.js +59 -0
- package/ui/js/MdFront.js +37 -0
- package/ui/js/MdHold.js +32 -0
- package/ui/js/MdHtml.js +307 -0
- package/ui/js/MdHtmlBlock.js +290 -0
- package/ui/js/MdHtmlHeading.js +53 -0
- package/ui/js/MdHtmlImage.js +179 -0
- package/ui/js/MdInline.js +154 -0
- package/ui/js/MdItems.js +212 -0
- package/ui/js/MdLeaf.js +309 -0
- package/ui/js/MdLink.js +196 -0
- package/ui/js/MdMath.js +67 -0
- package/ui/js/MdParagraphs.js +138 -0
- package/ui/js/MdRefs.js +232 -0
- package/ui/js/MdResolve.js +226 -0
- package/ui/js/MdRun.js +300 -0
- package/ui/js/MdUrl.js +226 -0
- package/ui/js/Menu.js +514 -0
- package/ui/js/MenuContext.js +85 -0
- package/ui/js/MenuFit.js +13 -0
- package/ui/js/MenuRefresh.js +74 -0
- package/ui/js/MenuWheel.js +35 -0
- package/ui/js/Messages.js +186 -0
- package/ui/js/Motion.js +16 -0
- package/ui/js/Mounts.js +320 -0
- package/ui/js/MouseNav.js +13 -0
- package/ui/js/Nav.js +329 -0
- package/ui/js/NetFs.js +26 -0
- package/ui/js/OpenWith.js +83 -0
- package/ui/js/Ops.js +585 -0
- package/ui/js/Palette.js +33 -0
- package/ui/js/PathBar.js +260 -0
- package/ui/js/Permissions.js +179 -0
- package/ui/js/Phones.js +112 -0
- package/ui/js/Picker.js +353 -0
- package/ui/js/PlaceMenu.js +96 -0
- package/ui/js/Places.js +265 -0
- package/ui/js/PreviewAsk.js +21 -0
- package/ui/js/PreviewKeys.js +155 -0
- package/ui/js/PreviewSettle.js +29 -0
- package/ui/js/PreviewSwap.js +101 -0
- package/ui/js/PropertyFacts.js +144 -0
- package/ui/js/Protocols.js +296 -0
- package/ui/js/QuickLookKinds.js +27 -0
- package/ui/js/QuickLookRect.js +24 -0
- package/ui/js/RailDrop.js +51 -0
- package/ui/js/RailKeys.js +87 -0
- package/ui/js/RailMenu.js +133 -0
- package/ui/js/Recent.js +135 -0
- package/ui/js/RecentMode.js +156 -0
- package/ui/js/Reload.js +60 -0
- package/ui/js/Renderer.js +9 -0
- package/ui/js/RunFile.js +143 -0
- package/ui/js/Scripts.js +28 -0
- package/ui/js/Scroll.js +304 -0
- package/ui/js/ScrollOff.js +69 -0
- package/ui/js/Search.js +478 -0
- package/ui/js/Selection.js +97 -0
- package/ui/js/Settings.js +476 -0
- package/ui/js/SettingsAbout.js +97 -0
- package/ui/js/SettingsShelf.js +52 -0
- package/ui/js/SheetKeys.js +42 -0
- package/ui/js/SheetQuery.js +281 -0
- package/ui/js/ShelfPile.js +27 -0
- package/ui/js/SlowClick.js +53 -0
- package/ui/js/SlowOp.js +6 -0
- package/ui/js/Sort.js +134 -0
- package/ui/js/Startup.js +63 -0
- package/ui/js/StateWords.js +17 -0
- package/ui/js/Status.js +238 -0
- package/ui/js/Swap.js +166 -0
- package/ui/js/TabMove.js +39 -0
- package/ui/js/Tabs.js +751 -0
- package/ui/js/Tags.js +134 -0
- package/ui/js/Taildrop.js +128 -0
- package/ui/js/Tap.js +180 -0
- package/ui/js/TextSize.js +107 -0
- package/ui/js/Thumbs.js +158 -0
- package/ui/js/Transfer.js +172 -0
- package/ui/js/Trash.js +84 -0
- package/ui/js/TrashDates.js +47 -0
- package/ui/js/TrashDrop.js +64 -0
- package/ui/js/UiState.js +438 -0
- package/ui/js/Unlock.js +152 -0
- package/ui/js/Update.js +130 -0
- package/ui/js/UserDirs.js +56 -0
- 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
|
+
}
|