flea-qml 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +511 -2
- package/THIRD-PARTY-NOTICES.md +29 -0
- package/demos/App.java +5 -0
- package/demos/Dockerfile +4 -0
- package/demos/Main.kt +3 -0
- package/demos/Program.cs +1 -0
- package/demos/README.md +12 -0
- package/demos/app.dart +3 -0
- package/demos/app.deb +0 -0
- package/demos/app.js +1 -0
- package/demos/backup.tar +0 -0
- package/demos/budget.xlsx +0 -0
- package/demos/build.sh +2 -0
- package/demos/bundle.zip +0 -0
- package/demos/clip.mp4 +0 -0
- package/demos/data.sqlite +0 -0
- package/demos/disk.iso +0 -0
- package/demos/engine.cpp +5 -0
- package/demos/firmware.bin +0 -0
- package/demos/flake.nix +4 -0
- package/demos/folder/inside.txt +1 -0
- package/demos/font.ttf +0 -0
- package/demos/index.html +5 -0
- package/demos/index.php +2 -0
- package/demos/init.lua +1 -0
- package/demos/letter.docx +0 -0
- package/demos/lib.rs +3 -0
- package/demos/main.c +6 -0
- package/demos/main.h +3 -0
- package/demos/math-and-diagrams.md +200 -0
- package/demos/notes.tar.gz +0 -0
- package/demos/notes.txt +3 -0
- package/demos/photo.png +0 -0
- package/demos/program +2 -0
- package/demos/report.pdf +32 -0
- package/demos/script.py +1 -0
- package/demos/server.go +7 -0
- package/demos/settings.json +4 -0
- package/demos/slides.pptx +0 -0
- package/demos/song.mp3 +0 -0
- package/demos/style.css +4 -0
- package/demos/tool.rb +1 -0
- package/demos/types.ts +2 -0
- package/docs/pele.md +23 -0
- package/docs/protocol.md +3420 -0
- package/docs/temml.md +63 -0
- package/index.js +107 -0
- package/package.json +34 -4
- package/src/archive.js +407 -0
- package/src/archiveops.js +728 -0
- package/src/backend.js +369 -0
- package/src/bulkrename.js +95 -0
- package/src/clip-host.js +76 -0
- package/src/clip.js +462 -0
- package/src/code.js +168 -0
- package/src/compare.js +74 -0
- package/src/create.js +128 -0
- package/src/dirsize.js +147 -0
- package/src/figure-svg.js +530 -0
- package/src/figure-thread.js +23 -0
- package/src/figure.js +132 -0
- package/src/find.js +55 -0
- package/src/flea.js +39 -0
- package/src/fsinfo.js +39 -0
- package/src/highlight.js +141 -0
- package/src/html.js +52 -0
- package/src/kinds.js +89 -0
- package/src/listing.js +130 -0
- package/src/markdown-html.js +317 -0
- package/src/mathml.js +186 -0
- package/src/menu.js +180 -0
- package/src/meta.js +135 -0
- package/src/office.js +810 -0
- package/src/order.js +100 -0
- package/src/peek.js +49 -0
- package/src/pele-wrapper.js +695 -0
- package/src/permissions.js +180 -0
- package/src/places.js +313 -0
- package/src/preview-language.js +10 -0
- package/src/terminal-server.js +95 -0
- package/src/terminal-shell.js +26 -0
- package/src/transfer.js +669 -0
- package/src/trash-record.js +41 -0
- package/src/trash.js +210 -0
- package/src/trashbrowse.js +327 -0
- package/src/uistate.js +393 -0
- package/src/uistore.js +168 -0
- package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
- package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
- package/src/vendor/LICENSES/MIT-katex.txt +21 -0
- package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
- package/src/vendor/LICENSES/MIT-pele.txt +40 -0
- package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
- package/src/vendor/LICENSES/MIT-temml.txt +21 -0
- package/src/vendor/pele.js +145 -0
- package/src/vendor/temml.mjs +14708 -0
- package/src/watch.js +98 -0
- package/src/wayland/client.js +109 -0
- package/src/wayland/protocol.js +55 -0
- package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
- package/src/wayland/protocols/wayland.xml +3248 -0
- package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
- package/src/wayland/resource-io.js +6 -0
- package/src/wayland/socket-discovery.js +26 -0
- package/src/wayland/transport-posix.js +120 -0
- package/src/wayland/transport-win32.js +11 -0
- package/src/wayland/transport.js +3 -0
- package/src/wayland/win32-resources.js +80 -0
- package/src/wayland/win32-wire.js +62 -0
- package/test/archive.test.js +80 -0
- package/test/bench-markdown-scroll.mjs +190 -0
- package/test/clip-host.test.js +113 -0
- package/test/code-preview.test.js +35 -0
- package/test/compare-ui-paths.test.js +24 -0
- package/test/compare.test.js +54 -0
- package/test/delete-trash.test.js +67 -0
- package/test/dirsize.test.js +138 -0
- package/test/file-ops.test.js +307 -0
- package/test/file-url.test.js +24 -0
- package/test/find-contents.test.js +161 -0
- package/test/find-input.test.js +66 -0
- package/test/fixtures/pele-parity.json +1006 -0
- package/test/highlight-launcher.test.js +35 -0
- package/test/html-preview.test.js +22 -0
- package/test/input.test.js +15 -0
- package/test/keymap.test.js +26 -0
- package/test/language-icons.test.js +36 -0
- package/test/launcher.test.js +51 -0
- package/test/manual-archive-here-ui.mjs +47 -0
- package/test/manual-code-scroll.mjs +28 -0
- package/test/manual-column-scroll.mjs +24 -0
- package/test/manual-compare-ui.mjs +20 -0
- package/test/manual-find-status.mjs +37 -0
- package/test/manual-folder-focus.mjs +63 -0
- package/test/manual-html-security.mjs +23 -0
- package/test/manual-html-ui.mjs +30 -0
- package/test/manual-syntax-preview.mjs +26 -0
- package/test/manual-terminal-lifecycle.mjs +42 -0
- package/test/manual-terminal-navigation.mjs +48 -0
- package/test/manual-terminal-ui.mjs +47 -0
- package/test/manual-trash-ui.mjs +86 -0
- package/test/markdown-diagrams.test.js +93 -0
- package/test/markdown-html.test.js +105 -0
- package/test/mathml.test.js +92 -0
- package/test/menu-transfer.test.js +57 -0
- package/test/office-preview.test.js +154 -0
- package/test/pele-parity.test.js +28 -0
- package/test/places.test.js +134 -0
- package/test/preview-keys.test.js +60 -0
- package/test/preview-language.test.js +22 -0
- package/test/status-filename.test.js +20 -0
- package/test/transfer-replace-merge.test.js +187 -0
- package/test/trash-address.test.js +23 -0
- package/test/trash-view.test.js +37 -0
- package/test/trashbrowse.test.js +135 -0
- package/ui/AboutFacts.qml +78 -0
- package/ui/ArchiveCards.qml +95 -0
- package/ui/ArchiveCompressDialog.qml +378 -0
- package/ui/ArchiveHereConfirm.qml +127 -0
- package/ui/ArchivePasswordDialog.qml +257 -0
- package/ui/Backend.qml +775 -0
- package/ui/BulkOldNames.qml +47 -0
- package/ui/BulkRenameDialog.qml +380 -0
- package/ui/CardFrame.qml +67 -0
- package/ui/CardScroll.qml +79 -0
- package/ui/CheckBox.qml +73 -0
- package/ui/ChromeBar.qml +360 -0
- package/ui/ChromeButton.qml +131 -0
- package/ui/ChromeModes.qml +43 -0
- package/ui/CodeLines.qml +256 -0
- package/ui/CodeRefusal.qml +52 -0
- package/ui/CollideConfirm.qml +147 -0
- package/ui/CollideHost.qml +167 -0
- package/ui/ColumnPane.qml +525 -0
- package/ui/ColumnRow.qml +380 -0
- package/ui/ColumnsArea.qml +594 -0
- package/ui/ColumnsLanding.qml +147 -0
- package/ui/CompareView.qml +321 -0
- package/ui/ContextMenu.qml +743 -0
- package/ui/ConvertDialog.qml +456 -0
- package/ui/CountedWorker.qml +7 -0
- package/ui/Crumb.qml +64 -0
- package/ui/CrumbDrop.qml +25 -0
- package/ui/CsvTable.qml +394 -0
- package/ui/CursorMark.qml +41 -0
- package/ui/DefaultClaim.qml +130 -0
- package/ui/DeviceLock.qml +47 -0
- package/ui/DeviceMounts.qml +540 -0
- package/ui/DialogButton.qml +150 -0
- package/ui/DialogField.qml +147 -0
- package/ui/DialogHeader.qml +31 -0
- package/ui/DialogScrim.qml +20 -0
- package/ui/DialogTitle.qml +37 -0
- package/ui/Divider.qml +9 -0
- package/ui/DropInto.qml +126 -0
- package/ui/DropTarget.qml +35 -0
- package/ui/DropboxMark.qml +60 -0
- package/ui/EmptyState.qml +150 -0
- package/ui/EscapeHint.qml +11 -0
- package/ui/FactsTable.qml +54 -0
- package/ui/FastScrollHandler.qml +476 -0
- package/ui/FatNamesConfirm.qml +157 -0
- package/ui/Favourites.qml +143 -0
- package/ui/FigureService.qml +120 -0
- package/ui/FileDrag.qml +267 -0
- package/ui/FilterStrip.qml +133 -0
- package/ui/FitMetrics.qml +22 -0
- package/ui/FlashDriveRows.qml +137 -0
- package/ui/FlashHost.qml +72 -0
- package/ui/FlashImageRow.qml +104 -0
- package/ui/FlashRunner.qml +119 -0
- package/ui/FlashStepRow.qml +172 -0
- package/ui/FlashStrip.qml +38 -0
- package/ui/FlashView.qml +397 -0
- package/ui/FleaMark.qml +88 -0
- package/ui/FlyoutFade.qml +23 -0
- package/ui/FontPane.qml +170 -0
- package/ui/Glass.qml +114 -0
- package/ui/GlassTagger.qml +59 -0
- package/ui/Glyph.qml +64 -0
- package/ui/GlyphSolid.qml +22 -0
- package/ui/GridArea.qml +664 -0
- package/ui/GridTile.qml +325 -0
- package/ui/GvfsBridge.qml +164 -0
- package/ui/Header.qml +433 -0
- package/ui/HoverTimers.qml +39 -0
- package/ui/HtmlClip.qml +30 -0
- package/ui/HtmlPane.qml +63 -0
- package/ui/HyprlandMark.qml +45 -0
- package/ui/Ipc.qml +1005 -0
- package/ui/IpcControls.qml +7 -0
- package/ui/IpcMenuState.qml +48 -0
- package/ui/IpcPreviewState.qml +185 -0
- package/ui/JumpPath.qml +51 -0
- package/ui/KeymapSheet.qml +561 -0
- package/ui/KeymapSheetResult.qml +89 -0
- package/ui/KindStack.qml +40 -0
- package/ui/LangMark.qml +51 -0
- package/ui/LangMarkLoader.qml +26 -0
- package/ui/List.qml +480 -0
- package/ui/LoadingState.qml +54 -0
- package/ui/LocalSend.qml +56 -0
- package/ui/LocalSendMark.qml +73 -0
- package/ui/MarkdownBlockView.qml +311 -0
- package/ui/MarkdownBlocks.qml +35 -0
- package/ui/MarkdownFigure.qml +254 -0
- package/ui/MarkdownImages.qml +72 -0
- package/ui/MarkdownList.qml +81 -0
- package/ui/MarkdownMathsText.qml +97 -0
- package/ui/MarkdownPane.qml +83 -0
- package/ui/MarkdownPictures.qml +41 -0
- package/ui/MarkdownQuote.qml +52 -0
- package/ui/MarkdownRemote.qml +82 -0
- package/ui/MarkdownSource.qml +155 -0
- package/ui/MarkdownTable.qml +222 -0
- package/ui/MarkdownTableScroll.qml +64 -0
- package/ui/MarkdownTableWheel.qml +126 -0
- package/ui/MarkdownText.qml +87 -0
- package/ui/MarkdownWorker.js +132 -0
- package/ui/MatchText.qml +99 -0
- package/ui/MediaSession.qml +38 -0
- package/ui/MediaSound.qml +26 -0
- package/ui/MediaStrip.qml +191 -0
- package/ui/MediaTrack.qml +36 -0
- package/ui/MediaVolume.qml +54 -0
- package/ui/MenuActionDialog.qml +396 -0
- package/ui/MenuEdgeFade.qml +24 -0
- package/ui/MenuHost.qml +227 -0
- package/ui/MenuRow.qml +351 -0
- package/ui/MountListing.qml +100 -0
- package/ui/NetworkDialog.qml +435 -0
- package/ui/NetworkForm.qml +426 -0
- package/ui/NetworkMounts.qml +913 -0
- package/ui/NetworkPlaces.qml +127 -0
- package/ui/OpenWithDialog.qml +613 -0
- package/ui/Opener.qml +95 -0
- package/ui/Pane.qml +1320 -0
- package/ui/PaneMenuActions.qml +527 -0
- package/ui/PanePath.qml +90 -0
- package/ui/PaneRail.qml +268 -0
- package/ui/PaneStates.qml +88 -0
- package/ui/PaneSwap.qml +339 -0
- package/ui/PaneWire.qml +601 -0
- package/ui/ParkedWait.qml +9 -0
- package/ui/PathEntry.qml +186 -0
- package/ui/PathJump.qml +400 -0
- package/ui/PdfViewer.qml +297 -0
- package/ui/PermissionsDialog.qml +658 -0
- package/ui/PermissionsHeadings.qml +31 -0
- package/ui/PhoneMounts.qml +67 -0
- package/ui/PickerAnswers.qml +75 -0
- package/ui/PickerBox.qml +26 -0
- package/ui/PickerChrome.qml +295 -0
- package/ui/PickerFilter.qml +97 -0
- package/ui/PickerGrid.qml +308 -0
- package/ui/PickerHeader.qml +28 -0
- package/ui/PickerLifecycle.qml +27 -0
- package/ui/PickerList.qml +218 -0
- package/ui/PickerListing.qml +149 -0
- package/ui/PickerPathBar.qml +127 -0
- package/ui/PickerPlaces.qml +189 -0
- package/ui/PickerRecent.qml +92 -0
- package/ui/PickerSave.qml +101 -0
- package/ui/PickerSelection.qml +155 -0
- package/ui/PickerWindow.qml +846 -0
- package/ui/PowerSectorsReader.qml +10 -0
- package/ui/PrebuildDriver.qml +146 -0
- package/ui/Preview.qml +1005 -0
- package/ui/PreviewAnimation.qml +24 -0
- package/ui/PreviewArchive.qml +91 -0
- package/ui/PreviewColumn.qml +553 -0
- package/ui/PreviewEdge.qml +63 -0
- package/ui/PreviewFacts.qml +30 -0
- package/ui/PreviewFactsLine.qml +34 -0
- package/ui/PreviewHtml.qml +233 -0
- package/ui/PreviewImage.qml +253 -0
- package/ui/PreviewImagePan.qml +13 -0
- package/ui/PreviewImageSharp.qml +32 -0
- package/ui/PreviewLines.qml +106 -0
- package/ui/PreviewMarkdown.qml +706 -0
- package/ui/PreviewMedia.qml +250 -0
- package/ui/PreviewPdf.qml +482 -0
- package/ui/PreviewScroll.qml +201 -0
- package/ui/PreviewSwap.qml +335 -0
- package/ui/PreviewText.qml +149 -0
- package/ui/ProtocolChip.qml +18 -0
- package/ui/QuickLookArchive.qml +41 -0
- package/ui/QuickLookBar.qml +103 -0
- package/ui/QuickLookPrepare.qml +355 -0
- package/ui/QuickLookSwap.qml +10 -0
- package/ui/QuickLookWarm.qml +65 -0
- package/ui/RailDrop.qml +155 -0
- package/ui/RailHeading.qml +19 -0
- package/ui/RailPlaces.qml +38 -0
- package/ui/RailTrashRow.qml +67 -0
- package/ui/RenameField.qml +353 -0
- package/ui/RendererRetry.qml +11 -0
- package/ui/ResizeHandle.qml +52 -0
- package/ui/Reveal.qml +54 -0
- package/ui/Row.qml +476 -0
- package/ui/RowDrag.qml +213 -0
- package/ui/RowDropTarget.qml +27 -0
- package/ui/RunCard.qml +286 -0
- package/ui/Scripts.qml +65 -0
- package/ui/SearchStrip.qml +232 -0
- package/ui/SelectionBand.qml +140 -0
- package/ui/SelectionPreview.qml +370 -0
- package/ui/SettingsFavourite.qml +122 -0
- package/ui/SettingsGroup.qml +96 -0
- package/ui/SettingsHint.qml +12 -0
- package/ui/SettingsMetrics.qml +29 -0
- package/ui/SettingsPane.qml +178 -0
- package/ui/SettingsPanel.qml +547 -0
- package/ui/SettingsRail.qml +128 -0
- package/ui/SettingsRow.qml +409 -0
- package/ui/SettingsRuler.qml +85 -0
- package/ui/SettingsSegment.qml +85 -0
- package/ui/ShareBrowser.qml +113 -0
- package/ui/ShareLink.qml +67 -0
- package/ui/ShelfPins.qml +101 -0
- package/ui/Sidebar.qml +728 -0
- package/ui/SidebarRow.qml +358 -0
- package/ui/Spinner.qml +60 -0
- package/ui/StableModel.qml +89 -0
- package/ui/StateMessage.qml +84 -0
- package/ui/StatusBar.qml +512 -0
- package/ui/StatusFileName.qml +27 -0
- package/ui/TabBar.qml +673 -0
- package/ui/TabDragGeometry.qml +60 -0
- package/ui/TagMenuMark.qml +52 -0
- package/ui/TagRailSection.qml +53 -0
- package/ui/TagSlot.qml +40 -0
- package/ui/TagState.qml +150 -0
- package/ui/TagSwatch.qml +28 -0
- package/ui/Taildrop.qml +86 -0
- package/ui/TailscaleMark.qml +50 -0
- package/ui/TerminalService.qml +69 -0
- package/ui/TerminalTab.qml +48 -0
- package/ui/TerminalTabs.qml +27 -0
- package/ui/Theme.qml +460 -0
- package/ui/ThemeColors.qml +43 -0
- package/ui/TransferCard.qml +239 -0
- package/ui/TrashConfirm.qml +129 -0
- package/ui/TrashDropHandler.qml +11 -0
- package/ui/TrashHost.qml +202 -0
- package/ui/TrashMonitor.qml +30 -0
- package/ui/TrashToolbar.qml +19 -0
- package/ui/TrashView.qml +492 -0
- package/ui/UnlockDialog.qml +450 -0
- package/ui/UnlockHost.qml +206 -0
- package/ui/UpdateCheck.qml +97 -0
- package/ui/UserDirs.qml +25 -0
- package/ui/ViewState.qml +565 -0
- package/ui/ViewportScrollBar.qml +195 -0
- package/ui/ViewportScrollBars.qml +25 -0
- package/ui/WebPreview.qml +33 -0
- package/ui/WebPreviewView.qml +26 -0
- package/ui/WindowBody.qml +829 -0
- package/ui/WindowDrag.qml +35 -0
- package/ui/boot/Commons/AudioNodes.qml +50 -0
- package/ui/boot/Commons/AudioNodesModel.js +96 -0
- package/ui/boot/Commons/Border.qml +243 -0
- package/ui/boot/Commons/BorderGeometry.js +373 -0
- package/ui/boot/Commons/Color.qml +258 -0
- package/ui/boot/Commons/I18n.qml +118 -0
- package/ui/boot/Commons/InputDevices.qml +112 -0
- package/ui/boot/Commons/InputMethodState.qml +38 -0
- package/ui/boot/Commons/IpcRegistry.qml +77 -0
- package/ui/boot/Commons/Numbers.js +19 -0
- package/ui/boot/Commons/Plural.js +91 -0
- package/ui/boot/Commons/ShellIpc.qml +12 -0
- package/ui/boot/Commons/Style.qml +561 -0
- package/ui/boot/Commons/Translations.qml +100 -0
- package/ui/boot/Commons/UntypedInput.qml +152 -0
- package/ui/boot/Commons/Util.qml +188 -0
- package/ui/boot/Commons/qmldir +13 -0
- package/ui/boot/LICENSE-omarchy +20 -0
- package/ui/boot/Ui/BackgroundMedia.qml +49 -0
- package/ui/boot/Ui/BarIconButton.qml +106 -0
- package/ui/boot/Ui/BarIconContent.qml +38 -0
- package/ui/boot/Ui/BarIndicator.qml +53 -0
- package/ui/boot/Ui/BarWidget.qml +50 -0
- package/ui/boot/Ui/BorderOverlay.qml +54 -0
- package/ui/boot/Ui/BorderSurface.qml +40 -0
- package/ui/boot/Ui/Button.qml +224 -0
- package/ui/boot/Ui/ButtonGroup.qml +131 -0
- package/ui/boot/Ui/ConfirmDialog.qml +134 -0
- package/ui/boot/Ui/CursorSurface.qml +42 -0
- package/ui/boot/Ui/Dropdown.qml +245 -0
- package/ui/boot/Ui/FilterInput.qml +26 -0
- package/ui/boot/Ui/IconContentBounds.qml +141 -0
- package/ui/boot/Ui/KeyboardPanel.qml +453 -0
- package/ui/boot/Ui/MultiSelect.qml +624 -0
- package/ui/boot/Ui/NumberField.qml +86 -0
- package/ui/boot/Ui/OpticalGlyph.qml +68 -0
- package/ui/boot/Ui/OverlayWindow.qml +102 -0
- package/ui/boot/Ui/Panel.qml +60 -0
- package/ui/boot/Ui/PanelActionButton.qml +105 -0
- package/ui/boot/Ui/PanelController.qml +16 -0
- package/ui/boot/Ui/PanelHero.qml +112 -0
- package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
- package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
- package/ui/boot/Ui/PanelSeparator.qml +19 -0
- package/ui/boot/Ui/PanelSlider.qml +156 -0
- package/ui/boot/Ui/PanelToolTip.qml +50 -0
- package/ui/boot/Ui/PluginBarApi.qml +89 -0
- package/ui/boot/Ui/PointerMoveGate.qml +54 -0
- package/ui/boot/Ui/PopupCard.qml +181 -0
- package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
- package/ui/boot/Ui/SearchableDropdown.qml +354 -0
- package/ui/boot/Ui/SizedImage.qml +125 -0
- package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
- package/ui/boot/Ui/TextField.qml +58 -0
- package/ui/boot/Ui/Toggle.qml +118 -0
- package/ui/boot/Ui/ToggleSwitch.qml +115 -0
- package/ui/boot/Ui/WidgetButton.qml +172 -0
- package/ui/boot/Ui/qmldir +41 -0
- package/ui/boot/fleatab.qml +50 -0
- package/ui/boot/picker.qml +39 -0
- package/ui/boot/shell.qml +131 -0
- package/ui/boot/tabtearoff.qml +51 -0
- package/ui/js/Anchor.js +379 -0
- package/ui/js/AnchorHold.js +162 -0
- package/ui/js/Archive.js +157 -0
- package/ui/js/ArchiveCard.js +44 -0
- package/ui/js/ArchiveOps.js +44 -0
- package/ui/js/BackReturn.js +118 -0
- package/ui/js/BulkRename.js +100 -0
- package/ui/js/Buttons.js +54 -0
- package/ui/js/ChromeKeys.js +116 -0
- package/ui/js/ClipMarks.js +73 -0
- package/ui/js/ClipSelection.js +67 -0
- package/ui/js/Clipboard.js +179 -0
- package/ui/js/Cloud.js +97 -0
- package/ui/js/CodeRuns.js +72 -0
- package/ui/js/Collide.js +212 -0
- package/ui/js/ColumnFit.js +28 -0
- package/ui/js/ColumnMenu.js +111 -0
- package/ui/js/Columns.js +298 -0
- package/ui/js/ColumnsCarry.js +103 -0
- package/ui/js/Compare.js +74 -0
- package/ui/js/Contrast.js +157 -0
- package/ui/js/ControlReader.js +42 -0
- package/ui/js/Convert.js +52 -0
- package/ui/js/CopyAs.js +52 -0
- package/ui/js/Crumbs.js +178 -0
- package/ui/js/Csv.js +231 -0
- package/ui/js/Density.js +44 -0
- package/ui/js/Devices.js +440 -0
- package/ui/js/DirSizes.js +180 -0
- package/ui/js/Drag.js +360 -0
- package/ui/js/DragOut.js +166 -0
- package/ui/js/DropDev.js +52 -0
- package/ui/js/Dropbox.js +41 -0
- package/ui/js/Eject.js +217 -0
- package/ui/js/Errors.js +188 -0
- package/ui/js/ExtThumbs.js +115 -0
- package/ui/js/Facts.js +402 -0
- package/ui/js/FigureDate.js +14 -0
- package/ui/js/Filter.js +285 -0
- package/ui/js/Find.js +46 -0
- package/ui/js/Flash.js +184 -0
- package/ui/js/FlashCard.js +79 -0
- package/ui/js/FlashEndings.js +125 -0
- package/ui/js/FlashPane.js +116 -0
- package/ui/js/FleaBin.js +12 -0
- package/ui/js/Focus.js +504 -0
- package/ui/js/FolderSorts.js +108 -0
- package/ui/js/FolderViews.js +44 -0
- package/ui/js/Format.js +314 -0
- package/ui/js/Fuzzy.js +141 -0
- package/ui/js/GlassTag.js +72 -0
- package/ui/js/Grid.js +33 -0
- package/ui/js/GridGeometry.js +90 -0
- package/ui/js/GridNames.js +153 -0
- package/ui/js/GvfsBridge.js +200 -0
- package/ui/js/HostClipboard.js +29 -0
- package/ui/js/Icons.js +218 -0
- package/ui/js/Input.js +50 -0
- package/ui/js/Jump.js +200 -0
- package/ui/js/KeyName.js +64 -0
- package/ui/js/Keymap.js +401 -0
- package/ui/js/Kinds.js +164 -0
- package/ui/js/LICENSES/ISC-lucide.txt +43 -0
- package/ui/js/LangMarkPaths.js +47 -0
- package/ui/js/LangMarks.js +120 -0
- package/ui/js/Lists.js +11 -0
- package/ui/js/LocalSend.js +39 -0
- package/ui/js/LockedMenu.js +63 -0
- package/ui/js/MakeDefault.js +186 -0
- package/ui/js/MarkBox.js +7 -0
- package/ui/js/Markdown.js +119 -0
- package/ui/js/MarkdownLists.js +86 -0
- package/ui/js/MarkdownMaths.js +58 -0
- package/ui/js/MarkdownPictures.js +32 -0
- package/ui/js/MarkdownPrepared.js +139 -0
- package/ui/js/MarkdownTableFit.js +34 -0
- package/ui/js/Marks.js +148 -0
- package/ui/js/Marquee.js +96 -0
- package/ui/js/Match.js +93 -0
- package/ui/js/Material.js +109 -0
- package/ui/js/MdBlocks.js +437 -0
- package/ui/js/MdBreak.js +71 -0
- package/ui/js/MdChunks.js +70 -0
- package/ui/js/MdContainer.js +137 -0
- package/ui/js/MdDocument.js +337 -0
- package/ui/js/MdEmph.js +97 -0
- package/ui/js/MdEntity.js +108 -0
- package/ui/js/MdEntityTable.js +223 -0
- package/ui/js/MdEscape.js +59 -0
- package/ui/js/MdFront.js +37 -0
- package/ui/js/MdHold.js +32 -0
- package/ui/js/MdHtml.js +307 -0
- package/ui/js/MdHtmlBlock.js +290 -0
- package/ui/js/MdHtmlHeading.js +53 -0
- package/ui/js/MdHtmlImage.js +179 -0
- package/ui/js/MdInline.js +154 -0
- package/ui/js/MdItems.js +212 -0
- package/ui/js/MdLeaf.js +309 -0
- package/ui/js/MdLink.js +196 -0
- package/ui/js/MdMath.js +67 -0
- package/ui/js/MdParagraphs.js +138 -0
- package/ui/js/MdRefs.js +232 -0
- package/ui/js/MdResolve.js +226 -0
- package/ui/js/MdRun.js +300 -0
- package/ui/js/MdUrl.js +226 -0
- package/ui/js/Menu.js +514 -0
- package/ui/js/MenuContext.js +85 -0
- package/ui/js/MenuFit.js +13 -0
- package/ui/js/MenuRefresh.js +74 -0
- package/ui/js/MenuWheel.js +35 -0
- package/ui/js/Messages.js +186 -0
- package/ui/js/Motion.js +16 -0
- package/ui/js/Mounts.js +320 -0
- package/ui/js/MouseNav.js +13 -0
- package/ui/js/Nav.js +329 -0
- package/ui/js/NetFs.js +26 -0
- package/ui/js/OpenWith.js +83 -0
- package/ui/js/Ops.js +585 -0
- package/ui/js/Palette.js +33 -0
- package/ui/js/PathBar.js +260 -0
- package/ui/js/Permissions.js +179 -0
- package/ui/js/Phones.js +112 -0
- package/ui/js/Picker.js +353 -0
- package/ui/js/PlaceMenu.js +96 -0
- package/ui/js/Places.js +265 -0
- package/ui/js/PreviewAsk.js +21 -0
- package/ui/js/PreviewKeys.js +155 -0
- package/ui/js/PreviewSettle.js +29 -0
- package/ui/js/PreviewSwap.js +101 -0
- package/ui/js/PropertyFacts.js +144 -0
- package/ui/js/Protocols.js +296 -0
- package/ui/js/QuickLookKinds.js +27 -0
- package/ui/js/QuickLookRect.js +24 -0
- package/ui/js/RailDrop.js +51 -0
- package/ui/js/RailKeys.js +87 -0
- package/ui/js/RailMenu.js +133 -0
- package/ui/js/Recent.js +135 -0
- package/ui/js/RecentMode.js +156 -0
- package/ui/js/Reload.js +60 -0
- package/ui/js/Renderer.js +9 -0
- package/ui/js/RunFile.js +143 -0
- package/ui/js/Scripts.js +28 -0
- package/ui/js/Scroll.js +304 -0
- package/ui/js/ScrollOff.js +69 -0
- package/ui/js/Search.js +478 -0
- package/ui/js/Selection.js +97 -0
- package/ui/js/Settings.js +476 -0
- package/ui/js/SettingsAbout.js +97 -0
- package/ui/js/SettingsShelf.js +52 -0
- package/ui/js/SheetKeys.js +42 -0
- package/ui/js/SheetQuery.js +281 -0
- package/ui/js/ShelfPile.js +27 -0
- package/ui/js/SlowClick.js +53 -0
- package/ui/js/SlowOp.js +6 -0
- package/ui/js/Sort.js +134 -0
- package/ui/js/Startup.js +63 -0
- package/ui/js/StateWords.js +17 -0
- package/ui/js/Status.js +238 -0
- package/ui/js/Swap.js +166 -0
- package/ui/js/TabMove.js +39 -0
- package/ui/js/Tabs.js +751 -0
- package/ui/js/Tags.js +134 -0
- package/ui/js/Taildrop.js +128 -0
- package/ui/js/Tap.js +180 -0
- package/ui/js/TextSize.js +107 -0
- package/ui/js/Thumbs.js +158 -0
- package/ui/js/Transfer.js +172 -0
- package/ui/js/Trash.js +84 -0
- package/ui/js/TrashDates.js +47 -0
- package/ui/js/TrashDrop.js +64 -0
- package/ui/js/UiState.js +438 -0
- package/ui/js/Unlock.js +152 -0
- package/ui/js/Update.js +130 -0
- package/ui/js/UserDirs.js +56 -0
- package/ui/qmldir +230 -0
package/ui/GridTile.qml
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Density.js" as Density
|
|
5
|
+
import "js/Drag.js" as DragOps
|
|
6
|
+
import "js/Format.js" as Format
|
|
7
|
+
import "js/GridNames.js" as GridNames
|
|
8
|
+
import "js/Match.js" as Match
|
|
9
|
+
import "js/Icons.js" as Icons
|
|
10
|
+
import "js/LangMarks.js" as LangMarks
|
|
11
|
+
|
|
12
|
+
// One grid cell: the same mark the list row draws, in a larger slot, with the name under it.
|
|
13
|
+
Item {
|
|
14
|
+
id: root
|
|
15
|
+
|
|
16
|
+
property var row: null
|
|
17
|
+
property bool cursor: false
|
|
18
|
+
property bool hovered: false
|
|
19
|
+
// False while the selection band runs, so the wash keeps the highlight off while the tip still reads hovered.
|
|
20
|
+
property bool hoverShown: true
|
|
21
|
+
property bool selected: false
|
|
22
|
+
property bool dropTarget: false
|
|
23
|
+
property bool dropCopying: false
|
|
24
|
+
property bool dropLinking: false
|
|
25
|
+
property string thumb: ""
|
|
26
|
+
property bool renaming: false
|
|
27
|
+
property var renamePane: null
|
|
28
|
+
// The grid area derives it per visible tile, so an empty clipboard costs nothing.
|
|
29
|
+
property string clipMark: ""
|
|
30
|
+
// A cut tile dims to the ClipMarks board's own opacity, content only.
|
|
31
|
+
readonly property bool clipCut: root.clipMark === "scissors"
|
|
32
|
+
// One dim for the mark slot and the caption, so one ternary serves both opacities.
|
|
33
|
+
readonly property real dimOpacity: root.clipCut ? Theme.disabledOpacity : 1
|
|
34
|
+
// The mark's own size: 12 px in the muted role, 9 px after the name, per the board.
|
|
35
|
+
readonly property int clipPx: Theme.clipMarkSize
|
|
36
|
+
// The query List marks: a search's answered query, else the "/" filter's, "" for none; ui/GridArea.qml hands it down.
|
|
37
|
+
property string markQuery: ""
|
|
38
|
+
// True while the strip is up, so the wash builds with the strip and no keystroke pays for it, as List's rows arm.
|
|
39
|
+
property bool markArmed: false
|
|
40
|
+
readonly property string editorText: renameLoader.item ? renameLoader.item.current : ""
|
|
41
|
+
readonly property Item editorField: renameLoader.item as Item
|
|
42
|
+
// Keep an uninitialized Loader visible; a begun editor's captured index survives retirement.
|
|
43
|
+
visible: !(root.editing || root.pooled) || !renameLoader.item
|
|
44
|
+
|| renameLoader.item.editIndex < 0 || !renameLoader.item.viewport
|
|
45
|
+
|| renameLoader.item.viewport.renameEditor === renameLoader.item
|
|
46
|
+
// The editor's one line box, centred on the caption's first line on whole pixels: it stands a little over the line's top.
|
|
47
|
+
readonly property real renameLineBox: renameLoader.item ? renameLoader.item.lineBox : Theme.rowHeight - 2 * Theme.spacing.rowPaddingY
|
|
48
|
+
readonly property real renameY: Math.round(nameLabel.y + (Theme.grid.captionLineHeight - root.renameLineBox) / 2)
|
|
49
|
+
readonly property real editorExtraHeight: root.editing && renameLoader.item ? Math.max(0, root.renameY - nameLabel.y + renameLoader.item.implicitHeight - Math.max(Theme.grid.captionHeight, Math.ceil(nameLabel.contentHeight)) - Density.gridPadY(Theme.spacing.rowPaddingX, ViewState.density)) : 0
|
|
50
|
+
property real renameExtraHeight: 0
|
|
51
|
+
// Grid layout can pool this Loader while reading its implicit height. Defer and coalesce per tile.
|
|
52
|
+
onEditorExtraHeightChanged: Qt.callLater(root.applyRenameHeight)
|
|
53
|
+
function applyRenameHeight() {
|
|
54
|
+
if (renameLoader.item) {
|
|
55
|
+
renameLoader.item.queueContainment()
|
|
56
|
+
renameLoader.item.extraHeight = root.editorExtraHeight
|
|
57
|
+
}
|
|
58
|
+
root.renameExtraHeight = root.editorExtraHeight
|
|
59
|
+
}
|
|
60
|
+
signal renameCommitted(string newName)
|
|
61
|
+
signal renameAbandoned()
|
|
62
|
+
function commitEditor() { return renameLoader.item ? renameLoader.item.commit() : false }
|
|
63
|
+
|
|
64
|
+
// A lifted tile is the cursor, the pointer or a selection member, the same ladder Row.qml climbs.
|
|
65
|
+
readonly property bool lifted: root.cursor || (root.hovered && root.hoverShown) || root.selected
|
|
66
|
+
// A thumbnail path is not a thumbnail: the cache file can be evicted between the pane's answer
|
|
67
|
+
// and the decode, and a tile whose Image failed to load has to be marked by its kind instead.
|
|
68
|
+
readonly property bool thumbDrawn: root.thumb.length > 0 && tileThumb.status !== Image.Error
|
|
69
|
+
// One filename lookup; only a mapped row without a thumbnail builds the mark's Loader.
|
|
70
|
+
readonly property string langSlug: ViewState.langMarks ? LangMarks.slugForRow(root.row) : ""
|
|
71
|
+
property var langLoader: null
|
|
72
|
+
function syncLangMark() { LangMarks.syncMark(root, markGlyph, Qt.resolvedUrl("LangMarkLoader.qml"), Component.Ready) }
|
|
73
|
+
onLangSlugChanged: root.syncLangMark()
|
|
74
|
+
onThumbDrawnChanged: root.syncLangMark()
|
|
75
|
+
// The same alias ui/Row.qml carries, so ui/Ipc.qml's rowThumbReady answers for a tile too.
|
|
76
|
+
readonly property alias iconStatus: tileThumb.status
|
|
77
|
+
readonly property Item thumbItem: tileThumb
|
|
78
|
+
readonly property Item captionItem: nameLabel
|
|
79
|
+
|
|
80
|
+
Accessible.role: Accessible.ListItem
|
|
81
|
+
Accessible.name: Match.rowName(root.row, false)
|
|
82
|
+
|
|
83
|
+
Rectangle {
|
|
84
|
+
anchors.fill: parent
|
|
85
|
+
anchors.margins: Theme.spacing.hairline
|
|
86
|
+
color: root.cursor ? Style.selectedAccentFill
|
|
87
|
+
: root.selected ? Style.selectionFill
|
|
88
|
+
: (root.hovered && root.hoverShown) ? Style.hoverFill
|
|
89
|
+
: "transparent"
|
|
90
|
+
// Only the cursor gets a frame; marked tiles retain their separate fill.
|
|
91
|
+
border.width: root.cursor ? Theme.spacing.hairline : 0
|
|
92
|
+
border.color: Theme.color.accent
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// The drop wash, and its label further down, build only on the tile under a drag, the way ui/Row.qml builds its drop frame.
|
|
96
|
+
Loader {
|
|
97
|
+
anchors.fill: parent
|
|
98
|
+
active: root.dropTarget
|
|
99
|
+
sourceComponent: Rectangle {
|
|
100
|
+
color: Util.alpha(Theme.color.accent, Style.hoverFillAlpha)
|
|
101
|
+
border.width: Theme.spacing.hairline
|
|
102
|
+
border.color: Theme.color.accent
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
Item {
|
|
107
|
+
id: markSlot
|
|
108
|
+
anchors.horizontalCenter: parent.horizontalCenter
|
|
109
|
+
anchors.top: parent.top
|
|
110
|
+
anchors.topMargin: Density.gridPadY(Theme.spacing.rowPaddingX, ViewState.density)
|
|
111
|
+
width: ViewState.thumbnailPixels
|
|
112
|
+
height: ViewState.thumbnailPixels
|
|
113
|
+
opacity: root.dimOpacity
|
|
114
|
+
|
|
115
|
+
// A thumbnail is a decoded image and stays one; the glyph beside it is a native mark, and
|
|
116
|
+
// exactly one is visible, chosen the same way ui/Row.qml chooses.
|
|
117
|
+
Image {
|
|
118
|
+
id: tileThumb
|
|
119
|
+
anchors.fill: parent
|
|
120
|
+
visible: root.thumbDrawn
|
|
121
|
+
// Format.fileUri, not a concatenation: a cache path can carry a # or a ? and either one
|
|
122
|
+
// silently truncates a plain file:// URL, which is what the hashcache fixture proves.
|
|
123
|
+
source: root.thumb.length > 0 ? Format.fileUri(root.thumb) : ""
|
|
124
|
+
fillMode: Image.PreserveAspectFit
|
|
125
|
+
sourceSize.width: ViewState.thumbnailPixels
|
|
126
|
+
sourceSize.height: ViewState.thumbnailPixels
|
|
127
|
+
asynchronous: true
|
|
128
|
+
cache: false
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
Flea.Glyph {
|
|
132
|
+
id: markGlyph
|
|
133
|
+
anchors.fill: parent
|
|
134
|
+
visible: !root.thumbDrawn && root.langSlug === ""
|
|
135
|
+
// A folder mark never grows past 128, centred in the larger slots, so only thumbnails grow.
|
|
136
|
+
maxSize: Density.glyphCap(ViewState.thumbnailPixels)
|
|
137
|
+
name: root.row ? Icons.glyphForRow(root.row.i, root.row.p) : "file"
|
|
138
|
+
// ThemeRoles.dc.html gives accent the selection fill and edge and foreground the label
|
|
139
|
+
// and the mark inside it, so the border carries the emphasis and the ink stays readable.
|
|
140
|
+
color: root.cursor || root.selected ? Theme.color.foreground : Theme.color.mutedFrame
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// One drawn line's piece of the match wash, at the box the mark measured for it.
|
|
145
|
+
component MatchWash: Rectangle {
|
|
146
|
+
id: wash
|
|
147
|
+
property var box: null
|
|
148
|
+
visible: wash.box !== null
|
|
149
|
+
x: wash.box ? wash.box.x : 0
|
|
150
|
+
y: wash.box ? wash.box.y : 0
|
|
151
|
+
width: wash.box ? wash.box.width : 0
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// List's match mark, ui/MatchText.qml's wash behind the matched letters under the unchanged caption, built with the strip.
|
|
155
|
+
Loader {
|
|
156
|
+
id: markLoader
|
|
157
|
+
active: root.markArmed || root.markQuery.length > 0
|
|
158
|
+
visible: !root.editing
|
|
159
|
+
opacity: root.dimOpacity
|
|
160
|
+
x: nameLabel.x
|
|
161
|
+
y: nameLabel.y
|
|
162
|
+
width: nameLabel.width
|
|
163
|
+
height: nameLabel.height
|
|
164
|
+
sourceComponent: Item {
|
|
165
|
+
id: washes
|
|
166
|
+
FontMetrics { id: captionFace; font: nameLabel.font }
|
|
167
|
+
// Only lines Qt drew as Flea broke them are measured; a caption Qt wrapped or elided again would place a box off its letters.
|
|
168
|
+
readonly property bool laidAsBroken: nameLabel.lineCount === nameLabel.text.split("\n").length && !nameLabel.truncated
|
|
169
|
+
readonly property var boxes: washes.laidAsBroken ? washes.measure(GridNames.captionMarks(nameLabel.text, root.markQuery), captionFace.font, washes.width) : []
|
|
170
|
+
// One box per line the run touches; face is read only so a font change re-measures, as RenameField's edgeX does.
|
|
171
|
+
function measure(spans, face, width) {
|
|
172
|
+
return spans.map(function (span) {
|
|
173
|
+
return { x: (width - captionFace.advanceWidth(span.centred)) / 2 + captionFace.advanceWidth(span.before),
|
|
174
|
+
y: span.line * Theme.grid.captionLineHeight, width: captionFace.advanceWidth(span.run) }
|
|
175
|
+
})
|
|
176
|
+
}
|
|
177
|
+
readonly property color wash: Qt.rgba(Theme.color.accent.r, Theme.color.accent.g, Theme.color.accent.b, Theme.color.accent.a * Theme.washActive)
|
|
178
|
+
MatchWash { box: washes.boxes.length > 0 ? washes.boxes[0] : null; height: Math.ceil(captionFace.height); color: washes.wash }
|
|
179
|
+
MatchWash { box: washes.boxes.length > 1 ? washes.boxes[1] : null; height: Math.ceil(captionFace.height); color: washes.wash }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// corner: a filename is arbitrary text, so PlainText; the breaks are Flea's own, WrapAnywhere only catches wide glyphs.
|
|
184
|
+
readonly property int captionLines: root.dropTarget ? 1 : 2
|
|
185
|
+
// Cells of one caption line at the bodySmall advance the label draws at; a wide glyph counts two.
|
|
186
|
+
readonly property int captionPerLine: Theme.bodySmallAdvance > 0 && nameLabel.width > 0 ? Math.floor(nameLabel.width / Theme.bodySmallAdvance) : -1
|
|
187
|
+
Text {
|
|
188
|
+
id: nameLabel
|
|
189
|
+
visible: !root.editing
|
|
190
|
+
opacity: root.dimOpacity
|
|
191
|
+
anchors.top: markSlot.bottom
|
|
192
|
+
anchors.topMargin: Theme.spacing.gap
|
|
193
|
+
anchors.left: parent.left
|
|
194
|
+
anchors.right: parent.right
|
|
195
|
+
anchors.leftMargin: Theme.spacing.gap
|
|
196
|
+
anchors.rightMargin: Theme.spacing.gap + (root.clipMark.length > 0 ? Theme.spacing.gap + root.clipPx : 0)
|
|
197
|
+
// The slot fits the laid-out text, keeping the token reserve as its minimum.
|
|
198
|
+
height: Math.max(root.dropTarget ? Theme.grid.captionLineHeight : Theme.grid.captionHeight, Math.ceil(contentHeight))
|
|
199
|
+
horizontalAlignment: Text.AlignHCenter
|
|
200
|
+
text: root.row ? GridNames.gridCaption(Match.rowName(root.row, false), root.captionPerLine, root.captionLines) : ""
|
|
201
|
+
color: Theme.color.foreground
|
|
202
|
+
font.family: Theme.font.family
|
|
203
|
+
font.pixelSize: Theme.font.bodySmall
|
|
204
|
+
textFormat: Text.PlainText
|
|
205
|
+
wrapMode: Text.WrapAnywhere
|
|
206
|
+
maximumLineCount: root.captionLines
|
|
207
|
+
lineHeightMode: Text.FixedHeight
|
|
208
|
+
lineHeight: Theme.grid.captionLineHeight
|
|
209
|
+
elide: Text.ElideRight
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// A tagged tile mounts its swatches (ui/TagSlot.qml) under the caption on first need; an untagged tile builds nothing.
|
|
213
|
+
property var tagItem: null
|
|
214
|
+
onRowChanged: root.syncTags()
|
|
215
|
+
onRenamingChanged: root.syncTags()
|
|
216
|
+
function syncTags() {
|
|
217
|
+
var names = root.row && !root.renaming ? root.row.tg : undefined
|
|
218
|
+
if (root.tagItem !== null) root.tagItem.tags = names || []
|
|
219
|
+
else if (names !== undefined) root.tagItem = Qt.createComponent("TagSlot.qml").createObject(root, { tags: names, below: nameLabel })
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Built only on a clipboard tile: a Glyph per tile costs a Shape, and the mark follows the last line it sits beside.
|
|
223
|
+
Loader {
|
|
224
|
+
id: clipLoader
|
|
225
|
+
active: root.clipMark.length > 0 && !root.editing
|
|
226
|
+
width: root.clipPx
|
|
227
|
+
height: root.clipPx
|
|
228
|
+
// One gap past the centred last line's own right end, capped at the strip the margin reserves; a tile with no mark measures nothing.
|
|
229
|
+
x: clipLoader.active ? Math.min(nameLabel.x + (nameLabel.width + GridNames.lastLineCells(nameLabel.text) * Theme.bodySmallAdvance) / 2 + Theme.spacing.gap, nameLabel.x + nameLabel.width + Theme.spacing.gap) : 0
|
|
230
|
+
y: clipLoader.active ? nameLabel.y + Math.min(nameLabel.text.split("\n").length, root.captionLines) * Theme.grid.captionLineHeight - (Theme.grid.captionLineHeight + root.clipPx) / 2 - 1 : 0
|
|
231
|
+
sourceComponent: Flea.Glyph {
|
|
232
|
+
width: root.clipPx
|
|
233
|
+
height: root.clipPx
|
|
234
|
+
name: root.clipMark
|
|
235
|
+
color: Theme.color.mutedFrame
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Built only while renaming, the way ui/Row.qml builds its own editor.
|
|
240
|
+
Loader {
|
|
241
|
+
id: renameLoader
|
|
242
|
+
active: root.pooled ? root.pooledEditorRow >= 0 : root.renaming
|
|
243
|
+
anchors { left: nameLabel.left; right: nameLabel.right }
|
|
244
|
+
y: root.renameY
|
|
245
|
+
// A normal editor's expansion starts and stays zero, so no height-change signal measures it.
|
|
246
|
+
onLoaded: Qt.callLater(root.applyRenameHeight)
|
|
247
|
+
sourceComponent: Flea.RenameField {
|
|
248
|
+
height: implicitHeight
|
|
249
|
+
editorHost: root
|
|
250
|
+
pane: root.renamePane
|
|
251
|
+
viewport: root.GridView.view
|
|
252
|
+
containOnBegin: true
|
|
253
|
+
name: root.row ? root.row.n.split("/").pop() : ""
|
|
254
|
+
onCommitted: function(newName) { root.renameCommitted(newName) }
|
|
255
|
+
onAbandoned: root.renameAbandoned()
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
Loader {
|
|
260
|
+
anchors.top: nameLabel.bottom
|
|
261
|
+
anchors.left: nameLabel.left
|
|
262
|
+
anchors.right: nameLabel.right
|
|
263
|
+
height: Theme.grid.captionLineHeight
|
|
264
|
+
active: root.dropTarget
|
|
265
|
+
sourceComponent: Text {
|
|
266
|
+
horizontalAlignment: Text.AlignHCenter
|
|
267
|
+
text: DragOps.label(root.dropCopying, root.dropLinking)
|
|
268
|
+
color: Theme.color.accent
|
|
269
|
+
font.family: Theme.font.family
|
|
270
|
+
font.pixelSize: Theme.font.caption
|
|
271
|
+
textFormat: Text.PlainText
|
|
272
|
+
elide: Text.ElideRight
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Flea elides the caption itself, so Qt reports truncated only when it had to cut a caption Flea handed over whole.
|
|
277
|
+
function captionElided() {
|
|
278
|
+
return nameLabel.truncated || (root.row ? nameLabel.text.split("\n").join("") !== String(Match.rowName(root.row, false)) : false)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Built only while the host's hover rests on a truncated caption: its size reads the wrapped name's layout, which every tile paid at rest.
|
|
282
|
+
Loader {
|
|
283
|
+
objectName: "nameTip"
|
|
284
|
+
active: !root.editing && !root.dropTarget && root.hovered && root.captionElided()
|
|
285
|
+
z: 1
|
|
286
|
+
anchors.horizontalCenter: parent.horizontalCenter
|
|
287
|
+
anchors.top: nameLabel.bottom
|
|
288
|
+
anchors.topMargin: Theme.spacing.hairline
|
|
289
|
+
sourceComponent: Rectangle {
|
|
290
|
+
width: Math.min(tip.implicitWidth + 2 * Theme.spacing.gap, Theme.grid.minCellWidth * 2)
|
|
291
|
+
height: tip.implicitHeight + Theme.spacing.gap
|
|
292
|
+
color: Theme.color.surface
|
|
293
|
+
border.width: Theme.spacing.hairline
|
|
294
|
+
border.color: Theme.color.mutedFrame
|
|
295
|
+
|
|
296
|
+
Text {
|
|
297
|
+
id: tip
|
|
298
|
+
anchors.centerIn: parent
|
|
299
|
+
width: parent.width - 2 * Theme.spacing.gap
|
|
300
|
+
text: Match.rowName(root.row, false)
|
|
301
|
+
color: Theme.color.foreground
|
|
302
|
+
font.family: Theme.font.family
|
|
303
|
+
font.pixelSize: Theme.font.caption
|
|
304
|
+
wrapMode: Text.Wrap
|
|
305
|
+
textFormat: Text.PlainText
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Pooled by its view, which parks the tile's listing reads on live (ui/GridArea.qml); a pooled tile builds no editor.
|
|
311
|
+
property bool pooled: false
|
|
312
|
+
readonly property bool live: !root.pooled
|
|
313
|
+
// The row whose editor the tile held when pooled, -1 for none; it keeps that editor while the edit stays on that row.
|
|
314
|
+
property int pooledEditorRow: -1
|
|
315
|
+
// The pane's edit row as a pooled tile sees it; once the edit leaves the recorded row the record clears for good.
|
|
316
|
+
readonly property int pooledRename: root.pooled && root.renamePane !== null ? root.renamePane.renamingIndex : -1
|
|
317
|
+
onPooledRenameChanged: if (root.pooledEditorRow >= 0 && root.pooledRename !== root.pooledEditorRow) root.pooledEditorRow = -1
|
|
318
|
+
// Drawn as the editing tile: renaming, or pooled with the editor it held.
|
|
319
|
+
readonly property bool editing: root.renaming || root.pooled && root.pooledEditorRow >= 0
|
|
320
|
+
GridView.onPooled: { root.pooledEditorRow = root.renaming && root.renamePane !== null ? root.renamePane.renamingIndex : -1; root.pooled = true }
|
|
321
|
+
// The kept editor drops first, while every listing read is still parked, so its retirement always owns the edit.
|
|
322
|
+
GridView.onReused: { root.pooledEditorRow = -1; root.pooled = false }
|
|
323
|
+
// What the grid last drew here (GridGeometry.heldRow), a plain object no binding tracks.
|
|
324
|
+
readonly property var rowMemo: ({ row: null, index: -1, listing: 0 })
|
|
325
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import Quickshell
|
|
3
|
+
import Quickshell.Io
|
|
4
|
+
import "js/GvfsBridge.js" as GvfsBridge
|
|
5
|
+
|
|
6
|
+
// Phones and shares open through the GVFS FUSE bridge at $XDG_RUNTIME_DIR/gvfs, and gvfsd
|
|
7
|
+
// spawns its own bridge once at its startup only, so one that died stays down until
|
|
8
|
+
// something starts it again. ensure() checks the folder first: a served one opens at once
|
|
9
|
+
// and starts nothing, an unserved one starts gvfsd-fuse's own argv a single time and the
|
|
10
|
+
// folder opening waits for the folder rather than for the process. The window stays put
|
|
11
|
+
// either way until ready() carries the folder, and failed() carries the board's error line.
|
|
12
|
+
// Local folders never reach here: ui/NetworkMounts.qml only ensures FUSE paths gio resolved.
|
|
13
|
+
//
|
|
14
|
+
// This service lives in the window-long network host rather than in the rail, so hiding the
|
|
15
|
+
// rail mid-wait kills no wait: the ready or the failure still lands and the Starting line it
|
|
16
|
+
// showed still clears. The bridge itself starts detached, so closing the rail or the chooser
|
|
17
|
+
// never takes gvfsd-fuse down with it; no exit status ever reaches the board, and the whole
|
|
18
|
+
// ensure's own deadline is the failure signal instead.
|
|
19
|
+
Item {
|
|
20
|
+
id: root
|
|
21
|
+
|
|
22
|
+
signal ready(string path, var origin, bool isDir)
|
|
23
|
+
signal starting(string text, var origin)
|
|
24
|
+
signal failed(string text, var origin)
|
|
25
|
+
signal notice(string text, var origin)
|
|
26
|
+
|
|
27
|
+
// The test seam: FLEA_GVFS_FUSE names a fake bridge command the way FLEA_BIN names one.
|
|
28
|
+
property string fuseEnv: Quickshell.env("FLEA_GVFS_FUSE") || ""
|
|
29
|
+
property string runtimeDir: Quickshell.env("XDG_RUNTIME_DIR") || ""
|
|
30
|
+
// Which question checkProcess is answering: the directory check, the file check, a wait
|
|
31
|
+
// poll or the classify after a poll landed.
|
|
32
|
+
property string pendingMode: ""
|
|
33
|
+
// Set beside the deadline's own kill so the helper's late exit answers nothing: the
|
|
34
|
+
// deadline already failed the wait, and that exit belongs to no waiter anymore.
|
|
35
|
+
property bool _ensureTimedOut: false
|
|
36
|
+
|
|
37
|
+
// D-103: flow, never state, which shadows Item.state and was the tree's own qmllint
|
|
38
|
+
// property-override.
|
|
39
|
+
property var flow: GvfsBridge.create()
|
|
40
|
+
|
|
41
|
+
function dir() { return GvfsBridge.bridgeDir(root.runtimeDir) }
|
|
42
|
+
|
|
43
|
+
function ensure(path, label, origin) {
|
|
44
|
+
root.run(GvfsBridge.ensure(root.flow, { path: path, label: label, origin: origin,
|
|
45
|
+
bridgeDir: root.dir(), fuseBin: GvfsBridge.fuseBin(root.fuseEnv) }))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function cancel() {
|
|
49
|
+
root.pendingMode = ""
|
|
50
|
+
if (checkProcess.running) { root._ensureTimedOut = true; checkProcess.running = false }
|
|
51
|
+
root.stopWaiting()
|
|
52
|
+
root.run(GvfsBridge.cancel(root.flow))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// A dialog cancel ends only its own flight's waiter; another flight's wait stands.
|
|
56
|
+
function cancelFor(origin) {
|
|
57
|
+
var waiter = root.flow.waiter
|
|
58
|
+
if (waiter && origin !== null && waiter.origin !== origin) return
|
|
59
|
+
root.cancel()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function run(actions) {
|
|
63
|
+
for (var i = 0; i < actions.length; i++) {
|
|
64
|
+
var action = actions[i]
|
|
65
|
+
if (action.op === "check" || action.op === "checkFile" || action.op === "classify") {
|
|
66
|
+
root.pendingMode = action.op
|
|
67
|
+
// Directories answer -d, anything else -e: a file under a live bridge is ready
|
|
68
|
+
// without any start, and only a path that is neither starts one.
|
|
69
|
+
checkProcess.command = action.op === "check" || action.op === "classify"
|
|
70
|
+
? ["test", "-d", action.path] : ["test", "-e", action.path]
|
|
71
|
+
checkProcess.running = true
|
|
72
|
+
ensureDeadline.restart()
|
|
73
|
+
} else if (action.op === "start") {
|
|
74
|
+
// Detached on purpose: an attached child dies with this service, and killing the
|
|
75
|
+
// rail or the chooser must never take gvfsd-fuse down for every app. There is no
|
|
76
|
+
// exit to wait for, so the folder poll below is the whole failure signal; the
|
|
77
|
+
// single flight in ensure() above is what keeps one wait to one start, because a
|
|
78
|
+
// detached spawn cannot be told apart from another one by a running flag.
|
|
79
|
+
Quickshell.execDetached(action.argv)
|
|
80
|
+
pollTimer.restart()
|
|
81
|
+
startingTimer.restart()
|
|
82
|
+
ensureDeadline.restart()
|
|
83
|
+
} else if (action.op === "ready") {
|
|
84
|
+
root.stopWaiting()
|
|
85
|
+
root.ready(action.path, action.origin, action.isDir)
|
|
86
|
+
} else if (action.op === "show") {
|
|
87
|
+
root.starting(action.text, action.origin)
|
|
88
|
+
} else if (action.op === "fail") {
|
|
89
|
+
root.stopWaiting()
|
|
90
|
+
root.failed(action.text, action.origin)
|
|
91
|
+
} else if (action.op === "refuse") {
|
|
92
|
+
root.notice(action.text, action.origin)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function stopWaiting() {
|
|
98
|
+
ensureDeadline.stop()
|
|
99
|
+
pollTimer.stop()
|
|
100
|
+
startingTimer.stop()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// One deadline for the whole ensure, checking, file-checking, waiting and classifying.
|
|
104
|
+
// Whichever leg is still running when it fires is the one that missed it. The flag is set
|
|
105
|
+
// only beside a real kill, so a deadline that lands between two helpers arms nothing for a
|
|
106
|
+
// later wait to swallow: one kill pairs with exactly one late exit.
|
|
107
|
+
Timer {
|
|
108
|
+
id: ensureDeadline
|
|
109
|
+
interval: GvfsBridge.ENSURE_MS
|
|
110
|
+
repeat: false
|
|
111
|
+
onTriggered: {
|
|
112
|
+
if (root.flow.phase === "idle" && !root.flow.waiter)
|
|
113
|
+
return
|
|
114
|
+
if (checkProcess.running) {
|
|
115
|
+
root._ensureTimedOut = true
|
|
116
|
+
checkProcess.running = false
|
|
117
|
+
}
|
|
118
|
+
root.stopWaiting()
|
|
119
|
+
root.run(GvfsBridge.onTimeout(root.flow))
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
Timer {
|
|
124
|
+
id: startingTimer
|
|
125
|
+
interval: GvfsBridge.STARTING_MS
|
|
126
|
+
repeat: false
|
|
127
|
+
onTriggered: root.run(GvfsBridge.onElapsed(root.flow))
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
Timer {
|
|
131
|
+
id: pollTimer
|
|
132
|
+
interval: GvfsBridge.POLL_MS
|
|
133
|
+
repeat: true
|
|
134
|
+
onTriggered: {
|
|
135
|
+
if (checkProcess.running || !root.flow.waiter
|
|
136
|
+
|| root.flow.phase !== "waiting")
|
|
137
|
+
return
|
|
138
|
+
root.pendingMode = "poll"
|
|
139
|
+
checkProcess.command = ["test", "-e", root.flow.waiter.path]
|
|
140
|
+
checkProcess.running = true
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
Process {
|
|
145
|
+
id: checkProcess
|
|
146
|
+
onExited: function (exitCode) {
|
|
147
|
+
if (root._ensureTimedOut) {
|
|
148
|
+
root._ensureTimedOut = false
|
|
149
|
+
root.pendingMode = ""
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
var mode = root.pendingMode
|
|
153
|
+
root.pendingMode = ""
|
|
154
|
+
if (mode === "poll")
|
|
155
|
+
root.run(GvfsBridge.onPolled(root.flow, exitCode === 0))
|
|
156
|
+
else if (mode === "checkFile")
|
|
157
|
+
root.run(GvfsBridge.onCheckedFile(root.flow, exitCode === 0))
|
|
158
|
+
else if (mode === "classify")
|
|
159
|
+
root.run(GvfsBridge.onClassified(root.flow, exitCode === 0))
|
|
160
|
+
else
|
|
161
|
+
root.run(GvfsBridge.onChecked(root.flow, exitCode === 0))
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|