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,358 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "js/Eject.js" as Eject
|
|
4
|
+
import "js/Format.js" as Format
|
|
5
|
+
import "js/TabMove.js" as TabMove
|
|
6
|
+
|
|
7
|
+
// One rail row, shared by the Favorites, Network and Devices groups so the three read alike; see
|
|
8
|
+
// ui/Sidebar.qml "The rail" for the entry shape each group feeds this delegate.
|
|
9
|
+
Item {
|
|
10
|
+
id: root
|
|
11
|
+
|
|
12
|
+
required property int index
|
|
13
|
+
required property var modelData
|
|
14
|
+
// Current-place identity stays separate from the keyboard's visual highlight, including over IPC.
|
|
15
|
+
property bool lit: false
|
|
16
|
+
property bool highlighted: root.lit
|
|
17
|
+
property bool cursor: false
|
|
18
|
+
property bool focused: false
|
|
19
|
+
// A drop cue replaces the trailing detail and reserves its caption's width.
|
|
20
|
+
property Item trailingLabel: null
|
|
21
|
+
// The keyboard is on this row's eject mark, which then draws its own frame in the foreground at its hit box.
|
|
22
|
+
property bool markFocused: false
|
|
23
|
+
// Network only, driven from ui/Sidebar.qml's renamingIndex; swaps the label for the editor.
|
|
24
|
+
property bool renaming: false
|
|
25
|
+
|
|
26
|
+
signal activated(int index)
|
|
27
|
+
// A click on the eject mark releases the row at once, the same Eject or Unmount the
|
|
28
|
+
// menu row and Ctrl+E take; carrying the index, because the rail rebuilds on its poll
|
|
29
|
+
// and a position taken later can name a different row.
|
|
30
|
+
signal ejectRequested(int index)
|
|
31
|
+
// Right click asks the rail to raise the menu over this row, carrying the point it opens at.
|
|
32
|
+
// The rail decides what the menu offers and opens none on a row with nothing to release. It is
|
|
33
|
+
// ui/Pane.qml's own single ui/ContextMenu.qml: a second instance in this tree took the keyboard
|
|
34
|
+
// away from the list, see AGENTS.md "A second ContextMenu instance breaks the whole window's
|
|
35
|
+
// keyboard focus", which is why the rail had no menu at all until now.
|
|
36
|
+
signal menuRequested(int index, var scenePosition)
|
|
37
|
+
// Middle click: the row's folder in a new tab; ui/js/PlaceMenu.js openTabAt decides which rows have one.
|
|
38
|
+
signal tabRequested(int index)
|
|
39
|
+
signal renameCommitted(int index, string text)
|
|
40
|
+
signal renameCancelled(int index)
|
|
41
|
+
// Favourites reorder by drag; a favourite carries its store index, others leave -1.
|
|
42
|
+
property int dragFrom: -1
|
|
43
|
+
property int lineCount: 0
|
|
44
|
+
signal moved(int to)
|
|
45
|
+
signal reorderAt(int line)
|
|
46
|
+
|
|
47
|
+
// A share or a removable volume carries a mount-state dot; the internal disk is always there
|
|
48
|
+
// and always mounted, so a dot on it would say nothing, and a favourite is not a mount at all.
|
|
49
|
+
readonly property var placesState: ViewState.state.places || ({})
|
|
50
|
+
// The eject mark's accessible name, one whole sentence per kind of row, each filled by Format.fill.
|
|
51
|
+
readonly property var ejectWords: ({ eject: "Eject %1", unmount: "Unmount %1" })
|
|
52
|
+
readonly property string detail: root.modelData.kind === "trash"
|
|
53
|
+
? (root.placesState.trashCount === true && root.modelData.count > 0 ? String(root.modelData.count) : "")
|
|
54
|
+
: (root.modelData.group === "device" || root.modelData.volume === true) && root.placesState.driveSize === true && root.modelData.size !== null
|
|
55
|
+
? Format.size(root.modelData.size) : ""
|
|
56
|
+
// PhoneMark: a phone is a volume, so its row carries the same mount-state square a removable
|
|
57
|
+
// disk and a share carry, in the same fixed slot.
|
|
58
|
+
readonly property bool showsDot: (root.modelData.group === "network" && root.modelData.kind !== "dropbox")
|
|
59
|
+
|| (root.modelData.group === "device"
|
|
60
|
+
&& (root.modelData.kind === "volume" || root.modelData.kind === "phone"))
|
|
61
|
+
// The Trash row draws its count where every other row draws its indicator, and never both.
|
|
62
|
+
readonly property bool countIsIndicator: root.modelData.kind === "trash" && root.detail.length > 0
|
|
63
|
+
// Small and fixed: a status dot is not part of the type or icon scale.
|
|
64
|
+
readonly property int dotSize: 6
|
|
65
|
+
// The canvas's own value for a bookmark nothing has mounted yet.
|
|
66
|
+
readonly property real unmountedOpacity: 0.5
|
|
67
|
+
|
|
68
|
+
// The favourite under the pointer while its reorder drag runs; it ghosts the way a dragged tab does, the bar says where it lands.
|
|
69
|
+
property bool held: false
|
|
70
|
+
opacity: root.held ? Theme.disabledOpacity : 1
|
|
71
|
+
|
|
72
|
+
width: parent ? parent.width : 0
|
|
73
|
+
// The rail reads denser than the list it sits beside; see Theme.qml's railRowHeight comment.
|
|
74
|
+
height: Theme.railRowHeight
|
|
75
|
+
|
|
76
|
+
Accessible.role: Accessible.ListItem
|
|
77
|
+
Accessible.name: root.modelData.label
|
|
78
|
+
|
|
79
|
+
// The rail rounds nothing: a lit place is the list row's square full-bleed fill, see ui/Row.qml.
|
|
80
|
+
Rectangle {
|
|
81
|
+
anchors.fill: parent
|
|
82
|
+
color: root.highlighted
|
|
83
|
+
? (root.modelData.kind === "trash" ? Style.selectedAccentFill : root.focused ? Style.selectedFill : Style.normalFill)
|
|
84
|
+
: "transparent"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// The eject mark's hover lift, the board's 8% rung; the mark itself lifts to foreground below.
|
|
88
|
+
Rectangle {
|
|
89
|
+
anchors.fill: parent
|
|
90
|
+
visible: ejectLoader.item !== null && ejectLoader.item.hovered
|
|
91
|
+
color: Theme.color.foreground
|
|
92
|
+
opacity: Theme.washHover
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
Rectangle {
|
|
96
|
+
visible: root.highlighted
|
|
97
|
+
width: Theme.spacing.hairline * 2
|
|
98
|
+
height: parent.height
|
|
99
|
+
color: Theme.color.accent
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// The TAGS section hands its rows their own swatch mark; every other row keeps the glyph.
|
|
103
|
+
property Component tagMark: null
|
|
104
|
+
|
|
105
|
+
Loader {
|
|
106
|
+
id: mark
|
|
107
|
+
anchors.left: parent.left
|
|
108
|
+
anchors.leftMargin: Style.spacing.rowPaddingX
|
|
109
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
110
|
+
width: Theme.railIconSize
|
|
111
|
+
height: Theme.railIconSize
|
|
112
|
+
sourceComponent: root.modelData.kind === "dropbox" ? dropboxMark : root.tagMark !== null ? root.tagMark : glyphMark
|
|
113
|
+
onLoaded: if (root.tagMark !== null) item.entry = root.modelData
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ThemeRoles.html gives every rail label and glyph the foreground role, selected rows included:
|
|
117
|
+
// the cursor reads through the fill and the accent edge above, never by dimming the rows it is not on.
|
|
118
|
+
Component {
|
|
119
|
+
id: glyphMark
|
|
120
|
+
Glyph {
|
|
121
|
+
name: root.modelData.glyph
|
|
122
|
+
color: root.highlighted && root.modelData.kind === "trash" ? Theme.color.accent : Theme.color.foreground
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// The brand marks are reproductions, so they take their own component rather than Glyph sizing.
|
|
127
|
+
Component {
|
|
128
|
+
id: dropboxMark
|
|
129
|
+
DropboxMark {
|
|
130
|
+
iconSize: Theme.railIconSize
|
|
131
|
+
color: Theme.color.foreground
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
Text {
|
|
136
|
+
id: label
|
|
137
|
+
visible: !root.renaming
|
|
138
|
+
anchors.left: mark.right
|
|
139
|
+
anchors.leftMargin: Style.spacing.rowGap
|
|
140
|
+
// The label ends one gap before any trailing number, square or mark.
|
|
141
|
+
anchors.right: root.trailingLabel ? parent.right : root.detail.length > 0 ? detailText.left : dot.left
|
|
142
|
+
anchors.rightMargin: root.trailingLabel ? Math.min(root.width - label.x,
|
|
143
|
+
Theme.spacing.rowPaddingX + root.trailingLabel.implicitWidth + Theme.spacing.gap)
|
|
144
|
+
: root.keepsTrailingGap ? Style.spacing.rowGap : 0
|
|
145
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
146
|
+
text: root.modelData.label
|
|
147
|
+
color: root.modelData.error ? Theme.color.error : Theme.color.foreground
|
|
148
|
+
font.family: Theme.font.family
|
|
149
|
+
font.pixelSize: Theme.font.body
|
|
150
|
+
// A label too long for the rail keeps its start and ends in an ellipsis.
|
|
151
|
+
elide: Text.ElideRight
|
|
152
|
+
clip: root.trailingLabel !== null
|
|
153
|
+
textFormat: Text.PlainText
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// The label's slot, holding the product's one editor, ui/RenameField.qml, in rail type.
|
|
157
|
+
Loader {
|
|
158
|
+
id: renameLoader
|
|
159
|
+
active: root.renaming
|
|
160
|
+
anchors.left: mark.right
|
|
161
|
+
anchors.leftMargin: Style.spacing.rowGap
|
|
162
|
+
anchors.right: root.detail.length > 0 ? detailText.left : dot.left
|
|
163
|
+
anchors.rightMargin: root.keepsTrailingGap ? Style.spacing.rowGap : 0
|
|
164
|
+
// The editor owns its height, one line box; the rail row centres it on whole pixels.
|
|
165
|
+
y: Math.round((root.height - renameLoader.height) / 2)
|
|
166
|
+
sourceComponent: RenameField {
|
|
167
|
+
height: implicitHeight
|
|
168
|
+
name: root.modelData.label
|
|
169
|
+
onCommitted: function (newName) { root.renameCommitted(root.index, newName) }
|
|
170
|
+
onAbandoned: root.renameCancelled(root.index)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// What the editor holds right now, for tests through ui/Ipc.qml's railRenameEditorText.
|
|
175
|
+
readonly property string editorText: renameLoader.item ? renameLoader.item.current : ""
|
|
176
|
+
readonly property bool editorShown: renameLoader.item !== null && renameLoader.item.visible
|
|
177
|
+
// The rail's editor as ui/Row.qml hands its own, so a test measures every host's frame the same way.
|
|
178
|
+
readonly property Item editorField: renameLoader.item as Item
|
|
179
|
+
// RailEject: a mounted row draws the eject mark in place of the square.
|
|
180
|
+
readonly property bool showsEject: Eject.releasable(root.modelData)
|
|
181
|
+
readonly property real ejectMarkSize: Theme.font.caption
|
|
182
|
+
// The keyboard frame on the eject mark, read by tests/keyreach.qml.
|
|
183
|
+
readonly property Item markFrameItem: ejectLoader.item ? ejectLoader.item.frame : null
|
|
184
|
+
// The rail's real trailing indicator slot, so ui/Ipc.qml measures this dot instead of recomputing it.
|
|
185
|
+
readonly property Item indicatorSlot: dot
|
|
186
|
+
readonly property Item detailItem: root.trailingLabel || detailText
|
|
187
|
+
readonly property Item labelItem: label
|
|
188
|
+
readonly property bool indicatorVisible: root.showsDot && root.trailingLabel === null
|
|
189
|
+
// One gap before any trailing number, square or mark; detail covers the Trash count's zero-width dot.
|
|
190
|
+
readonly property bool keepsTrailingGap: root.detail.length > 0 || dot.width > 0
|
|
191
|
+
|
|
192
|
+
Text {
|
|
193
|
+
id: detailText
|
|
194
|
+
visible: root.trailingLabel === null
|
|
195
|
+
anchors.right: dot.left
|
|
196
|
+
anchors.rightMargin: dot.width > 0 ? Style.spacing.rowGap : 0
|
|
197
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
198
|
+
text: root.detail
|
|
199
|
+
color: Theme.color.muted
|
|
200
|
+
font.family: Theme.font.family
|
|
201
|
+
font.pixelSize: Theme.font.caption
|
|
202
|
+
font.features: { "tnum": 1 }
|
|
203
|
+
horizontalAlignment: Text.AlignRight
|
|
204
|
+
textFormat: Text.PlainText
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Every right-aligned mark in the rail is centred in a caption-wide slot, so this dot and the
|
|
208
|
+
// NETWORK header's "+" share one centre line whatever their ink does: align by slot, never by ink.
|
|
209
|
+
Item {
|
|
210
|
+
id: dot
|
|
211
|
+
visible: root.trailingLabel === null
|
|
212
|
+
anchors.right: parent.right
|
|
213
|
+
anchors.rightMargin: Style.spacing.rowPaddingX
|
|
214
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
215
|
+
// RailDetails rules 1 and 3 with their 2026-09-14 amendment: a drive size is a number, so
|
|
216
|
+
// every device row ends its size on one x with this slot reserved after it, dot or no dot;
|
|
217
|
+
// the Trash count is an indicator rather than a size, so it sits in the slot itself, on the
|
|
218
|
+
// same edge as the mount dots and the NETWORK plus.
|
|
219
|
+
width: root.countIsIndicator ? 0 : (root.showsDot || root.detail.length > 0 ? Theme.font.caption : 0)
|
|
220
|
+
height: Theme.font.caption
|
|
221
|
+
|
|
222
|
+
// Green once gio mount -l lists it, muted at half strength while it is only a bookmark waiting
|
|
223
|
+
// to be mounted. A square, not a disc: the cut is hard corners, and the canvas draws it square.
|
|
224
|
+
Rectangle {
|
|
225
|
+
visible: root.showsDot && !root.showsEject
|
|
226
|
+
anchors.centerIn: parent
|
|
227
|
+
width: root.dotSize
|
|
228
|
+
height: root.dotSize
|
|
229
|
+
color: root.modelData.mounted ? Theme.color.executable : Theme.color.mutedFrame
|
|
230
|
+
opacity: root.modelData.mounted ? 1 : root.unmountedOpacity
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// The one-click release: the eject mark in the square's own slot, muted at rest and
|
|
234
|
+
// foreground under the cursor or the pointer, the way a lifted row's metadata is. Built
|
|
235
|
+
// only on a row that releases, the way the menu builds a brand mark only on its row.
|
|
236
|
+
Loader {
|
|
237
|
+
id: ejectLoader
|
|
238
|
+
anchors.centerIn: parent
|
|
239
|
+
width: root.ejectMarkSize
|
|
240
|
+
height: root.ejectMarkSize
|
|
241
|
+
active: root.showsEject
|
|
242
|
+
sourceComponent: ejectMark
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// The mark and its hit box, standing only while the row releases. The hit box grows to the
|
|
247
|
+
// WCAG floor and centres on the ink, the way the NETWORK header's own addMark does: a centre
|
|
248
|
+
// anchor quantises an odd size difference and leaves the two centres half a pixel apart.
|
|
249
|
+
Component {
|
|
250
|
+
id: ejectMark
|
|
251
|
+
Item {
|
|
252
|
+
property alias hit: hitBox
|
|
253
|
+
property alias frame: markFrame
|
|
254
|
+
property alias hovered: hitHover.hovered
|
|
255
|
+
width: root.ejectMarkSize
|
|
256
|
+
height: root.ejectMarkSize
|
|
257
|
+
|
|
258
|
+
Glyph {
|
|
259
|
+
id: ink
|
|
260
|
+
anchors.centerIn: parent
|
|
261
|
+
name: "eject"
|
|
262
|
+
color: root.cursor || hitHover.hovered || root.markFocused ? Theme.color.foreground : Theme.color.mutedFrame
|
|
263
|
+
width: root.ejectMarkSize
|
|
264
|
+
height: root.ejectMarkSize
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
Rectangle {
|
|
268
|
+
id: markFrame
|
|
269
|
+
anchors.fill: hitBox
|
|
270
|
+
color: "transparent"
|
|
271
|
+
border.width: Theme.spacing.hairline
|
|
272
|
+
border.color: Theme.color.foreground
|
|
273
|
+
visible: root.markFocused
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
Item {
|
|
277
|
+
id: hitBox
|
|
278
|
+
width: Math.max(Theme.hitMin, root.ejectMarkSize)
|
|
279
|
+
height: width
|
|
280
|
+
x: ink.x + (ink.width - width) / 2
|
|
281
|
+
y: ink.y + (ink.height - height) / 2
|
|
282
|
+
Accessible.role: Accessible.Button
|
|
283
|
+
Accessible.name: Format.fill(root.modelData.group === "device" ? root.ejectWords.eject : root.ejectWords.unmount, root.modelData.label)
|
|
284
|
+
Accessible.onPressAction: { if (!root.renaming) root.ejectRequested(root.index) }
|
|
285
|
+
HoverHandler { id: hitHover }
|
|
286
|
+
TapHandler {
|
|
287
|
+
acceptedButtons: Qt.LeftButton
|
|
288
|
+
gesturePolicy: TapHandler.ReleaseWithinBounds
|
|
289
|
+
enabled: root.showsEject && !root.renaming
|
|
290
|
+
onTapped: root.ejectRequested(root.index)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Whether a scene point lands in the mark's hit box, so the row's own tap never
|
|
297
|
+
// answers a press the mark's tap already took. The hit box overflows the slot it is
|
|
298
|
+
// centred on, so the slot alone would hand its rim to the row underneath.
|
|
299
|
+
function ejectAt(scene) {
|
|
300
|
+
var target = ejectLoader.item && ejectLoader.item.hit ? ejectLoader.item.hit : dot
|
|
301
|
+
var p = target.mapFromItem(null, scene.x, scene.y)
|
|
302
|
+
return p.x >= 0 && p.y >= 0 && p.x < target.width && p.y < target.height
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
TapHandler {
|
|
306
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
|
307
|
+
// Overlay taps take the grab so the covered listing cannot select the same click.
|
|
308
|
+
gesturePolicy: ViewState.railAutoHide ? TapHandler.ReleaseWithinBounds : TapHandler.DragThreshold
|
|
309
|
+
onTapped: function (eventPoint, button) {
|
|
310
|
+
// The field owns clicks inside itself while editing; this only covers the rest of the row.
|
|
311
|
+
if (root.renaming)
|
|
312
|
+
return
|
|
313
|
+
if (button === Qt.MiddleButton) {
|
|
314
|
+
root.tabRequested(root.index)
|
|
315
|
+
return
|
|
316
|
+
}
|
|
317
|
+
// The mark releases on its own left tap; the row must not activate underneath
|
|
318
|
+
// it, while a right tap still raises the menu it always did.
|
|
319
|
+
if (button === Qt.LeftButton && root.showsEject && root.ejectAt(eventPoint.scenePosition))
|
|
320
|
+
return
|
|
321
|
+
// A right click never activates, whatever the row is: it either raised a menu or the
|
|
322
|
+
// row had nothing to offer, and it must not mount and open a stick nobody asked to open.
|
|
323
|
+
if (button === Qt.RightButton) {
|
|
324
|
+
root.menuRequested(root.index, eventPoint.scenePosition)
|
|
325
|
+
return
|
|
326
|
+
}
|
|
327
|
+
root.activated(root.index)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Only favourites build a reorder handler; the row stays fixed and Sidebar draws the boundary.
|
|
332
|
+
Loader {
|
|
333
|
+
active: root.dragFrom >= 0
|
|
334
|
+
anchors.fill: parent
|
|
335
|
+
sourceComponent: Item {
|
|
336
|
+
DragHandler {
|
|
337
|
+
target: null
|
|
338
|
+
xAxis.enabled: false
|
|
339
|
+
property real startY: 0
|
|
340
|
+
onActiveChanged: {
|
|
341
|
+
root.held = active
|
|
342
|
+
if (active) {
|
|
343
|
+
startY = persistentTranslation.y
|
|
344
|
+
return
|
|
345
|
+
}
|
|
346
|
+
var to = TabMove.railReorder(persistentTranslation.y - startY, root.dragFrom, Theme.railRowHeight, root.lineCount).to
|
|
347
|
+
root.reorderAt(-1)
|
|
348
|
+
if (to !== root.dragFrom)
|
|
349
|
+
root.moved(to)
|
|
350
|
+
}
|
|
351
|
+
onCentroidChanged: {
|
|
352
|
+
if (active)
|
|
353
|
+
root.reorderAt(TabMove.railReorder(persistentTranslation.y - startY, root.dragFrom, Theme.railRowHeight, root.lineCount).line)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
package/ui/Spinner.qml
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import QtQuick.Shapes
|
|
3
|
+
|
|
4
|
+
// The Omarchy spiral as the activity mark: a stroke-dash crawl along the brand path, never a
|
|
5
|
+
// rotation. This and EmptyState's FleaMark are the only two places the spiral appears; rows
|
|
6
|
+
// and menus never draw it, per the icon-language spec.
|
|
7
|
+
Item {
|
|
8
|
+
id: root
|
|
9
|
+
|
|
10
|
+
property color color: Theme.color.mutedFrame
|
|
11
|
+
// The mark draws on the same 24 unit grid as every Glyph, scaled to the slot.
|
|
12
|
+
readonly property real grid: 24
|
|
13
|
+
readonly property real markScale: Math.min(root.width, root.height) / root.grid
|
|
14
|
+
|
|
15
|
+
Shape {
|
|
16
|
+
width: root.grid
|
|
17
|
+
height: root.grid
|
|
18
|
+
x: (root.width - root.grid * root.markScale) / 2
|
|
19
|
+
y: (root.height - root.grid * root.markScale) / 2
|
|
20
|
+
preferredRendererType: Shape.CurveRenderer
|
|
21
|
+
transform: Scale { xScale: root.markScale; yScale: root.markScale }
|
|
22
|
+
|
|
23
|
+
ShapePath {
|
|
24
|
+
id: crawl
|
|
25
|
+
strokeColor: root.color
|
|
26
|
+
fillColor: "transparent"
|
|
27
|
+
// A brand mark, not a cut glyph: the spiral keeps the brand's 2 and is exempt from Theme.strokeWidth on purpose.
|
|
28
|
+
strokeWidth: 2
|
|
29
|
+
capStyle: ShapePath.SquareCap
|
|
30
|
+
joinStyle: ShapePath.MiterJoin
|
|
31
|
+
strokeStyle: ShapePath.DashLine
|
|
32
|
+
// The spiral's centreline is 114 grid units and dash units are strokeWidth multiples,
|
|
33
|
+
// so 30+27=57 is exactly one period; the animation walks one period per cycle and the
|
|
34
|
+
// loop point is therefore invisible.
|
|
35
|
+
dashPattern: [30, 27]
|
|
36
|
+
PathSvg { path: "M21 21H3V3h18v14H7V7h10v6h-6" }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Still for its first second on screen, so a load faster than that draws no motion; a hide puts it back to rest.
|
|
41
|
+
readonly property int stillMs: 1000
|
|
42
|
+
property bool crawling: false
|
|
43
|
+
onVisibleChanged: if (!root.visible) { root.crawling = false; crawl.dashOffset = 0 }
|
|
44
|
+
Timer {
|
|
45
|
+
interval: root.stillMs
|
|
46
|
+
running: root.visible && !root.crawling
|
|
47
|
+
onTriggered: root.crawling = true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
NumberAnimation {
|
|
51
|
+
target: crawl
|
|
52
|
+
property: "dashOffset"
|
|
53
|
+
from: 0
|
|
54
|
+
to: -57
|
|
55
|
+
duration: 1600
|
|
56
|
+
loops: Animation.Infinite
|
|
57
|
+
// Item.visible reads effective visibility, so a hidden ancestor stops the crawl too.
|
|
58
|
+
running: root.visible && root.crawling
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import QtQml.Models
|
|
3
|
+
|
|
4
|
+
// A view's row count as a model that never changes identity, so a new count keeps the delegates that stay drawn.
|
|
5
|
+
DelegateModel {
|
|
6
|
+
id: root
|
|
7
|
+
|
|
8
|
+
required property Item view
|
|
9
|
+
property int total: 0
|
|
10
|
+
// The compositor is filled in componentComplete, so a group change before onCompleted is silently dropped.
|
|
11
|
+
property bool ready: false
|
|
12
|
+
|
|
13
|
+
// A move asked for inside the change's own layout is dropped, so a view that places itself does it here.
|
|
14
|
+
signal resized()
|
|
15
|
+
|
|
16
|
+
// Qt refuses an integer model larger than 100,000,000 rows.
|
|
17
|
+
readonly property int cap: 100000000
|
|
18
|
+
model: root.cap
|
|
19
|
+
groups: DelegateModelGroup { id: shown; name: "shown"; includeByDefault: false }
|
|
20
|
+
filterOnGroup: "shown"
|
|
21
|
+
|
|
22
|
+
// While true a view short of a viewport keeps a full layout's delegates in its reuse pool, so a count that grows takes them instead of building.
|
|
23
|
+
property bool warm: false
|
|
24
|
+
// The rows a full layout from the top builds, its cache buffer's included: the fill lays out no more, so none is left incubating.
|
|
25
|
+
property int warmRows: 0
|
|
26
|
+
|
|
27
|
+
// While true a count change leaves the current delegate current: Qt focuses each new current delegate, which takes the keys from an editor inside the old one.
|
|
28
|
+
property bool holdCurrent: false
|
|
29
|
+
|
|
30
|
+
onTotalChanged: root.resize()
|
|
31
|
+
onWarmChanged: if (root.warm) root.fill()
|
|
32
|
+
Component.onCompleted: { root.ready = true; root.resize() }
|
|
33
|
+
|
|
34
|
+
// Grows the count and shrinks it back in one turn, so no frame sees the rows and what they laid out waits pooled; a geometry change drains it.
|
|
35
|
+
function fill() {
|
|
36
|
+
var from = shown.count
|
|
37
|
+
var to = Math.min(root.warmRows, root.cap)
|
|
38
|
+
if (!root.ready || !root.view.reuseItems || to <= from)
|
|
39
|
+
return
|
|
40
|
+
// The buffer's rows lay out with the viewport's for this pass, built at once where a buffer pass would incubate them later.
|
|
41
|
+
var margin = root.view.displayMarginEnd
|
|
42
|
+
root.view.displayMarginEnd = margin + root.view.cacheBuffer + root.view.height
|
|
43
|
+
root.items.addGroups(from, to - from, "shown")
|
|
44
|
+
root.view.forceLayout()
|
|
45
|
+
shown.removeGroups(from, to - from, "shown")
|
|
46
|
+
root.view.forceLayout()
|
|
47
|
+
root.view.displayMarginEnd = margin
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Moves to the top and, unless holdCurrent, row 0 as a reset does, before the change, so only top rows lay out and a view placing itself after keeps its place.
|
|
51
|
+
function resize() {
|
|
52
|
+
var to = Math.min(Math.max(root.total, 0), root.cap)
|
|
53
|
+
var from = shown.count
|
|
54
|
+
if (!root.ready || to === from)
|
|
55
|
+
return
|
|
56
|
+
root.view.contentY = root.view.originY - root.view.topMargin
|
|
57
|
+
if (from > 0 && to > 0 && !root.holdCurrent)
|
|
58
|
+
root.view.currentIndex = 0
|
|
59
|
+
if (to > from)
|
|
60
|
+
root.items.addGroups(from, to - from, "shown")
|
|
61
|
+
else
|
|
62
|
+
shown.removeGroups(to, from - to, "shown")
|
|
63
|
+
// Lays out now: Qt pools a layout's removed rows only after building its inserted ones, so the next count reuses them.
|
|
64
|
+
root.view.forceLayout()
|
|
65
|
+
if (to > 0 && root.view.currentIndex < 0)
|
|
66
|
+
root.view.currentIndex = 0
|
|
67
|
+
root.resized()
|
|
68
|
+
if (to === 0)
|
|
69
|
+
root.drainHidden()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// True where a hidden count is rows kept for the return rather than an edit in flight, so the hide drains the pool beside them.
|
|
73
|
+
property bool keptRows: false
|
|
74
|
+
// A hidden view holds no delegates, pooled ones included; a shown one keeps its pool, parked, for the next listing.
|
|
75
|
+
function drainHidden() {
|
|
76
|
+
if (root.view.visible || shown.count > 0 && !root.keptRows || !root.view.reuseItems)
|
|
77
|
+
return
|
|
78
|
+
// Unpersist first so the pool toggle below frees the parked tiles too.
|
|
79
|
+
if (persistedItems.count > 0)
|
|
80
|
+
persistedItems.removeGroups(0, persistedItems.count, "persistedItems")
|
|
81
|
+
root.view.reuseItems = false
|
|
82
|
+
root.view.reuseItems = true
|
|
83
|
+
}
|
|
84
|
+
// A view hidden after it emptied drains here, since its count does not change again.
|
|
85
|
+
property Connections hiding: Connections {
|
|
86
|
+
target: root.view
|
|
87
|
+
function onVisibleChanged() { root.drainHidden() }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "js/Errors.js" as Errors
|
|
4
|
+
import "js/Filter.js" as Filter
|
|
5
|
+
import "js/Format.js" as Format
|
|
6
|
+
|
|
7
|
+
// The one thing a pane shows instead of rows, and it carries all three parts the States board gives
|
|
8
|
+
// a pane state: the mark, then one sentence, then the detail the system can prove. The sentence used
|
|
9
|
+
// to live in the status bar about 1300px away while the mode string sat here alone. The empty state
|
|
10
|
+
// has its own overlay in ui/shell.qml, so this yields to it there.
|
|
11
|
+
Item {
|
|
12
|
+
id: root
|
|
13
|
+
|
|
14
|
+
property string message: ""
|
|
15
|
+
property bool active: true
|
|
16
|
+
property string listingState: "loading"
|
|
17
|
+
property int total: 0
|
|
18
|
+
// The filter narrows rows already listed, so a query that matches none leaves a ready listing
|
|
19
|
+
// with nothing drawn in it; shown is -1 while no filter is up.
|
|
20
|
+
property string filterQuery: ""
|
|
21
|
+
property int shown: -1
|
|
22
|
+
// The st_mode of the directory the listing was denied. Zero whenever the backend could not stat
|
|
23
|
+
// it either, which draws no line rather than a mode string that would be false.
|
|
24
|
+
property int lockedMode: 0
|
|
25
|
+
|
|
26
|
+
readonly property bool locked: root.listingState === "locked"
|
|
27
|
+
// A listing past its wait is the Error state too, so the sentence draws with the alert mark.
|
|
28
|
+
readonly property bool failed: root.locked || root.listingState === "error" || root.listingState === "waiting"
|
|
29
|
+
readonly property bool nothingMatched: root.filterQuery.length > 0 && root.shown === 0 && root.total > 0
|
|
30
|
+
// The detail is the directory's own mode, which only a locked state has and only when the
|
|
31
|
+
// backend could stat it; everything else proves nothing extra and draws nothing.
|
|
32
|
+
readonly property string detail: root.locked ? Errors.lockedLine(root.lockedMode)
|
|
33
|
+
: root.nothingMatched ? Filter.noMatch(root.total) : ""
|
|
34
|
+
|
|
35
|
+
// The mark and lines at their unwrapped width, so ui/PaneStates.qml can tell whether they clear the listed columns.
|
|
36
|
+
readonly property real naturalWidth: Math.max(Theme.stateMarkSize, sentence.implicitWidth,
|
|
37
|
+
root.detail.length > 0 ? detailLine.implicitWidth : 0)
|
|
38
|
+
|
|
39
|
+
visible: root.active && (root.nothingMatched
|
|
40
|
+
|| (root.total === 0 && root.message.length > 0 && root.listingState !== "empty"))
|
|
41
|
+
|
|
42
|
+
Column {
|
|
43
|
+
anchors.centerIn: parent
|
|
44
|
+
spacing: Theme.spacing.gap
|
|
45
|
+
|
|
46
|
+
// corner: "lock" must reach ui/js/Icons.js before any pane can reach the locked state, because Icons.pathFor falls back to the file mark in silence.
|
|
47
|
+
Glyph {
|
|
48
|
+
anchors.horizontalCenter: parent.horizontalCenter
|
|
49
|
+
visible: root.failed || root.nothingMatched
|
|
50
|
+
// A failure mark stands alone rather than beside a row's text, so it opts in to the
|
|
51
|
+
// pane-state ceiling; States.dc.html draws Locked and Error at 40 and the row mark is 19.
|
|
52
|
+
maxSize: Theme.stateMarkSize
|
|
53
|
+
width: Theme.stateMarkSize
|
|
54
|
+
height: Theme.stateMarkSize
|
|
55
|
+
name: root.locked ? "lock" : root.nothingMatched ? "search" : "alert"
|
|
56
|
+
// Only a failure takes the urgent role, and only on the mark; the sentence stays readable.
|
|
57
|
+
color: root.nothingMatched ? Theme.color.mutedFrame : Theme.color.error
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
Text {
|
|
61
|
+
id: sentence
|
|
62
|
+
width: root.width
|
|
63
|
+
text: root.nothingMatched ? Format.fill(Filter.WORDS.nothingMatched, root.filterQuery) : root.message
|
|
64
|
+
color: Theme.color.foreground
|
|
65
|
+
font.family: Theme.font.family
|
|
66
|
+
font.pixelSize: Theme.font.body
|
|
67
|
+
horizontalAlignment: Text.AlignHCenter
|
|
68
|
+
wrapMode: Text.Wrap
|
|
69
|
+
textFormat: Text.PlainText
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Text {
|
|
73
|
+
id: detailLine
|
|
74
|
+
width: root.width
|
|
75
|
+
visible: root.detail.length > 0
|
|
76
|
+
text: root.detail
|
|
77
|
+
color: Theme.color.muted
|
|
78
|
+
font.family: Theme.font.family
|
|
79
|
+
font.pixelSize: Theme.font.caption
|
|
80
|
+
horizontalAlignment: Text.AlignHCenter
|
|
81
|
+
textFormat: Text.PlainText
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|