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/CsvTable.qml
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
pragma ComponentBehavior: Bound
|
|
2
|
+
|
|
3
|
+
import QtQuick
|
|
4
|
+
import qs.Commons
|
|
5
|
+
import "js/Csv.js" as Csv
|
|
6
|
+
import "." as Flea
|
|
7
|
+
|
|
8
|
+
// CSV or TSV as a sticky table, with raw line windows aligned to whole records by the backend.
|
|
9
|
+
Item {
|
|
10
|
+
id: root
|
|
11
|
+
|
|
12
|
+
property var backend: null
|
|
13
|
+
property string slot: "column"
|
|
14
|
+
property string path: ""
|
|
15
|
+
// true sends the bytes in `text` (null until the caller has read them) instead of the path.
|
|
16
|
+
property bool fromText: false
|
|
17
|
+
property var text: null
|
|
18
|
+
property bool active: false
|
|
19
|
+
// Quick Look's grid: row numbers, each column its widest cell plus the row padding, and both axes scroll.
|
|
20
|
+
property bool look: false
|
|
21
|
+
property int limit: 0
|
|
22
|
+
// Screens asked past the view on each side.
|
|
23
|
+
property int margin: 1
|
|
24
|
+
property int pixelSize: Theme.font.caption
|
|
25
|
+
readonly property int lineCap: 400 // The most lines one ask names (docs/protocol.md "code"); a longer window is asked in parts.
|
|
26
|
+
|
|
27
|
+
readonly property string delim: Csv.delimiter(root.path)
|
|
28
|
+
readonly property bool engine: root.backend !== null && typeof root.backend.askCode === "function"
|
|
29
|
+
// The board draws its table at caption 12; its pixel values scale with the caption, as the board sizes in Theme.qml do.
|
|
30
|
+
readonly property real boardScale: root.pixelSize / 12
|
|
31
|
+
// Board: the column's rows sit 12 px in from the frame on each side.
|
|
32
|
+
readonly property int columnEdge: Math.round(12 * root.boardScale)
|
|
33
|
+
// Board: 6 px between the column's cells.
|
|
34
|
+
readonly property int columnGap: Math.round(6 * root.boardScale)
|
|
35
|
+
// Board: Quick Look's row numbers fill a 42 px column.
|
|
36
|
+
readonly property int numberWidth: Math.round(42 * root.boardScale)
|
|
37
|
+
// Board: 3 px above and below each column row and its header.
|
|
38
|
+
readonly property int columnPadY: Math.round(3 * root.boardScale)
|
|
39
|
+
// Board: 6 px above and below each Quick Look row.
|
|
40
|
+
readonly property int gridPadY: Math.round(6 * root.boardScale)
|
|
41
|
+
// Board: 8 px above and below the Quick Look header.
|
|
42
|
+
readonly property int gridHeadPadY: Math.round(8 * root.boardScale)
|
|
43
|
+
readonly property int edge: root.look ? Theme.spacing.rowPaddingX : root.columnEdge
|
|
44
|
+
readonly property int bodyPadY: root.look ? root.gridPadY : root.columnPadY
|
|
45
|
+
readonly property int headPadY: root.look ? root.gridHeadPadY : root.columnPadY
|
|
46
|
+
// The table rule of ui/PreviewMarkdown.qml, drawn under the header.
|
|
47
|
+
readonly property real ruleOpacity: 0.12
|
|
48
|
+
readonly property real rowHeight: bodyMetrics.height + 2 * root.bodyPadY
|
|
49
|
+
readonly property real headHeight: headMetrics.height + 2 * root.headPadY + Theme.spacing.hairline
|
|
50
|
+
|
|
51
|
+
// "" until the first screen is answered, then styled, plain, binary, large or failed.
|
|
52
|
+
property string answer: ""
|
|
53
|
+
property int total: 0
|
|
54
|
+
property int records: 0
|
|
55
|
+
// The held physical lines, each {t: text}, with record: ordinal at every reply start; stamp counts changes to it.
|
|
56
|
+
property var held: ({})
|
|
57
|
+
property int stamp: 0
|
|
58
|
+
// The token of the ask in flight, 0 when none: an answer for any other token is dropped.
|
|
59
|
+
property int token: 0
|
|
60
|
+
property bool retiring: false
|
|
61
|
+
// The last record of the first screen, so the first screen is known whole before the table is drawn.
|
|
62
|
+
property int firstTo: 0
|
|
63
|
+
// The table as held: the header cells, the body rows and the column count.
|
|
64
|
+
property var table: ({ header: null, rows: [], byLine: ({}), byRecord: ({}), cols: 0, open: [] })
|
|
65
|
+
// Widths and alignments are measured on the first screen and only extended after it, so no column moves under the reader.
|
|
66
|
+
property bool frozen: false
|
|
67
|
+
property var heads: []
|
|
68
|
+
property var widths: []
|
|
69
|
+
property var rights: []
|
|
70
|
+
|
|
71
|
+
readonly property bool settled: root.answer === "styled" || root.answer === "plain"
|
|
72
|
+
readonly property int shown: root.limit > 0 ? Math.min(root.records, root.limit) : root.records
|
|
73
|
+
readonly property bool firstReady: root.settled && root.covered(1, Math.min(root.shown, root.firstTo))
|
|
74
|
+
&& Csv.ready(root.table, Math.min(root.shown, root.firstTo))
|
|
75
|
+
readonly property bool firstScreen: root.firstReady && (root.look
|
|
76
|
+
|| (root.covered(root.needed().from, root.needed().to) && Csv.ready(root.table, root.needed().to)))
|
|
77
|
+
visible: root.firstReady
|
|
78
|
+
// The scroll view the wheel, the bars and the Quick Look reader read.
|
|
79
|
+
readonly property var list: view
|
|
80
|
+
readonly property alias viewport: view
|
|
81
|
+
// One delegate per data record; continuation lines never take a row or a number.
|
|
82
|
+
readonly property int bodyRows: Csv.dataRows(root.shown)
|
|
83
|
+
// The plain text of the lines drawn, for the readers that check what is on screen.
|
|
84
|
+
readonly property var lines: {
|
|
85
|
+
root.stamp
|
|
86
|
+
var out = []
|
|
87
|
+
var tail = root.table.byRecord[root.shown]
|
|
88
|
+
var last = root.limit > 0 && root.shown > 1 ? (tail ? tail.line + tail.span - 1 : 0) : root.total
|
|
89
|
+
for (var i = 1; i <= last; i++)
|
|
90
|
+
out.push(root.held[i] ? root.held[i].t : "")
|
|
91
|
+
return out
|
|
92
|
+
}
|
|
93
|
+
readonly property var layout: root.look ? Csv.grid(root.widths, root.rights, root.numberWidth, Theme.spacing.rowPaddingX)
|
|
94
|
+
: Csv.fit(root.widths, root.heads, root.rights, root.columnGap, view.width - 2 * root.edge)
|
|
95
|
+
readonly property real contentEnd: root.layout.length > 0 ? root.layout[root.layout.length - 1].x + root.layout[root.layout.length - 1].w : 0
|
|
96
|
+
// Quick Look's grid is at least the frame wide and as wide as its boxes; a column keeps the frame's width.
|
|
97
|
+
readonly property real gridWidth: root.look ? Math.max(view.width, root.contentEnd) : view.width
|
|
98
|
+
|
|
99
|
+
FontMetrics {
|
|
100
|
+
id: bodyMetrics
|
|
101
|
+
font.family: Theme.font.family
|
|
102
|
+
font.pixelSize: root.pixelSize
|
|
103
|
+
}
|
|
104
|
+
FontMetrics {
|
|
105
|
+
id: headMetrics
|
|
106
|
+
font.family: Theme.font.family
|
|
107
|
+
font.pixelSize: root.pixelSize
|
|
108
|
+
font.bold: true
|
|
109
|
+
}
|
|
110
|
+
// Digits in a numeric cell draw with tabular figures, so they are measured the same way.
|
|
111
|
+
FontMetrics {
|
|
112
|
+
id: figureMetrics
|
|
113
|
+
font.family: Theme.font.family
|
|
114
|
+
font.pixelSize: root.pixelSize
|
|
115
|
+
font.features: ({ "tnum": 1 })
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// The width of column c: its widest header or body cell, the header in bold.
|
|
119
|
+
function naturalWidth(grid, c) {
|
|
120
|
+
var px = headMetrics.advanceWidth(String(grid[0][c] || ""))
|
|
121
|
+
for (var r = 1; r < grid.length; r++) {
|
|
122
|
+
var cell = String(grid[r][c] || "")
|
|
123
|
+
px = Math.max(px, (Csv.isNumber(cell) ? figureMetrics : bodyMetrics).advanceWidth(cell))
|
|
124
|
+
}
|
|
125
|
+
return Math.ceil(px)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Re-reads the held table, and measures each column it has not measured yet; nothing is measured again once the first screen is whole.
|
|
129
|
+
function refresh(parsed) {
|
|
130
|
+
var t = parsed || Csv.table(root.held, root.total, root.delim)
|
|
131
|
+
root.table = t
|
|
132
|
+
if (t.header === null || (root.frozen && root.widths.length >= t.cols))
|
|
133
|
+
return
|
|
134
|
+
var measured = root.frozen ? t.rows : t.rows.filter(function (rec) { return rec.record <= root.firstTo })
|
|
135
|
+
var grid = [t.header].concat(measured.map(function (rec) { return rec.cells }))
|
|
136
|
+
var align = Csv.numericColumns(grid, t.cols)
|
|
137
|
+
var heads = root.frozen ? root.heads.slice() : []
|
|
138
|
+
var widths = root.frozen ? root.widths.slice() : []
|
|
139
|
+
var rights = root.frozen ? root.rights.slice() : []
|
|
140
|
+
for (var c = widths.length; c < t.cols; c++) {
|
|
141
|
+
heads.push(Math.ceil(headMetrics.advanceWidth(String(t.header[c] || ""))))
|
|
142
|
+
widths.push(root.naturalWidth(grid, c))
|
|
143
|
+
rights.push(align[c])
|
|
144
|
+
}
|
|
145
|
+
if (!root.frozen && root.covered(1, Math.min(root.shown, root.firstTo)) && Csv.ready(t, Math.min(root.shown, root.firstTo)))
|
|
146
|
+
root.frozen = true
|
|
147
|
+
root.heads = heads
|
|
148
|
+
root.widths = widths
|
|
149
|
+
root.rights = rights
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// The record ordinals the view needs, with the margin, file and limit bounds; ordinal 1 is the header.
|
|
153
|
+
function needed() {
|
|
154
|
+
var rows = Math.max(1, Math.ceil(view.height / Math.max(1, root.rowHeight)))
|
|
155
|
+
// ListView rounds fractional row heights, so its delegate index names the record even on a far jump.
|
|
156
|
+
var top = view.contentHeight > 0 ? Math.max(0, view.indexAt(0, view.contentY + 1)) + 2 : 2
|
|
157
|
+
var to = top + rows * (1 + root.margin) - 1
|
|
158
|
+
if (root.limit > 0)
|
|
159
|
+
to = Math.min(to, root.limit)
|
|
160
|
+
if (root.settled)
|
|
161
|
+
to = Math.min(to, root.records)
|
|
162
|
+
var from = root.rowAt(1) ? Math.max(2, top - rows * root.margin) : 1
|
|
163
|
+
return { from: from, to: to }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function rowAt(n) {
|
|
167
|
+
return root.stamp >= 0 ? (n === 1 ? root.table.header : root.table.byRecord[n]) : undefined
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function covered(from, to) {
|
|
171
|
+
for (var i = from; i <= to; i++)
|
|
172
|
+
if (!root.rowAt(i))
|
|
173
|
+
return false
|
|
174
|
+
return true
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function reset() {
|
|
178
|
+
root.held = {}
|
|
179
|
+
root.stamp += 1
|
|
180
|
+
root.total = 0
|
|
181
|
+
root.records = 0
|
|
182
|
+
root.answer = ""
|
|
183
|
+
root.token = 0
|
|
184
|
+
root.firstTo = 0
|
|
185
|
+
root.frozen = false
|
|
186
|
+
root.heads = []
|
|
187
|
+
root.widths = []
|
|
188
|
+
root.rights = []
|
|
189
|
+
root.table = { header: null, rows: [], byLine: ({}), byRecord: ({}), cols: 0, open: [] }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Starts a view of a new file or text; the first ask waits for the end of the turn so one change of several properties asks once.
|
|
193
|
+
function fresh() {
|
|
194
|
+
root.reset()
|
|
195
|
+
if (!root.active)
|
|
196
|
+
return
|
|
197
|
+
if (!root.engine && root.fromText && root.text !== null)
|
|
198
|
+
root.answerPlain()
|
|
199
|
+
else
|
|
200
|
+
Qt.callLater(root.ask)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Lines of the caller's own text, drawn plain when no backend can ask for them.
|
|
204
|
+
function answerPlain() {
|
|
205
|
+
var rows = Csv.plainLines(root.text)
|
|
206
|
+
var held = {}
|
|
207
|
+
for (var i = 0; i < rows.length; i++)
|
|
208
|
+
held[i + 1] = { t: rows[i] }
|
|
209
|
+
root.held = held
|
|
210
|
+
root.total = rows.length
|
|
211
|
+
var parsed = Csv.table(held, root.total, root.delim)
|
|
212
|
+
root.records = parsed.rows.length + (parsed.header !== null ? 1 : 0)
|
|
213
|
+
root.answer = "plain"
|
|
214
|
+
root.firstTo = root.needed().to
|
|
215
|
+
root.refresh(parsed)
|
|
216
|
+
root.stamp += 1
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function ask() {
|
|
220
|
+
if (root.retiring || !root.active || !root.engine || view.height <= 0)
|
|
221
|
+
return
|
|
222
|
+
if (root.answer === "binary" || root.answer === "large" || root.answer === "failed")
|
|
223
|
+
return
|
|
224
|
+
if (root.fromText && root.text === null)
|
|
225
|
+
return
|
|
226
|
+
if (root.fromText && root.text.length === 0) {
|
|
227
|
+
root.answerPlain()
|
|
228
|
+
return
|
|
229
|
+
}
|
|
230
|
+
if (!root.fromText && root.path.length === 0)
|
|
231
|
+
return
|
|
232
|
+
if (root.token !== 0)
|
|
233
|
+
return
|
|
234
|
+
var want = root.needed()
|
|
235
|
+
if (want.to < want.from || (root.settled && root.covered(want.from, want.to)))
|
|
236
|
+
return
|
|
237
|
+
var from = want.from
|
|
238
|
+
while (from <= want.to && root.rowAt(from))
|
|
239
|
+
from += 1
|
|
240
|
+
if (root.firstTo === 0)
|
|
241
|
+
root.firstTo = want.to
|
|
242
|
+
// raw sends the lines plain: a table is never coloured as code.
|
|
243
|
+
var source = root.fromText ? { text: root.text, name: root.path.split("/").pop(), lang: "", raw: true, csv: root.delim, record: from } : { path: root.path, raw: true, csv: root.delim, record: from }
|
|
244
|
+
root.token = root.backend.askCode(root.slot, source, from, Math.min(root.lineCap, want.to - from + 1))
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function answered(message) {
|
|
248
|
+
if (root.token === 0 || message.token !== root.token)
|
|
249
|
+
return
|
|
250
|
+
root.token = 0
|
|
251
|
+
if (!root.settled || message.state === "binary" || message.state === "large" || message.state === "failed")
|
|
252
|
+
root.answer = message.state
|
|
253
|
+
root.total = message.total || 0
|
|
254
|
+
root.records = message.records || 0
|
|
255
|
+
var rows = message.lines || []
|
|
256
|
+
for (var i = 0; i < rows.length; i++)
|
|
257
|
+
root.held[message.first + i] = { t: rows[i].length > 0 ? rows[i][1] : "" }
|
|
258
|
+
if (rows.length > 0)
|
|
259
|
+
root.held[message.first].record = message.firstRecord
|
|
260
|
+
root.refresh()
|
|
261
|
+
root.stamp += 1
|
|
262
|
+
// Binary, large and failed are the file's whole answer: nothing more is asked of it until the view starts a new one.
|
|
263
|
+
if (root.settled)
|
|
264
|
+
Qt.callLater(root.ask)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
onPathChanged: root.fresh()
|
|
268
|
+
onTextChanged: root.fresh()
|
|
269
|
+
onFromTextChanged: root.fresh()
|
|
270
|
+
onActiveChanged: root.fresh()
|
|
271
|
+
Component.onDestruction: root.retiring = true
|
|
272
|
+
onLimitChanged: Qt.callLater(root.ask)
|
|
273
|
+
|
|
274
|
+
Connections {
|
|
275
|
+
target: root.engine ? root.backend : null
|
|
276
|
+
function onCodeResult(message) { root.answered(message) }
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// The header, sticky above the rows; in Quick Look it moves sideways with the grid and stays at the top.
|
|
280
|
+
Item {
|
|
281
|
+
id: head
|
|
282
|
+
anchors.top: parent.top
|
|
283
|
+
anchors.left: parent.left
|
|
284
|
+
anchors.right: parent.right
|
|
285
|
+
height: root.headHeight
|
|
286
|
+
visible: root.table.header !== null
|
|
287
|
+
clip: true
|
|
288
|
+
|
|
289
|
+
Item {
|
|
290
|
+
x: root.look ? -view.contentX : 0
|
|
291
|
+
width: root.gridWidth
|
|
292
|
+
height: parent.height
|
|
293
|
+
|
|
294
|
+
Repeater {
|
|
295
|
+
model: root.table.header !== null ? root.layout.length : 0
|
|
296
|
+
delegate: Text {
|
|
297
|
+
required property int index
|
|
298
|
+
// A reset clears the layout before old delegates are destroyed.
|
|
299
|
+
readonly property var place: root.layout[index] || { x: 0, w: 0, right: false }
|
|
300
|
+
x: root.look ? place.x + Theme.spacing.rowPaddingX : root.edge + place.x
|
|
301
|
+
width: root.look ? Math.max(0, place.w - 2 * Theme.spacing.rowPaddingX) : place.w
|
|
302
|
+
y: root.headPadY
|
|
303
|
+
text: Csv.oneLine(root.table.header !== null ? root.table.header[index] || "" : "")
|
|
304
|
+
horizontalAlignment: place.right ? Text.AlignRight : Text.AlignLeft
|
|
305
|
+
elide: Text.ElideRight
|
|
306
|
+
color: Theme.color.foregroundBright
|
|
307
|
+
font.family: Theme.font.family
|
|
308
|
+
font.pixelSize: root.pixelSize
|
|
309
|
+
font.bold: true
|
|
310
|
+
textFormat: Text.PlainText
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
Rectangle {
|
|
316
|
+
anchors.bottom: parent.bottom
|
|
317
|
+
anchors.left: parent.left
|
|
318
|
+
anchors.right: parent.right
|
|
319
|
+
height: Theme.spacing.hairline
|
|
320
|
+
color: Theme.color.foreground
|
|
321
|
+
opacity: root.ruleOpacity
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
ListView {
|
|
326
|
+
id: view
|
|
327
|
+
anchors.top: head.bottom
|
|
328
|
+
anchors.left: parent.left
|
|
329
|
+
anchors.right: parent.right
|
|
330
|
+
anchors.bottom: parent.bottom
|
|
331
|
+
clip: true
|
|
332
|
+
interactive: true
|
|
333
|
+
flickableDirection: Flickable.HorizontalAndVerticalFlick
|
|
334
|
+
boundsBehavior: Flickable.StopAtBounds
|
|
335
|
+
model: root.bodyRows
|
|
336
|
+
contentWidth: root.gridWidth
|
|
337
|
+
onContentYChanged: Qt.callLater(root.ask)
|
|
338
|
+
onHeightChanged: Qt.callLater(root.ask)
|
|
339
|
+
|
|
340
|
+
delegate: Item {
|
|
341
|
+
id: row
|
|
342
|
+
required property int index
|
|
343
|
+
// A held record occupies exactly one delegate at its ordinal.
|
|
344
|
+
readonly property var rec: root.table.byRecord[index + 2] || null
|
|
345
|
+
width: root.gridWidth
|
|
346
|
+
height: root.rowHeight
|
|
347
|
+
|
|
348
|
+
Text {
|
|
349
|
+
visible: root.look && row.rec !== null
|
|
350
|
+
x: 0
|
|
351
|
+
width: root.numberWidth - Theme.spacing.rowPaddingX
|
|
352
|
+
y: root.bodyPadY
|
|
353
|
+
text: row.rec !== null ? String(Csv.rowNumber(row.rec.record)) : ""
|
|
354
|
+
horizontalAlignment: Text.AlignRight
|
|
355
|
+
color: Theme.color.muted
|
|
356
|
+
font.family: Theme.font.family
|
|
357
|
+
font.pixelSize: root.pixelSize
|
|
358
|
+
font.features: ({ "tnum": 1 })
|
|
359
|
+
textFormat: Text.PlainText
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
Repeater {
|
|
363
|
+
model: row.rec !== null ? root.layout.length : 0
|
|
364
|
+
delegate: Text {
|
|
365
|
+
required property int index
|
|
366
|
+
// A reset may clear the record before its old cells are destroyed.
|
|
367
|
+
readonly property var place: root.layout[index] || { x: 0, w: 0, right: false }
|
|
368
|
+
readonly property string cell: Csv.oneLine(row.rec !== null ? row.rec.cells[index] || "" : "")
|
|
369
|
+
x: root.look ? place.x + Theme.spacing.rowPaddingX : root.edge + place.x
|
|
370
|
+
width: root.look ? Math.max(0, place.w - 2 * Theme.spacing.rowPaddingX) : place.w
|
|
371
|
+
y: root.bodyPadY
|
|
372
|
+
text: cell
|
|
373
|
+
horizontalAlignment: place.right ? Text.AlignRight : Text.AlignLeft
|
|
374
|
+
elide: Text.ElideRight
|
|
375
|
+
color: Theme.color.foreground
|
|
376
|
+
font.family: Theme.font.family
|
|
377
|
+
font.pixelSize: root.pixelSize
|
|
378
|
+
font.features: Csv.isNumber(cell) ? ({ "tnum": 1 }) : ({})
|
|
379
|
+
textFormat: Text.PlainText
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
Flea.FastScrollHandler {
|
|
386
|
+
visible: root.look
|
|
387
|
+
flickable: view
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
Flea.ViewportScrollBars {
|
|
391
|
+
visible: root.look
|
|
392
|
+
flickable: view
|
|
393
|
+
}
|
|
394
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
|
|
3
|
+
// Each delegate files itself here by listing row, so a cursor move relights only the delegate it leaves and the one it reaches.
|
|
4
|
+
QtObject {
|
|
5
|
+
id: root
|
|
6
|
+
|
|
7
|
+
// The listing row the cursor is on; -1 lights none.
|
|
8
|
+
property int row: -1
|
|
9
|
+
// Listing row to the delegate filed under it, changed in place and read only here.
|
|
10
|
+
readonly property var cells: new Map()
|
|
11
|
+
// The delegate drawn as the cursor, null while no delegate holds the cursor row.
|
|
12
|
+
property Item lit: null
|
|
13
|
+
|
|
14
|
+
onRowChanged: {
|
|
15
|
+
var cell = root.row >= 0 ? root.cells.get(root.row) : undefined
|
|
16
|
+
// A delegate destroyed without parking first reads no markRow back, so its stale entry goes here.
|
|
17
|
+
if (cell !== undefined && cell.markRow !== root.row) { root.cells.delete(root.row); cell = undefined }
|
|
18
|
+
root.light(cell === undefined ? null : cell)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// A delegate calls this when built and whenever its listing row changes; a parked one reads -1 and files nowhere.
|
|
22
|
+
function place(cell) {
|
|
23
|
+
var from = cell.markRow
|
|
24
|
+
var to = cell.listingIndex
|
|
25
|
+
if (from >= 0 && root.cells.get(from) === cell) root.cells.delete(from)
|
|
26
|
+
cell.markRow = to
|
|
27
|
+
if (to >= 0) root.cells.set(to, cell)
|
|
28
|
+
if (to >= 0 && to === root.row) {
|
|
29
|
+
root.light(cell)
|
|
30
|
+
} else {
|
|
31
|
+
cell.cursor = false
|
|
32
|
+
if (root.lit === cell) root.lit = null
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function light(cell) {
|
|
37
|
+
if (root.lit !== null && root.lit !== cell) root.lit.cursor = false
|
|
38
|
+
root.lit = cell
|
|
39
|
+
if (cell !== null) cell.cursor = true
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
pragma Singleton
|
|
2
|
+
import QtQuick
|
|
3
|
+
import Quickshell
|
|
4
|
+
import Quickshell.Io
|
|
5
|
+
import "js/MakeDefault.js" as MakeDefault
|
|
6
|
+
|
|
7
|
+
// Settings > About's Make Flea the default, shared by every window: the handler xdg-mime answers, whether this build has a desktop entry, `flea --default [off]` and the portal restart after it; ui/js/MakeDefault.js holds the states and the words.
|
|
8
|
+
QtObject {
|
|
9
|
+
id: root
|
|
10
|
+
|
|
11
|
+
readonly property string binary: Quickshell.env("FLEA_BIN") || "flea"
|
|
12
|
+
// The one answer the File manager row states and the box is ticked by.
|
|
13
|
+
property string handler: ""
|
|
14
|
+
property var claim: MakeDefault.idle()
|
|
15
|
+
// Handler reads are numbered as they start, so a run is settled only by a read begun after it exited.
|
|
16
|
+
property int reads: 0
|
|
17
|
+
// True from a read's start until its exit and its text are both in, which is when the next may start.
|
|
18
|
+
property bool readBusy: false
|
|
19
|
+
// A run that exited during another window's read asks for one more behind it, since a running Process is not restarted.
|
|
20
|
+
property bool readAgain: false
|
|
21
|
+
// Each process's exit code and collector text, filled in whichever order they land.
|
|
22
|
+
property var readAnswer: ({})
|
|
23
|
+
property var runAnswer: ({})
|
|
24
|
+
// What the run asked for, so a flea that never starts is named in the note.
|
|
25
|
+
property var runCommand: []
|
|
26
|
+
|
|
27
|
+
// About opening: the handler, and whether there is an entry for flea --default to point at.
|
|
28
|
+
function read() {
|
|
29
|
+
root.startRead()
|
|
30
|
+
prober.command = MakeDefault.probeCommand(MakeDefault.entryPaths({
|
|
31
|
+
HOME: Quickshell.env("HOME") || "",
|
|
32
|
+
XDG_DATA_HOME: Quickshell.env("XDG_DATA_HOME") || "",
|
|
33
|
+
XDG_DATA_DIRS: Quickshell.env("XDG_DATA_DIRS") || ""
|
|
34
|
+
}))
|
|
35
|
+
prober.running = true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Enter, Space or a click on the row; a press during a run, or on a build with no entry, does nothing.
|
|
39
|
+
function toggle() {
|
|
40
|
+
var args = MakeDefault.press(root.handler, root.claim)
|
|
41
|
+
if (args === null || runner.running)
|
|
42
|
+
return
|
|
43
|
+
root.claim = MakeDefault.started(root.claim, args)
|
|
44
|
+
root.runAnswer = ({})
|
|
45
|
+
root.runCommand = [root.binary].concat(args)
|
|
46
|
+
runner.command = root.runCommand
|
|
47
|
+
runner.running = true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// False when a read is already in flight, whose answer may predate whatever the caller is waiting on.
|
|
51
|
+
function startRead() {
|
|
52
|
+
if (root.readBusy)
|
|
53
|
+
return false
|
|
54
|
+
root.readBusy = true
|
|
55
|
+
root.reads += 1
|
|
56
|
+
root.readAnswer = ({})
|
|
57
|
+
reader.running = true
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// A half landing after the answer is whole, a stream ending behind a program that never ran, is ignored.
|
|
62
|
+
function readLanded(half) {
|
|
63
|
+
if (MakeDefault.whole(root.readAnswer))
|
|
64
|
+
return
|
|
65
|
+
root.readAnswer = MakeDefault.landed(root.readAnswer, half)
|
|
66
|
+
if (!MakeDefault.whole(root.readAnswer))
|
|
67
|
+
return
|
|
68
|
+
root.readBusy = false
|
|
69
|
+
root.handler = MakeDefault.handlerOf(root.readAnswer)
|
|
70
|
+
root.claim = MakeDefault.settled(root.claim, root.reads)
|
|
71
|
+
if (root.readAgain) {
|
|
72
|
+
root.readAgain = false
|
|
73
|
+
root.startRead()
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function runLanded(half) {
|
|
78
|
+
if (MakeDefault.whole(root.runAnswer))
|
|
79
|
+
return
|
|
80
|
+
root.runAnswer = MakeDefault.landed(root.runAnswer, half)
|
|
81
|
+
if (!MakeDefault.whole(root.runAnswer))
|
|
82
|
+
return
|
|
83
|
+
// The next read to start is the first that can see what this run wrote.
|
|
84
|
+
root.claim = MakeDefault.finished(root.claim, root.runAnswer.code, root.runAnswer.text, root.reads + 1)
|
|
85
|
+
if (!root.startRead())
|
|
86
|
+
root.readAgain = true
|
|
87
|
+
if (root.claim.restarting)
|
|
88
|
+
restarter.running = true
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
property var readQuery: Process {
|
|
92
|
+
id: reader
|
|
93
|
+
command: ["xdg-mime", "query", "default", "inode/directory"]
|
|
94
|
+
// Sample output: com.thisisgm.flea.desktop
|
|
95
|
+
stdout: StdioCollector { waitForEnd: true; onStreamFinished: root.readLanded({ text: this.text }) }
|
|
96
|
+
onExited: function (code) { root.readLanded({ code: code }) }
|
|
97
|
+
// An xdg-mime that cannot start raises no exited, so the read ends here, stating no handler.
|
|
98
|
+
onRunningChanged: {
|
|
99
|
+
if (MakeDefault.neverRan(root.readAnswer, reader.running))
|
|
100
|
+
root.readLanded(MakeDefault.NEVER_RAN)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
property var probeQuery: Process {
|
|
105
|
+
id: prober
|
|
106
|
+
onExited: function (code) { root.claim = MakeDefault.probed(root.claim, code === 0) }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Asynchronous like every Process, so the window keeps drawing while flea rewrites the four files.
|
|
110
|
+
property var runQuery: Process {
|
|
111
|
+
id: runner
|
|
112
|
+
stderr: StdioCollector { waitForEnd: true; onStreamFinished: root.runLanded({ text: this.text }) }
|
|
113
|
+
onExited: function (code) { root.runLanded({ code: code }) }
|
|
114
|
+
// A flea that cannot start wrote nothing, so there is nothing to read again and no portal to restart.
|
|
115
|
+
onRunningChanged: {
|
|
116
|
+
if (MakeDefault.neverRan(root.runAnswer, runner.running)) {
|
|
117
|
+
root.runAnswer = MakeDefault.landed(root.runAnswer, MakeDefault.NEVER_RAN)
|
|
118
|
+
root.claim = MakeDefault.unstarted(root.claim, root.runCommand)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Only this switch restarts the portal; flea --default on a command line prints the hint instead.
|
|
124
|
+
property var restartQuery: Process {
|
|
125
|
+
id: restarter
|
|
126
|
+
command: MakeDefault.RESTART
|
|
127
|
+
onExited: function (code) { root.claim = MakeDefault.restarted(root.claim, code === 0) }
|
|
128
|
+
onRunningChanged: root.claim = MakeDefault.restartStopped(root.claim, restarter.running)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import Quickshell.Io
|
|
3
|
+
import "js/Unlock.js" as Unlock
|
|
4
|
+
|
|
5
|
+
// U039: the udisksctl lock after releasing an unlocked crypt; a refusal names the drive.
|
|
6
|
+
Item {
|
|
7
|
+
id: root
|
|
8
|
+
// The DeviceMounts that posts the refusal and re-polls once the lock has settled.
|
|
9
|
+
property var host: null
|
|
10
|
+
property string _label: ""
|
|
11
|
+
// Locks waiting while one runs, each keeping its own backing container and label.
|
|
12
|
+
property var _queue: []
|
|
13
|
+
|
|
14
|
+
// Answers whether a lock started: only a crypt leaf has a backing container, so no caller checks the kind first.
|
|
15
|
+
function lockCryptAfter(listing, cryptDevice, label) {
|
|
16
|
+
var backing = Unlock.backingFor(String(listing || ""), String(cryptDevice || ""))
|
|
17
|
+
if (backing.length === 0)
|
|
18
|
+
return false
|
|
19
|
+
if (lockProcess.running) {
|
|
20
|
+
root._queue = root._queue.concat([{ backing: backing, label: label }])
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
23
|
+
root._label = label
|
|
24
|
+
lockProcess.command = ["udisksctl", "lock", "--block-device", backing]
|
|
25
|
+
lockProcess.running = true
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Process {
|
|
30
|
+
id: lockProcess
|
|
31
|
+
onExited: function (exitCode) {
|
|
32
|
+
var label = root._label
|
|
33
|
+
root._label = ""
|
|
34
|
+
if (exitCode !== 0)
|
|
35
|
+
root.host.message(Unlock.lockNote(label), true)
|
|
36
|
+
if (root._queue.length > 0) {
|
|
37
|
+
var next = root._queue[0]
|
|
38
|
+
root._queue = root._queue.slice(1)
|
|
39
|
+
root._label = next.label
|
|
40
|
+
lockProcess.command = ["udisksctl", "lock", "--block-device", next.backing]
|
|
41
|
+
lockProcess.running = true
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
root.host.poll()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|