flea-qml 0.0.0-stage → 0.1.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 +478 -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 +402 -0
- package/src/archiveops.js +697 -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 +129 -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/transfer.js +669 -0
- package/src/trash-record.js +41 -0
- package/src/trash.js +210 -0
- package/src/trashbrowse.js +326 -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 +241 -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-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-html-security.mjs +23 -0
- package/test/manual-html-ui.mjs +30 -0
- package/test/manual-syntax-preview.mjs +26 -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 +68 -0
- package/ui/ArchiveCompressDialog.qml +378 -0
- package/ui/ArchivePasswordDialog.qml +257 -0
- package/ui/Backend.qml +771 -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 +523 -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 +115 -0
- package/ui/Pane.qml +1296 -0
- package/ui/PaneMenuActions.qml +527 -0
- package/ui/PanePath.qml +90 -0
- package/ui/PaneRail.qml +239 -0
- package/ui/PaneStates.qml +88 -0
- package/ui/PaneSwap.qml +339 -0
- package/ui/PaneWire.qml +605 -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 +1004 -0
- package/ui/PreviewAnimation.qml +24 -0
- package/ui/PreviewArchive.qml +66 -0
- package/ui/PreviewColumn.qml +551 -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 +38 -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 +732 -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/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 +827 -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 +122 -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 +364 -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 +502 -0
- package/ui/js/FolderSorts.js +108 -0
- package/ui/js/FolderViews.js +44 -0
- package/ui/js/Format.js +305 -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 +736 -0
- package/ui/js/Tags.js +134 -0
- package/ui/js/Taildrop.js +128 -0
- package/ui/js/Tap.js +174 -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 +81 -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 +228 -0
package/ui/RowDrag.qml
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "js/Drag.js" as DragOps
|
|
3
|
+
import "js/DragOut.js" as DragOut
|
|
4
|
+
import "js/DropDev.js" as DropDev
|
|
5
|
+
import "js/Tabs.js" as Tabs
|
|
6
|
+
import "js/Search.js" as Search
|
|
7
|
+
|
|
8
|
+
// Delegate input and drop eligibility share a view-owned FileDrag; no platform object lives in this row.
|
|
9
|
+
Item {
|
|
10
|
+
id: root
|
|
11
|
+
|
|
12
|
+
required property var session
|
|
13
|
+
required property int listingIndex
|
|
14
|
+
required property var row
|
|
15
|
+
readonly property var pane: root.session.pane
|
|
16
|
+
// A peek column's session names the directory it shows and the pane whose collide sends its drops; null is the pane's own listing.
|
|
17
|
+
readonly property var dropScope: root.pane === null && root.session.peekSource ? root.session.peekSource : null
|
|
18
|
+
readonly property var targetPane: root.dropScope ? root.dropScope.pane : root.pane
|
|
19
|
+
readonly property string targetDir: root.dropScope ? root.dropScope.dir : (root.pane ? Search.baseOf(root.pane) : "")
|
|
20
|
+
|
|
21
|
+
// A listing row names its own device; a peek or carried column row names none, so the backend's answer for its path stands in, and an unanswered path is 0, which copies.
|
|
22
|
+
readonly property int destDev: !root.row ? 0 : root.row.v ? root.row.v
|
|
23
|
+
: (root.row.d === true && root.targetPane && root.targetPane.backend
|
|
24
|
+
? DropDev.devFor(root.targetPane.backend.pathDevs, root.targetPane.join(root.targetDir, root.row.n)) : 0)
|
|
25
|
+
// The answer landing while this folder is hovered re-says its line once, in the right verb.
|
|
26
|
+
onDestDevChanged: if (root.lit()) {
|
|
27
|
+
root.session.dropDestDev = root.destDev
|
|
28
|
+
root.session.showTarget(root.row.n, root.destDev)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// The drop destination this delegate last recorded on the session, kept so leaving clears only its own record.
|
|
32
|
+
property string recorded: ""
|
|
33
|
+
// False where the view answers drops from one shared area, so the row's own area stays disabled.
|
|
34
|
+
property bool dropsLocal: true
|
|
35
|
+
|
|
36
|
+
anchors.fill: parent
|
|
37
|
+
// A peek column's row lifts through the session's peekSource; which drops it takes is the DropArea's call alone.
|
|
38
|
+
enabled: !!root.row && (root.pane !== null ? !root.pane.listInFlight && root.listingIndex >= 0
|
|
39
|
+
: root.session.peekSource !== null)
|
|
40
|
+
|
|
41
|
+
DragHandler {
|
|
42
|
+
id: lift
|
|
43
|
+
enabled: root.pane === null || (!root.pane.renamePending && root.pane.renamingIndex !== root.listingIndex)
|
|
44
|
+
target: null
|
|
45
|
+
// Preserve List's grab contract: the Flickable must not take the row drag after its threshold.
|
|
46
|
+
grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByHandlersOfSameType
|
|
47
|
+
onActiveChanged: {
|
|
48
|
+
if (active && root.pane !== null) root.session.liftBegan(root.listingIndex, lift.centroid)
|
|
49
|
+
else if (active) root.session.liftPeek(root.row, lift.centroid)
|
|
50
|
+
else root.session.liftReleased()
|
|
51
|
+
}
|
|
52
|
+
onCentroidChanged: if (active) root.session.liftMoved(lift.centroid)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// The row's own area answers where dropsLocal holds; a view with one shared area leaves this one inert. No Loader stands in front of it: a Loader would add an object to every list row for a grid tile's saving.
|
|
56
|
+
DropArea {
|
|
57
|
+
anchors.fill: parent
|
|
58
|
+
// A peek row takes drops only as a folder, through its dropScope; without one it would aim the drop at the pane's own folder.
|
|
59
|
+
enabled: root.dropsLocal && (root.pane !== null || (root.dropScope !== null && !!root.row && root.row.d === true && root.targetPane !== null && !root.targetPane.listInFlight))
|
|
60
|
+
keys: [DragOps.ROWS_MIME, "text/uri-list", "text/plain"]
|
|
61
|
+
onEntered: function (drag) { root.enterAt(drag, drag) }
|
|
62
|
+
onPositionChanged: function (drag) { root.moveAt(drag) }
|
|
63
|
+
onExited: root.leaveRow()
|
|
64
|
+
onDropped: function (drop) { root.dropAt(drop) }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// A drop area's entrance, at a point in this row's own coordinates: the per-row area passes its drag, a shared one the mapped point.
|
|
68
|
+
function enterAt(drag, at) {
|
|
69
|
+
// xw6: a tab drag carries only the private tab type and is never a file drop.
|
|
70
|
+
if (drag.getDataAsString(Tabs.TAB_MIME) !== "") {
|
|
71
|
+
drag.accepted = false
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
drag.accepted = root.enter(drag.getDataAsString(DragOps.ROWS_MIME), drag.urls,
|
|
75
|
+
drag.getDataAsString(DragOps.SHELF_MIME),
|
|
76
|
+
drag.getDataAsString("text/plain"), drag.proposedAction,
|
|
77
|
+
drag.getDataAsString(DragOut.keys.liftMime))
|
|
78
|
+
root.hoverAt(at)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function moveAt(at) {
|
|
82
|
+
if (root.lit()) {
|
|
83
|
+
root.session.showTarget(root.row.n, root.destDev)
|
|
84
|
+
root.hoverAt(at)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function leaveAt() { root.leaveRow() }
|
|
89
|
+
|
|
90
|
+
function dropAt(drop) {
|
|
91
|
+
if (drop.getDataAsString(Tabs.TAB_MIME) !== "")
|
|
92
|
+
return
|
|
93
|
+
var marker = drop.getDataAsString(DragOps.ROWS_MIME)
|
|
94
|
+
var shelf = drop.getDataAsString(DragOps.SHELF_MIME)
|
|
95
|
+
var plain = drop.getDataAsString("text/plain")
|
|
96
|
+
if (root.refuseDrop(marker, drop.urls, shelf, plain)) return
|
|
97
|
+
if (root.dropped(marker, drop.urls, shelf, plain, drop.proposedAction)) {
|
|
98
|
+
drop.accept(Qt.CopyAction)
|
|
99
|
+
}
|
|
100
|
+
root.session.hoverEnded()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// The pointer leaves this delegate: the destination it recorded goes, even when a swap reused the delegate on another row, and a destination another row recorded since stays.
|
|
104
|
+
function leaveRow() {
|
|
105
|
+
if (root.recorded.length > 0 && root.session.dropDest === root.recorded) {
|
|
106
|
+
root.session.dropIndex = -1
|
|
107
|
+
root.session.dropDest = ""
|
|
108
|
+
root.session.dropDestDev = 0
|
|
109
|
+
root.session.leaveTarget()
|
|
110
|
+
}
|
|
111
|
+
root.recorded = ""
|
|
112
|
+
if (root.session.dragRows.length === 0) {
|
|
113
|
+
root.session.dragCopy = false
|
|
114
|
+
root.session.dragLink = false
|
|
115
|
+
}
|
|
116
|
+
root.session.hoverEnded()
|
|
117
|
+
DragOut.keys.leave()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// One reset for every finished gesture, refused or dropped: the drag's keys end and the row goes dark again.
|
|
121
|
+
function clearTarget() {
|
|
122
|
+
DragOut.keys.clear()
|
|
123
|
+
root.session.dropIndex = -1
|
|
124
|
+
root.session.dropDest = ""
|
|
125
|
+
root.session.dropDestDev = 0
|
|
126
|
+
root.session.dragCopy = false
|
|
127
|
+
root.session.dragLink = false
|
|
128
|
+
root.session.leaveTarget()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Testable entrance: a refused folder row stays dark and names its refusal, never lighting "move here" for a drop that cannot land.
|
|
132
|
+
function enter(marker, urls, shelf, plain, proposed, lift) {
|
|
133
|
+
if (!(root.row && root.row.d === true)) return false
|
|
134
|
+
var dest = root.targetPane.join(root.targetDir, root.row.n)
|
|
135
|
+
var line = ""
|
|
136
|
+
var ok = false
|
|
137
|
+
if (DragOps.hasPaths(urls) || (plain && !marker)) {
|
|
138
|
+
line = DragOut.refusal(DragOut.sources(urls, plain, marker, ""), dest, marker, "")
|
|
139
|
+
ok = line === "" && DragOps.canDropInto(marker, urls, dest, plain)
|
|
140
|
+
} else if (root.dropScope === null) {
|
|
141
|
+
ok = DragOps.canDropByIndex(marker, root.targetDir, root.session.dragRows, root.listingIndex)
|
|
142
|
+
}
|
|
143
|
+
if (!ok) {
|
|
144
|
+
if (line) root.targetPane.message(line, false)
|
|
145
|
+
return false
|
|
146
|
+
}
|
|
147
|
+
root.session.dropIndex = root.listingIndex
|
|
148
|
+
// The drop's own address: the swap may rebuild this delegate on another row before the release.
|
|
149
|
+
root.session.dropDest = dest
|
|
150
|
+
root.session.dropDestDev = root.destDev
|
|
151
|
+
root.recorded = dest
|
|
152
|
+
if (root.targetPane.columnsArea) root.targetPane.columnsArea.askDropDevs(lift)
|
|
153
|
+
DragOut.keys.enter(marker, lift)
|
|
154
|
+
root.session.enterTarget(marker, urls, root.row.n, root.destDev, shelf, proposed)
|
|
155
|
+
return true
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Lit means this delegate still shows the hovered folder: after a swap the index may name another row.
|
|
159
|
+
function lit() {
|
|
160
|
+
return root.session.dropIndex === root.listingIndex && !!root.row
|
|
161
|
+
&& root.session.dropDest === root.targetPane.join(root.targetDir, root.row.n)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Where a drop lands: the recorded hovered folder, else this row's own folder, since a swap may have reused the delegate.
|
|
165
|
+
function landing() {
|
|
166
|
+
if (root.session.dropDest.length > 0) return { dest: root.session.dropDest, dev: root.session.dropDestDev }
|
|
167
|
+
var folder = root.row && root.row.d === true
|
|
168
|
+
return { dest: folder ? root.targetPane.join(root.targetDir, root.row.n) : "", dev: folder ? root.destDev : 0 }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Testable refusal: says the sentence and darkens exactly like dropped(), so a refused
|
|
172
|
+
// drop never leaves the row lit (Qt sends dropped, not exited, after the drop).
|
|
173
|
+
function refuseDrop(marker, urls, shelf, plain) {
|
|
174
|
+
var dest = root.landing().dest
|
|
175
|
+
if (!dest) return ""
|
|
176
|
+
var line = DragOut.refusal(DragOut.sources(urls, plain, marker, shelf), dest, marker, shelf)
|
|
177
|
+
if (!line) return ""
|
|
178
|
+
root.targetPane.message(line, false)
|
|
179
|
+
root.clearTarget()
|
|
180
|
+
return line
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// The drop apart from its platform event, which tests/js/collide.js cannot build: answers whether it was taken.
|
|
184
|
+
function dropped(marker, urls, shelf, plain, proposed) {
|
|
185
|
+
var accepted = false
|
|
186
|
+
var at = root.landing()
|
|
187
|
+
if (at.dest.length > 0) {
|
|
188
|
+
if (DragOps.hasPaths(urls) || (plain && !marker && !shelf))
|
|
189
|
+
accepted = DragOps.dropInto(root.targetPane, marker, urls, at.dest, at.dev, shelf, plain, proposed, DragOut.keys.ctrl, DragOut.keys.shift)
|
|
190
|
+
else if (root.dropScope === null
|
|
191
|
+
&& DragOps.canDropByIndex(marker, root.targetDir, root.session.dragRows, root.listingIndex))
|
|
192
|
+
accepted = DragOps.dropByIndex(root.targetPane, root.session.dragRows, root.listingIndex,
|
|
193
|
+
root.session.verbAt(marker, root.row, DragOut.keys.ctrl, DragOut.keys.shift), root.session.dragListing)
|
|
194
|
+
}
|
|
195
|
+
root.clearTarget()
|
|
196
|
+
return accepted
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// In the view's own coordinates, so the band reads the listing, not the row.
|
|
200
|
+
function hoverAt(at) {
|
|
201
|
+
if (root.dropScope !== null || !at)
|
|
202
|
+
return
|
|
203
|
+
var viewer = root.session.pane
|
|
204
|
+
var list = viewer ? viewer.listArea : null
|
|
205
|
+
if (!list || !viewer || root.targetDir !== Search.baseOf(viewer))
|
|
206
|
+
return
|
|
207
|
+
var pt = root.mapToItem(list, at.x, at.y)
|
|
208
|
+
if (root.lit())
|
|
209
|
+
root.session.hoverBegan(root.listingIndex, root.targetPane.join(root.targetDir, root.row.n), pt.y, list.height)
|
|
210
|
+
else
|
|
211
|
+
root.session.hoverMoved(pt.y, list.height)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "js/Drag.js" as DragOps
|
|
3
|
+
|
|
4
|
+
// The file row's shared drop cue and clipboard mark, compiled only when either is drawn.
|
|
5
|
+
DropTarget {
|
|
6
|
+
id: root
|
|
7
|
+
|
|
8
|
+
required property var row
|
|
9
|
+
property alias mark: clipGlyph
|
|
10
|
+
anchors.fill: parent
|
|
11
|
+
shown: root.row.dropTarget
|
|
12
|
+
paintWidth: root.row.paintWidth
|
|
13
|
+
text: DragOps.label(root.row.dropCopying, root.row.dropLinking)
|
|
14
|
+
|
|
15
|
+
// A clipboard row under a drag keeps its mark beside the label, one pixel above the text centre line.
|
|
16
|
+
Glyph {
|
|
17
|
+
id: clipGlyph
|
|
18
|
+
visible: root.row.clipMark.length > 0 && !root.row.renaming && !root.row.searching
|
|
19
|
+
width: root.row.clipPx
|
|
20
|
+
height: root.row.clipPx
|
|
21
|
+
x: root.row.clipMark.length > 0 ? root.row.nameItem().x + Math.min(root.row.nameItem().implicitWidth, root.row.nameItem().width) + Theme.spacing.gap : 0
|
|
22
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
23
|
+
anchors.verticalCenterOffset: -1
|
|
24
|
+
name: root.row.clipMark
|
|
25
|
+
color: Theme.color.mutedFrame
|
|
26
|
+
}
|
|
27
|
+
}
|
package/ui/RunCard.qml
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import Quickshell
|
|
2
|
+
import Quickshell.Io
|
|
3
|
+
import QtQuick
|
|
4
|
+
import qs.Commons
|
|
5
|
+
import "." as Flea
|
|
6
|
+
import "js/RunFile.js" as RunFile
|
|
7
|
+
|
|
8
|
+
// Opening an executable file asks once, in this one card: Cancel, Open as text, Run and Run in terminal, with the ring on the default. An AppImage the desktop names a handler for offers that application first, by its own name, and focuses it instead.
|
|
9
|
+
FocusScope {
|
|
10
|
+
id: root
|
|
11
|
+
anchors.fill: parent
|
|
12
|
+
visible: opened || opacity > 0
|
|
13
|
+
// Closed means no input, even while the fade-out is still drawn.
|
|
14
|
+
enabled: opened
|
|
15
|
+
opacity: 0
|
|
16
|
+
property bool opened: false
|
|
17
|
+
property string path: ""
|
|
18
|
+
property string kind: "script"
|
|
19
|
+
property double size: 0
|
|
20
|
+
// The listed path the ask was opened from, which names the row; path names the resolved target it runs.
|
|
21
|
+
property string listedPath: ""
|
|
22
|
+
property bool hasHandler: false
|
|
23
|
+
property string handlerId: ""
|
|
24
|
+
property string handlerName: ""
|
|
25
|
+
// The mark the listing draws for the asked row, read once at open.
|
|
26
|
+
property string listedGlyph: ""
|
|
27
|
+
// dev and ino stay strings end to end: a double cannot hold every 64-bit value exactly.
|
|
28
|
+
property string dev: ""
|
|
29
|
+
property string ino: ""
|
|
30
|
+
property double mtimeS: 0
|
|
31
|
+
property double mtimeNs: 0
|
|
32
|
+
property string tweak: ""
|
|
33
|
+
property var pane: null
|
|
34
|
+
readonly property string fileName: RunFile.leafOf(root.path)
|
|
35
|
+
readonly property var buttons: RunFile.buttonsFor(root.kind, root.hasHandler)
|
|
36
|
+
// The board's own default: the handler where one is named, Run in terminal elsewhere.
|
|
37
|
+
readonly property string defaultName: RunFile.defaultButton(root.kind, root.hasHandler)
|
|
38
|
+
property string focusName: RunFile.START
|
|
39
|
+
// The card's own single-flight run lane, one per window: a second press while one runs is refused out loud, never queued.
|
|
40
|
+
property string runCurrent: ""
|
|
41
|
+
property string runAction: ""
|
|
42
|
+
readonly property int isDirectoryStatus: 3
|
|
43
|
+
// The run card's own failures, the same numbers src/runfile.rs answers with.
|
|
44
|
+
readonly property int runChangedStatus: 6
|
|
45
|
+
readonly property int runNoExecStatus: 7
|
|
46
|
+
readonly property int runSpawnStatus: 8
|
|
47
|
+
readonly property int runHandlerGoneStatus: 9
|
|
48
|
+
readonly property var cardItem: card
|
|
49
|
+
readonly property string titleText: title.text
|
|
50
|
+
readonly property bool buttonsFit: buttons.width <= body.holderWidth
|
|
51
|
+
function buttonItem(name) {
|
|
52
|
+
var at = root.buttons.indexOf(name)
|
|
53
|
+
return at >= 0 ? buttonRow.itemAt(at) : null
|
|
54
|
+
}
|
|
55
|
+
// One shot: the ask's raw text is parsed here so the card names the resolved target, and the next open re-derives the ring.
|
|
56
|
+
function open(info, pane) {
|
|
57
|
+
var ask = RunFile.parseAsk(info.raw || "")
|
|
58
|
+
if (ask === null) {
|
|
59
|
+
if (pane) pane.message("Flea could not check that file, so it was not run.", true)
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
root.pane = pane
|
|
63
|
+
root.path = ask.target
|
|
64
|
+
root.listedPath = info.path || ask.target
|
|
65
|
+
root.kind = ask.kind
|
|
66
|
+
root.size = ask.size
|
|
67
|
+
root.hasHandler = ask.hasHandler
|
|
68
|
+
root.handlerId = ask.handlerId
|
|
69
|
+
root.handlerName = ask.handlerName
|
|
70
|
+
root.listedGlyph = RunFile.listedGlyph(pane, root.listedPath)
|
|
71
|
+
root.dev = ask.dev
|
|
72
|
+
root.ino = ask.ino
|
|
73
|
+
root.mtimeS = ask.mtimeS
|
|
74
|
+
root.mtimeNs = ask.mtimeNs
|
|
75
|
+
root.tweak = info.tweak || ""
|
|
76
|
+
root.focusName = RunFile.startFocus(root.buttons, root.tweak)
|
|
77
|
+
body.contentY = 0
|
|
78
|
+
root.opened = true
|
|
79
|
+
root.forceActiveFocus()
|
|
80
|
+
}
|
|
81
|
+
// Closing hands the keyboard back to the asking pane, whatever closed it.
|
|
82
|
+
function close() {
|
|
83
|
+
root.opened = false
|
|
84
|
+
if (root.pane) root.pane.forceActiveFocus()
|
|
85
|
+
}
|
|
86
|
+
// A press lands on its own button first, so the accent never shows one choice while another is taken.
|
|
87
|
+
function press(choice) {
|
|
88
|
+
root.focusName = choice
|
|
89
|
+
root.choose(choice)
|
|
90
|
+
}
|
|
91
|
+
function launch(action, command, path) {
|
|
92
|
+
if (runChild.running) {
|
|
93
|
+
root.pane.message("Still running the last file; try again in a moment.", false)
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
root.runAction = action
|
|
97
|
+
root.runCurrent = path
|
|
98
|
+
runChild.command = command
|
|
99
|
+
runChild.running = true
|
|
100
|
+
}
|
|
101
|
+
// Sample argv: flea --run /home/gm/tool.sh <the card's identity>, never a shell string.
|
|
102
|
+
function run(path, dev, ino, size, mtimeS, mtimeNs) {
|
|
103
|
+
root.launch("run", [Quickshell.env("FLEA_BIN") || "flea", "--run", path, dev, ino, size, mtimeS, mtimeNs], path)
|
|
104
|
+
}
|
|
105
|
+
function runTerminal(path, dev, ino, size, mtimeS, mtimeNs) {
|
|
106
|
+
root.launch("terminal", [Quickshell.env("FLEA_BIN") || "flea", "--run-terminal", path, dev, ino, size, mtimeS, mtimeNs], path)
|
|
107
|
+
}
|
|
108
|
+
function openText(path, pane) {
|
|
109
|
+
if (pane) root.pane = pane
|
|
110
|
+
root.launch("text", [Quickshell.env("FLEA_BIN") || "flea", "--open-text", path], path)
|
|
111
|
+
}
|
|
112
|
+
// Sample argv: flea --open-handler /home/gm/app.AppImage appimagelauncher.desktop <the card's identity>.
|
|
113
|
+
function openHandler(path, id, dev, ino, size, mtimeS, mtimeNs) {
|
|
114
|
+
root.launch("handler", [Quickshell.env("FLEA_BIN") || "flea", "--open-handler", path, id, dev, ino, size, mtimeS, mtimeNs], path)
|
|
115
|
+
}
|
|
116
|
+
// The choice lands on the pane that asked, through ui/js/RunFile.js.
|
|
117
|
+
function choose(choice) {
|
|
118
|
+
root.close()
|
|
119
|
+
RunFile.choose(root.pane, root, choice)
|
|
120
|
+
}
|
|
121
|
+
// A held key never presses the default: repeats move nothing and run nothing.
|
|
122
|
+
function keyPressed(key, autoRepeat, modifiers) {
|
|
123
|
+
if (key === Qt.Key_Escape) { root.choose("cancel"); return }
|
|
124
|
+
if (modifiers & (Qt.ControlModifier | Qt.AltModifier | Qt.MetaModifier)) return
|
|
125
|
+
if (autoRepeat === true) return
|
|
126
|
+
if (RunFile.activates(key)) root.choose(root.focusName)
|
|
127
|
+
else root.focusName = RunFile.moved(root.buttons, root.focusName, key, modifiers)
|
|
128
|
+
if (root.opened) body.reveal(root.buttonItem(root.focusName))
|
|
129
|
+
}
|
|
130
|
+
Keys.onPressed: function (event) {
|
|
131
|
+
root.keyPressed(event.key, event.isAutoRepeat, event.modifiers)
|
|
132
|
+
event.accepted = true
|
|
133
|
+
}
|
|
134
|
+
Flea.Reveal { target: root; shown: root.opened; lift: card }
|
|
135
|
+
Process {
|
|
136
|
+
id: runChild
|
|
137
|
+
|
|
138
|
+
onExited: function (exitCode, exitStatus) {
|
|
139
|
+
var action = root.runAction
|
|
140
|
+
var path = root.runCurrent
|
|
141
|
+
root.runAction = ""
|
|
142
|
+
root.runCurrent = ""
|
|
143
|
+
if (exitCode === 0)
|
|
144
|
+
return
|
|
145
|
+
if (exitCode === root.isDirectoryStatus) {
|
|
146
|
+
root.pane.open(path)
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
if (exitCode === root.runChangedStatus) {
|
|
150
|
+
root.pane.message(action === "handler" ? "That file changed after Flea checked it, so it was not opened."
|
|
151
|
+
: "That file changed after Flea checked it, so it was not run.", true)
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
if (exitCode === root.runNoExecStatus) {
|
|
155
|
+
root.pane.message("That program is on a volume that does not allow running files.", true)
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
if (exitCode === root.runHandlerGoneStatus) {
|
|
159
|
+
root.pane.message("That application is no longer installed.", true)
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
if (exitCode === root.runSpawnStatus) {
|
|
163
|
+
if (action === "run")
|
|
164
|
+
root.pane.message("Nothing on this system could run that file.", true)
|
|
165
|
+
else if (action === "terminal")
|
|
166
|
+
root.pane.message("Nothing on this system could run that file in a terminal.", true)
|
|
167
|
+
else if (action === "handler")
|
|
168
|
+
root.pane.message("Nothing on this system could be asked to open that file.", true)
|
|
169
|
+
else
|
|
170
|
+
root.pane.message("Nothing on this system could open that file as text.", true)
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
if (action === "run")
|
|
174
|
+
root.pane.message("That program could not be run.", true)
|
|
175
|
+
else if (action === "terminal")
|
|
176
|
+
root.pane.message("That program could not be run in a terminal.", true)
|
|
177
|
+
else if (action === "handler")
|
|
178
|
+
root.pane.message("That application did not open the file.", true)
|
|
179
|
+
else
|
|
180
|
+
root.pane.message("No text editor opened that file.", true)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
Flea.DialogScrim {
|
|
184
|
+
onDismissed: root.choose("cancel")
|
|
185
|
+
}
|
|
186
|
+
Rectangle {
|
|
187
|
+
id: card
|
|
188
|
+
x: Theme.cardOrigin(root.width, width)
|
|
189
|
+
y: Theme.cardOrigin(root.height, height)
|
|
190
|
+
// The board's own 448, grown by the text size the way the collision card is.
|
|
191
|
+
width: Theme.cardSpan(card.contentWidth + 2 * card.cardPadding + 2 * Theme.spacing.hairline, root.width - 2 * Theme.spacing.gap)
|
|
192
|
+
height: Theme.cardSpan(body.wanted + card.cardPadding + card.cardBottomPadding + 2 * Theme.spacing.hairline, root.height - 2 * Theme.spacing.gap)
|
|
193
|
+
color: Theme.color.surface
|
|
194
|
+
border.color: Theme.color.mutedFrame
|
|
195
|
+
border.width: Theme.spacing.hairline
|
|
196
|
+
radius: Style.cornerRadius
|
|
197
|
+
readonly property real referenceScale: Theme.font.bodySmall / referenceBody
|
|
198
|
+
readonly property real cardPadding: Math.round(cardPad * referenceScale)
|
|
199
|
+
readonly property real cardBottomPadding: Math.round(cardBottomPad * referenceScale)
|
|
200
|
+
// RunFile's buttons keep 6 px of air over the gap.
|
|
201
|
+
readonly property real buttonsAir: Math.round(buttonsPad * referenceScale)
|
|
202
|
+
// The board's 414 content, since four buttons at DialogButton's pad and gap need 409.
|
|
203
|
+
readonly property real contentWidth: Math.max(card.boardContent, buttons.implicitWidth)
|
|
204
|
+
// The board's own reference size, pad and content width, so no bare number sits in an expression.
|
|
205
|
+
readonly property real referenceBody: 13
|
|
206
|
+
readonly property real cardPad: 16
|
|
207
|
+
readonly property real cardBottomPad: 12
|
|
208
|
+
readonly property real buttonsPad: 6
|
|
209
|
+
readonly property real contentBase: 414
|
|
210
|
+
readonly property real boardContent: Math.round(contentBase * referenceScale * Theme.dialogWidthRatio)
|
|
211
|
+
// The handler's name elides inside what the board's content leaves beside the other buttons, so a long name never widens the card.
|
|
212
|
+
readonly property real handlerRoom: {
|
|
213
|
+
var used = 0
|
|
214
|
+
for (var i = 0; i < buttonRow.count; i++) {
|
|
215
|
+
var item = buttonRow.itemAt(i)
|
|
216
|
+
if (item && item.modelData !== "handler") used += item.implicitWidth + buttons.spacing
|
|
217
|
+
}
|
|
218
|
+
return Math.max(Theme.hitMin, card.boardContent - used - 2 * Theme.spacing.gap - 2 * Theme.spacing.hairline)
|
|
219
|
+
}
|
|
220
|
+
TextMetrics {
|
|
221
|
+
id: handlerLabel
|
|
222
|
+
font.family: Theme.font.family
|
|
223
|
+
font.pixelSize: Theme.font.body
|
|
224
|
+
elide: Text.ElideRight
|
|
225
|
+
elideWidth: card.handlerRoom
|
|
226
|
+
text: root.handlerName
|
|
227
|
+
}
|
|
228
|
+
MouseArea {
|
|
229
|
+
anchors.fill: parent
|
|
230
|
+
hoverEnabled: true
|
|
231
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
232
|
+
onWheel: function (wheel) { wheel.accepted = true }
|
|
233
|
+
}
|
|
234
|
+
Flea.CardFrame {
|
|
235
|
+
id: body
|
|
236
|
+
bleed: Theme.focusClearance
|
|
237
|
+
anchors.fill: parent
|
|
238
|
+
anchors.leftMargin: card.cardPadding + Theme.spacing.hairline - Theme.focusClearance
|
|
239
|
+
anchors.rightMargin: card.cardPadding + Theme.spacing.hairline - Theme.focusClearance
|
|
240
|
+
anchors.topMargin: card.cardPadding + Theme.spacing.hairline - Theme.focusClearance
|
|
241
|
+
anchors.bottomMargin: card.cardBottomPadding + Theme.spacing.hairline - Theme.focusClearance
|
|
242
|
+
title: Flea.DialogHeader {
|
|
243
|
+
id: title
|
|
244
|
+
width: parent.width
|
|
245
|
+
text: RunFile.titleFor(root.fileName)
|
|
246
|
+
}
|
|
247
|
+
buttons: Row {
|
|
248
|
+
id: buttons
|
|
249
|
+
anchors.right: parent.right
|
|
250
|
+
topPadding: card.buttonsAir
|
|
251
|
+
spacing: Theme.spacing.gap
|
|
252
|
+
Repeater {
|
|
253
|
+
id: buttonRow
|
|
254
|
+
model: root.buttons
|
|
255
|
+
Flea.DialogButton {
|
|
256
|
+
required property string modelData
|
|
257
|
+
label: RunFile.labelFor(modelData, handlerLabel.elidedText) || modelData
|
|
258
|
+
primary: modelData === root.defaultName
|
|
259
|
+
focused: root.focusName === modelData
|
|
260
|
+
onActivated: root.press(modelData)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
Row {
|
|
265
|
+
width: parent.width
|
|
266
|
+
height: Theme.fileRowHeight
|
|
267
|
+
spacing: Theme.spacing.gap
|
|
268
|
+
Flea.Glyph {
|
|
269
|
+
width: Theme.markSize
|
|
270
|
+
height: parent.height
|
|
271
|
+
name: RunFile.glyphFor(root.kind, root.listedGlyph)
|
|
272
|
+
color: Theme.color.foreground
|
|
273
|
+
}
|
|
274
|
+
Text {
|
|
275
|
+
width: Math.max(0, parent.width - Theme.markSize - parent.spacing)
|
|
276
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
277
|
+
text: RunFile.subtitleFor(root.kind, root.size)
|
|
278
|
+
textFormat: Text.PlainText
|
|
279
|
+
elide: Text.ElideRight
|
|
280
|
+
color: Theme.color.foreground
|
|
281
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
package/ui/Scripts.qml
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
pragma Singleton
|
|
2
|
+
import QtQuick
|
|
3
|
+
import Quickshell
|
|
4
|
+
import Quickshell.Io
|
|
5
|
+
import "js/Scripts.js" as Model
|
|
6
|
+
|
|
7
|
+
// MenuAdditions rule 2: the scripts a menu can run, read out of ~/.config/flea/scripts when a menu
|
|
8
|
+
// opens rather than watched, and run with the selected paths as arguments in the first one's folder.
|
|
9
|
+
// The one thing here that touches the outside world, the way ui/NetworkMounts.qml is for gio.
|
|
10
|
+
Item {
|
|
11
|
+
id: root
|
|
12
|
+
|
|
13
|
+
// [{ id, label, path }], sorted by name, the label the file name without its extension.
|
|
14
|
+
property var entries: []
|
|
15
|
+
property bool loaded: false
|
|
16
|
+
readonly property string directory: (Quickshell.env("XDG_CONFIG_HOME") && Quickshell.env("XDG_CONFIG_HOME").length > 0
|
|
17
|
+
? Quickshell.env("XDG_CONFIG_HOME") : Quickshell.env("HOME") + "/.config") + "/flea/scripts"
|
|
18
|
+
|
|
19
|
+
signal said(string text, bool isError)
|
|
20
|
+
|
|
21
|
+
function refresh() {
|
|
22
|
+
if (!lister.running)
|
|
23
|
+
lister.running = true
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function run(id, paths) {
|
|
27
|
+
var script = ""
|
|
28
|
+
for (var i = 0; i < root.entries.length; i++)
|
|
29
|
+
if (root.entries[i].id === id) script = root.entries[i].path
|
|
30
|
+
if (script.length === 0 || paths.length === 0) {
|
|
31
|
+
root.said("That script is no longer there.", true)
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
runner.script = script
|
|
35
|
+
runner.workingDirectory = paths[0].substring(0, paths[0].lastIndexOf("/")) || "/"
|
|
36
|
+
runner.command = [script].concat(paths)
|
|
37
|
+
runner.running = true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// An executable regular file, one level down and nothing else: a directory of scripts is a flat
|
|
41
|
+
// one, and -perm -u+x is the owner bit the board names.
|
|
42
|
+
Process {
|
|
43
|
+
id: lister
|
|
44
|
+
command: ["find", root.directory, "-maxdepth", "1", "-type", "f", "-perm", "-u+x", "-printf", "%f\\n"]
|
|
45
|
+
stdout: StdioCollector {
|
|
46
|
+
waitForEnd: true
|
|
47
|
+
onStreamFinished: {
|
|
48
|
+
root.entries = Model.parse(text, root.directory)
|
|
49
|
+
root.loaded = true
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// A script's own last stderr line is the report, elided to one sentence by the status centre.
|
|
55
|
+
Process {
|
|
56
|
+
id: runner
|
|
57
|
+
property string script: ""
|
|
58
|
+
stderr: StdioCollector { waitForEnd: true }
|
|
59
|
+
onExited: function (code, status) {
|
|
60
|
+
if (code === 0)
|
|
61
|
+
return
|
|
62
|
+
root.said(Model.failure(runner.script.substring(runner.script.lastIndexOf("/") + 1), runner.stderr.text, code), true)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|