summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpml68 <contact@pml68.dev>2025-06-20 03:01:07 +0200
committerpml68 <contact@pml68.dev>2025-06-20 03:01:07 +0200
commitefb9d3f7bcb013b39e31304293e58b7fb4144d30 (patch)
tree6478322170861e49895dcd3d0e1471ac9761cf67
parentfeat(PKGBUILD): add `check` for tests [skip ci] (diff)
downloadiced-builder-efb9d3f7bcb013b39e31304293e58b7fb4144d30.tar.gz
feat: project file to open can be passed as an argument + desktop entry
Diffstat (limited to '')
-rw-r--r--PKGBUILD4
-rw-r--r--assets/linux/dev.pml68.iced-builder.desktop11
-rw-r--r--src/main.rs73
-rw-r--r--src/types/project.rs9
4 files changed, 74 insertions, 23 deletions
diff --git a/PKGBUILD b/PKGBUILD
index d98445f..6832782 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,7 +1,7 @@
# Maintainer: pml68 <contact@pml68.dev>
pkgname=iced-builder
-pkgver=0.1.0.r174.g7398f64
+pkgver=0.1.0.r175.g0ade991
pkgrel=1
pkgdesc='UI builder for iced, built with iced.'
arch=(x86_64)
@@ -58,5 +58,7 @@ package() {
cd "${pkgname}"
install -Dm755 "target/release/${pkgname}" "${pkgdir}/usr/bin/${pkgname}"
+
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
+ install -Dm644 "assets/linux/dev.pml68.${pkgname}.desktop" -t "${pkgdir}/usr/share/applications"
}
diff --git a/assets/linux/dev.pml68.iced-builder.desktop b/assets/linux/dev.pml68.iced-builder.desktop
new file mode 100644
index 0000000..32392a2
--- /dev/null
+++ b/assets/linux/dev.pml68.iced-builder.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Version=0.1
+Type=Application
+Name=iced Builder
+Comment=UI builder for iced, built with iced.
+TryExec=iced-builder
+Exec=iced-builder %f
+Terminal=false
+MimeType=application/json;
+Categories=GTK;GUIDesigner;Development;
+Keywords=iced;GUI;builder;designer;
diff --git a/src/main.rs b/src/main.rs
index 49b2d60..59fcc25 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -12,6 +12,7 @@ mod types;
mod values;
mod widget;
+use std::io;
use std::path::PathBuf;
use config::Config;
@@ -30,27 +31,44 @@ use types::{
Action, ConfigChangeType, DesignerPane, Element, Message, Panes, Project,
};
-fn main() -> iced::Result {
- let version = std::env::args()
- .nth(1)
- .is_some_and(|s| s == "--version" || s == "-V");
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let mut project_path = None;
- if version {
- println!("iced-builder {}", environment::formatted_version());
- println!("{}", env!("CARGO_PKG_REPOSITORY"));
+ if let Some(arg) = std::env::args().nth(1) {
+ if arg == "-V" || arg == "--version" {
+ println!("iced-builder {}", environment::formatted_version());
+ println!("{}", env!("CARGO_PKG_REPOSITORY"));
- return Ok(());
+ return Ok(());
+ } else {
+ let path = PathBuf::from(&arg);
+
+ if path.try_exists()? && !path.is_file() {
+ return Err(Box::new(io::Error::new(
+ io::ErrorKind::IsADirectory,
+ "Expected a file, directory given.",
+ )));
+ } else {
+ project_path = Some(path);
+ }
+ }
}
- iced::application(IcedBuilder::boot, IcedBuilder::update, IcedBuilder::view)
- .title(IcedBuilder::title)
- .theme(IcedBuilder::theme)
- .subscription(IcedBuilder::subscription)
- .exit_on_close_request(false)
- .font(icon::FONT)
- .antialiasing(true)
- .centered()
- .run()
+ iced::application(
+ move || IcedBuilder::boot(project_path.clone()),
+ IcedBuilder::update,
+ IcedBuilder::view,
+ )
+ .title(IcedBuilder::title)
+ .theme(IcedBuilder::theme)
+ .subscription(IcedBuilder::subscription)
+ .exit_on_close_request(false)
+ .font(icon::FONT)
+ .antialiasing(true)
+ .centered()
+ .run()?;
+
+ Ok(())
}
struct IcedBuilder {
@@ -68,7 +86,7 @@ struct IcedBuilder {
}
impl IcedBuilder {
- fn boot() -> (Self, Task<Message>) {
+ fn boot(project_path: Option<PathBuf>) -> (Self, Task<Message>) {
let state = pane_grid::State::with_configuration(
pane_grid::Configuration::Split {
axis: pane_grid::Axis::Vertical,
@@ -81,11 +99,22 @@ impl IcedBuilder {
let config = Config::default();
let theme = config.selected_theme();
+ let mut tasks =
+ vec![Task::perform(Config::load(), Message::ConfigLoad)];
+ if let Some(path) = project_path.as_deref() {
+ if path.exists() && path.is_file() {
+ tasks.push(Task::perform(
+ Project::from_path(path.to_path_buf()),
+ Message::FileOpened,
+ ));
+ }
+ }
+
(
Self {
is_dirty: false,
is_loading: false,
- project_path: None,
+ project_path,
project: Project::new(),
config,
theme: Animated::new(theme, Easing::EASE_IN),
@@ -95,7 +124,7 @@ impl IcedBuilder {
dialog: Dialog::default(),
editor_content: text_editor::Content::new(),
},
- Task::perform(Config::load(), Message::ConfigLoad),
+ Task::batch(tasks),
)
}
@@ -130,7 +159,9 @@ impl IcedBuilder {
self.config = config;
self.theme.settle_at(self.config.selected_theme());
- if let Some(path) = self.config.last_project() {
+ if let Some(path) = self.config.last_project()
+ && self.project_path.is_none()
+ {
if path.exists() && path.is_file() {
return Task::perform(
Project::from_path(path.to_owned()),
diff --git a/src/types/project.rs b/src/types/project.rs
index 11789ac..7262ccf 100644
--- a/src/types/project.rs
+++ b/src/types/project.rs
@@ -62,7 +62,14 @@ impl Project {
self,
path: Option<PathBuf>,
) -> Result<PathBuf, Error> {
+ use tokio::fs;
+
let path = if let Some(p) = path {
+ let parent = p.parent();
+ if parent.is_some_and(|parent| !parent.exists()) {
+ fs::create_dir_all(parent.unwrap()).await?;
+ }
+
p
} else {
rfd::AsyncFileDialog::new()
@@ -77,7 +84,7 @@ impl Project {
};
let contents = serde_json::to_string(&self)?;
- tokio::fs::write(&path, contents).await?;
+ fs::write(&path, contents).await?;
Ok(path)
}