flea-qml 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +511 -2
- package/THIRD-PARTY-NOTICES.md +29 -0
- package/demos/App.java +5 -0
- package/demos/Dockerfile +4 -0
- package/demos/Main.kt +3 -0
- package/demos/Program.cs +1 -0
- package/demos/README.md +12 -0
- package/demos/app.dart +3 -0
- package/demos/app.deb +0 -0
- package/demos/app.js +1 -0
- package/demos/backup.tar +0 -0
- package/demos/budget.xlsx +0 -0
- package/demos/build.sh +2 -0
- package/demos/bundle.zip +0 -0
- package/demos/clip.mp4 +0 -0
- package/demos/data.sqlite +0 -0
- package/demos/disk.iso +0 -0
- package/demos/engine.cpp +5 -0
- package/demos/firmware.bin +0 -0
- package/demos/flake.nix +4 -0
- package/demos/folder/inside.txt +1 -0
- package/demos/font.ttf +0 -0
- package/demos/index.html +5 -0
- package/demos/index.php +2 -0
- package/demos/init.lua +1 -0
- package/demos/letter.docx +0 -0
- package/demos/lib.rs +3 -0
- package/demos/main.c +6 -0
- package/demos/main.h +3 -0
- package/demos/math-and-diagrams.md +200 -0
- package/demos/notes.tar.gz +0 -0
- package/demos/notes.txt +3 -0
- package/demos/photo.png +0 -0
- package/demos/program +2 -0
- package/demos/report.pdf +32 -0
- package/demos/script.py +1 -0
- package/demos/server.go +7 -0
- package/demos/settings.json +4 -0
- package/demos/slides.pptx +0 -0
- package/demos/song.mp3 +0 -0
- package/demos/style.css +4 -0
- package/demos/tool.rb +1 -0
- package/demos/types.ts +2 -0
- package/docs/pele.md +23 -0
- package/docs/protocol.md +3420 -0
- package/docs/temml.md +63 -0
- package/index.js +107 -0
- package/package.json +34 -4
- package/src/archive.js +407 -0
- package/src/archiveops.js +728 -0
- package/src/backend.js +369 -0
- package/src/bulkrename.js +95 -0
- package/src/clip-host.js +76 -0
- package/src/clip.js +462 -0
- package/src/code.js +168 -0
- package/src/compare.js +74 -0
- package/src/create.js +128 -0
- package/src/dirsize.js +147 -0
- package/src/figure-svg.js +530 -0
- package/src/figure-thread.js +23 -0
- package/src/figure.js +132 -0
- package/src/find.js +55 -0
- package/src/flea.js +39 -0
- package/src/fsinfo.js +39 -0
- package/src/highlight.js +141 -0
- package/src/html.js +52 -0
- package/src/kinds.js +89 -0
- package/src/listing.js +130 -0
- package/src/markdown-html.js +317 -0
- package/src/mathml.js +186 -0
- package/src/menu.js +180 -0
- package/src/meta.js +135 -0
- package/src/office.js +810 -0
- package/src/order.js +100 -0
- package/src/peek.js +49 -0
- package/src/pele-wrapper.js +695 -0
- package/src/permissions.js +180 -0
- package/src/places.js +313 -0
- package/src/preview-language.js +10 -0
- package/src/terminal-server.js +95 -0
- package/src/terminal-shell.js +26 -0
- package/src/transfer.js +669 -0
- package/src/trash-record.js +41 -0
- package/src/trash.js +210 -0
- package/src/trashbrowse.js +327 -0
- package/src/uistate.js +393 -0
- package/src/uistore.js +168 -0
- package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
- package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
- package/src/vendor/LICENSES/MIT-katex.txt +21 -0
- package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
- package/src/vendor/LICENSES/MIT-pele.txt +40 -0
- package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
- package/src/vendor/LICENSES/MIT-temml.txt +21 -0
- package/src/vendor/pele.js +145 -0
- package/src/vendor/temml.mjs +14708 -0
- package/src/watch.js +98 -0
- package/src/wayland/client.js +109 -0
- package/src/wayland/protocol.js +55 -0
- package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
- package/src/wayland/protocols/wayland.xml +3248 -0
- package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
- package/src/wayland/resource-io.js +6 -0
- package/src/wayland/socket-discovery.js +26 -0
- package/src/wayland/transport-posix.js +120 -0
- package/src/wayland/transport-win32.js +11 -0
- package/src/wayland/transport.js +3 -0
- package/src/wayland/win32-resources.js +80 -0
- package/src/wayland/win32-wire.js +62 -0
- package/test/archive.test.js +80 -0
- package/test/bench-markdown-scroll.mjs +190 -0
- package/test/clip-host.test.js +113 -0
- package/test/code-preview.test.js +35 -0
- package/test/compare-ui-paths.test.js +24 -0
- package/test/compare.test.js +54 -0
- package/test/delete-trash.test.js +67 -0
- package/test/dirsize.test.js +138 -0
- package/test/file-ops.test.js +307 -0
- package/test/file-url.test.js +24 -0
- package/test/find-contents.test.js +161 -0
- package/test/find-input.test.js +66 -0
- package/test/fixtures/pele-parity.json +1006 -0
- package/test/highlight-launcher.test.js +35 -0
- package/test/html-preview.test.js +22 -0
- package/test/input.test.js +15 -0
- package/test/keymap.test.js +26 -0
- package/test/language-icons.test.js +36 -0
- package/test/launcher.test.js +51 -0
- package/test/manual-archive-here-ui.mjs +47 -0
- package/test/manual-code-scroll.mjs +28 -0
- package/test/manual-column-scroll.mjs +24 -0
- package/test/manual-compare-ui.mjs +20 -0
- package/test/manual-find-status.mjs +37 -0
- package/test/manual-folder-focus.mjs +63 -0
- package/test/manual-html-security.mjs +23 -0
- package/test/manual-html-ui.mjs +30 -0
- package/test/manual-syntax-preview.mjs +26 -0
- package/test/manual-terminal-lifecycle.mjs +42 -0
- package/test/manual-terminal-navigation.mjs +48 -0
- package/test/manual-terminal-ui.mjs +47 -0
- package/test/manual-trash-ui.mjs +86 -0
- package/test/markdown-diagrams.test.js +93 -0
- package/test/markdown-html.test.js +105 -0
- package/test/mathml.test.js +92 -0
- package/test/menu-transfer.test.js +57 -0
- package/test/office-preview.test.js +154 -0
- package/test/pele-parity.test.js +28 -0
- package/test/places.test.js +134 -0
- package/test/preview-keys.test.js +60 -0
- package/test/preview-language.test.js +22 -0
- package/test/status-filename.test.js +20 -0
- package/test/transfer-replace-merge.test.js +187 -0
- package/test/trash-address.test.js +23 -0
- package/test/trash-view.test.js +37 -0
- package/test/trashbrowse.test.js +135 -0
- package/ui/AboutFacts.qml +78 -0
- package/ui/ArchiveCards.qml +95 -0
- package/ui/ArchiveCompressDialog.qml +378 -0
- package/ui/ArchiveHereConfirm.qml +127 -0
- package/ui/ArchivePasswordDialog.qml +257 -0
- package/ui/Backend.qml +775 -0
- package/ui/BulkOldNames.qml +47 -0
- package/ui/BulkRenameDialog.qml +380 -0
- package/ui/CardFrame.qml +67 -0
- package/ui/CardScroll.qml +79 -0
- package/ui/CheckBox.qml +73 -0
- package/ui/ChromeBar.qml +360 -0
- package/ui/ChromeButton.qml +131 -0
- package/ui/ChromeModes.qml +43 -0
- package/ui/CodeLines.qml +256 -0
- package/ui/CodeRefusal.qml +52 -0
- package/ui/CollideConfirm.qml +147 -0
- package/ui/CollideHost.qml +167 -0
- package/ui/ColumnPane.qml +525 -0
- package/ui/ColumnRow.qml +380 -0
- package/ui/ColumnsArea.qml +594 -0
- package/ui/ColumnsLanding.qml +147 -0
- package/ui/CompareView.qml +321 -0
- package/ui/ContextMenu.qml +743 -0
- package/ui/ConvertDialog.qml +456 -0
- package/ui/CountedWorker.qml +7 -0
- package/ui/Crumb.qml +64 -0
- package/ui/CrumbDrop.qml +25 -0
- package/ui/CsvTable.qml +394 -0
- package/ui/CursorMark.qml +41 -0
- package/ui/DefaultClaim.qml +130 -0
- package/ui/DeviceLock.qml +47 -0
- package/ui/DeviceMounts.qml +540 -0
- package/ui/DialogButton.qml +150 -0
- package/ui/DialogField.qml +147 -0
- package/ui/DialogHeader.qml +31 -0
- package/ui/DialogScrim.qml +20 -0
- package/ui/DialogTitle.qml +37 -0
- package/ui/Divider.qml +9 -0
- package/ui/DropInto.qml +126 -0
- package/ui/DropTarget.qml +35 -0
- package/ui/DropboxMark.qml +60 -0
- package/ui/EmptyState.qml +150 -0
- package/ui/EscapeHint.qml +11 -0
- package/ui/FactsTable.qml +54 -0
- package/ui/FastScrollHandler.qml +476 -0
- package/ui/FatNamesConfirm.qml +157 -0
- package/ui/Favourites.qml +143 -0
- package/ui/FigureService.qml +120 -0
- package/ui/FileDrag.qml +267 -0
- package/ui/FilterStrip.qml +133 -0
- package/ui/FitMetrics.qml +22 -0
- package/ui/FlashDriveRows.qml +137 -0
- package/ui/FlashHost.qml +72 -0
- package/ui/FlashImageRow.qml +104 -0
- package/ui/FlashRunner.qml +119 -0
- package/ui/FlashStepRow.qml +172 -0
- package/ui/FlashStrip.qml +38 -0
- package/ui/FlashView.qml +397 -0
- package/ui/FleaMark.qml +88 -0
- package/ui/FlyoutFade.qml +23 -0
- package/ui/FontPane.qml +170 -0
- package/ui/Glass.qml +114 -0
- package/ui/GlassTagger.qml +59 -0
- package/ui/Glyph.qml +64 -0
- package/ui/GlyphSolid.qml +22 -0
- package/ui/GridArea.qml +664 -0
- package/ui/GridTile.qml +325 -0
- package/ui/GvfsBridge.qml +164 -0
- package/ui/Header.qml +433 -0
- package/ui/HoverTimers.qml +39 -0
- package/ui/HtmlClip.qml +30 -0
- package/ui/HtmlPane.qml +63 -0
- package/ui/HyprlandMark.qml +45 -0
- package/ui/Ipc.qml +1005 -0
- package/ui/IpcControls.qml +7 -0
- package/ui/IpcMenuState.qml +48 -0
- package/ui/IpcPreviewState.qml +185 -0
- package/ui/JumpPath.qml +51 -0
- package/ui/KeymapSheet.qml +561 -0
- package/ui/KeymapSheetResult.qml +89 -0
- package/ui/KindStack.qml +40 -0
- package/ui/LangMark.qml +51 -0
- package/ui/LangMarkLoader.qml +26 -0
- package/ui/List.qml +480 -0
- package/ui/LoadingState.qml +54 -0
- package/ui/LocalSend.qml +56 -0
- package/ui/LocalSendMark.qml +73 -0
- package/ui/MarkdownBlockView.qml +311 -0
- package/ui/MarkdownBlocks.qml +35 -0
- package/ui/MarkdownFigure.qml +254 -0
- package/ui/MarkdownImages.qml +72 -0
- package/ui/MarkdownList.qml +81 -0
- package/ui/MarkdownMathsText.qml +97 -0
- package/ui/MarkdownPane.qml +83 -0
- package/ui/MarkdownPictures.qml +41 -0
- package/ui/MarkdownQuote.qml +52 -0
- package/ui/MarkdownRemote.qml +82 -0
- package/ui/MarkdownSource.qml +155 -0
- package/ui/MarkdownTable.qml +222 -0
- package/ui/MarkdownTableScroll.qml +64 -0
- package/ui/MarkdownTableWheel.qml +126 -0
- package/ui/MarkdownText.qml +87 -0
- package/ui/MarkdownWorker.js +132 -0
- package/ui/MatchText.qml +99 -0
- package/ui/MediaSession.qml +38 -0
- package/ui/MediaSound.qml +26 -0
- package/ui/MediaStrip.qml +191 -0
- package/ui/MediaTrack.qml +36 -0
- package/ui/MediaVolume.qml +54 -0
- package/ui/MenuActionDialog.qml +396 -0
- package/ui/MenuEdgeFade.qml +24 -0
- package/ui/MenuHost.qml +227 -0
- package/ui/MenuRow.qml +351 -0
- package/ui/MountListing.qml +100 -0
- package/ui/NetworkDialog.qml +435 -0
- package/ui/NetworkForm.qml +426 -0
- package/ui/NetworkMounts.qml +913 -0
- package/ui/NetworkPlaces.qml +127 -0
- package/ui/OpenWithDialog.qml +613 -0
- package/ui/Opener.qml +95 -0
- package/ui/Pane.qml +1320 -0
- package/ui/PaneMenuActions.qml +527 -0
- package/ui/PanePath.qml +90 -0
- package/ui/PaneRail.qml +268 -0
- package/ui/PaneStates.qml +88 -0
- package/ui/PaneSwap.qml +339 -0
- package/ui/PaneWire.qml +601 -0
- package/ui/ParkedWait.qml +9 -0
- package/ui/PathEntry.qml +186 -0
- package/ui/PathJump.qml +400 -0
- package/ui/PdfViewer.qml +297 -0
- package/ui/PermissionsDialog.qml +658 -0
- package/ui/PermissionsHeadings.qml +31 -0
- package/ui/PhoneMounts.qml +67 -0
- package/ui/PickerAnswers.qml +75 -0
- package/ui/PickerBox.qml +26 -0
- package/ui/PickerChrome.qml +295 -0
- package/ui/PickerFilter.qml +97 -0
- package/ui/PickerGrid.qml +308 -0
- package/ui/PickerHeader.qml +28 -0
- package/ui/PickerLifecycle.qml +27 -0
- package/ui/PickerList.qml +218 -0
- package/ui/PickerListing.qml +149 -0
- package/ui/PickerPathBar.qml +127 -0
- package/ui/PickerPlaces.qml +189 -0
- package/ui/PickerRecent.qml +92 -0
- package/ui/PickerSave.qml +101 -0
- package/ui/PickerSelection.qml +155 -0
- package/ui/PickerWindow.qml +846 -0
- package/ui/PowerSectorsReader.qml +10 -0
- package/ui/PrebuildDriver.qml +146 -0
- package/ui/Preview.qml +1005 -0
- package/ui/PreviewAnimation.qml +24 -0
- package/ui/PreviewArchive.qml +91 -0
- package/ui/PreviewColumn.qml +553 -0
- package/ui/PreviewEdge.qml +63 -0
- package/ui/PreviewFacts.qml +30 -0
- package/ui/PreviewFactsLine.qml +34 -0
- package/ui/PreviewHtml.qml +233 -0
- package/ui/PreviewImage.qml +253 -0
- package/ui/PreviewImagePan.qml +13 -0
- package/ui/PreviewImageSharp.qml +32 -0
- package/ui/PreviewLines.qml +106 -0
- package/ui/PreviewMarkdown.qml +706 -0
- package/ui/PreviewMedia.qml +250 -0
- package/ui/PreviewPdf.qml +482 -0
- package/ui/PreviewScroll.qml +201 -0
- package/ui/PreviewSwap.qml +335 -0
- package/ui/PreviewText.qml +149 -0
- package/ui/ProtocolChip.qml +18 -0
- package/ui/QuickLookArchive.qml +41 -0
- package/ui/QuickLookBar.qml +103 -0
- package/ui/QuickLookPrepare.qml +355 -0
- package/ui/QuickLookSwap.qml +10 -0
- package/ui/QuickLookWarm.qml +65 -0
- package/ui/RailDrop.qml +155 -0
- package/ui/RailHeading.qml +19 -0
- package/ui/RailPlaces.qml +38 -0
- package/ui/RailTrashRow.qml +67 -0
- package/ui/RenameField.qml +353 -0
- package/ui/RendererRetry.qml +11 -0
- package/ui/ResizeHandle.qml +52 -0
- package/ui/Reveal.qml +54 -0
- package/ui/Row.qml +476 -0
- package/ui/RowDrag.qml +213 -0
- package/ui/RowDropTarget.qml +27 -0
- package/ui/RunCard.qml +286 -0
- package/ui/Scripts.qml +65 -0
- package/ui/SearchStrip.qml +232 -0
- package/ui/SelectionBand.qml +140 -0
- package/ui/SelectionPreview.qml +370 -0
- package/ui/SettingsFavourite.qml +122 -0
- package/ui/SettingsGroup.qml +96 -0
- package/ui/SettingsHint.qml +12 -0
- package/ui/SettingsMetrics.qml +29 -0
- package/ui/SettingsPane.qml +178 -0
- package/ui/SettingsPanel.qml +547 -0
- package/ui/SettingsRail.qml +128 -0
- package/ui/SettingsRow.qml +409 -0
- package/ui/SettingsRuler.qml +85 -0
- package/ui/SettingsSegment.qml +85 -0
- package/ui/ShareBrowser.qml +113 -0
- package/ui/ShareLink.qml +67 -0
- package/ui/ShelfPins.qml +101 -0
- package/ui/Sidebar.qml +728 -0
- package/ui/SidebarRow.qml +358 -0
- package/ui/Spinner.qml +60 -0
- package/ui/StableModel.qml +89 -0
- package/ui/StateMessage.qml +84 -0
- package/ui/StatusBar.qml +512 -0
- package/ui/StatusFileName.qml +27 -0
- package/ui/TabBar.qml +673 -0
- package/ui/TabDragGeometry.qml +60 -0
- package/ui/TagMenuMark.qml +52 -0
- package/ui/TagRailSection.qml +53 -0
- package/ui/TagSlot.qml +40 -0
- package/ui/TagState.qml +150 -0
- package/ui/TagSwatch.qml +28 -0
- package/ui/Taildrop.qml +86 -0
- package/ui/TailscaleMark.qml +50 -0
- package/ui/TerminalService.qml +69 -0
- package/ui/TerminalTab.qml +48 -0
- package/ui/TerminalTabs.qml +27 -0
- package/ui/Theme.qml +460 -0
- package/ui/ThemeColors.qml +43 -0
- package/ui/TransferCard.qml +239 -0
- package/ui/TrashConfirm.qml +129 -0
- package/ui/TrashDropHandler.qml +11 -0
- package/ui/TrashHost.qml +202 -0
- package/ui/TrashMonitor.qml +30 -0
- package/ui/TrashToolbar.qml +19 -0
- package/ui/TrashView.qml +492 -0
- package/ui/UnlockDialog.qml +450 -0
- package/ui/UnlockHost.qml +206 -0
- package/ui/UpdateCheck.qml +97 -0
- package/ui/UserDirs.qml +25 -0
- package/ui/ViewState.qml +565 -0
- package/ui/ViewportScrollBar.qml +195 -0
- package/ui/ViewportScrollBars.qml +25 -0
- package/ui/WebPreview.qml +33 -0
- package/ui/WebPreviewView.qml +26 -0
- package/ui/WindowBody.qml +829 -0
- package/ui/WindowDrag.qml +35 -0
- package/ui/boot/Commons/AudioNodes.qml +50 -0
- package/ui/boot/Commons/AudioNodesModel.js +96 -0
- package/ui/boot/Commons/Border.qml +243 -0
- package/ui/boot/Commons/BorderGeometry.js +373 -0
- package/ui/boot/Commons/Color.qml +258 -0
- package/ui/boot/Commons/I18n.qml +118 -0
- package/ui/boot/Commons/InputDevices.qml +112 -0
- package/ui/boot/Commons/InputMethodState.qml +38 -0
- package/ui/boot/Commons/IpcRegistry.qml +77 -0
- package/ui/boot/Commons/Numbers.js +19 -0
- package/ui/boot/Commons/Plural.js +91 -0
- package/ui/boot/Commons/ShellIpc.qml +12 -0
- package/ui/boot/Commons/Style.qml +561 -0
- package/ui/boot/Commons/Translations.qml +100 -0
- package/ui/boot/Commons/UntypedInput.qml +152 -0
- package/ui/boot/Commons/Util.qml +188 -0
- package/ui/boot/Commons/qmldir +13 -0
- package/ui/boot/LICENSE-omarchy +20 -0
- package/ui/boot/Ui/BackgroundMedia.qml +49 -0
- package/ui/boot/Ui/BarIconButton.qml +106 -0
- package/ui/boot/Ui/BarIconContent.qml +38 -0
- package/ui/boot/Ui/BarIndicator.qml +53 -0
- package/ui/boot/Ui/BarWidget.qml +50 -0
- package/ui/boot/Ui/BorderOverlay.qml +54 -0
- package/ui/boot/Ui/BorderSurface.qml +40 -0
- package/ui/boot/Ui/Button.qml +224 -0
- package/ui/boot/Ui/ButtonGroup.qml +131 -0
- package/ui/boot/Ui/ConfirmDialog.qml +134 -0
- package/ui/boot/Ui/CursorSurface.qml +42 -0
- package/ui/boot/Ui/Dropdown.qml +245 -0
- package/ui/boot/Ui/FilterInput.qml +26 -0
- package/ui/boot/Ui/IconContentBounds.qml +141 -0
- package/ui/boot/Ui/KeyboardPanel.qml +453 -0
- package/ui/boot/Ui/MultiSelect.qml +624 -0
- package/ui/boot/Ui/NumberField.qml +86 -0
- package/ui/boot/Ui/OpticalGlyph.qml +68 -0
- package/ui/boot/Ui/OverlayWindow.qml +102 -0
- package/ui/boot/Ui/Panel.qml +60 -0
- package/ui/boot/Ui/PanelActionButton.qml +105 -0
- package/ui/boot/Ui/PanelController.qml +16 -0
- package/ui/boot/Ui/PanelHero.qml +112 -0
- package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
- package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
- package/ui/boot/Ui/PanelSeparator.qml +19 -0
- package/ui/boot/Ui/PanelSlider.qml +156 -0
- package/ui/boot/Ui/PanelToolTip.qml +50 -0
- package/ui/boot/Ui/PluginBarApi.qml +89 -0
- package/ui/boot/Ui/PointerMoveGate.qml +54 -0
- package/ui/boot/Ui/PopupCard.qml +181 -0
- package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
- package/ui/boot/Ui/SearchableDropdown.qml +354 -0
- package/ui/boot/Ui/SizedImage.qml +125 -0
- package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
- package/ui/boot/Ui/TextField.qml +58 -0
- package/ui/boot/Ui/Toggle.qml +118 -0
- package/ui/boot/Ui/ToggleSwitch.qml +115 -0
- package/ui/boot/Ui/WidgetButton.qml +172 -0
- package/ui/boot/Ui/qmldir +41 -0
- package/ui/boot/fleatab.qml +50 -0
- package/ui/boot/picker.qml +39 -0
- package/ui/boot/shell.qml +131 -0
- package/ui/boot/tabtearoff.qml +51 -0
- package/ui/js/Anchor.js +379 -0
- package/ui/js/AnchorHold.js +162 -0
- package/ui/js/Archive.js +157 -0
- package/ui/js/ArchiveCard.js +44 -0
- package/ui/js/ArchiveOps.js +44 -0
- package/ui/js/BackReturn.js +118 -0
- package/ui/js/BulkRename.js +100 -0
- package/ui/js/Buttons.js +54 -0
- package/ui/js/ChromeKeys.js +116 -0
- package/ui/js/ClipMarks.js +73 -0
- package/ui/js/ClipSelection.js +67 -0
- package/ui/js/Clipboard.js +179 -0
- package/ui/js/Cloud.js +97 -0
- package/ui/js/CodeRuns.js +72 -0
- package/ui/js/Collide.js +212 -0
- package/ui/js/ColumnFit.js +28 -0
- package/ui/js/ColumnMenu.js +111 -0
- package/ui/js/Columns.js +298 -0
- package/ui/js/ColumnsCarry.js +103 -0
- package/ui/js/Compare.js +74 -0
- package/ui/js/Contrast.js +157 -0
- package/ui/js/ControlReader.js +42 -0
- package/ui/js/Convert.js +52 -0
- package/ui/js/CopyAs.js +52 -0
- package/ui/js/Crumbs.js +178 -0
- package/ui/js/Csv.js +231 -0
- package/ui/js/Density.js +44 -0
- package/ui/js/Devices.js +440 -0
- package/ui/js/DirSizes.js +180 -0
- package/ui/js/Drag.js +360 -0
- package/ui/js/DragOut.js +166 -0
- package/ui/js/DropDev.js +52 -0
- package/ui/js/Dropbox.js +41 -0
- package/ui/js/Eject.js +217 -0
- package/ui/js/Errors.js +188 -0
- package/ui/js/ExtThumbs.js +115 -0
- package/ui/js/Facts.js +402 -0
- package/ui/js/FigureDate.js +14 -0
- package/ui/js/Filter.js +285 -0
- package/ui/js/Find.js +46 -0
- package/ui/js/Flash.js +184 -0
- package/ui/js/FlashCard.js +79 -0
- package/ui/js/FlashEndings.js +125 -0
- package/ui/js/FlashPane.js +116 -0
- package/ui/js/FleaBin.js +12 -0
- package/ui/js/Focus.js +504 -0
- package/ui/js/FolderSorts.js +108 -0
- package/ui/js/FolderViews.js +44 -0
- package/ui/js/Format.js +314 -0
- package/ui/js/Fuzzy.js +141 -0
- package/ui/js/GlassTag.js +72 -0
- package/ui/js/Grid.js +33 -0
- package/ui/js/GridGeometry.js +90 -0
- package/ui/js/GridNames.js +153 -0
- package/ui/js/GvfsBridge.js +200 -0
- package/ui/js/HostClipboard.js +29 -0
- package/ui/js/Icons.js +218 -0
- package/ui/js/Input.js +50 -0
- package/ui/js/Jump.js +200 -0
- package/ui/js/KeyName.js +64 -0
- package/ui/js/Keymap.js +401 -0
- package/ui/js/Kinds.js +164 -0
- package/ui/js/LICENSES/ISC-lucide.txt +43 -0
- package/ui/js/LangMarkPaths.js +47 -0
- package/ui/js/LangMarks.js +120 -0
- package/ui/js/Lists.js +11 -0
- package/ui/js/LocalSend.js +39 -0
- package/ui/js/LockedMenu.js +63 -0
- package/ui/js/MakeDefault.js +186 -0
- package/ui/js/MarkBox.js +7 -0
- package/ui/js/Markdown.js +119 -0
- package/ui/js/MarkdownLists.js +86 -0
- package/ui/js/MarkdownMaths.js +58 -0
- package/ui/js/MarkdownPictures.js +32 -0
- package/ui/js/MarkdownPrepared.js +139 -0
- package/ui/js/MarkdownTableFit.js +34 -0
- package/ui/js/Marks.js +148 -0
- package/ui/js/Marquee.js +96 -0
- package/ui/js/Match.js +93 -0
- package/ui/js/Material.js +109 -0
- package/ui/js/MdBlocks.js +437 -0
- package/ui/js/MdBreak.js +71 -0
- package/ui/js/MdChunks.js +70 -0
- package/ui/js/MdContainer.js +137 -0
- package/ui/js/MdDocument.js +337 -0
- package/ui/js/MdEmph.js +97 -0
- package/ui/js/MdEntity.js +108 -0
- package/ui/js/MdEntityTable.js +223 -0
- package/ui/js/MdEscape.js +59 -0
- package/ui/js/MdFront.js +37 -0
- package/ui/js/MdHold.js +32 -0
- package/ui/js/MdHtml.js +307 -0
- package/ui/js/MdHtmlBlock.js +290 -0
- package/ui/js/MdHtmlHeading.js +53 -0
- package/ui/js/MdHtmlImage.js +179 -0
- package/ui/js/MdInline.js +154 -0
- package/ui/js/MdItems.js +212 -0
- package/ui/js/MdLeaf.js +309 -0
- package/ui/js/MdLink.js +196 -0
- package/ui/js/MdMath.js +67 -0
- package/ui/js/MdParagraphs.js +138 -0
- package/ui/js/MdRefs.js +232 -0
- package/ui/js/MdResolve.js +226 -0
- package/ui/js/MdRun.js +300 -0
- package/ui/js/MdUrl.js +226 -0
- package/ui/js/Menu.js +514 -0
- package/ui/js/MenuContext.js +85 -0
- package/ui/js/MenuFit.js +13 -0
- package/ui/js/MenuRefresh.js +74 -0
- package/ui/js/MenuWheel.js +35 -0
- package/ui/js/Messages.js +186 -0
- package/ui/js/Motion.js +16 -0
- package/ui/js/Mounts.js +320 -0
- package/ui/js/MouseNav.js +13 -0
- package/ui/js/Nav.js +329 -0
- package/ui/js/NetFs.js +26 -0
- package/ui/js/OpenWith.js +83 -0
- package/ui/js/Ops.js +585 -0
- package/ui/js/Palette.js +33 -0
- package/ui/js/PathBar.js +260 -0
- package/ui/js/Permissions.js +179 -0
- package/ui/js/Phones.js +112 -0
- package/ui/js/Picker.js +353 -0
- package/ui/js/PlaceMenu.js +96 -0
- package/ui/js/Places.js +265 -0
- package/ui/js/PreviewAsk.js +21 -0
- package/ui/js/PreviewKeys.js +155 -0
- package/ui/js/PreviewSettle.js +29 -0
- package/ui/js/PreviewSwap.js +101 -0
- package/ui/js/PropertyFacts.js +144 -0
- package/ui/js/Protocols.js +296 -0
- package/ui/js/QuickLookKinds.js +27 -0
- package/ui/js/QuickLookRect.js +24 -0
- package/ui/js/RailDrop.js +51 -0
- package/ui/js/RailKeys.js +87 -0
- package/ui/js/RailMenu.js +133 -0
- package/ui/js/Recent.js +135 -0
- package/ui/js/RecentMode.js +156 -0
- package/ui/js/Reload.js +60 -0
- package/ui/js/Renderer.js +9 -0
- package/ui/js/RunFile.js +143 -0
- package/ui/js/Scripts.js +28 -0
- package/ui/js/Scroll.js +304 -0
- package/ui/js/ScrollOff.js +69 -0
- package/ui/js/Search.js +478 -0
- package/ui/js/Selection.js +97 -0
- package/ui/js/Settings.js +476 -0
- package/ui/js/SettingsAbout.js +97 -0
- package/ui/js/SettingsShelf.js +52 -0
- package/ui/js/SheetKeys.js +42 -0
- package/ui/js/SheetQuery.js +281 -0
- package/ui/js/ShelfPile.js +27 -0
- package/ui/js/SlowClick.js +53 -0
- package/ui/js/SlowOp.js +6 -0
- package/ui/js/Sort.js +134 -0
- package/ui/js/Startup.js +63 -0
- package/ui/js/StateWords.js +17 -0
- package/ui/js/Status.js +238 -0
- package/ui/js/Swap.js +166 -0
- package/ui/js/TabMove.js +39 -0
- package/ui/js/Tabs.js +751 -0
- package/ui/js/Tags.js +134 -0
- package/ui/js/Taildrop.js +128 -0
- package/ui/js/Tap.js +180 -0
- package/ui/js/TextSize.js +107 -0
- package/ui/js/Thumbs.js +158 -0
- package/ui/js/Transfer.js +172 -0
- package/ui/js/Trash.js +84 -0
- package/ui/js/TrashDates.js +47 -0
- package/ui/js/TrashDrop.js +64 -0
- package/ui/js/UiState.js +438 -0
- package/ui/js/Unlock.js +152 -0
- package/ui/js/Update.js +130 -0
- package/ui/js/UserDirs.js +56 -0
- package/ui/qmldir +230 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
import "js/Match.js" as Match
|
|
4
|
+
import "js/Picker.js" as Picker
|
|
5
|
+
import "js/Keymap.js" as Keymap
|
|
6
|
+
import "js/GridGeometry.js" as GridGeometry
|
|
7
|
+
import "js/Density.js" as Density
|
|
8
|
+
import "js/Thumbs.js" as Thumbs
|
|
9
|
+
import "js/ExtThumbs.js" as ExtThumbs
|
|
10
|
+
import "js/Sort.js" as Sort
|
|
11
|
+
|
|
12
|
+
// Issue #191 grid mode: the main window's tiles over the same rows, visible tiles only.
|
|
13
|
+
GridView {
|
|
14
|
+
id: root
|
|
15
|
+
|
|
16
|
+
property var picker: null
|
|
17
|
+
// The listing worker, which holds the rows a thumb request names; see ui/PickerListing.qml.
|
|
18
|
+
property var backend: null
|
|
19
|
+
|
|
20
|
+
// The first screen outlasts the compositor's resize, the fling debounce after that.
|
|
21
|
+
readonly property int firstSettleMs: 70
|
|
22
|
+
readonly property int settleMs: 120
|
|
23
|
+
|
|
24
|
+
// The same tile maths the main grid lays out by, so a tile here is a tile there.
|
|
25
|
+
readonly property int columns: GridGeometry.columnsFor(root.width, Theme.grid.minCellWidth,
|
|
26
|
+
ViewState.thumbnailPixels, Theme.spacing.rowPaddingX, Theme.spacing.gap, Theme.spacing.rowPaddingX)
|
|
27
|
+
readonly property int cellHeightPx: GridGeometry.cellHeightFor(ViewState.thumbnailPixels, Theme.spacing.gap,
|
|
28
|
+
Math.ceil(Theme.grid.captionHeight),
|
|
29
|
+
Density.gridPadY(Theme.spacing.rowPaddingX, ViewState.density))
|
|
30
|
+
readonly property int visibleTileRows: Math.max(1, Math.ceil(root.height / root.cellHeightPx))
|
|
31
|
+
onColumnsChanged: if (root.visible) settle.restart()
|
|
32
|
+
onVisibleTileRowsChanged: if (root.visible) settle.restart()
|
|
33
|
+
|
|
34
|
+
// Hidden builds nothing: a hidden view is not a free view, AGENTS.md rule 6.
|
|
35
|
+
model: root.visible ? root.picker.total : 0
|
|
36
|
+
clip: true
|
|
37
|
+
boundsBehavior: Flickable.StopAtBounds
|
|
38
|
+
highlightMoveDuration: 0
|
|
39
|
+
reuseItems: true
|
|
40
|
+
cacheBuffer: root.cellHeightPx * 2
|
|
41
|
+
activeFocusOnTab: true
|
|
42
|
+
Keys.onTabPressed: function(event) { root.picker.stepFocus(root, (event.modifiers & Qt.ShiftModifier) !== 0) }
|
|
43
|
+
Keys.onBacktabPressed: root.picker.stepFocus(root, true)
|
|
44
|
+
property bool firstArmed: false
|
|
45
|
+
// The previous tap path, so a rebuilt grid never sends a tile the first tap missed.
|
|
46
|
+
property string lastTapPath: ""
|
|
47
|
+
leftMargin: Theme.spacing.gap
|
|
48
|
+
topMargin: Theme.spacing.gap
|
|
49
|
+
cellWidth: GridGeometry.cellWidthFor(root.width, root.columns, Theme.spacing.gap, Theme.spacing.rowPaddingX)
|
|
50
|
+
cellHeight: root.cellHeightPx
|
|
51
|
+
Flea.FastScrollHandler { flickable: root }
|
|
52
|
+
Flea.ViewportScrollBar {
|
|
53
|
+
parent: root
|
|
54
|
+
anchors { top: parent.top; right: parent.right }
|
|
55
|
+
flickable: root
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
delegate: Item {
|
|
59
|
+
id: cell
|
|
60
|
+
required property int index
|
|
61
|
+
readonly property int listingIndex: index
|
|
62
|
+
readonly property var row: root.picker.rowFor(cell.listingIndex)
|
|
63
|
+
readonly property string rowPath: cell.row ? Picker.rowPath(root.picker.path, cell.row.n) : ""
|
|
64
|
+
// A Recent row is named by its whole path, drawn by its own leaf; see ui/PickerList.qml.
|
|
65
|
+
readonly property var shownRow: cell.row && root.picker.recent
|
|
66
|
+
? Object.assign({}, cell.row, { n: Match.base(cell.row.n) })
|
|
67
|
+
: cell.row
|
|
68
|
+
// A file request marks files and a folder request marks folders; the other kind is a way
|
|
69
|
+
// through the tree and never an answer, so it carries no box at all.
|
|
70
|
+
readonly property bool markable: root.picker.marksAllowed && cell.row !== null && Picker.directory(cell.row) === root.picker.folderMode
|
|
71
|
+
readonly property bool isMarked: cell.markable && Picker.marked(root.picker.marks, cell.rowPath)
|
|
72
|
+
|
|
73
|
+
width: root.cellWidth
|
|
74
|
+
height: root.cellHeight
|
|
75
|
+
|
|
76
|
+
Flea.GridTile {
|
|
77
|
+
anchors.fill: parent
|
|
78
|
+
row: cell.shownRow
|
|
79
|
+
cursor: cell.listingIndex === root.picker.cursorIndex
|
|
80
|
+
hovered: hover.hovered
|
|
81
|
+
selected: cell.isMarked
|
|
82
|
+
thumb: root.thumbFor(cell.listingIndex)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The board's box, one gap in from the tile's top left; the cursor tile's mark is
|
|
86
|
+
// foreground through GridTile itself, like the main grid.
|
|
87
|
+
Flea.PickerBox {
|
|
88
|
+
id: box
|
|
89
|
+
visible: cell.markable
|
|
90
|
+
x: Theme.spacing.gap
|
|
91
|
+
y: Theme.spacing.gap
|
|
92
|
+
marked: cell.isMarked
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
HoverHandler {
|
|
96
|
+
id: hover
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
TapHandler {
|
|
100
|
+
id: tap
|
|
101
|
+
acceptedButtons: Qt.LeftButton
|
|
102
|
+
// One tap moves the cursor; a same-path double tap opens, accepts or marks by mode; a box tap toggles.
|
|
103
|
+
onTapped: function (eventPoint, button) {
|
|
104
|
+
var was = root.picker.cursorIndex
|
|
105
|
+
var extending = (tap.point.modifiers & Qt.ShiftModifier) !== 0 && root.picker.marksAllowed
|
|
106
|
+
if (!extending) root.picker.endRange()
|
|
107
|
+
root.picker.cursorIndex = cell.listingIndex
|
|
108
|
+
root.forceActiveFocus()
|
|
109
|
+
var onBox = box.visible && eventPoint.position.x <= box.x + box.width + Theme.spacing.gap
|
|
110
|
+
&& eventPoint.position.y <= box.y + box.height + Theme.spacing.gap
|
|
111
|
+
var second = tap.tapCount === 2
|
|
112
|
+
var firstPath = root.lastTapPath
|
|
113
|
+
root.lastTapPath = cell.rowPath
|
|
114
|
+
if (extending)
|
|
115
|
+
root.picker.markRange(was, cell.listingIndex)
|
|
116
|
+
else if (onBox)
|
|
117
|
+
root.picker.toggleMark(cell.listingIndex)
|
|
118
|
+
else if (second && Picker.sameTap(firstPath, cell.rowPath))
|
|
119
|
+
root.picker.doubleActivate(cell.listingIndex, cell.rowPath, firstPath)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// One tile row of bare ground at the end, the same inset the main grid keeps.
|
|
125
|
+
footer: Item {
|
|
126
|
+
width: Math.max(0, root.width - Theme.spacing.rowPaddingX)
|
|
127
|
+
height: Theme.chromeHeight
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function moveCursor(delta, extending) {
|
|
131
|
+
if (root.picker.total === 0)
|
|
132
|
+
return
|
|
133
|
+
var to = Picker.gridTarget(root.picker.cursorIndex, delta, root.columns, root.picker.total)
|
|
134
|
+
var before = root.picker.cursorIndex
|
|
135
|
+
if (!extending) root.picker.endRange()
|
|
136
|
+
root.picker.cursorIndex = to
|
|
137
|
+
if (extending) root.picker.markRange(before, to)
|
|
138
|
+
root.positionViewAtIndex(to, GridView.Contain)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function jumpTo(index) {
|
|
142
|
+
if (root.picker.total === 0)
|
|
143
|
+
return
|
|
144
|
+
root.picker.endRange()
|
|
145
|
+
var to = Math.max(0, Math.min(root.picker.total - 1, index))
|
|
146
|
+
root.picker.cursorIndex = to
|
|
147
|
+
root.positionViewAtIndex(to, GridView.Contain)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function thumbFor(index) {
|
|
151
|
+
return Thumbs.allowed(root.picker.rowFor(index), ViewState.thumbnailMode)
|
|
152
|
+
? Thumbs.fileFor(root.picker.thumbState, index) : ""
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// One dispatch for every action the lookup names, so a key test pins the live path.
|
|
156
|
+
function handleAction(action, key, modifiers) {
|
|
157
|
+
if (action === "pathBar") {
|
|
158
|
+
root.firstArmed = false
|
|
159
|
+
root.picker.openPathBar()
|
|
160
|
+
return true
|
|
161
|
+
}
|
|
162
|
+
if (action === "cursorFirstArm") {
|
|
163
|
+
if (root.firstArmed) root.jumpTo(0)
|
|
164
|
+
root.firstArmed = !root.firstArmed
|
|
165
|
+
return true
|
|
166
|
+
}
|
|
167
|
+
root.firstArmed = false
|
|
168
|
+
if (key === Qt.Key_Escape) {
|
|
169
|
+
root.picker.cancel()
|
|
170
|
+
} else if (action === "cursorDown") {
|
|
171
|
+
root.moveCursor(root.columns)
|
|
172
|
+
} else if (action === "cursorUp") {
|
|
173
|
+
root.moveCursor(-root.columns)
|
|
174
|
+
} else if (action === "extendDown") {
|
|
175
|
+
root.moveCursor(root.columns, true)
|
|
176
|
+
} else if (action === "extendUp") {
|
|
177
|
+
root.moveCursor(-root.columns, true)
|
|
178
|
+
} else if (action === "selectAll") {
|
|
179
|
+
root.picker.selectAll()
|
|
180
|
+
} else if (action === "pageDown") {
|
|
181
|
+
root.jumpTo(Picker.pageTarget(root.picker.cursorIndex, root.visibleTileRows * root.columns, root.picker.total))
|
|
182
|
+
} else if (action === "pageUp") {
|
|
183
|
+
root.jumpTo(Picker.pageTarget(root.picker.cursorIndex, -root.visibleTileRows * root.columns, root.picker.total))
|
|
184
|
+
} else if (action === "cursorFirst") {
|
|
185
|
+
root.jumpTo(0)
|
|
186
|
+
} else if (action === "cursorLast") {
|
|
187
|
+
root.jumpTo(root.picker.total - 1)
|
|
188
|
+
} else if (action === "viewList") {
|
|
189
|
+
root.picker.setView("list")
|
|
190
|
+
} else if (action === "viewGrid") {
|
|
191
|
+
root.picker.setView("grid")
|
|
192
|
+
} else if (key === Qt.Key_Space && modifiers === Qt.NoModifier) {
|
|
193
|
+
root.picker.toggleMark(root.picker.cursorIndex)
|
|
194
|
+
} else if (Picker.activates(action, key)) {
|
|
195
|
+
root.picker.activate(root.picker.cursorIndex)
|
|
196
|
+
} else if (action === "parent") {
|
|
197
|
+
root.picker.goUp()
|
|
198
|
+
} else if (action === "historyBack") {
|
|
199
|
+
root.picker.goBack()
|
|
200
|
+
} else if (action === "sortNext") {
|
|
201
|
+
root.picker.requestSort(Sort.nextOrder(Picker.SORT_ORDERS, root.picker.sortBy))
|
|
202
|
+
} else if (action === "sortReverse") {
|
|
203
|
+
root.picker.requestSort(Sort.reverseOrder(root.picker.sortBy, root.picker.sortDesc))
|
|
204
|
+
} else if (action === "toggleHidden") {
|
|
205
|
+
root.picker.showHidden = !root.picker.showHidden
|
|
206
|
+
if (root.picker.path.length > 0)
|
|
207
|
+
root.picker.openWithoutHistory(root.picker.path)
|
|
208
|
+
} else {
|
|
209
|
+
return false
|
|
210
|
+
}
|
|
211
|
+
return true
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
Keys.onPressed: function (event) {
|
|
215
|
+
// Bare arrows and h/l step to visual neighbours in the grid, the main grid's own rule;
|
|
216
|
+
// the map below would read them as parent and browse-in instead.
|
|
217
|
+
if (event.modifiers === Qt.NoModifier
|
|
218
|
+
&& (event.key === Qt.Key_Left || event.key === Qt.Key_Right
|
|
219
|
+
|| event.text === "h" || event.text === "l")) {
|
|
220
|
+
var across = (event.key === Qt.Key_Left || event.text === "h") ? -1 : 1
|
|
221
|
+
event.accepted = true
|
|
222
|
+
root.firstArmed = false
|
|
223
|
+
root.moveCursor(across)
|
|
224
|
+
return
|
|
225
|
+
}
|
|
226
|
+
var action = Keymap.lookup(event.key, event.text, event.modifiers, "listing")
|
|
227
|
+
event.accepted = root.handleAction(action, event.key, event.modifiers)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// A scroll refetches the window and restarts the thumb settle for newly visible tiles.
|
|
231
|
+
// Held rows are never refetched, so without the restart no settle asks for them.
|
|
232
|
+
onContentYChanged: {
|
|
233
|
+
coalesce.restart()
|
|
234
|
+
settle.restart()
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
Timer {
|
|
238
|
+
id: coalesce
|
|
239
|
+
interval: root.picker.coalesceMs
|
|
240
|
+
onTriggered: root.requestIfDrifted()
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Settle fires counted, so a probe waits on the first run rather than a delay.
|
|
244
|
+
property int settleRuns: 0
|
|
245
|
+
// Whether a settle fire is pending, so a probe quiesces before proving a restart.
|
|
246
|
+
property alias settleRunning: settle.running
|
|
247
|
+
Timer {
|
|
248
|
+
id: settle
|
|
249
|
+
interval: root.firstSettleMs
|
|
250
|
+
onTriggered: { root.settleRuns += 1; root.requestThumbs() }
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function primeSettle() { settle.interval = root.firstSettleMs }
|
|
254
|
+
function restartSettle() { settle.restart() }
|
|
255
|
+
|
|
256
|
+
// A reshow owns its window: move to the cursor, refetch there, restart thumbs.
|
|
257
|
+
function reshow(index) {
|
|
258
|
+
root.positionViewAtIndex(index, GridView.Contain)
|
|
259
|
+
root.requestIfDrifted()
|
|
260
|
+
root.restartSettle()
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function requestIfDrifted() {
|
|
264
|
+
if (!root.visible || root.picker.backendUnavailable || root.picker.total === 0 || root.picker.pendingListings > 0)
|
|
265
|
+
return
|
|
266
|
+
var range = Picker.tileRange(root.contentY, root.cellHeightPx, root.visibleTileRows, root.columns, root.picker.total)
|
|
267
|
+
var heldEnd = root.picker.held + root.picker.rows.length
|
|
268
|
+
if (root.picker.rows.length === 0
|
|
269
|
+
|| (range.first < root.picker.held && root.picker.held > 0)
|
|
270
|
+
|| (range.last >= heldEnd && heldEnd < root.picker.total)) {
|
|
271
|
+
var start = Math.max(0, range.first - Math.floor(root.picker.windowSize * root.picker.windowLead))
|
|
272
|
+
root.backend.window(Math.floor(start), root.picker.windowSize)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Only the visible tiles, only once each, and only after the grid has stopped moving.
|
|
277
|
+
// Unknown storage holds until fsinfo names it, so the first screen never decodes as local.
|
|
278
|
+
function requestThumbs() {
|
|
279
|
+
if (!root.visible || root.picker.backendUnavailable || root.picker.total === 0
|
|
280
|
+
|| root.picker.pendingListings > 0 || root.picker.recent || !root.picker.storageKnown)
|
|
281
|
+
return
|
|
282
|
+
var range = Picker.tileRange(root.contentY, root.cellHeightPx, root.visibleTileRows, root.columns, root.picker.total)
|
|
283
|
+
var work = Thumbs.plan(root.picker.thumbState, root.picker.rows, root.picker.held,
|
|
284
|
+
range.first, range.last, ViewState.thumbnailMode)
|
|
285
|
+
root.backend.thumbcancel(work.drop)
|
|
286
|
+
// An off class still asks; the worker answers from the cache alone, see ui/js/ExtThumbs.js.
|
|
287
|
+
work.cacheOnly = ExtThumbs.cacheOnly(root.picker.storageClass, ViewState.preview)
|
|
288
|
+
root.backend.thumb(work.ask, work.cacheOnly)
|
|
289
|
+
if (work.ask.length > 0)
|
|
290
|
+
settle.interval = root.settleMs
|
|
291
|
+
root.thumbsApplied(work)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
signal thumbsApplied(var work)
|
|
295
|
+
|
|
296
|
+
Connections {
|
|
297
|
+
target: root.picker
|
|
298
|
+
function onRowsChanged() { if (root.visible) settle.restart() }
|
|
299
|
+
function onTotalChanged() { if (root.visible) { root.primeSettle(); settle.restart() } }
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
Connections {
|
|
303
|
+
target: ViewState
|
|
304
|
+
function onThumbnailModeChanged() { if (root.visible) settle.restart() }
|
|
305
|
+
function onThumbnailPixelsChanged() { if (root.visible) settle.restart() }
|
|
306
|
+
function onPreviewChanged() { if (root.visible) settle.restart() }
|
|
307
|
+
}
|
|
308
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
import "js/Picker.js" as Picker
|
|
4
|
+
import "js/Sort.js" as Sort
|
|
5
|
+
|
|
6
|
+
// Owns no sort state; the picker's sortable gates both this click and the s and S keys so they cannot differ.
|
|
7
|
+
Flea.Header {
|
|
8
|
+
id: root
|
|
9
|
+
required property var picker
|
|
10
|
+
required property var backend
|
|
11
|
+
|
|
12
|
+
hiddenCols: Picker.HIDDEN_COLS
|
|
13
|
+
compactDate: true
|
|
14
|
+
enabled: root.picker.sortable
|
|
15
|
+
// Recent is the desktop's own order, so no mark; the mark moves on the click, not the reply.
|
|
16
|
+
sortBy: root.picker.recent ? "" : root.backend.sortBy
|
|
17
|
+
sortDesc: root.backend.sortDesc
|
|
18
|
+
onSortRequested: function (key) {
|
|
19
|
+
root.picker.requestSort(Sort.columnOrder(Picker.SORT_ORDERS, root.backend.sortBy, root.backend.sortDesc, key))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// What tests/picker-native.py clicks, in the shape every other chooser control reports.
|
|
23
|
+
function controls() {
|
|
24
|
+
return [["Sort by Name", "name"], ["Sort by Size", "size"], ["Sort by Modified", "date"]].map(function (entry) {
|
|
25
|
+
return root.picker.control(entry[0], root.cell(entry[1]), root.enabled)
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
|
|
3
|
+
// Called only after the portal reply has been saved (or the save has failed). Both processes are
|
|
4
|
+
// owned by this chooser; neither can write selected files, so a stalled read needs no write drain.
|
|
5
|
+
Item {
|
|
6
|
+
id: root
|
|
7
|
+
required property var checks
|
|
8
|
+
required property var listing
|
|
9
|
+
signal stopped()
|
|
10
|
+
property bool checksStopped: false
|
|
11
|
+
property bool listingStopped: false
|
|
12
|
+
property bool finished: false
|
|
13
|
+
function quit() { listing.quit(); checks.quit() }
|
|
14
|
+
function finish() {
|
|
15
|
+
if (finished || !checksStopped || !listingStopped) return
|
|
16
|
+
finished = true
|
|
17
|
+
stopped()
|
|
18
|
+
}
|
|
19
|
+
Connections {
|
|
20
|
+
target: root.checks
|
|
21
|
+
function onQuitReady() { root.checksStopped = true; root.finish() }
|
|
22
|
+
}
|
|
23
|
+
Connections {
|
|
24
|
+
target: root.listing
|
|
25
|
+
function onQuitReady() { root.listingStopped = true; root.finish() }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Match.js" as Match
|
|
5
|
+
import "js/Picker.js" as Picker
|
|
6
|
+
import "js/Keymap.js" as Keymap
|
|
7
|
+
import "js/MarkBox.js" as MarkBox
|
|
8
|
+
import "js/Scroll.js" as Scroll
|
|
9
|
+
import "js/Sort.js" as Sort
|
|
10
|
+
|
|
11
|
+
// The picker's listing: ui/Row.qml drawn behind a check box, and the keys that move through it. The
|
|
12
|
+
// window's own ui/List.qml is not reused, because every line of it that is not layout is a drag, a
|
|
13
|
+
// rename, a thumbnail or a context menu, and a chooser has none of those.
|
|
14
|
+
ListView {
|
|
15
|
+
id: root
|
|
16
|
+
|
|
17
|
+
property var picker: null
|
|
18
|
+
property var backend: null
|
|
19
|
+
|
|
20
|
+
readonly property int visibleRows: Math.max(1, Math.ceil(root.height / Theme.rowHeight))
|
|
21
|
+
// PickerBox's outer size, read by the header's leading slot.
|
|
22
|
+
readonly property int checkSize: MarkBox.outer(Theme.font.bodySmall, Theme.spacing.hairline)
|
|
23
|
+
|
|
24
|
+
// Hidden builds nothing: a hidden view is not a free view, AGENTS.md rule 6.
|
|
25
|
+
model: root.visible ? root.picker.shownTotal : 0
|
|
26
|
+
clip: true
|
|
27
|
+
boundsBehavior: Flickable.StopAtBounds
|
|
28
|
+
highlightMoveDuration: 0
|
|
29
|
+
reuseItems: true
|
|
30
|
+
cacheBuffer: Theme.rowHeight * 4
|
|
31
|
+
activeFocusOnTab: true
|
|
32
|
+
Keys.onTabPressed: function(event) { root.picker.stepFocus(root, (event.modifiers & Qt.ShiftModifier) !== 0) }
|
|
33
|
+
Keys.onBacktabPressed: root.picker.stepFocus(root, true)
|
|
34
|
+
property bool firstArmed: false
|
|
35
|
+
// The previous tap path, so a rebuilt list never sends a row the first tap missed.
|
|
36
|
+
property string lastTapPath: ""
|
|
37
|
+
Flea.FastScrollHandler { flickable: root }
|
|
38
|
+
Flea.ViewportScrollBar {
|
|
39
|
+
parent: root
|
|
40
|
+
anchors { top: parent.top; right: parent.right }
|
|
41
|
+
flickable: root
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
delegate: Item {
|
|
45
|
+
id: cell
|
|
46
|
+
required property int index
|
|
47
|
+
readonly property int listingIndex: index
|
|
48
|
+
readonly property var row: root.picker.rowFor(cell.listingIndex)
|
|
49
|
+
readonly property string rowPath: cell.row ? Picker.rowPath(root.picker.path, cell.row.n) : ""
|
|
50
|
+
// A Recent row is named by its whole path under the listing base, and SendPicker.html draws
|
|
51
|
+
// the file's own name; the row handed to Row.qml is the same row under that name.
|
|
52
|
+
readonly property var shownRow: cell.row && root.picker.recent
|
|
53
|
+
? Object.assign({}, cell.row, { n: Match.base(cell.row.n) })
|
|
54
|
+
: cell.row
|
|
55
|
+
// A file request marks files and a folder request marks folders; the other kind is a way
|
|
56
|
+
// through the tree and never an answer, so it carries no box at all.
|
|
57
|
+
readonly property bool markable: root.picker.marksAllowed && cell.row !== null && Picker.directory(cell.row) === root.picker.folderMode
|
|
58
|
+
readonly property bool isMarked: cell.markable && Picker.marked(root.picker.marks, cell.rowPath)
|
|
59
|
+
|
|
60
|
+
// The scroll lane stays clear, the same rule the window's own list follows.
|
|
61
|
+
width: Scroll.contentWidth(root.width, Theme.spacing.rowPaddingX)
|
|
62
|
+
height: Theme.rowHeight
|
|
63
|
+
|
|
64
|
+
// The board's marked row: the selection fill under the row's own text, never folded with the cursor rung ui/Row.qml paints.
|
|
65
|
+
Rectangle {
|
|
66
|
+
visible: cell.isMarked
|
|
67
|
+
width: root.width
|
|
68
|
+
height: parent.height
|
|
69
|
+
color: Style.selectionFill
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Flea.Row {
|
|
73
|
+
anchors.fill: parent
|
|
74
|
+
paintWidth: root.width
|
|
75
|
+
leadingSlot: root.picker.marksAllowed ? root.checkSize + Theme.spacing.gap : 0
|
|
76
|
+
compactDate: true
|
|
77
|
+
foregroundMetadata: true
|
|
78
|
+
hiddenCols: Picker.HIDDEN_COLS
|
|
79
|
+
row: cell.shownRow
|
|
80
|
+
cursor: cell.listingIndex === root.picker.cursorIndex
|
|
81
|
+
hovered: hover.hovered
|
|
82
|
+
kindNames: root.picker.kindNames
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Flea.PickerBox {
|
|
86
|
+
id: box
|
|
87
|
+
visible: cell.markable
|
|
88
|
+
anchors.left: parent.left
|
|
89
|
+
anchors.leftMargin: Theme.spacing.rowPaddingX
|
|
90
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
91
|
+
marked: cell.isMarked
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
HoverHandler {
|
|
95
|
+
id: hover
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
TapHandler {
|
|
99
|
+
id: tap
|
|
100
|
+
acceptedButtons: Qt.LeftButton
|
|
101
|
+
// One tap moves the cursor; a same-path double tap opens, accepts or marks by mode; a box tap toggles.
|
|
102
|
+
onTapped: function (eventPoint, button) {
|
|
103
|
+
var was = root.picker.cursorIndex
|
|
104
|
+
var extending = (tap.point.modifiers & Qt.ShiftModifier) !== 0 && root.picker.marksAllowed
|
|
105
|
+
if (!extending) root.picker.endRange()
|
|
106
|
+
root.picker.cursorIndex = cell.listingIndex
|
|
107
|
+
root.forceActiveFocus()
|
|
108
|
+
var onBox = box.visible && eventPoint.position.x <= box.x + box.width + Theme.spacing.gap
|
|
109
|
+
var second = tap.tapCount === 2
|
|
110
|
+
var firstPath = root.lastTapPath
|
|
111
|
+
root.lastTapPath = cell.rowPath
|
|
112
|
+
if (extending)
|
|
113
|
+
root.picker.markRange(was, cell.listingIndex)
|
|
114
|
+
else if (onBox)
|
|
115
|
+
root.picker.toggleMark(cell.listingIndex)
|
|
116
|
+
else if (second && Picker.sameTap(firstPath, cell.rowPath))
|
|
117
|
+
root.picker.doubleActivate(cell.listingIndex, cell.rowPath, firstPath)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function moveCursor(delta, extending) {
|
|
123
|
+
if (root.picker.shownTotal === 0)
|
|
124
|
+
return
|
|
125
|
+
var was = root.picker.cursorIndex
|
|
126
|
+
var to = Math.max(0, Math.min(root.picker.shownTotal - 1, was + delta))
|
|
127
|
+
if (!extending) root.picker.endRange()
|
|
128
|
+
root.picker.cursorIndex = to
|
|
129
|
+
if (extending) root.picker.markRange(was, to)
|
|
130
|
+
root.positionViewAtIndex(to, ListView.Contain)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
Keys.onPressed: function (event) {
|
|
134
|
+
var action = Keymap.lookup(event.key, event.text, event.modifiers, "listing")
|
|
135
|
+
event.accepted = true
|
|
136
|
+
if (action === "cursorFirstArm") {
|
|
137
|
+
if (root.firstArmed) root.moveCursor(-root.picker.shownTotal)
|
|
138
|
+
root.firstArmed = !root.firstArmed
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
root.firstArmed = false
|
|
142
|
+
if (event.key === Qt.Key_Escape) {
|
|
143
|
+
root.picker.cancel()
|
|
144
|
+
} else if (action === "cursorDown") {
|
|
145
|
+
root.moveCursor(1)
|
|
146
|
+
} else if (action === "cursorUp") {
|
|
147
|
+
root.moveCursor(-1)
|
|
148
|
+
} else if (action === "extendDown") {
|
|
149
|
+
root.moveCursor(1, true)
|
|
150
|
+
} else if (action === "extendUp") {
|
|
151
|
+
root.moveCursor(-1, true)
|
|
152
|
+
} else if (action === "selectAll") {
|
|
153
|
+
root.picker.selectAll()
|
|
154
|
+
} else if (action === "pageDown") {
|
|
155
|
+
root.moveCursor(root.visibleRows)
|
|
156
|
+
} else if (action === "pageUp") {
|
|
157
|
+
root.moveCursor(-root.visibleRows)
|
|
158
|
+
} else if (action === "cursorFirst") {
|
|
159
|
+
root.moveCursor(-root.picker.shownTotal)
|
|
160
|
+
} else if (action === "cursorLast") {
|
|
161
|
+
root.moveCursor(root.picker.shownTotal)
|
|
162
|
+
} else if (action === "viewList") {
|
|
163
|
+
root.picker.setView("list")
|
|
164
|
+
} else if (action === "viewGrid") {
|
|
165
|
+
root.picker.setView("grid")
|
|
166
|
+
} else if (event.key === Qt.Key_Space && event.modifiers === Qt.NoModifier) {
|
|
167
|
+
root.picker.toggleMark(root.picker.cursorIndex)
|
|
168
|
+
} else if (Picker.activates(action, event.key)) {
|
|
169
|
+
root.picker.activate(root.picker.cursorIndex)
|
|
170
|
+
} else if (action === "parent") {
|
|
171
|
+
root.picker.goUp()
|
|
172
|
+
} else if (action === "historyBack") {
|
|
173
|
+
root.picker.goBack()
|
|
174
|
+
} else if (action === "sortNext") {
|
|
175
|
+
root.picker.requestSort(Sort.nextOrder(Picker.SORT_ORDERS, root.picker.sortBy))
|
|
176
|
+
} else if (action === "sortReverse") {
|
|
177
|
+
root.picker.requestSort(Sort.reverseOrder(root.picker.sortBy, root.picker.sortDesc))
|
|
178
|
+
} else if (action === "toggleHidden") {
|
|
179
|
+
root.picker.showHidden = !root.picker.showHidden
|
|
180
|
+
if (root.picker.path.length > 0)
|
|
181
|
+
root.picker.openWithoutHistory(root.picker.path)
|
|
182
|
+
} else if (action === "pathBar") {
|
|
183
|
+
root.firstArmed = false
|
|
184
|
+
root.picker.openPathBar()
|
|
185
|
+
} else {
|
|
186
|
+
event.accepted = false
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// The listing is a window around the viewport, not the directory, so scrolling refetches. Same
|
|
191
|
+
// shape as ui/List.qml's own drift check, minus the thumbnail and directory-size planners.
|
|
192
|
+
onContentYChanged: coalesce.restart()
|
|
193
|
+
|
|
194
|
+
Timer {
|
|
195
|
+
id: coalesce
|
|
196
|
+
interval: root.picker.coalesceMs
|
|
197
|
+
onTriggered: root.requestIfDrifted()
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function requestIfDrifted() {
|
|
201
|
+
if (!root.visible || root.picker.backendUnavailable || root.picker.total === 0 || root.picker.pendingListings > 0)
|
|
202
|
+
return
|
|
203
|
+
var firstVisible = Math.floor(root.contentY / Theme.rowHeight)
|
|
204
|
+
var heldEnd = root.picker.held + root.picker.rows.length
|
|
205
|
+
if (root.picker.rows.length === 0
|
|
206
|
+
|| (firstVisible < root.picker.held && root.picker.held > 0)
|
|
207
|
+
|| (firstVisible + root.visibleRows > heldEnd && heldEnd < root.picker.total)) {
|
|
208
|
+
var start = Math.max(0, firstVisible - Math.floor(root.picker.windowSize * root.picker.windowLead))
|
|
209
|
+
root.backend.window(Math.floor(start), root.picker.windowSize)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// A reshow owns its window: move to the cursor and refetch there.
|
|
214
|
+
function reshow(index) {
|
|
215
|
+
root.positionViewAtIndex(index, ListView.Contain)
|
|
216
|
+
root.requestIfDrifted()
|
|
217
|
+
}
|
|
218
|
+
}
|