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,525 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import qs.Ui
|
|
4
|
+
import "." as Flea
|
|
5
|
+
import "js/ClipMarks.js" as ClipMarks
|
|
6
|
+
import "js/Filter.js" as Filter
|
|
7
|
+
import "js/ExtThumbs.js" as ExtThumbs
|
|
8
|
+
import "js/Scroll.js" as Scroll
|
|
9
|
+
import "js/ScrollOff.js" as ScrollOff
|
|
10
|
+
import "js/Tap.js" as Tap
|
|
11
|
+
import "js/Thumbs.js" as Thumbs
|
|
12
|
+
import "js/DirSizes.js" as DirSizes
|
|
13
|
+
import "js/Sort.js" as Sort
|
|
14
|
+
import "js/DragOut.js" as DragOut
|
|
15
|
+
import "js/DropDev.js" as DropDev
|
|
16
|
+
|
|
17
|
+
// One Miller column: a scrolling list of ColumnRows over either a peeked directory or the pane's
|
|
18
|
+
// own listing window. It owns no state; the area above it decides which row is which.
|
|
19
|
+
Item {
|
|
20
|
+
id: root
|
|
21
|
+
|
|
22
|
+
// [{n, d, i}], from a peek or from the pane's own held window.
|
|
23
|
+
property var rows: []
|
|
24
|
+
property bool loadingRows: false
|
|
25
|
+
signal loadingShown(bool shown)
|
|
26
|
+
// The row this column's cursor is on, as an absolute index; -1 when this column has no cursor.
|
|
27
|
+
property int selectedIndex: -1
|
|
28
|
+
// The one row drawn as this column's cursor; a cursor move touches two delegates, not every live one.
|
|
29
|
+
Flea.CursorMark { id: cursorMark; row: root.selectedIndex }
|
|
30
|
+
// The row named here is the one the trail passes through: lifted like a hover, never accented.
|
|
31
|
+
property string liftedName: ""
|
|
32
|
+
// The pane whose listing this column draws, or null for a peek. Only that one column has a
|
|
33
|
+
// selection to paint, and pane.isSelected reads selectionVersion, so the delegate follows it.
|
|
34
|
+
property var pane: null
|
|
35
|
+
// The window pane plus this peek column's directory, device and writability, for a drag from its rows; null on the pane's own column.
|
|
36
|
+
property var peekSource: null
|
|
37
|
+
// A column that is not the active one reads back.
|
|
38
|
+
property bool dim: false
|
|
39
|
+
// The mode of a denied peek, or -1 when this column's directory was read and its rows are true.
|
|
40
|
+
property int lockedMode: -1
|
|
41
|
+
// Whether zero rows here means empty: false while a peek is still out, because a pending peek answers zero rows too, and false for the pane's own listing, whose empty answer is the hero ui/shell.qml lays over the area.
|
|
42
|
+
property bool drawsEmpty: false
|
|
43
|
+
// True when this column draws its size cell, the same flag its rows read as showSize.
|
|
44
|
+
readonly property bool showsSize: root.pane !== null && root.pane !== undefined
|
|
45
|
+
// Parked rows the active column built ahead of the next landing; only the pane's own column has a pane, so only it prebuilds.
|
|
46
|
+
readonly property Flea.PrebuildDriver prebuild: Flea.PrebuildDriver {
|
|
47
|
+
view: root.viewport
|
|
48
|
+
model: stable
|
|
49
|
+
pane: root.pane
|
|
50
|
+
limit: stable.warmRows
|
|
51
|
+
park: function (cell) { cell.live = false; cell.visible = false }
|
|
52
|
+
adopt: function (cell) { cell.live = true; cell.visible = true; cursorMark.place(cell) }
|
|
53
|
+
}
|
|
54
|
+
// One character budget for a row without the chevron, so a column lays its names out once.
|
|
55
|
+
readonly property int nameBudgetPlain: Theme.bodyAdvance > 0 ? Math.max(0, Math.floor((Scroll.contentWidth(root.width, Theme.spacing.rowPaddingX) - Theme.spacing.rowPaddingX - Theme.iconSize - Theme.spacing.gap - Theme.spacing.rowPaddingX - (root.showsSize ? Theme.column.size + 2 * Theme.spacing.gap : 0)) / Theme.bodyAdvance)) : -1
|
|
56
|
+
// The same terms plus the chevron slot, for the chosen directory alone.
|
|
57
|
+
readonly property int nameBudgetChevron: Theme.bodyAdvance > 0 ? Math.max(0, Math.floor((Scroll.contentWidth(root.width, Theme.spacing.rowPaddingX) - Theme.spacing.rowPaddingX - Theme.iconSize - Theme.spacing.gap - Theme.spacing.rowPaddingX - Theme.font.caption - (root.showsSize ? Theme.column.size + 2 * Theme.spacing.gap : 0)) / Theme.bodyAdvance)) : -1
|
|
58
|
+
// True for every shown pane but the rightmost one; the line sits on the pane edge and changes no width.
|
|
59
|
+
property bool showDivider: false
|
|
60
|
+
// Empty short-circuits before the library, the same rule ui/List.qml carries.
|
|
61
|
+
property bool clipEmpty: ClipMarks.isEmpty(root.pane ? root.pane.clipboard : null)
|
|
62
|
+
// The short-circuit above is the only release while empty, so a cut of a large directory frees its lookup here.
|
|
63
|
+
onClipEmptyChanged: { if (root.clipEmpty) ClipMarks.release() }
|
|
64
|
+
|
|
65
|
+
// isDir says which of the two things a neighbour column's row is: a directory the pane opens as
|
|
66
|
+
// its own listing, or a file it hands to the opener. See keys.toml's [[pointer]] table.
|
|
67
|
+
signal activated(string name, bool isDir)
|
|
68
|
+
signal picked(int index, int tapCount, int modifiers, bool onName)
|
|
69
|
+
// A row press, so the columns view can stop the slow-click timer before a
|
|
70
|
+
// hold past the interval fires while the button is still down.
|
|
71
|
+
signal rowPressed(int index)
|
|
72
|
+
// The row under a right click. Only the column carrying the pane's own listing answers it, because a peeked column's rows are another directory's and every menu action addresses the pane's cursor.
|
|
73
|
+
signal menuRequested(int index, var eventPoint)
|
|
74
|
+
// A right click that landed on no row, which only the pane's own column can answer for the same
|
|
75
|
+
// reason: the background menu acts on the directory being shown and a peek is not that directory.
|
|
76
|
+
signal backgroundMenuRequested(var eventPoint)
|
|
77
|
+
// A right click on a peek's row: the peek's directory becomes the listing with this row as the cursor, and the menu opens there.
|
|
78
|
+
signal neighbourMenuRequested(string name)
|
|
79
|
+
// A right click on a peek's empty space: the peek's drawn directory becomes the listing, and the background menu opens there once its rows land.
|
|
80
|
+
signal neighbourBackgroundRequested(var eventPoint)
|
|
81
|
+
// A middle click on a directory row, in any of the three columns: ui/js/Tap.js tappedTab opens it in
|
|
82
|
+
// a new tab, and ui/ColumnsArea.qml supplies which directory this column is showing.
|
|
83
|
+
signal tabRequested(var row)
|
|
84
|
+
// The thumbnail plan for this column's viewport, computed here and written by the pane, the grid's own contract.
|
|
85
|
+
signal thumbsApplied(var work)
|
|
86
|
+
signal dirSizesApplied(var ask)
|
|
87
|
+
|
|
88
|
+
// The listArea contract ui/ColumnsArea.qml drives the middle column through; the view is private.
|
|
89
|
+
function positionViewAtIndex(index, mode) { view.positionViewAtIndex(index, mode) }
|
|
90
|
+
function itemAtIndex(index) { return view.itemAtIndex(index) }
|
|
91
|
+
function contentY() { return view.contentY }
|
|
92
|
+
// The scrolling list itself, for the anchor that puts the view back after a re-list; see ui/js/AnchorHold.js.
|
|
93
|
+
readonly property alias viewport: view
|
|
94
|
+
// A platform drag in flight, so a slow click never renames off one; ui/ColumnsArea.qml reads it.
|
|
95
|
+
readonly property bool fileDragActive: dragSession.Drag.active
|
|
96
|
+
// Cursor keeps three rows context above and below; wheel path follows viewport margin-free; click context 0 never moves list.
|
|
97
|
+
function showCursor(viewIndex, context) {
|
|
98
|
+
// The column's own rowTotal falls back to its rows with no pane, the same fallback its model uses.
|
|
99
|
+
var to = ScrollOff.cursorY(view, viewIndex, root.rowTotal, Theme.fileRowHeight, context)
|
|
100
|
+
if (to !== null)
|
|
101
|
+
view.contentY = to
|
|
102
|
+
}
|
|
103
|
+
readonly property alias scrollBar: verticalScroll
|
|
104
|
+
function restartSettle() { settle.restart() }
|
|
105
|
+
function restartCoalesce() { coalesce.restart() }
|
|
106
|
+
function primeSettle() { settle.interval = root.pane.firstSettleMs }
|
|
107
|
+
|
|
108
|
+
function visibleRange() {
|
|
109
|
+
var visibleRows = Math.max(1, Math.ceil(view.height / Theme.fileRowHeight))
|
|
110
|
+
var fallback = Thumbs.viewport(view.contentY - view.originY, Theme.fileRowHeight, visibleRows, view.count)
|
|
111
|
+
if (root.pane && root.pane.renamingIndex >= 0) {
|
|
112
|
+
var first = view.indexAt(0, view.contentY)
|
|
113
|
+
var last = view.indexAt(0, view.contentY + view.height - 1)
|
|
114
|
+
first = first < 0 ? fallback.first : first
|
|
115
|
+
return {first: first, last: last < 0 ? Math.min(view.count - 1, first + visibleRows) : last}
|
|
116
|
+
}
|
|
117
|
+
return fallback
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// The visible folder rows of a peek column that name no device, which a drag entering the pane asks the backend for.
|
|
121
|
+
function dropAsks() {
|
|
122
|
+
if (!root.visible || !root.peekSource) return []
|
|
123
|
+
var range = root.visibleRange()
|
|
124
|
+
return DropDev.folderAsks(root.rows, root.peekSource.dir, range.first, range.last, root.peekSource.pane)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// The active column uses List/Grid's integer model and refills only around its viewport.
|
|
128
|
+
function requestIfDrifted() {
|
|
129
|
+
if (root.pane === null || !root.visible || root.pane.listInFlight
|
|
130
|
+
|| root.pane.total === 0 || root.pane.shown !== null)
|
|
131
|
+
return
|
|
132
|
+
var range = root.visibleRange()
|
|
133
|
+
var heldEnd = root.pane.held + root.pane.rows.length
|
|
134
|
+
if (root.pane.rows.length === 0
|
|
135
|
+
|| (range.first - root.pane.held < root.pane.refetchMargin && root.pane.held > 0)
|
|
136
|
+
|| (heldEnd - range.last < root.pane.refetchMargin && heldEnd < root.pane.total))
|
|
137
|
+
root.pane.backend.window(Math.max(0, range.first - root.pane.buffer), root.pane.windowSize)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// The viewport's rows and no more, rule 1: the same plan the list and the grid run, over this column's own scroll position.
|
|
141
|
+
function requestThumbs() {
|
|
142
|
+
// visible is effective visibility, so the column kept alive under another view plans nothing against the shared state.
|
|
143
|
+
if (root.pane === null || !root.visible || root.pane.total === 0 || root.pane.listInFlight || !root.pane.storageKnown)
|
|
144
|
+
return
|
|
145
|
+
var range = root.visibleRange()
|
|
146
|
+
var span = Filter.span(root.pane.shown, range.first, range.last)
|
|
147
|
+
var work = Filter.cut(Thumbs.plan(root.pane.thumbState, root.pane.rows, root.pane.held,
|
|
148
|
+
span.first, span.last, ViewState.thumbnailMode), root.pane.shown, root.pane.thumbState)
|
|
149
|
+
// Only the loaded preview owns an off-viewport request; manual cursor movement asks nothing extra.
|
|
150
|
+
work.drop = work.drop.filter(function (index) { return index !== root.pane.previewIndex })
|
|
151
|
+
root.pane.backend.thumbcancel(work.drop)
|
|
152
|
+
work.cacheOnly = ExtThumbs.cacheOnly(root.pane.storageClass, ViewState.preview)
|
|
153
|
+
root.pane.backend.thumb(work.ask, work.cacheOnly)
|
|
154
|
+
if (work.ask.length > 0) settle.interval = root.pane.settleMs
|
|
155
|
+
root.thumbsApplied(work)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// The same viewport plan the list runs, over this column's own scroll position. Only the active
|
|
159
|
+
// column can ask: dirsize resolves against st.listing, which a peeked row has no index in.
|
|
160
|
+
function requestDirSizes() {
|
|
161
|
+
// Folder sizes are measured only when the user asks: a ⚖️ click, see Pane.measureDirs.
|
|
162
|
+
return
|
|
163
|
+
if (root.pane === null || !root.visible || root.pane.total === 0 || root.pane.listInFlight)
|
|
164
|
+
return
|
|
165
|
+
// The active column always draws its size, so only the class gate applies here.
|
|
166
|
+
if (!DirSizes.wantsSizes("columns", [], root.pane.storageClass, root.pane.storageKnown))
|
|
167
|
+
return
|
|
168
|
+
var range = root.visibleRange()
|
|
169
|
+
var span = Filter.span(root.pane.shown, range.first, range.last)
|
|
170
|
+
var ask = Filter.keep(DirSizes.plan(root.pane.dirSizeState, root.pane.rows, root.pane.held,
|
|
171
|
+
span.first, span.last, ViewState.thumbnailMode), root.pane.shown)
|
|
172
|
+
if (ask.length > 0) {
|
|
173
|
+
root.pane.backend.dirsize(ask)
|
|
174
|
+
settle.interval = root.pane.settleMs
|
|
175
|
+
}
|
|
176
|
+
root.dirSizesApplied(ask)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
Connections {
|
|
180
|
+
target: ViewState
|
|
181
|
+
function onThumbnailModeChanged() { if (root.visible) settle.restart() }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
Timer {
|
|
185
|
+
id: coalesce
|
|
186
|
+
interval: root.pane ? root.pane.coalesceMs : 0
|
|
187
|
+
repeat: false
|
|
188
|
+
onTriggered: root.requestIfDrifted()
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
Timer {
|
|
192
|
+
id: settle
|
|
193
|
+
interval: root.pane ? root.pane.settleMs : 120
|
|
194
|
+
repeat: false
|
|
195
|
+
onTriggered: { root.requestThumbs(); root.requestDirSizes() }
|
|
196
|
+
}
|
|
197
|
+
onRowsChanged: if (root.pane !== null) settle.restart()
|
|
198
|
+
// A column with no pane is a peek the user is not working in, so it keeps fewer unseen rows than the pane's cacheRows: 4 (ui/Pane.qml).
|
|
199
|
+
readonly property int bareCacheRows: 2
|
|
200
|
+
// No pane yet: the column's own rows are the listing, the same fallback its model uses.
|
|
201
|
+
readonly property int rowTotal: root.pane ? root.pane.shownTotal : root.rows.length
|
|
202
|
+
// The count a hidden column keeps its rows for, -1 once another reached it; the model compares counts, so no handler order builds a row.
|
|
203
|
+
property int keptTotal: -1
|
|
204
|
+
// Where a dropped column stands: the top a new count leaves, then each cursor move contained as showCursor does.
|
|
205
|
+
property real heldY: 0
|
|
206
|
+
Component.onCompleted: root.keptTotal = root.rowTotal
|
|
207
|
+
onRowTotalChanged: { root.keptTotal = root.visible ? root.rowTotal : -1; root.heldY = 0 }
|
|
208
|
+
onVisibleChanged: {
|
|
209
|
+
// A dropped column builds its rows on the frame that shows it, standing where a kept one would.
|
|
210
|
+
if (root.visible && root.keptTotal !== root.rowTotal) {
|
|
211
|
+
root.keptTotal = root.rowTotal
|
|
212
|
+
verticalScroll.settling = true
|
|
213
|
+
view.contentY = view.originY + root.heldY
|
|
214
|
+
verticalScroll.settling = false
|
|
215
|
+
}
|
|
216
|
+
if (root.visible && root.pane !== null) { coalesce.restart(); settle.restart() }
|
|
217
|
+
}
|
|
218
|
+
onHeightChanged: if (root.visible && root.pane !== null) { coalesce.restart(); settle.restart() }
|
|
219
|
+
|
|
220
|
+
Flea.FileDrag {
|
|
221
|
+
id: dragSession
|
|
222
|
+
pane: root.pane
|
|
223
|
+
peekSource: root.peekSource
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Only the active column owns this directory; neighboring peek floors cannot target its listing.
|
|
227
|
+
Flea.DropInto {
|
|
228
|
+
anchors.fill: parent
|
|
229
|
+
enabled: root.pane !== null && !root.pane.trash.opened && root.pane.searchMode === ""
|
|
230
|
+
pane: root.pane
|
|
231
|
+
dest: root.pane ? root.pane.dropPath : ""
|
|
232
|
+
refuseLoading: DragOut.refuseLoading(root.pane && root.pane.listInFlight, false, false)
|
|
233
|
+
destDev: root.pane && root.pane.backend && !root.pane.listInFlight ? root.pane.backend.dirDev : 0
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// flea-qml: every column carries the list's own titles, so the columns view (and its preview
|
|
237
|
+
// column) never loses them: Name in each, and on the pane's own column the ⚖️ that measures
|
|
238
|
+
// every folder and the Size title over the size cells. Name and Size sort as the list's do.
|
|
239
|
+
Item {
|
|
240
|
+
id: columnHeader
|
|
241
|
+
anchors.top: parent.top
|
|
242
|
+
anchors.left: parent.left
|
|
243
|
+
width: root.width
|
|
244
|
+
height: Theme.chromeHeight
|
|
245
|
+
// The rows keep the scroll lane clear; the titles over them keep it too, the fill spans it.
|
|
246
|
+
readonly property real lane: root.width - Scroll.contentWidth(root.width, Theme.spacing.rowPaddingX)
|
|
247
|
+
readonly property bool own: root.pane !== null && root.pane !== undefined
|
|
248
|
+
readonly property string sortBy: own && root.pane.backend ? root.pane.backend.sortBy : ""
|
|
249
|
+
readonly property bool sortDesc: own && root.pane.backend ? root.pane.backend.sortDesc : false
|
|
250
|
+
function title(label, key) { return columnHeader.sortBy === key ? Sort.title(label, columnHeader.sortDesc) : label }
|
|
251
|
+
Rectangle { anchors.fill: parent; color: Style.normalFill }
|
|
252
|
+
PanelSectionHeader {
|
|
253
|
+
id: columnName
|
|
254
|
+
anchors.left: parent.left
|
|
255
|
+
anchors.leftMargin: Theme.spacing.rowPaddingX + Theme.iconSize + Theme.spacing.gap
|
|
256
|
+
anchors.right: columnScale.visible ? columnScale.left : parent.right
|
|
257
|
+
anchors.rightMargin: columnScale.visible ? Theme.spacing.gap : columnHeader.lane + Theme.spacing.rowPaddingX
|
|
258
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
259
|
+
text: columnHeader.title("Name", "name")
|
|
260
|
+
elide: Text.ElideRight
|
|
261
|
+
TapHandler { enabled: columnHeader.own; onTapped: Sort.column(root.pane, "name") }
|
|
262
|
+
}
|
|
263
|
+
Text {
|
|
264
|
+
id: columnScale
|
|
265
|
+
anchors.right: columnSize.left
|
|
266
|
+
anchors.rightMargin: Theme.spacing.gap
|
|
267
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
268
|
+
visible: root.showsSize
|
|
269
|
+
text: DirSizes.UNMEASURED
|
|
270
|
+
textFormat: Text.PlainText
|
|
271
|
+
font.pixelSize: columnName.font.pixelSize
|
|
272
|
+
HoverHandler { cursorShape: Qt.PointingHandCursor }
|
|
273
|
+
TapHandler { onTapped: root.pane.measureAllDirs() }
|
|
274
|
+
}
|
|
275
|
+
PanelSectionHeader {
|
|
276
|
+
id: columnSize
|
|
277
|
+
anchors.right: parent.right
|
|
278
|
+
anchors.rightMargin: columnHeader.lane + Theme.spacing.rowPaddingX + Theme.spacing.gap
|
|
279
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
280
|
+
visible: root.showsSize
|
|
281
|
+
text: columnHeader.title("Size", "size")
|
|
282
|
+
horizontalAlignment: Text.AlignRight
|
|
283
|
+
TapHandler { onTapped: Sort.column(root.pane, "size") }
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
ListView {
|
|
288
|
+
id: view
|
|
289
|
+
// The shared pane owns selection and arrow navigation, including after rename.
|
|
290
|
+
keyNavigationEnabled: false
|
|
291
|
+
anchors.top: columnHeader.bottom
|
|
292
|
+
anchors.left: parent.left
|
|
293
|
+
anchors.right: parent.right
|
|
294
|
+
anchors.bottom: parent.bottom
|
|
295
|
+
|
|
296
|
+
model: Flea.StableModel { id: stable; view: view; total: root.visible || root.keptTotal === root.rowTotal ? root.rowTotal : 0; keptRows: true
|
|
297
|
+
warm: root.pane !== null && view.visible && root.pane.searchMode.length > 0 && root.pane.swap.searchWarm === true; warmRows: Math.floor((view.height + view.cacheBuffer) / Theme.fileRowHeight) + 1 }
|
|
298
|
+
clip: true
|
|
299
|
+
// The pane's cache rows, as ui/List.qml takes them: Qt's default 320 px builds about 12 unseen rows into every landing.
|
|
300
|
+
cacheBuffer: Theme.fileRowHeight * (root.pane ? root.pane.cacheRows : root.bareCacheRows)
|
|
301
|
+
boundsBehavior: Flickable.StopAtBounds
|
|
302
|
+
onContentYChanged: if (root.pane !== null) { coalesce.start(); settle.restart() }
|
|
303
|
+
onCountChanged: root.prebuild.landed()
|
|
304
|
+
// The error line's growth lands in contentHeight after layout, so the row is contained once then, never on a later scroll's estimate.
|
|
305
|
+
onContentHeightChanged: if (root.containRenameError) { root.containRenameError = false; view.positionViewAtIndex(root.renameViewIndex, ListView.Contain) }
|
|
306
|
+
reuseItems: true
|
|
307
|
+
|
|
308
|
+
// G7 needs an empty press target below the final row even when a long column fills the viewport.
|
|
309
|
+
footer: Item {
|
|
310
|
+
width: Scroll.contentWidth(view.width, Theme.spacing.rowPaddingX)
|
|
311
|
+
height: root.pane ? Theme.spacing.rowPaddingY : 0
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
Flea.FastScrollHandler {
|
|
315
|
+
parent: view
|
|
316
|
+
flickable: view
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
Flea.ViewportScrollBar {
|
|
320
|
+
id: verticalScroll
|
|
321
|
+
parent: view
|
|
322
|
+
anchors { top: parent.top; right: parent.right }
|
|
323
|
+
flickable: view
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
Flea.SelectionBand {
|
|
327
|
+
parent: view
|
|
328
|
+
pane: root.pane
|
|
329
|
+
flickable: view
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Empty space below the last row, the same rule ui/List.qml carries: the pane's own column answers at once while a peek navigates to its drawn directory first and opens its menu once the rows land.
|
|
333
|
+
TapHandler {
|
|
334
|
+
acceptedButtons: Qt.RightButton
|
|
335
|
+
onTapped: function (eventPoint) {
|
|
336
|
+
if (!Tap.onBackground(view, eventPoint))
|
|
337
|
+
return
|
|
338
|
+
if (root.pane !== null)
|
|
339
|
+
root.backgroundMenuRequested(eventPoint)
|
|
340
|
+
else
|
|
341
|
+
root.neighbourBackgroundRequested(eventPoint)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
delegate: Flea.ColumnRow {
|
|
346
|
+
id: cell
|
|
347
|
+
required property int index
|
|
348
|
+
// Parked while pooled (ColumnRow.live): a parked value reads itself back, so parking re-runs nothing that draws.
|
|
349
|
+
readonly property int listingIndex: !cell.live ? -1 : root.pane ? Filter.at(root.pane.shown, index) : index
|
|
350
|
+
// Filed by listing row in the column's cursor mark, which sets cursor; see ui/CursorMark.qml.
|
|
351
|
+
property int markRow: -1
|
|
352
|
+
// Built ahead of a landing past the shown rows: parked hidden until the landing adopts it.
|
|
353
|
+
property bool prebuilt: false
|
|
354
|
+
Component.onCompleted: if (!root.prebuild.built(cell)) cursorMark.place(cell)
|
|
355
|
+
Component.onDestruction: root.prebuild.gone(cell)
|
|
356
|
+
ListView.onReused: root.prebuild.adoptCell(cell)
|
|
357
|
+
onListingIndexChanged: cursorMark.place(cell)
|
|
358
|
+
// Each column keeps the scroll lane clear, the same rule ui/List.qml follows.
|
|
359
|
+
width: Scroll.contentWidth(view.width, Theme.spacing.rowPaddingX)
|
|
360
|
+
paintWidth: view.width
|
|
361
|
+
// A shrunk listing subscripts out of range under a delegate not yet released, and QML
|
|
362
|
+
// hands that back as undefined; every row reader in the tree tests against a real null.
|
|
363
|
+
row: !cell.live ? cell.row : root.pane ? root.pane.rowFor(listingIndex) : root.rows[index] !== undefined ? root.rows[index] : null
|
|
364
|
+
thumb: !cell.live ? cell.thumb : root.pane !== null && Thumbs.allowed(row, ViewState.thumbnailMode) ? root.pane.thumbFor(listingIndex) : ""
|
|
365
|
+
showSize: root.showsSize
|
|
366
|
+
dirSize: !cell.live ? cell.dirSize : root.pane !== null ? DirSizes.cellFor(root.pane.dirSizeState, listingIndex) : null
|
|
367
|
+
pane: root.pane
|
|
368
|
+
// The clipboard mark is looked up only on the pane's own column, and never while it is empty.
|
|
369
|
+
clipMark: !cell.live ? cell.clipMark : root.clipEmpty ? "" : (root.pane !== null ? ClipMarks.markForRow(root.pane, cell.row ? cell.row.n : "", root.pane.clipboard) : "")
|
|
370
|
+
// The list and the grid both mark a selection member apart from the cursor; so does this.
|
|
371
|
+
selected: cell.live && root.pane !== null && root.pane.isSelected(listingIndex)
|
|
372
|
+
dropTarget: dragSession.dropIndex >= 0 && listingIndex === dragSession.dropIndex
|
|
373
|
+
dropCopying: dragSession.dragCopy
|
|
374
|
+
dropLinking: dragSession.dragLink
|
|
375
|
+
// Read off the normalised row above: subscripting rows again hands a shrunk listing's undefined to a bool.
|
|
376
|
+
lifted: !cell.live ? cell.lifted : root.liftedName.length > 0 && row !== null && row.n === root.liftedName
|
|
377
|
+
dim: cell.live ? root.dim && !lifted : cell.dim
|
|
378
|
+
// The renaming row is always the cursor row; it hides its own name under the editor, as ui/Row.qml does.
|
|
379
|
+
renaming: cell.cursor && root.renaming
|
|
380
|
+
errorGrowth: cell.cursor && root.renameErrorHeight > 0 ? Math.max(root.renameErrorHeight, renameLoader.y + renameLoader.height - root.renameTop - Theme.fileRowHeight) : 0
|
|
381
|
+
// The column's own budget, so no row measures its own text to elide it.
|
|
382
|
+
nameBudget: cell.showChevron ? root.nameBudgetChevron : root.nameBudgetPlain
|
|
383
|
+
|
|
384
|
+
TapHandler {
|
|
385
|
+
id: tap
|
|
386
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
|
387
|
+
// A held press must still tap on release.
|
|
388
|
+
longPressThreshold: 0
|
|
389
|
+
// A press held past the interval must not fire while the button
|
|
390
|
+
// is still down; ColumnsArea stops the pane's timer from onRowPressed.
|
|
391
|
+
onPressedChanged: if (pressed) root.rowPressed(cell.listingIndex)
|
|
392
|
+
onTapped: function (eventPoint, button) {
|
|
393
|
+
if (root.pane !== null) {
|
|
394
|
+
if (cell.listingIndex < 0 || !cell.row) return
|
|
395
|
+
if (button === Qt.MiddleButton)
|
|
396
|
+
root.tabRequested(cell.row)
|
|
397
|
+
else if (button === Qt.RightButton)
|
|
398
|
+
root.menuRequested(cell.listingIndex, eventPoint)
|
|
399
|
+
else if (cell.onSizeCell(eventPoint.position)) {
|
|
400
|
+
if (tap.tapCount === 1) root.pane.measureDirs([cell.listingIndex])
|
|
401
|
+
} else
|
|
402
|
+
root.picked(cell.listingIndex, tap.tapCount, tap.point.modifiers, Tap.onName(cell.nameItem(), cell, eventPoint.position, false))
|
|
403
|
+
return
|
|
404
|
+
}
|
|
405
|
+
if (button === Qt.RightButton && root.rows[index]) {
|
|
406
|
+
root.neighbourMenuRequested(root.rows[index].n)
|
|
407
|
+
return
|
|
408
|
+
}
|
|
409
|
+
var verb = Tap.tappedColumn(root.rows[index], button, tap.tapCount)
|
|
410
|
+
if (verb === "openTab")
|
|
411
|
+
root.tabRequested(root.rows[index])
|
|
412
|
+
else if (verb.length > 0)
|
|
413
|
+
root.activated(root.rows[index].n, verb === "reveal")
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
Flea.RowDrag {
|
|
418
|
+
session: dragSession
|
|
419
|
+
listingIndex: cell.listingIndex
|
|
420
|
+
row: cell.row
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// A denied peek answers zero rows, the exact count an empty directory answers, so a locked column draws States.dc.html's Locked tile rather than reading as an empty one.
|
|
426
|
+
Flea.StateMessage {
|
|
427
|
+
anchors.fill: parent
|
|
428
|
+
listingState: root.lockedMode >= 0 ? "locked" : "ready"
|
|
429
|
+
lockedMode: root.lockedMode
|
|
430
|
+
total: root.rows.length
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// The column boundary, one per pane and never one per row; an inactive Loader builds no pane so draws none.
|
|
434
|
+
Flea.Divider {
|
|
435
|
+
anchors.right: parent.right
|
|
436
|
+
anchors.top: parent.top
|
|
437
|
+
anchors.bottom: parent.bottom
|
|
438
|
+
visible: root.showDivider
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// corner: one editor for this column, never one inside each row. A delegate binding that follows
|
|
442
|
+
// the pane's renamingIndex costs this column its keys, measured on the box: the comma that opens
|
|
443
|
+
// Settings stopped reaching ui/js/Focus.js, which case_overlays catches. An overlay follows no
|
|
444
|
+
// delegate, so the keys are safe by construction and only the active column ever draws one.
|
|
445
|
+
readonly property int renameViewIndex: root.pane !== null && root.pane.renamingIndex >= 0
|
|
446
|
+
? Filter.viewOf(root.pane.shown, root.pane.renamingIndex) : -1
|
|
447
|
+
readonly property bool renaming: root.renameViewIndex >= 0
|
|
448
|
+
// What ui/Pane.qml's renameEditor() hands ui/Ipc.qml, the shape a list delegate hands it.
|
|
449
|
+
readonly property Item editorField: renameLoader.item as Item
|
|
450
|
+
readonly property string editorText: renameLoader.item ? renameLoader.item.current : ""
|
|
451
|
+
function commitEditor() { return renameLoader.item ? renameLoader.item.commit() : false }
|
|
452
|
+
|
|
453
|
+
// The span ColumnRow draws its name in, one gap after the mark to one gap before its size cell, and nothing beyond it.
|
|
454
|
+
readonly property real renameLeft: Theme.spacing.rowPaddingX + Theme.iconSize + Theme.spacing.gap
|
|
455
|
+
// Read when the editor is built, as its name is, because rowFor answers only once the row is held.
|
|
456
|
+
function renamingFolder() {
|
|
457
|
+
var row = root.pane ? root.pane.rowFor(root.pane.renamingIndex) : null
|
|
458
|
+
return !!row && row.d === true
|
|
459
|
+
}
|
|
460
|
+
// The renaming row is the cursor row, so a folder carries its chevron, and the size cell sits left of it as ColumnRow anchors both.
|
|
461
|
+
readonly property real renameRight: Theme.spacing.rowPaddingX + (renameLoader.item !== null && root.renamingFolder() ? Theme.font.caption : 0)
|
|
462
|
+
+ (root.showsSize ? 2 * Theme.spacing.gap + Theme.column.size : 0)
|
|
463
|
+
readonly property real renameWidth: Math.max(0, Scroll.contentWidth(view.width, Theme.spacing.rowPaddingX) - root.renameLeft - root.renameRight)
|
|
464
|
+
readonly property real renameTop: root.renameViewIndex * Theme.fileRowHeight
|
|
465
|
+
// The editor owns its height, one line box; the column centres it in the row on whole pixels.
|
|
466
|
+
readonly property real renameY: root.renameTop + Math.round((Theme.fileRowHeight - (renameLoader.item ? renameLoader.item.fieldHeight : 0)) / 2)
|
|
467
|
+
readonly property real renameErrorHeight: renameLoader.item ? renameLoader.item.errorHeight : 0
|
|
468
|
+
// Set when an error line appears or changes height, and spent by the view's next contentHeight change.
|
|
469
|
+
property bool containRenameError: false
|
|
470
|
+
onRenameErrorHeightChanged: root.containRenameError = root.renameErrorHeight > 0
|
|
471
|
+
|
|
472
|
+
Loader {
|
|
473
|
+
id: renameLoader
|
|
474
|
+
parent: view.contentItem
|
|
475
|
+
// Loaded only while a rename is open: a RenameField built beside every row reports its own
|
|
476
|
+
// hide at creation, and that hide is an abandon.
|
|
477
|
+
active: root.renaming
|
|
478
|
+
// The editor leaves focus in this ListView, which eats Up and Down, so this pane's columns area takes it back in any view.
|
|
479
|
+
onActiveChanged: if (!active && view.focus && root.pane && root.pane.columnsArea) root.pane.columnsArea.focus = true
|
|
480
|
+
x: root.renameLeft
|
|
481
|
+
y: root.renameY
|
|
482
|
+
width: root.renameWidth
|
|
483
|
+
z: 2
|
|
484
|
+
sourceComponent: Flea.RenameField {
|
|
485
|
+
height: implicitHeight
|
|
486
|
+
pane: root.pane
|
|
487
|
+
errorSpan: Math.max(0, root.renameWidth + root.renameRight - Theme.spacing.rowPaddingX)
|
|
488
|
+
name: root.pane && root.pane.rowFor(root.pane.renamingIndex)
|
|
489
|
+
? String(root.pane.rowFor(root.pane.renamingIndex).n).split("/").pop() : ""
|
|
490
|
+
onCommitted: function (newName) { root.pane.commitRename(newName) }
|
|
491
|
+
onAbandoned: root.pane.renamingIndex = -1
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// For ui/Ipc.qml's columnChildEmpty readers: the tile's state and its mark's box.
|
|
496
|
+
readonly property Item emptyItem: emptyTile
|
|
497
|
+
Loader {
|
|
498
|
+
anchors.fill: parent
|
|
499
|
+
active: root.loadingRows
|
|
500
|
+
sourceComponent: Flea.LoadingState {
|
|
501
|
+
heldOff: true
|
|
502
|
+
onShownChanged: root.loadingShown(shown)
|
|
503
|
+
Component.onCompleted: if (shown) root.loadingShown(true)
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
// The same hero the list draws, per the operator: a peeked empty directory animates like the pane's own.
|
|
507
|
+
Flea.EmptyState {
|
|
508
|
+
id: emptyTile
|
|
509
|
+
anchors.fill: parent
|
|
510
|
+
visible: root.drawsEmpty && root.rows.length === 0 && root.lockedMode < 0
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Cursor can move off screen through keyboard, so column follows it with context.
|
|
514
|
+
// Selection ensures whole row (context 0); showRow spent margin, second margin would move clicked row.
|
|
515
|
+
onSelectedIndexChanged: {
|
|
516
|
+
root.prebuild.kick()
|
|
517
|
+
if (root.selectedIndex < 0)
|
|
518
|
+
return
|
|
519
|
+
var at = root.pane ? Filter.viewOf(root.pane.shown, root.selectedIndex) : root.selectedIndex
|
|
520
|
+
if (root.visible || root.keptTotal === root.rowTotal)
|
|
521
|
+
root.showCursor(at, 0)
|
|
522
|
+
else
|
|
523
|
+
root.heldY = ScrollOff.containY(at * Theme.fileRowHeight, Theme.fileRowHeight, root.heldY, view.height)
|
|
524
|
+
}
|
|
525
|
+
}
|