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
package/ui/KindStack.qml
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
|
|
4
|
+
// The marks a multi-selection stacks in the preview frame, one per kind, front-most first. The
|
|
5
|
+
// canvas offsets its marks a quarter of the mark across and an eleventh of it down, so both steps
|
|
6
|
+
// are measured against the mark this pane actually draws, HANDOFF rule 17's stateMarkSize.
|
|
7
|
+
Item {
|
|
8
|
+
id: root
|
|
9
|
+
|
|
10
|
+
// Glyph names, front-most first, as ui/js/Facts.js multiMarks builds them.
|
|
11
|
+
property var marks: []
|
|
12
|
+
|
|
13
|
+
readonly property int stepX: Math.round(Theme.stateMarkSize / 4)
|
|
14
|
+
readonly property int stepY: Math.round(Theme.stateMarkSize / 11)
|
|
15
|
+
// Every mark behind the front one is a step fainter, which is the canvas's 1.0, 0.7 and 0.4.
|
|
16
|
+
readonly property real fade: 0.3
|
|
17
|
+
readonly property int steps: Math.max(0, root.marks.length - 1)
|
|
18
|
+
|
|
19
|
+
width: Theme.stateMarkSize + root.steps * root.stepX
|
|
20
|
+
height: Theme.stateMarkSize + root.steps * root.stepY
|
|
21
|
+
|
|
22
|
+
Repeater {
|
|
23
|
+
model: root.marks
|
|
24
|
+
|
|
25
|
+
delegate: Flea.Glyph {
|
|
26
|
+
required property string modelData
|
|
27
|
+
required property int index
|
|
28
|
+
// Model order paints back to front, so the front mark has to claim its own z.
|
|
29
|
+
z: root.marks.length - index
|
|
30
|
+
x: (root.steps - index) * root.stepX
|
|
31
|
+
y: index * root.stepY
|
|
32
|
+
maxSize: Theme.stateMarkSize
|
|
33
|
+
width: Theme.stateMarkSize
|
|
34
|
+
height: Theme.stateMarkSize
|
|
35
|
+
name: modelData
|
|
36
|
+
color: Theme.color.mutedFrame
|
|
37
|
+
opacity: 1 - index * root.fade
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
package/ui/LangMark.qml
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import QtQuick.Shapes
|
|
3
|
+
import "js/LangMarkPaths.js" as LangMarkPaths
|
|
4
|
+
|
|
5
|
+
// A language logo on the file page: stroked page plus filled logo in the same ink.
|
|
6
|
+
Item {
|
|
7
|
+
id: root
|
|
8
|
+
|
|
9
|
+
property string slug: ""
|
|
10
|
+
property color color: "transparent"
|
|
11
|
+
// Shared 24-unit grid with ui/js/Icons.js.
|
|
12
|
+
readonly property real grid: 24
|
|
13
|
+
// Caller ceiling; without one it draws nothing (fails loud).
|
|
14
|
+
property real maxSize
|
|
15
|
+
// "scale" would shadow Item.scale, as in ui/Glyph.qml.
|
|
16
|
+
readonly property real markSize: Math.min(root.maxSize, root.width, root.height)
|
|
17
|
+
readonly property real gridScale: root.markSize / root.grid
|
|
18
|
+
// Board's two-unit stroke on the shared grid.
|
|
19
|
+
property real strokeWidth: 2
|
|
20
|
+
// Caller caps; false is the Omarchy cut.
|
|
21
|
+
property bool roundCaps: false
|
|
22
|
+
|
|
23
|
+
// File page with the corner cut for the logo box (x 1..15, y 9..23).
|
|
24
|
+
readonly property string page: "M4 7V2h10l6 6v14H17 M14 2v6h6"
|
|
25
|
+
|
|
26
|
+
// Grid-sized Shape re-centered in the slot (Scale origin is 0,0).
|
|
27
|
+
Shape {
|
|
28
|
+
width: root.grid
|
|
29
|
+
height: root.grid
|
|
30
|
+
x: (root.width - root.markSize) / 2
|
|
31
|
+
y: (root.height - root.markSize) / 2
|
|
32
|
+
preferredRendererType: Shape.CurveRenderer
|
|
33
|
+
transform: Scale { xScale: root.gridScale; yScale: root.gridScale }
|
|
34
|
+
|
|
35
|
+
ShapePath {
|
|
36
|
+
strokeColor: root.color
|
|
37
|
+
fillColor: "transparent"
|
|
38
|
+
strokeWidth: root.strokeWidth
|
|
39
|
+
capStyle: root.roundCaps ? ShapePath.RoundCap : ShapePath.SquareCap
|
|
40
|
+
joinStyle: root.roundCaps ? ShapePath.RoundJoin : ShapePath.MiterJoin
|
|
41
|
+
PathSvg { path: root.page }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Filled logo baked via translate(1 9) scale(14/24); see ui/js/LangMarkPaths.js.
|
|
45
|
+
ShapePath {
|
|
46
|
+
strokeColor: "transparent"
|
|
47
|
+
fillColor: root.color
|
|
48
|
+
PathSvg { path: LangMarkPaths.pathFor(root.slug) }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
pragma ComponentBehavior: Bound
|
|
2
|
+
import QtQuick
|
|
3
|
+
import qs.Commons
|
|
4
|
+
|
|
5
|
+
// Only a row with a visible language logo builds it; the glyph supplies its geometry.
|
|
6
|
+
Loader {
|
|
7
|
+
id: root
|
|
8
|
+
|
|
9
|
+
required property Item owner
|
|
10
|
+
required property Item glyph
|
|
11
|
+
active: !root.owner.thumbDrawn && root.owner.langSlug !== ""
|
|
12
|
+
visible: !root.owner.thumbDrawn && root.owner.langSlug !== ""
|
|
13
|
+
x: root.glyph.x
|
|
14
|
+
y: root.glyph.y
|
|
15
|
+
width: root.glyph.width
|
|
16
|
+
height: root.glyph.height
|
|
17
|
+
sourceComponent: LangMark {
|
|
18
|
+
anchors.fill: parent
|
|
19
|
+
maxSize: root.glyph.maxSize
|
|
20
|
+
slug: root.owner.langSlug
|
|
21
|
+
color: root.glyph.color
|
|
22
|
+
strokeWidth: root.glyph.strokeWidth
|
|
23
|
+
roundCaps: ViewState.hyprlandIcons && Style.cornerRadius > 0
|
|
24
|
+
}
|
|
25
|
+
onStatusChanged: if (status === Loader.Error) throw new Error("LangMark.qml did not load: Loader status " + status)
|
|
26
|
+
}
|
package/ui/List.qml
ADDED
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
import "js/ClipMarks.js" as ClipMarks
|
|
4
|
+
import "js/DirSizes.js" as DirSizes
|
|
5
|
+
import "js/ExtThumbs.js" as ExtThumbs
|
|
6
|
+
import "js/Filter.js" as Filter
|
|
7
|
+
import "js/Scroll.js" as Scroll
|
|
8
|
+
import "js/ScrollOff.js" as ScrollOff
|
|
9
|
+
import "js/Tap.js" as Tap
|
|
10
|
+
import "js/Thumbs.js" as Thumbs
|
|
11
|
+
|
|
12
|
+
// The listing's render, scroll and settle-triggered refetch, split out of Pane.qml; reaches Pane's state through the pane reference and the context menu through menu, both handed in at instantiation.
|
|
13
|
+
ListView {
|
|
14
|
+
id: root
|
|
15
|
+
|
|
16
|
+
property var pane: null
|
|
17
|
+
readonly property bool fileDragActive: dragSession.Drag.active
|
|
18
|
+
property var menu: null
|
|
19
|
+
|
|
20
|
+
// Parked rows built ahead of the next landing; a row parks invisible and the landing shows it again.
|
|
21
|
+
readonly property Flea.PrebuildDriver prebuild: Flea.PrebuildDriver {
|
|
22
|
+
view: root
|
|
23
|
+
model: stable
|
|
24
|
+
pane: root.pane
|
|
25
|
+
limit: stable.warmRows
|
|
26
|
+
held: root.hiddenHeld
|
|
27
|
+
park: function (cell) { cell.live = false; cell.visible = false }
|
|
28
|
+
adopt: function (cell) { cell.live = true; cell.visible = true; cursorMark.place(cell) }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Shared once, read plainly per row, so no delegate builds its own width or array.
|
|
32
|
+
property real rowWidth: Scroll.contentWidth(root.width, Theme.spacing.rowPaddingX)
|
|
33
|
+
// Dual mode hides mode and kind on top of the stored set; one array, never one per row.
|
|
34
|
+
property var rowHiddenCols: root.pane && root.pane.dualMode ? ["mode", "kind"].concat(ViewState.hiddenCols) : ViewState.hiddenCols
|
|
35
|
+
// Shared name budgets remove the per-row floor; Row keeps its local default for PickerList and drop targets.
|
|
36
|
+
readonly property bool listDual: root.pane && root.pane.dualMode ? true : false
|
|
37
|
+
readonly property real listMarkSlot: root.listDual ? Theme.markSize : Theme.iconSize
|
|
38
|
+
readonly property real listSizeWidth: root.listDual ? Theme.dualColumn.size : Theme.column.size
|
|
39
|
+
readonly property real listDateWidth: root.listDual ? Theme.dualColumn.date : Theme.column.date
|
|
40
|
+
// The same set Row.cols resolves, from the same width and hidden array, so the two cannot drift.
|
|
41
|
+
readonly property var listCols: root.pane && root.pane.recentMode.length > 0 ? Theme.columns(root.rowWidth, root.rowHiddenCols, root.listDateWidth, true, root.listDual) : root.listDual ? Theme.dualColumns(root.rowWidth, root.rowHiddenCols) : Theme.columns(root.rowWidth, root.rowHiddenCols, root.listDateWidth)
|
|
42
|
+
readonly property bool listModeShown: root.listCols ? !!root.listCols.mode : false
|
|
43
|
+
readonly property bool listSizeShown: root.listCols ? !!root.listCols.size : false
|
|
44
|
+
readonly property bool listDateShown: root.listCols ? !!root.listCols.date : false
|
|
45
|
+
readonly property bool listKindShown: root.listCols ? !!root.listCols.kind : false
|
|
46
|
+
// Matches Theme.clipMarkSize; the reserve keeps the glyph readable.
|
|
47
|
+
readonly property int listClipPx: Theme.clipMarkSize
|
|
48
|
+
// Exact drawn geometry: the row less padding, mark, gap, columns, gaps and name-to-mode gap, in pixels then floored.
|
|
49
|
+
readonly property real nameSlotPlainPx: Math.max(0, root.rowWidth - 2 * Theme.spacing.rowPaddingX - root.listMarkSlot - Theme.spacing.gap - (root.listModeShown ? Theme.column.mode : 0) - (root.listSizeShown ? root.listSizeWidth : 0) - (root.listDateShown ? root.listDateWidth : 0) - (root.listKindShown ? Theme.column.kind : 0) - (root.listKindShown ? Theme.spacing.gap : 0) - ((root.listDateShown && !root.listDual) ? Theme.spacing.gap : 0) - ((root.listSizeShown && !root.listDual) ? Theme.spacing.gap : 0) - (root.listModeShown ? Theme.spacing.gap : 0))
|
|
50
|
+
readonly property real nameSlotClipPx: Math.max(0, root.nameSlotPlainPx - Theme.spacing.gap - root.listClipPx)
|
|
51
|
+
readonly property int nameBudgetPlain: Theme.bodyAdvance > 0 && root.nameSlotPlainPx > 0 ? Math.floor(root.nameSlotPlainPx / Theme.bodyAdvance) : -1
|
|
52
|
+
readonly property int nameBudgetClip: Theme.bodyAdvance > 0 && root.nameSlotClipPx > 0 ? Math.floor(root.nameSlotClipPx / Theme.bodyAdvance) : -1
|
|
53
|
+
property bool clipEmpty: ClipMarks.isEmpty(root.pane ? root.pane.clipboard : null)
|
|
54
|
+
// The short-circuit below is the only release while empty, so a cut of a large directory frees its lookup here.
|
|
55
|
+
onClipEmptyChanged: { if (root.clipEmpty) ClipMarks.release() }
|
|
56
|
+
|
|
57
|
+
// Pane owns cursorIndex, thumbState and dirSizeState; List only computes what changed and hands it back.
|
|
58
|
+
// Both ends of cursorClamped are view positions, not listing rows: under a filter they differ.
|
|
59
|
+
signal cursorClamped(int first, int last)
|
|
60
|
+
signal thumbsApplied(var work)
|
|
61
|
+
signal dirSizesApplied(var ask)
|
|
62
|
+
signal dirSizesCancelled()
|
|
63
|
+
|
|
64
|
+
focus: true
|
|
65
|
+
keyNavigationEnabled: false
|
|
66
|
+
// Hidden holds no delegates; an edit the List held when it hid keeps its own per RenameField.qml.
|
|
67
|
+
model: Flea.StableModel { id: stable; view: root; total: (root.visible || root.renameHeld) ? root.pane.shownTotal : 0
|
|
68
|
+
warm: root.visible && root.pane.searchMode.length > 0 && root.pane.swap.searchWarm === true; warmRows: Math.floor((root.height + root.cacheBuffer) / Theme.fileRowHeight) + 1 }
|
|
69
|
+
clip: true
|
|
70
|
+
cacheBuffer: Theme.fileRowHeight * pane.cacheRows
|
|
71
|
+
boundsBehavior: Flickable.StopAtBounds
|
|
72
|
+
highlightMoveDuration: 0
|
|
73
|
+
// Every property the delegate draws binds to index and cursor is refiled by listingIndex, so a row leaving the buffer is re-bound rather than rebuilt.
|
|
74
|
+
reuseItems: true
|
|
75
|
+
// The one row drawn as the cursor; a cursor move touches two delegates, not every live one.
|
|
76
|
+
Flea.CursorMark { id: cursorMark; row: root.pane.cursorIndex }
|
|
77
|
+
|
|
78
|
+
Flea.FastScrollHandler {
|
|
79
|
+
parent: root
|
|
80
|
+
flickable: root
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
readonly property alias scrollBar: verticalScroll
|
|
84
|
+
Flea.ViewportScrollBar {
|
|
85
|
+
id: verticalScroll
|
|
86
|
+
parent: root
|
|
87
|
+
anchors { top: parent.top; right: parent.right }
|
|
88
|
+
flickable: root
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
Flea.SelectionBand {
|
|
92
|
+
parent: root
|
|
93
|
+
pane: root.pane
|
|
94
|
+
flickable: root
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
Flea.FileDrag {
|
|
98
|
+
id: dragSession
|
|
99
|
+
pane: root.pane
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
delegate: Flea.Row {
|
|
103
|
+
id: cell
|
|
104
|
+
required property int index
|
|
105
|
+
// Parked while pooled: each listing read returns its own last value until onReused rebinds it before the next frame; a row holding the open editor stays live, since a prebuild create pools and reuses the shown rows and pooling would destroy the editor.
|
|
106
|
+
property bool live: true
|
|
107
|
+
ListView.onPooled: if (!cell.renaming) cell.live = false
|
|
108
|
+
ListView.onReused: {
|
|
109
|
+
// The driver's create can take a pooled row past the shown ones; it parks as a built one does.
|
|
110
|
+
if (cell.index >= root.count) { root.prebuild.parkCell(cell); return }
|
|
111
|
+
cell.live = true
|
|
112
|
+
root.prebuild.adoptCell(cell)
|
|
113
|
+
}
|
|
114
|
+
// Built ahead of a landing past the shown rows: parked invisible until the landing reuses it.
|
|
115
|
+
property bool prebuilt: false
|
|
116
|
+
Component.onDestruction: root.prebuild.gone(cell)
|
|
117
|
+
// index is where the row is drawn; listingIndex is the row the backend numbers, and under a
|
|
118
|
+
// filter the two are different. Everything that leaves this delegate takes the listing one.
|
|
119
|
+
readonly property int listingIndex: cell.live ? Filter.at(root.pane.shown, index) : -1
|
|
120
|
+
// Filed by listing row in the view's cursor mark, which sets cursor; see ui/CursorMark.qml.
|
|
121
|
+
property int markRow: -1
|
|
122
|
+
Component.onCompleted: if (!root.prebuild.built(cell)) cursorMark.place(cell)
|
|
123
|
+
onListingIndexChanged: cursorMark.place(cell)
|
|
124
|
+
// The scroll lane stays clear so rows never reflow under the bar.
|
|
125
|
+
width: root.rowWidth
|
|
126
|
+
paintWidth: root.width
|
|
127
|
+
row: cell.live ? root.pane.rowFor(listingIndex) : cell.row
|
|
128
|
+
paneFocused: root.pane.paneFocused
|
|
129
|
+
dualMode: root.pane.dualMode
|
|
130
|
+
hiddenCols: root.rowHiddenCols
|
|
131
|
+
// One Columns.set per List state, shared by every delegate; Row keeps its local default for PickerList and drop targets.
|
|
132
|
+
assignedCols: root.listCols
|
|
133
|
+
hovered: hover.hovered
|
|
134
|
+
thumb: cell.live ? root.thumbFor(listingIndex) : cell.thumb
|
|
135
|
+
selected: cell.live && root.pane.isSelected(listingIndex)
|
|
136
|
+
// Empty short-circuits before the library, so no row calls it while the clipboard is empty.
|
|
137
|
+
clipMark: !cell.live ? cell.clipMark : root.clipEmpty ? "" : ClipMarks.markForRow(root.pane, cell.row ? cell.row.n : "", root.pane.clipboard)
|
|
138
|
+
// Shared budgets: one floor per List state, not per row; drop rows keep local measured geometry in Row.
|
|
139
|
+
assignedNameBudget: cell.clipMark.length > 0 ? root.nameBudgetClip : root.nameBudgetPlain
|
|
140
|
+
// The highlight content builds with the filter strip, so no keystroke pays for it; mirrors the strip's own up rule.
|
|
141
|
+
markArmed: root.pane.filterTyping || root.pane.filterQuery.length > 0
|
|
142
|
+
// A search's location layout builds hidden after the strip's first frame, so no answer pays for it.
|
|
143
|
+
locateArmed: root.pane.searchMode.length > 0 && root.pane.swap.searchWarm === true
|
|
144
|
+
kindNames: cell.live ? root.pane.kindNames : cell.kindNames
|
|
145
|
+
dirSize: cell.live ? DirSizes.cellFor(root.pane.dirSizeState, listingIndex) : cell.dirSize
|
|
146
|
+
// A filter paints its run the same way a search does; filtering below is what keeps the
|
|
147
|
+
// ordinary columns, because these rows are still this directory's own and not walk results.
|
|
148
|
+
searchQuery: !cell.live ? cell.searchQuery : root.pane.searchMode.length > 0 ? root.pane.swap.answeredQuery : root.pane.filterQuery
|
|
149
|
+
filtering: cell.live ? root.pane.shown !== null : cell.filtering
|
|
150
|
+
// Sidebar040: Recent splits its path into Name and the fixed Location column.
|
|
151
|
+
recenting: cell.live ? root.pane.recentMode.length > 0 : cell.recenting
|
|
152
|
+
renaming: listingIndex >= 0 && listingIndex === root.pane.renamingIndex
|
|
153
|
+
renamePane: root.pane
|
|
154
|
+
// -1 is also what Filter.at answers for a stale delegate, so an idle list must never light one.
|
|
155
|
+
dropTarget: dragSession.dropIndex >= 0 && listingIndex === dragSession.dropIndex
|
|
156
|
+
dropCopying: dragSession.dragCopy
|
|
157
|
+
dropLinking: dragSession.dragLink
|
|
158
|
+
|
|
159
|
+
onRenameCommitted: function (newName) { root.pane.commitRename(newName) }
|
|
160
|
+
onRenameAbandoned: root.pane.renamingIndex = -1
|
|
161
|
+
|
|
162
|
+
HoverHandler {
|
|
163
|
+
id: hover
|
|
164
|
+
// Disabled while pooled, so a reused row starts unhovered as a new one does.
|
|
165
|
+
enabled: cell.live && root.pane.selectionBand === null
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
TapHandler {
|
|
169
|
+
id: tap
|
|
170
|
+
enabled: !cell.renaming
|
|
171
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
|
172
|
+
// A held press must still tap on release.
|
|
173
|
+
longPressThreshold: 0
|
|
174
|
+
// A press held past the interval must not fire while the button is
|
|
175
|
+
// still down on a row about to be dragged; the release still arms.
|
|
176
|
+
onPressedChanged: if (pressed) root.pane.pressSlowClick()
|
|
177
|
+
onTapped: function (eventPoint, button) {
|
|
178
|
+
if (button === Qt.MiddleButton)
|
|
179
|
+
Tap.tappedTab(root.pane.rowFor(listingIndex), root.pane.path, root.pane)
|
|
180
|
+
else if (button === Qt.RightButton)
|
|
181
|
+
Tap.tappedMenu(listingIndex, eventPoint, root.pane, root.menu)
|
|
182
|
+
else if (cell.onSizeCell(eventPoint.position)) {
|
|
183
|
+
// A folder's ⚖️ Size cell measures that folder and does nothing else; a double click stays one ask.
|
|
184
|
+
if (tap.tapCount === 1) root.pane.measureDirs([listingIndex])
|
|
185
|
+
} else {
|
|
186
|
+
var wasSole = root.pane.slowClickWasSole(listingIndex)
|
|
187
|
+
Tap.tapped(listingIndex, tap.tapCount, tap.point.modifiers, root.pane)
|
|
188
|
+
Tap.slowTap(root.pane, tap.tapCount === 1 && Tap.onName(cell.nameItem(), cell, eventPoint.position, false),
|
|
189
|
+
listingIndex, tap.point.modifiers, dragSession.Drag.active, wasSole)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
Flea.RowDrag {
|
|
195
|
+
session: dragSession
|
|
196
|
+
listingIndex: cell.listingIndex
|
|
197
|
+
row: cell.row
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// The listing keeps one row of bare ground at its end. SearchFilter rule 1 took the filter's
|
|
201
|
+
// sentence off this slot, and the ground under it is not the sentence: it is where a band starts
|
|
202
|
+
// and where the background menu is raised, and a listing whose last row sits flush on the bottom
|
|
203
|
+
// edge offers neither once it is scrolled to the end.
|
|
204
|
+
footer: Item {
|
|
205
|
+
width: root.rowWidth
|
|
206
|
+
height: Theme.chromeHeight
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Empty space under the last row belongs to the directory, not to a row, so it raises the
|
|
210
|
+
// background menu. Tap.onBackground says the point missed every delegate, which is what leaves a
|
|
211
|
+
// right click on a row to that row's own handler above.
|
|
212
|
+
TapHandler {
|
|
213
|
+
acceptedButtons: Qt.RightButton
|
|
214
|
+
onTapped: function (eventPoint) {
|
|
215
|
+
if (Tap.onBackground(root, eventPoint))
|
|
216
|
+
root.menu.openBackground(eventPoint.scenePosition)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
onContentYChanged: {
|
|
221
|
+
// Hidden geometry and a restore in flight move no shared state.
|
|
222
|
+
if (!root.visible || root.hiddenHeld)
|
|
223
|
+
return
|
|
224
|
+
// The cursor follows the bounded view, silent while that view did not move.
|
|
225
|
+
var at = Scroll.bounded(root.contentY, root.originY, root.contentHeight, root.height)
|
|
226
|
+
// Qt shifts originY when expanded delegates collapse; row offsets start at that origin.
|
|
227
|
+
var first = Math.floor((at - root.originY) / Theme.fileRowHeight)
|
|
228
|
+
var last = Math.min(root.pane.shownTotal - 1, first + root.pane.visibleRows - 1)
|
|
229
|
+
if (root.pane.renamingIndex >= 0) {
|
|
230
|
+
var range = root.visibleRange()
|
|
231
|
+
first = range.first
|
|
232
|
+
last = range.last
|
|
233
|
+
}
|
|
234
|
+
if (last >= first && root.pane.selectionBand === null && at !== root._clampAt) {
|
|
235
|
+
root._clampAt = at
|
|
236
|
+
root.cursorClamped(first, last)
|
|
237
|
+
}
|
|
238
|
+
root.menu.close()
|
|
239
|
+
// A scroll never cancels a size the user asked for (src/dirsize.js).
|
|
240
|
+
coalesce.start()
|
|
241
|
+
settle.restart()
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function visibleRange() {
|
|
245
|
+
var fallback = Thumbs.viewport(root.contentY - root.originY, Theme.fileRowHeight, root.pane.visibleRows, root.pane.shownTotal)
|
|
246
|
+
// The retained error caption expands one row; query actual delegates while it is present.
|
|
247
|
+
if (root.pane.renamingIndex >= 0) {
|
|
248
|
+
var first = root.indexAt(0, root.contentY)
|
|
249
|
+
var last = root.indexAt(0, root.contentY + root.height - 1)
|
|
250
|
+
first = first < 0 ? fallback.first : first
|
|
251
|
+
return {first: first, last: last < 0 ? Math.min(root.count - 1, first + root.pane.visibleRows) : last}
|
|
252
|
+
}
|
|
253
|
+
return fallback
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Returning parks the view on the shared cursor once the reset rows land.
|
|
257
|
+
property bool hiddenHeld: false
|
|
258
|
+
// True while the List's own edit is open, so a hide keeps it in any binding order; a rename in Grid or Columns leaves it false.
|
|
259
|
+
property bool renameHeld: false
|
|
260
|
+
// The bounded view last emitted; a bounce holds it, so the cursor stays put.
|
|
261
|
+
property var _clampAt
|
|
262
|
+
// Last parked contentY and loop turns spent; only a value stable across turns ends the hold.
|
|
263
|
+
property real restoreY: -1
|
|
264
|
+
property int restoreTicks: 0
|
|
265
|
+
onVisibleChanged: {
|
|
266
|
+
if (!root.visible) {
|
|
267
|
+
coalesce.stop()
|
|
268
|
+
settle.stop()
|
|
269
|
+
root.hiddenHeld = true
|
|
270
|
+
root.restoreY = -1
|
|
271
|
+
root.restoreTicks = 0
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
root.renameHeld = root.pane ? root.pane.renamingIndex >= 0 : false
|
|
275
|
+
if (root.hiddenHeld)
|
|
276
|
+
root.restoreCursorView()
|
|
277
|
+
}
|
|
278
|
+
onCountChanged: {
|
|
279
|
+
if (root.hiddenHeld && root.visible && root.count > 0)
|
|
280
|
+
root.restoreCursorView()
|
|
281
|
+
root.prebuild.landed()
|
|
282
|
+
}
|
|
283
|
+
onCurrentIndexChanged: root.prebuild.kick()
|
|
284
|
+
function restoreCursorView() {
|
|
285
|
+
// A queued turn arriving after the hold ended is stale.
|
|
286
|
+
if (!root.hiddenHeld || !root.visible)
|
|
287
|
+
return
|
|
288
|
+
if (!root.pane) {
|
|
289
|
+
root.hiddenHeld = false
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
// The model reset may still be landing; a later turn retries.
|
|
293
|
+
if (root.count === 0 && root.pane.shownTotal > 0) {
|
|
294
|
+
root.deferRestore()
|
|
295
|
+
return
|
|
296
|
+
}
|
|
297
|
+
// An empty listing and a filtered-away cursor have no view to park, so the hold ends here.
|
|
298
|
+
var view = Filter.viewOf(root.pane.shown, root.pane.cursorIndex)
|
|
299
|
+
if (root.count === 0 || view < 0) {
|
|
300
|
+
root.hiddenHeld = false
|
|
301
|
+
return
|
|
302
|
+
}
|
|
303
|
+
root.forceLayout()
|
|
304
|
+
root.positionViewAtIndex(view, ListView.Contain)
|
|
305
|
+
// Only a value stable across turns ends the hold; an optimistic position never releases it.
|
|
306
|
+
if (root.coversCursor(view) && root.contentY === root.restoreY) {
|
|
307
|
+
root.hiddenHeld = false
|
|
308
|
+
root.restoreY = -1
|
|
309
|
+
root.restoreTicks = 0
|
|
310
|
+
settle.restart()
|
|
311
|
+
return
|
|
312
|
+
}
|
|
313
|
+
root.restoreY = root.contentY
|
|
314
|
+
root.deferRestore()
|
|
315
|
+
}
|
|
316
|
+
// The parked check the return asserts through: the cursor row is inside the viewport.
|
|
317
|
+
function coversCursor(view) {
|
|
318
|
+
var top = root.originY + view * Theme.fileRowHeight
|
|
319
|
+
return root.contentY <= top + Theme.fileRowHeight && root.contentY + root.height >= top
|
|
320
|
+
}
|
|
321
|
+
// One more loop turn, with a deadlock guard that ends the hold rather than keeping it.
|
|
322
|
+
function deferRestore() {
|
|
323
|
+
if (!root.visible)
|
|
324
|
+
return
|
|
325
|
+
if (root.restoreTicks >= 60) {
|
|
326
|
+
root.hiddenHeld = false
|
|
327
|
+
root.restoreY = -1
|
|
328
|
+
root.restoreTicks = 0
|
|
329
|
+
settle.restart()
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
root.restoreTicks += 1
|
|
333
|
+
Qt.callLater(root.restoreCursorView)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// The renaming row's view index, the same mapping restoreCursorView uses.
|
|
337
|
+
readonly property int renameViewIndex: root.pane && root.pane.renamingIndex >= 0 ? Filter.viewOf(root.pane.shown, root.pane.renamingIndex) : -1
|
|
338
|
+
// The renaming delegate's error height, read once here rather than bound per row; none while hidden, when Grid or Columns owns the editor.
|
|
339
|
+
readonly property real renameErrorHeight: {
|
|
340
|
+
if (!root.visible || !root.pane || root.pane.renamingIndex < 0 || root.pane.renameError.length === 0) return 0
|
|
341
|
+
var ed = root.pane.renameEditor()
|
|
342
|
+
var f = ed ? ed.editorField : null
|
|
343
|
+
return f ? f.errorHeight : 0
|
|
344
|
+
}
|
|
345
|
+
// Set when an error line appears or grows, and spent by the view's next contentHeight change.
|
|
346
|
+
property bool containRenameError: false
|
|
347
|
+
onRenameErrorHeightChanged: root.containRenameError = root.renameErrorHeight > 0
|
|
348
|
+
// The error line's growth lands in contentHeight after layout, so the row is contained once then, never on a later scroll's estimate.
|
|
349
|
+
onContentHeightChanged: if (root.containRenameError && root.renameViewIndex >= 0) { root.containRenameError = false; root.positionViewAtIndex(root.renameViewIndex, ListView.Contain) }
|
|
350
|
+
|
|
351
|
+
// Pane's own open() and its Connections.onRows reach these two through the wrapper functions below.
|
|
352
|
+
Timer {
|
|
353
|
+
id: coalesce
|
|
354
|
+
interval: root.pane.coalesceMs
|
|
355
|
+
repeat: false
|
|
356
|
+
onTriggered: root.requestIfDrifted()
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// The cursor keeps three rows of context above and below while scrolling; every cursor move routes through here.
|
|
360
|
+
function showCursor(view, context) {
|
|
361
|
+
var to = ScrollOff.cursorY(root, view, root.pane.shownTotal, Theme.fileRowHeight, context)
|
|
362
|
+
if (to !== null)
|
|
363
|
+
root.contentY = to
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Resize and filter changes can change the visible work without moving contentY.
|
|
367
|
+
Connections {
|
|
368
|
+
target: root.pane
|
|
369
|
+
function onVisibleRowsChanged() { if (root.visible) settle.restart() }
|
|
370
|
+
function onRenamingIndexChanged() { root.renameHeld = root.visible && root.pane.renamingIndex >= 0 }
|
|
371
|
+
function onFilterQueryChanged() {
|
|
372
|
+
if (!root.visible) return
|
|
373
|
+
var work = Filter.cut({ask: [], drop: []}, root.pane.shown, root.pane.thumbState)
|
|
374
|
+
work.drop = work.drop.filter(function(index) { return index !== root.pane.previewIndex })
|
|
375
|
+
if (work.drop.length > 0) {
|
|
376
|
+
root.pane.backend.thumbcancel(work.drop)
|
|
377
|
+
root.thumbsApplied(work)
|
|
378
|
+
}
|
|
379
|
+
// A scroll never cancels a size the user asked for (src/dirsize.js).
|
|
380
|
+
settle.restart()
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
Connections {
|
|
385
|
+
target: ViewState
|
|
386
|
+
function onThumbnailModeChanged() { if (root.visible) settle.restart() }
|
|
387
|
+
// A hidden-then-shown Size column asks for the visible rows at that moment.
|
|
388
|
+
function onHiddenColsChanged() { if (root.visible) settle.restart() }
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
Timer {
|
|
392
|
+
id: settle
|
|
393
|
+
interval: root.pane.firstSettleMs
|
|
394
|
+
repeat: false
|
|
395
|
+
onTriggered: { root.requestThumbs(); root.requestDirSizes() }
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Pane.open() primes the next settle to the short first-screen interval before any row arrives.
|
|
399
|
+
function primeSettle() { settle.interval = root.pane.firstSettleMs }
|
|
400
|
+
function restartCoalesce() { coalesce.restart() }
|
|
401
|
+
function restartSettle() { settle.restart() }
|
|
402
|
+
|
|
403
|
+
// Only the visible rows, only once each, and only after the list has stopped moving.
|
|
404
|
+
// Unknown storage holds until fsinfo names it, so the first screen never decodes as local.
|
|
405
|
+
function requestThumbs() {
|
|
406
|
+
if (!root.visible || root.pane.listInFlight || !root.pane.storageKnown)
|
|
407
|
+
return
|
|
408
|
+
var view = root.visibleRange()
|
|
409
|
+
// A filtered viewport covers a set and not a run, so the run it spans is what the planner
|
|
410
|
+
// gets and Filter.cut takes back every row inside that run the filter is hiding.
|
|
411
|
+
var span = Filter.span(root.pane.shown, view.first, view.last)
|
|
412
|
+
var work = Filter.cut(Thumbs.plan(root.pane.thumbState, root.pane.rows, root.pane.held, span.first, span.last, ViewState.thumbnailMode), root.pane.shown, root.pane.thumbState)
|
|
413
|
+
work.drop = work.drop.filter(function (index) { return index !== root.pane.previewIndex })
|
|
414
|
+
root.pane.backend.thumbcancel(work.drop)
|
|
415
|
+
// An off class still asks; the backend answers from the cache alone, see ui/js/ExtThumbs.js.
|
|
416
|
+
work.cacheOnly = ExtThumbs.cacheOnly(root.pane.storageClass, ViewState.preview)
|
|
417
|
+
root.pane.backend.thumb(work.ask, work.cacheOnly)
|
|
418
|
+
// The short first settle latches to the fling debounce only once a request has actually gone out.
|
|
419
|
+
if (work.ask.length > 0)
|
|
420
|
+
settle.interval = root.pane.settleMs
|
|
421
|
+
root.thumbsApplied(work)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function thumbFor(index) {
|
|
425
|
+
return Thumbs.allowed(root.pane.rowFor(index), ViewState.thumbnailMode) ? Thumbs.fileFor(root.pane.thumbState, index) : ""
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function dirSizeFor(index) {
|
|
429
|
+
return DirSizes.sizeFor(root.pane.dirSizeState, index)
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Same idiom as requestThumbs, minus a cancel: onContentYChanged already sent it, see above.
|
|
433
|
+
function requestDirSizes() {
|
|
434
|
+
// Folder sizes are measured only when the user asks: a ⚖️ click, see Pane.measureDirs.
|
|
435
|
+
return
|
|
436
|
+
if (!root.visible || root.pane.shownTotal === 0 || root.pane.listInFlight)
|
|
437
|
+
return
|
|
438
|
+
// A hidden Size column or a network or phone folder draws no size, so it asks for no walk.
|
|
439
|
+
if (!DirSizes.wantsSizes("list", ViewState.hiddenCols, root.pane.storageClass, root.pane.storageKnown))
|
|
440
|
+
return
|
|
441
|
+
// Thumbs.viewport() is reused: it takes no thumb-specific state, only geometry.
|
|
442
|
+
var view = root.visibleRange()
|
|
443
|
+
var span = Filter.span(root.pane.shown, view.first, view.last)
|
|
444
|
+
var ask = Filter.keep(DirSizes.plan(root.pane.dirSizeState, root.pane.rows, root.pane.held, span.first, span.last, ViewState.thumbnailMode), root.pane.shown)
|
|
445
|
+
if (ask.length > 0) {
|
|
446
|
+
root.pane.backend.dirsize(ask)
|
|
447
|
+
settle.interval = root.pane.settleMs
|
|
448
|
+
}
|
|
449
|
+
root.dirSizesApplied(ask)
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Handle an empty held window explicitly before applying held-edge arithmetic.
|
|
453
|
+
function requestIfDrifted() {
|
|
454
|
+
// No window while hidden, while a filter narrows rows already held, nor while a listing is out, whose windows are the directory asked for.
|
|
455
|
+
if (!root.visible || root.pane.total === 0 || root.pane.shown !== null || root.pane.listInFlight)
|
|
456
|
+
return
|
|
457
|
+
var firstVisible = Math.floor((root.contentY - root.originY) / Theme.fileRowHeight)
|
|
458
|
+
var lastVisible = firstVisible + root.pane.visibleRows
|
|
459
|
+
if (root.pane.renamingIndex >= 0) {
|
|
460
|
+
var range = root.visibleRange()
|
|
461
|
+
firstVisible = range.first
|
|
462
|
+
lastVisible = range.last + 1
|
|
463
|
+
}
|
|
464
|
+
if (root.pane.rows.length === 0) {
|
|
465
|
+
root.requestAround(firstVisible)
|
|
466
|
+
return
|
|
467
|
+
}
|
|
468
|
+
var heldEnd = root.pane.held + root.pane.rows.length
|
|
469
|
+
if (firstVisible - root.pane.held < root.pane.refetchMargin && root.pane.held > 0) {
|
|
470
|
+
root.requestAround(firstVisible)
|
|
471
|
+
} else if (heldEnd - lastVisible < root.pane.refetchMargin && heldEnd < root.pane.total) {
|
|
472
|
+
root.requestAround(firstVisible)
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function requestAround(firstVisible) {
|
|
477
|
+
var start = Math.max(0, firstVisible - root.pane.buffer)
|
|
478
|
+
root.pane.backend.window(start, root.pane.windowSize)
|
|
479
|
+
}
|
|
480
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "js/Swap.js" as Swap
|
|
3
|
+
|
|
4
|
+
// The listing's loading touch, EmptyState's sibling: the caller places it over listArea and
|
|
5
|
+
// gates visibility on listingState. The hold-off keeps a local listing, single-digit
|
|
6
|
+
// milliseconds on this box, from ever flashing the mark; only slow sources (network mounts,
|
|
7
|
+
// a cold spinning disk) live long enough to show it.
|
|
8
|
+
Item {
|
|
9
|
+
id: root
|
|
10
|
+
|
|
11
|
+
property int holdOffMs: Swap.HOLD_MS
|
|
12
|
+
property bool armed: false
|
|
13
|
+
// Set when the listing swap already held the old rows for its own cap, which spent this hold-off.
|
|
14
|
+
property bool heldOff: false
|
|
15
|
+
// The mark and its word are on screen; ui/PaneStates.qml tells ui/PaneSwap.qml, which keeps them Swap.MIN_SHOW_MS.
|
|
16
|
+
readonly property bool shown: root.visible && (root.armed || root.heldOff)
|
|
17
|
+
// The crawl's own width, so a Columns pane can tell whether it clears the listed columns.
|
|
18
|
+
readonly property real naturalWidth: crawl.implicitWidth
|
|
19
|
+
|
|
20
|
+
// running binds to visibility rather than an onVisibleChanged handler: the pane starts life
|
|
21
|
+
// in "loading", so visible is true at creation and a change handler would never fire.
|
|
22
|
+
Timer {
|
|
23
|
+
id: holdOff
|
|
24
|
+
interval: root.holdOffMs
|
|
25
|
+
running: root.visible
|
|
26
|
+
onTriggered: root.armed = true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
onVisibleChanged: if (!root.visible) root.armed = false
|
|
30
|
+
|
|
31
|
+
Column {
|
|
32
|
+
id: crawl
|
|
33
|
+
anchors.centerIn: parent
|
|
34
|
+
spacing: Theme.spacing.gap
|
|
35
|
+
visible: root.armed || root.heldOff
|
|
36
|
+
|
|
37
|
+
Spinner {
|
|
38
|
+
anchors.horizontalCenter: parent.horizontalCenter
|
|
39
|
+
// The same brand mark as EmptyState's hero, which States.dc.html draws at 48; two row heights was 74.
|
|
40
|
+
width: Theme.heroMarkSize
|
|
41
|
+
height: Theme.heroMarkSize
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// States draws the crawl with one word under it, and one word is the whole of what it knows.
|
|
45
|
+
Text {
|
|
46
|
+
anchors.horizontalCenter: parent.horizontalCenter
|
|
47
|
+
text: "reading"
|
|
48
|
+
color: Theme.color.muted
|
|
49
|
+
font.family: Theme.font.family
|
|
50
|
+
font.pixelSize: Theme.font.caption
|
|
51
|
+
textFormat: Text.PlainText
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|