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,561 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Keymap.js" as Keymap
|
|
5
|
+
import "js/Menu.js" as Menu
|
|
6
|
+
import "js/Places.js" as Places
|
|
7
|
+
import "js/RailKeys.js" as RailKeys
|
|
8
|
+
import "js/SheetKeys.js" as SheetKeys
|
|
9
|
+
import "js/SheetQuery.js" as SheetQuery
|
|
10
|
+
|
|
11
|
+
// The keymap sheet ? opens, drawn as the Keys panel on Operations.dc.html draws it. Every row comes
|
|
12
|
+
// from keys.toml through Keymap.sheetFor, so a key that loses its binding cannot go on being advertised.
|
|
13
|
+
Item {
|
|
14
|
+
id: root
|
|
15
|
+
|
|
16
|
+
property bool opened: false
|
|
17
|
+
property Item focusHolder: null
|
|
18
|
+
readonly property var pane: root.focusHolder ? (root.focusHolder.sheetPane || root.focusHolder) : null
|
|
19
|
+
// The query field appears on the first typed key only; an exact place name ranks first.
|
|
20
|
+
property string query: ""
|
|
21
|
+
// The history read once when the query line opens, never per keystroke, bounded by
|
|
22
|
+
// Recent.LIMIT with no per-entry stat, listed whether or not the Recent rail row is on.
|
|
23
|
+
property var recentPaths: []
|
|
24
|
+
property bool recentAsked: false
|
|
25
|
+
// The cursor sits on the first row, the menu lift, and arrows move it.
|
|
26
|
+
property int resultCursor: 0
|
|
27
|
+
onQueryChanged: root.resultCursor = 0
|
|
28
|
+
// The whole table in every state, so the cap column keeps one width whatever the query narrows to.
|
|
29
|
+
readonly property var sheet: root.actionRows()
|
|
30
|
+
// The query results across actions, the cursor row's menu, places and recent files, bounded.
|
|
31
|
+
readonly property var queryResults: {
|
|
32
|
+
if (root.query.length === 0 || !root.focusHolder)
|
|
33
|
+
return []
|
|
34
|
+
var rows = root.sheet
|
|
35
|
+
var actions = SheetQuery.actionCandidates(rows)
|
|
36
|
+
var menus = SheetQuery.menuCandidates(root.menuModel(), function (a) { return Keymap.hintFor(a) })
|
|
37
|
+
var places = SheetQuery.placeCandidates(root.railModel())
|
|
38
|
+
var recents = SheetQuery.recentCandidates(root.recentPaths, root.pane.home)
|
|
39
|
+
return SheetQuery.rank(actions.concat(menus, places, recents), root.query)
|
|
40
|
+
}
|
|
41
|
+
function actionRows() {
|
|
42
|
+
var rows = Keymap.sheetFor(ViewState.keysPreset, "gui")
|
|
43
|
+
return root.focusHolder && root.focusHolder.sheetActionRows ? root.focusHolder.sheetActionRows(rows) : rows
|
|
44
|
+
}
|
|
45
|
+
// The cursor row's menu rows, hidden ones included so the sheet finds a row Settings Menus hides; disabled ones never run.
|
|
46
|
+
function menuModel() {
|
|
47
|
+
var holder = root.focusHolder
|
|
48
|
+
if (holder && holder.sheetMenuModel) return holder.sheetMenuModel()
|
|
49
|
+
if (!holder || !holder.cursorRow) return []
|
|
50
|
+
var context = holder.contextMenu().listingContext("", true)
|
|
51
|
+
context.hasRow = true
|
|
52
|
+
return Menu.listingEntries(context)
|
|
53
|
+
}
|
|
54
|
+
function railModel() {
|
|
55
|
+
var bar = root.pane ? root.pane.sidebar : null
|
|
56
|
+
return Flea.RailPlaces.entries().concat(bar ? bar.networkEntries.concat(bar.deviceEntries) : [])
|
|
57
|
+
}
|
|
58
|
+
function ensureRecent() {
|
|
59
|
+
if (root.recentAsked)
|
|
60
|
+
return
|
|
61
|
+
root.recentAsked = true
|
|
62
|
+
recentLoader.active = true
|
|
63
|
+
}
|
|
64
|
+
// Enter runs the highlighted row the way its own surface would.
|
|
65
|
+
function activateResult() {
|
|
66
|
+
var pick = root.queryResults[root.resultCursor]
|
|
67
|
+
if (!pick)
|
|
68
|
+
return
|
|
69
|
+
var decided = SheetQuery.dispatch(pick)
|
|
70
|
+
var holder = root.focusHolder
|
|
71
|
+
if (!holder || decided.kind === "disabled" || decided.kind === "none")
|
|
72
|
+
return
|
|
73
|
+
if (decided.kind === "action") {
|
|
74
|
+
SheetQuery.runAction(holder, decided.action, function () { root.close() })
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
if (decided.kind === "menu" || decided.kind === "confirm") {
|
|
78
|
+
SheetQuery.runMenu(holder, decided.menuAction, function () { root.close() })
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
if (decided.kind === "place") {
|
|
82
|
+
var entries = root.railModel()
|
|
83
|
+
var at = SheetQuery.placeIndex(entries, decided)
|
|
84
|
+
root.close()
|
|
85
|
+
if (at < 0) return
|
|
86
|
+
var pane = root.pane, entry = entries[at]
|
|
87
|
+
if (pane.sidebar && entry.group !== "home" && entry.kind !== "favourite" && entry.kind !== "trash") {
|
|
88
|
+
var railAt = SheetQuery.placeIndex(pane.sidebar.entries, decided)
|
|
89
|
+
if (railAt >= 0) pane.sidebar.activate(railAt)
|
|
90
|
+
} else Places.openEntry(entry, { pane: pane,
|
|
91
|
+
opened: function (path) { RailKeys.openFrom(pane, path, pane.sidebar) },
|
|
92
|
+
networkHost: function () { return pane.ensureNetworkService() },
|
|
93
|
+
trash: function () { pane.trash.open() }, message: pane.message })
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
if (decided.kind === "recent") {
|
|
97
|
+
root.close()
|
|
98
|
+
root.pane.openFile(decided.path)
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Directive 18's footprint: the four blocks flow into two columns of equal length rather than a
|
|
103
|
+
// 2x2 grid, which paid twice for the taller block of each pair and grew the card to the screen.
|
|
104
|
+
readonly property var columnSlots: {
|
|
105
|
+
var flat = []
|
|
106
|
+
for (var g = 0; g < root.groups.length; g++) {
|
|
107
|
+
flat.push({ heading: root.groups[g].title, row: null })
|
|
108
|
+
for (var i = 0; i < root.groups[g].rows.length; i++)
|
|
109
|
+
flat.push({ heading: "", row: root.groups[g].rows[i] })
|
|
110
|
+
}
|
|
111
|
+
if (root.columns === 1)
|
|
112
|
+
return [flat]
|
|
113
|
+
var half = Math.ceil(flat.length / 2)
|
|
114
|
+
// The fold prefers a group's own boundary, which costs at most one row of imbalance here.
|
|
115
|
+
for (var b = half - 1; b <= half + 1; b++)
|
|
116
|
+
if (b > 0 && b < flat.length && flat[b].heading.length > 0)
|
|
117
|
+
return [flat.slice(0, b), flat.slice(b)]
|
|
118
|
+
// It cannot always: a group longer than a column has to break inside itself, and then the
|
|
119
|
+
// continuation names it again, so no row on this sheet ever sits under no heading at all.
|
|
120
|
+
var owner = ""
|
|
121
|
+
for (var k = half - 1; k >= 0; k--)
|
|
122
|
+
if (flat[k].heading.length > 0) {
|
|
123
|
+
owner = flat[k].heading
|
|
124
|
+
break
|
|
125
|
+
}
|
|
126
|
+
var tail = flat.slice(half)
|
|
127
|
+
if (owner.length > 0)
|
|
128
|
+
tail = [{ heading: owner, row: null }].concat(tail)
|
|
129
|
+
return [flat.slice(0, half), tail]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// KeymapSheet rule 1: a binding gets a group in keys.toml and the sheet reads it, in the order
|
|
133
|
+
// that table lists them, with the heading its own key carries under a raised first letter.
|
|
134
|
+
readonly property var groups: {
|
|
135
|
+
var out = []
|
|
136
|
+
for (var name in Keymap.SHEET_GROUPS) {
|
|
137
|
+
var order = Keymap.SHEET_GROUPS[name], claimed = []
|
|
138
|
+
// The group's own list is the order the board draws, cursor keys before the chords;
|
|
139
|
+
// the generated sheet is in keys.toml's file order, which puts every preset row first.
|
|
140
|
+
for (var i = 0; i < order.length; i++) {
|
|
141
|
+
var row = root.sheet.filter(function (candidate) { return candidate.action === order[i] })
|
|
142
|
+
if (row.length > 0)
|
|
143
|
+
claimed.push(row[0])
|
|
144
|
+
}
|
|
145
|
+
if (claimed.length > 0)
|
|
146
|
+
out.push({ title: name.charAt(0).toUpperCase() + name.slice(1), rows: claimed })
|
|
147
|
+
}
|
|
148
|
+
return out
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// The canvas drew this panel at 300, the convert popup's width, beside four illustrative rows.
|
|
152
|
+
// The real sheet is sixty rows whose chords run to eighteen characters: at 300 a cap took the
|
|
153
|
+
// whole half-cell, the wording beside it elided to a single ellipsis, and the two columns
|
|
154
|
+
// overprinted each other. 480 is the Open with card's own anchor and leaves both room.
|
|
155
|
+
readonly property int sheetWidth: 480
|
|
156
|
+
readonly property int clampMargin: 8
|
|
157
|
+
// var, not Item: BorderSurface is a qs.Ui type qmllint cannot resolve, and Item would read as incompatible.
|
|
158
|
+
readonly property var cardItem: card
|
|
159
|
+
// A cap is sized from the type scale, never from the text inside it, so every cap is one height.
|
|
160
|
+
readonly property int capSize: Theme.markSize
|
|
161
|
+
// The 0.2.1 sheet's own row, which directive 18 makes the ceiling: the cap with one row padding
|
|
162
|
+
// under it. The board draws 32 around a 19 cap, but its pane holds 36 rows and this one holds 56.
|
|
163
|
+
readonly property int rowPitch: root.capSize + Theme.spacing.rowPaddingY
|
|
164
|
+
// A heading carries no cap box, so it takes the cap's own height rather than a whole row's.
|
|
165
|
+
readonly property int headingPitch: root.capSize
|
|
166
|
+
readonly property int capGap: Theme.spacing.gap
|
|
167
|
+
|
|
168
|
+
// One cap column for the whole sheet, measured off the widest chord this preset spells. Sizing
|
|
169
|
+
// each cap to its own text left every wording starting on a different x, and a wide chord took
|
|
170
|
+
// the cell whole and drew across the column beside it.
|
|
171
|
+
readonly property string widestCap: {
|
|
172
|
+
var out = ""
|
|
173
|
+
for (var i = 0; i < root.sheet.length; i++)
|
|
174
|
+
if (root.sheet[i].keys.length > out.length) out = root.sheet[i].keys
|
|
175
|
+
return out
|
|
176
|
+
}
|
|
177
|
+
readonly property int capWidth: Math.max(root.capSize, Math.ceil(capMetrics.width) + root.capGap)
|
|
178
|
+
// Board rule 4: no label is ever cut, so the floor is the widest wording this preset really
|
|
179
|
+
// draws. A window that cannot give two cells that much takes one column and scrolls instead.
|
|
180
|
+
readonly property string widestLabel: {
|
|
181
|
+
var out = ""
|
|
182
|
+
for (var i = 0; i < root.sheet.length; i++)
|
|
183
|
+
if (root.sheet[i].label.length > out.length) out = root.sheet[i].label
|
|
184
|
+
return out
|
|
185
|
+
}
|
|
186
|
+
readonly property int cellFloor: root.capWidth + root.capGap + Math.ceil(labelFloor.width)
|
|
187
|
+
// Two columns is what the canvas draws, and what keeps the whole map on one panel where it fits.
|
|
188
|
+
readonly property int columns: root.contentWidth >= 2 * root.cellFloor + Theme.spacing.rowPaddingX ? 2 : 1
|
|
189
|
+
|
|
190
|
+
// The body spans the card's inner width so a result's lift can run edge to edge; the text keeps its padded columns.
|
|
191
|
+
readonly property real textInset: Theme.spacing.rowPaddingX - Theme.spacing.hairline
|
|
192
|
+
readonly property real contentWidth: body.width - 2 * root.textInset
|
|
193
|
+
|
|
194
|
+
TextMetrics {
|
|
195
|
+
id: capMetrics
|
|
196
|
+
font.family: Theme.font.family
|
|
197
|
+
font.pixelSize: Theme.font.caption
|
|
198
|
+
text: root.widestCap
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
TextMetrics {
|
|
202
|
+
id: labelFloor
|
|
203
|
+
font.family: Theme.font.family
|
|
204
|
+
font.pixelSize: Theme.font.caption
|
|
205
|
+
text: root.widestLabel
|
|
206
|
+
}
|
|
207
|
+
readonly property real groundOpacity: 0.5
|
|
208
|
+
// The most of a result's label column its muted suffix may take, so a deep folder elides too and the name keeps the rest.
|
|
209
|
+
readonly property real whereShare: 0.5
|
|
210
|
+
|
|
211
|
+
anchors.fill: parent
|
|
212
|
+
visible: root.opened || root.opacity > 0
|
|
213
|
+
// Closed means no input, even while the fade-out is still drawn.
|
|
214
|
+
enabled: root.opened
|
|
215
|
+
opacity: 0
|
|
216
|
+
z: 2
|
|
217
|
+
Flea.Reveal { target: root; shown: root.opened; lift: card }
|
|
218
|
+
|
|
219
|
+
function open(holder) {
|
|
220
|
+
root.focusHolder = holder
|
|
221
|
+
root.query = ""
|
|
222
|
+
root.recentPaths = []
|
|
223
|
+
root.recentAsked = false
|
|
224
|
+
root.resultCursor = 0
|
|
225
|
+
recentLoader.active = false
|
|
226
|
+
// MenuAdditions040 callout 10: one two-byte read for the cursor row, so Make executable reads as the menu shows.
|
|
227
|
+
if (!holder.sheetPane) holder.checkShebang()
|
|
228
|
+
root.opened = true
|
|
229
|
+
keys.forceActiveFocus()
|
|
230
|
+
}
|
|
231
|
+
Loader {
|
|
232
|
+
id: recentLoader
|
|
233
|
+
active: false
|
|
234
|
+
source: "PickerRecent.qml"
|
|
235
|
+
onLoaded: item.refresh()
|
|
236
|
+
}
|
|
237
|
+
Connections {
|
|
238
|
+
target: recentLoader.item
|
|
239
|
+
function onRefreshed() { root.recentPaths = recentLoader.item.paths }
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function close() {
|
|
243
|
+
if (!root.opened)
|
|
244
|
+
return
|
|
245
|
+
root.opened = false
|
|
246
|
+
if (root.focusHolder) {
|
|
247
|
+
if (root.focusHolder.sheetFocus) root.focusHolder.sheetFocus()
|
|
248
|
+
else root.focusHolder.forceActiveFocus()
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// What a test reads instead of running OCR over the panel, the same idiom ui/Pane.qml's
|
|
253
|
+
// menuEntries() uses: one row per line, the cap and the wording it is drawn beside.
|
|
254
|
+
function rows() {
|
|
255
|
+
var out = []
|
|
256
|
+
// Under a query the sheet draws its results, so a test reads those instead of the resting grid.
|
|
257
|
+
if (root.query.length > 0) {
|
|
258
|
+
for (var r = 0; r < root.queryResults.length; r++)
|
|
259
|
+
out.push(root.queryResults[r].keys + " " + root.queryResults[r].label
|
|
260
|
+
+ (root.queryResults[r].disabled === true ? " (disabled)" : ""))
|
|
261
|
+
return out.join("\n")
|
|
262
|
+
}
|
|
263
|
+
for (var g = 0; g < root.groups.length; g++) {
|
|
264
|
+
out.push(root.groups[g].title)
|
|
265
|
+
for (var i = 0; i < root.groups[g].rows.length; i++)
|
|
266
|
+
out.push(root.groups[g].rows[i].keys + " " + root.groups[g].rows[i].label)
|
|
267
|
+
}
|
|
268
|
+
return out.join("\n")
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// The query results as JSON, each row's cap, wording and the muted where its delegate draws, for a test that reads the screen.
|
|
272
|
+
function resultState() {
|
|
273
|
+
var out = []
|
|
274
|
+
for (var r = 0; r < resultRepeater.count; r++) {
|
|
275
|
+
var item = resultRepeater.itemAt(r)
|
|
276
|
+
if (item)
|
|
277
|
+
out.push({ keys: item.modelData.keys, label: item.modelData.label, where: item.whereShown, disabled: item.modelData.disabled === true })
|
|
278
|
+
}
|
|
279
|
+
return JSON.stringify(out)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// A dimmed ground, and a click on it closes, the same shape ui/ConvertDialog.qml uses.
|
|
283
|
+
Rectangle {
|
|
284
|
+
anchors.fill: parent
|
|
285
|
+
color: Theme.color.background
|
|
286
|
+
opacity: root.groundOpacity
|
|
287
|
+
|
|
288
|
+
MouseArea {
|
|
289
|
+
anchors.fill: parent
|
|
290
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
291
|
+
hoverEnabled: true
|
|
292
|
+
onClicked: root.close()
|
|
293
|
+
onWheel: function (wheel) { wheel.accepted = true }
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// The resting card's body: the title, then the taller of the two columns of the key grid.
|
|
298
|
+
readonly property real restBodyHeight: {
|
|
299
|
+
var tall = 0
|
|
300
|
+
for (var c = 0; c < root.columnSlots.length; c++) {
|
|
301
|
+
var column = 0
|
|
302
|
+
for (var r = 0; r < root.columnSlots[c].length; r++)
|
|
303
|
+
column += root.columnSlots[c][r].heading.length > 0 ? root.headingPitch : root.rowPitch
|
|
304
|
+
tall = Math.max(tall, column)
|
|
305
|
+
}
|
|
306
|
+
return title.implicitHeight + Theme.spacing.gap + tall
|
|
307
|
+
}
|
|
308
|
+
readonly property real restCardHeight: Math.min(root.restBodyHeight + 2 * Theme.spacing.rowPaddingX, root.height - 2 * root.clampMargin)
|
|
309
|
+
|
|
310
|
+
Rectangle {
|
|
311
|
+
id: card
|
|
312
|
+
x: Theme.cardOrigin(root.width, width)
|
|
313
|
+
// The rest card centres, and a query grows or shrinks it from its bottom, so the title never moves.
|
|
314
|
+
y: Math.round((root.height - root.restCardHeight) / 2)
|
|
315
|
+
width: Theme.cardSpan(Theme.space(root.sheetWidth) * Theme.dialogWidthRatio, root.width - 2 * root.clampMargin)
|
|
316
|
+
// Clamped to the window below its top; the body scrolls whatever the clamp cut, see ui/CardScroll.qml.
|
|
317
|
+
height: Theme.cardSpan(body.wanted + 2 * Theme.spacing.rowPaddingX, root.height - card.y - root.clampMargin)
|
|
318
|
+
color: Theme.color.surface
|
|
319
|
+
border.width: Theme.spacing.hairline
|
|
320
|
+
border.color: Theme.color.mutedFrame
|
|
321
|
+
// Mirrors hyprland decoration:rounding, same as ui/ConvertDialog.qml; 0 on a stock box stays square.
|
|
322
|
+
radius: Style.cornerRadius
|
|
323
|
+
|
|
324
|
+
Flea.CardFrame {
|
|
325
|
+
id: body
|
|
326
|
+
anchors.fill: parent
|
|
327
|
+
anchors.topMargin: Theme.spacing.rowPaddingX
|
|
328
|
+
anchors.bottomMargin: Theme.spacing.rowPaddingX
|
|
329
|
+
anchors.leftMargin: card.border.width
|
|
330
|
+
anchors.rightMargin: card.border.width
|
|
331
|
+
|
|
332
|
+
// Rule 2: the one clause a reader needs, in the corner every other surface puts it in.
|
|
333
|
+
title: Item {
|
|
334
|
+
x: root.textInset
|
|
335
|
+
width: root.contentWidth
|
|
336
|
+
height: title.implicitHeight
|
|
337
|
+
|
|
338
|
+
Text {
|
|
339
|
+
id: title
|
|
340
|
+
anchors.left: parent.left
|
|
341
|
+
text: "Keys"
|
|
342
|
+
color: Theme.color.foreground
|
|
343
|
+
font.family: Theme.font.family
|
|
344
|
+
font.pixelSize: Theme.font.bodySmall
|
|
345
|
+
textFormat: Text.PlainText
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
Text {
|
|
349
|
+
anchors.right: parent.right
|
|
350
|
+
anchors.baseline: title.baseline
|
|
351
|
+
text: "esc closes"
|
|
352
|
+
color: Theme.color.muted
|
|
353
|
+
font.family: Theme.font.family
|
|
354
|
+
font.pixelSize: Theme.font.caption
|
|
355
|
+
textFormat: Text.PlainText
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
Column {
|
|
360
|
+
x: root.textInset
|
|
361
|
+
width: root.contentWidth
|
|
362
|
+
spacing: Theme.spacing.gap
|
|
363
|
+
|
|
364
|
+
// The query line, drawn only while one stands: a ? in the cap column, the query in a hairline accent field (decided 2026-10-03: no ring).
|
|
365
|
+
Item {
|
|
366
|
+
id: queryRow
|
|
367
|
+
width: parent.width
|
|
368
|
+
height: queryRow.visible ? queryBox.height : 0
|
|
369
|
+
visible: root.query.length > 0
|
|
370
|
+
|
|
371
|
+
Text {
|
|
372
|
+
anchors.left: parent.left
|
|
373
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
374
|
+
width: root.capWidth
|
|
375
|
+
horizontalAlignment: Text.AlignHCenter
|
|
376
|
+
text: "?"
|
|
377
|
+
color: Theme.color.muted
|
|
378
|
+
font.family: Theme.font.family
|
|
379
|
+
font.pixelSize: Theme.font.bodySmall
|
|
380
|
+
textFormat: Text.PlainText
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
Rectangle {
|
|
384
|
+
id: queryBox
|
|
385
|
+
anchors.left: parent.left
|
|
386
|
+
anchors.leftMargin: root.capWidth + root.capGap
|
|
387
|
+
anchors.right: parent.right
|
|
388
|
+
height: Theme.rowHeight - Theme.spacing.rowPaddingY
|
|
389
|
+
color: Theme.color.background
|
|
390
|
+
border.width: Theme.spacing.hairline
|
|
391
|
+
border.color: Theme.color.accent
|
|
392
|
+
|
|
393
|
+
TextInput {
|
|
394
|
+
id: queryLine
|
|
395
|
+
objectName: "keymapInput"
|
|
396
|
+
anchors.left: parent.left
|
|
397
|
+
anchors.right: parent.right
|
|
398
|
+
anchors.margins: Theme.spacing.gap
|
|
399
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
400
|
+
text: root.query
|
|
401
|
+
color: Theme.color.foreground
|
|
402
|
+
selectionColor: Theme.color.accent
|
|
403
|
+
selectedTextColor: Theme.color.background
|
|
404
|
+
font.family: Theme.font.family
|
|
405
|
+
font.pixelSize: Theme.font.body
|
|
406
|
+
selectByMouse: true
|
|
407
|
+
clip: true
|
|
408
|
+
onTextEdited: {
|
|
409
|
+
root.query = text
|
|
410
|
+
if (!text.length) keys.forceActiveFocus()
|
|
411
|
+
}
|
|
412
|
+
Keys.onPressed: function (event) {
|
|
413
|
+
if (event.key === Qt.Key_Escape) root.close()
|
|
414
|
+
else if (event.key === Qt.Key_Up || event.key === Qt.Key_Down)
|
|
415
|
+
root.resultCursor = SheetKeys.stepCursor(root.resultCursor,
|
|
416
|
+
event.key === Qt.Key_Up ? -1 : 1, root.queryResults.length)
|
|
417
|
+
else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter)
|
|
418
|
+
root.activateResult()
|
|
419
|
+
else return
|
|
420
|
+
event.accepted = true
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// The query results replace the key grid, one row per match with the run washed.
|
|
428
|
+
Column {
|
|
429
|
+
width: parent.width
|
|
430
|
+
visible: root.query.length > 0
|
|
431
|
+
Repeater {
|
|
432
|
+
id: resultRepeater
|
|
433
|
+
model: root.queryResults
|
|
434
|
+
delegate: Flea.KeymapSheetResult {
|
|
435
|
+
width: parent.width
|
|
436
|
+
resultCursor: root.resultCursor
|
|
437
|
+
query: root.query
|
|
438
|
+
capWidth: root.capWidth
|
|
439
|
+
capSize: root.capSize
|
|
440
|
+
capGap: root.capGap
|
|
441
|
+
rowPitch: root.rowPitch
|
|
442
|
+
textInset: root.textInset
|
|
443
|
+
whereShare: root.whereShare
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
Row {
|
|
448
|
+
visible: root.query.length === 0
|
|
449
|
+
spacing: Theme.spacing.rowPaddingX
|
|
450
|
+
|
|
451
|
+
Repeater {
|
|
452
|
+
model: root.columnSlots
|
|
453
|
+
|
|
454
|
+
// Equal halves, so the second column starts on one x the whole way down.
|
|
455
|
+
delegate: Column {
|
|
456
|
+
id: block
|
|
457
|
+
required property var modelData
|
|
458
|
+
width: (root.contentWidth - (root.columns - 1) * Theme.spacing.rowPaddingX) / root.columns
|
|
459
|
+
|
|
460
|
+
Repeater {
|
|
461
|
+
model: block.modelData
|
|
462
|
+
|
|
463
|
+
delegate: Item {
|
|
464
|
+
id: slot
|
|
465
|
+
required property var modelData
|
|
466
|
+
width: block.width
|
|
467
|
+
height: slot.modelData.heading.length > 0 ? root.headingPitch : root.rowPitch
|
|
468
|
+
// Nothing this cell draws may reach the cell beside it, whatever it holds.
|
|
469
|
+
clip: true
|
|
470
|
+
|
|
471
|
+
// A heading takes a row's own slot, so both columns keep one rhythm.
|
|
472
|
+
Text {
|
|
473
|
+
anchors.left: parent.left
|
|
474
|
+
anchors.bottom: parent.bottom
|
|
475
|
+
anchors.bottomMargin: Theme.spacing.hairline * 2
|
|
476
|
+
visible: slot.modelData.heading.length > 0
|
|
477
|
+
text: slot.modelData.heading
|
|
478
|
+
color: Theme.color.muted
|
|
479
|
+
font.family: Theme.font.family
|
|
480
|
+
font.pixelSize: Theme.font.caption
|
|
481
|
+
font.capitalization: Font.AllUppercase
|
|
482
|
+
font.letterSpacing: Theme.spacing.hairline
|
|
483
|
+
textFormat: Text.PlainText
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
Rectangle {
|
|
487
|
+
id: capBox
|
|
488
|
+
anchors.left: parent.left
|
|
489
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
490
|
+
visible: slot.modelData.row !== null
|
|
491
|
+
// The sheet's own cap column, never this row's text: see root.capWidth.
|
|
492
|
+
width: root.capWidth
|
|
493
|
+
height: root.capSize
|
|
494
|
+
color: "transparent"
|
|
495
|
+
border.width: Theme.spacing.hairline
|
|
496
|
+
border.color: Theme.color.mutedFrame
|
|
497
|
+
|
|
498
|
+
Text {
|
|
499
|
+
anchors.fill: parent
|
|
500
|
+
anchors.margins: Theme.spacing.hairline
|
|
501
|
+
horizontalAlignment: Text.AlignHCenter
|
|
502
|
+
verticalAlignment: Text.AlignVCenter
|
|
503
|
+
text: slot.modelData.row ? slot.modelData.row.keys : ""
|
|
504
|
+
color: Theme.color.foreground
|
|
505
|
+
font.family: Theme.font.family
|
|
506
|
+
font.pixelSize: Theme.font.caption
|
|
507
|
+
textFormat: Text.PlainText
|
|
508
|
+
elide: Text.ElideRight
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
Text {
|
|
513
|
+
anchors.left: capBox.right
|
|
514
|
+
anchors.leftMargin: root.capGap
|
|
515
|
+
anchors.right: parent.right
|
|
516
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
517
|
+
visible: slot.modelData.row !== null
|
|
518
|
+
text: slot.modelData.row ? slot.modelData.row.label : ""
|
|
519
|
+
// The wording is the sheet's own running text, so it takes the
|
|
520
|
+
// foreground the board draws it in; muted is for the headings.
|
|
521
|
+
color: Theme.color.foreground
|
|
522
|
+
font.family: Theme.font.family
|
|
523
|
+
font.pixelSize: Theme.font.caption
|
|
524
|
+
textFormat: Text.PlainText
|
|
525
|
+
elide: Text.ElideRight
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
Item {
|
|
537
|
+
id: keys
|
|
538
|
+
anchors.fill: parent
|
|
539
|
+
focus: true
|
|
540
|
+
|
|
541
|
+
// Esc closes the sheet from any state; every key answers through SheetKeys.sheetKey.
|
|
542
|
+
Keys.onPressed: function (event) {
|
|
543
|
+
var decision = SheetKeys.sheetKey(root.query, event.key, event.text)
|
|
544
|
+
if (decision === "up" || decision === "down") {
|
|
545
|
+
root.resultCursor = SheetKeys.stepCursor(root.resultCursor, decision === "up" ? -1 : 1, root.queryResults.length)
|
|
546
|
+
}
|
|
547
|
+
else if (decision === "activate") { root.activateResult() }
|
|
548
|
+
else if (decision === "backspace") { root.query = root.query.substring(0, root.query.length - 1) }
|
|
549
|
+
else if (decision === "type") {
|
|
550
|
+
if (root.query.length === 0)
|
|
551
|
+
root.ensureRecent()
|
|
552
|
+
root.query += event.text
|
|
553
|
+
queryLine.forceActiveFocus()
|
|
554
|
+
queryLine.cursorPosition = queryLine.text.length
|
|
555
|
+
}
|
|
556
|
+
else if (decision === "ignore") { event.accepted = true; return }
|
|
557
|
+
else { root.close() }
|
|
558
|
+
event.accepted = true
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/SheetQuery.js" as SheetQuery
|
|
5
|
+
|
|
6
|
+
// One result row of the keymap sheet's query: the cursor lift across the card's inner width, the cap, the label with its matched run washed, and the muted where.
|
|
7
|
+
Item {
|
|
8
|
+
id: hit
|
|
9
|
+
|
|
10
|
+
required property var modelData
|
|
11
|
+
required property int index
|
|
12
|
+
// What the sheet hands down, so a row owns no sheet state.
|
|
13
|
+
required property int resultCursor
|
|
14
|
+
required property string query
|
|
15
|
+
required property int capWidth
|
|
16
|
+
required property int capSize
|
|
17
|
+
required property int capGap
|
|
18
|
+
required property int rowPitch
|
|
19
|
+
required property real textInset
|
|
20
|
+
// The most of the label column the muted where may take, so a deep folder elides too and the name keeps the rest.
|
|
21
|
+
required property real whereShare
|
|
22
|
+
height: hit.rowPitch
|
|
23
|
+
// What a row has left of its width after the cap column.
|
|
24
|
+
readonly property real labelColumn: hit.width - hit.capWidth - hit.capGap
|
|
25
|
+
readonly property string whereText: String(hit.modelData.where || "")
|
|
26
|
+
// The muted where as drawn, "" when the row shows none, so a test reads the screen and not the model.
|
|
27
|
+
readonly property string whereShown: hitWhere.visible ? hitWhere.text : ""
|
|
28
|
+
// One match run per row per keystroke, read by the label's matched run below.
|
|
29
|
+
readonly property var match: SheetQuery.matchOf(hit.modelData.label, hit.query)
|
|
30
|
+
// The lift runs across the card's inner width, past the text's padding on both sides.
|
|
31
|
+
Rectangle {
|
|
32
|
+
x: -hit.textInset
|
|
33
|
+
width: hit.width + 2 * hit.textInset
|
|
34
|
+
height: parent.height
|
|
35
|
+
visible: hit.index === hit.resultCursor
|
|
36
|
+
color: Qt.alpha(Theme.color.foreground, Theme.washHover)
|
|
37
|
+
}
|
|
38
|
+
Rectangle {
|
|
39
|
+
id: hitCap
|
|
40
|
+
anchors.left: parent.left
|
|
41
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
42
|
+
width: hit.capWidth
|
|
43
|
+
height: hit.capSize
|
|
44
|
+
color: "transparent"
|
|
45
|
+
border.width: hit.modelData.keys.length > 0 ? Theme.spacing.hairline : 0
|
|
46
|
+
border.color: Qt.alpha(Theme.color.mutedFrame, hit.modelData.disabled === true ? Theme.disabledOpacity : 1)
|
|
47
|
+
Text {
|
|
48
|
+
anchors.fill: parent
|
|
49
|
+
anchors.margins: Theme.spacing.hairline
|
|
50
|
+
horizontalAlignment: Text.AlignHCenter
|
|
51
|
+
verticalAlignment: Text.AlignVCenter
|
|
52
|
+
text: hit.modelData.keys
|
|
53
|
+
color: hit.modelData.disabled === true ? Theme.color.muted : Theme.color.foreground
|
|
54
|
+
opacity: hit.modelData.disabled === true ? Theme.disabledOpacity : 1
|
|
55
|
+
font.family: Theme.font.family
|
|
56
|
+
font.pixelSize: Theme.font.caption
|
|
57
|
+
textFormat: Text.PlainText
|
|
58
|
+
elide: Text.ElideRight
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
Flea.MatchText {
|
|
62
|
+
id: hitLabel
|
|
63
|
+
anchors.left: hitCap.right
|
|
64
|
+
anchors.leftMargin: hit.capGap
|
|
65
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
66
|
+
width: Math.min(implicitWidth, hit.labelColumn - hitWhere.width)
|
|
67
|
+
text: hit.modelData.label
|
|
68
|
+
color: hit.modelData.disabled === true ? Theme.color.muted : Theme.color.foreground
|
|
69
|
+
opacity: hit.modelData.disabled === true ? Theme.disabledOpacity : 1
|
|
70
|
+
pixelSize: Theme.font.caption
|
|
71
|
+
matchStart: hit.match ? hit.match.start : -1
|
|
72
|
+
matchLength: hit.match ? hit.match.length : 0
|
|
73
|
+
}
|
|
74
|
+
// Where the result lives, muted and inline right after its name, as the board draws it; it keeps its width, so a long name elides instead.
|
|
75
|
+
Text {
|
|
76
|
+
id: hitWhere
|
|
77
|
+
anchors.left: hitLabel.right
|
|
78
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
79
|
+
width: hit.whereText.length > 0 ? Math.min(implicitWidth, hit.labelColumn * hit.whereShare) : 0
|
|
80
|
+
visible: hit.whereText.length > 0
|
|
81
|
+
text: hit.whereText.length > 0 ? " in " + hit.whereText : ""
|
|
82
|
+
color: Theme.color.muted
|
|
83
|
+
opacity: hit.modelData.disabled === true ? Theme.disabledOpacity : 1
|
|
84
|
+
font.family: Theme.font.family
|
|
85
|
+
font.pixelSize: Theme.font.caption
|
|
86
|
+
textFormat: Text.PlainText
|
|
87
|
+
elide: Text.ElideRight
|
|
88
|
+
}
|
|
89
|
+
}
|