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,396 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Format.js" as Format
|
|
5
|
+
import "js/PropertyFacts.js" as PropertyFacts
|
|
6
|
+
import "js/Tags.js" as Tags
|
|
7
|
+
|
|
8
|
+
// Menu-only actions share the existing card, field and button language.
|
|
9
|
+
FocusScope {
|
|
10
|
+
id: root
|
|
11
|
+
anchors.fill: parent
|
|
12
|
+
visible: opened || opacity > 0
|
|
13
|
+
// Closed means no input, even while the fade-out is still drawn.
|
|
14
|
+
enabled: opened
|
|
15
|
+
opacity: 0
|
|
16
|
+
Flea.Reveal { target: root; shown: root.opened; lift: card }
|
|
17
|
+
property bool opened: false
|
|
18
|
+
property string action: ""
|
|
19
|
+
property int requestId: 0
|
|
20
|
+
property string folder: ""
|
|
21
|
+
property var facts: ({})
|
|
22
|
+
// A folder's walk as the card knows it, null for anything else; the Size and Contains lines read it as it moves.
|
|
23
|
+
property var walk: null
|
|
24
|
+
// A file's codec, bit rate or photo facts as the facts reply sent them, empty until it lands; the pairs between Size and Modified read it.
|
|
25
|
+
property var extra: ({})
|
|
26
|
+
property string errorText: ""
|
|
27
|
+
property bool busy: false
|
|
28
|
+
property bool committing: false
|
|
29
|
+
property bool checkPending: false
|
|
30
|
+
property Item focusHolder: null
|
|
31
|
+
readonly property bool inputAction: action === "newFile" || action === "moveTo" || action === "copyTo"
|
|
32
|
+
readonly property bool deletionActive: action === "deletePermanently" && committing
|
|
33
|
+
readonly property bool canSubmit: !busy && inputAction && field.text.length > 0
|
|
34
|
+
// The lines that change in place while the folder counts; the model names them and is not rebuilt as the count moves.
|
|
35
|
+
readonly property var liveLines: facts.ok ? ({size: PropertyFacts.size(facts.bytes, walk), contains: PropertyFacts.contains(walk)}) : ({})
|
|
36
|
+
// Raw.html and Properties040: a photo's Camera, Lens, Exposure and Taken, the ones its EXIF names, sit before Modified.
|
|
37
|
+
readonly property var extraPairs: PropertyFacts.extraPairs(Object.assign({ok: root.facts.ok}, root.extra), root.facts.photo)
|
|
38
|
+
readonly property string title: ({moveTo: "Move to", copyTo: "Copy to", properties: "Properties", newFile: "New file", deletePermanently: "Delete permanently"})[action] || ""
|
|
39
|
+
// The card and its scrim step aside for the confirmation, and stay aside while it fades out with a closing dialog.
|
|
40
|
+
readonly property bool cardShown: !confirmation.opened && (root.opened || !confirmation.visible)
|
|
41
|
+
// Cleanup a closing reply defers until the fade ended, so the card holds still while it fades out.
|
|
42
|
+
property var settle: null
|
|
43
|
+
readonly property var cardItem: card
|
|
44
|
+
readonly property var confirmationItem: confirmation
|
|
45
|
+
readonly property var closeItem: closeButton
|
|
46
|
+
readonly property var submitItem: submitButton
|
|
47
|
+
readonly property var fieldItem: field
|
|
48
|
+
signal requested(var message)
|
|
49
|
+
signal approved(var message)
|
|
50
|
+
signal created(string path)
|
|
51
|
+
signal deleted(var message)
|
|
52
|
+
signal closed()
|
|
53
|
+
|
|
54
|
+
function open(operation, identity, parentPath, holder) {
|
|
55
|
+
action = operation
|
|
56
|
+
requestId = identity
|
|
57
|
+
folder = parentPath
|
|
58
|
+
focusHolder = holder
|
|
59
|
+
walk = null
|
|
60
|
+
extra = ({})
|
|
61
|
+
facts = ({})
|
|
62
|
+
errorText = ""
|
|
63
|
+
checkPending = false
|
|
64
|
+
confirmation.close()
|
|
65
|
+
settle = null
|
|
66
|
+
field.text = operation === "newFile" ? "New File" : parentPath
|
|
67
|
+
busy = operation === "properties" || operation === "deletePermanently"
|
|
68
|
+
committing = false
|
|
69
|
+
opened = true
|
|
70
|
+
body.contentY = 0
|
|
71
|
+
if (inputAction) { field.forceActiveFocus(); field.selectAll() }
|
|
72
|
+
else closeButton.forceActiveFocus()
|
|
73
|
+
if (busy) requested({c: "menuaction", op: operation === "deletePermanently" ? "prepareDelete" : "properties", id: requestId})
|
|
74
|
+
}
|
|
75
|
+
// Two dialogs share the one request id, so this one answers only for the ops it asked for:
|
|
76
|
+
// routing an Open with reply in here closed a Properties card that had just opened over it.
|
|
77
|
+
readonly property var ownedOps: ["properties", "prepareDelete", "refreshDelete", "checkDelete",
|
|
78
|
+
"delete", "validate", "newFile", "contents", "facts", ""]
|
|
79
|
+
function receive(message) {
|
|
80
|
+
if ((!opened && !deletionActive) || message.id !== requestId || message.op === "close") return
|
|
81
|
+
if (root.ownedOps.indexOf(message.op === undefined ? "" : message.op) < 0) return
|
|
82
|
+
if (deletionActive && message.op !== "delete") return
|
|
83
|
+
// A late count after the card left Properties changes nothing; a refused one ends as the floor already counted.
|
|
84
|
+
if (message.op === "contents") { if (walk) walk = PropertyFacts.next(walk, message); return }
|
|
85
|
+
// A refused or late facts reply adds no pair; the card already says everything else.
|
|
86
|
+
if (message.op === "facts") { if (message.ok) extra = message; return }
|
|
87
|
+
// A reply that ends the card keeps its busy look until the fade ended.
|
|
88
|
+
var ends = message.ok && !message.stale && (message.op === undefined || message.op === "" || message.op === "validate" || message.op === "newFile")
|
|
89
|
+
if (!ends) { busy = false; committing = false }
|
|
90
|
+
if (!message.ok) {
|
|
91
|
+
confirmation.close()
|
|
92
|
+
opened = true
|
|
93
|
+
closeButton.forceActiveFocus()
|
|
94
|
+
errorText = message.error || "That action could not be completed."
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
if (message.stale || message.op === "checkDelete" && !message.valid) { refreshDeletion(); return }
|
|
98
|
+
if (message.op === "prepareDelete" || message.op === "refreshDelete") {
|
|
99
|
+
facts = message
|
|
100
|
+
if (checkPending) { checkPending = false; refreshDeletion() }
|
|
101
|
+
else confirmation.open(message)
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
if (message.op === "checkDelete") {
|
|
105
|
+
if (checkPending) { checkPending = false; refreshDeletion() }
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
if (message.op === "delete") { deleted(Object.assign({count: facts.count}, message)); finish(); return }
|
|
109
|
+
if (message.op === "properties") {
|
|
110
|
+
walk = message.directory ? PropertyFacts.begin(message) : null
|
|
111
|
+
facts = message
|
|
112
|
+
if (walk) requested({c: "menuaction", op: "contents", id: requestId})
|
|
113
|
+
else if (message.kind === "File") requested({c: "menuaction", op: "facts", id: requestId})
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
if (message.op === "validate") { approved(message); closeSettled(); return }
|
|
117
|
+
if (message.op === "newFile") created(message.path)
|
|
118
|
+
closeSettled()
|
|
119
|
+
}
|
|
120
|
+
// The close of a finished reply: the busy look it left is cleared once the card is gone.
|
|
121
|
+
function closeSettled() {
|
|
122
|
+
settle = function () { busy = false; committing = false }
|
|
123
|
+
finish()
|
|
124
|
+
settleNow()
|
|
125
|
+
}
|
|
126
|
+
function settleNow() {
|
|
127
|
+
if (opacity !== 0 || settle === null) return
|
|
128
|
+
var run = settle
|
|
129
|
+
settle = null
|
|
130
|
+
run()
|
|
131
|
+
}
|
|
132
|
+
onOpacityChanged: root.settleNow()
|
|
133
|
+
function close() {
|
|
134
|
+
if (!opened || busy && committing && action === "newFile") return
|
|
135
|
+
finish()
|
|
136
|
+
}
|
|
137
|
+
function finish() {
|
|
138
|
+
requested({c: "menuaction", op: "close", id: requestId})
|
|
139
|
+
confirmation.close()
|
|
140
|
+
opened = false
|
|
141
|
+
closed()
|
|
142
|
+
if (focusHolder) focusHolder.forceActiveFocus()
|
|
143
|
+
}
|
|
144
|
+
function refreshDeletion() {
|
|
145
|
+
confirmation.close()
|
|
146
|
+
opened = true
|
|
147
|
+
busy = true
|
|
148
|
+
errorText = ""
|
|
149
|
+
closeButton.forceActiveFocus()
|
|
150
|
+
requested({c: "menuaction", op: "refreshDelete", id: requestId})
|
|
151
|
+
}
|
|
152
|
+
function checkDeletion() {
|
|
153
|
+
if (!opened || action !== "deletePermanently" || errorText) return
|
|
154
|
+
if (busy) { checkPending = true; return }
|
|
155
|
+
busy = true
|
|
156
|
+
requested({c: "menuaction", op: "checkDelete", id: requestId, token: facts.token})
|
|
157
|
+
}
|
|
158
|
+
function sourceChanged() {
|
|
159
|
+
if (!opened || action !== "deletePermanently" || errorText) return
|
|
160
|
+
confirmation.close()
|
|
161
|
+
if (busy) checkPending = true
|
|
162
|
+
else refreshDeletion()
|
|
163
|
+
}
|
|
164
|
+
function submit() {
|
|
165
|
+
if (!canSubmit) return
|
|
166
|
+
if (action !== "newFile" && field.text.charAt(0) !== "/") {
|
|
167
|
+
errorText = "Enter a full folder path, starting with /."
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
if (action === "newFile" && (field.text === "." || field.text === ".." || field.text.indexOf("/") >= 0)) {
|
|
171
|
+
errorText = "Enter a name without a /."
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
if (action === "newFile") body.forceActiveFocus()
|
|
175
|
+
else closeButton.forceActiveFocus()
|
|
176
|
+
busy = true
|
|
177
|
+
committing = true
|
|
178
|
+
errorText = ""
|
|
179
|
+
if (action === "newFile") requested({c: "newfile", op: "newFile", id: requestId, path: folder, name: field.text})
|
|
180
|
+
else requested({c: "menuaction", op: "validate", id: requestId, action: action, dest: field.text})
|
|
181
|
+
}
|
|
182
|
+
// Each focusable child routes Tab here before Qt can move focus outside the card.
|
|
183
|
+
function stepFocus(back) {
|
|
184
|
+
var items = [field, closeButton, submitButton].filter(function(item) {
|
|
185
|
+
return item.visible && item.enabled && item.activeFocusOnTab
|
|
186
|
+
})
|
|
187
|
+
if (!items.length) return
|
|
188
|
+
var current = -1
|
|
189
|
+
for (var i = 0; i < items.length; i++) if (items[i].activeFocus) current = i
|
|
190
|
+
var next = current < 0 ? (back ? items.length - 1 : 0)
|
|
191
|
+
: (current + (back ? -1 : 1) + items.length) % items.length
|
|
192
|
+
items[next].forceActiveFocus()
|
|
193
|
+
}
|
|
194
|
+
Keys.onTabPressed: function(event) { root.stepFocus((event.modifiers & Qt.ShiftModifier) !== 0); event.accepted = true }
|
|
195
|
+
Keys.onBacktabPressed: function(event) { root.stepFocus(true); event.accepted = true }
|
|
196
|
+
Keys.onEscapePressed: function(event) { root.close(); event.accepted = true }
|
|
197
|
+
Keys.onPressed: function(event) { event.accepted = true }
|
|
198
|
+
Rectangle {
|
|
199
|
+
anchors.fill: parent
|
|
200
|
+
visible: root.cardShown
|
|
201
|
+
color: Theme.color.background
|
|
202
|
+
opacity: 0.5
|
|
203
|
+
MouseArea {
|
|
204
|
+
anchors.fill: parent
|
|
205
|
+
hoverEnabled: true
|
|
206
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
207
|
+
onClicked: root.close()
|
|
208
|
+
onWheel: function(wheel) { wheel.accepted = true }
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
Rectangle {
|
|
212
|
+
id: card
|
|
213
|
+
visible: root.cardShown
|
|
214
|
+
x: Theme.cardOrigin(root.width, width)
|
|
215
|
+
y: Theme.cardOrigin(root.height, height)
|
|
216
|
+
width: Theme.cardSpan(Theme.space(420) * Theme.dialogWidthRatio, root.width - 2 * Theme.spacing.gap)
|
|
217
|
+
height: Theme.cardSpan(body.wanted + 2 * Theme.spacing.rowPaddingX, root.height - 2 * Theme.spacing.gap)
|
|
218
|
+
color: Theme.color.surface
|
|
219
|
+
border.color: Theme.color.mutedFrame
|
|
220
|
+
border.width: Theme.spacing.hairline
|
|
221
|
+
radius: Style.cornerRadius
|
|
222
|
+
MouseArea {
|
|
223
|
+
anchors.fill: parent
|
|
224
|
+
hoverEnabled: true
|
|
225
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
226
|
+
onWheel: function(wheel) { wheel.accepted = true }
|
|
227
|
+
}
|
|
228
|
+
Flea.CardFrame {
|
|
229
|
+
id: body
|
|
230
|
+
bleed: Theme.focusClearance
|
|
231
|
+
anchors.fill: parent
|
|
232
|
+
anchors.margins: Theme.spacing.rowPaddingX - Theme.focusClearance
|
|
233
|
+
title: Column {
|
|
234
|
+
width: parent.width
|
|
235
|
+
spacing: Theme.spacing.gap
|
|
236
|
+
Flea.DialogTitle {
|
|
237
|
+
width: parent.width
|
|
238
|
+
text: root.title
|
|
239
|
+
}
|
|
240
|
+
Rectangle { width: parent.width; height: Theme.spacing.hairline; color: Theme.color.mutedFrame; opacity: 0.4 }
|
|
241
|
+
}
|
|
242
|
+
buttons: Row {
|
|
243
|
+
anchors.right: parent.right
|
|
244
|
+
spacing: Theme.spacing.gap
|
|
245
|
+
Flea.DialogButton {
|
|
246
|
+
id: closeButton
|
|
247
|
+
label: root.action === "properties" ? "Close" : "Cancel"
|
|
248
|
+
available: !(root.busy && root.committing && root.action === "newFile")
|
|
249
|
+
tabHandle: true
|
|
250
|
+
tabStop: true
|
|
251
|
+
onTabbed: function(from, back) { root.stepFocus(back) }
|
|
252
|
+
onActivated: root.close()
|
|
253
|
+
}
|
|
254
|
+
Flea.DialogButton {
|
|
255
|
+
id: submitButton
|
|
256
|
+
visible: root.action !== "properties" && root.action !== "deletePermanently"
|
|
257
|
+
label: root.action === "newFile" ? "Create" : root.action === "moveTo" ? "Move" : "Copy"
|
|
258
|
+
primary: true
|
|
259
|
+
available: root.canSubmit
|
|
260
|
+
tabHandle: true
|
|
261
|
+
tabStop: true
|
|
262
|
+
onTabbed: function(from, back) { root.stepFocus(back) }
|
|
263
|
+
onActivated: root.submit()
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
Column {
|
|
267
|
+
width: parent.width
|
|
268
|
+
spacing: Theme.spacing.gap
|
|
269
|
+
Text {
|
|
270
|
+
width: parent.width
|
|
271
|
+
visible: root.inputAction
|
|
272
|
+
text: root.action === "newFile" ? "Name" : "Destination folder"
|
|
273
|
+
textFormat: Text.PlainText
|
|
274
|
+
color: Theme.color.foreground
|
|
275
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
276
|
+
}
|
|
277
|
+
Rectangle {
|
|
278
|
+
visible: root.inputAction
|
|
279
|
+
width: parent.width
|
|
280
|
+
height: Theme.rowHeight - Theme.spacing.rowPaddingY
|
|
281
|
+
color: Theme.color.background
|
|
282
|
+
border.color: field.activeFocus ? Theme.color.accent : Theme.color.mutedFrame
|
|
283
|
+
border.width: Theme.spacing.hairline
|
|
284
|
+
TextInput {
|
|
285
|
+
id: field
|
|
286
|
+
anchors.left: parent.left
|
|
287
|
+
anchors.right: parent.right
|
|
288
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
289
|
+
anchors.leftMargin: Theme.spacing.gap
|
|
290
|
+
anchors.rightMargin: Theme.spacing.gap
|
|
291
|
+
color: Theme.color.foreground
|
|
292
|
+
selectionColor: Theme.color.accent
|
|
293
|
+
selectedTextColor: Theme.color.background
|
|
294
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
295
|
+
activeFocusOnTab: root.inputAction
|
|
296
|
+
enabled: !root.busy
|
|
297
|
+
clip: true
|
|
298
|
+
selectByMouse: true
|
|
299
|
+
Accessible.name: root.action === "newFile" ? "Filename" : "Destination folder"
|
|
300
|
+
Keys.onTabPressed: function(event) { root.stepFocus((event.modifiers & Qt.ShiftModifier) !== 0) }
|
|
301
|
+
Keys.onBacktabPressed: root.stepFocus(true)
|
|
302
|
+
Keys.onReturnPressed: root.submit()
|
|
303
|
+
Keys.onEnterPressed: root.submit()
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
Repeater {
|
|
307
|
+
model: root.action === "properties" && root.facts.ok ? [
|
|
308
|
+
["Path", root.facts.path],
|
|
309
|
+
["Type", root.facts.kind],
|
|
310
|
+
["Size", "", "size"],
|
|
311
|
+
...(root.facts.directory ? [["Contains", "", "contains"]] : []),
|
|
312
|
+
...(root.extraPairs || []),
|
|
313
|
+
// A foreign word stays untouched and shows here, so a tag another app set is visible.
|
|
314
|
+
...((root.facts.tags || []).length > 0 ? [["Tags", (root.facts.tags || []).join(", ")]] : []),
|
|
315
|
+
["Modified", Format.date(root.facts.modified)],
|
|
316
|
+
["Permissions", root.facts.mode],
|
|
317
|
+
["Owner", (root.facts.owner || "Unknown") + " (uid " + root.facts.uid + ")"],
|
|
318
|
+
["Group", "gid " + root.facts.gid],
|
|
319
|
+
...(root.facts.symlink ? [["Link target", root.facts.target]] : [])
|
|
320
|
+
] : []
|
|
321
|
+
Column {
|
|
322
|
+
id: pair
|
|
323
|
+
required property var modelData
|
|
324
|
+
// The Tags value is drawn as swatch and name per tag, so its plain string stays only as the model's text.
|
|
325
|
+
readonly property bool tagged: modelData[0] === "Tags"
|
|
326
|
+
width: body.holderWidth
|
|
327
|
+
Text { width: parent.width; text: parent.modelData[0]; textFormat: Text.PlainText; color: Theme.color.muted; font { family: Theme.font.family; pixelSize: Theme.font.caption } }
|
|
328
|
+
Text {
|
|
329
|
+
readonly property var line: parent.modelData.length > 2 ? root.liveLines[parent.modelData[2]] : null
|
|
330
|
+
visible: !pair.tagged
|
|
331
|
+
width: parent.width
|
|
332
|
+
text: line ? PropertyFacts.styled(line, Theme.color.muted) : parent.modelData[1]
|
|
333
|
+
textFormat: line ? Text.StyledText : Text.PlainText
|
|
334
|
+
wrapMode: Text.WrapAnywhere
|
|
335
|
+
color: Theme.color.foreground
|
|
336
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
337
|
+
}
|
|
338
|
+
Flow {
|
|
339
|
+
visible: pair.tagged
|
|
340
|
+
width: parent.width
|
|
341
|
+
spacing: Theme.spacing.tagPairGap
|
|
342
|
+
Repeater {
|
|
343
|
+
model: pair.tagged ? root.facts.tags : []
|
|
344
|
+
Row {
|
|
345
|
+
id: tagItem
|
|
346
|
+
required property string modelData
|
|
347
|
+
spacing: Theme.spacing.tagNameGap
|
|
348
|
+
// A name Flea does not know is plain text with no swatch; a digit fallback keeps the 14 px square its digit needs.
|
|
349
|
+
Flea.TagSwatch {
|
|
350
|
+
size: Theme.tag.fallback ? Tags.SWATCH_SIZE : Tags.PAIR_SWATCH_SIZE
|
|
351
|
+
visible: Tags.NAMES.indexOf(tagItem.modelData) >= 0
|
|
352
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
353
|
+
swatch: tagItem.modelData
|
|
354
|
+
fallback: Theme.tag.fallback
|
|
355
|
+
digit: Tags.keyFor(tagItem.modelData)
|
|
356
|
+
tagColors: Theme.tag.menuColors
|
|
357
|
+
}
|
|
358
|
+
Text {
|
|
359
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
360
|
+
text: tagItem.modelData
|
|
361
|
+
textFormat: Text.PlainText
|
|
362
|
+
color: Theme.color.foreground
|
|
363
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
Text {
|
|
371
|
+
width: parent.width
|
|
372
|
+
visible: text.length > 0
|
|
373
|
+
text: root.errorText || (root.busy ? "Working…" : "")
|
|
374
|
+
textFormat: Text.PlainText
|
|
375
|
+
wrapMode: Text.Wrap
|
|
376
|
+
color: root.errorText ? Theme.color.errorOnSurface : Theme.color.muted
|
|
377
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// Match Trash's identity-check cadence only while the destructive strip is visible.
|
|
383
|
+
Timer { interval: 2500; repeat: true; running: confirmation.opened && !root.busy; onTriggered: root.checkDeletion() }
|
|
384
|
+
Flea.TrashConfirm {
|
|
385
|
+
id: confirmation
|
|
386
|
+
scopeName: "items"
|
|
387
|
+
onCancelled: root.close()
|
|
388
|
+
onConfirmed: function(token) {
|
|
389
|
+
root.busy = true
|
|
390
|
+
root.committing = true
|
|
391
|
+
root.opened = false
|
|
392
|
+
if (root.focusHolder) root.focusHolder.forceActiveFocus()
|
|
393
|
+
root.requested({c: "menuaction", op: "delete", id: root.requestId, token: token})
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
|
|
3
|
+
// One edge of a menu that scrolls, fading the surface out where more rows wait: the Menus board's "Edges fade to say so".
|
|
4
|
+
Rectangle {
|
|
5
|
+
// The card's own padding between its border and its rows, which the fade crosses before it reaches a cut row.
|
|
6
|
+
property real inset: 0
|
|
7
|
+
// How far the fade reaches past that padding into the row the edge cuts.
|
|
8
|
+
property real reach: Theme.spacing.gap
|
|
9
|
+
// The frame Rectangle's border width: the fade lies inside it, so the hairline frame stays whole, corners included.
|
|
10
|
+
readonly property real frameBorder: parent.border.width
|
|
11
|
+
anchors.left: parent.left
|
|
12
|
+
anchors.right: parent.right
|
|
13
|
+
anchors.leftMargin: frameBorder
|
|
14
|
+
anchors.rightMargin: frameBorder
|
|
15
|
+
anchors.topMargin: frameBorder
|
|
16
|
+
anchors.bottomMargin: frameBorder
|
|
17
|
+
// Measured from the inner edge, so it still ends where the card's padding plus reach ends.
|
|
18
|
+
height: inset + reach - frameBorder
|
|
19
|
+
radius: Math.max(0, parent.radius - frameBorder)
|
|
20
|
+
gradient: Gradient {
|
|
21
|
+
GradientStop { position: 0; color: Theme.color.surface }
|
|
22
|
+
GradientStop { position: 1; color: Qt.rgba(Theme.color.surface.r, Theme.color.surface.g, Theme.color.surface.b, 0) }
|
|
23
|
+
}
|
|
24
|
+
}
|
package/ui/MenuHost.qml
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
import "js/Menu.js" as Menu
|
|
4
|
+
import "js/MenuContext.js" as MenuContext
|
|
5
|
+
|
|
6
|
+
// Menu state and receivers stay live; the visual warms after the first frame and listing idle.
|
|
7
|
+
Item {
|
|
8
|
+
id: root
|
|
9
|
+
required property var pane
|
|
10
|
+
anchors.fill: parent
|
|
11
|
+
visible: false
|
|
12
|
+
readonly property var item: visual.item
|
|
13
|
+
readonly property int status: visual.status
|
|
14
|
+
property bool syncing: false
|
|
15
|
+
property bool firstFrame: false
|
|
16
|
+
readonly property bool ready: root.item !== null && visual.status === Loader.Ready
|
|
17
|
+
readonly property bool settled: root.pane.listingState !== "loading" && !root.pane.listInFlight
|
|
18
|
+
readonly property real inputAt: root.pane.inputAt
|
|
19
|
+
onInputAtChanged: if (warm.running) warm.restart()
|
|
20
|
+
|
|
21
|
+
signal chosen(string action)
|
|
22
|
+
signal refused(string reason)
|
|
23
|
+
signal snapshotRequested()
|
|
24
|
+
signal railChosen(string action, string key)
|
|
25
|
+
signal lockedChosen(string action, string path)
|
|
26
|
+
|
|
27
|
+
property Item focusOwner: null
|
|
28
|
+
property bool showHidden: false
|
|
29
|
+
property bool providersRefreshing: false
|
|
30
|
+
property var taildropPeers: []
|
|
31
|
+
property bool rowIsFile: false
|
|
32
|
+
property bool taildropInstalled: false
|
|
33
|
+
property string taildropReason: ""
|
|
34
|
+
property string taildropCode: ""
|
|
35
|
+
property var archiveFormats: []
|
|
36
|
+
property bool canConvert: false
|
|
37
|
+
property bool canExtract: false
|
|
38
|
+
property string archiveName: ""
|
|
39
|
+
property int rowMode: 0
|
|
40
|
+
property int selectionCount: 0
|
|
41
|
+
property bool cursorIsTarget: false
|
|
42
|
+
property var openWithApps: []
|
|
43
|
+
property bool openWithLoaded: false
|
|
44
|
+
property var identitySource: null
|
|
45
|
+
property bool clipboardAvailable: false
|
|
46
|
+
property bool clipboardWatchFailed: false
|
|
47
|
+
property bool rowIsArchive: false
|
|
48
|
+
property bool rowIsImage: false
|
|
49
|
+
property string rowName: ""
|
|
50
|
+
property string flashZipMember: ""
|
|
51
|
+
property bool rowIsSymlink: false
|
|
52
|
+
property bool rowHasShebang: false
|
|
53
|
+
property var selectionModes: []
|
|
54
|
+
property var compareKinds: []
|
|
55
|
+
property bool dropboxInstalled: false
|
|
56
|
+
property var localSend: ({ installed: false, peers: [], checking: false })
|
|
57
|
+
property string dropboxPath: ""
|
|
58
|
+
property string dropboxReason: ""
|
|
59
|
+
property string dropboxCode: ""
|
|
60
|
+
property bool rowInDropbox: false
|
|
61
|
+
property bool canTrash: true
|
|
62
|
+
property bool dirWritable: true
|
|
63
|
+
property bool canLink: true
|
|
64
|
+
property var tagSubmenu: null
|
|
65
|
+
property string storageClass: ""
|
|
66
|
+
property bool hasFolderSort: false
|
|
67
|
+
property string tileTarget: ""
|
|
68
|
+
property int tileMode: 0
|
|
69
|
+
property rect workArea: Qt.rect(0, 0, root.width, root.height)
|
|
70
|
+
property bool opened: false
|
|
71
|
+
property bool preparing: false
|
|
72
|
+
property bool hasRow: true
|
|
73
|
+
property bool forHeader: false
|
|
74
|
+
property string openedIdentity: ""
|
|
75
|
+
property string lockedPath: ""
|
|
76
|
+
property int lockedMode: 0
|
|
77
|
+
property var railEntries: []
|
|
78
|
+
property string railKey: ""
|
|
79
|
+
property Item focusHolder: null
|
|
80
|
+
property int cursor: 0
|
|
81
|
+
property int openSubmenuRow: -1
|
|
82
|
+
property int submenuCursor: 0
|
|
83
|
+
property string loneFlyoutAction: ""
|
|
84
|
+
property var lastProviderAnswer: null
|
|
85
|
+
|
|
86
|
+
readonly property bool forRail: root.railEntries.length > 0
|
|
87
|
+
readonly property bool forLocked: root.lockedPath.length > 0
|
|
88
|
+
readonly property bool submenuOpen: root.openSubmenuRow >= 0 || root.loneFlyoutAction.length > 0
|
|
89
|
+
readonly property var entries: root.item ? root.item.entries : []
|
|
90
|
+
readonly property var submenuEntries: root.item ? root.item.submenuEntries : []
|
|
91
|
+
readonly property var frameItem: root.item ? root.item.frameItem : null
|
|
92
|
+
readonly property var submenuFrameItem: root.item ? root.item.submenuFrameItem : null
|
|
93
|
+
readonly property bool keyboardFocused: root.item ? root.item.keyboardFocused : false
|
|
94
|
+
readonly property var inputNames: [
|
|
95
|
+
"focusOwner", "showHidden", "providersRefreshing", "taildropPeers",
|
|
96
|
+
"rowIsFile", "taildropInstalled", "taildropReason", "taildropCode",
|
|
97
|
+
"archiveFormats", "canConvert", "canExtract", "archiveName",
|
|
98
|
+
"rowMode", "selectionCount", "cursorIsTarget", "openWithApps",
|
|
99
|
+
"openWithLoaded", "identitySource", "clipboardAvailable", "clipboardWatchFailed",
|
|
100
|
+
"rowIsArchive", "rowIsImage", "rowName", "flashZipMember",
|
|
101
|
+
"rowIsSymlink", "rowHasShebang", "selectionModes", "compareKinds", "dropboxInstalled",
|
|
102
|
+
"localSend", "dropboxPath", "dropboxReason", "dropboxCode",
|
|
103
|
+
"rowInDropbox", "canTrash", "dirWritable", "canLink",
|
|
104
|
+
"tagSubmenu", "storageClass", "hasFolderSort", "tileTarget",
|
|
105
|
+
"tileMode", "workArea"
|
|
106
|
+
]
|
|
107
|
+
readonly property var stateNames: [
|
|
108
|
+
"opened", "preparing", "hasRow", "forHeader",
|
|
109
|
+
"openedIdentity", "lockedPath", "lockedMode", "railEntries",
|
|
110
|
+
"railKey", "focusHolder", "cursor", "openSubmenuRow",
|
|
111
|
+
"submenuCursor", "loneFlyoutAction", "lastProviderAnswer"
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
function liveInput(name) { return Qt.binding(function () { return root[name] }) }
|
|
115
|
+
function copyState(name, from, to) {
|
|
116
|
+
if (root.syncing || !root.item) return
|
|
117
|
+
root.syncing = true
|
|
118
|
+
try { to[name] = from[name] } finally { root.syncing = false }
|
|
119
|
+
}
|
|
120
|
+
function watchState(name) {
|
|
121
|
+
root[name + "Changed"].connect(function () { root.copyState(name, root, root.item) })
|
|
122
|
+
root.item[name + "Changed"].connect(function () { root.copyState(name, root.item, root) })
|
|
123
|
+
}
|
|
124
|
+
function configure() {
|
|
125
|
+
if (String(visual.source).length > 0) return
|
|
126
|
+
var values = { parent: root.liveInput("parent") }
|
|
127
|
+
for (var i = 0; i < root.inputNames.length; i++) values[root.inputNames[i]] = root.liveInput(root.inputNames[i])
|
|
128
|
+
visual.setSource("ContextMenu.qml", values)
|
|
129
|
+
}
|
|
130
|
+
function loaded() {
|
|
131
|
+
for (var s = 0; s < root.stateNames.length; s++) root.item[root.stateNames[s]] = root[root.stateNames[s]]
|
|
132
|
+
for (var n = 0; n < root.stateNames.length; n++) root.watchState(root.stateNames[n])
|
|
133
|
+
root.item.chosen.connect(root.chosen)
|
|
134
|
+
root.item.refused.connect(root.refused)
|
|
135
|
+
root.item.snapshotRequested.connect(root.snapshotRequested)
|
|
136
|
+
root.item.railChosen.connect(root.railChosen)
|
|
137
|
+
root.item.lockedChosen.connect(root.lockedChosen)
|
|
138
|
+
}
|
|
139
|
+
function prewarm() {
|
|
140
|
+
if (visual.active) return
|
|
141
|
+
root.configure()
|
|
142
|
+
visual.active = true
|
|
143
|
+
}
|
|
144
|
+
function ensure() {
|
|
145
|
+
if (root.item) return root.item
|
|
146
|
+
warm.stop()
|
|
147
|
+
// Cancelling first preserves inputs from birth when Qt restarts unfinished compilation.
|
|
148
|
+
visual.active = false
|
|
149
|
+
visual.source = ""
|
|
150
|
+
visual.asynchronous = false
|
|
151
|
+
root.configure()
|
|
152
|
+
visual.active = true
|
|
153
|
+
if (!root.item) throw new Error("ContextMenu.qml did not load: Loader status " + visual.status)
|
|
154
|
+
return root.item
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
Loader {
|
|
158
|
+
id: visual
|
|
159
|
+
active: false
|
|
160
|
+
asynchronous: true
|
|
161
|
+
onLoaded: root.loaded()
|
|
162
|
+
onStatusChanged: if (status === Loader.Error) throw new Error("ContextMenu.qml did not load: Loader status " + status)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Match Quick Look's one-second idle hold, after both the first swap and listing readiness.
|
|
166
|
+
Timer {
|
|
167
|
+
id: warm
|
|
168
|
+
interval: 1000
|
|
169
|
+
running: root.firstFrame && root.settled && !visual.active
|
|
170
|
+
onTriggered: root.prewarm()
|
|
171
|
+
}
|
|
172
|
+
Connections {
|
|
173
|
+
target: root.firstFrame ? null : root.Window.window
|
|
174
|
+
function onFrameSwapped() { root.firstFrame = true }
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function selectionIdentity() { return root.identitySource ? root.identitySource.menuSelectionIdentity() : "" }
|
|
178
|
+
function listingContext(flyoutAction, includeHidden) {
|
|
179
|
+
if (root.item) return root.item.listingContext(flyoutAction, includeHidden)
|
|
180
|
+
return MenuContext.listingContext(root, flyoutAction, includeHidden, {
|
|
181
|
+
scripts: Flea.Scripts.entries, hiddenActions: ViewState.menuHidden,
|
|
182
|
+
langMarks: ViewState.langMarks,
|
|
183
|
+
thumbPreview: ViewState.preview, updateVersion: UpdateCheck.menuVersion
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
function buildEntries(flyoutAction, includeHidden) {
|
|
187
|
+
if (root.item) return root.item.buildEntries(flyoutAction, includeHidden)
|
|
188
|
+
if (root.forRail) return root.railEntries
|
|
189
|
+
if (root.forHeader) return Menu.headerEntries(ViewState.hiddenCols, root.showHidden)
|
|
190
|
+
return Menu.listingEntries(root.listingContext(flyoutAction, includeHidden))
|
|
191
|
+
}
|
|
192
|
+
function validateChoice(action, subId, includeHidden) {
|
|
193
|
+
if (root.item) return root.item.validateChoice(action, subId, includeHidden)
|
|
194
|
+
return MenuContext.validateChoice(root, action, subId, includeHidden)
|
|
195
|
+
}
|
|
196
|
+
function refuseLone(kind) {
|
|
197
|
+
root.close()
|
|
198
|
+
root.refused(kind === "moved" ? "Selected items changed; reopen the menu."
|
|
199
|
+
: "That action is no longer available; reopen the menu.")
|
|
200
|
+
}
|
|
201
|
+
function providersSettled() {
|
|
202
|
+
if (root.item) root.item.providersSettled()
|
|
203
|
+
else root.lastProviderAnswer = MenuContext.settle(MenuContext.live(root))
|
|
204
|
+
}
|
|
205
|
+
function refreshProviderRows() { if (root.item) root.item.refreshProviderRows() }
|
|
206
|
+
function close() {
|
|
207
|
+
if (root.item) root.item.close()
|
|
208
|
+
else root.opened = false
|
|
209
|
+
}
|
|
210
|
+
function clearRail() {
|
|
211
|
+
if (root.item) root.item.clearRail()
|
|
212
|
+
else { root.railEntries = []; root.railKey = ""; root.lockedPath = ""; root.lockedMode = 0 }
|
|
213
|
+
}
|
|
214
|
+
function openAt(point) { root.ensure().openAt(point) }
|
|
215
|
+
function openBackground(point) { root.ensure().openBackground(point) }
|
|
216
|
+
function openLocked(path, mode, point) { root.ensure().openLocked(path, mode, point) }
|
|
217
|
+
function openForHeader(point) { root.ensure().openForHeader(point) }
|
|
218
|
+
function openForRail(key, rows, point) { if (rows && rows.length) root.ensure().openForRail(key, rows, point) }
|
|
219
|
+
function openSubmenu(index) { if (root.item) root.item.openSubmenu(index) }
|
|
220
|
+
function openSubmenuFor(action) { return root.ensure().openSubmenuFor(action) }
|
|
221
|
+
function choose(action) { if (root.item) root.item.choose(action) }
|
|
222
|
+
function chooseSub(id) { if (root.item) root.item.chooseSub(id) }
|
|
223
|
+
function setEntries(rows, flyoutRow) { root.ensure().setEntries(rows, flyoutRow) }
|
|
224
|
+
function itemFor(index) { return root.item ? root.item.itemFor(index) : null }
|
|
225
|
+
function submenuItemFor(index) { return root.item ? root.item.submenuItemFor(index) : null }
|
|
226
|
+
function submenuGlyphs() { return root.item ? root.item.submenuGlyphs() : "" }
|
|
227
|
+
}
|