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,658 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Format.js" as Format
|
|
5
|
+
import "js/Permissions.js" as Permissions
|
|
6
|
+
|
|
7
|
+
// One item, one mode; the backend owns its reviewed descriptor for this dialog's lifetime.
|
|
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
|
+
Flea.Reveal { target: root; shown: root.opened; lift: card }
|
|
16
|
+
property bool opened: false
|
|
17
|
+
property int requestId: 0
|
|
18
|
+
// Inspect ids are request blocks of this width; a wider selection reserves whole blocks.
|
|
19
|
+
readonly property int inspectStride: 1000
|
|
20
|
+
property int multiBase: 0
|
|
21
|
+
property var facts: ({})
|
|
22
|
+
property string path: ""
|
|
23
|
+
property string modeText: ""
|
|
24
|
+
property string errorText: ""
|
|
25
|
+
property bool busy: false
|
|
26
|
+
property bool transportFailed: false
|
|
27
|
+
property Item focusHolder: null
|
|
28
|
+
// The selection's paths with modes in the same order, the first inspect refusal, and the explicit bits.
|
|
29
|
+
property var multiPaths: []
|
|
30
|
+
// The live inspect store noteMode owns; multiModes is its one last-reply snapshot.
|
|
31
|
+
property var multiStore: ({ modes: [], reasons: [], skipped: [] })
|
|
32
|
+
property var multiModes: []
|
|
33
|
+
property int multiPending: 0
|
|
34
|
+
property int explicitSet: 0
|
|
35
|
+
property int explicitClear: 0
|
|
36
|
+
property bool applyingMany: false
|
|
37
|
+
// A failed batch's own error until its re-read lands, so the held note may replace it when it names that refusal.
|
|
38
|
+
property string failedBatchError: ""
|
|
39
|
+
// The Apply skips, carried to the applyMany reply for the final message.
|
|
40
|
+
property var multiApplySkipped: []
|
|
41
|
+
readonly property bool isMulti: multiPaths.length > 1
|
|
42
|
+
readonly property var multiSummary: isMulti ? Permissions.summarize(multiModes, multiStore.reasons) : null
|
|
43
|
+
// Several items: a selection where no file can change shows the files' bits and is not editable, as one unchangeable file is.
|
|
44
|
+
readonly property bool editable: isMulti ? !busy && !transportFailed && !!multiSummary && multiSummary.changeable
|
|
45
|
+
: facts.ok === true && !facts.reason && !busy && !transportFailed
|
|
46
|
+
readonly property int modeValue: Permissions.parse(modeText)
|
|
47
|
+
readonly property bool applying: busy && facts.ok === true
|
|
48
|
+
// Permissions040: a multi Apply cannot be cancelled either.
|
|
49
|
+
readonly property bool applyLocked: applying || applyingMany
|
|
50
|
+
// One Apply condition for the button and the probe, which reads the button.
|
|
51
|
+
readonly property bool canApply: isMulti ? editable : editable && modeValue >= 0
|
|
52
|
+
readonly property real labelWidth: Math.round(96 * root.boardScale)
|
|
53
|
+
// ButtonSystem040 A: a text field is DialogField's height (ui/DialogField.qml's box), centred in its row.
|
|
54
|
+
readonly property int fieldHeight: Theme.rowHeight - Theme.spacing.rowPaddingY
|
|
55
|
+
readonly property int controlHeight: Math.max(Theme.rowHeight, Math.ceil(Theme.font.body * Theme.lineBoxRatio) + 2 * Theme.spacing.rowPaddingY)
|
|
56
|
+
// The board is drawn at base size 14, whose bodySmall is 13; every board pixel below scales from it and lands whole.
|
|
57
|
+
readonly property real boardScale: Theme.font.bodySmall / 13
|
|
58
|
+
readonly property int boardCardWidth: 480
|
|
59
|
+
readonly property int bodyInset: Math.round(16 * root.boardScale) + Theme.spacing.hairline
|
|
60
|
+
readonly property int headingHeight: Math.round(26 * root.boardScale)
|
|
61
|
+
// Permissions040, several items: the surface's one 8 px gap, and the 6 px its button row adds above itself.
|
|
62
|
+
readonly property int multiGap: Theme.spacing.rowPaddingY + Theme.spacing.hairline
|
|
63
|
+
// The board's three flex:1 columns are exact thirds of this span; whole-number arithmetic rounds each start half up, as the board's paint does.
|
|
64
|
+
readonly property real bitSpan: body.holderWidth - root.labelWidth
|
|
65
|
+
function bitStart(column) { return Math.floor((2 * column * root.bitSpan + 3) / 6) }
|
|
66
|
+
function bitWidth(column) { return root.bitStart(column + 1) - root.bitStart(column) }
|
|
67
|
+
// The box sits at the rounded exact centre of its third, so it lands on whole pixels where the board's does.
|
|
68
|
+
function boxLead(column, box) { return Math.floor((2 * column * root.bitSpan + root.bitSpan - 3 * box + 3) / 6) - root.bitStart(column) }
|
|
69
|
+
// lib.py note(): a caption's line box is 1.5 x its size and its glyphs sit centred in it.
|
|
70
|
+
readonly property int captionLead: Math.round((SettingsMetrics.hintLine - noteFont.height) / 2)
|
|
71
|
+
// Permissions040's strip draws the title and "esc" glyphs one row above where Qt's line box seats them (board rows 7-16 and 10-16, the build's 8-17 and 11-17 once centred above the rule).
|
|
72
|
+
readonly property int stripTextRise: Theme.spacing.hairline
|
|
73
|
+
readonly property int railHalf: Math.round(Theme.settings.railPaddingY / 2)
|
|
74
|
+
readonly property int buttonLead: root.railHalf + Theme.spacing.hairline
|
|
75
|
+
readonly property var cardItem: card
|
|
76
|
+
// The title strip's four marks, so a probe reads where each sits against the board's rows.
|
|
77
|
+
readonly property var stripItems: ({ lock: lockMark, title: title, esc: escHint, close: closeMark })
|
|
78
|
+
readonly property var noteItem: scopeLabel
|
|
79
|
+
readonly property var octalFrame: octalBox
|
|
80
|
+
readonly property var bodyItem: body
|
|
81
|
+
readonly property string displayedError: errorLabel.text
|
|
82
|
+
readonly property string displayedSummary: (isMulti ? "" : changeSummary.text + "\n") + scopeLabel.text
|
|
83
|
+
// One section rule for the four drawn below; each site sets its own place and visibility.
|
|
84
|
+
component Rule: Rectangle {
|
|
85
|
+
width: parent.width
|
|
86
|
+
height: Theme.spacing.hairline
|
|
87
|
+
color: Theme.color.mutedFrame
|
|
88
|
+
opacity: 0.4
|
|
89
|
+
}
|
|
90
|
+
// No enabled keys: each item.enabled already carries every mode's answer, a copy could disagree.
|
|
91
|
+
function controls() {
|
|
92
|
+
var result = [{name: "Close", item: closeMark}, {name: "Octal", item: octal},
|
|
93
|
+
{name: "Cancel", item: cancelButton}, {name: "Apply", item: applyButton}]
|
|
94
|
+
for (var row = 0; row < permissionRows.count; row++) {
|
|
95
|
+
var group = permissionRows.itemAt(row)
|
|
96
|
+
for (var column = 0; column < group.checks.count; column++) {
|
|
97
|
+
var checkbox = group.checks.itemAt(column)
|
|
98
|
+
result.push({name: checkbox.Accessible.name, item: checkbox, checked: checkbox.checked, bit: checkbox.bit})
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return result
|
|
102
|
+
}
|
|
103
|
+
readonly property string scopeText: facts.directory
|
|
104
|
+
? "Scope this folder only · enclosed items unchanged · ownership unchanged"
|
|
105
|
+
: "Scope this item only · ownership unchanged"
|
|
106
|
+
signal requested(var message)
|
|
107
|
+
signal changed(string note)
|
|
108
|
+
signal refreshNeeded()
|
|
109
|
+
signal closed()
|
|
110
|
+
|
|
111
|
+
// One reset for both openers, so a field added to one cannot be missed in the other.
|
|
112
|
+
function reset(itemPath, paths, holder) {
|
|
113
|
+
multiPaths = paths.slice()
|
|
114
|
+
multiStore = ({ modes: [], reasons: [], skipped: [], pending: paths.length })
|
|
115
|
+
multiModes = []
|
|
116
|
+
multiPending = paths.length
|
|
117
|
+
multiApplySkipped = []
|
|
118
|
+
failedBatchError = ""
|
|
119
|
+
explicitSet = 0
|
|
120
|
+
explicitClear = 0
|
|
121
|
+
applyingMany = false
|
|
122
|
+
path = itemPath
|
|
123
|
+
focusHolder = holder
|
|
124
|
+
facts = ({})
|
|
125
|
+
modeText = ""
|
|
126
|
+
errorText = ""
|
|
127
|
+
transportFailed = false
|
|
128
|
+
busy = true
|
|
129
|
+
opened = true
|
|
130
|
+
body.contentY = 0
|
|
131
|
+
cancelButton.forceActiveFocus()
|
|
132
|
+
}
|
|
133
|
+
// One inspect fan-out for openMany and the failed-batch re-read: the same requests.
|
|
134
|
+
function inspectAll() {
|
|
135
|
+
multiStore = ({ modes: [], reasons: [], skipped: [], pending: multiPaths.length })
|
|
136
|
+
multiModes = []
|
|
137
|
+
multiPending = multiPaths.length
|
|
138
|
+
for (var i = 0; i < multiPaths.length; i++)
|
|
139
|
+
requested({ c: "permissions", op: "inspect", id: multiBase * inspectStride + i, path: multiPaths[i] })
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function open(itemPath, holder) {
|
|
143
|
+
requestId += 1
|
|
144
|
+
reset(itemPath, [], holder)
|
|
145
|
+
requested({ c: "permissions", op: "inspect", id: requestId, path: path })
|
|
146
|
+
}
|
|
147
|
+
// One Entry holds every path the Apply changed, so one undo restores them all.
|
|
148
|
+
function openMany(paths, holder) {
|
|
149
|
+
requestId += 1
|
|
150
|
+
multiBase = requestId
|
|
151
|
+
reset("", paths, holder)
|
|
152
|
+
inspectAll()
|
|
153
|
+
// A wider selection reserves whole strides so the next open's block cannot overlap this one.
|
|
154
|
+
requestId += Math.max(0, Math.floor((paths.length - 1) / inspectStride))
|
|
155
|
+
}
|
|
156
|
+
function receive(message) {
|
|
157
|
+
if (isMulti) { receiveMany(message); return }
|
|
158
|
+
if (!opened || transportFailed || message.id !== requestId || message.op === "close") return
|
|
159
|
+
busy = false
|
|
160
|
+
cancelButton.forceActiveFocus()
|
|
161
|
+
if (!message.ok) { errorText = message.error || "Could not change permissions."; return }
|
|
162
|
+
if (message.op === "apply") { changed(""); close(); return }
|
|
163
|
+
facts = message
|
|
164
|
+
modeText = message.mode
|
|
165
|
+
}
|
|
166
|
+
// The grid over several files; an untouched box takes the explicit opposite of what it shows.
|
|
167
|
+
function multiBit(bit) {
|
|
168
|
+
if (!multiSummary) return { on: false, mixed: false }
|
|
169
|
+
for (var i = 0; i < multiSummary.bits.length; i++) {
|
|
170
|
+
if (multiSummary.bits[i].mask === bit)
|
|
171
|
+
return multiSummary.bits[i]
|
|
172
|
+
}
|
|
173
|
+
return { on: false, mixed: false }
|
|
174
|
+
}
|
|
175
|
+
function multiChecked(bit) {
|
|
176
|
+
if ((explicitSet & bit) !== 0) return true
|
|
177
|
+
if ((explicitClear & bit) !== 0) return false
|
|
178
|
+
return multiBit(bit).on
|
|
179
|
+
}
|
|
180
|
+
function multiValue(bit) {
|
|
181
|
+
if ((explicitSet & bit) !== 0) return "on"
|
|
182
|
+
if ((explicitClear & bit) !== 0) return "off"
|
|
183
|
+
var found = multiBit(bit)
|
|
184
|
+
if (found.mixed) return "some"
|
|
185
|
+
return found.on ? "on" : "off"
|
|
186
|
+
}
|
|
187
|
+
// A set box lets go unless mixed, so a uniform-off box reads off, on, off, on.
|
|
188
|
+
function multiToggle(bit) {
|
|
189
|
+
if ((explicitSet & bit) !== 0) {
|
|
190
|
+
explicitSet &= ~bit
|
|
191
|
+
if (multiBit(bit).mixed) explicitClear |= bit
|
|
192
|
+
} else if ((explicitClear & bit) !== 0) {
|
|
193
|
+
explicitClear &= ~bit
|
|
194
|
+
} else if (multiBit(bit).mixed || !multiBit(bit).on) {
|
|
195
|
+
explicitSet |= bit
|
|
196
|
+
explicitClear &= ~bit
|
|
197
|
+
} else {
|
|
198
|
+
explicitClear |= bit
|
|
199
|
+
explicitSet &= ~bit
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function receiveMany(message) {
|
|
203
|
+
if (!opened || transportFailed || (message.op === "applyMany" && (!applyingMany || message.id !== requestId))) return
|
|
204
|
+
if (message.op === "applyMany") {
|
|
205
|
+
applyingMany = false
|
|
206
|
+
if (message.ok === true) {
|
|
207
|
+
changed(Permissions.multiResult(multiApplySkipped))
|
|
208
|
+
close()
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
errorText = message.error || "Could not change permissions."
|
|
212
|
+
if (multiApplySkipped.length > 0)
|
|
213
|
+
errorText += "\n" + Permissions.skipNote(multiApplySkipped)
|
|
214
|
+
// A failed batch re-reads every mode so the grid and a retry start from disk.
|
|
215
|
+
failedBatchError = message.error || ""
|
|
216
|
+
inspectAll()
|
|
217
|
+
busy = true
|
|
218
|
+
cancelButton.forceActiveFocus()
|
|
219
|
+
refreshNeeded()
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
if (message.op !== "inspect") return
|
|
223
|
+
var at = (message.id || 0) - multiBase * inspectStride
|
|
224
|
+
if (at < 0 || at >= multiPaths.length) return
|
|
225
|
+
// Accumulated in place through noteMode, which answers true once per selection.
|
|
226
|
+
if (Permissions.noteMode(multiStore, at, multiPaths[at], message)) {
|
|
227
|
+
multiPending = 0
|
|
228
|
+
// The single assignment lands with the last reply, before busy clears, so editable never reads the previous selection's summary.
|
|
229
|
+
multiModes = multiStore.modes.slice()
|
|
230
|
+
busy = false
|
|
231
|
+
var note = Permissions.inspectNote(multiStore, multiPaths)
|
|
232
|
+
// A batch refused for a file the re-read cannot inspect is named by the held note, which quotes that refusal; any other batch error stays.
|
|
233
|
+
var refused = failedBatchError.length > 0 && multiStore.skipped.some(function (skip) { return skip.why === failedBatchError })
|
|
234
|
+
if (note.length > 0 && (errorText.length === 0 || refused)) errorText = note
|
|
235
|
+
failedBatchError = ""
|
|
236
|
+
cancelButton.forceActiveFocus()
|
|
237
|
+
} else {
|
|
238
|
+
multiPending = multiStore.pending
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function backendFailed() {
|
|
242
|
+
if (!opened || transportFailed) return
|
|
243
|
+
// A multi Apply counts as applying with an unknown outcome, and ends so Cancel and close work.
|
|
244
|
+
var applying = applyLocked
|
|
245
|
+
applyingMany = false
|
|
246
|
+
transportFailed = true
|
|
247
|
+
busy = false
|
|
248
|
+
cancelButton.forceActiveFocus()
|
|
249
|
+
errorText = applying
|
|
250
|
+
? "Flea stopped responding, so the permission change may not have finished. Restart Flea and reopen Permissions to check."
|
|
251
|
+
: "Permissions is unavailable because Flea stopped responding. Restart Flea and reopen Permissions."
|
|
252
|
+
}
|
|
253
|
+
function close() {
|
|
254
|
+
// An issued fchmod cannot be cancelled; retain its result before allowing dismissal.
|
|
255
|
+
if (!opened || applyLocked) return
|
|
256
|
+
if (isMulti) {
|
|
257
|
+
for (var i = 0; i < multiPaths.length; i++)
|
|
258
|
+
requested({ c: "permissions", op: "close", id: multiBase * inspectStride + i })
|
|
259
|
+
} else {
|
|
260
|
+
requested({ c: "permissions", op: "close", id: requestId })
|
|
261
|
+
}
|
|
262
|
+
opened = false
|
|
263
|
+
closed()
|
|
264
|
+
if (focusHolder) focusHolder.forceActiveFocus()
|
|
265
|
+
}
|
|
266
|
+
function apply() {
|
|
267
|
+
if (isMulti) { applyMany(); return }
|
|
268
|
+
if (!editable || modeValue < 0) return
|
|
269
|
+
root.forceActiveFocus()
|
|
270
|
+
busy = true
|
|
271
|
+
errorText = ""
|
|
272
|
+
requested({ c: "permissions", op: "apply", id: requestId, mode: modeText })
|
|
273
|
+
}
|
|
274
|
+
// Apply is one undo step; unchangeable items are counted and an empty batch answers at once.
|
|
275
|
+
function applyMany() {
|
|
276
|
+
if (!editable) return
|
|
277
|
+
root.forceActiveFocus()
|
|
278
|
+
busy = true
|
|
279
|
+
applyingMany = true
|
|
280
|
+
errorText = ""
|
|
281
|
+
// Built fresh from the per-row reasons, so every skip is counted exactly once.
|
|
282
|
+
var skipped = []
|
|
283
|
+
var paths = []
|
|
284
|
+
var modes = []
|
|
285
|
+
for (var i = 0; i < multiPaths.length; i++) {
|
|
286
|
+
var why = multiStore.reasons[i] || ""
|
|
287
|
+
var base = Permissions.parse(multiStore.modes[i])
|
|
288
|
+
if (why.length === 0 && base < 0)
|
|
289
|
+
why = Permissions.specialReason(multiStore.modes[i])
|
|
290
|
+
if (why.length > 0 || base < 0) {
|
|
291
|
+
skipped.push({ path: multiPaths[i],
|
|
292
|
+
why: why.length > 0 ? why : "Could not change permissions." })
|
|
293
|
+
continue
|
|
294
|
+
}
|
|
295
|
+
var target = (base & ~explicitClear) | explicitSet
|
|
296
|
+
paths.push(multiPaths[i])
|
|
297
|
+
modes.push(Permissions.octal(target))
|
|
298
|
+
}
|
|
299
|
+
if (paths.length === 0) {
|
|
300
|
+
applyingMany = false
|
|
301
|
+
busy = false
|
|
302
|
+
errorText = Permissions.multiResult(skipped)
|
|
303
|
+
cancelButton.forceActiveFocus()
|
|
304
|
+
return
|
|
305
|
+
}
|
|
306
|
+
multiApplySkipped = skipped
|
|
307
|
+
requested({ c: "permissionsBatch", paths: paths, modes: modes, id: requestId })
|
|
308
|
+
}
|
|
309
|
+
function focusItems(item, result) {
|
|
310
|
+
if (!item.visible || !item.enabled) return
|
|
311
|
+
if (item.activeFocusOnTab) result.push(item)
|
|
312
|
+
for (var i = 0; i < item.children.length; i++) focusItems(item.children[i], result)
|
|
313
|
+
}
|
|
314
|
+
function stepFocus(back) {
|
|
315
|
+
var items = []
|
|
316
|
+
focusItems(card, items)
|
|
317
|
+
if (!items.length) return
|
|
318
|
+
var current = -1
|
|
319
|
+
for (var i = 0; i < items.length; i++) if (items[i].activeFocus) current = i
|
|
320
|
+
var next = current < 0 ? (back ? items.length - 1 : 0)
|
|
321
|
+
: (current + (back ? -1 : 1) + items.length) % items.length
|
|
322
|
+
items[next].forceActiveFocus()
|
|
323
|
+
body.reveal(items[next])
|
|
324
|
+
}
|
|
325
|
+
FontMetrics { id: noteFont; font { family: Theme.font.family; pixelSize: Theme.font.caption } }
|
|
326
|
+
Keys.onTabPressed: function(event) { root.stepFocus((event.modifiers & Qt.ShiftModifier) !== 0); event.accepted = true }
|
|
327
|
+
Keys.onBacktabPressed: function(event) { root.stepFocus(true); event.accepted = true }
|
|
328
|
+
Keys.onPressed: function(event) { event.accepted = true }
|
|
329
|
+
Keys.onEscapePressed: function(event) { root.close(); event.accepted = true }
|
|
330
|
+
Rectangle {
|
|
331
|
+
anchors.fill: parent
|
|
332
|
+
color: Theme.color.background
|
|
333
|
+
opacity: 0.5
|
|
334
|
+
MouseArea {
|
|
335
|
+
anchors.fill: parent
|
|
336
|
+
hoverEnabled: true
|
|
337
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
338
|
+
onClicked: root.close()
|
|
339
|
+
onWheel: function(wheel) { wheel.accepted = true }
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
Rectangle {
|
|
343
|
+
id: card
|
|
344
|
+
x: Theme.cardOrigin(root.width, width)
|
|
345
|
+
y: Theme.cardOrigin(root.height, height)
|
|
346
|
+
width: Theme.cardSpan(Math.round(root.boardCardWidth * root.boardScale), root.width - 2 * Theme.spacing.gap)
|
|
347
|
+
height: Theme.cardSpan(Theme.spacing.hairline + chrome.height + body.wanted + Theme.spacing.rowPaddingX + root.bodyInset, root.height - 2 * Theme.spacing.gap)
|
|
348
|
+
color: Theme.color.surface
|
|
349
|
+
border.color: Theme.color.mutedFrame
|
|
350
|
+
border.width: Theme.spacing.hairline
|
|
351
|
+
radius: Style.cornerRadius
|
|
352
|
+
clip: true
|
|
353
|
+
MouseArea {
|
|
354
|
+
anchors.fill: parent
|
|
355
|
+
hoverEnabled: true
|
|
356
|
+
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
357
|
+
onWheel: function(wheel) { wheel.accepted = true }
|
|
358
|
+
}
|
|
359
|
+
Item {
|
|
360
|
+
id: chrome
|
|
361
|
+
// The strip sits inside the card's border, as the board's title does, so its rule and marks start a hairline in.
|
|
362
|
+
anchors.left: parent.left
|
|
363
|
+
anchors.right: parent.right
|
|
364
|
+
anchors.top: parent.top
|
|
365
|
+
anchors.margins: Theme.spacing.hairline
|
|
366
|
+
height: Theme.chromeHeight
|
|
367
|
+
// The board centres the marks and title in the strip above its rule, so the rule's row is never part of the centring band.
|
|
368
|
+
Item { id: titleBand; anchors.left: parent.left; anchors.right: parent.right; anchors.top: parent.top; height: parent.height - Theme.spacing.hairline }
|
|
369
|
+
Flea.Glyph {
|
|
370
|
+
id: lockMark
|
|
371
|
+
x: Theme.spacing.rowPaddingX
|
|
372
|
+
y: Math.floor((titleBand.height - height) / 2)
|
|
373
|
+
width: Theme.chromeMarkSize; height: title.height; name: "lock"; color: Theme.color.accent
|
|
374
|
+
}
|
|
375
|
+
Text {
|
|
376
|
+
id: title
|
|
377
|
+
x: lockMark.x + lockMark.width + Theme.spacing.gap
|
|
378
|
+
y: Math.floor((titleBand.height - height) / 2) - root.stripTextRise
|
|
379
|
+
text: root.isMulti ? Format.fill(Permissions.WORDS.titleMany, root.multiPaths.length) : "Permissions"
|
|
380
|
+
color: Theme.color.foreground; textFormat: Text.PlainText; font { family: Theme.font.family; pixelSize: Theme.font.caption; bold: true }
|
|
381
|
+
}
|
|
382
|
+
// Dialogs rule 7: the way out is named beside the mark that performs it, the settings panel's own corner.
|
|
383
|
+
Flea.EscapeHint {
|
|
384
|
+
id: escHint
|
|
385
|
+
anchors.right: closeMark.left
|
|
386
|
+
anchors.rightMargin: Theme.spacing.gap
|
|
387
|
+
y: Math.floor((titleBand.height - height) / 2) - root.stripTextRise
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
Flea.ChromeButton {
|
|
391
|
+
id: closeMark
|
|
392
|
+
ruleRows: Theme.spacing.hairline
|
|
393
|
+
anchors.right: parent.right
|
|
394
|
+
anchors.rightMargin: Theme.spacing.rowPaddingX
|
|
395
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
396
|
+
glyph: "x"; gesturePolicy: TapHandler.ReleaseWithinBounds
|
|
397
|
+
// Muted at rest as the board draws the strip; the keyboard adds ChromeButton's own frame.
|
|
398
|
+
restingColor: Theme.color.mutedFrame
|
|
399
|
+
enabled: !root.applyLocked
|
|
400
|
+
accessName: "Close permissions"
|
|
401
|
+
activeFocusOnTab: true
|
|
402
|
+
keyboardFocused: activeFocus
|
|
403
|
+
Keys.onTabPressed: function(event) { root.stepFocus((event.modifiers & Qt.ShiftModifier) !== 0) }
|
|
404
|
+
Keys.onBacktabPressed: root.stepFocus(true)
|
|
405
|
+
onActivated: root.close()
|
|
406
|
+
}
|
|
407
|
+
Rule { anchors.bottom: parent.bottom }
|
|
408
|
+
}
|
|
409
|
+
Flea.CardFrame {
|
|
410
|
+
id: body
|
|
411
|
+
anchors.left: parent.left
|
|
412
|
+
anchors.right: parent.right
|
|
413
|
+
anchors.top: chrome.bottom
|
|
414
|
+
anchors.bottom: parent.bottom
|
|
415
|
+
bleed: Theme.focusClearance
|
|
416
|
+
anchors.leftMargin: root.bodyInset - Theme.focusClearance
|
|
417
|
+
anchors.rightMargin: root.bodyInset - Theme.focusClearance
|
|
418
|
+
anchors.topMargin: Theme.spacing.rowPaddingX - Theme.focusClearance
|
|
419
|
+
anchors.bottomMargin: root.bodyInset - Theme.focusClearance
|
|
420
|
+
spacing: 0
|
|
421
|
+
Column {
|
|
422
|
+
width: body.holderWidth
|
|
423
|
+
spacing: 0
|
|
424
|
+
Row {
|
|
425
|
+
width: parent.width
|
|
426
|
+
height: root.controlHeight
|
|
427
|
+
spacing: Theme.spacing.gap
|
|
428
|
+
// For several items the grid and Apply are the whole card, so the name row drops out.
|
|
429
|
+
visible: !root.isMulti
|
|
430
|
+
Flea.Glyph { width: Theme.markSize; height: nameLabel.height; anchors.verticalCenter: parent.verticalCenter; name: root.facts.directory ? "folder" : "file"; color: Theme.color.mutedFrame }
|
|
431
|
+
Text { id: nameLabel; width: parent.width - Theme.markSize - kindLabel.width - 2 * parent.spacing; anchors.verticalCenter: parent.verticalCenter; text: root.path.split("/").pop(); elide: Text.ElideMiddle; textFormat: Text.PlainText; color: Theme.color.foreground; font { family: Theme.font.family; pixelSize: Theme.font.body } }
|
|
432
|
+
Text { id: kindLabel; anchors.verticalCenter: parent.verticalCenter; text: root.facts.ok ? (root.facts.directory ? "directory" : "file") : ""; textFormat: Text.PlainText; color: Theme.color.foreground; font { family: Theme.font.family; pixelSize: Theme.font.caption } }
|
|
433
|
+
}
|
|
434
|
+
Rule { visible: !root.isMulti }
|
|
435
|
+
Flea.PermissionsHeadings { width: parent.width; card: root; enter: !root.isMulti && root.facts.directory === true }
|
|
436
|
+
Repeater {
|
|
437
|
+
id: permissionRows
|
|
438
|
+
model: ["Owner", "Group", "Everyone"]
|
|
439
|
+
Row {
|
|
440
|
+
id: permissionRow
|
|
441
|
+
required property string modelData
|
|
442
|
+
required property int index
|
|
443
|
+
readonly property alias checks: checks
|
|
444
|
+
width: body.holderWidth
|
|
445
|
+
height: root.controlHeight
|
|
446
|
+
Text { width: root.labelWidth; anchors.verticalCenter: parent.verticalCenter; text: permissionRow.modelData; textFormat: Text.PlainText; color: Theme.color.foreground; font { family: Theme.font.family; pixelSize: Theme.font.body } }
|
|
447
|
+
Repeater {
|
|
448
|
+
id: checks
|
|
449
|
+
model: 3
|
|
450
|
+
FocusScope {
|
|
451
|
+
id: checkbox
|
|
452
|
+
required property int index
|
|
453
|
+
readonly property int bit: 1 << (8 - permissionRow.index * 3 - index)
|
|
454
|
+
readonly property bool checked: root.isMulti ? root.multiChecked(bit)
|
|
455
|
+
: (root.modeValue >= 0 ? root.modeValue : parseInt(root.facts.mode || "0", 8)) & bit
|
|
456
|
+
width: root.bitWidth(index)
|
|
457
|
+
height: permissionRow.height
|
|
458
|
+
activeFocusOnTab: true
|
|
459
|
+
enabled: root.editable
|
|
460
|
+
// The pointer's own state, read by the native capture harness before it shoots a hover or a press.
|
|
461
|
+
readonly property bool hovered: boxHover.hovered
|
|
462
|
+
readonly property bool pressed: boxTap.pressed
|
|
463
|
+
Accessible.role: Accessible.CheckBox
|
|
464
|
+
Accessible.name: permissionRow.modelData + " " + ["read", "write", root.facts.directory ? "enter" : "execute"][index]
|
|
465
|
+
Accessible.checked: checked
|
|
466
|
+
Accessible.onPressAction: toggle()
|
|
467
|
+
Accessible.onToggleAction: toggle()
|
|
468
|
+
function toggle() {
|
|
469
|
+
if (!root.editable) return
|
|
470
|
+
if (root.isMulti) root.multiToggle(bit)
|
|
471
|
+
else root.modeText = Permissions.toggle(root.modeText, bit)
|
|
472
|
+
forceActiveFocus()
|
|
473
|
+
}
|
|
474
|
+
Keys.onSpacePressed: toggle()
|
|
475
|
+
Keys.onTabPressed: function(event) { root.stepFocus((event.modifiers & Qt.ShiftModifier) !== 0) }
|
|
476
|
+
Keys.onBacktabPressed: root.stepFocus(true)
|
|
477
|
+
Flea.CheckBox {
|
|
478
|
+
x: root.boxLead(checkbox.index, width)
|
|
479
|
+
y: Math.round((parent.height - height) / 2)
|
|
480
|
+
// A bit differing across the files shows a bar until it is clicked.
|
|
481
|
+
value: root.isMulti ? root.multiValue(bit) : checkbox.checked ? "on" : "off"
|
|
482
|
+
focused: checkbox.activeFocus
|
|
483
|
+
// A disabled row stays checked, so the box dims and keeps its value.
|
|
484
|
+
available: root.editable
|
|
485
|
+
}
|
|
486
|
+
HoverHandler { id: boxHover }
|
|
487
|
+
TapHandler { id: boxTap; gesturePolicy: TapHandler.ReleaseWithinBounds; onTapped: checkbox.toggle() }
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
Item {
|
|
493
|
+
width: parent.width
|
|
494
|
+
height: Theme.spacing.rowPaddingY + root.railHalf + Theme.spacing.hairline
|
|
495
|
+
visible: !root.isMulti
|
|
496
|
+
Rule { y: root.railHalf }
|
|
497
|
+
}
|
|
498
|
+
Row {
|
|
499
|
+
width: parent.width
|
|
500
|
+
height: root.controlHeight
|
|
501
|
+
spacing: Theme.spacing.gap
|
|
502
|
+
// Permissions040: for several items Octal drops out.
|
|
503
|
+
visible: !root.isMulti
|
|
504
|
+
Text { width: root.labelWidth; anchors.verticalCenter: parent.verticalCenter; text: "Octal"; textFormat: Text.PlainText; color: Theme.color.foreground; font { family: Theme.font.family; pixelSize: Theme.font.body } }
|
|
505
|
+
Rectangle {
|
|
506
|
+
id: octalBox
|
|
507
|
+
width: body.holderWidth - root.labelWidth - parent.spacing
|
|
508
|
+
height: root.fieldHeight
|
|
509
|
+
y: Math.round((parent.height - height) / 2)
|
|
510
|
+
color: Theme.color.background
|
|
511
|
+
// A focused field is its own frame in the accent, and the error role where its line reports an error, as RenameField draws it.
|
|
512
|
+
border.color: octal.activeFocus ? (errorLabel.visible && !root.busy ? Theme.color.error : Theme.color.accent) : Theme.color.mutedFrame
|
|
513
|
+
TextInput {
|
|
514
|
+
id: octal
|
|
515
|
+
anchors.fill: parent
|
|
516
|
+
anchors.leftMargin: Theme.spacing.gap
|
|
517
|
+
anchors.rightMargin: Theme.spacing.gap
|
|
518
|
+
verticalAlignment: TextInput.AlignVCenter
|
|
519
|
+
text: root.modeText
|
|
520
|
+
readOnly: !root.editable
|
|
521
|
+
activeFocusOnTab: !root.isMulti
|
|
522
|
+
enabled: root.editable && !root.isMulti
|
|
523
|
+
Accessible.name: "Octal mode"
|
|
524
|
+
color: root.editable ? Theme.color.foreground : Theme.color.muted
|
|
525
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
526
|
+
clip: true
|
|
527
|
+
selectByMouse: true
|
|
528
|
+
Keys.onTabPressed: function(event) { root.stepFocus((event.modifiers & Qt.ShiftModifier) !== 0) }
|
|
529
|
+
Keys.onBacktabPressed: root.stepFocus(true)
|
|
530
|
+
onTextEdited: root.modeText = text
|
|
531
|
+
onAccepted: if (root.editable && root.modeValue >= 0) applyButton.forceActiveFocus()
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
Repeater {
|
|
536
|
+
model: ["Owner", "Group"]
|
|
537
|
+
Row {
|
|
538
|
+
required property string modelData
|
|
539
|
+
required property int index
|
|
540
|
+
// Permissions040: for several items Owner and Group drop out.
|
|
541
|
+
visible: !root.isMulti
|
|
542
|
+
width: body.holderWidth
|
|
543
|
+
height: root.controlHeight
|
|
544
|
+
spacing: Theme.spacing.gap
|
|
545
|
+
Text { width: root.labelWidth; anchors.verticalCenter: parent.verticalCenter; text: parent.modelData; textFormat: Text.PlainText; color: Theme.color.foreground; font { family: Theme.font.family; pixelSize: Theme.font.body } }
|
|
546
|
+
Text { width: body.holderWidth - root.labelWidth - identity.width - 2 * parent.spacing; anchors.verticalCenter: parent.verticalCenter; text: root.facts.ok ? ((parent.index === 0 ? root.facts.owner : root.facts.group) || "Unknown") + " · read-only" : ""; textFormat: Text.PlainText; elide: Text.ElideRight; color: Theme.color.foreground; font { family: Theme.font.family; pixelSize: Theme.font.body } }
|
|
547
|
+
Text { id: identity; anchors.verticalCenter: parent.verticalCenter; text: root.facts.ok ? (parent.index === 0 ? "uid " + root.facts.uid : "gid " + root.facts.gid) : ""; textFormat: Text.PlainText; color: Theme.color.foreground; font { family: Theme.font.family; pixelSize: Theme.font.caption } }
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
Rectangle {
|
|
551
|
+
width: parent.width
|
|
552
|
+
height: directoryScope.implicitHeight + 2 * Theme.spacing.gap
|
|
553
|
+
// Permissions040: for several items the scope box drops out.
|
|
554
|
+
visible: root.facts.directory === true && !root.isMulti
|
|
555
|
+
color: Theme.color.background
|
|
556
|
+
border.width: Theme.spacing.hairline
|
|
557
|
+
border.color: Theme.color.mutedFrame
|
|
558
|
+
Flea.Glyph { id: scopeMark; x: Theme.spacing.gap; y: Theme.spacing.gap; width: Theme.font.bodySmall; height: width; name: "check"; color: Theme.color.accent }
|
|
559
|
+
Text {
|
|
560
|
+
id: directoryScope
|
|
561
|
+
x: scopeMark.x + scopeMark.width + Theme.spacing.gap
|
|
562
|
+
y: Theme.spacing.gap
|
|
563
|
+
width: parent.width - x - Theme.spacing.gap
|
|
564
|
+
text: "Scope: this folder only. Items inside it keep their permissions."
|
|
565
|
+
textFormat: Text.PlainText
|
|
566
|
+
wrapMode: Text.Wrap
|
|
567
|
+
color: Theme.color.foreground
|
|
568
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
Text {
|
|
572
|
+
id: errorLabel
|
|
573
|
+
width: parent.width
|
|
574
|
+
visible: text.length > 0
|
|
575
|
+
topPadding: Theme.spacing.gap
|
|
576
|
+
text: root.errorText || root.facts.reason || (root.busy
|
|
577
|
+
? (root.isMulti ? (root.multiPending > 0 ? "Reading permissions…" : "Applying permissions…")
|
|
578
|
+
: (root.facts.ok ? "Applying permissions…" : "Reading permissions…"))
|
|
579
|
+
: root.facts.ok && root.modeValue < 0 ? "Enter three octal digits or a leading-zero four-digit mode." : "")
|
|
580
|
+
textFormat: Text.PlainText
|
|
581
|
+
wrapMode: Text.Wrap
|
|
582
|
+
color: root.busy ? Theme.color.muted : Theme.color.errorOnSurface
|
|
583
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
584
|
+
}
|
|
585
|
+
Item {
|
|
586
|
+
width: parent.width
|
|
587
|
+
height: root.isMulti ? root.multiGap : Theme.settings.railPaddingY + Theme.spacing.gap + Theme.spacing.hairline
|
|
588
|
+
Rule { y: Theme.settings.railPaddingY; visible: !root.isMulti }
|
|
589
|
+
}
|
|
590
|
+
Text {
|
|
591
|
+
text: "WILL CHANGE"
|
|
592
|
+
visible: !root.isMulti
|
|
593
|
+
bottomPadding: Math.round(Theme.spacing.rowPaddingY / 2)
|
|
594
|
+
textFormat: Text.PlainText
|
|
595
|
+
color: Theme.color.foreground
|
|
596
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption; letterSpacing: Theme.font.caption / 10 }
|
|
597
|
+
}
|
|
598
|
+
Text {
|
|
599
|
+
id: changeSummary
|
|
600
|
+
width: parent.width
|
|
601
|
+
// For several items the grid and Apply are the whole card, so the preview drops out.
|
|
602
|
+
visible: !root.isMulti
|
|
603
|
+
text: (root.facts.ok && !root.facts.reason && root.modeValue >= 0
|
|
604
|
+
? Format.fill(Permissions.WORDS.requestedMode, Permissions.octal(root.modeValue)) : "No changes to apply")
|
|
605
|
+
+ "\nPath " + root.path.replace(/\//g, "/\u200b")
|
|
606
|
+
+ (root.facts.reason ? "\n" + Format.fill(Permissions.WORDS.currentMode, root.facts.mode) : "")
|
|
607
|
+
textFormat: Text.PlainText
|
|
608
|
+
wrapMode: Text.WordWrap
|
|
609
|
+
color: Theme.color.accent
|
|
610
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
611
|
+
}
|
|
612
|
+
Text {
|
|
613
|
+
id: scopeLabel
|
|
614
|
+
width: parent.width
|
|
615
|
+
// Fixed line boxes put the spare height under the glyphs, so the top padding centres them as CSS line-height does.
|
|
616
|
+
height: lineCount * SettingsMetrics.hintLine
|
|
617
|
+
lineHeight: SettingsMetrics.hintLine
|
|
618
|
+
lineHeightMode: Text.FixedHeight
|
|
619
|
+
topPadding: root.captionLead
|
|
620
|
+
// A box whose bit differs across the files shows a bar until it is clicked.
|
|
621
|
+
text: root.isMulti ? Permissions.mixedNote() : root.scopeText
|
|
622
|
+
textFormat: Text.PlainText
|
|
623
|
+
wrapMode: Text.Wrap
|
|
624
|
+
color: Theme.color.foreground
|
|
625
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
buttons: Column {
|
|
629
|
+
width: parent.width
|
|
630
|
+
Item { width: parent.width; height: root.isMulti ? root.multiGap + root.buttonLead : Theme.settings.railPaddingY + Theme.spacing.hairline }
|
|
631
|
+
Row {
|
|
632
|
+
anchors.right: parent.right
|
|
633
|
+
spacing: Theme.spacing.gap
|
|
634
|
+
Flea.DialogButton {
|
|
635
|
+
id: cancelButton
|
|
636
|
+
label: "Cancel"
|
|
637
|
+
available: !root.applyLocked
|
|
638
|
+
tabHandle: true
|
|
639
|
+
tabStop: true
|
|
640
|
+
onTabbed: function(from, back) { root.stepFocus(back) }
|
|
641
|
+
onActivated: root.close()
|
|
642
|
+
}
|
|
643
|
+
Flea.DialogButton {
|
|
644
|
+
id: applyButton
|
|
645
|
+
label: "Apply"
|
|
646
|
+
primary: true
|
|
647
|
+
// The multi card has no octal to validate, so Apply enables on the grid alone.
|
|
648
|
+
available: root.canApply
|
|
649
|
+
tabHandle: true
|
|
650
|
+
tabStop: true
|
|
651
|
+
onTabbed: function(from, back) { root.stepFocus(back) }
|
|
652
|
+
onActivated: root.apply()
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|