flea-qml 0.0.0-stage → 0.1.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 +478 -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 +402 -0
- package/src/archiveops.js +697 -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 +129 -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/transfer.js +669 -0
- package/src/trash-record.js +41 -0
- package/src/trash.js +210 -0
- package/src/trashbrowse.js +326 -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 +241 -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-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-html-security.mjs +23 -0
- package/test/manual-html-ui.mjs +30 -0
- package/test/manual-syntax-preview.mjs +26 -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 +68 -0
- package/ui/ArchiveCompressDialog.qml +378 -0
- package/ui/ArchivePasswordDialog.qml +257 -0
- package/ui/Backend.qml +771 -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 +523 -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 +115 -0
- package/ui/Pane.qml +1296 -0
- package/ui/PaneMenuActions.qml +527 -0
- package/ui/PanePath.qml +90 -0
- package/ui/PaneRail.qml +239 -0
- package/ui/PaneStates.qml +88 -0
- package/ui/PaneSwap.qml +339 -0
- package/ui/PaneWire.qml +605 -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 +1004 -0
- package/ui/PreviewAnimation.qml +24 -0
- package/ui/PreviewArchive.qml +66 -0
- package/ui/PreviewColumn.qml +551 -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 +38 -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 +732 -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/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 +827 -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 +122 -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 +364 -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 +502 -0
- package/ui/js/FolderSorts.js +108 -0
- package/ui/js/FolderViews.js +44 -0
- package/ui/js/Format.js +305 -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 +736 -0
- package/ui/js/Tags.js +134 -0
- package/ui/js/Taildrop.js +128 -0
- package/ui/js/Tap.js +174 -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 +81 -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 +228 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "js/Format.js" as Format
|
|
3
|
+
|
|
4
|
+
// The moving layer over a still GIF frame, built by its host only once that frame is drawn; the host's Loader holds the still's rect and this fills it.
|
|
5
|
+
AnimatedImage {
|
|
6
|
+
id: root
|
|
7
|
+
|
|
8
|
+
property string path: ""
|
|
9
|
+
// False while the host's picture is covered or off screen.
|
|
10
|
+
property bool shown: true
|
|
11
|
+
// The window is mapped and not minimised; a hidden window pauses on its current frame.
|
|
12
|
+
readonly property bool exposed: Window.window !== null && Window.window.visible
|
|
13
|
+
&& Window.visibility !== Window.Hidden && Window.visibility !== Window.Minimized
|
|
14
|
+
// True from the frame its own first frame is ready, which is when the host stops drawing the still.
|
|
15
|
+
readonly property bool ready: root.status === Image.Ready && root.frameCount > 1
|
|
16
|
+
|
|
17
|
+
anchors.fill: parent
|
|
18
|
+
opacity: root.ready ? 1 : 0
|
|
19
|
+
source: root.path.length > 0 ? Format.fileUri(root.path) : ""
|
|
20
|
+
fillMode: Image.Stretch
|
|
21
|
+
playing: root.visible && root.shown && root.exposed
|
|
22
|
+
asynchronous: true
|
|
23
|
+
cache: false
|
|
24
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Facts.js" as Facts
|
|
5
|
+
import "js/Format.js" as Format
|
|
6
|
+
|
|
7
|
+
// The Archive tile's frame: the entries the wire carried, as many as the frame has room for, and the
|
|
8
|
+
// count it could not name. One row per line box, less the "+ N more" line, which always has to be
|
|
9
|
+
// visible: a list that ran past the frame would hide the very number it exists to state.
|
|
10
|
+
Item {
|
|
11
|
+
id: root
|
|
12
|
+
|
|
13
|
+
// The meta answer for the archive row, or null before one has arrived.
|
|
14
|
+
property var meta: null
|
|
15
|
+
|
|
16
|
+
readonly property real lineHeight: Math.round(Theme.font.caption * Theme.lineBoxRatio)
|
|
17
|
+
readonly property int shown: Math.max(0, Math.floor(height / lineHeight) - 1)
|
|
18
|
+
|
|
19
|
+
Column {
|
|
20
|
+
anchors.fill: parent
|
|
21
|
+
clip: true
|
|
22
|
+
spacing: 0
|
|
23
|
+
|
|
24
|
+
Repeater {
|
|
25
|
+
model: Facts.archiveEntries(root.meta, root.shown)
|
|
26
|
+
|
|
27
|
+
delegate: Row {
|
|
28
|
+
required property var modelData
|
|
29
|
+
width: root.width
|
|
30
|
+
height: root.lineHeight
|
|
31
|
+
spacing: Theme.spacing.gap
|
|
32
|
+
|
|
33
|
+
Flea.Glyph {
|
|
34
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
35
|
+
width: Theme.font.caption
|
|
36
|
+
height: Theme.font.caption
|
|
37
|
+
name: modelData.d ? "folder" : "file"
|
|
38
|
+
color: Theme.color.mutedFrame
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// corner: an archive holds arbitrary names, so PlainText; the row's height, centred, puts the name on the glyph's line.
|
|
42
|
+
Text {
|
|
43
|
+
height: parent.height
|
|
44
|
+
verticalAlignment: Text.AlignVCenter
|
|
45
|
+
text: modelData.n
|
|
46
|
+
color: Theme.color.muted
|
|
47
|
+
font.family: Theme.font.family
|
|
48
|
+
font.pixelSize: Theme.font.caption
|
|
49
|
+
textFormat: Text.PlainText
|
|
50
|
+
elide: Text.ElideRight
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
Text {
|
|
56
|
+
height: root.lineHeight
|
|
57
|
+
visible: Facts.archiveMore(root.meta, root.shown) > 0
|
|
58
|
+
text: "+ " + Format.count(Facts.archiveMore(root.meta, root.shown)) + " more"
|
|
59
|
+
color: Theme.color.muted
|
|
60
|
+
opacity: 0.6
|
|
61
|
+
font.family: Theme.font.family
|
|
62
|
+
font.pixelSize: Theme.font.caption
|
|
63
|
+
textFormat: Text.PlainText
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Facts.js" as Facts
|
|
5
|
+
import "js/PreviewKeys.js" as PreviewKeys
|
|
6
|
+
import "js/Format.js" as Format
|
|
7
|
+
import "js/Icons.js" as Icons
|
|
8
|
+
import "js/KeyName.js" as KeyName
|
|
9
|
+
import "js/Kinds.js" as Kinds
|
|
10
|
+
import "js/Thumbs.js" as Thumbs
|
|
11
|
+
import "js/ExtThumbs.js" as ExtThumbs
|
|
12
|
+
// The columns view's last pane when a file is picked. One anatomy for all twelve states the canvas
|
|
13
|
+
// draws: a frame, an optional transport, the name, and a caption-type table of facts under it.
|
|
14
|
+
Item {
|
|
15
|
+
id: root
|
|
16
|
+
|
|
17
|
+
property var row: null
|
|
18
|
+
// The meta reply's own fields, whatever ui/Backend.qml's meta signal carries; null until it arrives.
|
|
19
|
+
property var meta: null
|
|
20
|
+
property string kindName: ""
|
|
21
|
+
property string thumb: ""
|
|
22
|
+
// ExtThumbs: a class that is off holds the frame on its facts until Ctrl+Space loads it.
|
|
23
|
+
property bool manualHold: false
|
|
24
|
+
// ExtThumbs: how much of a text file the frame may read; 256 KiB on network and phone storage.
|
|
25
|
+
property int textLimit: 1048576
|
|
26
|
+
// True where the board truncates instead of refusing: an over-limit remote file shows its first bytes.
|
|
27
|
+
property bool truncateText: false
|
|
28
|
+
// True once no thumbnail is coming: the backend answered with none, or never offered one at all.
|
|
29
|
+
property bool noThumbComing: false
|
|
30
|
+
// A move cleared the row and its settle is running, so the column is loading, not showing a file with no preview.
|
|
31
|
+
property bool pending: false
|
|
32
|
+
// Set by ui/PreviewSwap.qml when a hold ran out, which already spent LoadingState's own hold-off.
|
|
33
|
+
property bool loadingHeldOff: false
|
|
34
|
+
property int selectionCount: 0
|
|
35
|
+
property var selectedRows: []
|
|
36
|
+
property string path: ""
|
|
37
|
+
readonly property real pdfScrollY: pdfFlick.contentY
|
|
38
|
+
readonly property var pdfFrameItem: frame
|
|
39
|
+
signal expandRequested()
|
|
40
|
+
// No player exists until the operator presses play. The strip draws from the probe's own
|
|
41
|
+
// duration, so browsing a folder of clips builds no MediaPlayer at all: it costs nothing, makes
|
|
42
|
+
// no sound, and stops QtMultimedia logging a teardown warning on every cursor move.
|
|
43
|
+
property bool wantsPlayback: false
|
|
44
|
+
// The shared Space preview, handed in by ui/ColumnsArea.qml: one file plays in one place.
|
|
45
|
+
property bool overlayOpen: false
|
|
46
|
+
// Where a player may exist at all: this column on screen, no overlay over it, and a strip to drive it; losing any of them ends the play intent.
|
|
47
|
+
readonly property bool playerAllowed: root.visible && !root.overlayOpen && mediaLoader.active
|
|
48
|
+
onPlayerAllowedChanged: if (!root.playerAllowed) root.wantsPlayback = false
|
|
49
|
+
|
|
50
|
+
// A new row is a new subject, so whatever was playing stops being this column's business, and
|
|
51
|
+
// the player it needed is torn down with it.
|
|
52
|
+
onPathChanged: root.wantsPlayback = false
|
|
53
|
+
|
|
54
|
+
// What the row itself is, before Loading or Error can override it. The readers below are built
|
|
55
|
+
// from this and never from previewState: an error that switched its own reader off would clear
|
|
56
|
+
// the error, re-enter the read, and flap between the two states forever.
|
|
57
|
+
readonly property string rowState: root.row !== null && root.row.d !== true
|
|
58
|
+
? Facts.state(root.row, 1, false, "", root.kindName) : ""
|
|
59
|
+
|
|
60
|
+
// Loading and Error are states the column reaches on its own: loading while the facts are still
|
|
61
|
+
// in flight, and error when the thing it was going to draw could not be read at all. A held
|
|
62
|
+
// frame is neither: its facts are the listing's own and there is nothing in flight.
|
|
63
|
+
readonly property bool busy: root.pending || (root.row !== null && root.row.d !== true && root.meta === null && !root.manualHold)
|
|
64
|
+
readonly property string pdfSentence: pdfLoader.item ? pdfLoader.item.failSentence : ""
|
|
65
|
+
readonly property string failure: lines.readFailed || root.pdfFailed || (root.isHtmlRow && root.markdown && root.markdown.failed)
|
|
66
|
+
? (root.pdfFailed && root.pdfSentence.length > 0 ? root.pdfSentence : "This file could not be read.")
|
|
67
|
+
: (root.meta && root.meta.archiveFailed ? "This archive could not be read." : "")
|
|
68
|
+
|
|
69
|
+
// The PDF reader exists only for a PDF row, the same rule the media transport follows: browsing
|
|
70
|
+
// a folder of anything else builds no PdfDocument at all.
|
|
71
|
+
readonly property int pdfPages: pdfLoader.item ? pdfLoader.item.pageCount : 0
|
|
72
|
+
readonly property bool pdfFailed: pdfLoader.item ? pdfLoader.item.failed : false
|
|
73
|
+
readonly property bool pdfDrawn: pdfLoader.item ? pdfLoader.item.shownPage >= 0 : false
|
|
74
|
+
|
|
75
|
+
readonly property string previewState: Facts.state(root.row, root.selectionCount, root.busy, root.failure, root.kindName)
|
|
76
|
+
// What the rows and the facts line state that the listing and the meta reply do not carry.
|
|
77
|
+
readonly property var factExtra: ({ pages: root.pdfPages > 0 ? String(root.pdfPages) : "",
|
|
78
|
+
owner: root.meta && root.meta.owner ? root.meta.owner : "" })
|
|
79
|
+
readonly property var factRows: root.previewState === Facts.MULTI
|
|
80
|
+
? Facts.multiFacts(root.selectedRows, root.selectionCount)
|
|
81
|
+
: (root.row ? Facts.facts(root.previewState, root.row, root.meta, root.kindName, root.factExtra) : [])
|
|
82
|
+
|
|
83
|
+
// The canvas's frame is 16 by 10, the one proportion every state shares but a tall kind's, which fills the column down to the name.
|
|
84
|
+
readonly property real frameRatio: 10 / 16
|
|
85
|
+
readonly property bool tallRow: root.previewState !== Facts.MULTI && Facts.tall(root.rowState)
|
|
86
|
+
// Document rows always render in the tall column frame, independently of Quick Look.
|
|
87
|
+
readonly property bool isMarkdownRow: root.rowState === Facts.TEXT && root.row !== null
|
|
88
|
+
&& root.row.s <= root.textLimit && Kinds.isMarkdown(root.row.n)
|
|
89
|
+
// An office document is converted by the backend, so it needs local storage and has its own size gate.
|
|
90
|
+
readonly property bool isOfficeRow: root.rowState === Facts.TEXT && root.row !== null && !root.truncateText
|
|
91
|
+
&& root.row.s <= Kinds.OFFICE_LIMIT && Kinds.isOfficeDocument(root.row.n)
|
|
92
|
+
readonly property bool isHtmlRow: root.isOfficeRow || (root.rowState === Facts.CODE && root.row !== null && root.row.s <= root.textLimit && Kinds.isHtml(root.row.n))
|
|
93
|
+
readonly property bool isDocumentRow: root.isMarkdownRow || root.isHtmlRow
|
|
94
|
+
// The document pane stays null without a document row, so every reader guards the loader item.
|
|
95
|
+
readonly property var markdown: markdownLoader.item
|
|
96
|
+
// The document reader's activation is shared by the Loader and its item so the two cannot drift apart.
|
|
97
|
+
readonly property bool markdownActive: root.visible && !root.manualHold && root.isDocumentRow && (!root.isHtmlRow || root.selectionCount <= 1)
|
|
98
|
+
// Stretch renders a vector to the whole box, so the frame's pictures keep Fit for an SVG alone.
|
|
99
|
+
readonly property bool vectorPath: /\.svgz?$/i.test(root.path)
|
|
100
|
+
// EXIF orientations 5 to 8 swap the sides, and Qt fits its decode before it turns, so the box it is asked for turns too.
|
|
101
|
+
readonly property bool turned: root.meta !== null && root.meta.orient >= 5
|
|
102
|
+
|
|
103
|
+
// The states that draw a picture of the file itself. A PDF draws its own page, loading draws the
|
|
104
|
+
// crawl, and a multi-selection is a summary and never the cursor row's own picture.
|
|
105
|
+
readonly property bool wantsThumb: root.previewState !== Facts.LOADING
|
|
106
|
+
&& root.previewState !== Facts.PDF && root.previewState !== Facts.MULTI
|
|
107
|
+
// A thumbnail path is not a thumbnail: the cache file can be evicted between the pane's answer
|
|
108
|
+
// and the decode, and an Image that failed to load draws nothing at all. The fallback waits for
|
|
109
|
+
// Ready instead, because a file off a slow mount would leave the frame blank for seconds.
|
|
110
|
+
readonly property bool thumbDrawn: root.thumb.length > 0 ? frameThumb.status !== Image.Error
|
|
111
|
+
: frameThumb.status === Image.Ready
|
|
112
|
+
readonly property bool thumbShown: root.wantsThumb && root.thumbDrawn
|
|
113
|
+
// For ui/Ipc.qml's columnFrameRect: the box a playing video's pixels must change inside.
|
|
114
|
+
readonly property Item frameItem: frame
|
|
115
|
+
// For ui/Ipc.qml's columnPictureRect: the player's content rect while it plays, else the poster;
|
|
116
|
+
// frameThumb keeps its geometry hidden under the player, so reading it then measures a stale poster.
|
|
117
|
+
readonly property Item pictureItem: playerLoader.visible && playerLoader.item ? playerLoader.item.contentItem : frameThumb
|
|
118
|
+
readonly property Item linesItem: lines
|
|
119
|
+
readonly property Item archiveItem: archivePane
|
|
120
|
+
readonly property alias factsLine: facts.line
|
|
121
|
+
// A 3D model's original is never decoded: Qt has no plugin for it, and each attempt logs a warning.
|
|
122
|
+
readonly property bool originalRefused: Kinds.isModel(root.path)
|
|
123
|
+
// Ready is the decoded picture (thumbShown is true while it loads); a model with no thumbnail coming reads Error, which ui/js/PreviewSwap.js treats as settled.
|
|
124
|
+
readonly property int frameStatus: root.originalRefused && root.thumb.length === 0 && root.noThumbComing ? Image.Error : frameThumb.status
|
|
125
|
+
// The two states whose picture is the thumbnail; audio's mark is what that state draws when it works.
|
|
126
|
+
readonly property bool picturesFromThumb: root.previewState === Facts.IMAGE || root.previewState === Facts.VIDEO
|
|
127
|
+
|
|
128
|
+
// One mark per kind in the selection, front-most first; ui/KindStack.qml stacks them.
|
|
129
|
+
readonly property var multiMarks: root.previewState === Facts.MULTI
|
|
130
|
+
? Facts.multiMarks(root.selectedRows) : []
|
|
131
|
+
|
|
132
|
+
Column {
|
|
133
|
+
anchors.fill: parent
|
|
134
|
+
anchors.margins: Theme.spacing.rowPaddingX
|
|
135
|
+
spacing: Theme.spacing.gap
|
|
136
|
+
|
|
137
|
+
Rectangle {
|
|
138
|
+
id: frame
|
|
139
|
+
width: parent.width
|
|
140
|
+
height: root.tallRow ? Facts.tallHeight(root.height, Theme.spacing.rowPaddingX, nameText.height, facts.height, Theme.spacing.gap) : Math.round(width * root.frameRatio)
|
|
141
|
+
// The listing's own colour, so on glass the pane's ground under it is the fill; see ui/Glass.qml.
|
|
142
|
+
color: Glass.on ? "transparent" : Theme.color.background
|
|
143
|
+
border.width: Theme.spacing.hairline
|
|
144
|
+
border.color: Theme.color.mutedFrame
|
|
145
|
+
// Mirrors hyprland decoration:rounding, the same as every other floating chrome surface.
|
|
146
|
+
radius: Style.cornerRadius
|
|
147
|
+
clip: true
|
|
148
|
+
|
|
149
|
+
// The thumbnail subsystem's own surface: a real thumbnail when there is one, the kind's
|
|
150
|
+
// mark when there is not, which is what the canvas means by "the glyph stands in here".
|
|
151
|
+
// Sized the way ui/PreviewImage.qml sizes its picture, and for its reasons: the exact fit, never enlarged in the decode.
|
|
152
|
+
Image {
|
|
153
|
+
id: frameThumb
|
|
154
|
+
readonly property real boxWidth: parent.width - 2 * Theme.spacing.hairline
|
|
155
|
+
readonly property real boxHeight: parent.height - 2 * Theme.spacing.hairline
|
|
156
|
+
readonly property bool vector: root.thumb.length === 0 && root.vectorPath
|
|
157
|
+
// The fallback is the original, so never enlarged; a cache file up to the original's own size.
|
|
158
|
+
// A video poster is the exception: it draws at the player's size, enlarged when the clip is small.
|
|
159
|
+
readonly property real fit: Thumbs.fitScale(boxWidth, boxHeight, implicitWidth, implicitHeight, root.thumb.length === 0 ? 1
|
|
160
|
+
: Thumbs.posterLimit(root.previewState === Facts.VIDEO, implicitWidth, implicitHeight, root.meta ? root.meta.w : 0, root.meta ? root.meta.h : 0))
|
|
161
|
+
x: vector ? Theme.spacing.hairline : Math.round((parent.width - width) / 2)
|
|
162
|
+
y: vector ? Theme.spacing.hairline : Math.round((parent.height - height) / 2)
|
|
163
|
+
width: vector ? boxWidth : implicitWidth * fit
|
|
164
|
+
height: vector ? boxHeight : implicitHeight * fit
|
|
165
|
+
visible: root.thumbShown && !playerLoader.visible && !(gifLoader.item && gifLoader.item.ready)
|
|
166
|
+
// Owned by root.applyDecodeTarget, never bound: a bound url and a bound
|
|
167
|
+
// ceiling land in separate passes and each pass reloads the standing file.
|
|
168
|
+
source: ""
|
|
169
|
+
fillMode: vector ? Image.PreserveAspectFit : Image.Stretch
|
|
170
|
+
// The fallback is the camera file itself, whose EXIF turn Qt applies only when asked.
|
|
171
|
+
autoTransform: true
|
|
172
|
+
asynchronous: true
|
|
173
|
+
cache: false
|
|
174
|
+
Component.onCompleted: root.applyDecodeTarget()
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// An animated GIF moves only after its still frame is drawn, and not while the column is hidden or covered; the still stays until the first moving frame is ready.
|
|
178
|
+
Loader {
|
|
179
|
+
id: gifLoader
|
|
180
|
+
x: frameThumb.x
|
|
181
|
+
y: frameThumb.y
|
|
182
|
+
width: frameThumb.width
|
|
183
|
+
height: frameThumb.height
|
|
184
|
+
active: root.previewState === Facts.IMAGE && root.meta !== null && root.meta.frames > 1
|
|
185
|
+
&& /\.gif$/i.test(root.path) && frameThumb.status === Image.Ready
|
|
186
|
+
source: "PreviewAnimation.qml"
|
|
187
|
+
onLoaded: {
|
|
188
|
+
item.path = Qt.binding(function () { return root.path })
|
|
189
|
+
item.shown = Qt.binding(function () { return root.visible && !root.overlayOpen })
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// The player, in the frame it paints into; built by the first press of play and not before, and by source rather than type, because QtMultimedia costs 20 MB on import alone.
|
|
194
|
+
Loader {
|
|
195
|
+
id: playerLoader
|
|
196
|
+
anchors.fill: parent
|
|
197
|
+
anchors.margins: Theme.spacing.hairline
|
|
198
|
+
active: root.wantsPlayback && root.playerAllowed
|
|
199
|
+
visible: active && root.previewState === Facts.VIDEO
|
|
200
|
+
source: "PreviewMedia.qml"
|
|
201
|
+
onLoaded: {
|
|
202
|
+
item.path = Qt.binding(function () { return root.path })
|
|
203
|
+
item.kind = Qt.binding(function () {
|
|
204
|
+
return root.previewState === Facts.VIDEO ? "video" : "audio"
|
|
205
|
+
})
|
|
206
|
+
item.letterbox = Qt.binding(function () { return Glass.on ? "transparent" : Theme.color.background })
|
|
207
|
+
// It exists because play was pressed, so it starts.
|
|
208
|
+
item.autoStart = true
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// The kind's mark, and the one line saying why it is standing in. A frame with neither is
|
|
213
|
+
// the blank-frame defect: an evicted cache file drew a bordered empty box and said nothing.
|
|
214
|
+
Column {
|
|
215
|
+
anchors.centerIn: parent
|
|
216
|
+
spacing: Theme.spacing.gap
|
|
217
|
+
// Match the thumbnail: the video surface owns the frame once opened,
|
|
218
|
+
// including pause/seek, so a missing poster must not cover its pixels.
|
|
219
|
+
visible: !root.thumbShown && !playerLoader.visible && root.glyphState()
|
|
220
|
+
|
|
221
|
+
Flea.Glyph {
|
|
222
|
+
anchors.horizontalCenter: parent.horizontalCenter
|
|
223
|
+
// A kind standing in for a missing thumbnail is a pane state, not a row mark: PreviewColumn.dc.html draws 40 on its Video tile.
|
|
224
|
+
maxSize: Theme.stateMarkSize
|
|
225
|
+
width: Theme.stateMarkSize
|
|
226
|
+
height: Theme.stateMarkSize
|
|
227
|
+
name: root.frameGlyph()
|
|
228
|
+
// A symlink takes the cyan role the row list already gives it; everything else stays muted.
|
|
229
|
+
color: root.previewState === Facts.SYMLINK ? Theme.color.symlink : Theme.color.mutedFrame
|
|
230
|
+
opacity: 0.7
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
Text {
|
|
234
|
+
anchors.horizontalCenter: parent.horizontalCenter
|
|
235
|
+
visible: root.frameNote().length > 0
|
|
236
|
+
text: root.frameNote()
|
|
237
|
+
color: Theme.color.muted
|
|
238
|
+
font.family: Theme.font.family
|
|
239
|
+
font.pixelSize: Theme.font.caption
|
|
240
|
+
textFormat: Text.PlainText
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// A multi-selection is a count, so the frame stacks the kinds it holds rather than
|
|
245
|
+
// picking one of them; the front mark is the kind the Kinds row below names first.
|
|
246
|
+
Flea.KindStack {
|
|
247
|
+
anchors.centerIn: parent
|
|
248
|
+
visible: root.previewState === Facts.MULTI && root.multiMarks.length > 0
|
|
249
|
+
marks: root.multiMarks
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// The file's own first lines, which is the frame's whole content for text and code.
|
|
253
|
+
Flea.PreviewLines {
|
|
254
|
+
id: lines
|
|
255
|
+
anchors.fill: parent
|
|
256
|
+
anchors.margins: Theme.spacing.hairline
|
|
257
|
+
visible: (root.previewState === Facts.TEXT || root.previewState === Facts.CODE) && !root.isDocumentRow
|
|
258
|
+
active: root.visible && !root.manualHold && (root.rowState === Facts.TEXT || root.rowState === Facts.CODE) && !root.isDocumentRow
|
|
259
|
+
path: root.path
|
|
260
|
+
size: root.row ? root.row.s : 0
|
|
261
|
+
maxBytes: root.textLimit
|
|
262
|
+
truncate: root.truncateText
|
|
263
|
+
backend: root.pane ? root.pane.backend : null
|
|
264
|
+
numbered: root.previewState === Facts.CODE
|
|
265
|
+
}
|
|
266
|
+
// The document body flows tall with no toggle; a file-path Loader compiles it only when needed.
|
|
267
|
+
Loader {
|
|
268
|
+
id: markdownLoader
|
|
269
|
+
anchors.fill: parent
|
|
270
|
+
anchors.margins: Theme.spacing.hairline
|
|
271
|
+
active: root.markdownActive
|
|
272
|
+
visible: root.isDocumentRow && (!root.isHtmlRow || root.selectionCount <= 1)
|
|
273
|
+
source: root.isHtmlRow ? "PreviewHtml.qml" : "PreviewMarkdown.qml"
|
|
274
|
+
onLoaded: {
|
|
275
|
+
item.path = Qt.binding(function () { return root.path })
|
|
276
|
+
item.size = Qt.binding(function () { return root.row ? root.row.s : 0 })
|
|
277
|
+
item.maxBytes = Qt.binding(function () { return root.isOfficeRow ? Kinds.OFFICE_LIMIT : root.textLimit })
|
|
278
|
+
item.active = Qt.binding(function () { return root.markdownActive })
|
|
279
|
+
item.truncate = Qt.binding(function () { return root.truncateText })
|
|
280
|
+
item.compact = true
|
|
281
|
+
item.externalScrollBars = true
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// The document reader takes the pane's backend once loaded, so Source and Markdown fences colour through the engine.
|
|
285
|
+
Binding {
|
|
286
|
+
target: markdownLoader.item
|
|
287
|
+
property: "backend"
|
|
288
|
+
value: root.pane ? root.pane.backend : null
|
|
289
|
+
when: markdownLoader.status === Loader.Ready
|
|
290
|
+
}
|
|
291
|
+
// The PDF's pages, one under another at the frame's width; QtPdf is reached only through this Loader, so a folder with no PDF never opens one.
|
|
292
|
+
Flickable {
|
|
293
|
+
id: pdfFlick
|
|
294
|
+
anchors.fill: parent
|
|
295
|
+
anchors.margins: Theme.spacing.hairline
|
|
296
|
+
visible: root.previewState === Facts.PDF
|
|
297
|
+
clip: true
|
|
298
|
+
contentWidth: width
|
|
299
|
+
contentHeight: pdfLoader.height
|
|
300
|
+
flickableDirection: Flickable.VerticalFlick
|
|
301
|
+
boundsBehavior: Flickable.StopAtBounds
|
|
302
|
+
Flea.FastScrollHandler { flickable: pdfFlick }
|
|
303
|
+
Flea.ViewportScrollBars { parent: pdfFlick; flickable: pdfFlick }
|
|
304
|
+
Loader {
|
|
305
|
+
id: pdfLoader
|
|
306
|
+
width: pdfFlick.width
|
|
307
|
+
height: item ? item.stackHeight : 0
|
|
308
|
+
active: root.visible && !root.manualHold && root.rowState === Facts.PDF
|
|
309
|
+
source: "PreviewPdf.qml"
|
|
310
|
+
onLoaded: {
|
|
311
|
+
item.continuous = true
|
|
312
|
+
item.path = Qt.binding(function () { return root.path })
|
|
313
|
+
item.viewport = pdfFlick
|
|
314
|
+
item.active = true
|
|
315
|
+
// A document on a hangable class loads from the backend's fetched copy.
|
|
316
|
+
item.backend = Qt.binding(function () { return root.pane ? root.pane.backend : null })
|
|
317
|
+
item.fetchFirst = Qt.binding(function () { return root.pane ? ExtThumbs.present(root.pane.storageClass) : false })
|
|
318
|
+
item.viewerSlot = "column"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// The canvas's Archive tile: the first entries by name, then the count it could not show.
|
|
324
|
+
Flea.PreviewArchive {
|
|
325
|
+
id: archivePane
|
|
326
|
+
anchors.fill: parent
|
|
327
|
+
anchors.margins: Theme.spacing.gap
|
|
328
|
+
visible: root.previewState === Facts.ARCHIVE && root.meta !== null
|
|
329
|
+
meta: root.meta
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
Flea.LoadingState {
|
|
333
|
+
anchors.fill: parent
|
|
334
|
+
visible: root.previewState === Facts.LOADING
|
|
335
|
+
heldOff: root.loadingHeldOff
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// The one sentence an error is, in the theme's error role; the facts below still show. An office file's
|
|
339
|
+
// embedded thumbnail is the frame's own picture, so Unsupported says "no preview" only when there is none.
|
|
340
|
+
Column {
|
|
341
|
+
anchors.centerIn: parent
|
|
342
|
+
visible: false // Unavailable previews must not cover the content.
|
|
343
|
+
spacing: Theme.spacing.gap
|
|
344
|
+
|
|
345
|
+
Flea.Glyph {
|
|
346
|
+
anchors.horizontalCenter: parent.horizontalCenter
|
|
347
|
+
// A failure mark stands alone, so it takes the pane-state ceiling; the board draws 32 here and 36 for unsupported, and 40 is the one token for both.
|
|
348
|
+
maxSize: Theme.stateMarkSize
|
|
349
|
+
width: Theme.stateMarkSize
|
|
350
|
+
height: Theme.stateMarkSize
|
|
351
|
+
name: root.previewState === Facts.ERROR ? "alert" : "file"
|
|
352
|
+
color: root.previewState === Facts.ERROR ? Theme.color.error : Theme.color.mutedFrame
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
Text {
|
|
356
|
+
anchors.horizontalCenter: parent.horizontalCenter
|
|
357
|
+
text: root.previewState === Facts.ERROR ? root.failure : "no preview"
|
|
358
|
+
color: root.previewState === Facts.ERROR ? Theme.color.foreground : Theme.color.muted
|
|
359
|
+
font.family: Theme.font.family
|
|
360
|
+
font.pixelSize: Theme.font.caption
|
|
361
|
+
textFormat: Text.PlainText
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// A media file adds the transport strip under the frame, which is what the canvas draws on
|
|
367
|
+
// its Video and Audio tiles. QtMultimedia is reached only through this Loader, on demand.
|
|
368
|
+
Loader {
|
|
369
|
+
id: mediaLoader
|
|
370
|
+
width: parent.width
|
|
371
|
+
height: active ? Theme.chromeHeight : 0
|
|
372
|
+
active: root.visible && (root.previewState === Facts.VIDEO || root.previewState === Facts.AUDIO)
|
|
373
|
+
sourceComponent: mediaTransport
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// corner: a filename is arbitrary text, so PlainText, the same rule every name on this surface follows.
|
|
377
|
+
Text {
|
|
378
|
+
id: nameText
|
|
379
|
+
width: parent.width
|
|
380
|
+
text: root.nameText()
|
|
381
|
+
color: Theme.color.foreground
|
|
382
|
+
font.family: Theme.font.family
|
|
383
|
+
font.pixelSize: Theme.font.body
|
|
384
|
+
textFormat: Text.PlainText
|
|
385
|
+
elide: Text.ElideRight
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
Flea.PreviewFacts {
|
|
389
|
+
id: facts
|
|
390
|
+
width: parent.width
|
|
391
|
+
compact: root.tallRow && ViewState.previewFacts === "compact"
|
|
392
|
+
line: Facts.compactLine(root.rowState, root.row, root.meta, root.kindName, root.factExtra)
|
|
393
|
+
rows: root.factRows
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
Component {
|
|
398
|
+
id: mediaTransport
|
|
399
|
+
|
|
400
|
+
Item {
|
|
401
|
+
id: transport
|
|
402
|
+
readonly property bool playing: playerLoader.item ? playerLoader.item.status === "playing" : false
|
|
403
|
+
readonly property real position: playerLoader.item ? playerLoader.item.position : 0
|
|
404
|
+
readonly property var strip: strip
|
|
405
|
+
|
|
406
|
+
// The player is playerLoader in the frame above; the probe's duration gives the strip a scale until it exists.
|
|
407
|
+
Flea.MediaStrip {
|
|
408
|
+
id: strip
|
|
409
|
+
anchors.fill: parent
|
|
410
|
+
playing: transport.playing
|
|
411
|
+
position: transport.position
|
|
412
|
+
duration: transport.position > 0 && playerLoader.item && playerLoader.item.duration > 0
|
|
413
|
+
? playerLoader.item.duration
|
|
414
|
+
: (root.meta && root.meta.durationMs ? root.meta.durationMs : 0)
|
|
415
|
+
onToggled: {
|
|
416
|
+
if (!root.wantsPlayback)
|
|
417
|
+
root.wantsPlayback = true
|
|
418
|
+
else if (playerLoader.item)
|
|
419
|
+
playerLoader.item.togglePlay()
|
|
420
|
+
}
|
|
421
|
+
onSeeked: function (ms) { if (playerLoader.item) playerLoader.item.seekTo(ms) }
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
Flea.PreviewScroll {
|
|
427
|
+
id: scrolling
|
|
428
|
+
column: root
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function pageBy(direction) {
|
|
432
|
+
if (root.rowState === Facts.PDF) {
|
|
433
|
+
if (!root.overlayOpen && !root.manualHold && !root.pending)
|
|
434
|
+
PreviewKeys.pageViewport(pdfFlick, direction)
|
|
435
|
+
} else scrolling.pageBy(direction)
|
|
436
|
+
}
|
|
437
|
+
// The page under the frame's top, read back over IPC too, and the turn that scrolls to the next or previous one.
|
|
438
|
+
function pdfPage() { return pdfLoader.item ? pdfLoader.item.page : 0 }
|
|
439
|
+
function turnPage(delta) { if (pdfLoader.item) pdfLoader.item.turn(delta) }
|
|
440
|
+
function toggleExpand() { root.expandRequested() }
|
|
441
|
+
function scrollPage(delta) { scrolling.scrollPage(delta, pdfFlick) }
|
|
442
|
+
// Whether a PdfDocument exists at all, which is what makes the Loader worth having.
|
|
443
|
+
function pdfLoaded() { return pdfLoader.item !== null }
|
|
444
|
+
function pdfLanded() { return pdfLoader.item ? pdfLoader.item.landedPages() : [] }
|
|
445
|
+
|
|
446
|
+
// For the geometry gates: the box of the page under the frame's top, or of page index, null until the document below built it.
|
|
447
|
+
function pdfPageItem(index) { return pdfLoader.item ? pdfLoader.item.pageSlot(index === undefined ? pdfLoader.item.page : index) : null }
|
|
448
|
+
// Read back through shell.qml's IPC so a test can prove the transport plays and seeks.
|
|
449
|
+
function mediaPlaying() { return mediaLoader.item ? mediaLoader.item.playing : false }
|
|
450
|
+
function mediaPosition() { return mediaLoader.item ? mediaLoader.item.position : 0 }
|
|
451
|
+
function mediaStripItem() { return mediaLoader.item ? mediaLoader.item.strip : null }
|
|
452
|
+
// Whether a player object exists at all, for the teardown check; playing false alone would mask one that survived.
|
|
453
|
+
function playerLoaded() { return playerLoader.item !== null }
|
|
454
|
+
// What the text, archive and failure surfaces actually draw, for ui/Ipc.qml: the lines, the member names, the sentence.
|
|
455
|
+
function textLines() { return lines.tooLarge ? "too large" : lines.lines.join("|") }
|
|
456
|
+
// Sample input: "# Notes\n###\ntext" reads "Notes\n\ntext"; source view returns the bytes.
|
|
457
|
+
function markdownText() {
|
|
458
|
+
if (!root.isMarkdownRow || !markdown) return ""
|
|
459
|
+
var body = markdown.rawText || ""
|
|
460
|
+
if (markdown.shownView === "source") return body
|
|
461
|
+
var out = body.split("\n")
|
|
462
|
+
for (var i = 0; i < out.length; i++) {
|
|
463
|
+
var head = /^#{1,6}\s/.exec(out[i])
|
|
464
|
+
if (head !== null) out[i] = out[i].slice(head[0].length)
|
|
465
|
+
else if (/^#{1,6}$/.test(out[i])) out[i] = ""
|
|
466
|
+
}
|
|
467
|
+
return out.join("\n")
|
|
468
|
+
}
|
|
469
|
+
readonly property bool textLoading: scrolling.loading
|
|
470
|
+
function archiveNames() { return root.meta && root.meta.names ? root.meta.names.map(function (e) { return e.n }).join("|") : "" }
|
|
471
|
+
function failureText() { return root.failure }
|
|
472
|
+
function toggleFacts() { ViewState.changeKey("previewFacts", ViewState.previewFacts === "compact" ? "full" : "compact") }
|
|
473
|
+
|
|
474
|
+
// The two whole sentences a multi-selection names its count with, one per count, each filled by Format.fill.
|
|
475
|
+
readonly property var selectedWords: ({ one: "%1 item selected", many: "%1 items selected" })
|
|
476
|
+
// A multi-selection describes a count, not a file, so it names the count instead of a name.
|
|
477
|
+
function nameText() {
|
|
478
|
+
if (root.previewState === Facts.MULTI)
|
|
479
|
+
return Format.fill(root.selectionCount === 1 ? root.selectedWords.one : root.selectedWords.many, root.selectionCount)
|
|
480
|
+
return root.row ? root.row.n : ""
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// One rule for the whole frame: a state that draws its own content takes the mark away, and
|
|
484
|
+
// gives it back the moment its own reader has nothing on screen. Error, unsupported and loading
|
|
485
|
+
// draw a mark of their own, so they never come back here.
|
|
486
|
+
function glyphState() {
|
|
487
|
+
switch (root.previewState) {
|
|
488
|
+
case Facts.ERROR:
|
|
489
|
+
case Facts.UNSUPPORTED:
|
|
490
|
+
case Facts.LOADING:
|
|
491
|
+
return false
|
|
492
|
+
case Facts.PDF:
|
|
493
|
+
return !root.pdfDrawn
|
|
494
|
+
case Facts.TEXT:
|
|
495
|
+
return root.isDocumentRow ? (markdown ? markdown.blank : false) : lines.blank
|
|
496
|
+
case Facts.CODE:
|
|
497
|
+
return root.isDocumentRow ? (markdown ? markdown.blank : false) : lines.blank
|
|
498
|
+
case Facts.ARCHIVE:
|
|
499
|
+
return root.meta === null
|
|
500
|
+
case Facts.MULTI:
|
|
501
|
+
return root.multiMarks.length === 0
|
|
502
|
+
}
|
|
503
|
+
return true
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// The cache file while there is one, then the image itself once the backend says none is coming.
|
|
507
|
+
// A held frame never decodes the original: its cache entry still shows, nothing else does.
|
|
508
|
+
function frameSource() {
|
|
509
|
+
if (!root.visible) return ""
|
|
510
|
+
if (root.thumb.length > 0)
|
|
511
|
+
return Format.fileUri(root.thumb)
|
|
512
|
+
if (!root.manualHold && root.noThumbComing && root.previewState === Facts.IMAGE && root.path.length > 0 && !root.originalRefused)
|
|
513
|
+
return Format.fileUri(root.path)
|
|
514
|
+
return ""
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// One binding for the whole decode request: url and ceiling change in one pass, zero is Qt unbounded.
|
|
518
|
+
readonly property var decodeTarget: ({
|
|
519
|
+
url: root.frameSource(),
|
|
520
|
+
w: root.thumb.length > 0 ? 0 : Math.max(1, Math.round(root.turned ? frameThumb.boxHeight : frameThumb.boxWidth)),
|
|
521
|
+
h: root.thumb.length > 0 ? 0 : Math.max(1, Math.round(root.turned ? frameThumb.boxWidth : frameThumb.boxHeight))
|
|
522
|
+
})
|
|
523
|
+
onDecodeTargetChanged: root.applyDecodeTarget()
|
|
524
|
+
|
|
525
|
+
// Blank first, then ceiling, then url, so the three never land in separate passes.
|
|
526
|
+
// A request that changed nothing is skipped, so a relayout over a cache file loads nothing.
|
|
527
|
+
function applyDecodeTarget() {
|
|
528
|
+
var t = root.decodeTarget
|
|
529
|
+
if (String(frameThumb.source) === String(t.url)
|
|
530
|
+
&& frameThumb.sourceSize.width === t.w && frameThumb.sourceSize.height === t.h)
|
|
531
|
+
return
|
|
532
|
+
frameThumb.source = ""
|
|
533
|
+
frameThumb.sourceSize.width = t.w
|
|
534
|
+
frameThumb.sourceSize.height = t.h
|
|
535
|
+
frameThumb.source = t.url
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Why the frame is showing a mark instead of the thing it meant to draw. Empty for every state
|
|
539
|
+
// whose mark is simply what it draws, so the line only ever appears when something went wrong.
|
|
540
|
+
function frameNote() {
|
|
541
|
+
return root.manualHold ? KeyName.hinted("%1 loads it", "loadPreview") : ""
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function frameGlyph() {
|
|
545
|
+
if (root.previewState === Facts.SYMLINK)
|
|
546
|
+
return "symlink"
|
|
547
|
+
if (root.previewState === Facts.MULTI)
|
|
548
|
+
return "file"
|
|
549
|
+
return root.row ? Icons.glyphForRow(root.row.i, root.row.p) : "file"
|
|
550
|
+
}
|
|
551
|
+
}
|