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/GridArea.qml
ADDED
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
import "js/ClipMarks.js" as ClipMarks
|
|
4
|
+
import "js/Density.js" as Density
|
|
5
|
+
import "js/DirSizes.js" as DirSizes
|
|
6
|
+
import "js/Drag.js" as DragOps
|
|
7
|
+
import "js/DragOut.js" as DragOut
|
|
8
|
+
import "js/ExtThumbs.js" as ExtThumbs
|
|
9
|
+
import "js/Filter.js" as Filter
|
|
10
|
+
import "js/Focus.js" as Focus
|
|
11
|
+
import "js/GridGeometry.js" as GridGeometry
|
|
12
|
+
import "js/Scroll.js" as Scroll
|
|
13
|
+
import "js/Tap.js" as Tap
|
|
14
|
+
import "js/Thumbs.js" as Thumbs
|
|
15
|
+
|
|
16
|
+
// Grid shares the list's rows, marks, thumbnails and viewport plan, scaled to tile rows.
|
|
17
|
+
GridView {
|
|
18
|
+
id: root
|
|
19
|
+
|
|
20
|
+
property var pane: null
|
|
21
|
+
readonly property bool fileDragActive: dragSession.Drag.active
|
|
22
|
+
property var menu: null
|
|
23
|
+
|
|
24
|
+
property real zoomTravel: 0
|
|
25
|
+
readonly property int wheelNotch: 120
|
|
26
|
+
readonly property int touchpadStep: 48
|
|
27
|
+
|
|
28
|
+
function zoomWheel(wheel) {
|
|
29
|
+
if (!ViewState.ctrlZoom) return false
|
|
30
|
+
var phase = wheel.phase !== undefined ? wheel.phase : Qt.NoScrollPhase
|
|
31
|
+
root.zoomTravel += Scroll.zoomTravel(phase, wheel.pixelDelta.y, wheel.angleDelta.y, root.touchpadStep, root.wheelNotch)
|
|
32
|
+
var steps = root.zoomTravel > 0 ? Math.floor(root.zoomTravel) : Math.ceil(root.zoomTravel)
|
|
33
|
+
if (steps !== 0) {
|
|
34
|
+
root.zoomTravel -= steps
|
|
35
|
+
var sizes = ["small", "medium", "large", "xlarge", "huge", "largest"]
|
|
36
|
+
var next = Math.max(0, Math.min(sizes.length - 1, sizes.indexOf(ViewState.thumbnailSize) + steps))
|
|
37
|
+
ViewState.changeSetting("preview.thumbSize", sizes[next])
|
|
38
|
+
}
|
|
39
|
+
return true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
signal thumbsApplied(var work)
|
|
43
|
+
signal dirSizesApplied(var ask)
|
|
44
|
+
signal dirSizesCancelled()
|
|
45
|
+
|
|
46
|
+
// Tile columns leave one gap, both edge insets and the scroll lane.
|
|
47
|
+
readonly property int columns: GridGeometry.columnsFor(root.width, Theme.grid.minCellWidth,
|
|
48
|
+
ViewState.thumbnailPixels, Theme.spacing.rowPaddingX, Theme.spacing.gap, Theme.spacing.rowPaddingX)
|
|
49
|
+
readonly property int tileRows: Math.max(1, Math.ceil(root.pane.shownTotal / root.columns))
|
|
50
|
+
// Mark, one gap, two caption lines, and the density's pad above and below.
|
|
51
|
+
readonly property int cellHeightPx: GridGeometry.cellHeightFor(ViewState.thumbnailPixels, Theme.spacing.gap,
|
|
52
|
+
Math.ceil(Theme.grid.captionHeight),
|
|
53
|
+
Density.gridPadY(Theme.spacing.rowPaddingX, ViewState.density))
|
|
54
|
+
+ renameExtraHeight
|
|
55
|
+
property Item renameEditor: null
|
|
56
|
+
property real renameExtraHeight: 0
|
|
57
|
+
property var renameRetirement: null
|
|
58
|
+
|
|
59
|
+
// Grid pooling can leave itemAtIndex pointing at a superseded same-row tile.
|
|
60
|
+
function currentRenameTile(expectedPane) {
|
|
61
|
+
var editor = root.renameEditor
|
|
62
|
+
var host = editor ? editor.editorHost : null
|
|
63
|
+
return editor && editor.visible && root.visible && !root.hiddenHeld && host && host.visible
|
|
64
|
+
&& editor.pane === expectedPane && editor.viewport === root && editor.ownsEdit()
|
|
65
|
+
&& host === editor.layoutHost() && host.renaming && host.editorField === editor ? host : null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
onPaneChanged: { root.renameRetirement = null; root.queueRenameLayout(); root.takeHeld() }
|
|
69
|
+
// Editor replacement and destruction must not reenter Grid layout through its cell height.
|
|
70
|
+
onRenameEditorChanged: {
|
|
71
|
+
if (root.renameEditor) root.renameRetirement = null
|
|
72
|
+
root.queueRenameLayout()
|
|
73
|
+
}
|
|
74
|
+
function queueRenameLayout() { Qt.callLater(root.settleRenameEditor) }
|
|
75
|
+
function retireRenameEditor(editor, retirement) {
|
|
76
|
+
if (root.renameEditor !== editor) return
|
|
77
|
+
root.renameRetirement = retirement
|
|
78
|
+
root.renameEditor = null
|
|
79
|
+
}
|
|
80
|
+
function settleRenameEditor() {
|
|
81
|
+
var retirement = root.renameRetirement
|
|
82
|
+
var sameEdit = retirement && !root.renameEditor && root.pane && root.pane === retirement.pane
|
|
83
|
+
&& root === retirement.viewport && root.pane.renamingIndex === retirement.index
|
|
84
|
+
var row = sameEdit ? root.pane.rowFor(retirement.index) : null
|
|
85
|
+
// A pending write can outlive its Loader. Keep only its values until that exact edit returns.
|
|
86
|
+
var keep = sameEdit && row && row.n.split("/").pop() === retirement.name
|
|
87
|
+
&& root.pane.renamePending && root.pane.renameRequest === retirement.request
|
|
88
|
+
if (!keep) root.renameRetirement = null
|
|
89
|
+
if (sameEdit && !root.pane.renamePending)
|
|
90
|
+
root.pane.renamingIndex = -1
|
|
91
|
+
var editor = root.renameEditor
|
|
92
|
+
if (editor && root.pane && root.pane.renamingIndex >= 0 && editor.extraHeight < 0) return
|
|
93
|
+
var height = root.pane && root.pane.renamingIndex >= 0 && editor ? editor.extraHeight : 0
|
|
94
|
+
if (height === root.renameExtraHeight) return
|
|
95
|
+
if (editor) editor.queueContainment()
|
|
96
|
+
root.renameExtraHeight = height
|
|
97
|
+
}
|
|
98
|
+
readonly property int visibleTileRows: Math.max(1, Math.ceil(root.height / root.cellHeightPx))
|
|
99
|
+
onColumnsChanged: if (root.visible) { settle.restart(); coalesce.restart() }
|
|
100
|
+
onVisibleTileRowsChanged: if (root.visible) { settle.restart(); coalesce.restart() }
|
|
101
|
+
|
|
102
|
+
focus: true
|
|
103
|
+
// Whichever view is up owns the keyboard, and Focus.handleKey is the one route all three take.
|
|
104
|
+
Keys.onPressed: function (event) {
|
|
105
|
+
root.prebuild.kick()
|
|
106
|
+
root.holdCache()
|
|
107
|
+
event.accepted = Focus.handleKey(event, root.pane, root.pane.sidebar)
|
|
108
|
+
}
|
|
109
|
+
// Written, not bound: a count change puts the view on row 0 as a reset does, which would drop a binding.
|
|
110
|
+
readonly property int cursorView: Filter.viewOf(root.pane.shown, root.pane.renamingIndex >= 0 ? root.pane.renamingIndex : root.pane.cursorIndex)
|
|
111
|
+
onCursorViewChanged: { root.prebuild.kick(); root.askLanding(); root.currentIndex = root.cursorView }
|
|
112
|
+
// Hidden holds no delegates; an edit in flight keeps its own per RenameField.qml.
|
|
113
|
+
model: Flea.StableModel { view: root; total: (root.visible || root.pane.renamingIndex >= 0) ? root.pane.shownTotal : 0; onResized: root.modelResized(); holdCurrent: root.pane.renamingIndex >= 0
|
|
114
|
+
warm: root.visible && root.pane.searchMode.length > 0 && root.pane.swap.searchWarm === true; warmRows: root.columns * (Math.floor(Math.max(0, root.height - root.topMargin + root.cacheFull) / root.cellHeight) + 2) }
|
|
115
|
+
clip: true
|
|
116
|
+
// Qt's own tracking scrolls a flush-parked end to the footer's end on a cursor move; revealCursor's Contain leaves a whole tile alone.
|
|
117
|
+
highlightFollowsCurrentItem: false
|
|
118
|
+
// Qt emits currentIndexChanged before it frees the old current item; positioning inside it leaves that item behind as a second delegate for its row.
|
|
119
|
+
onCurrentIndexChanged: { root.prebuild.kick(); root.holdCache(); Qt.callLater(root.revealCursor) }
|
|
120
|
+
function revealCursor() {
|
|
121
|
+
// StableModel.resize parks currentIndex on row 0 mid-change, so onResized places the view; a far landing waits for its window, which onRowsChanged lands.
|
|
122
|
+
if (root.visible && !root.hiddenHeld && !root.landingWait && root.count > 0 && root.cursorView >= 0 && root.currentIndex === root.cursorView)
|
|
123
|
+
root.containTile(root.cursorView)
|
|
124
|
+
}
|
|
125
|
+
// One gap of bare ground along the left, the top and below the last row; the hairline inset stays.
|
|
126
|
+
leftMargin: Theme.spacing.gap
|
|
127
|
+
topMargin: Theme.spacing.gap
|
|
128
|
+
bottomMargin: Theme.spacing.gap
|
|
129
|
+
cellWidth: GridGeometry.cellWidthFor(root.width, root.columns, Theme.spacing.gap, Theme.spacing.rowPaddingX)
|
|
130
|
+
cellHeight: root.cellHeightPx
|
|
131
|
+
// An emptied view drops its cache rows; they come back in cacheStepsMargin frame steps, each built in its own turn, never by incubation an emptied view would cancel.
|
|
132
|
+
// A switch builds the viewport's tiles before its first frame and the rows past them after it, as every landing does.
|
|
133
|
+
readonly property int cacheFull: root.cellHeightPx * GridGeometry.cacheRows
|
|
134
|
+
property int cacheSteps: 0
|
|
135
|
+
readonly property int cacheStepsMargin: 4
|
|
136
|
+
property int cacheQuiet: 0
|
|
137
|
+
// The frames a key holds growth quiet, so the key's own frame builds nothing else.
|
|
138
|
+
readonly property int cacheQuietFrames: 2
|
|
139
|
+
cacheBuffer: root.cacheSteps > root.cacheStepsMargin ? root.cacheFull : 0
|
|
140
|
+
displayMarginEnd: root.cacheSteps > root.cacheStepsMargin ? 0 : root.cacheFull * root.cacheSteps / root.cacheStepsMargin
|
|
141
|
+
function regrowCache() {
|
|
142
|
+
if (root.model.count === 0)
|
|
143
|
+
root.cacheSteps = 0
|
|
144
|
+
cacheGrow.stop()
|
|
145
|
+
if (root.model.count > 0 && root.cacheSteps <= root.cacheStepsMargin)
|
|
146
|
+
cacheGrow.start()
|
|
147
|
+
}
|
|
148
|
+
function holdCache() {
|
|
149
|
+
if (cacheGrow.running) root.cacheQuiet = root.cacheQuietFrames
|
|
150
|
+
}
|
|
151
|
+
FrameAnimation {
|
|
152
|
+
id: cacheGrow
|
|
153
|
+
running: false
|
|
154
|
+
onTriggered: {
|
|
155
|
+
if (root.cacheQuiet > 0) root.cacheQuiet -= 1
|
|
156
|
+
if (root.cacheQuiet > 0 || root.pane.listInFlight || root.moving) return
|
|
157
|
+
root.cacheSteps += 1
|
|
158
|
+
root.forceLayout()
|
|
159
|
+
if (root.cacheSteps > root.cacheStepsMargin) cacheGrow.stop()
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
boundsBehavior: Flickable.StopAtBounds
|
|
163
|
+
reuseItems: true
|
|
164
|
+
// Parked tiles for the next landing: a tile parks unparented and the landing's layout parents it again.
|
|
165
|
+
readonly property Flea.PrebuildDriver prebuild: Flea.PrebuildDriver {
|
|
166
|
+
view: root
|
|
167
|
+
model: root.model
|
|
168
|
+
pane: root.pane
|
|
169
|
+
limit: root.landingTiles
|
|
170
|
+
held: root.hiddenHeld
|
|
171
|
+
rowsPerTick: 4
|
|
172
|
+
park: function (cell) { cell.pooled = true; cell.parent = null }
|
|
173
|
+
adopt: function (cell) { cell.pooled = false; cursorMark.place(cell) }
|
|
174
|
+
}
|
|
175
|
+
// The tiles a full landing from the top lays out; the partial row warmRows bounds stays out (Qt 6.11.2 qquickgridview.cpp:507).
|
|
176
|
+
readonly property int landingTiles: {
|
|
177
|
+
var c = root.columns, h = root.cellHeight, end = root.height - root.topMargin + root.cacheFull, n = 0
|
|
178
|
+
while (c > 0 && h > 0 && n < root.model.warmRows && Math.floor(n / c) * h <= end + h * (c - n % c) / (c + 1)) n++
|
|
179
|
+
return n
|
|
180
|
+
}
|
|
181
|
+
// The one tile drawn as the cursor; a cursor move touches two delegates, not every live one.
|
|
182
|
+
Flea.CursorMark { id: cursorMark; row: root.pane.cursorIndex }
|
|
183
|
+
|
|
184
|
+
Flea.FastScrollHandler {
|
|
185
|
+
parent: root
|
|
186
|
+
flickable: root
|
|
187
|
+
ctrlWheelAction: function (wheel) { return root.zoomWheel(wheel) }
|
|
188
|
+
onWheeled: root.endLanding(false)
|
|
189
|
+
}
|
|
190
|
+
// movementStarted is the view's own drag or flick, never a positionViewAtIndex or contentY write, so the landing's moves do not end its wait.
|
|
191
|
+
onMovementStarted: root.endLanding(false)
|
|
192
|
+
|
|
193
|
+
readonly property alias scrollBar: verticalScroll
|
|
194
|
+
Flea.ViewportScrollBar {
|
|
195
|
+
id: verticalScroll
|
|
196
|
+
parent: root
|
|
197
|
+
anchors { top: parent.top; right: parent.right }
|
|
198
|
+
flickable: root
|
|
199
|
+
ctrlWheelAction: function (wheel) { return root.zoomWheel(wheel) }
|
|
200
|
+
onUserScrolled: root.endLanding(false)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
Flea.SelectionBand {
|
|
204
|
+
parent: root
|
|
205
|
+
pane: root.pane
|
|
206
|
+
flickable: root
|
|
207
|
+
columns: root.columns
|
|
208
|
+
cellWidth: root.cellWidth
|
|
209
|
+
cellHeight: root.cellHeight
|
|
210
|
+
rowAt: root.tileAt
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
Flea.FileDrag {
|
|
214
|
+
id: dragSession
|
|
215
|
+
pane: root.pane
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
delegate: Flea.GridTile {
|
|
219
|
+
id: cell
|
|
220
|
+
required property int index
|
|
221
|
+
|
|
222
|
+
// Acts on the backend row it displays; while pooled (GridTile.live) each listing read keeps its last value until onReused.
|
|
223
|
+
readonly property int listingIndex: cell.live ? Filter.at(root.pane.shown, index) : -1
|
|
224
|
+
// Filed by listing row in the view's cursor mark, which sets cursor; see ui/CursorMark.qml.
|
|
225
|
+
property int markRow: -1
|
|
226
|
+
// Built ahead of a landing past the shown rows: parked and unparented until the landing adopts it.
|
|
227
|
+
property bool prebuilt: false
|
|
228
|
+
// Where hover, a press, a tap or a drag reaches this tile: its icon box and painted caption.
|
|
229
|
+
readonly property QtObject pressMask: QtObject { function contains(point: point): bool { return root.hitsTile(cell, point) } }
|
|
230
|
+
readonly property Item rowDrag: rowDragItem
|
|
231
|
+
Component.onCompleted: if (!root.prebuild.built(cell)) cursorMark.place(cell)
|
|
232
|
+
Component.onDestruction: root.prebuild.gone(cell)
|
|
233
|
+
onParentChanged: if (cell.prebuilt && cell.parent === root.contentItem) root.prebuild.adoptCell(cell)
|
|
234
|
+
onListingIndexChanged: cursorMark.place(cell)
|
|
235
|
+
width: root.cellWidth
|
|
236
|
+
height: root.cellHeight
|
|
237
|
+
row: cell.live ? GridGeometry.heldRow(cell.rowMemo, root.heldRows, listingIndex) : cell.row
|
|
238
|
+
// One shared hover index for every tile, so no tile builds its own handler.
|
|
239
|
+
hovered: cell.live && root.hoveredIndex === cell.index
|
|
240
|
+
hoverShown: root.pane.selectionBand === null
|
|
241
|
+
selected: cell.live && root.pane.isSelected(listingIndex)
|
|
242
|
+
dropTarget: dragSession.dropIndex >= 0 && listingIndex === dragSession.dropIndex
|
|
243
|
+
dropCopying: dragSession.dragCopy
|
|
244
|
+
dropLinking: dragSession.dragLink
|
|
245
|
+
thumb: !cell.live ? cell.thumb : Thumbs.allowed(row, ViewState.thumbnailMode) ? Thumbs.fileFor(root.pane.thumbState, listingIndex) : ""
|
|
246
|
+
// List's own query and arming (ui/List.qml), so a tile marks what a row marks and builds its mark with the strip.
|
|
247
|
+
// flea-qml: a standing filter marks its own match, over Find's results too.
|
|
248
|
+
markQuery: root.pane.filterQuery.length > 0 ? root.pane.filterQuery : root.pane.searchMode.length > 0 ? root.pane.swap.answeredQuery : ""
|
|
249
|
+
markArmed: root.pane.filterTyping || root.pane.filterQuery.length > 0 || root.pane.searchMode.length > 0
|
|
250
|
+
renaming: listingIndex >= 0 && listingIndex === root.pane.renamingIndex
|
|
251
|
+
renamePane: root.pane
|
|
252
|
+
// The clipboard mark is looked up only for tiles a delegate holds.
|
|
253
|
+
clipMark: cell.live ? ClipMarks.markForRow(root.pane, cell.row ? cell.row.n : "", root.pane.clipboard) : cell.clipMark
|
|
254
|
+
onRenameCommitted: function(newName) { root.pane.commitRename(newName) }
|
|
255
|
+
onRenameAbandoned: root.pane.renamingIndex = -1
|
|
256
|
+
|
|
257
|
+
Item {
|
|
258
|
+
anchors.fill: parent
|
|
259
|
+
containmentMask: cell.pressMask
|
|
260
|
+
TapHandler {
|
|
261
|
+
id: tap
|
|
262
|
+
enabled: !cell.renaming
|
|
263
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
|
264
|
+
// A held press must still tap on release.
|
|
265
|
+
longPressThreshold: 0
|
|
266
|
+
// A press held past the interval must not fire while the button is
|
|
267
|
+
// still down on a row about to be dragged; the release still arms.
|
|
268
|
+
onPressedChanged: if (pressed) root.pane.pressSlowClick()
|
|
269
|
+
onTapped: function (eventPoint, button) {
|
|
270
|
+
if (cell.listingIndex < 0) return
|
|
271
|
+
if (button === Qt.MiddleButton)
|
|
272
|
+
Tap.tappedTab(root.pane.rowFor(cell.listingIndex), root.pane.path, root.pane)
|
|
273
|
+
else if (button === Qt.RightButton)
|
|
274
|
+
Tap.tappedMenu(cell.listingIndex, eventPoint, root.pane, root.menu)
|
|
275
|
+
else {
|
|
276
|
+
var wasSole = root.pane.slowClickWasSole(cell.listingIndex)
|
|
277
|
+
Tap.tapped(cell.listingIndex, tap.tapCount, tap.point.modifiers, root.pane)
|
|
278
|
+
// The slow click renames on the pane's timer; a double click opens through tapped() above instead.
|
|
279
|
+
if (tap.tapCount === 2) root.pane.cancelSlowClick()
|
|
280
|
+
else if (tap.tapCount === 1 && Tap.onName(cell.captionItem, cell, eventPoint.position, true)) root.pane.armSlowClick(cell.listingIndex, tap.point.modifiers, dragSession.Drag.active, wasSole)
|
|
281
|
+
else root.pane.cancelSlowClick()
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
Flea.RowDrag {
|
|
288
|
+
id: rowDragItem
|
|
289
|
+
containmentMask: cell.pressMask
|
|
290
|
+
session: dragSession
|
|
291
|
+
listingIndex: cell.listingIndex
|
|
292
|
+
row: cell.row
|
|
293
|
+
// Drops answer from the one shared area below, so no tile builds its own.
|
|
294
|
+
dropsLocal: false
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// One hover index for every tile: a per-tile HoverHandler costs a delegate each in the landing turn.
|
|
299
|
+
property int hoveredIndex: -1
|
|
300
|
+
// The tile under a view point, or -1 on a cell's bare margin or past the tiles: only the icon box and the caption hover.
|
|
301
|
+
function hoverAt(x, y) {
|
|
302
|
+
root.hoveredIndex = root.tileAt(x + root.contentX, y + root.contentY)
|
|
303
|
+
}
|
|
304
|
+
// A Flickable puts its handlers in the content item, so the probe's point is read from the scene, which a scroll leaves in place.
|
|
305
|
+
function hoverScene(scene) {
|
|
306
|
+
var p = root.mapFromItem(null, scene.x, scene.y)
|
|
307
|
+
root.hoverAt(p.x, p.y)
|
|
308
|
+
}
|
|
309
|
+
HoverHandler {
|
|
310
|
+
id: hoverProbe
|
|
311
|
+
enabled: root.visible && !root.hiddenHeld
|
|
312
|
+
onHoveredChanged: { if (!hovered) root.hoveredIndex = -1; else root.hoverScene(point.scenePosition) }
|
|
313
|
+
onPointChanged: if (hovered) root.hoverScene(point.scenePosition)
|
|
314
|
+
}
|
|
315
|
+
// One drop area for every folder tile: a per-tile DropArea costs a delegate each in the landing turn.
|
|
316
|
+
property var dropTile: null
|
|
317
|
+
property int dropListingIndex: -1
|
|
318
|
+
// What the tile under the drag answered; one refusal on entry must not end the area's events, so the area itself stays accepted and each move re-says this.
|
|
319
|
+
property bool dropAccepted: false
|
|
320
|
+
// A folder tile's drop row under a view point, or null on a file, past its icon and caption, or on bare ground; the index lookup never meets another item of the content, and a pooled or stale tile never answers.
|
|
321
|
+
function tileDropAt(x, y) {
|
|
322
|
+
var p = root.mapToItem(root.contentItem, x, y)
|
|
323
|
+
var tile = root.itemAtIndex(root.indexAt(p.x, p.y))
|
|
324
|
+
if (!tile || tile.visible === false || !tile.live || tile.listingIndex === undefined || tile.listingIndex < 0
|
|
325
|
+
|| !tile.row || tile.row.d !== true || !root.hitsTile(tile, tile.mapFromItem(root, x, y)))
|
|
326
|
+
return null
|
|
327
|
+
return tile.rowDrag
|
|
328
|
+
}
|
|
329
|
+
// The hovered tile's own exit, or its record on the session when a re-list destroyed it already.
|
|
330
|
+
function dropLeft() {
|
|
331
|
+
var tile = root.dropTile
|
|
332
|
+
root.dropTile = null
|
|
333
|
+
root.dropListingIndex = -1
|
|
334
|
+
if (tile) {
|
|
335
|
+
tile.leaveAt()
|
|
336
|
+
return
|
|
337
|
+
}
|
|
338
|
+
dragSession.dropIndex = -1
|
|
339
|
+
dragSession.dropDest = ""
|
|
340
|
+
dragSession.dropDestDev = 0
|
|
341
|
+
dragSession.leaveTarget()
|
|
342
|
+
if (dragSession.dragRows.length === 0) {
|
|
343
|
+
dragSession.dragCopy = false
|
|
344
|
+
dragSession.dragLink = false
|
|
345
|
+
}
|
|
346
|
+
dragSession.hoverEnded()
|
|
347
|
+
DragOut.keys.leave()
|
|
348
|
+
}
|
|
349
|
+
function dropEnter(next, drag) {
|
|
350
|
+
root.dropTile = next
|
|
351
|
+
root.dropListingIndex = next ? next.listingIndex : -1
|
|
352
|
+
if (next) next.enterAt(drag, next.mapFromItem(root, drag.x, drag.y))
|
|
353
|
+
else drag.accepted = false
|
|
354
|
+
root.dropAccepted = drag.accepted
|
|
355
|
+
}
|
|
356
|
+
DropArea {
|
|
357
|
+
parent: root
|
|
358
|
+
anchors.fill: parent
|
|
359
|
+
// Bare ground and file tiles are not this area's, so the pane's floor (ui/PaneWire.qml) takes them as it does under List.
|
|
360
|
+
containmentMask: QtObject { function contains(point: point): bool { return root.tileDropAt(point.x, point.y) !== null } }
|
|
361
|
+
enabled: root.pane !== null && !root.pane.listInFlight
|
|
362
|
+
keys: [DragOps.ROWS_MIME, "text/uri-list", "text/plain"]
|
|
363
|
+
onEntered: function (drag) {
|
|
364
|
+
root.dropEnter(root.tileDropAt(drag.x, drag.y), drag)
|
|
365
|
+
drag.accepted = true
|
|
366
|
+
}
|
|
367
|
+
onPositionChanged: function (drag) {
|
|
368
|
+
var next = root.tileDropAt(drag.x, drag.y)
|
|
369
|
+
if (next !== root.dropTile || (next && next.listingIndex !== root.dropListingIndex)) {
|
|
370
|
+
if (root.dropTile || root.dropListingIndex >= 0) root.dropLeft()
|
|
371
|
+
root.dropEnter(next, drag)
|
|
372
|
+
} else {
|
|
373
|
+
if (next) next.moveAt(next.mapFromItem(root, drag.x, drag.y))
|
|
374
|
+
drag.accepted = root.dropAccepted
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
onExited: root.dropLeft()
|
|
378
|
+
onDropped: function (drop) {
|
|
379
|
+
var target = root.tileDropAt(drop.x, drop.y)
|
|
380
|
+
if (target !== root.dropTile) root.dropLeft()
|
|
381
|
+
root.dropTile = null
|
|
382
|
+
root.dropListingIndex = -1
|
|
383
|
+
if (target) target.dropAt(drop)
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// One tile row of bare ground at the end, the same inset ui/List.qml keeps and for the same two
|
|
388
|
+
// reasons: a band has to start somewhere and the background menu has to be raisable at the end.
|
|
389
|
+
footer: Item {
|
|
390
|
+
width: Math.max(0, root.width - Theme.spacing.rowPaddingX)
|
|
391
|
+
height: Theme.chromeHeight
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// The space past the last tile is the directory's own, the same rule ui/List.qml carries: a
|
|
395
|
+
// tile's right click belongs to its delegate, and tileAt is what tells the two apart.
|
|
396
|
+
TapHandler {
|
|
397
|
+
acceptedButtons: Qt.RightButton
|
|
398
|
+
onTapped: function (eventPoint) {
|
|
399
|
+
if (root.tileAt(eventPoint.position.x, eventPoint.position.y) < 0)
|
|
400
|
+
root.menu.openBackground(eventPoint.scenePosition)
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// A tile is its icon box and its painted caption, or the whole editor while it renames; the rest of a cell is bare ground.
|
|
405
|
+
function hitsTile(tile, point) {
|
|
406
|
+
var icon = tile.thumbItem.mapFromItem(tile, point.x, point.y)
|
|
407
|
+
return tile.editing || (icon.x >= 0 && icon.x < tile.thumbItem.width && icon.y >= 0 && icon.y < tile.thumbItem.height)
|
|
408
|
+
|| Tap.onName(tile.captionItem, tile, point, true)
|
|
409
|
+
}
|
|
410
|
+
// The tile index under a content point, -1 on a cell's bare margin or past the last tile.
|
|
411
|
+
function tileAt(x, y) {
|
|
412
|
+
var index = root.indexAt(x, y), tile = root.itemAtIndex(index)
|
|
413
|
+
return tile && root.hitsTile(tile, Qt.point(x - tile.x, y - tile.y)) ? index : -1
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
onContentYChanged: {
|
|
417
|
+
// Hidden geometry and a restore in flight move no shared state.
|
|
418
|
+
if (!root.visible || root.hiddenHeld)
|
|
419
|
+
return
|
|
420
|
+
// A scroll under a resting pointer moves the hovered tile without a point change.
|
|
421
|
+
if (hoverProbe.hovered) root.hoverScene(hoverProbe.point.scenePosition)
|
|
422
|
+
root.menu.close()
|
|
423
|
+
// A scroll never cancels a size the user asked for (src/dirsize.js).
|
|
424
|
+
coalesce.start()
|
|
425
|
+
settle.restart()
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// The same drift check the list runs: a grid scrolled past the held window would otherwise draw
|
|
429
|
+
// empty tiles for rows the backend has never been asked for.
|
|
430
|
+
Timer {
|
|
431
|
+
id: coalesce
|
|
432
|
+
interval: root.pane.coalesceMs
|
|
433
|
+
repeat: false
|
|
434
|
+
onTriggered: root.requestIfDrifted()
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
Timer {
|
|
438
|
+
id: settle
|
|
439
|
+
interval: root.pane.settleMs
|
|
440
|
+
repeat: false
|
|
441
|
+
onTriggered: { root.requestThumbs(); root.requestDirSizes() }
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function restartSettle() { settle.restart() }
|
|
445
|
+
function restartCoalesce() { coalesce.restart() }
|
|
446
|
+
function primeSettle() { settle.interval = root.pane.firstSettleMs }
|
|
447
|
+
|
|
448
|
+
Component.onCompleted: root.takeHeld()
|
|
449
|
+
// The held rows as the tiles read them, taken once per rows write: held and rows land as two writes, and a tile bound to both would read the old rows against the new start.
|
|
450
|
+
property var heldRows: ({ start: 0, rows: [], listing: 0 })
|
|
451
|
+
function takeHeld() { if (root.pane) root.heldRows = { start: root.pane.held, rows: root.pane.rows, listing: root.pane.backend ? root.pane.backend.heldListing : 0 } }
|
|
452
|
+
// The held window in tile rows, where Pane's windowSize and buffer count list rows: the list's context in pixels, rebuilt in tiles.
|
|
453
|
+
readonly property var windowPlan: GridGeometry.windowFor(root.columns, root.visibleTileRows, root.pane.buffer, Theme.fileRowHeight, root.cellHeightPx, root.pane.refetchMargin)
|
|
454
|
+
// A cursor landing past the held rows asks for its window now, ahead of the move Pane.showRow makes right after, so the first layout binds real rows.
|
|
455
|
+
function askLanding() {
|
|
456
|
+
if (root.cursorView < 0 || root.hiddenHeld) return
|
|
457
|
+
var need = root.landingNeed()
|
|
458
|
+
// Set before the ask: a reply that beats this call lands the view in onRowsChanged.
|
|
459
|
+
root.landingWait = need !== null && root.owes()
|
|
460
|
+
root.landingStart = need === null ? -1 : need.start
|
|
461
|
+
root.askWindow(need)
|
|
462
|
+
}
|
|
463
|
+
// The window a far cursor landing owes, null for a step, a landing the held rows reach, or a view that may not ask.
|
|
464
|
+
function landingNeed() {
|
|
465
|
+
return GridGeometry.landingAsk(root.windowPlan, root.cursorView, root.visibleRange().first, root.pane.total, root.pane.held, root.pane.rows.length)
|
|
466
|
+
}
|
|
467
|
+
// Owed while the cursor's own row is not held; a landing inside the held rows has rows to bind and moves at once.
|
|
468
|
+
function owes() { return root.canAsk() && root.pane.rowFor(root.pane.cursorIndex) === null }
|
|
469
|
+
function windowOwed() { return root.owes() && root.landingNeed() !== null }
|
|
470
|
+
// The view move of a cursor landing, which Pane.showRow makes right after the ask: a far one waits for its rows, as one pass binds them where two would clear then bind.
|
|
471
|
+
function showCursor(view, context) {
|
|
472
|
+
if (!root.landingWait) root.containTile(view)
|
|
473
|
+
}
|
|
474
|
+
property bool landingWait: false
|
|
475
|
+
// Where the landing ask's window starts, so its own reply is told from another ask's.
|
|
476
|
+
property int landingStart: -1
|
|
477
|
+
// The wait ends on the ask's outcome, rows covering the cursor or not, or its refusal; a wheel, drag, flick or bar press ends it for an ask never answered.
|
|
478
|
+
function landIfReady() {
|
|
479
|
+
if (!root.landingWait || (root.windowOwed() && root.pane.held !== root.landingStart)) return
|
|
480
|
+
root.landingWait = false
|
|
481
|
+
root.revealCursor()
|
|
482
|
+
}
|
|
483
|
+
// A refused or unanswered window leaves the view where it is and frees the drift asks; the operator owns the view from here.
|
|
484
|
+
function endLanding(reveal) {
|
|
485
|
+
if (!root.landingWait) return
|
|
486
|
+
root.landingWait = false
|
|
487
|
+
if (reveal) root.revealCursor()
|
|
488
|
+
else coalesce.restart()
|
|
489
|
+
}
|
|
490
|
+
// No window while hidden, while a filter narrows rows already held, nor while a listing is out, whose windows are the directory asked for.
|
|
491
|
+
function canAsk() { return root.visible && root.pane.total !== 0 && root.pane.shown === null && !root.pane.listInFlight }
|
|
492
|
+
function askWindow(ask) {
|
|
493
|
+
if (ask !== null && root.canAsk())
|
|
494
|
+
root.pane.backend.window(ask.start, ask.count)
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function requestIfDrifted() {
|
|
498
|
+
// The view is parked on the old rows until the landing window arrives; a drift ask from there would fetch the window it left.
|
|
499
|
+
if (root.landingWait) return
|
|
500
|
+
var range = root.visibleRange()
|
|
501
|
+
root.askWindow(GridGeometry.driftAsk(root.windowPlan, range.first, range.last, root.pane.held, root.pane.rows.length, root.pane.total))
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Thumbs.viewport takes geometry and no thumb-specific state, so a tile row is handed to it the
|
|
505
|
+
// same way a text row is; the answer is then multiplied out into item indices.
|
|
506
|
+
function visibleRange() {
|
|
507
|
+
var view = Thumbs.viewport(root.viewTop(), root.cellHeightPx, root.visibleTileRows, root.tileRows)
|
|
508
|
+
return {
|
|
509
|
+
first: view.first * root.columns,
|
|
510
|
+
last: Math.min(root.pane.shownTotal - 1, (view.last + 1) * root.columns - 1)
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Returning parks the view on the shared cursor once the reset rows land.
|
|
515
|
+
property bool hiddenHeld: false
|
|
516
|
+
// Last parked contentY and loop turns spent; only a value stable across turns ends the hold.
|
|
517
|
+
property real restoreY: -1
|
|
518
|
+
property int restoreTicks: 0
|
|
519
|
+
onVisibleChanged: {
|
|
520
|
+
if (!root.visible) {
|
|
521
|
+
coalesce.stop()
|
|
522
|
+
settle.stop()
|
|
523
|
+
root.landingWait = false
|
|
524
|
+
root.hiddenHeld = true
|
|
525
|
+
root.restoreY = -1
|
|
526
|
+
root.restoreTicks = 0
|
|
527
|
+
return
|
|
528
|
+
}
|
|
529
|
+
if (root.hiddenHeld)
|
|
530
|
+
root.restoreCursorView()
|
|
531
|
+
}
|
|
532
|
+
// Count changes inside StableModel's layout, where a move refills every tile between the top and the cursor; resized follows it.
|
|
533
|
+
function modelResized() { root.landingWait = false; root.placeCursor(); root.prebuild.landed(); root.regrowCache() }
|
|
534
|
+
function placeCursor() {
|
|
535
|
+
root.currentIndex = root.cursorView
|
|
536
|
+
if (root.hiddenHeld && root.visible && root.count > 0)
|
|
537
|
+
root.restoreCursorView()
|
|
538
|
+
else root.revealCursor()
|
|
539
|
+
}
|
|
540
|
+
// A cursor reveal parks its tile in one pass, the last row's gap included, so no later turn moves a view already drawn.
|
|
541
|
+
function containTile(viewIndex) { root.positionViewAtIndex(viewIndex, GridView.Contain); root.keepLastRowClear(viewIndex) }
|
|
542
|
+
// Contain parks a last-row cursor flush on the view bottom, so keep the tiles one gap clear; a row already clear stays put.
|
|
543
|
+
function keepLastRowClear(view) {
|
|
544
|
+
if (root.contentHeight + root.topMargin + root.bottomMargin <= root.height || root.columns < 1 || view < 0) return
|
|
545
|
+
if (Math.floor(view / root.columns) !== root.tileRows - 1) return
|
|
546
|
+
root.contentY = Math.max(root.contentY, root.originY + root.contentHeight - Theme.chromeHeight + Theme.spacing.gap - root.height)
|
|
547
|
+
}
|
|
548
|
+
function restoreCursorView() {
|
|
549
|
+
// A queued turn arriving after the hold ended is stale.
|
|
550
|
+
if (!root.hiddenHeld || !root.visible)
|
|
551
|
+
return
|
|
552
|
+
if (!root.pane) {
|
|
553
|
+
root.hiddenHeld = false
|
|
554
|
+
return
|
|
555
|
+
}
|
|
556
|
+
// The model reset may still be landing; a later turn retries.
|
|
557
|
+
if (root.count === 0 && root.pane.shownTotal > 0) {
|
|
558
|
+
root.deferRestore()
|
|
559
|
+
return
|
|
560
|
+
}
|
|
561
|
+
// An empty listing and a filtered-away cursor have no view to park, so the hold ends here.
|
|
562
|
+
var view = Filter.viewOf(root.pane.shown, root.pane.cursorIndex)
|
|
563
|
+
if (root.count === 0 || view < 0) {
|
|
564
|
+
root.hiddenHeld = false
|
|
565
|
+
return
|
|
566
|
+
}
|
|
567
|
+
root.forceLayout()
|
|
568
|
+
root.positionViewAtIndex(view, GridView.Contain)
|
|
569
|
+
root.keepLastRowClear(view)
|
|
570
|
+
// Only a value stable across turns ends the hold; an optimistic position never releases it.
|
|
571
|
+
if (root.coversCursor(view) && root.contentY === root.restoreY) {
|
|
572
|
+
root.hiddenHeld = false
|
|
573
|
+
root.restoreY = -1
|
|
574
|
+
root.restoreTicks = 0
|
|
575
|
+
settle.restart()
|
|
576
|
+
return
|
|
577
|
+
}
|
|
578
|
+
root.restoreY = root.contentY
|
|
579
|
+
root.deferRestore()
|
|
580
|
+
}
|
|
581
|
+
// Restore gives up after this many turns, the bound the hidden return waits on.
|
|
582
|
+
readonly property int restoreMaxTurns: 60
|
|
583
|
+
// The parked check the return asserts through: the cursor tile overlaps the viewport.
|
|
584
|
+
function coversCursor(view) {
|
|
585
|
+
var row = Math.floor(view / Math.max(1, root.columns))
|
|
586
|
+
var top = row * root.cellHeightPx
|
|
587
|
+
return top < root.viewTop() + root.height && top + root.cellHeightPx > root.viewTop()
|
|
588
|
+
}
|
|
589
|
+
// The viewport's top in tile space: a column change re-flows the tiles and moves originY, so contentY alone reads the wrong row.
|
|
590
|
+
function viewTop() { return root.contentY - root.originY }
|
|
591
|
+
// One more loop turn, with a deadlock guard that ends the hold rather than keeping it.
|
|
592
|
+
function deferRestore() {
|
|
593
|
+
if (!root.visible)
|
|
594
|
+
return
|
|
595
|
+
if (root.restoreTicks >= root.restoreMaxTurns) {
|
|
596
|
+
root.hiddenHeld = false
|
|
597
|
+
root.restoreY = -1
|
|
598
|
+
root.restoreTicks = 0
|
|
599
|
+
settle.restart()
|
|
600
|
+
return
|
|
601
|
+
}
|
|
602
|
+
root.restoreTicks += 1
|
|
603
|
+
Qt.callLater(root.restoreCursorView)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
Connections {
|
|
607
|
+
target: root.pane.backend
|
|
608
|
+
ignoreUnknownSignals: true
|
|
609
|
+
function onFailed(where, input, message, mode) { if (where === "window") root.endLanding(true) }
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
Connections {
|
|
613
|
+
target: root.pane
|
|
614
|
+
function onRowsChanged() { root.takeHeld(); root.landIfReady() }
|
|
615
|
+
function onRenamingIndexChanged() { root.renameRetirement = null; root.queueRenameLayout() }
|
|
616
|
+
function onRenameRequestChanged() { root.queueRenameLayout() }
|
|
617
|
+
function onFilterQueryChanged() {
|
|
618
|
+
if (!root.visible) return
|
|
619
|
+
var work = Filter.cut({ask: [], drop: []}, root.pane.shown, root.pane.thumbState)
|
|
620
|
+
work.drop = work.drop.filter(function(index) { return index !== root.pane.previewIndex })
|
|
621
|
+
if (work.drop.length > 0) {
|
|
622
|
+
root.pane.backend.thumbcancel(work.drop)
|
|
623
|
+
root.thumbsApplied(work)
|
|
624
|
+
}
|
|
625
|
+
// A scroll never cancels a size the user asked for (src/dirsize.js).
|
|
626
|
+
settle.restart()
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
Connections {
|
|
631
|
+
target: ViewState
|
|
632
|
+
function onThumbnailModeChanged() { if (root.visible) settle.restart() }
|
|
633
|
+
function onThumbnailPixelsChanged() { if (root.visible) settle.restart() }
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function requestThumbs() {
|
|
637
|
+
if (!root.visible || root.pane.listInFlight || !root.pane.storageKnown)
|
|
638
|
+
return
|
|
639
|
+
var range = root.visibleRange()
|
|
640
|
+
var span = Filter.span(root.pane.shown, range.first, range.last)
|
|
641
|
+
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)
|
|
642
|
+
work.drop = work.drop.filter(function (index) { return index !== root.pane.previewIndex })
|
|
643
|
+
root.pane.backend.thumbcancel(work.drop)
|
|
644
|
+
work.cacheOnly = ExtThumbs.cacheOnly(root.pane.storageClass, ViewState.preview)
|
|
645
|
+
root.pane.backend.thumb(work.ask, work.cacheOnly)
|
|
646
|
+
root.thumbsApplied(work)
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
function requestDirSizes() {
|
|
650
|
+
// Folder sizes are measured only when the user asks: a ⚖️ click, see Pane.measureDirs.
|
|
651
|
+
return
|
|
652
|
+
if (!root.visible || root.pane.shownTotal === 0 || root.pane.listInFlight)
|
|
653
|
+
return
|
|
654
|
+
// A tile draws no size, so the grid never asks, whatever rows are visible.
|
|
655
|
+
if (!DirSizes.wantsSizes("grid", ViewState.hiddenCols, root.pane.storageClass, root.pane.storageKnown))
|
|
656
|
+
return
|
|
657
|
+
var range = root.visibleRange()
|
|
658
|
+
var span = Filter.span(root.pane.shown, range.first, range.last)
|
|
659
|
+
var ask = Filter.keep(DirSizes.plan(root.pane.dirSizeState, root.pane.rows, root.pane.held, span.first, span.last), root.pane.shown)
|
|
660
|
+
if (ask.length > 0)
|
|
661
|
+
root.pane.backend.dirsize(ask)
|
|
662
|
+
root.dirSizesApplied(ask)
|
|
663
|
+
}
|
|
664
|
+
}
|