flea-qml 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +511 -2
- package/THIRD-PARTY-NOTICES.md +29 -0
- package/demos/App.java +5 -0
- package/demos/Dockerfile +4 -0
- package/demos/Main.kt +3 -0
- package/demos/Program.cs +1 -0
- package/demos/README.md +12 -0
- package/demos/app.dart +3 -0
- package/demos/app.deb +0 -0
- package/demos/app.js +1 -0
- package/demos/backup.tar +0 -0
- package/demos/budget.xlsx +0 -0
- package/demos/build.sh +2 -0
- package/demos/bundle.zip +0 -0
- package/demos/clip.mp4 +0 -0
- package/demos/data.sqlite +0 -0
- package/demos/disk.iso +0 -0
- package/demos/engine.cpp +5 -0
- package/demos/firmware.bin +0 -0
- package/demos/flake.nix +4 -0
- package/demos/folder/inside.txt +1 -0
- package/demos/font.ttf +0 -0
- package/demos/index.html +5 -0
- package/demos/index.php +2 -0
- package/demos/init.lua +1 -0
- package/demos/letter.docx +0 -0
- package/demos/lib.rs +3 -0
- package/demos/main.c +6 -0
- package/demos/main.h +3 -0
- package/demos/math-and-diagrams.md +200 -0
- package/demos/notes.tar.gz +0 -0
- package/demos/notes.txt +3 -0
- package/demos/photo.png +0 -0
- package/demos/program +2 -0
- package/demos/report.pdf +32 -0
- package/demos/script.py +1 -0
- package/demos/server.go +7 -0
- package/demos/settings.json +4 -0
- package/demos/slides.pptx +0 -0
- package/demos/song.mp3 +0 -0
- package/demos/style.css +4 -0
- package/demos/tool.rb +1 -0
- package/demos/types.ts +2 -0
- package/docs/pele.md +23 -0
- package/docs/protocol.md +3420 -0
- package/docs/temml.md +63 -0
- package/index.js +107 -0
- package/package.json +34 -4
- package/src/archive.js +407 -0
- package/src/archiveops.js +728 -0
- package/src/backend.js +369 -0
- package/src/bulkrename.js +95 -0
- package/src/clip-host.js +76 -0
- package/src/clip.js +462 -0
- package/src/code.js +168 -0
- package/src/compare.js +74 -0
- package/src/create.js +128 -0
- package/src/dirsize.js +147 -0
- package/src/figure-svg.js +530 -0
- package/src/figure-thread.js +23 -0
- package/src/figure.js +132 -0
- package/src/find.js +55 -0
- package/src/flea.js +39 -0
- package/src/fsinfo.js +39 -0
- package/src/highlight.js +141 -0
- package/src/html.js +52 -0
- package/src/kinds.js +89 -0
- package/src/listing.js +130 -0
- package/src/markdown-html.js +317 -0
- package/src/mathml.js +186 -0
- package/src/menu.js +180 -0
- package/src/meta.js +135 -0
- package/src/office.js +810 -0
- package/src/order.js +100 -0
- package/src/peek.js +49 -0
- package/src/pele-wrapper.js +695 -0
- package/src/permissions.js +180 -0
- package/src/places.js +313 -0
- package/src/preview-language.js +10 -0
- package/src/terminal-server.js +95 -0
- package/src/terminal-shell.js +26 -0
- package/src/transfer.js +669 -0
- package/src/trash-record.js +41 -0
- package/src/trash.js +210 -0
- package/src/trashbrowse.js +327 -0
- package/src/uistate.js +393 -0
- package/src/uistore.js +168 -0
- package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
- package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
- package/src/vendor/LICENSES/MIT-katex.txt +21 -0
- package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
- package/src/vendor/LICENSES/MIT-pele.txt +40 -0
- package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
- package/src/vendor/LICENSES/MIT-temml.txt +21 -0
- package/src/vendor/pele.js +145 -0
- package/src/vendor/temml.mjs +14708 -0
- package/src/watch.js +98 -0
- package/src/wayland/client.js +109 -0
- package/src/wayland/protocol.js +55 -0
- package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
- package/src/wayland/protocols/wayland.xml +3248 -0
- package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
- package/src/wayland/resource-io.js +6 -0
- package/src/wayland/socket-discovery.js +26 -0
- package/src/wayland/transport-posix.js +120 -0
- package/src/wayland/transport-win32.js +11 -0
- package/src/wayland/transport.js +3 -0
- package/src/wayland/win32-resources.js +80 -0
- package/src/wayland/win32-wire.js +62 -0
- package/test/archive.test.js +80 -0
- package/test/bench-markdown-scroll.mjs +190 -0
- package/test/clip-host.test.js +113 -0
- package/test/code-preview.test.js +35 -0
- package/test/compare-ui-paths.test.js +24 -0
- package/test/compare.test.js +54 -0
- package/test/delete-trash.test.js +67 -0
- package/test/dirsize.test.js +138 -0
- package/test/file-ops.test.js +307 -0
- package/test/file-url.test.js +24 -0
- package/test/find-contents.test.js +161 -0
- package/test/find-input.test.js +66 -0
- package/test/fixtures/pele-parity.json +1006 -0
- package/test/highlight-launcher.test.js +35 -0
- package/test/html-preview.test.js +22 -0
- package/test/input.test.js +15 -0
- package/test/keymap.test.js +26 -0
- package/test/language-icons.test.js +36 -0
- package/test/launcher.test.js +51 -0
- package/test/manual-archive-here-ui.mjs +47 -0
- package/test/manual-code-scroll.mjs +28 -0
- package/test/manual-column-scroll.mjs +24 -0
- package/test/manual-compare-ui.mjs +20 -0
- package/test/manual-find-status.mjs +37 -0
- package/test/manual-folder-focus.mjs +63 -0
- package/test/manual-html-security.mjs +23 -0
- package/test/manual-html-ui.mjs +30 -0
- package/test/manual-syntax-preview.mjs +26 -0
- package/test/manual-terminal-lifecycle.mjs +42 -0
- package/test/manual-terminal-navigation.mjs +48 -0
- package/test/manual-terminal-ui.mjs +47 -0
- package/test/manual-trash-ui.mjs +86 -0
- package/test/markdown-diagrams.test.js +93 -0
- package/test/markdown-html.test.js +105 -0
- package/test/mathml.test.js +92 -0
- package/test/menu-transfer.test.js +57 -0
- package/test/office-preview.test.js +154 -0
- package/test/pele-parity.test.js +28 -0
- package/test/places.test.js +134 -0
- package/test/preview-keys.test.js +60 -0
- package/test/preview-language.test.js +22 -0
- package/test/status-filename.test.js +20 -0
- package/test/transfer-replace-merge.test.js +187 -0
- package/test/trash-address.test.js +23 -0
- package/test/trash-view.test.js +37 -0
- package/test/trashbrowse.test.js +135 -0
- package/ui/AboutFacts.qml +78 -0
- package/ui/ArchiveCards.qml +95 -0
- package/ui/ArchiveCompressDialog.qml +378 -0
- package/ui/ArchiveHereConfirm.qml +127 -0
- package/ui/ArchivePasswordDialog.qml +257 -0
- package/ui/Backend.qml +775 -0
- package/ui/BulkOldNames.qml +47 -0
- package/ui/BulkRenameDialog.qml +380 -0
- package/ui/CardFrame.qml +67 -0
- package/ui/CardScroll.qml +79 -0
- package/ui/CheckBox.qml +73 -0
- package/ui/ChromeBar.qml +360 -0
- package/ui/ChromeButton.qml +131 -0
- package/ui/ChromeModes.qml +43 -0
- package/ui/CodeLines.qml +256 -0
- package/ui/CodeRefusal.qml +52 -0
- package/ui/CollideConfirm.qml +147 -0
- package/ui/CollideHost.qml +167 -0
- package/ui/ColumnPane.qml +525 -0
- package/ui/ColumnRow.qml +380 -0
- package/ui/ColumnsArea.qml +594 -0
- package/ui/ColumnsLanding.qml +147 -0
- package/ui/CompareView.qml +321 -0
- package/ui/ContextMenu.qml +743 -0
- package/ui/ConvertDialog.qml +456 -0
- package/ui/CountedWorker.qml +7 -0
- package/ui/Crumb.qml +64 -0
- package/ui/CrumbDrop.qml +25 -0
- package/ui/CsvTable.qml +394 -0
- package/ui/CursorMark.qml +41 -0
- package/ui/DefaultClaim.qml +130 -0
- package/ui/DeviceLock.qml +47 -0
- package/ui/DeviceMounts.qml +540 -0
- package/ui/DialogButton.qml +150 -0
- package/ui/DialogField.qml +147 -0
- package/ui/DialogHeader.qml +31 -0
- package/ui/DialogScrim.qml +20 -0
- package/ui/DialogTitle.qml +37 -0
- package/ui/Divider.qml +9 -0
- package/ui/DropInto.qml +126 -0
- package/ui/DropTarget.qml +35 -0
- package/ui/DropboxMark.qml +60 -0
- package/ui/EmptyState.qml +150 -0
- package/ui/EscapeHint.qml +11 -0
- package/ui/FactsTable.qml +54 -0
- package/ui/FastScrollHandler.qml +476 -0
- package/ui/FatNamesConfirm.qml +157 -0
- package/ui/Favourites.qml +143 -0
- package/ui/FigureService.qml +120 -0
- package/ui/FileDrag.qml +267 -0
- package/ui/FilterStrip.qml +133 -0
- package/ui/FitMetrics.qml +22 -0
- package/ui/FlashDriveRows.qml +137 -0
- package/ui/FlashHost.qml +72 -0
- package/ui/FlashImageRow.qml +104 -0
- package/ui/FlashRunner.qml +119 -0
- package/ui/FlashStepRow.qml +172 -0
- package/ui/FlashStrip.qml +38 -0
- package/ui/FlashView.qml +397 -0
- package/ui/FleaMark.qml +88 -0
- package/ui/FlyoutFade.qml +23 -0
- package/ui/FontPane.qml +170 -0
- package/ui/Glass.qml +114 -0
- package/ui/GlassTagger.qml +59 -0
- package/ui/Glyph.qml +64 -0
- package/ui/GlyphSolid.qml +22 -0
- package/ui/GridArea.qml +664 -0
- package/ui/GridTile.qml +325 -0
- package/ui/GvfsBridge.qml +164 -0
- package/ui/Header.qml +433 -0
- package/ui/HoverTimers.qml +39 -0
- package/ui/HtmlClip.qml +30 -0
- package/ui/HtmlPane.qml +63 -0
- package/ui/HyprlandMark.qml +45 -0
- package/ui/Ipc.qml +1005 -0
- package/ui/IpcControls.qml +7 -0
- package/ui/IpcMenuState.qml +48 -0
- package/ui/IpcPreviewState.qml +185 -0
- package/ui/JumpPath.qml +51 -0
- package/ui/KeymapSheet.qml +561 -0
- package/ui/KeymapSheetResult.qml +89 -0
- package/ui/KindStack.qml +40 -0
- package/ui/LangMark.qml +51 -0
- package/ui/LangMarkLoader.qml +26 -0
- package/ui/List.qml +480 -0
- package/ui/LoadingState.qml +54 -0
- package/ui/LocalSend.qml +56 -0
- package/ui/LocalSendMark.qml +73 -0
- package/ui/MarkdownBlockView.qml +311 -0
- package/ui/MarkdownBlocks.qml +35 -0
- package/ui/MarkdownFigure.qml +254 -0
- package/ui/MarkdownImages.qml +72 -0
- package/ui/MarkdownList.qml +81 -0
- package/ui/MarkdownMathsText.qml +97 -0
- package/ui/MarkdownPane.qml +83 -0
- package/ui/MarkdownPictures.qml +41 -0
- package/ui/MarkdownQuote.qml +52 -0
- package/ui/MarkdownRemote.qml +82 -0
- package/ui/MarkdownSource.qml +155 -0
- package/ui/MarkdownTable.qml +222 -0
- package/ui/MarkdownTableScroll.qml +64 -0
- package/ui/MarkdownTableWheel.qml +126 -0
- package/ui/MarkdownText.qml +87 -0
- package/ui/MarkdownWorker.js +132 -0
- package/ui/MatchText.qml +99 -0
- package/ui/MediaSession.qml +38 -0
- package/ui/MediaSound.qml +26 -0
- package/ui/MediaStrip.qml +191 -0
- package/ui/MediaTrack.qml +36 -0
- package/ui/MediaVolume.qml +54 -0
- package/ui/MenuActionDialog.qml +396 -0
- package/ui/MenuEdgeFade.qml +24 -0
- package/ui/MenuHost.qml +227 -0
- package/ui/MenuRow.qml +351 -0
- package/ui/MountListing.qml +100 -0
- package/ui/NetworkDialog.qml +435 -0
- package/ui/NetworkForm.qml +426 -0
- package/ui/NetworkMounts.qml +913 -0
- package/ui/NetworkPlaces.qml +127 -0
- package/ui/OpenWithDialog.qml +613 -0
- package/ui/Opener.qml +95 -0
- package/ui/Pane.qml +1320 -0
- package/ui/PaneMenuActions.qml +527 -0
- package/ui/PanePath.qml +90 -0
- package/ui/PaneRail.qml +268 -0
- package/ui/PaneStates.qml +88 -0
- package/ui/PaneSwap.qml +339 -0
- package/ui/PaneWire.qml +601 -0
- package/ui/ParkedWait.qml +9 -0
- package/ui/PathEntry.qml +186 -0
- package/ui/PathJump.qml +400 -0
- package/ui/PdfViewer.qml +297 -0
- package/ui/PermissionsDialog.qml +658 -0
- package/ui/PermissionsHeadings.qml +31 -0
- package/ui/PhoneMounts.qml +67 -0
- package/ui/PickerAnswers.qml +75 -0
- package/ui/PickerBox.qml +26 -0
- package/ui/PickerChrome.qml +295 -0
- package/ui/PickerFilter.qml +97 -0
- package/ui/PickerGrid.qml +308 -0
- package/ui/PickerHeader.qml +28 -0
- package/ui/PickerLifecycle.qml +27 -0
- package/ui/PickerList.qml +218 -0
- package/ui/PickerListing.qml +149 -0
- package/ui/PickerPathBar.qml +127 -0
- package/ui/PickerPlaces.qml +189 -0
- package/ui/PickerRecent.qml +92 -0
- package/ui/PickerSave.qml +101 -0
- package/ui/PickerSelection.qml +155 -0
- package/ui/PickerWindow.qml +846 -0
- package/ui/PowerSectorsReader.qml +10 -0
- package/ui/PrebuildDriver.qml +146 -0
- package/ui/Preview.qml +1005 -0
- package/ui/PreviewAnimation.qml +24 -0
- package/ui/PreviewArchive.qml +91 -0
- package/ui/PreviewColumn.qml +553 -0
- package/ui/PreviewEdge.qml +63 -0
- package/ui/PreviewFacts.qml +30 -0
- package/ui/PreviewFactsLine.qml +34 -0
- package/ui/PreviewHtml.qml +233 -0
- package/ui/PreviewImage.qml +253 -0
- package/ui/PreviewImagePan.qml +13 -0
- package/ui/PreviewImageSharp.qml +32 -0
- package/ui/PreviewLines.qml +106 -0
- package/ui/PreviewMarkdown.qml +706 -0
- package/ui/PreviewMedia.qml +250 -0
- package/ui/PreviewPdf.qml +482 -0
- package/ui/PreviewScroll.qml +201 -0
- package/ui/PreviewSwap.qml +335 -0
- package/ui/PreviewText.qml +149 -0
- package/ui/ProtocolChip.qml +18 -0
- package/ui/QuickLookArchive.qml +41 -0
- package/ui/QuickLookBar.qml +103 -0
- package/ui/QuickLookPrepare.qml +355 -0
- package/ui/QuickLookSwap.qml +10 -0
- package/ui/QuickLookWarm.qml +65 -0
- package/ui/RailDrop.qml +155 -0
- package/ui/RailHeading.qml +19 -0
- package/ui/RailPlaces.qml +38 -0
- package/ui/RailTrashRow.qml +67 -0
- package/ui/RenameField.qml +353 -0
- package/ui/RendererRetry.qml +11 -0
- package/ui/ResizeHandle.qml +52 -0
- package/ui/Reveal.qml +54 -0
- package/ui/Row.qml +476 -0
- package/ui/RowDrag.qml +213 -0
- package/ui/RowDropTarget.qml +27 -0
- package/ui/RunCard.qml +286 -0
- package/ui/Scripts.qml +65 -0
- package/ui/SearchStrip.qml +232 -0
- package/ui/SelectionBand.qml +140 -0
- package/ui/SelectionPreview.qml +370 -0
- package/ui/SettingsFavourite.qml +122 -0
- package/ui/SettingsGroup.qml +96 -0
- package/ui/SettingsHint.qml +12 -0
- package/ui/SettingsMetrics.qml +29 -0
- package/ui/SettingsPane.qml +178 -0
- package/ui/SettingsPanel.qml +547 -0
- package/ui/SettingsRail.qml +128 -0
- package/ui/SettingsRow.qml +409 -0
- package/ui/SettingsRuler.qml +85 -0
- package/ui/SettingsSegment.qml +85 -0
- package/ui/ShareBrowser.qml +113 -0
- package/ui/ShareLink.qml +67 -0
- package/ui/ShelfPins.qml +101 -0
- package/ui/Sidebar.qml +728 -0
- package/ui/SidebarRow.qml +358 -0
- package/ui/Spinner.qml +60 -0
- package/ui/StableModel.qml +89 -0
- package/ui/StateMessage.qml +84 -0
- package/ui/StatusBar.qml +512 -0
- package/ui/StatusFileName.qml +27 -0
- package/ui/TabBar.qml +673 -0
- package/ui/TabDragGeometry.qml +60 -0
- package/ui/TagMenuMark.qml +52 -0
- package/ui/TagRailSection.qml +53 -0
- package/ui/TagSlot.qml +40 -0
- package/ui/TagState.qml +150 -0
- package/ui/TagSwatch.qml +28 -0
- package/ui/Taildrop.qml +86 -0
- package/ui/TailscaleMark.qml +50 -0
- package/ui/TerminalService.qml +69 -0
- package/ui/TerminalTab.qml +48 -0
- package/ui/TerminalTabs.qml +27 -0
- package/ui/Theme.qml +460 -0
- package/ui/ThemeColors.qml +43 -0
- package/ui/TransferCard.qml +239 -0
- package/ui/TrashConfirm.qml +129 -0
- package/ui/TrashDropHandler.qml +11 -0
- package/ui/TrashHost.qml +202 -0
- package/ui/TrashMonitor.qml +30 -0
- package/ui/TrashToolbar.qml +19 -0
- package/ui/TrashView.qml +492 -0
- package/ui/UnlockDialog.qml +450 -0
- package/ui/UnlockHost.qml +206 -0
- package/ui/UpdateCheck.qml +97 -0
- package/ui/UserDirs.qml +25 -0
- package/ui/ViewState.qml +565 -0
- package/ui/ViewportScrollBar.qml +195 -0
- package/ui/ViewportScrollBars.qml +25 -0
- package/ui/WebPreview.qml +33 -0
- package/ui/WebPreviewView.qml +26 -0
- package/ui/WindowBody.qml +829 -0
- package/ui/WindowDrag.qml +35 -0
- package/ui/boot/Commons/AudioNodes.qml +50 -0
- package/ui/boot/Commons/AudioNodesModel.js +96 -0
- package/ui/boot/Commons/Border.qml +243 -0
- package/ui/boot/Commons/BorderGeometry.js +373 -0
- package/ui/boot/Commons/Color.qml +258 -0
- package/ui/boot/Commons/I18n.qml +118 -0
- package/ui/boot/Commons/InputDevices.qml +112 -0
- package/ui/boot/Commons/InputMethodState.qml +38 -0
- package/ui/boot/Commons/IpcRegistry.qml +77 -0
- package/ui/boot/Commons/Numbers.js +19 -0
- package/ui/boot/Commons/Plural.js +91 -0
- package/ui/boot/Commons/ShellIpc.qml +12 -0
- package/ui/boot/Commons/Style.qml +561 -0
- package/ui/boot/Commons/Translations.qml +100 -0
- package/ui/boot/Commons/UntypedInput.qml +152 -0
- package/ui/boot/Commons/Util.qml +188 -0
- package/ui/boot/Commons/qmldir +13 -0
- package/ui/boot/LICENSE-omarchy +20 -0
- package/ui/boot/Ui/BackgroundMedia.qml +49 -0
- package/ui/boot/Ui/BarIconButton.qml +106 -0
- package/ui/boot/Ui/BarIconContent.qml +38 -0
- package/ui/boot/Ui/BarIndicator.qml +53 -0
- package/ui/boot/Ui/BarWidget.qml +50 -0
- package/ui/boot/Ui/BorderOverlay.qml +54 -0
- package/ui/boot/Ui/BorderSurface.qml +40 -0
- package/ui/boot/Ui/Button.qml +224 -0
- package/ui/boot/Ui/ButtonGroup.qml +131 -0
- package/ui/boot/Ui/ConfirmDialog.qml +134 -0
- package/ui/boot/Ui/CursorSurface.qml +42 -0
- package/ui/boot/Ui/Dropdown.qml +245 -0
- package/ui/boot/Ui/FilterInput.qml +26 -0
- package/ui/boot/Ui/IconContentBounds.qml +141 -0
- package/ui/boot/Ui/KeyboardPanel.qml +453 -0
- package/ui/boot/Ui/MultiSelect.qml +624 -0
- package/ui/boot/Ui/NumberField.qml +86 -0
- package/ui/boot/Ui/OpticalGlyph.qml +68 -0
- package/ui/boot/Ui/OverlayWindow.qml +102 -0
- package/ui/boot/Ui/Panel.qml +60 -0
- package/ui/boot/Ui/PanelActionButton.qml +105 -0
- package/ui/boot/Ui/PanelController.qml +16 -0
- package/ui/boot/Ui/PanelHero.qml +112 -0
- package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
- package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
- package/ui/boot/Ui/PanelSeparator.qml +19 -0
- package/ui/boot/Ui/PanelSlider.qml +156 -0
- package/ui/boot/Ui/PanelToolTip.qml +50 -0
- package/ui/boot/Ui/PluginBarApi.qml +89 -0
- package/ui/boot/Ui/PointerMoveGate.qml +54 -0
- package/ui/boot/Ui/PopupCard.qml +181 -0
- package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
- package/ui/boot/Ui/SearchableDropdown.qml +354 -0
- package/ui/boot/Ui/SizedImage.qml +125 -0
- package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
- package/ui/boot/Ui/TextField.qml +58 -0
- package/ui/boot/Ui/Toggle.qml +118 -0
- package/ui/boot/Ui/ToggleSwitch.qml +115 -0
- package/ui/boot/Ui/WidgetButton.qml +172 -0
- package/ui/boot/Ui/qmldir +41 -0
- package/ui/boot/fleatab.qml +50 -0
- package/ui/boot/picker.qml +39 -0
- package/ui/boot/shell.qml +131 -0
- package/ui/boot/tabtearoff.qml +51 -0
- package/ui/js/Anchor.js +379 -0
- package/ui/js/AnchorHold.js +162 -0
- package/ui/js/Archive.js +157 -0
- package/ui/js/ArchiveCard.js +44 -0
- package/ui/js/ArchiveOps.js +44 -0
- package/ui/js/BackReturn.js +118 -0
- package/ui/js/BulkRename.js +100 -0
- package/ui/js/Buttons.js +54 -0
- package/ui/js/ChromeKeys.js +116 -0
- package/ui/js/ClipMarks.js +73 -0
- package/ui/js/ClipSelection.js +67 -0
- package/ui/js/Clipboard.js +179 -0
- package/ui/js/Cloud.js +97 -0
- package/ui/js/CodeRuns.js +72 -0
- package/ui/js/Collide.js +212 -0
- package/ui/js/ColumnFit.js +28 -0
- package/ui/js/ColumnMenu.js +111 -0
- package/ui/js/Columns.js +298 -0
- package/ui/js/ColumnsCarry.js +103 -0
- package/ui/js/Compare.js +74 -0
- package/ui/js/Contrast.js +157 -0
- package/ui/js/ControlReader.js +42 -0
- package/ui/js/Convert.js +52 -0
- package/ui/js/CopyAs.js +52 -0
- package/ui/js/Crumbs.js +178 -0
- package/ui/js/Csv.js +231 -0
- package/ui/js/Density.js +44 -0
- package/ui/js/Devices.js +440 -0
- package/ui/js/DirSizes.js +180 -0
- package/ui/js/Drag.js +360 -0
- package/ui/js/DragOut.js +166 -0
- package/ui/js/DropDev.js +52 -0
- package/ui/js/Dropbox.js +41 -0
- package/ui/js/Eject.js +217 -0
- package/ui/js/Errors.js +188 -0
- package/ui/js/ExtThumbs.js +115 -0
- package/ui/js/Facts.js +402 -0
- package/ui/js/FigureDate.js +14 -0
- package/ui/js/Filter.js +285 -0
- package/ui/js/Find.js +46 -0
- package/ui/js/Flash.js +184 -0
- package/ui/js/FlashCard.js +79 -0
- package/ui/js/FlashEndings.js +125 -0
- package/ui/js/FlashPane.js +116 -0
- package/ui/js/FleaBin.js +12 -0
- package/ui/js/Focus.js +504 -0
- package/ui/js/FolderSorts.js +108 -0
- package/ui/js/FolderViews.js +44 -0
- package/ui/js/Format.js +314 -0
- package/ui/js/Fuzzy.js +141 -0
- package/ui/js/GlassTag.js +72 -0
- package/ui/js/Grid.js +33 -0
- package/ui/js/GridGeometry.js +90 -0
- package/ui/js/GridNames.js +153 -0
- package/ui/js/GvfsBridge.js +200 -0
- package/ui/js/HostClipboard.js +29 -0
- package/ui/js/Icons.js +218 -0
- package/ui/js/Input.js +50 -0
- package/ui/js/Jump.js +200 -0
- package/ui/js/KeyName.js +64 -0
- package/ui/js/Keymap.js +401 -0
- package/ui/js/Kinds.js +164 -0
- package/ui/js/LICENSES/ISC-lucide.txt +43 -0
- package/ui/js/LangMarkPaths.js +47 -0
- package/ui/js/LangMarks.js +120 -0
- package/ui/js/Lists.js +11 -0
- package/ui/js/LocalSend.js +39 -0
- package/ui/js/LockedMenu.js +63 -0
- package/ui/js/MakeDefault.js +186 -0
- package/ui/js/MarkBox.js +7 -0
- package/ui/js/Markdown.js +119 -0
- package/ui/js/MarkdownLists.js +86 -0
- package/ui/js/MarkdownMaths.js +58 -0
- package/ui/js/MarkdownPictures.js +32 -0
- package/ui/js/MarkdownPrepared.js +139 -0
- package/ui/js/MarkdownTableFit.js +34 -0
- package/ui/js/Marks.js +148 -0
- package/ui/js/Marquee.js +96 -0
- package/ui/js/Match.js +93 -0
- package/ui/js/Material.js +109 -0
- package/ui/js/MdBlocks.js +437 -0
- package/ui/js/MdBreak.js +71 -0
- package/ui/js/MdChunks.js +70 -0
- package/ui/js/MdContainer.js +137 -0
- package/ui/js/MdDocument.js +337 -0
- package/ui/js/MdEmph.js +97 -0
- package/ui/js/MdEntity.js +108 -0
- package/ui/js/MdEntityTable.js +223 -0
- package/ui/js/MdEscape.js +59 -0
- package/ui/js/MdFront.js +37 -0
- package/ui/js/MdHold.js +32 -0
- package/ui/js/MdHtml.js +307 -0
- package/ui/js/MdHtmlBlock.js +290 -0
- package/ui/js/MdHtmlHeading.js +53 -0
- package/ui/js/MdHtmlImage.js +179 -0
- package/ui/js/MdInline.js +154 -0
- package/ui/js/MdItems.js +212 -0
- package/ui/js/MdLeaf.js +309 -0
- package/ui/js/MdLink.js +196 -0
- package/ui/js/MdMath.js +67 -0
- package/ui/js/MdParagraphs.js +138 -0
- package/ui/js/MdRefs.js +232 -0
- package/ui/js/MdResolve.js +226 -0
- package/ui/js/MdRun.js +300 -0
- package/ui/js/MdUrl.js +226 -0
- package/ui/js/Menu.js +514 -0
- package/ui/js/MenuContext.js +85 -0
- package/ui/js/MenuFit.js +13 -0
- package/ui/js/MenuRefresh.js +74 -0
- package/ui/js/MenuWheel.js +35 -0
- package/ui/js/Messages.js +186 -0
- package/ui/js/Motion.js +16 -0
- package/ui/js/Mounts.js +320 -0
- package/ui/js/MouseNav.js +13 -0
- package/ui/js/Nav.js +329 -0
- package/ui/js/NetFs.js +26 -0
- package/ui/js/OpenWith.js +83 -0
- package/ui/js/Ops.js +585 -0
- package/ui/js/Palette.js +33 -0
- package/ui/js/PathBar.js +260 -0
- package/ui/js/Permissions.js +179 -0
- package/ui/js/Phones.js +112 -0
- package/ui/js/Picker.js +353 -0
- package/ui/js/PlaceMenu.js +96 -0
- package/ui/js/Places.js +265 -0
- package/ui/js/PreviewAsk.js +21 -0
- package/ui/js/PreviewKeys.js +155 -0
- package/ui/js/PreviewSettle.js +29 -0
- package/ui/js/PreviewSwap.js +101 -0
- package/ui/js/PropertyFacts.js +144 -0
- package/ui/js/Protocols.js +296 -0
- package/ui/js/QuickLookKinds.js +27 -0
- package/ui/js/QuickLookRect.js +24 -0
- package/ui/js/RailDrop.js +51 -0
- package/ui/js/RailKeys.js +87 -0
- package/ui/js/RailMenu.js +133 -0
- package/ui/js/Recent.js +135 -0
- package/ui/js/RecentMode.js +156 -0
- package/ui/js/Reload.js +60 -0
- package/ui/js/Renderer.js +9 -0
- package/ui/js/RunFile.js +143 -0
- package/ui/js/Scripts.js +28 -0
- package/ui/js/Scroll.js +304 -0
- package/ui/js/ScrollOff.js +69 -0
- package/ui/js/Search.js +478 -0
- package/ui/js/Selection.js +97 -0
- package/ui/js/Settings.js +476 -0
- package/ui/js/SettingsAbout.js +97 -0
- package/ui/js/SettingsShelf.js +52 -0
- package/ui/js/SheetKeys.js +42 -0
- package/ui/js/SheetQuery.js +281 -0
- package/ui/js/ShelfPile.js +27 -0
- package/ui/js/SlowClick.js +53 -0
- package/ui/js/SlowOp.js +6 -0
- package/ui/js/Sort.js +134 -0
- package/ui/js/Startup.js +63 -0
- package/ui/js/StateWords.js +17 -0
- package/ui/js/Status.js +238 -0
- package/ui/js/Swap.js +166 -0
- package/ui/js/TabMove.js +39 -0
- package/ui/js/Tabs.js +751 -0
- package/ui/js/Tags.js +134 -0
- package/ui/js/Taildrop.js +128 -0
- package/ui/js/Tap.js +180 -0
- package/ui/js/TextSize.js +107 -0
- package/ui/js/Thumbs.js +158 -0
- package/ui/js/Transfer.js +172 -0
- package/ui/js/Trash.js +84 -0
- package/ui/js/TrashDates.js +47 -0
- package/ui/js/TrashDrop.js +64 -0
- package/ui/js/UiState.js +438 -0
- package/ui/js/Unlock.js +152 -0
- package/ui/js/Update.js +130 -0
- package/ui/js/UserDirs.js +56 -0
- package/ui/qmldir +230 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Collide.js" as Collide
|
|
5
|
+
import "js/Icons.js" as Icons
|
|
6
|
+
|
|
7
|
+
// FAT-family names, on CollideConfirm's card, keys and look.
|
|
8
|
+
FocusScope {
|
|
9
|
+
id: root
|
|
10
|
+
anchors.fill: parent
|
|
11
|
+
visible: opened || opacity > 0
|
|
12
|
+
// Closed means no input, even while the fade-out is still drawn.
|
|
13
|
+
enabled: opened
|
|
14
|
+
opacity: 0
|
|
15
|
+
property bool opened: false
|
|
16
|
+
property string titleText: ""
|
|
17
|
+
property var renames: []
|
|
18
|
+
property string noteText: ""
|
|
19
|
+
property string focusName: Collide.FAT_DEFAULT
|
|
20
|
+
// The card geometry lives in ui/js/Collide.js, shared with CollideConfirm.
|
|
21
|
+
readonly property real referenceScale: Collide.cardReferenceScale(Theme.font.bodySmall)
|
|
22
|
+
readonly property real cardPadding: Collide.cardPadding(referenceScale)
|
|
23
|
+
readonly property real cardBottomPadding: Theme.spacing.rowPaddingX
|
|
24
|
+
// The card grows with the labels rather than wrapping one, and Rename and copy keeps the ring.
|
|
25
|
+
readonly property real contentWidth: Collide.cardContentWidth(referenceScale, Theme.dialogWidthRatio, buttons.implicitWidth)
|
|
26
|
+
signal chosen(string choice)
|
|
27
|
+
readonly property var cardItem: card
|
|
28
|
+
readonly property bool buttonsFit: buttons.width <= body.holderWidth
|
|
29
|
+
function buttonItem(name) { return ({cancel: cancelButton, skip: skipButton, rename: renameButton})[name] || null }
|
|
30
|
+
function open(heading, list, note) {
|
|
31
|
+
titleText = heading
|
|
32
|
+
renames = list
|
|
33
|
+
noteText = note
|
|
34
|
+
focusName = Collide.FAT_DEFAULT
|
|
35
|
+
body.contentY = 0
|
|
36
|
+
opened = true
|
|
37
|
+
forceActiveFocus()
|
|
38
|
+
}
|
|
39
|
+
function choose(choice) {
|
|
40
|
+
opened = false
|
|
41
|
+
chosen(choice)
|
|
42
|
+
}
|
|
43
|
+
Flea.Reveal { target: root; shown: root.opened; lift: card }
|
|
44
|
+
// A press lands on its own button first, so the accent never shows one choice while another is taken.
|
|
45
|
+
function press(choice) {
|
|
46
|
+
focusName = choice
|
|
47
|
+
choose(choice)
|
|
48
|
+
}
|
|
49
|
+
Keys.onPressed: function(event) {
|
|
50
|
+
if (event.key === Qt.Key_Escape) root.choose("cancel")
|
|
51
|
+
else if (event.modifiers & (Qt.ControlModifier | Qt.AltModifier | Qt.MetaModifier)) { event.accepted = true; return }
|
|
52
|
+
else if (Collide.activates(event.key)) root.choose(root.focusName)
|
|
53
|
+
else root.focusName = Collide.walk(["cancel", "skip", "rename"], root.focusName, event.key, event.modifiers, "cancel")
|
|
54
|
+
if (root.opened) body.reveal(root.buttonItem(root.focusName))
|
|
55
|
+
event.accepted = true
|
|
56
|
+
}
|
|
57
|
+
Flea.DialogScrim {
|
|
58
|
+
onDismissed: root.choose("cancel")
|
|
59
|
+
}
|
|
60
|
+
Rectangle {
|
|
61
|
+
id: card
|
|
62
|
+
x: Theme.cardOrigin(root.width, width)
|
|
63
|
+
y: Theme.cardOrigin(root.height, height)
|
|
64
|
+
width: Theme.cardSpan(root.contentWidth + 2 * root.cardPadding + 2 * Theme.spacing.hairline, root.width - 2 * Theme.spacing.gap)
|
|
65
|
+
height: Theme.cardSpan(body.wanted + root.cardPadding + root.cardBottomPadding + 2 * Theme.spacing.hairline, root.height - 2 * Theme.spacing.gap)
|
|
66
|
+
color: Theme.color.surface
|
|
67
|
+
border.color: Theme.color.mutedFrame
|
|
68
|
+
border.width: Theme.spacing.hairline
|
|
69
|
+
radius: Style.cornerRadius
|
|
70
|
+
MouseArea {
|
|
71
|
+
anchors.fill: parent
|
|
72
|
+
hoverEnabled: true
|
|
73
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
74
|
+
onWheel: function(wheel) { wheel.accepted = true }
|
|
75
|
+
}
|
|
76
|
+
Flea.CardFrame {
|
|
77
|
+
id: body
|
|
78
|
+
bleed: Theme.focusClearance
|
|
79
|
+
anchors.fill: parent
|
|
80
|
+
anchors.leftMargin: root.cardPadding + Theme.spacing.hairline - Theme.focusClearance
|
|
81
|
+
anchors.rightMargin: root.cardPadding + Theme.spacing.hairline - Theme.focusClearance
|
|
82
|
+
anchors.topMargin: root.cardPadding + Theme.spacing.hairline - Theme.focusClearance
|
|
83
|
+
anchors.bottomMargin: root.cardBottomPadding + Theme.spacing.hairline - Theme.focusClearance
|
|
84
|
+
title: Column {
|
|
85
|
+
width: parent.width
|
|
86
|
+
spacing: Theme.spacing.gap
|
|
87
|
+
Flea.DialogTitle {
|
|
88
|
+
width: parent.width
|
|
89
|
+
text: root.titleText
|
|
90
|
+
}
|
|
91
|
+
Rectangle { width: parent.width; height: Theme.spacing.hairline; color: Theme.color.mutedFrame; opacity: 0.4 }
|
|
92
|
+
}
|
|
93
|
+
buttons: Row {
|
|
94
|
+
id: buttons
|
|
95
|
+
anchors.right: parent.right
|
|
96
|
+
spacing: Theme.spacing.gap
|
|
97
|
+
Flea.DialogButton { id: cancelButton; label: Collide.FAT_BUTTONS.cancel; focused: root.focusName === "cancel"; onActivated: root.press("cancel") }
|
|
98
|
+
Flea.DialogButton { id: skipButton; label: Collide.FAT_BUTTONS.skip; focused: root.focusName === "skip"; onActivated: root.press("skip") }
|
|
99
|
+
Flea.DialogButton { id: renameButton; label: Collide.FAT_BUTTONS.rename; primary: true; focused: root.focusName === "rename"; onActivated: root.press("rename") }
|
|
100
|
+
}
|
|
101
|
+
Column {
|
|
102
|
+
width: parent.width
|
|
103
|
+
spacing: Theme.spacing.gap
|
|
104
|
+
Column {
|
|
105
|
+
width: parent.width
|
|
106
|
+
Repeater {
|
|
107
|
+
model: root.renames
|
|
108
|
+
delegate: Row {
|
|
109
|
+
id: nameRow
|
|
110
|
+
required property var modelData
|
|
111
|
+
// The label column: what is left of the row once the mark and its gap are taken.
|
|
112
|
+
readonly property real labelWidth: Math.max(0, width - Theme.markSize - spacing)
|
|
113
|
+
width: parent.width
|
|
114
|
+
height: Theme.fileRowHeight
|
|
115
|
+
spacing: Theme.spacing.gap
|
|
116
|
+
Flea.Glyph { width: Theme.markSize; height: parent.height; name: nameRow.modelData.d ? "folder" : Icons.glyphFor(nameRow.modelData.i); color: Theme.color.foreground }
|
|
117
|
+
Text {
|
|
118
|
+
id: oldName
|
|
119
|
+
width: Math.min(implicitWidth, Math.max(0, nameRow.labelWidth - arrow.implicitWidth))
|
|
120
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
121
|
+
text: nameRow.modelData.old
|
|
122
|
+
textFormat: Text.PlainText
|
|
123
|
+
elide: Text.ElideRight
|
|
124
|
+
color: Theme.color.muted
|
|
125
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
126
|
+
}
|
|
127
|
+
Text {
|
|
128
|
+
id: arrow
|
|
129
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
130
|
+
text: " → "
|
|
131
|
+
color: Theme.color.foreground
|
|
132
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
133
|
+
}
|
|
134
|
+
Text {
|
|
135
|
+
width: Math.max(0, nameRow.labelWidth - oldName.width - arrow.implicitWidth)
|
|
136
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
137
|
+
text: nameRow.modelData.new
|
|
138
|
+
textFormat: Text.PlainText
|
|
139
|
+
elide: Text.ElideRight
|
|
140
|
+
color: Theme.color.foreground
|
|
141
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
Text {
|
|
147
|
+
width: parent.width
|
|
148
|
+
text: root.noteText
|
|
149
|
+
textFormat: Text.PlainText
|
|
150
|
+
wrapMode: Text.Wrap
|
|
151
|
+
color: Theme.color.foreground
|
|
152
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
pragma Singleton
|
|
2
|
+
import QtQuick
|
|
3
|
+
import Quickshell
|
|
4
|
+
import Quickshell.Io
|
|
5
|
+
import "js/UiState.js" as UiState
|
|
6
|
+
import "js/Startup.js" as Startup
|
|
7
|
+
|
|
8
|
+
// All callers share one operation writer; the Rust updater locks and re-reads before editing.
|
|
9
|
+
QtObject {
|
|
10
|
+
id: root
|
|
11
|
+
readonly property var records: ((ViewState.state.places || {}).favourites || [])
|
|
12
|
+
readonly property bool busy: writer.running
|
|
13
|
+
property bool operationActive: false
|
|
14
|
+
property int recordCount: 0
|
|
15
|
+
property var statuses: ({})
|
|
16
|
+
onRecordsChanged: {
|
|
17
|
+
var previousCount = root.recordCount
|
|
18
|
+
root.recordCount = root.records.length
|
|
19
|
+
root.statuses = ({})
|
|
20
|
+
if (!root.operationActive) root.externalChanged(previousCount)
|
|
21
|
+
}
|
|
22
|
+
property string lastError: ""
|
|
23
|
+
signal wrote()
|
|
24
|
+
signal failed(string message)
|
|
25
|
+
signal completed(string requestId, bool success, string message)
|
|
26
|
+
signal externalChanged(int previousCount)
|
|
27
|
+
|
|
28
|
+
function apply(operation, requestId) {
|
|
29
|
+
if (root.busy) { root.failed("A Favorites change is still being saved."); return false }
|
|
30
|
+
root.lastError = ""
|
|
31
|
+
writer.answer = ""
|
|
32
|
+
writer.errorText = ""
|
|
33
|
+
writer.requestId = requestId || ""
|
|
34
|
+
writer.beforeRecords = root.records
|
|
35
|
+
writer.expectedRecords = UiState.favouritesAfter(root.records, operation)
|
|
36
|
+
root.operationActive = true
|
|
37
|
+
writer.command = [Quickshell.env("FLEA_BIN") || "flea", "--favourites", JSON.stringify(operation)]
|
|
38
|
+
writer.pending = true
|
|
39
|
+
writer.running = true
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
function add(path, label, requestId) {
|
|
43
|
+
return root.apply({ op: "add", record: { label: label, path: path } }, requestId)
|
|
44
|
+
}
|
|
45
|
+
function remove(index) {
|
|
46
|
+
return root.apply({ op: "remove", index: index, expected: root.records })
|
|
47
|
+
}
|
|
48
|
+
function move(index, to) {
|
|
49
|
+
return root.apply({ op: "move", index: index, to: to, expected: root.records })
|
|
50
|
+
}
|
|
51
|
+
function rename(index, label) {
|
|
52
|
+
return root.apply({ op: "rename", index: index, label: label, expected: root.records })
|
|
53
|
+
}
|
|
54
|
+
// One favourite on a dead mount must not hold the single-flight guard forever.
|
|
55
|
+
readonly property int inspectWaitMs: Startup.INSPECT_WAIT_MS
|
|
56
|
+
property var inspectTimeout: Timer {
|
|
57
|
+
interval: root.inspectWaitMs
|
|
58
|
+
onTriggered: inspector.running = false
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function inspect(indices) {
|
|
62
|
+
var pending = indices.filter(function (index) { return root.statuses[index] === undefined })
|
|
63
|
+
if (pending.length === 0 || inspector.running) return
|
|
64
|
+
inspector.answer = ""
|
|
65
|
+
inspector.command = [Quickshell.env("FLEA_BIN") || "flea", "--favourites", JSON.stringify({ op: "inspect", indices: pending.slice(0, 128) })]
|
|
66
|
+
inspector.running = true
|
|
67
|
+
inspectTimeout.restart()
|
|
68
|
+
}
|
|
69
|
+
function finish(expected) {
|
|
70
|
+
var changed = JSON.stringify(root.records) !== JSON.stringify(expected)
|
|
71
|
+
root.operationActive = false
|
|
72
|
+
if (changed) root.externalChanged(writer.beforeRecords.length)
|
|
73
|
+
}
|
|
74
|
+
property var stateChanges: Connections {
|
|
75
|
+
target: ViewState
|
|
76
|
+
function onFavouritesReadFailed(message) { root.failed(message) }
|
|
77
|
+
}
|
|
78
|
+
property var inspection: Process {
|
|
79
|
+
id: inspector
|
|
80
|
+
property string answer: ""
|
|
81
|
+
stdout: StdioCollector { onStreamFinished: inspector.answer = this.text }
|
|
82
|
+
onExited: function (code) {
|
|
83
|
+
inspectTimeout.stop()
|
|
84
|
+
if (code !== 0) return
|
|
85
|
+
try {
|
|
86
|
+
var rows = JSON.parse(inspector.answer).statuses
|
|
87
|
+
var next = Object.assign({}, root.statuses)
|
|
88
|
+
for (var i = 0; i < rows.length; i++) {
|
|
89
|
+
if (JSON.stringify(root.records[rows[i].index]) === JSON.stringify(rows[i].record))
|
|
90
|
+
next[rows[i].index] = rows[i].error
|
|
91
|
+
}
|
|
92
|
+
root.statuses = next
|
|
93
|
+
} catch (error) { root.failed("Flea could not check which favorites still exist.") }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
property var process: Process {
|
|
98
|
+
id: writer
|
|
99
|
+
property string answer: ""
|
|
100
|
+
property string errorText: ""
|
|
101
|
+
property bool pending: false
|
|
102
|
+
property string requestId: ""
|
|
103
|
+
property var beforeRecords: []
|
|
104
|
+
property var expectedRecords: []
|
|
105
|
+
onStarted: writer.pending = false
|
|
106
|
+
onRunningChanged: {
|
|
107
|
+
if (!running && pending) {
|
|
108
|
+
pending = false
|
|
109
|
+
root.finish(writer.beforeRecords)
|
|
110
|
+
root.lastError = "Favorites could not be saved."
|
|
111
|
+
root.failed(root.lastError)
|
|
112
|
+
root.completed(writer.requestId, false, root.lastError)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
stdout: StdioCollector { onStreamFinished: writer.answer = this.text }
|
|
116
|
+
stderr: StdioCollector { onStreamFinished: writer.errorText = this.text.trim() }
|
|
117
|
+
onExited: function (code) {
|
|
118
|
+
writer.pending = false
|
|
119
|
+
if (code !== 0) {
|
|
120
|
+
ViewState.refreshFavourites()
|
|
121
|
+
root.finish(writer.beforeRecords)
|
|
122
|
+
root.lastError = writer.errorText.replace(/^flea: /, "").split("\n")[0] || "Favorites could not be saved."
|
|
123
|
+
root.failed(root.lastError)
|
|
124
|
+
root.completed(writer.requestId, false, root.lastError)
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
var state = JSON.parse(writer.answer)
|
|
129
|
+
if (!state.places || !Array.isArray(state.places.favourites)) throw new Error("missing favorites")
|
|
130
|
+
if (!ViewState.refreshFavourites()) throw new Error("saved favorites could not be read")
|
|
131
|
+
root.finish(writer.expectedRecords)
|
|
132
|
+
root.wrote()
|
|
133
|
+
root.completed(writer.requestId, true, "")
|
|
134
|
+
} catch (error) {
|
|
135
|
+
root.finish(writer.beforeRecords)
|
|
136
|
+
root.lastError = "Favorites were saved, but their new state could not be read."
|
|
137
|
+
root.failed(root.lastError)
|
|
138
|
+
// CLI exit zero means the write committed; a response error must never replay the add.
|
|
139
|
+
root.completed(writer.requestId, true, root.lastError)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
pragma Singleton
|
|
2
|
+
|
|
3
|
+
import QtQuick
|
|
4
|
+
|
|
5
|
+
// The block view's diagrams, drawn by the backend (src/figure.js, Pele in a Bun Worker) through a
|
|
6
|
+
// window's Backend, which WindowBody adopts and releases. Answers come by ticket through `done`,
|
|
7
|
+
// and recent ones are held here, so a revisit or a theme flip back asks nothing.
|
|
8
|
+
QtObject {
|
|
9
|
+
id: root
|
|
10
|
+
|
|
11
|
+
signal done(int ticket, string svg, string error)
|
|
12
|
+
|
|
13
|
+
// Every open window's Backend, adopted as each window is built and released as it closes; the
|
|
14
|
+
// first still open draws. With none every ask fails, and the figure shows its source.
|
|
15
|
+
property var backends: []
|
|
16
|
+
readonly property var backend: root.backends.length > 0 ? root.backends[0] : null
|
|
17
|
+
function adopt(backend) {
|
|
18
|
+
if (backend && root.backends.indexOf(backend) < 0)
|
|
19
|
+
root.backends = root.backends.concat([backend]);
|
|
20
|
+
}
|
|
21
|
+
function release(backend) {
|
|
22
|
+
var at = root.backends.indexOf(backend);
|
|
23
|
+
if (at < 0)
|
|
24
|
+
return;
|
|
25
|
+
root.backends = root.backends.filter(function (other) { return other !== backend; });
|
|
26
|
+
if (at !== 0)
|
|
27
|
+
return;
|
|
28
|
+
// The drawing backend went with its window: what it still owed fails, and a new ask goes to the next one.
|
|
29
|
+
var owed = Object.keys(root.waiting);
|
|
30
|
+
root.waiting = ({});
|
|
31
|
+
root.byRequest = ({});
|
|
32
|
+
for (var i = 0; i < owed.length; i++)
|
|
33
|
+
root.done(Number(owed[i]), "", "backend closed");
|
|
34
|
+
}
|
|
35
|
+
readonly property int cacheMax: 64
|
|
36
|
+
property int seq: 0
|
|
37
|
+
// ticket -> cache key, and backend request id -> ticket, for the answer that names only its id.
|
|
38
|
+
property var waiting: ({})
|
|
39
|
+
property var byRequest: ({})
|
|
40
|
+
property var answerCache: ({})
|
|
41
|
+
property var answerOrder: []
|
|
42
|
+
|
|
43
|
+
// FNV-1a over the table's comma-joined text, "0" for none.
|
|
44
|
+
function tableDigestOf(table) {
|
|
45
|
+
if (!table || table.length === 0)
|
|
46
|
+
return "0";
|
|
47
|
+
var fnvOffset = 0x811c9dc5;
|
|
48
|
+
var fnvPrime = 0x01000193;
|
|
49
|
+
var hexRadix = 16;
|
|
50
|
+
var text = table.join(",");
|
|
51
|
+
var hash = fnvOffset;
|
|
52
|
+
for (var i = 0; i < text.length; i++)
|
|
53
|
+
hash = Math.imul(hash ^ text.charCodeAt(i), fnvPrime);
|
|
54
|
+
return (hash >>> 0).toString(hexRadix);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// The cache key: everything the drawing depends on; a dated figure's day joins it, so the next day's ask draws that day's chart.
|
|
58
|
+
function cacheKeyOf(kind, source, t, display) {
|
|
59
|
+
var key = [t.bg, t.fg, t.accent || "", t.muted || "", t.surface || "", t.font || "", t.bodyPx || 0,
|
|
60
|
+
root.tableDigestOf(t.advances), root.tableDigestOf(t.boldAdvances)].join("|");
|
|
61
|
+
return kind + "\n" + key + (t.today ? "|" + t.today : "") + "\n" + !!display + "\n" + source;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function cached(kind, source, theme, display) {
|
|
65
|
+
var key = root.cacheKeyOf(kind, source, theme, display);
|
|
66
|
+
var hit = root.answerCache[key];
|
|
67
|
+
if (hit !== undefined) {
|
|
68
|
+
var at = root.answerOrder.indexOf(key);
|
|
69
|
+
if (at >= 0)
|
|
70
|
+
root.answerOrder.splice(at, 1);
|
|
71
|
+
root.answerOrder.push(key);
|
|
72
|
+
}
|
|
73
|
+
return hit;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function store(key, svg) {
|
|
77
|
+
var at = root.answerOrder.indexOf(key);
|
|
78
|
+
if (at >= 0)
|
|
79
|
+
root.answerOrder.splice(at, 1);
|
|
80
|
+
root.answerCache[key] = svg;
|
|
81
|
+
root.answerOrder.push(key);
|
|
82
|
+
while (root.answerOrder.length > root.cacheMax)
|
|
83
|
+
delete root.answerCache[root.answerOrder.shift()];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// A ticket for one figure; its answer comes later through done(ticket, svg, error), never during this call.
|
|
87
|
+
function ask(kind, source, display, theme) {
|
|
88
|
+
root.seq++;
|
|
89
|
+
var ticket = root.seq;
|
|
90
|
+
var hit = root.cached(kind, source, theme, display);
|
|
91
|
+
if (hit !== undefined) {
|
|
92
|
+
Qt.callLater(function () { root.done(ticket, hit, ""); });
|
|
93
|
+
return ticket;
|
|
94
|
+
}
|
|
95
|
+
if (kind !== "mermaid" || root.backend === null || typeof root.backend.askFigure !== "function") {
|
|
96
|
+
Qt.callLater(function () { root.done(ticket, "", kind !== "mermaid" ? "unknown figure kind" : "no backend"); });
|
|
97
|
+
return ticket;
|
|
98
|
+
}
|
|
99
|
+
var id = root.backend.askFigure(source, theme);
|
|
100
|
+
root.waiting[ticket] = root.cacheKeyOf(kind, source, theme, display);
|
|
101
|
+
root.byRequest[id] = ticket;
|
|
102
|
+
return ticket;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
property Connections answers: Connections {
|
|
106
|
+
target: root.backend
|
|
107
|
+
ignoreUnknownSignals: true
|
|
108
|
+
function onFigureResult(message) {
|
|
109
|
+
var ticket = root.byRequest[message.id];
|
|
110
|
+
if (ticket === undefined)
|
|
111
|
+
return;
|
|
112
|
+
delete root.byRequest[message.id];
|
|
113
|
+
var key = root.waiting[ticket];
|
|
114
|
+
delete root.waiting[ticket];
|
|
115
|
+
if (message.svg)
|
|
116
|
+
root.store(key, message.svg);
|
|
117
|
+
root.done(ticket, message.svg || "", message.svg ? "" : (message.error || "render failed"));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
package/ui/FileDrag.qml
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "js/Drag.js" as DragOps
|
|
3
|
+
import "js/DragOut.js" as DragOut
|
|
4
|
+
import "js/Ops.js" as Ops
|
|
5
|
+
import "js/Search.js" as Search
|
|
6
|
+
|
|
7
|
+
// The platform drag belongs to the view: a tab switch may destroy the pressed delegate inside QDrag.exec().
|
|
8
|
+
Item {
|
|
9
|
+
id: root
|
|
10
|
+
|
|
11
|
+
required property var pane
|
|
12
|
+
// A peek column's {pane, dir, v, w}: its rows are in no listing, so a lift carries the row's own path instead.
|
|
13
|
+
property var peekSource: null
|
|
14
|
+
// The window the gesture speaks in: the listing's pane, or the pane a peek column belongs to.
|
|
15
|
+
readonly property var host: root.pane || (root.peekSource ? root.peekSource.pane : null)
|
|
16
|
+
property var dragRows: []
|
|
17
|
+
// The numbering dragRows were read in, fixed at the lift so a drop after a re-list is refused rather than resolved anew.
|
|
18
|
+
property real dragListing: 0
|
|
19
|
+
property int dropIndex: -1
|
|
20
|
+
// The hovered folder a drop lands in after it opens: a swap may rebuild the lit delegate on another row.
|
|
21
|
+
property string dropDest: ""
|
|
22
|
+
property int dropDestDev: 0
|
|
23
|
+
property bool dragCopy: false
|
|
24
|
+
property bool dragShift: false
|
|
25
|
+
property bool dragLink: false
|
|
26
|
+
property bool awaitingPaths: false
|
|
27
|
+
property bool buttonUp: false
|
|
28
|
+
property var dragMime: ({})
|
|
29
|
+
property var feedback: null
|
|
30
|
+
// Drops callout 2: the folder the pointer rests on and the autoscroll band it rests in; the timers are built on first use.
|
|
31
|
+
property int hoverIndex: -1
|
|
32
|
+
property string hoverPath: ""
|
|
33
|
+
property int scrollDir: 0
|
|
34
|
+
property var hoverTimers: null
|
|
35
|
+
|
|
36
|
+
Drag.dragType: Drag.Automatic
|
|
37
|
+
// Plain lift offers copy alone, narrowed by modifiers (a browser uploader refuses move); Ctrl copy, Shift move, both link, so any receiver takes the lift's verb.
|
|
38
|
+
Drag.supportedActions: root.dragLink ? Qt.LinkAction : root.dragCopy ? Qt.CopyAction : root.dragShift ? Qt.MoveAction : Qt.CopyAction
|
|
39
|
+
Drag.proposedAction: root.dragLink ? Qt.LinkAction : root.dragCopy ? Qt.CopyAction : root.dragShift ? Qt.MoveAction : Qt.CopyAction
|
|
40
|
+
Drag.mimeData: root.dragMime
|
|
41
|
+
// The receiver moves or copies itself: deleting on its acceptance would trash files before Files reads them.
|
|
42
|
+
Drag.onDragFinished: function () { root.liftEnded() }
|
|
43
|
+
|
|
44
|
+
function liftBegan(index, centroid) {
|
|
45
|
+
if (!root.pane || root.pane.listInFlight || index < 0 || !root.pane.rowFor(index)) return
|
|
46
|
+
if (root.pane.cancelSlowClick) root.pane.cancelSlowClick()
|
|
47
|
+
root.buttonUp = false
|
|
48
|
+
root.awaitingPaths = false
|
|
49
|
+
if (root.pane) root.pane.awaitingPaths = false
|
|
50
|
+
root.dragRows = DragOps.carried(root.pane, index)
|
|
51
|
+
root.dragListing = root.pane.backend ? root.pane.backend.heldListing : 0
|
|
52
|
+
root.dropIndex = -1
|
|
53
|
+
root.dropDest = ""
|
|
54
|
+
root.dropDestDev = 0
|
|
55
|
+
// Ctrl is the threshold's, and a paths reply must not sample it again.
|
|
56
|
+
root.dragCopy = DragOps.copying(centroid.modifiers)
|
|
57
|
+
root.dragShift = DragOps.shifting(centroid.modifiers)
|
|
58
|
+
root.dragLink = DragOps.linking(centroid.modifiers)
|
|
59
|
+
root.dragMime = DragOps.mimeFor(root.pane, root.dragRows, root.dragCopy, root.dragShift)
|
|
60
|
+
if (root.dragMime["text/uri-list"]) {
|
|
61
|
+
root.startOffer()
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
if (!root.pane.backend || !DragOut.askAllowed(root.pane.pathsPending, root.pane.clipPending)) {
|
|
65
|
+
root.cannotLeave()
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
root.awaitingPaths = true
|
|
69
|
+
if (root.pane) root.pane.awaitingPaths = true
|
|
70
|
+
var dev = root.pane.backend.dirDev || 0
|
|
71
|
+
root.feedback = { own: true, copy: root.dragCopy, shift: root.dragShift, dev: dev,
|
|
72
|
+
deletable: DragOps.listingDeletable(root.pane), count: root.dragRows.length, canLeave: true }
|
|
73
|
+
root.say(DragOps.feedbackLine(root.feedback, "", dev))
|
|
74
|
+
var rows = root.dragRows.slice()
|
|
75
|
+
var listing = root.dragListing
|
|
76
|
+
var copy = root.dragCopy
|
|
77
|
+
var shift = root.dragShift
|
|
78
|
+
var link = root.dragLink
|
|
79
|
+
root.pane.pathsPending = {
|
|
80
|
+
kind: "drag", rows: rows, listing: listing, copy: copy, shift: shift, link: link,
|
|
81
|
+
deliver: function (list, pending) { root.deliverPaths(list, pending) }
|
|
82
|
+
}
|
|
83
|
+
root.pane.backend.send({ c: "paths", rows: rows, listing: listing })
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function liftPeek(row, centroid) {
|
|
87
|
+
if (!root.peekSource || !row) return
|
|
88
|
+
root.buttonUp = false
|
|
89
|
+
root.dragRows = []
|
|
90
|
+
root.dragListing = 0
|
|
91
|
+
root.dropIndex = -1
|
|
92
|
+
root.dropDest = ""
|
|
93
|
+
root.dropDestDev = 0
|
|
94
|
+
root.dragCopy = DragOps.copying(centroid.modifiers)
|
|
95
|
+
root.dragShift = DragOps.shifting(centroid.modifiers)
|
|
96
|
+
root.dragLink = DragOps.linking(centroid.modifiers)
|
|
97
|
+
root.dragMime = root.peekMime(row, root.dragCopy, root.dragShift)
|
|
98
|
+
root.startOffer()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// No rows in the marker, so no receiver resolves it by index (DragOps.canDropByIndex needs rows); the uri is the column's directory plus the name.
|
|
102
|
+
function peekMime(row, copy, shift) {
|
|
103
|
+
var src = root.peekSource
|
|
104
|
+
var path = src.pane.join(src.dir, row.n)
|
|
105
|
+
var mime = {}
|
|
106
|
+
mime[DragOps.ROWS_MIME] = DragOps.markerPayload([], copy, src.dir, src.v, src.w, shift === true)
|
|
107
|
+
mime["text/uri-list"] = DragOps.uriFor(path) + "\r\n"
|
|
108
|
+
mime["text/plain"] = path
|
|
109
|
+
return mime
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function liftReleased() {
|
|
113
|
+
root.buttonUp = true
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function liftMoved(centroid) {
|
|
117
|
+
if (root.awaitingPaths || root.Drag.active) return
|
|
118
|
+
root.dragCopy = DragOps.copying(centroid.modifiers)
|
|
119
|
+
root.dragShift = DragOps.shifting(centroid.modifiers)
|
|
120
|
+
root.dragLink = DragOps.linking(centroid.modifiers)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function startOffer() {
|
|
124
|
+
root.dragMime = DragOut.keys.stamped(root.dragMime)
|
|
125
|
+
root.feedback = DragOps.feedbackFor(root.dragMime[DragOps.ROWS_MIME],
|
|
126
|
+
(root.dragMime["text/uri-list"] || "").split("\r\n"))
|
|
127
|
+
root.showTarget("", root.feedback.dev)
|
|
128
|
+
// Drag.Automatic runs QDrag::exec synchronously, so a finish inside it must not overwrite the hold: arm the watch first.
|
|
129
|
+
if (root.host) root.host.dragHolding = true
|
|
130
|
+
root.Drag.active = true
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function deliverPaths(list, pending) {
|
|
134
|
+
root.awaitingPaths = false
|
|
135
|
+
if (root.pane) root.pane.awaitingPaths = false
|
|
136
|
+
var held = root.pane && root.pane.backend ? root.pane.backend.heldListing : 0
|
|
137
|
+
if (root.buttonUp || held !== pending.listing || !list || list.length !== pending.rows.length) {
|
|
138
|
+
root.cannotLeave()
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
root.dragCopy = pending.copy
|
|
142
|
+
root.dragShift = pending.shift === true
|
|
143
|
+
root.dragLink = pending.link === true || (pending.copy === true && pending.shift === true)
|
|
144
|
+
root.dragMime = root.mimeForPaths(pending.rows, list, pending.copy, root.dragShift)
|
|
145
|
+
root.startOffer()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function mimeForPaths(rows, paths, copy, shift) {
|
|
149
|
+
var mime = {}
|
|
150
|
+
var dev = root.pane.backend ? root.pane.backend.dirDev : 0
|
|
151
|
+
mime[DragOps.ROWS_MIME] = DragOps.markerPayload(rows, copy, Search.baseOf(root.pane), dev, DragOps.listingDeletable(root.pane), shift === true)
|
|
152
|
+
var uris = []
|
|
153
|
+
for (var i = 0; i < paths.length; i++) uris.push(DragOps.uriFor(paths[i]))
|
|
154
|
+
mime["text/uri-list"] = uris.join("\r\n") + "\r\n"
|
|
155
|
+
mime["text/plain"] = paths.join("\n")
|
|
156
|
+
return mime
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Too wide carries no uri-list, so the gesture ends here and the refusal reads as a pane message.
|
|
160
|
+
function cannotLeave() {
|
|
161
|
+
var line = DragOps.line(root.dragRows.length, "", root.dragCopy, root.dragLink) + DragOps.reachNote(false)
|
|
162
|
+
root.awaitingPaths = false
|
|
163
|
+
root.liftEnded()
|
|
164
|
+
if (root.host) root.host.message(line, false)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function verbAt(marker, row, seenCopy, seenShift) {
|
|
168
|
+
return DragOps.verbFor(DragOps.isOwnDrag(marker), DragOps.dropHeld(DragOps.markerCopying(marker), seenCopy),
|
|
169
|
+
DragOps.dropHeld(DragOps.markerShift(marker), seenShift), DragOps.markerDev(marker),
|
|
170
|
+
row ? row.v : 0, DragOps.markerDeletable(marker))
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function liftEnded() {
|
|
174
|
+
root.Drag.active = false
|
|
175
|
+
if (root.host) { root.host.dragHolding = false; root.host.awaitingPaths = false; root.host.pointerHeld = false }
|
|
176
|
+
root.dragRows = []
|
|
177
|
+
root.dragListing = 0
|
|
178
|
+
root.dragMime = ({})
|
|
179
|
+
root.dropIndex = -1
|
|
180
|
+
root.dropDest = ""
|
|
181
|
+
root.dropDestDev = 0
|
|
182
|
+
root.dragCopy = false
|
|
183
|
+
root.dragShift = false
|
|
184
|
+
root.dragLink = false
|
|
185
|
+
root.feedback = null
|
|
186
|
+
root.hoverIndex = -1
|
|
187
|
+
root.hoverPath = ""
|
|
188
|
+
root.scrollDir = 0
|
|
189
|
+
if (root.hoverTimers) root.hoverTimers.stopRest()
|
|
190
|
+
// A different view may now speak for this gesture; its activity is separate from every transfer.
|
|
191
|
+
var bar = root.host ? root.host.statusBar : null
|
|
192
|
+
if (bar && bar.dragFeedbackOwner) bar.dragFeedbackOwner.say("")
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// A folder row under the pointer starts the rest that opens it and the band that scrolls; a move restarts both.
|
|
196
|
+
function hoverBegan(index, path, y, height) {
|
|
197
|
+
root.hoverIndex = index
|
|
198
|
+
root.hoverPath = path
|
|
199
|
+
root.scrollDir = DragOut.band(y, height)
|
|
200
|
+
root.ensureHoverTimers()
|
|
201
|
+
root.hoverTimers.rest()
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function hoverMoved(y, height) {
|
|
205
|
+
root.scrollDir = DragOut.band(y, height)
|
|
206
|
+
if (root.scrollDir !== 0) root.ensureHoverTimers()
|
|
207
|
+
if (root.hoverTimers) root.hoverTimers.rest()
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function hoverEnded() {
|
|
211
|
+
root.hoverIndex = -1
|
|
212
|
+
root.hoverPath = ""
|
|
213
|
+
root.scrollDir = 0
|
|
214
|
+
if (root.hoverTimers) root.hoverTimers.stopRest()
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function ensureHoverTimers() {
|
|
218
|
+
if (root.hoverTimers !== null)
|
|
219
|
+
return
|
|
220
|
+
root.hoverTimers = Qt.createComponent("HoverTimers.qml").createObject(root, { session: root })
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function say(text) {
|
|
224
|
+
var bar = root.host ? root.host.statusBar : null
|
|
225
|
+
if (!bar) return
|
|
226
|
+
if (!text) {
|
|
227
|
+
if (bar.dragFeedbackOwner === root) {
|
|
228
|
+
bar.dragFeedbackOwner = null
|
|
229
|
+
bar.setActivity(root, "", Ops.emptyTransfer())
|
|
230
|
+
}
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
if (bar.activities.some(function (entry) { return entry.transfer.running })) return
|
|
234
|
+
if (bar.dragFeedbackOwner && bar.dragFeedbackOwner !== root)
|
|
235
|
+
bar.setActivity(bar.dragFeedbackOwner, "", Ops.emptyTransfer())
|
|
236
|
+
bar.dragFeedbackOwner = root
|
|
237
|
+
bar.setActivity(root, text, Ops.emptyTransfer())
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function enterTarget(marker, urls, name, destDev, shelf, proposed) {
|
|
241
|
+
root.feedback = DragOps.feedbackFor(marker, urls, shelf, proposed)
|
|
242
|
+
root.showTarget(name, destDev)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function showTarget(name, destDev) {
|
|
246
|
+
if (!root.feedback) return
|
|
247
|
+
root.dragCopy = DragOps.copyingFor(root.feedback, destDev)
|
|
248
|
+
root.dragLink = DragOps.linkingFor(root.feedback, destDev)
|
|
249
|
+
root.say(DragOps.feedbackLine(root.feedback, name, destDev))
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function leaveTarget() {
|
|
253
|
+
var bar = root.host ? root.host.statusBar : null
|
|
254
|
+
if (!bar || bar.dragFeedbackOwner !== root) return
|
|
255
|
+
root.say(root.feedback && root.feedback.own
|
|
256
|
+
? DragOps.feedbackLine(root.feedback, "", root.feedback.dev) : "")
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
Connections {
|
|
260
|
+
target: root.host ? root.host.statusBar : null
|
|
261
|
+
function onActivitiesChanged() {
|
|
262
|
+
var bar = root.host.statusBar
|
|
263
|
+
if (bar.dragFeedbackOwner === root
|
|
264
|
+
&& bar.activities.some(function (entry) { return entry.transfer.running })) root.say("")
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|