zui 0.0.1
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.
- checksums.yaml +7 -0
- data/Components/Builtins/Accordion.qml +208 -0
- data/Components/Builtins/Action.qml +43 -0
- data/Components/Builtins/ActionButton.qml +19 -0
- data/Components/Builtins/ActionGroup.qml +81 -0
- data/Components/Builtins/AlertDialog.qml +398 -0
- data/Components/Builtins/AnchorAnimation.qml +3 -0
- data/Components/Builtins/AnchorChanges.qml +11 -0
- data/Components/Builtins/AnimatedImage.qml +39 -0
- data/Components/Builtins/Animation.qml +3 -0
- data/Components/Builtins/AnimationController.qml +11 -0
- data/Components/Builtins/ApplicationWindow.qml +103 -0
- data/Components/Builtins/AreaChart.qml +70 -0
- data/Components/Builtins/AspectRatio.qml +30 -0
- data/Components/Builtins/Audio.qml +85 -0
- data/Components/Builtins/AudioInput.qml +10 -0
- data/Components/Builtins/AudioOutput.qml +10 -0
- data/Components/Builtins/Avatar.qml +46 -0
- data/Components/Builtins/Badge.qml +38 -0
- data/Components/Builtins/Banner.qml +133 -0
- data/Components/Builtins/BarChart.qml +67 -0
- data/Components/Builtins/BarIconButton.qml +30 -0
- data/Components/Builtins/BarIndicator.qml +26 -0
- data/Components/Builtins/Behavior.qml +13 -0
- data/Components/Builtins/Blur.qml +14 -0
- data/Components/Builtins/BorderImage.qml +38 -0
- data/Components/Builtins/BorderOverlay.qml +25 -0
- data/Components/Builtins/BottomSheet.qml +211 -0
- data/Components/Builtins/Breadcrumb.qml +169 -0
- data/Components/Builtins/BubbleChart.qml +3 -0
- data/Components/Builtins/BusyIndicator.qml +24 -0
- data/Components/Builtins/Button.qml +55 -0
- data/Components/Builtins/ButtonGroup.qml +18 -0
- data/Components/Builtins/Calendar.qml +55 -0
- data/Components/Builtins/Camera.qml +18 -0
- data/Components/Builtins/CandlestickChart.qml +3 -0
- data/Components/Builtins/Canvas.qml +159 -0
- data/Components/Builtins/CaptureSession.qml +19 -0
- data/Components/Builtins/Card.qml +23 -0
- data/Components/Builtins/Carousel.qml +72 -0
- data/Components/Builtins/Center.qml +20 -0
- data/Components/Builtins/CheckDelegate.qml +132 -0
- data/Components/Builtins/Checkbox.qml +62 -0
- data/Components/Builtins/Chip.qml +65 -0
- data/Components/Builtins/Circle.qml +35 -0
- data/Components/Builtins/Clipboard.qml +29 -0
- data/Components/Builtins/ColorAnimation.qml +3 -0
- data/Components/Builtins/ColorPicker.qml +70 -0
- data/Components/Builtins/Colorize.qml +14 -0
- data/Components/Builtins/Column.qml +17 -0
- data/Components/Builtins/ColumnLayout.qml +13 -0
- data/Components/Builtins/ConfirmDialog.qml +20 -0
- data/Components/Builtins/ConstrainedBox.qml +28 -0
- data/Components/Builtins/Container.qml +30 -0
- data/Components/Builtins/ContextMenu.qml +140 -0
- data/Components/Builtins/CursorSurface.qml +18 -0
- data/Components/Builtins/DataTable.qml +69 -0
- data/Components/Builtins/DatePicker.qml +180 -0
- data/Components/Builtins/DayOfWeekRow.qml +11 -0
- data/Components/Builtins/DelayButton.qml +47 -0
- data/Components/Builtins/DelegateModel.qml +10 -0
- data/Components/Builtins/DelegateModelGroup.qml +10 -0
- data/Components/Builtins/Dial.qml +42 -0
- data/Components/Builtins/Dialog.qml +128 -0
- data/Components/Builtins/DialogButtonBox.qml +137 -0
- data/Components/Builtins/Divider.qml +26 -0
- data/Components/Builtins/DonutChart.qml +3 -0
- data/Components/Builtins/DoubleSpinBox.qml +58 -0
- data/Components/Builtins/DragArea.qml +43 -0
- data/Components/Builtins/Drawer.qml +107 -0
- data/Components/Builtins/DropArea.qml +19 -0
- data/Components/Builtins/DropShadow.qml +16 -0
- data/Components/Builtins/Dropdown.qml +19 -0
- data/Components/Builtins/ExpansionPanel.qml +157 -0
- data/Components/Builtins/FilePicker.qml +140 -0
- data/Components/Builtins/FittedBox.qml +40 -0
- data/Components/Builtins/Flickable.qml +40 -0
- data/Components/Builtins/Flipable.qml +45 -0
- data/Components/Builtins/Flow.qml +16 -0
- data/Components/Builtins/FocusScope.qml +29 -0
- data/Components/Builtins/FolderListModel.qml +9 -0
- data/Components/Builtins/FolderPicker.qml +93 -0
- data/Components/Builtins/FontLoader.qml +21 -0
- data/Components/Builtins/FontPicker.qml +91 -0
- data/Components/Builtins/Frame.qml +71 -0
- data/Components/Builtins/FrameAnimation.qml +13 -0
- data/Components/Builtins/Gauge.qml +3 -0
- data/Components/Builtins/Glow.qml +15 -0
- data/Components/Builtins/Gradient.qml +93 -0
- data/Components/Builtins/Grid.qml +16 -0
- data/Components/Builtins/GridLayout.qml +16 -0
- data/Components/Builtins/GridView.qml +226 -0
- data/Components/Builtins/GroupBox.qml +95 -0
- data/Components/Builtins/Heatmap.qml +3 -0
- data/Components/Builtins/Histogram.qml +3 -0
- data/Components/Builtins/HorizontalHeader.qml +23 -0
- data/Components/Builtins/HorizontalHeaderDelegate.qml +39 -0
- data/Components/Builtins/HoverArea.qml +19 -0
- data/Components/Builtins/Icon.qml +16 -0
- data/Components/Builtins/Image.qml +110 -0
- data/Components/Builtins/ImageCapture.qml +14 -0
- data/Components/Builtins/ItemDelegate.qml +152 -0
- data/Components/Builtins/KeyCatcher.qml +25 -0
- data/Components/Builtins/Label.qml +43 -0
- data/Components/Builtins/LayoutItemProxy.qml +51 -0
- data/Components/Builtins/Legend.qml +86 -0
- data/Components/Builtins/Line.qml +28 -0
- data/Components/Builtins/LineChart.qml +87 -0
- data/Components/Builtins/ListModel.qml +8 -0
- data/Components/Builtins/ListView.qml +65 -0
- data/Components/Builtins/Loader.qml +33 -0
- data/Components/Builtins/Markdown.qml +23 -0
- data/Components/Builtins/MediaDevices.qml +10 -0
- data/Components/Builtins/MediaPlayer.qml +27 -0
- data/Components/Builtins/MediaRecorder.qml +16 -0
- data/Components/Builtins/Menu.qml +119 -0
- data/Components/Builtins/MenuBar.qml +128 -0
- data/Components/Builtins/MenuItem.qml +77 -0
- data/Components/Builtins/MenuSeparator.qml +30 -0
- data/Components/Builtins/MessageDialog.qml +104 -0
- data/Components/Builtins/ModalSheet.qml +222 -0
- data/Components/Builtins/ModelView3d.qml +50 -0
- data/Components/Builtins/MonthGrid.qml +23 -0
- data/Components/Builtins/MultiEffect.qml +48 -0
- data/Components/Builtins/MultiSelect.qml +23 -0
- data/Components/Builtins/NavigationRail.qml +154 -0
- data/Components/Builtins/NumberAnimation.qml +3 -0
- data/Components/Builtins/NumberField.qml +18 -0
- data/Components/Builtins/OpacityAnimator.qml +3 -0
- data/Components/Builtins/OpacityMask.qml +21 -0
- data/Components/Builtins/OpticalGlyph.qml +16 -0
- data/Components/Builtins/Page.qml +111 -0
- data/Components/Builtins/PageIndicator.qml +63 -0
- data/Components/Builtins/Pagination.qml +158 -0
- data/Components/Builtins/Pane.qml +72 -0
- data/Components/Builtins/PanelHero.qml +15 -0
- data/Components/Builtins/ParallelAnimation.qml +3 -0
- data/Components/Builtins/ParentAnimation.qml +3 -0
- data/Components/Builtins/ParentChange.qml +10 -0
- data/Components/Builtins/ParticleSystem.qml +81 -0
- data/Components/Builtins/PasswordField.qml +58 -0
- data/Components/Builtins/Path.qml +35 -0
- data/Components/Builtins/PathAnimation.qml +3 -0
- data/Components/Builtins/PauseAnimation.qml +3 -0
- data/Components/Builtins/PieChart.qml +3 -0
- data/Components/Builtins/PinchArea.qml +23 -0
- data/Components/Builtins/Popup.qml +130 -0
- data/Components/Builtins/Progress.qml +15 -0
- data/Components/Builtins/ProgressRing.qml +120 -0
- data/Components/Builtins/PropertyAction.qml +11 -0
- data/Components/Builtins/PropertyAnimation.qml +3 -0
- data/Components/Builtins/PropertyChanges.qml +10 -0
- data/Components/Builtins/RadarChart.qml +3 -0
- data/Components/Builtins/RadialGauge.qml +3 -0
- data/Components/Builtins/RadioButton.qml +46 -0
- data/Components/Builtins/RadioDelegate.qml +115 -0
- data/Components/Builtins/RadioGroup.qml +58 -0
- data/Components/Builtins/RangeSlider.qml +39 -0
- data/Components/Builtins/Rectangle.qml +23 -0
- data/Components/Builtins/RectangularShadow.qml +23 -0
- data/Components/Builtins/ReorderableList.qml +204 -0
- data/Components/Builtins/RichText.qml +23 -0
- data/Components/Builtins/RotationAnimation.qml +3 -0
- data/Components/Builtins/RotationAnimator.qml +3 -0
- data/Components/Builtins/RoundButton.qml +42 -0
- data/Components/Builtins/Row.qml +17 -0
- data/Components/Builtins/RowLayout.qml +13 -0
- data/Components/Builtins/ScaleAnimator.qml +3 -0
- data/Components/Builtins/ScatterChart.qml +3 -0
- data/Components/Builtins/ScreenCapture.qml +78 -0
- data/Components/Builtins/ScriptAction.qml +15 -0
- data/Components/Builtins/Scroll.qml +18 -0
- data/Components/Builtins/ScrollBar.qml +18 -0
- data/Components/Builtins/ScrollIndicator.qml +15 -0
- data/Components/Builtins/SearchField.qml +178 -0
- data/Components/Builtins/SearchableDropdown.qml +21 -0
- data/Components/Builtins/SectionHeader.qml +14 -0
- data/Components/Builtins/SelectableText.qml +33 -0
- data/Components/Builtins/SelectionRectangle.qml +17 -0
- data/Components/Builtins/Separator.qml +13 -0
- data/Components/Builtins/SequentialAnimation.qml +3 -0
- data/Components/Builtins/Settings.qml +10 -0
- data/Components/Builtins/ShaderEffect.qml +115 -0
- data/Components/Builtins/ShaderEffectSource.qml +61 -0
- data/Components/Builtins/Shaders/grayscale.frag +14 -0
- data/Components/Builtins/Shaders/grayscale.frag.qsb +0 -0
- data/Components/Builtins/Shaders/passthrough.frag +11 -0
- data/Components/Builtins/Shaders/passthrough.frag.qsb +0 -0
- data/Components/Builtins/Shaders/pixelate.frag +16 -0
- data/Components/Builtins/Shaders/pixelate.frag.qsb +0 -0
- data/Components/Builtins/Shaders/vignette.frag +18 -0
- data/Components/Builtins/Shaders/vignette.frag.qsb +0 -0
- data/Components/Builtins/Shaders/wave.frag +18 -0
- data/Components/Builtins/Shaders/wave.frag.qsb +0 -0
- data/Components/Builtins/Shape.qml +53 -0
- data/Components/Builtins/Skeleton.qml +78 -0
- data/Components/Builtins/Slider.qml +21 -0
- data/Components/Builtins/SmoothedAnimation.qml +3 -0
- data/Components/Builtins/Snackbar.qml +181 -0
- data/Components/Builtins/SortFilterProxyModel.qml +16 -0
- data/Components/Builtins/SoundEffect.qml +10 -0
- data/Components/Builtins/Spacer.qml +13 -0
- data/Components/Builtins/Sparkline.qml +3 -0
- data/Components/Builtins/SpinBox.qml +44 -0
- data/Components/Builtins/SplitView.qml +31 -0
- data/Components/Builtins/SpringAnimation.qml +3 -0
- data/Components/Builtins/Stack.qml +14 -0
- data/Components/Builtins/StackLayout.qml +19 -0
- data/Components/Builtins/StackView.qml +122 -0
- data/Components/Builtins/StackedBarChart.qml +3 -0
- data/Components/Builtins/StandardPaths.qml +9 -0
- data/Components/Builtins/State.qml +13 -0
- data/Components/Builtins/StateGroup.qml +11 -0
- data/Components/Builtins/Support/AnimationDriver.qml +79 -0
- data/Components/Builtins/Support/AnimationGroupDriver.qml +32 -0
- data/Components/Builtins/Support/ChartCanvas.qml +629 -0
- data/Components/Builtins/Support/ModelView3dScene.qml +292 -0
- data/Components/Builtins/Support/OptionalModuleState.js +5 -0
- data/Components/Builtins/SwipeDelegate.qml +231 -0
- data/Components/Builtins/SwipeView.qml +69 -0
- data/Components/Builtins/SwitchDelegate.qml +140 -0
- data/Components/Builtins/TabBar.qml +117 -0
- data/Components/Builtins/TabButton.qml +105 -0
- data/Components/Builtins/TableView.qml +388 -0
- data/Components/Builtins/TableViewDelegate.qml +17 -0
- data/Components/Builtins/Tabs.qml +138 -0
- data/Components/Builtins/Text.qml +24 -0
- data/Components/Builtins/TextArea.qml +59 -0
- data/Components/Builtins/TextField.qml +21 -0
- data/Components/Builtins/TextMetrics.qml +39 -0
- data/Components/Builtins/TimePicker.qml +213 -0
- data/Components/Builtins/Timer.qml +13 -0
- data/Components/Builtins/Toast.qml +213 -0
- data/Components/Builtins/Toggle.qml +19 -0
- data/Components/Builtins/ToggleSwitch.qml +22 -0
- data/Components/Builtins/ToolBar.qml +61 -0
- data/Components/Builtins/ToolButton.qml +41 -0
- data/Components/Builtins/ToolSeparator.qml +36 -0
- data/Components/Builtins/Tooltip.qml +20 -0
- data/Components/Builtins/Transition.qml +3 -0
- data/Components/Builtins/TreeView.qml +423 -0
- data/Components/Builtins/TreeViewDelegate.qml +46 -0
- data/Components/Builtins/Tumbler.qml +18 -0
- data/Components/Builtins/UniformAnimator.qml +3 -0
- data/Components/Builtins/VectorAnimation.qml +3 -0
- data/Components/Builtins/VectorImage.qml +62 -0
- data/Components/Builtins/VerticalHeader.qml +21 -0
- data/Components/Builtins/VerticalHeaderDelegate.qml +35 -0
- data/Components/Builtins/Video.qml +54 -0
- data/Components/Builtins/VideoOutput.qml +54 -0
- data/Components/Builtins/WebView.qml +57 -0
- data/Components/Builtins/WeekNumberColumn.qml +13 -0
- data/Components/Builtins/WidgetButton.qml +26 -0
- data/Components/Builtins/Window.qml +90 -0
- data/Components/Builtins/WindowCapture.qml +11 -0
- data/Components/Builtins/Wrap.qml +18 -0
- data/Components/Builtins/XAnimator.qml +3 -0
- data/Components/Builtins/YAnimator.qml +3 -0
- data/Components/README.md +45 -0
- data/ControlNode.qml +1369 -0
- data/Controls/BarIconButton.qml +27 -0
- data/Controls/BarIndicator.qml +22 -0
- data/Controls/BorderOverlay.qml +10 -0
- data/Controls/BorderSurface.qml +10 -0
- data/Controls/Button.qml +78 -0
- data/Controls/ButtonGroup.qml +19 -0
- data/Controls/ConfirmDialog.qml +37 -0
- data/Controls/CursorSurface.qml +29 -0
- data/Controls/Dropdown.qml +59 -0
- data/Controls/MultiSelect.qml +32 -0
- data/Controls/NumberField.qml +24 -0
- data/Controls/OpticalGlyph.qml +14 -0
- data/Controls/PanelActionButton.qml +10 -0
- data/Controls/PanelHero.qml +18 -0
- data/Controls/PanelKeyCatcher.qml +25 -0
- data/Controls/PanelSectionHeader.qml +11 -0
- data/Controls/PanelSeparator.qml +10 -0
- data/Controls/PanelSlider.qml +36 -0
- data/Controls/PanelToolTip.qml +13 -0
- data/Controls/SearchableDropdown.qml +11 -0
- data/Controls/TextField.qml +25 -0
- data/Controls/Toggle.qml +22 -0
- data/Controls/ToggleSwitch.qml +26 -0
- data/Controls/WidgetButton.qml +35 -0
- data/Controls/qmldir +25 -0
- data/Desktop.qml +76 -0
- data/LICENSE +22 -0
- data/README.md +112 -0
- data/Service.qml +430 -0
- data/Theme/Border.qml +22 -0
- data/Theme/Color.qml +22 -0
- data/Theme/Style.qml +47 -0
- data/Theme/Util.qml +6 -0
- data/Theme/qmldir +5 -0
- data/bin/zui +7 -0
- data/lib/zui/animation.rb +24 -0
- data/lib/zui/application.rb +327 -0
- data/lib/zui/builder.rb +725 -0
- data/lib/zui/cli.rb +91 -0
- data/lib/zui/command.rb +101 -0
- data/lib/zui/component_registry.rb +91 -0
- data/lib/zui/components.rb +262 -0
- data/lib/zui/distribution.rb +200 -0
- data/lib/zui/generator.rb +84 -0
- data/lib/zui/host.rb +123 -0
- data/lib/zui/node.rb +30 -0
- data/lib/zui/platform.rb +40 -0
- data/lib/zui/protocol.rb +29 -0
- data/lib/zui/runner.rb +37 -0
- data/lib/zui/runtime.rb +23 -0
- data/lib/zui/scheduler.rb +136 -0
- data/lib/zui/source_bundle.rb +63 -0
- data/lib/zui/state_store.rb +100 -0
- data/lib/zui/value.rb +44 -0
- data/lib/zui.rb +33 -0
- data/native/CMakeLists.txt +45 -0
- data/native/ZuiClipboard.cpp +16 -0
- data/native/ZuiClipboard.h +16 -0
- data/native/ZuiProcess.cpp +84 -0
- data/native/ZuiProcess.h +34 -0
- data/native/main.cpp +64 -0
- data/vendor/host/linux-x86_64/PROVENANCE.md +15 -0
- data/vendor/host/linux-x86_64/zui-host +0 -0
- data/vendor/host/linux-x86_64/zui-host.sha256 +1 -0
- metadata +365 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
module Zui
|
|
7
|
+
class Distribution
|
|
8
|
+
attr_reader :platform
|
|
9
|
+
|
|
10
|
+
def initialize(host: Host.new, platform: Platform.current, framework_root: FRAMEWORK_ROOT)
|
|
11
|
+
@host = host
|
|
12
|
+
@platform = platform.assert_supported!
|
|
13
|
+
@framework_root = framework_root
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def bundle(source, name: nil, destination: nil)
|
|
17
|
+
project = File.expand_path(source)
|
|
18
|
+
raise ArgumentError, "project directory not found: #{project}" unless File.directory?(project)
|
|
19
|
+
raise ArgumentError, "main.rb not found: #{project}" unless File.file?(File.join(project, "main.rb"))
|
|
20
|
+
app_name = name || titleize(File.basename(project))
|
|
21
|
+
destination ||= default_destination(project, app_name)
|
|
22
|
+
destination = File.expand_path(destination)
|
|
23
|
+
raise ArgumentError, "bundle destination already exists: #{destination}" if File.exist?(destination)
|
|
24
|
+
|
|
25
|
+
case platform.os
|
|
26
|
+
when :linux then bundle_linux(project, destination, app_name)
|
|
27
|
+
when :macos then bundle_macos(project, destination, app_name)
|
|
28
|
+
when :windows then bundle_windows(project, destination, app_name)
|
|
29
|
+
end
|
|
30
|
+
destination
|
|
31
|
+
rescue StandardError
|
|
32
|
+
FileUtils.remove_entry(destination) if destination && File.exist?(destination)
|
|
33
|
+
raise
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def bundle_linux(project, destination, app_name)
|
|
39
|
+
FileUtils.mkdir_p([File.join(destination, "app"), File.join(destination, "bin"),
|
|
40
|
+
File.join(destination, "runtime"), File.join(destination, "share", "applications")])
|
|
41
|
+
install_application(project, File.join(destination, "app"))
|
|
42
|
+
install_runtime(File.join(destination, "runtime"))
|
|
43
|
+
FileUtils.cp(@host.executable, File.join(destination, "bin", "zui-host"))
|
|
44
|
+
FileUtils.chmod(0o755, File.join(destination, "bin", "zui-host"))
|
|
45
|
+
write_linux_launcher(destination, app_name)
|
|
46
|
+
desktop_name = "#{slug(app_name)}.desktop"
|
|
47
|
+
File.write(File.join(destination, "share", "applications", desktop_name), <<~DESKTOP)
|
|
48
|
+
[Desktop Entry]
|
|
49
|
+
Type=Application
|
|
50
|
+
Name=#{app_name}
|
|
51
|
+
Exec=#{File.join(destination, "run")}
|
|
52
|
+
Terminal=false
|
|
53
|
+
Categories=Utility;
|
|
54
|
+
DESKTOP
|
|
55
|
+
write_manifest(destination, app_name)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def bundle_macos(project, destination, app_name)
|
|
59
|
+
contents = File.join(destination, "Contents")
|
|
60
|
+
macos = File.join(contents, "MacOS")
|
|
61
|
+
resources = File.join(contents, "Resources")
|
|
62
|
+
FileUtils.mkdir_p([macos, File.join(resources, "app"), File.join(resources, "runtime")])
|
|
63
|
+
install_application(project, File.join(resources, "app"))
|
|
64
|
+
install_runtime(File.join(resources, "runtime"))
|
|
65
|
+
FileUtils.cp(@host.executable, File.join(macos, "zui-host"))
|
|
66
|
+
FileUtils.chmod(0o755, File.join(macos, "zui-host"))
|
|
67
|
+
File.write(File.join(macos, "run"), macos_launcher(app_name))
|
|
68
|
+
FileUtils.chmod(0o755, File.join(macos, "run"))
|
|
69
|
+
File.write(File.join(contents, "Info.plist"), info_plist(app_name))
|
|
70
|
+
write_manifest(resources, app_name)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def bundle_windows(project, destination, app_name)
|
|
74
|
+
FileUtils.mkdir_p([File.join(destination, "app"), File.join(destination, "bin"),
|
|
75
|
+
File.join(destination, "runtime")])
|
|
76
|
+
install_application(project, File.join(destination, "app"))
|
|
77
|
+
install_runtime(File.join(destination, "runtime"))
|
|
78
|
+
FileUtils.cp(@host.executable, File.join(destination, "bin", "zui-host.exe"))
|
|
79
|
+
File.write(File.join(destination, "run.rb"), windows_ruby_launcher(app_name))
|
|
80
|
+
File.write(File.join(destination, "run.cmd"), windows_command_launcher)
|
|
81
|
+
write_manifest(destination, app_name)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def install_application(source, destination)
|
|
85
|
+
entries = Dir.children(source).reject do |entry|
|
|
86
|
+
entry_path = File.join(source, entry)
|
|
87
|
+
%w[.git dist].include?(entry) || destination.start_with?("#{entry_path}#{File::SEPARATOR}")
|
|
88
|
+
end
|
|
89
|
+
FileUtils.cp_r(entries.map { |entry| File.join(source, entry) }, destination) unless entries.empty?
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def install_runtime(destination)
|
|
93
|
+
Runtime.install_qml(File.join(destination, "qml"), framework_root: @framework_root)
|
|
94
|
+
FileUtils.mkdir_p(File.join(destination, "lib"))
|
|
95
|
+
FileUtils.cp(File.join(@framework_root, "lib", "zui.rb"), File.join(destination, "lib", "zui.rb"))
|
|
96
|
+
FileUtils.cp_r(File.join(@framework_root, "lib", "zui"), File.join(destination, "lib", "zui"))
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def write_linux_launcher(destination, app_name)
|
|
100
|
+
File.write(File.join(destination, "run"), <<~SH)
|
|
101
|
+
#!/bin/sh
|
|
102
|
+
set -eu
|
|
103
|
+
bundle_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
104
|
+
ruby_command=${ZUI_RUBY:-ruby}
|
|
105
|
+
exec "$bundle_dir/bin/zui-host" \
|
|
106
|
+
--qml-root "$bundle_dir/runtime/qml" \
|
|
107
|
+
--project "$bundle_dir/app" \
|
|
108
|
+
--program "$bundle_dir/app/main.rb" \
|
|
109
|
+
--ruby "$ruby_command" \
|
|
110
|
+
--load-path "$bundle_dir/runtime/lib" \
|
|
111
|
+
--name #{shell_quote(app_name)}
|
|
112
|
+
SH
|
|
113
|
+
FileUtils.chmod(0o755, File.join(destination, "run"))
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def macos_launcher(app_name)
|
|
117
|
+
<<~SH
|
|
118
|
+
#!/bin/sh
|
|
119
|
+
set -eu
|
|
120
|
+
contents=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
|
121
|
+
resources="$contents/Resources"
|
|
122
|
+
ruby_command=${ZUI_RUBY:-ruby}
|
|
123
|
+
exec "$contents/MacOS/zui-host" \
|
|
124
|
+
--qml-root "$resources/runtime/qml" \
|
|
125
|
+
--project "$resources/app" \
|
|
126
|
+
--program "$resources/app/main.rb" \
|
|
127
|
+
--ruby "$ruby_command" \
|
|
128
|
+
--load-path "$resources/runtime/lib" \
|
|
129
|
+
--name #{shell_quote(app_name)}
|
|
130
|
+
SH
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def windows_ruby_launcher(app_name)
|
|
134
|
+
<<~RUBY
|
|
135
|
+
# frozen_string_literal: true
|
|
136
|
+
|
|
137
|
+
require "rbconfig"
|
|
138
|
+
|
|
139
|
+
bundle_dir = File.expand_path(__dir__)
|
|
140
|
+
arguments = [
|
|
141
|
+
File.join(bundle_dir, "bin", "zui-host.exe"),
|
|
142
|
+
"--qml-root", File.join(bundle_dir, "runtime", "qml"),
|
|
143
|
+
"--project", File.join(bundle_dir, "app"),
|
|
144
|
+
"--program", File.join(bundle_dir, "app", "main.rb"),
|
|
145
|
+
"--ruby", RbConfig.ruby,
|
|
146
|
+
"--load-path", File.join(bundle_dir, "runtime", "lib"),
|
|
147
|
+
"--name", #{app_name.to_s.dump}
|
|
148
|
+
]
|
|
149
|
+
exec(*arguments)
|
|
150
|
+
RUBY
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def windows_command_launcher
|
|
154
|
+
<<~CMD.gsub("\n", "\r\n")
|
|
155
|
+
@echo off
|
|
156
|
+
setlocal
|
|
157
|
+
if defined ZUI_RUBY (
|
|
158
|
+
"%ZUI_RUBY%" "%~dp0run.rb"
|
|
159
|
+
) else (
|
|
160
|
+
ruby "%~dp0run.rb"
|
|
161
|
+
)
|
|
162
|
+
exit /b %ERRORLEVEL%
|
|
163
|
+
CMD
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def info_plist(app_name)
|
|
167
|
+
identifier = "dev.zui.#{slug(app_name).tr("-", ".")}"
|
|
168
|
+
<<~PLIST
|
|
169
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
170
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
171
|
+
<plist version="1.0"><dict>
|
|
172
|
+
<key>CFBundleExecutable</key><string>run</string>
|
|
173
|
+
<key>CFBundleIdentifier</key><string>#{identifier}</string>
|
|
174
|
+
<key>CFBundleName</key><string>#{xml_escape(app_name)}</string>
|
|
175
|
+
<key>CFBundlePackageType</key><string>APPL</string>
|
|
176
|
+
<key>CFBundleShortVersionString</key><string>#{VERSION}</string>
|
|
177
|
+
<key>NSHighResolutionCapable</key><true/>
|
|
178
|
+
</dict></plist>
|
|
179
|
+
PLIST
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def write_manifest(directory, app_name)
|
|
183
|
+
File.write(File.join(directory, "zui-bundle.json"), JSON.pretty_generate(
|
|
184
|
+
"format" => 1, "framework" => "zui", "version" => VERSION,
|
|
185
|
+
"platform" => platform.os.to_s, "architecture" => platform.arch.to_s,
|
|
186
|
+
"name" => app_name
|
|
187
|
+
))
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def default_destination(project, app_name)
|
|
191
|
+
base = File.join(project, "dist")
|
|
192
|
+
platform.macos? ? File.join(base, "#{app_name}.app") : File.join(base, "#{slug(app_name)}-#{platform.id}")
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def titleize(value) = value.split(/[-_]/).map(&:capitalize).join(" ")
|
|
196
|
+
def slug(value) = value.downcase.gsub(/[^a-z0-9]+/, "-").gsub(/\A-|-\z/, "")
|
|
197
|
+
def shell_quote(value) = "'#{value.to_s.gsub("'", %q('"'"'))}'"
|
|
198
|
+
def xml_escape(value) = value.to_s.gsub("&", "&").gsub("<", "<").gsub(">", ">")
|
|
199
|
+
end
|
|
200
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Zui
|
|
6
|
+
class Generator
|
|
7
|
+
def initialize(path:, name: nil)
|
|
8
|
+
@path = File.expand_path(path)
|
|
9
|
+
@name = name || File.basename(@path).split(/[-_]/).map(&:capitalize).join(" ")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def create
|
|
13
|
+
raise ArgumentError, "destination already exists: #{@path}" if File.exist?(@path)
|
|
14
|
+
created = true
|
|
15
|
+
FileUtils.mkdir_p(File.join(@path, "components"))
|
|
16
|
+
File.write(File.join(@path, "main.rb"), main_program)
|
|
17
|
+
File.write(File.join(@path, "components", "welcome.rb"), welcome_component)
|
|
18
|
+
File.write(File.join(@path, "README.md"), readme)
|
|
19
|
+
@path
|
|
20
|
+
rescue StandardError
|
|
21
|
+
FileUtils.remove_entry(@path) if created && File.directory?(@path)
|
|
22
|
+
raise
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def main_program
|
|
28
|
+
<<~RUBY
|
|
29
|
+
# frozen_string_literal: true
|
|
30
|
+
|
|
31
|
+
require "zui"
|
|
32
|
+
require_relative "components/welcome"
|
|
33
|
+
|
|
34
|
+
module #{constant_name}
|
|
35
|
+
def self.build
|
|
36
|
+
Zui::Application.new(ui: WelcomeComponent) do
|
|
37
|
+
app :main, title: "#{@name}", width: 760, height: 520 do
|
|
38
|
+
welcome_card(title: "Welcome to #{@name}", message: "A native cross-platform Zui application.")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.run = build.run
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
#{constant_name}.run
|
|
47
|
+
RUBY
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def welcome_component
|
|
51
|
+
<<~RUBY
|
|
52
|
+
# frozen_string_literal: true
|
|
53
|
+
|
|
54
|
+
module WelcomeComponent
|
|
55
|
+
def welcome_card(title:, message:)
|
|
56
|
+
card padding: 24, spacing: 12 do
|
|
57
|
+
text title, style: :heading
|
|
58
|
+
text message, wrap: true
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
RUBY
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def readme
|
|
66
|
+
<<~MARKDOWN
|
|
67
|
+
# #{@name}
|
|
68
|
+
|
|
69
|
+
A native Linux, macOS, and Windows desktop application written in Ruby with Zui.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
zui run main.rb
|
|
73
|
+
zui bundle
|
|
74
|
+
```
|
|
75
|
+
MARKDOWN
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def constant_name
|
|
79
|
+
value = @name.scan(/[a-z0-9]+/i).map { |part| part[0].upcase + part[1..].to_s }.join
|
|
80
|
+
value = "Application#{value}" if value.match?(/\A\d/)
|
|
81
|
+
value.empty? ? "ZuiApplication" : value
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
data/lib/zui/host.rb
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "tmpdir"
|
|
5
|
+
|
|
6
|
+
module Zui
|
|
7
|
+
class Host
|
|
8
|
+
attr_reader :platform
|
|
9
|
+
|
|
10
|
+
def initialize(platform: Platform.current, framework_root: FRAMEWORK_ROOT, environment: ENV)
|
|
11
|
+
@platform = platform.assert_supported!
|
|
12
|
+
@framework_root = framework_root
|
|
13
|
+
@environment = environment
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def executable(build: true)
|
|
17
|
+
override = @environment["ZUI_HOST"]
|
|
18
|
+
return checked_executable(override) if override && !override.empty?
|
|
19
|
+
return bundled if File.executable?(bundled)
|
|
20
|
+
return cached if File.executable?(cached)
|
|
21
|
+
return nil unless build
|
|
22
|
+
|
|
23
|
+
build!(cached)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def available? = !executable(build: false).nil?
|
|
27
|
+
|
|
28
|
+
def build!(destination = cached)
|
|
29
|
+
cmake = find_command("cmake")
|
|
30
|
+
raise ArgumentError, platform_help unless cmake
|
|
31
|
+
|
|
32
|
+
FileUtils.mkdir_p(File.dirname(destination))
|
|
33
|
+
Dir.mktmpdir("zui-host-build-") do |build_dir|
|
|
34
|
+
configure = Command.run([
|
|
35
|
+
cmake, "-S", File.join(@framework_root, "native"), "-B", build_dir,
|
|
36
|
+
"-DCMAKE_BUILD_TYPE=Release"
|
|
37
|
+
], timeout: 180, max_output_bytes: 4_194_304)
|
|
38
|
+
raise ArgumentError, "Zui host configuration failed:\n#{configure.stderr}" unless configure.success?
|
|
39
|
+
|
|
40
|
+
compile = Command.run([cmake, "--build", build_dir, "--config", "Release", "--parallel"],
|
|
41
|
+
timeout: 600, max_output_bytes: 8_388_608)
|
|
42
|
+
raise ArgumentError, "Zui host build failed:\n#{compile.stderr}" unless compile.success?
|
|
43
|
+
|
|
44
|
+
built = locate_build(build_dir)
|
|
45
|
+
raise ArgumentError, "Zui host build produced no executable" unless built
|
|
46
|
+
temporary = "#{destination}.install-#{Process.pid}"
|
|
47
|
+
FileUtils.cp(built, temporary)
|
|
48
|
+
FileUtils.chmod(0o755, temporary)
|
|
49
|
+
File.rename(temporary, destination)
|
|
50
|
+
ensure
|
|
51
|
+
FileUtils.rm_f(temporary) if temporary && File.exist?(temporary)
|
|
52
|
+
end
|
|
53
|
+
destination
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def platform_help
|
|
57
|
+
if platform.macos?
|
|
58
|
+
"building Zui on macOS requires CMake and Qt 6 (for example: brew install cmake qt)"
|
|
59
|
+
elsif platform.windows?
|
|
60
|
+
"building Zui on Windows requires CMake, Qt 6, and a C++17 toolchain (Visual Studio Build Tools or LLVM/MinGW)"
|
|
61
|
+
else
|
|
62
|
+
"building Zui on Linux requires CMake, a C++17 compiler, and Qt 6 Core/Gui/Qml/Quick development packages"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def bundled
|
|
69
|
+
File.join(@framework_root, "vendor", "host", platform.id, executable_name)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def cached
|
|
73
|
+
cache_root = @environment["XDG_CACHE_HOME"]
|
|
74
|
+
cache_root = default_cache_root if cache_root.nil? || cache_root.empty?
|
|
75
|
+
File.join(cache_root, "zui", "host", VERSION, platform.id, executable_name)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def default_cache_root
|
|
79
|
+
home = @environment["HOME"] || @environment["USERPROFILE"] || Dir.home
|
|
80
|
+
if platform.windows?
|
|
81
|
+
@environment["LOCALAPPDATA"] || @environment["APPDATA"] || File.join(home, "AppData", "Local")
|
|
82
|
+
elsif platform.macos?
|
|
83
|
+
File.join(home, "Library", "Caches")
|
|
84
|
+
else
|
|
85
|
+
File.join(home, ".cache")
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def executable_name = platform.os == :windows ? "zui-host.exe" : "zui-host"
|
|
90
|
+
|
|
91
|
+
def checked_executable(path)
|
|
92
|
+
expanded = File.expand_path(path)
|
|
93
|
+
raise ArgumentError, "ZUI_HOST is not executable: #{expanded}" unless File.executable?(expanded)
|
|
94
|
+
expanded
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def find_command(name)
|
|
98
|
+
@environment.fetch("PATH", "").split(File::PATH_SEPARATOR).each do |directory|
|
|
99
|
+
command_names(name).each do |command_name|
|
|
100
|
+
path = File.join(directory, command_name)
|
|
101
|
+
return path if File.executable?(path) && !File.directory?(path)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
nil
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def command_names(name)
|
|
108
|
+
return [name] unless platform.windows? && File.extname(name).empty?
|
|
109
|
+
|
|
110
|
+
extensions = @environment.fetch("PATHEXT", ".COM;.EXE;.BAT;.CMD").split(";")
|
|
111
|
+
[name] + extensions.flat_map { |extension| ["#{name}#{extension.downcase}", "#{name}#{extension.upcase}"] }.uniq
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def locate_build(build_dir)
|
|
115
|
+
candidates = [
|
|
116
|
+
File.join(build_dir, executable_name),
|
|
117
|
+
File.join(build_dir, "Release", executable_name),
|
|
118
|
+
File.join(build_dir, "zui-host.app", "Contents", "MacOS", "zui-host")
|
|
119
|
+
]
|
|
120
|
+
candidates.find { |path| File.executable?(path) }
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
data/lib/zui/node.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Zui
|
|
4
|
+
class Node
|
|
5
|
+
attr_reader :type, :id, :props, :children, :events
|
|
6
|
+
|
|
7
|
+
def initialize(type:, id:, props: {})
|
|
8
|
+
@type = type.to_s
|
|
9
|
+
@id = id.to_s
|
|
10
|
+
@props = props.transform_keys(&:to_s)
|
|
11
|
+
@children = []
|
|
12
|
+
@events = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_h
|
|
16
|
+
result = { "type" => type, "id" => id }
|
|
17
|
+
result["props"] = props unless props.empty?
|
|
18
|
+
result["children"] = children.map(&:to_h) unless children.empty?
|
|
19
|
+
result["events"] = events unless events.empty?
|
|
20
|
+
result
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def subscribe(event)
|
|
24
|
+
@events << event.to_s unless @events.include?(event.to_s)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Binding = Struct.new(:node, :property, :reader, :last_value, :animation, keyword_init: true)
|
|
29
|
+
StructuralBinding = Struct.new(:node, :renderer, :last_children, keyword_init: true)
|
|
30
|
+
end
|
data/lib/zui/platform.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rbconfig"
|
|
4
|
+
|
|
5
|
+
module Zui
|
|
6
|
+
Platform = Struct.new(:os, :arch, keyword_init: true) do
|
|
7
|
+
SUPPORTED_OSES = %i[linux macos windows].freeze
|
|
8
|
+
|
|
9
|
+
def self.current
|
|
10
|
+
detect(RbConfig::CONFIG.fetch("host_os"), RbConfig::CONFIG.fetch("host_cpu"))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.detect(host_os, host_cpu)
|
|
14
|
+
os = case host_os.to_s
|
|
15
|
+
when /darwin|mac\s?os/i then :macos
|
|
16
|
+
when /linux/i then :linux
|
|
17
|
+
when /mswin|mingw|cygwin|windows/i then :windows
|
|
18
|
+
else :unsupported
|
|
19
|
+
end
|
|
20
|
+
arch = case host_cpu.to_s
|
|
21
|
+
when /aarch64|arm64/i then :arm64
|
|
22
|
+
when /x86_64|amd64|x64/i then :x86_64
|
|
23
|
+
else host_cpu.to_s.downcase.gsub(/[^a-z0-9_]+/, "_").to_sym
|
|
24
|
+
end
|
|
25
|
+
new(os:, arch:)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def supported? = SUPPORTED_OSES.include?(os)
|
|
29
|
+
def id = "#{os}-#{arch}"
|
|
30
|
+
def linux? = os == :linux
|
|
31
|
+
def macos? = os == :macos
|
|
32
|
+
def windows? = os == :windows
|
|
33
|
+
|
|
34
|
+
def assert_supported!
|
|
35
|
+
return self if supported?
|
|
36
|
+
|
|
37
|
+
raise ArgumentError, "Zui desktop applications support Linux, macOS, and Windows; detected #{os}/#{arch}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/zui/protocol.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Zui
|
|
4
|
+
PROTOCOL_VERSION = 1
|
|
5
|
+
MAX_MESSAGE_BYTES = 1_048_576
|
|
6
|
+
class AsciiPattern
|
|
7
|
+
def initialize(min:, max:, first: nil, rest:)
|
|
8
|
+
@min = min
|
|
9
|
+
@max = max
|
|
10
|
+
@first = first
|
|
11
|
+
@rest = rest
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def match?(value)
|
|
15
|
+
text = value.to_s
|
|
16
|
+
return false if text.length < @min || text.length > @max
|
|
17
|
+
return false if @first && !@first.include?(text[0])
|
|
18
|
+
text.each_char.all? { |character| @rest.include?(character) }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
LOWER = ("a".."z").to_a.join.freeze
|
|
23
|
+
UPPER = ("A".."Z").to_a.join.freeze
|
|
24
|
+
DIGITS = ("0".."9").to_a.join.freeze
|
|
25
|
+
VALID_ID = AsciiPattern.new(min: 1, max: 128, rest: LOWER + UPPER + DIGITS + "_.:-")
|
|
26
|
+
VALID_EVENT = AsciiPattern.new(min: 1, max: 64, first: LOWER, rest: LOWER + DIGITS + "_")
|
|
27
|
+
|
|
28
|
+
class ProtocolError < StandardError; end
|
|
29
|
+
end
|
data/lib/zui/runner.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rbconfig"
|
|
4
|
+
|
|
5
|
+
module Zui
|
|
6
|
+
class Runner
|
|
7
|
+
def initialize(host: Host.new, framework_root: FRAMEWORK_ROOT, ruby: RbConfig.ruby)
|
|
8
|
+
@host = host
|
|
9
|
+
@framework_root = framework_root
|
|
10
|
+
@ruby = ruby
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run(file, name: nil, environment: ENV.to_h)
|
|
14
|
+
program = File.expand_path(file)
|
|
15
|
+
raise ArgumentError, "Ruby file not found: #{program}" unless File.file?(program)
|
|
16
|
+
executable = @host.executable
|
|
17
|
+
project = File.dirname(program)
|
|
18
|
+
arguments = [
|
|
19
|
+
executable,
|
|
20
|
+
"--qml-root", @framework_root,
|
|
21
|
+
"--project", project,
|
|
22
|
+
"--program", program,
|
|
23
|
+
"--ruby", @ruby,
|
|
24
|
+
"--load-path", File.join(@framework_root, "lib"),
|
|
25
|
+
"--name", name || project_name(project)
|
|
26
|
+
]
|
|
27
|
+
system(environment, *arguments)
|
|
28
|
+
$?&.exitstatus || 1
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def project_name(path)
|
|
34
|
+
File.basename(path).split(/[-_]/).map(&:capitalize).join(" ")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/zui/runtime.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Zui
|
|
6
|
+
module Runtime
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
QML_FILES = %w[Desktop.qml Service.qml ControlNode.qml].freeze
|
|
10
|
+
QML_DIRECTORIES = %w[Components Controls Theme].freeze
|
|
11
|
+
|
|
12
|
+
def install_qml(destination, framework_root: FRAMEWORK_ROOT)
|
|
13
|
+
FileUtils.mkdir_p(destination)
|
|
14
|
+
QML_FILES.each do |name|
|
|
15
|
+
FileUtils.cp(File.join(framework_root, name), File.join(destination, name))
|
|
16
|
+
end
|
|
17
|
+
QML_DIRECTORIES.each do |name|
|
|
18
|
+
FileUtils.cp_r(File.join(framework_root, name), File.join(destination, name))
|
|
19
|
+
end
|
|
20
|
+
destination
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|