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
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Convert.js" as Convert
|
|
5
|
+
import "js/Format.js" as Format
|
|
6
|
+
|
|
7
|
+
// The one popup in the whole design. Every other operation answers in the status bar; this one asks two questions first, so it is the exception the operations design names rather than a pattern.
|
|
8
|
+
Item {
|
|
9
|
+
id: root
|
|
10
|
+
|
|
11
|
+
property bool opened: false
|
|
12
|
+
// The card's title, for ui/Ipc.qml: a driven click on it proves the card swallows what its controls do not.
|
|
13
|
+
readonly property alias titleItem: title
|
|
14
|
+
property string name: ""
|
|
15
|
+
property Item focusHolder: null
|
|
16
|
+
property var owner: null
|
|
17
|
+
property var source: null
|
|
18
|
+
property int serial: 0
|
|
19
|
+
property int requestId: 0
|
|
20
|
+
property int operationId: 0
|
|
21
|
+
property bool checking: false
|
|
22
|
+
property bool checkAgain: false
|
|
23
|
+
property bool busy: false
|
|
24
|
+
property bool unavailable: false
|
|
25
|
+
property bool collision: false
|
|
26
|
+
property string errorText: ""
|
|
27
|
+
property int focusPart: 0
|
|
28
|
+
|
|
29
|
+
// The format row that starts picked is never the one the file already is.
|
|
30
|
+
property string format: ""
|
|
31
|
+
property bool strip: false
|
|
32
|
+
property int cursor: 0
|
|
33
|
+
// Where a row or the ground last saw the pointer, -1 since opening, so a row built under a resting pointer never takes the cursor.
|
|
34
|
+
property point pointerGlobal: Qt.point(-1, -1)
|
|
35
|
+
|
|
36
|
+
signal accepted(var source, string format, bool strip, int requestId)
|
|
37
|
+
|
|
38
|
+
// The card title, filled by Format.fill.
|
|
39
|
+
readonly property string titleWord: "Convert %1"
|
|
40
|
+
readonly property var formats: Convert.FORMATS
|
|
41
|
+
readonly property string outputPath: root.source ? Convert.destination(root.source, root.format) : ""
|
|
42
|
+
readonly property bool editable: !root.busy && !root.unavailable
|
|
43
|
+
readonly property bool canConvert: root.opened && root.editable && !root.checking && !root.collision && !root.errorText
|
|
44
|
+
readonly property var cancelItem: cancelButton
|
|
45
|
+
readonly property var submitItem: convertButton
|
|
46
|
+
readonly property var metadataItem: metadata
|
|
47
|
+
readonly property var outputItem: output
|
|
48
|
+
readonly property var bodyItem: body
|
|
49
|
+
function formatItem(index) { return formatRows.itemAt(index) }
|
|
50
|
+
// What each row prints. The canvas draws JPEG, WebP and AVIF, which is neither the extension
|
|
51
|
+
// nor a plain upper-casing of it, so the wording is a table and not a rule.
|
|
52
|
+
readonly property var formatLabels: ({
|
|
53
|
+
jpg: "JPEG", png: "PNG", webp: "WebP", avif: "AVIF", heic: "HEIC", tiff: "TIFF", bmp: "BMP"
|
|
54
|
+
})
|
|
55
|
+
// The canvas draws this popup at 300 design pixels wide.
|
|
56
|
+
readonly property int dialogWidth: 300
|
|
57
|
+
readonly property int clampMargin: 8
|
|
58
|
+
// var, not Item: BorderSurface is a qs.Ui type qmllint cannot resolve, and Item would read as incompatible.
|
|
59
|
+
readonly property var cardItem: card
|
|
60
|
+
|
|
61
|
+
anchors.fill: parent
|
|
62
|
+
visible: root.opened || root.opacity > 0
|
|
63
|
+
// Closed means no input, even while the fade-out is still drawn.
|
|
64
|
+
enabled: root.opened
|
|
65
|
+
opacity: 0
|
|
66
|
+
z: 2
|
|
67
|
+
|
|
68
|
+
Flea.Reveal { target: root; shown: root.opened; lift: card }
|
|
69
|
+
|
|
70
|
+
// A codec this box converts to but the canvas does not name still needs a cap, so upper-casing
|
|
71
|
+
// the extension is the fallback rather than an empty row.
|
|
72
|
+
function formatLabel(id) {
|
|
73
|
+
var text = root.formatLabels[id]
|
|
74
|
+
return text !== undefined ? text : String(id).toUpperCase()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function open(rowName, holder) {
|
|
78
|
+
if (root.opened || !holder || !holder.convertSource) return
|
|
79
|
+
root.owner = holder
|
|
80
|
+
root.source = Object.assign({}, holder.convertSource)
|
|
81
|
+
root.name = root.source.name
|
|
82
|
+
root.format = Convert.defaultFormat(root.name)
|
|
83
|
+
root.strip = false
|
|
84
|
+
root.cursor = root.formats.indexOf(root.format)
|
|
85
|
+
root.pointerGlobal = Qt.point(-1, -1)
|
|
86
|
+
root.focusHolder = holder.listArea
|
|
87
|
+
root.errorText = ""
|
|
88
|
+
root.collision = false
|
|
89
|
+
root.busy = false
|
|
90
|
+
root.unavailable = false
|
|
91
|
+
root.checking = false
|
|
92
|
+
root.checkAgain = false
|
|
93
|
+
root.focusPart = 0
|
|
94
|
+
root.opened = true
|
|
95
|
+
body.contentY = 0
|
|
96
|
+
root.formatItem(root.cursor).forceActiveFocus()
|
|
97
|
+
root.probe()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function close() {
|
|
101
|
+
if (!root.opened || root.busy)
|
|
102
|
+
return
|
|
103
|
+
root.opened = false
|
|
104
|
+
if (root.focusHolder)
|
|
105
|
+
root.focusHolder.forceActiveFocus()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function commit() {
|
|
109
|
+
if (!root.canConvert) return
|
|
110
|
+
keys.forceActiveFocus()
|
|
111
|
+
root.busy = true
|
|
112
|
+
root.operationId = 0
|
|
113
|
+
root.requestId = ++root.serial
|
|
114
|
+
root.accepted(root.source, root.format, root.strip, root.requestId)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function probe() {
|
|
118
|
+
if (!root.opened || !root.editable) return
|
|
119
|
+
if (root.checking) { root.checkAgain = true; return }
|
|
120
|
+
root.checking = true
|
|
121
|
+
root.errorText = ""
|
|
122
|
+
root.collision = false
|
|
123
|
+
root.requestId = ++root.serial
|
|
124
|
+
root.owner.backend.convertImage(root.source.path, root.outputPath, root.strip, root.source.menuId, root.requestId, true)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function chooseFormat(index) {
|
|
128
|
+
if (!root.editable) return
|
|
129
|
+
root.focusPart = 0
|
|
130
|
+
root.cursor = Math.max(0, Math.min(root.formats.length - 1, index))
|
|
131
|
+
var next = root.formats[root.cursor]
|
|
132
|
+
if (root.format !== next || root.errorText) {
|
|
133
|
+
root.format = next
|
|
134
|
+
root.probe()
|
|
135
|
+
}
|
|
136
|
+
body.reveal(root.formatItem(root.cursor))
|
|
137
|
+
root.formatItem(root.cursor).forceActiveFocus()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function stepFocus(back) {
|
|
141
|
+
if (root.busy) { keys.forceActiveFocus(); return }
|
|
142
|
+
var parts = root.unavailable ? [2] : root.canConvert ? [0, 1, 2, 3] : [0, 1, 2]
|
|
143
|
+
var at = parts.indexOf(root.focusPart)
|
|
144
|
+
root.focusPart = parts[(at + (back ? parts.length - 1 : 1)) % parts.length]
|
|
145
|
+
var item = [root.formatItem(root.cursor), metadata, cancelButton, convertButton][root.focusPart]
|
|
146
|
+
item.forceActiveFocus()
|
|
147
|
+
body.reveal(item)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
Connections {
|
|
151
|
+
target: root.owner ? root.owner.backend : null
|
|
152
|
+
function onConvertChecked(message) {
|
|
153
|
+
if (!root.opened || root.unavailable || !Convert.matchesReply(root.source, root.requestId, message)) return
|
|
154
|
+
root.checking = false
|
|
155
|
+
if (root.checkAgain || message.path !== root.outputPath) { root.checkAgain = false; root.probe(); return }
|
|
156
|
+
root.collision = message.collision === true
|
|
157
|
+
root.errorText = message.ok && !root.collision ? "" : message.error
|
|
158
|
+
}
|
|
159
|
+
function onConvertStarted(id, requestId, source) {
|
|
160
|
+
if (root.busy && Convert.matchesReply(root.source, root.requestId, {requestId: requestId, source: source}))
|
|
161
|
+
root.operationId = id
|
|
162
|
+
}
|
|
163
|
+
function onConvertDone(id, ok, path, err, requestId, source, collision) {
|
|
164
|
+
if (!root.opened || !root.busy || !Convert.matchesReply(root.source, root.requestId, {requestId: requestId, source: source})
|
|
165
|
+
|| (root.operationId ? id !== root.operationId : ok)) return
|
|
166
|
+
root.busy = false
|
|
167
|
+
root.collision = collision
|
|
168
|
+
root.errorText = err
|
|
169
|
+
if (ok) root.close()
|
|
170
|
+
else root.formatItem(root.cursor).forceActiveFocus()
|
|
171
|
+
}
|
|
172
|
+
function onFailed(where, input, message, mode) {
|
|
173
|
+
if (!root.opened || root.unavailable || (where !== "backend" && where !== "read")) return
|
|
174
|
+
var pending = root.busy
|
|
175
|
+
root.unavailable = true
|
|
176
|
+
root.busy = false
|
|
177
|
+
root.checking = false
|
|
178
|
+
root.checkAgain = false
|
|
179
|
+
root.focusPart = 2
|
|
180
|
+
cancelButton.forceActiveFocus()
|
|
181
|
+
root.errorText = pending
|
|
182
|
+
? "Flea stopped responding, so the conversion may not have finished. Check the converted file."
|
|
183
|
+
: "Flea stopped responding. Reopen Flea, then convert again."
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// A dimmed ground, and a click on it is a cancel, the same shape the network dialog already uses.
|
|
188
|
+
Rectangle {
|
|
189
|
+
anchors.fill: parent
|
|
190
|
+
color: Theme.color.background
|
|
191
|
+
opacity: 0.5
|
|
192
|
+
|
|
193
|
+
MouseArea {
|
|
194
|
+
id: ground
|
|
195
|
+
anchors.fill: parent
|
|
196
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
197
|
+
hoverEnabled: true
|
|
198
|
+
onEntered: root.pointerGlobal = ground.mapToItem(null, ground.mouseX, ground.mouseY)
|
|
199
|
+
onPositionChanged: function (mouse) { root.pointerGlobal = ground.mapToItem(null, mouse.x, mouse.y) }
|
|
200
|
+
onClicked: root.close()
|
|
201
|
+
onWheel: function (wheel) { wheel.accepted = true }
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
Rectangle {
|
|
206
|
+
id: card
|
|
207
|
+
x: Theme.cardOrigin(root.width, width)
|
|
208
|
+
y: Theme.cardOrigin(root.height, height)
|
|
209
|
+
width: Theme.cardSpan(Theme.space(root.dialogWidth) * Theme.dialogWidthRatio, root.width - 2 * root.clampMargin)
|
|
210
|
+
// Clamped to the window; the body scrolls whatever the clamp cut, see ui/CardScroll.qml.
|
|
211
|
+
height: Theme.cardSpan(body.wanted + 2 * Theme.spacing.rowPaddingX, root.height - 2 * root.clampMargin)
|
|
212
|
+
color: Theme.color.surface
|
|
213
|
+
border.width: Theme.spacing.hairline
|
|
214
|
+
border.color: Theme.color.mutedFrame
|
|
215
|
+
radius: Style.cornerRadius
|
|
216
|
+
|
|
217
|
+
// The strip toggle's handler takes a passive grab, so without this sink its press fell
|
|
218
|
+
// through the card to the ground below, which closed the dialog on release.
|
|
219
|
+
MouseArea {
|
|
220
|
+
id: cardSink
|
|
221
|
+
anchors.fill: parent
|
|
222
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
223
|
+
hoverEnabled: true
|
|
224
|
+
onEntered: root.pointerGlobal = cardSink.mapToItem(null, cardSink.mouseX, cardSink.mouseY)
|
|
225
|
+
onPositionChanged: function (mouse) { root.pointerGlobal = cardSink.mapToItem(null, mouse.x, mouse.y) }
|
|
226
|
+
onClicked: {}
|
|
227
|
+
onWheel: function (wheel) { wheel.accepted = true }
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
Flea.CardFrame {
|
|
231
|
+
id: body
|
|
232
|
+
bleedY: Theme.focusClearance
|
|
233
|
+
anchors.fill: parent
|
|
234
|
+
anchors.topMargin: Theme.spacing.rowPaddingX - Theme.focusClearance
|
|
235
|
+
anchors.bottomMargin: Theme.spacing.rowPaddingX - Theme.focusClearance
|
|
236
|
+
spacing: Theme.spacing.gap / 2
|
|
237
|
+
|
|
238
|
+
title: Item {
|
|
239
|
+
id: title
|
|
240
|
+
width: parent.width
|
|
241
|
+
height: header.implicitHeight + Theme.spacing.gap
|
|
242
|
+
|
|
243
|
+
Flea.DialogTitle {
|
|
244
|
+
id: header
|
|
245
|
+
anchors.left: parent.left
|
|
246
|
+
anchors.right: parent.right
|
|
247
|
+
anchors.margins: Theme.spacing.rowPaddingX
|
|
248
|
+
text: Format.fill(root.titleWord, root.name)
|
|
249
|
+
elide: Text.ElideMiddle
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
Rectangle {
|
|
253
|
+
anchors.bottom: parent.bottom
|
|
254
|
+
width: parent.width
|
|
255
|
+
height: Theme.spacing.hairline
|
|
256
|
+
color: Theme.color.mutedFrame
|
|
257
|
+
opacity: 0.4
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
buttons: Item {
|
|
262
|
+
width: parent.width
|
|
263
|
+
height: Theme.spacing.gap + Math.max(cancelButton.implicitHeight, convertButton.implicitHeight)
|
|
264
|
+
Row {
|
|
265
|
+
anchors.bottom: parent.bottom
|
|
266
|
+
anchors.right: parent.right
|
|
267
|
+
anchors.rightMargin: Theme.spacing.rowPaddingX
|
|
268
|
+
spacing: Theme.spacing.gap
|
|
269
|
+
|
|
270
|
+
Flea.DialogButton {
|
|
271
|
+
id: cancelButton
|
|
272
|
+
label: "Cancel"
|
|
273
|
+
focused: root.focusPart === 2
|
|
274
|
+
available: !root.busy
|
|
275
|
+
enabled: available
|
|
276
|
+
Keys.forwardTo: [keys]
|
|
277
|
+
onActivated: root.close()
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
Flea.DialogButton {
|
|
281
|
+
id: convertButton
|
|
282
|
+
label: "Convert"
|
|
283
|
+
primary: true
|
|
284
|
+
focused: root.focusPart === 3
|
|
285
|
+
available: root.canConvert
|
|
286
|
+
enabled: available
|
|
287
|
+
Keys.forwardTo: [keys]
|
|
288
|
+
onActivated: root.commit()
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
Column {
|
|
294
|
+
width: parent.width
|
|
295
|
+
spacing: Theme.spacing.gap / 2
|
|
296
|
+
|
|
297
|
+
Repeater {
|
|
298
|
+
id: formatRows
|
|
299
|
+
model: root.formats
|
|
300
|
+
delegate: Flea.MenuRow {
|
|
301
|
+
required property string modelData
|
|
302
|
+
required property int index
|
|
303
|
+
width: body.holderWidth
|
|
304
|
+
enabled: root.editable
|
|
305
|
+
entry: ({ label: root.formatLabel(modelData), action: modelData, glyph: "image",
|
|
306
|
+
labelColor: Theme.color.foreground, disabled: !root.editable })
|
|
307
|
+
picked: root.format === modelData
|
|
308
|
+
current: root.focusPart === 0 && root.cursor === index
|
|
309
|
+
Accessible.role: Accessible.RadioButton
|
|
310
|
+
Accessible.name: root.formatLabel(modelData)
|
|
311
|
+
Accessible.checkable: true
|
|
312
|
+
Accessible.checked: root.format === modelData
|
|
313
|
+
Keys.forwardTo: [keys]
|
|
314
|
+
Accessible.onPressAction: root.chooseFormat(index)
|
|
315
|
+
lastPointerGlobal: root.pointerGlobal
|
|
316
|
+
onPointerSeen: function (at) { root.pointerGlobal = at }
|
|
317
|
+
onPointerMoved: { root.focusPart = 0; root.cursor = index }
|
|
318
|
+
onActivated: root.chooseFormat(index)
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
Rectangle {
|
|
323
|
+
width: parent.width
|
|
324
|
+
height: Theme.spacing.hairline
|
|
325
|
+
color: Theme.color.mutedFrame
|
|
326
|
+
opacity: 0.4
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// The rule's checkbox row; Space and a tap toggle it.
|
|
330
|
+
Item {
|
|
331
|
+
id: metadata
|
|
332
|
+
width: parent.width
|
|
333
|
+
height: Theme.rowHeight
|
|
334
|
+
enabled: root.editable
|
|
335
|
+
Accessible.role: Accessible.CheckBox
|
|
336
|
+
Accessible.name: "Remove metadata"
|
|
337
|
+
Accessible.checkable: true
|
|
338
|
+
Accessible.checked: root.strip
|
|
339
|
+
Keys.forwardTo: [keys]
|
|
340
|
+
Accessible.onPressAction: if (root.editable) root.strip = !root.strip
|
|
341
|
+
|
|
342
|
+
Item {
|
|
343
|
+
id: box
|
|
344
|
+
anchors.left: parent.left
|
|
345
|
+
anchors.leftMargin: Theme.spacing.rowPaddingX
|
|
346
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
347
|
+
width: ruleBox.implicitWidth
|
|
348
|
+
height: ruleBox.implicitHeight
|
|
349
|
+
|
|
350
|
+
Flea.CheckBox {
|
|
351
|
+
id: ruleBox
|
|
352
|
+
value: root.strip ? "on" : "off"
|
|
353
|
+
focused: root.focusPart === 1
|
|
354
|
+
available: root.editable
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
Text {
|
|
359
|
+
anchors.left: box.right
|
|
360
|
+
anchors.leftMargin: Theme.spacing.gap
|
|
361
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
362
|
+
// Unchecked by default: a user converting a photo does not expect metadata
|
|
363
|
+
// silently dropped unless they asked for it.
|
|
364
|
+
text: "Remove metadata"
|
|
365
|
+
color: Theme.color.foreground
|
|
366
|
+
font.family: Theme.font.family
|
|
367
|
+
font.pixelSize: Theme.font.body
|
|
368
|
+
textFormat: Text.PlainText
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
TapHandler {
|
|
372
|
+
acceptedButtons: Qt.LeftButton
|
|
373
|
+
gesturePolicy: TapHandler.ReleaseWithinBounds
|
|
374
|
+
onTapped: if (root.editable) { root.focusPart = 1; root.strip = !root.strip; metadata.forceActiveFocus() }
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
Text {
|
|
379
|
+
id: output
|
|
380
|
+
x: Theme.spacing.rowPaddingX
|
|
381
|
+
width: parent.width - 2 * Theme.spacing.rowPaddingX
|
|
382
|
+
topPadding: 2 * Theme.spacing.hairline
|
|
383
|
+
bottomPadding: 2 * Theme.spacing.hairline
|
|
384
|
+
text: "Output: " + root.outputPath
|
|
385
|
+
color: Theme.color.foreground
|
|
386
|
+
font.family: Theme.font.family
|
|
387
|
+
font.pixelSize: Theme.font.caption
|
|
388
|
+
textFormat: Text.PlainText
|
|
389
|
+
wrapMode: Text.WrapAnywhere
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// The status slot is always laid out, two caption lines tall (the network slot's rowHeight) inside its padding, so rest, busy and a short error keep one card height; only a longer error grows it.
|
|
393
|
+
Text {
|
|
394
|
+
x: Theme.spacing.rowPaddingX
|
|
395
|
+
width: parent.width - 2 * Theme.spacing.rowPaddingX
|
|
396
|
+
height: Math.max(Theme.rowHeight + topPadding + bottomPadding, implicitHeight)
|
|
397
|
+
topPadding: 2 * Theme.spacing.hairline
|
|
398
|
+
bottomPadding: 2 * Theme.spacing.hairline
|
|
399
|
+
text: root.busy ? "Converting…" : root.errorText
|
|
400
|
+
color: root.busy ? Theme.color.muted : Theme.color.errorOnSurface
|
|
401
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
402
|
+
textFormat: Text.PlainText
|
|
403
|
+
wrapMode: Text.Wrap
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
Text {
|
|
407
|
+
x: Theme.spacing.rowPaddingX
|
|
408
|
+
width: parent.width - 2 * Theme.spacing.rowPaddingX
|
|
409
|
+
topPadding: 2 * Theme.spacing.hairline
|
|
410
|
+
bottomPadding: 2 * Theme.spacing.hairline
|
|
411
|
+
visible: root.collision
|
|
412
|
+
text: "Choose another format."
|
|
413
|
+
color: Theme.color.foreground
|
|
414
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
415
|
+
textFormat: Text.PlainText
|
|
416
|
+
wrapMode: Text.Wrap
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
Item {
|
|
423
|
+
id: keys
|
|
424
|
+
anchors.fill: parent
|
|
425
|
+
|
|
426
|
+
Keys.onPressed: function (event) {
|
|
427
|
+
event.accepted = true
|
|
428
|
+
if (event.key === Qt.Key_Escape) { root.close(); event.accepted = true; return }
|
|
429
|
+
if (event.key === Qt.Key_Tab || event.key === Qt.Key_Backtab) {
|
|
430
|
+
root.stepFocus(event.key === Qt.Key_Backtab || (event.modifiers & Qt.ShiftModifier)); return
|
|
431
|
+
}
|
|
432
|
+
if (root.busy) return
|
|
433
|
+
if (root.unavailable) {
|
|
434
|
+
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter || event.key === Qt.Key_Space) root.close()
|
|
435
|
+
return
|
|
436
|
+
}
|
|
437
|
+
if (event.key === Qt.Key_Down) {
|
|
438
|
+
root.chooseFormat(root.cursor + 1)
|
|
439
|
+
event.accepted = true
|
|
440
|
+
return
|
|
441
|
+
}
|
|
442
|
+
if (event.key === Qt.Key_Up) {
|
|
443
|
+
root.chooseFormat(root.cursor - 1)
|
|
444
|
+
event.accepted = true
|
|
445
|
+
return
|
|
446
|
+
}
|
|
447
|
+
// Space toggles the one checkbox, which is the only other thing this popup asks.
|
|
448
|
+
if (event.key === Qt.Key_Space && root.focusPart < 2) { root.strip = !root.strip; return }
|
|
449
|
+
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter || event.key === Qt.Key_Space) {
|
|
450
|
+
if (root.focusPart === 2) root.close()
|
|
451
|
+
else if (root.focusPart === 1) root.strip = !root.strip
|
|
452
|
+
else root.commit()
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
|
|
3
|
+
// Says WORKER_STARTED under flea.worker (off unless QT_LOGGING_RULES names it), so log checks match Qt 6.11.2's one null connect warning per start.
|
|
4
|
+
WorkerScript {
|
|
5
|
+
property QtObject startLog: LoggingCategory { name: "flea.worker"; defaultLogLevel: LoggingCategory.Warning }
|
|
6
|
+
Component.onCompleted: if (source.toString() !== "") console.info(startLog, "WORKER_STARTED " + source)
|
|
7
|
+
}
|
package/ui/Crumb.qml
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
|
|
3
|
+
// One piece of a path that a click can land on, the chrome's and a dual pane's alike; keys.toml's "chrome" rows are its contract.
|
|
4
|
+
Text {
|
|
5
|
+
id: crumb
|
|
6
|
+
|
|
7
|
+
required property var modelData
|
|
8
|
+
// What an ancestor reads at rest: muted in the chrome, where only the leaf is lit, and the foreground on a dual pane's path.
|
|
9
|
+
property color restColor: Theme.color.muted
|
|
10
|
+
// ui/ChromeButton.qml's inputLive: the handlers stop while something covers the crumb.
|
|
11
|
+
property bool inputLive: true
|
|
12
|
+
// Drops callout 4: the pane whose collide sends a drop on this crumb, null where crumbs take none.
|
|
13
|
+
property var dropPane: null
|
|
14
|
+
// The hovered ancestor inside the row's drop frame: an accent hairline over the wash, inside the crumb's own advance.
|
|
15
|
+
property bool dropTarget: false
|
|
16
|
+
// Built when a drag first needs it and kept, so no DropArea per crumb stands at startup.
|
|
17
|
+
property var dropArea: null
|
|
18
|
+
// A platform drag sends no hover, so the lift is what builds the target; the first hover builds it too.
|
|
19
|
+
readonly property bool dragLive: crumb.dropPane !== null && crumb.dropPane.dragActive === true
|
|
20
|
+
onDragLiveChanged: if (crumb.dragLive) crumb.armDrop()
|
|
21
|
+
|
|
22
|
+
signal chosen(string path)
|
|
23
|
+
signal editRequested()
|
|
24
|
+
|
|
25
|
+
// corner: a path is arbitrary text, so PlainText, the same rule every filename on this surface follows.
|
|
26
|
+
text: crumb.modelData.text
|
|
27
|
+
color: crumb.dropTarget ? Theme.color.accent
|
|
28
|
+
: crumb.modelData.last || (crumbHover.hovered && !crumb.modelData.elided) ? Theme.color.foreground : crumb.restColor
|
|
29
|
+
font.family: Theme.font.family
|
|
30
|
+
font.pixelSize: Theme.font.caption
|
|
31
|
+
textFormat: Text.PlainText
|
|
32
|
+
verticalAlignment: Text.AlignVCenter
|
|
33
|
+
|
|
34
|
+
function armDrop() {
|
|
35
|
+
if (crumb.dropArea !== null || crumb.dropPane === null)
|
|
36
|
+
return
|
|
37
|
+
var dest = String(crumb.modelData.path || "")
|
|
38
|
+
if (dest.length === 0 || crumb.modelData.last === true)
|
|
39
|
+
return
|
|
40
|
+
var area = Qt.createComponent("CrumbDrop.qml").createObject(crumb,
|
|
41
|
+
{ crumb: crumb, pane: crumb.dropPane, dest: dest, label: String(crumb.modelData.text || "") })
|
|
42
|
+
if (area === null)
|
|
43
|
+
return
|
|
44
|
+
crumb.dropArea = area
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
HoverHandler {
|
|
48
|
+
id: crumbHover
|
|
49
|
+
enabled: crumb.inputLive
|
|
50
|
+
cursorShape: crumb.modelData.last || crumb.modelData.elided ? Qt.IBeamCursor : Qt.PointingHandCursor
|
|
51
|
+
onHoveredChanged: if (hovered) crumb.armDrop()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// No exclusiveSignals, decided 2026-09-22: the pair held every tap for the whole double-click interval, about 400 ms.
|
|
55
|
+
// The gesture sits on the crumb because a TapHandler on a parent takes the second tap from the child under the pointer.
|
|
56
|
+
TapHandler {
|
|
57
|
+
enabled: crumb.inputLive
|
|
58
|
+
acceptedButtons: Qt.LeftButton
|
|
59
|
+
// The collapsed marker names no directory, so a press on it opens nothing rather than whichever crumb it stands for.
|
|
60
|
+
onSingleTapped: if (!crumb.modelData.last && !crumb.modelData.elided) crumb.chosen(crumb.modelData.path)
|
|
61
|
+
// Only where a tap opens nothing does a double click type the path; on a parent it is two taps.
|
|
62
|
+
onDoubleTapped: if (crumb.modelData.last || crumb.modelData.elided) crumb.editRequested()
|
|
63
|
+
}
|
|
64
|
+
}
|
package/ui/CrumbDrop.qml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
import "js/DropDev.js" as DropDev
|
|
4
|
+
|
|
5
|
+
// One crumb's drop target: the floor's own receiver, naming the crumb, with a frame inside the crumb's own advance so it never reaches the "/" either side.
|
|
6
|
+
Flea.DropInto {
|
|
7
|
+
id: root
|
|
8
|
+
|
|
9
|
+
required property var crumb
|
|
10
|
+
anchors.fill: parent
|
|
11
|
+
enabled: root.crumb.inputLive && root.pane !== null
|
|
12
|
+
refuseLoading: root.pane ? root.pane.listInFlight === true : true
|
|
13
|
+
// A plain drop moves on the source volume and copies across it; this crumb's device is the backend's answer, and an unanswered one copies.
|
|
14
|
+
destDev: DropDev.devFor(root.pane && root.pane.backend ? root.pane.backend.pathDevs : null, root.dest)
|
|
15
|
+
onContainsDragChanged: root.crumb.dropTarget = root.containsDrag
|
|
16
|
+
|
|
17
|
+
Rectangle {
|
|
18
|
+
anchors.fill: parent
|
|
19
|
+
visible: root.containsDrag
|
|
20
|
+
color: Theme.color.accent
|
|
21
|
+
opacity: 0.08
|
|
22
|
+
border.width: Theme.spacing.hairline
|
|
23
|
+
border.color: Theme.color.accent
|
|
24
|
+
}
|
|
25
|
+
}
|