moving around complete

This commit is contained in:
Sebastian Moser
2026-02-15 14:14:18 +01:00
parent 691e695659
commit 0b7e54dc1d
103 changed files with 12 additions and 26 deletions

8841
crates/mme/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

76
crates/mme/Cargo.toml Normal file
View File

@@ -0,0 +1,76 @@
[package]
name = "mme"
version = "0.1.0"
edition = "2021"
[package.metadata.wasm-pack.profile.dev]
wasm-opt = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = [ "os-target" ]
qt = [ "slint", "cpp", "qt_core", "qt_gui", "qt_widgets", "comandr/qt" ]
slint = [ "i-slint-backend-qt", "dep:slint", "slint-interpreter", "spin_on", "qt" ]
os-target = [ "tao", "wry", "tracing-subscriber", "clap", "webkit2gtk", "mize/os-target", "glib" ]
#os-target = [ "tao", "wry", "tracing-subscriber", "clap" ]
wasm-target = [ "wasm-bindgen", "console_error_panic_hook", "wasm-bindgen-cli", "web-sys", "comandr/wasm-target", "mize/wasm-target" ]
console_error_panic_hook = ["dep:console_error_panic_hook"]
[target.'cfg(unix)'.dependencies]
webkit2gtk = { version = "2.0.1", optional = true }
[dependencies]
# core deps
colored = "2.1.0"
enum_dispatch = "0.3.13"
comandr = { git = "https://github.com/c2vi/comandr", default-features = false }
#comandr = { path = "../../../dr-comandr" }
mize = { git = "https://github.com/c2vi/mize", default-features = false }
tracing = "0.1.40"
base64 = "0.22.1"
# wasm dependencies
wasm-bindgen = { version = "0.2.84", optional = true }
console_error_panic_hook = { version = "0.1.7", optional = true }
wasm-bindgen-cli = { version = "0.2.92", optional = true }
web-sys = { version = "0.3.70", optional = true, features = ['console'] }
# os deps
tao = { version = "0.28.1", optional = true }
wry = { version = "0.41.0", optional = true, features = [ "devtools" ] }
tracing-subscriber = { version = "0.3.18", features = ["env-filter"], optional = true }
clap = { version = "4.5.8", features = ["cargo"], optional = true }
glib = { version = "0.15.12", optional = true }
# qt deps
#qt_gui = "0.5.0"
cpp = { version = "0.5.9", optional = true }
qt_gui = { version = "0.5.0", optional = true }
qt_core = { version = "0.5.0", optional = true }
qt_widgets = { version = "0.5.0", optional = true }
#slint deps
i-slint-backend-qt = { version = "1.7.1", optional = true }
slint = { version = "1.7.1", optional = true }
slint-interpreter = { version = "1.7.1", optional = true }
spin_on = { version = "0.1.1", optional = true }
custom-print = "1.0.0"
flume = "0.11.1"
ciborium = "0.2.2"
ciborium-io = { version = "0.2.2", features = ["std", "alloc"] }
wasm-bindgen-futures = "0.4.49"
[build-dependencies]
cc = "1.1.5"
cpp_build = "0.5"
[lib]
name = "mize_module_mme"
crate-type =["cdylib", "rlib"]
[target.wasm32-unknown-unknown]
rustflags = [
"-C", "link-args=--import-memory",
]

8
crates/mme/build-web.sh Executable file
View File

@@ -0,0 +1,8 @@
set -e
wasm-pack build --features wasm-target --no-default-features
cd /home/me/work/mme-presenters/presenters/mme-js/
npm run build -- --mode development

29
crates/mme/build.rs Normal file
View File

@@ -0,0 +1,29 @@
fn main() {
#[cfg(feature = "qt")]
{
let qt_lib_path = env!("MME_QT_LIB");
cc::Build::new()
.cpp(true)
.file("src/main.cpp")
.flag("-w")
.compile("mme");
println!("cargo:rustc-link-search={}", qt_lib_path);
println!("cargo:rustc-link-lib=Qt5Quick");
println!("cargo:rustc-link-lib=Qt5PrintSupport ");
println!("cargo:rustc-link-lib=Qt5Qml ");
println!("cargo:rustc-link-lib=Qt5Network ");
println!("cargo:rustc-link-lib=Qt5Widgets ");
println!("cargo:rustc-link-lib=Qt5Gui ");
println!("cargo:rustc-link-lib=Qt5Core");
println!("cargo:rustc-link-lib=Qt5WebEngine");
println!("cargo:rustc-link-lib=Qt5WebEngineCore");
println!("cargo:rustc-link-lib=Qt5WebEngineWidgets");
println!("cargo:rerun-if-changed=src/main.cpp");
cpp_build::build("src/implementors/qt_widget/mod.rs");
}
}

19
crates/mme/dev Normal file
View File

@@ -0,0 +1,19 @@
export MIZE_MODULE_PATH=/home/me/work/mme:/home/me/work/modules:/home/me/work/mesenters
export MIZE_MODULE_NO_REPO=1
export MIZE_MODULE_NO_EXTERNALS=1
export MIZE_CONFIG=$MIZE_CONFIG:module_dir.mme=/home/me/work/mme/dist:module_dir.String=/home/me/work/modules/modules/String/dist
function dev() {
#nix develop /home/me/work/mize#modules.mme --override-input nixpkgs github:nixos/nixpkgs/ea6033ce4ddf2c0ede2ea147a450d4f880796128 --impure
nix develop /home/me/work/mize#modules.mme --override-input nixpkgs github:nixos/nixpkgs/10e687235226880ed5e9f33f1ffa71fe60f2638a --impure
#nix develop /home/me/work/mize#modules.mme --impure
}
if [[ "$1" != "no" ]]
then
dev
fi

171
crates/mme/mize.nix Normal file
View File

@@ -0,0 +1,171 @@
{
module = { buildMizeForSystem, mizeBuildConfig, mkMizeRustModule, hostSystem, pkgsCross, mkMizeRustShell, pkgs, pkgsNative, buildNpmPackage, mkSelString, mizeBuildConfigStr, fenix, ... }: let
selector_string = mkSelString {
modName = "mme";
};
hash = builtins.substring 0 32 (builtins.hashString "sha256" selector_string);
url = "file:///home/me/work/mme/dist/mize.js";
html = ''
<html>
<head>
<!-- script src="https://c2vi.dev/mize/wasm32-none-unknown/mize.js"></script --!>
<!-- script src="${url}"></script --!>
<script>
console.log("from script")
</script>
</head>
<body>
hello world...............
</body>
</html>
'';
in mkMizeRustModule ({
modName = "mme";
src = ./.;
cargoExtraArgs = "--no-default-features --lib";
## add the index.html
postInstall = ''
echo -n '${html}' > $out/index.html
'';
}
// (if hostSystem.name == "wasm32-none-unknown" then {
mizeBuildPhase = ''
cd $build_dir
RUSTFLAGS="-C link-args=--import-memory" RUST_LOG=off wasm-pack build --target no-modules --dev --out-dir $out -- --features wasm-target --no-default-features
echo -n 'export function get_wasm_bindgen() { return wasm_bindgen }' >> $out/mize_module_mme.js
echo -n '${html}' > $out/index.html
'';
mizeInstallPhase = "";
} else {})
// (if hostSystem.kernel.name == "linux" then builtins.trace "adding linux stuff" {
nativeBuildInputs = with pkgsCross.buildPackages; [
pkg-config
];
buildInputs = with pkgsNative; [
webkitgtk_4_1
];
} else {})
# add the devShell
// {
devShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
#emscripten
wasm-pack
pkg-config
webkitgtk_4_1
libsForQt5.full
cmake
nasm
pkg-config
nodejs
(fenix.packages.${system}.combine [
fenix.packages.${system}.targets.wasm32-unknown-unknown.latest.toolchain
fenix.packages.${system}.latest.toolchain
fenix.packages.${system}.latest.rust-src
])
];
MIZE_BUILD_CONFIG = mizeBuildConfigStr;
buildInputs = with pkgs; [
openssl
#pango
#libsoup_3
webkitgtk_4_1
# gobject-introspection gtk4 atkmm
];
shellHook = ''
echo hiiiiiiiiiiiiii
export LD_LIBRARY_PATH=${pkgs.webkitgtk_4_1}/lib:${pkgs.libsoup_3}/lib:${pkgs.glib.out}/lib:${pkgs.gtk3}/lib:${pkgs.cairo}/lib:${pkgs.gdk-pixbuf}/lib:${pkgs.libxkbcommon}/lib:${pkgs.fontconfig.lib}/lib:${pkgs.libsForQt5.full}/lib:${pkgs.stdenv.cc.cc.lib}/lib:${pkgs.libsForQt5.qt5.qtwebengine}/lib
export CPLUS_INCLUDE_PATH=${pkgs.libsForQt5.full}/include:${pkgs.libsForQt5.qt5.qtwebengine}/include
export MME_QT_LIB=${pkgs.libsForQt5.full}/lib
# i found that this is the env war to set where QT looks for platform plugins
# at: https://forums.fedoraforum.org/showthread.php?326508-How-to-set-QT_QPA_PLATFORM_PLUGIN_PATH
export QT_QPA_PLATFORM_PLUGIN_PATH=${pkgs.libsForQt5.full}/lib/qt-5.15.14/plugins/platforms/
alias run="${./.}/run.sh"
'';
};
}
);
lib = { mkMizeModule, buildNpmPackage, pkgsCross, pkgsNative, ... }: rec {
mkMmePresenter = attrs: mkMizeModule (attrs // {
src = attrs.src;
modName = attrs.name;
select = {
mme_presenter = true;
};
});
mkMmeNpmPresenter = attrs: mkMizeModule (attrs // {
drvFunc = buildNpmPackage;
mizeBuildPhase = ''
cd $build_dir
npm i
npm run build
mv dist tmp
mkdir -p $out
mv tmp/* $out
rm -rf tmp
'';
mizeInstallPhase = "";
select = {
mme_presenter = true;
};
devShell = pkgsNative.mkShell {
buildInputs = with pkgsNative; [ nodejs_20 ];
};
});
mkMmeHtmlPresenter = attrs: mkMmePresenter ({
dontUnpack = true;
dontPath = true;
buildPhase = "";
installPhase = ''
mkdir -p $out
cp -r ${attrs.src}/* $out
'';
} // attrs);
};
externals = { fetchFromGitHub, ... }: [
(fetchFromGitHub {
owner = "c2vi";
repo = "mme-presenters";
rev = "master";
hash = "sha256-FeMBDCJBkw9XOLXC1rfedNk71uyg4OTCHaaO1jAAGto=";
})
];
}

58
crates/mme/run.sh Executable file
View File

@@ -0,0 +1,58 @@
set -e
# override, where mize loads the mme module from
export MIZE_MODULE_PATH=/home/me/work/mme:/home/me/work/modules:/home/me/work/presenters
export MIZE_MODULE_NO_REPO=1
export MIZE_MODULE_NO_EXTERNALS=1
export MIZE_CONFIG=$MIZE_CONFIG:module_dir.mme=/home/me/work/mme/dist:module_dir.String=/home/me/work/modules/modules/String/dist:module_dir.mme_presenter.mme_js=/home/me/work/presenters/presenters/mme_js/dist
#export MIZE_CONFIG=$MIZE_CONFIG:module_dir.mme=/home/me/work/mize/result
# build mme for the browser
echo '############################# MME for Browser #############################'
RUST_LOG=off wasm-pack build --target no-modules --dev --out-dir ./dist -- --features wasm-target --no-default-features
# build mize for the browser
echo '############################# mize for Browser #############################'
cd /home/me/work/mize
RUST_LOG=off wasm-pack build --target no-modules --dev -- --features wasm-target --no-default-features
cat /home/me/work/mize/src/platform/wasm/init.js >> /home/me/work/mize/pkg/mize.js
#--out-dir ~/work/mize/src/platform/wasm/npm_pkg/generated
#export CARGO_BUILD_RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals'
#wasm-pack build --target no-modules --dev . -Z build-std=panic_abort,std --features wasm-target --no-default-features --config 'build.rustflags = "-C target-feature=+atomics,+bulk-memory,+mutable-globals"'
#cp -r ~/work/mize/pkg/* ~/work/mize/src/platform/wasm/npm_pkg/generated
#RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals' cargo build --target wasm32-unknown-unknown -Z build-std=panic_abort,std --lib --no-default-features
#cp ~/work/mize/target/wasm32-unknown-unknown/debug/mize.wasm ~/work/mize/src/platform/wasm/npm_pkg/generated/mize_bg.wasm
# build the mme-js presenter
echo '############################# mme-js presenter #############################'
cd /home/me/work/presenters/presenters/mme_js/
npm run build -- --mode development
# build the mme module
echo '############################# mme module for os #############################'
cd /home/me/work/mme
cargo build --lib
mkdir -p /home/me/work/mme/dist/lib
cp /home/me/work/mme/target/debug/libmize_module_mme.so /home/me/work/mme/dist/lib
nix eval --expr 'import /home/me/work/mme/src/implementors/html/index.nix { mize_url = "file:///home/me/work/mize/pkg/mize.js"; }' --impure --raw > /home/me/work/mme/dist/index.html
# build the String module
echo '############################# string module for os #############################'
cargo build --manifest-path ~/work/modules/modules/String/Cargo.toml --lib
mkdir -p /home/me/work/modules/modules/String/dist/lib
cp /home/me/work/modules/modules/String/target/debug/libmize_module_String.so /home/me/work/modules/modules/String/dist/lib
# run mize with gui
echo '############################# run mize for os #############################'
cargo run --manifest-path ~/work/mize/Cargo.toml -- gui

View File

@@ -0,0 +1,14 @@
use crate::slot::Slot;
use mize::MizeResult;
// A Presenter, that takes not data and produces only one output Space
// with that space being of a different type.
// In order to put Presenters of different types into one another.
// eg a QT-Webview is put into a qt-space ... in order to get a web-space....
pub struct Adapter {
}
pub trait AdapterTrait {
fn sub_slot() -> MizeResult<Slot>;
}

View File

@@ -0,0 +1,5 @@
// A Presenter, that takes no data. Just provides sub spaces.
pub struct Layout {
}

557
crates/mme/src/core/mme.rs Normal file
View File

@@ -0,0 +1,557 @@
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use std::sync::Arc;
use crate::{implementors::{html::HtmlPresenter}, presenter};
use crate::slot::{Slot, SlotTrait};
use crate::presenter::Presenter;
use tracing::info;
use comandr::Comandr;
use flume::{ Receiver, Sender };
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use core::ptr::NonNull;
#[cfg(feature = "wasm-target")]
use wasm_bindgen::JsValue;
#[cfg(feature = "wasm-target")]
use web_sys::js_sys::Function;
//#[cfg(feature = "os-target")]
//use crate::implementors::qt_widget::QtWidgetSlot;
#[cfg(feature = "qt")]
use qt_core::{qs, QString, QTimer, SlotNoArgs};
#[cfg(feature = "qt")]
use qt_widgets::{QApplication, QGridLayout, QWidget};
#[cfg(feature = "qt")]
use qt_gui::{cpp_core::CppBox};
use mize::Module;
use mize::MizeResult;
use mize::error::MizeResultTrait;
use mize::Instance;
use mize::mize_err;
use mize::MizeError;
use mize::proto::MizeMessage;
#[derive(Clone)]
pub struct Mme {
pub comandr: Arc<Mutex<Comandr>>,
pub mize: Instance,
}
// console_log macro
// that can be copied into other files for debugging purposes
#[cfg(feature = "wasm-target")]
use wasm_bindgen::prelude::*;
#[cfg(feature = "wasm-target")]
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[cfg(feature = "wasm-target")]
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (unsafe { log(&format_args!($($t)*).to_string())})
}
#[no_mangle]
extern "C" fn get_mize_module_mme(empty_module: &mut Box<dyn Module + Send + Sync>, mize: Instance) -> () {
#[cfg(feature = "wasm-target")]
console_log!("hiiiiiiiiiiiiiiii from inside get_mize_module_mme!!!!!!!!!");
let comandr = Comandr::new();
let new_box: Box<dyn Module + Send + Sync> = Box::new( Mme { comandr: Arc::new(Mutex::new(comandr)), mize, } );
*empty_module = new_box
}
#[cfg(feature = "wasm-target")]
use mize::platform::wasm::JsInstance;
#[cfg(feature = "wasm-target")]
use wasm_bindgen::prelude::*;
#[cfg(feature = "wasm-target")]
#[wasm_bindgen]
pub unsafe fn wasm_get_mize_module_mme(mut empty_module_ptr: usize, mut mize_ptr: usize) -> () {
console_log!("hiiiiiiiiiiiiiiiiiiiiiii form wasm_get_mize_module_mme");
let empty_module = empty_module_ptr as * mut Box<dyn Module + Send + Sync>;
console_log!("here");
let mize = (*(mize_ptr as * mut Instance)).clone();
console_log!("here2");
//(*empty_module).init(&mize);
console_log!("here3");
let comandr = Comandr::new();
let mut new_box: Box<dyn Module + Send + Sync> = Box::new( Mme { comandr: Arc::new(Mutex::new(comandr)), mize: mize.clone(), } );
console_log!("before new_box.init()");
new_box.init(&mize);
console_log!("before assignment");
*empty_module = new_box
}
/*
pub fn wasm_get_mize_module_mme(empty_module_ptr: usize, mize: JsInstance) -> usize {
let mut empty_module: Box<dyn Module + Send + Sync> = *(empty_module_ptr as Box<Box<dyn Module + Send + Sync>>);
let mize = mize.inner().clone();
let comandr = Comandr::new();
let new_box: Box<dyn Module + Send + Sync> = Box::new( Mme { comandr: Arc::new(Mutex::new(comandr)), mize, } );
*empty_module = new_box
}
*/
impl Module for Mme {
fn init(&mut self, _instance: &Instance) -> MizeResult<()> {
#[cfg(feature = "wasm-target")]
{
// console log
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
}
console_log!("mme module inittttttttttttttttttttttt");
}
println!("MmeModule init");
#[cfg(feature = "os-target")]
{
//self.mize.spawn("mme-main", || self.create_x_window());
let mut cloned_self = self.clone();
// "significant cross-platform compatibility hazard." xD
//self.mize.spawn("mme-main", move || cloned_self.create_x_window());
self.create_x_window();
}
#[cfg(feature = "wasm-target")]
{
use web_sys::js_sys::eval;
use crate::implementors::html::wasm::MmeJs;
use std::ptr::NonNull;
// create mme module object
let mut mme_js = MmeJs {
inner: NonNull::from(Box::leak(Box::new(self.clone()))),
webview_con_id: 0,
};
let func = Function::new_with_args("mme_js", r#"
window.mize.mod.mme = mme_js;
"#);
func.call1(&JsValue::null(), &JsValue::from(mme_js)).map_err(|e| mize_err!("from js error: {:?}", e));
//
}
Ok(())
}
fn exit(&mut self, _instance: &Instance) -> MizeResult<()> {
info!("mme module exit");
Ok(())
}
fn clone_module(&self) -> Box<dyn Module + Send + Sync> {
Box::new(self.clone())
}
}
#[cfg(feature = "qt")]
unsafe fn qstring_to_rust(q_string: CppBox<QString>) -> String {
let mut rust_string = String::new();
let q_string_size = q_string.size();
for j in 0..q_string_size {
let q_char = q_string.index_int(j);
let rust_char = char::from_u32(q_char.unicode() as u32);
rust_string.push(rust_char.unwrap());
}
return rust_string;
}
impl Mme {
pub fn new(mize: Instance) -> MizeResult<Mme> {
let comandr = Comandr::new();
Ok(Mme { comandr: Arc::new(Mutex::new(comandr)), mize, })
}
#[cfg(feature = "wasm-target")]
pub fn create_html_slot() -> MizeResult<()> {
println!("hi wasm");
Ok(())
}
#[cfg(feature = "os-target")]
pub fn create_x_window(&mut self) -> MizeResult<()> {
use std::fs;
use tao::{
event::{Event, WindowEvent},
event_loop::{self, ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy},
window::WindowBuilder,
};
use wry::{http::{Method, Request, Response}, WebViewBuilder};
#[cfg(target_os = "linux")]
use wry::WebViewExtUnix;
#[cfg(target_os = "linux")]
use webkit2gtk::{Settings, WebInspectorExt};
#[cfg(target_os = "linux")]
use webkit2gtk::WebViewExt;
use crate::implementors::html::webview_con::{msg_from_string, msg_to_string};
let event_loop = EventLoopBuilder::with_user_event().build();
let event_loop_proxy: EventLoopProxy<MizeMessage> = event_loop.create_proxy();
let window = WindowBuilder::new().build(&event_loop).unwrap();
#[cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
))]
let builder = WebViewBuilder::new(&window);
#[cfg(not(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
)))]
let builder = {
use tao::platform::unix::WindowExtUnix;
use wry::WebViewBuilderExtUnix;
let vbox = window.default_vbox().unwrap();
WebViewBuilder::new_gtk(vbox)
};
//let html_str = fs::read_to_string(format!("{}/../implementors/html/js-runtime/dist/index.html", file!()))?;
//println!("html_str: {}", html_str);
// get the path of the index.html
let test = self.mize.fetch_module("mme")?;
let mme_module_path = self.mize.fetch_module("cross.wasm32-none-unknown.mme")?;
let mize_module_path = self.mize.fetch_module("cross.wasm32-none-unknown.mize")?;
let init_script = format!(r#"
import("{mize_module_path}/mize.js").then( module => module.init_mize({{module_dir: {{mize: "{mize_module_path}"}}}}))
"#);
// add the mize connection to the instance inside the webview
let (tx, rx): (Sender<MizeMessage>, Receiver<MizeMessage>) = flume::unbounded();
let conn_id = self.mize.new_connection(tx)?;
let mut self_clone = self.clone();
let mut self_clone_two = self.clone();
let webview = builder
//.with_url("http://localhost:8000/index.html")
//.with_url("file:/
//home/me/tmp/rd/test.html")
//.with_url(format!("file://{}/index.html", mme_module_path))
//.with_html("hello worldddddddddddddddddddddddddddddddddd".to_owned())
//.with_initialization_script(init_script.as_str())
.with_custom_protocol(
"wry".into(),
move | request| {
// the body will be a mize message as a string
if request.method() == &Method::POST {
let msg_str = request.headers().get("MizeMsg").unwrap().to_str().unwrap();
println!("webview_con incoming got msg: {}", msg_str);
let msg = match msg_from_string(msg_str.to_owned(), conn_id) {
Ok(val) => val,
Err(err) => {
self_clone_two.mize.report_err(err.into());
return http::Response::builder()
.header(CONTENT_TYPE, "text/plain")
.status(500)
.body("".to_string().as_bytes().to_vec())
.unwrap()
.map(Into::into);
},
};
self_clone_two.mize.got_msg(msg);
return http::Response::builder()
.header(CONTENT_TYPE, "text/plain")
.status(http::StatusCode::OK)
.body("".to_string().as_bytes().to_vec())
.unwrap()
.map(Into::into);
}
match get_wry_response(request, self_clone_two.clone()) {
Ok(r) => r.map(Into::into),
Err(e) => {
println!("get_wry_response error: {}", e);
http::Response::builder()
.header(CONTENT_TYPE, "text/plain")
.status(500)
.body(e.to_string().as_bytes().to_vec())
.unwrap()
.map(Into::into)
},
}
}
)
// tell the webview to load the custom protocol
.with_url("wry://localhost")
//.with_ipc_handler(move | res: Request<String> | {
//crate::implementors::html::webview_con::ipc_handler(res, self_clone.clone(), conn_id)
//})
//.with_html(html_str)
/*
.with_drag_drop_handler(|e| {
match e {
wry::DragDropEvent::Enter { paths, position } => {
println!("DragEnter: {position:?} {paths:?} ")
}
wry::DragDropEvent::Over { position } => println!("DragOver: {position:?} "),
wry::DragDropEvent::Drop { paths, position } => {
println!("DragDrop: {position:?} {paths:?} ")
}
wry::DragDropEvent::Leave => println!("DragLeave"),
_ => {}
}
true
})
*/
.build()?;
//_webview.open_devtools();
println!("{}", webview.url().unwrap());
let req = Request::builder()
.uri(webview.url().unwrap().to_string())
.body("hooooooooooooo")
.unwrap();
#[cfg(target_os = "linux")]
{
let settings = Settings::builder()
.allow_file_access_from_file_urls(true)
.enable_developer_extras(true)
.build();
let __webview = webview.webview();
__webview.set_settings(&settings);
let inspector = __webview.inspector().expect("no inspector");
inspector.show();
}
crate::implementors::html::webview_con::mme_setup_weview_con_host(self, rx, event_loop_proxy)?;
let cloned_self = self.clone();
// this is where we block the main thread....
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
*control_flow = ControlFlow::Exit
},
Event::UserEvent::<MizeMessage>(msg) => {
match msg_to_string(msg) {
Ok(msg_string) => {
webview.evaluate_script(format!("mize.mod.mme.webview_msg_recv_fn({})", msg_string).as_str());
},
Err(err) => {
cloned_self.mize.report_err(err.into());
},
};
},
_ => {},
}
});
}
#[cfg(features = "qt")]
pub fn create_qt_slot(&self) -> MizeResult<()> {
unsafe {
let backend = i_slint_backend_qt::Backend::new();
let main_widget = qt_widgets::QWidget::new_0a();
main_widget.show();
main_widget.set_window_title(&qs("mme_main"));
comandr::platform::qt::init(main_widget.as_ptr());
//let other_window = OtherWindow::new().unwrap();
//other_window.show();
let presenter: Presenter = Presenter::HtmlPresenter(HtmlPresenter::from_folder(Path::new("/home/me/work/mme-presenters/presenters/hello-world").to_owned())?);
let mut slot: Slot = Slot::QtWidgetSlot(QtWidgetSlot::from_widget(main_widget)?);
slot.load(presenter);
println!("run_event_loop");
unsafe {
qt_core::QCoreApplication::exec();
}
//backend.run_event_loop();
//unsafe {
//run_my_event_loop(my_app);
//}
Ok(())
}
}
}
#[cfg(feature = "os-target")]
use tao::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
#[cfg(feature = "os-target")]
use wry::{
http::{self, header::CONTENT_TYPE, Request, Response},
WebViewBuilder,
};
#[cfg(feature = "os-target")]
fn get_wry_response(request: Request<Vec<u8>>, mut mme: Mme) -> Result<http::Response<Vec<u8>>, Box<dyn std::error::Error>> {
use comandr::core::module;
use mize::item::ItemData;
use mize::error::MizeResultTrait;
let mut path = PathBuf::from(request.uri().path());
let root = if path.starts_with("/modules") {
let mod_name = path.iter().nth(2).unwrap().to_str().unwrap();
println!("get_wry_response: modname: {}", mod_name);
let mod_dir = PathBuf::from(mme.mize.fetch_module(format!("cross.wasm32-none-unknown.{}", mod_name).as_str()).unwrap());
mod_dir
} else {
PathBuf::from(mme.mize.fetch_module("cross.wasm32-none-unknown.mme").unwrap())
};
let mut module_dir_conf: ItemData = mme.mize.get("self/config/module_dir/cross/wasm32-none-unknown").as_std()?.as_data_full().as_std()?;
let mut module_dir_str = String::new();
if !module_dir_conf.cbor().is_null() {
let map = module_dir_conf.cbor().as_map().ok_or(mize_err!("self/config/module_dir was not a map")).as_std()?;
for (mod_name, module_dir) in map {
let mod_name_str = mod_name.as_text().ok_or(mize_err!("mod_name was not a string")).as_std()?;
module_dir_str += format!(r#" "{mod_name_str}": "wry://localhost/modules/{mod_name_str}", "#).as_str();
}
}
let index_html = format!(r#"
<html>
<head>
<script>
import("/modules/mize/mize.js").then( module => module.init_mize({{
module_dir: {{ {module_dir_str} }},
load_modules: "mme",
module_url: "wry://localhost/modules"
}}))
</script>
</head>
<body>
MME loading...
</body>
</html>
"#);
let path = if path == PathBuf::from("/") {
// return the index.html
return Response::builder()
.header(CONTENT_TYPE, "text/html")
.body(index_html.into_bytes())
.map_err(Into::into);
} else if path.starts_with("/modules") {
path.iter().skip(3).collect()
} else {
// removing leading slash
let mut string = path.into_os_string().into_string().unwrap();
string.remove(0);
PathBuf::from(string)
};
println!("root: {}", root.display());
println!("path: {}", path.display());
let content = std::fs::read(std::fs::canonicalize(root.join(path.as_path()))?)?;
let path_str = path.as_os_str().to_str().unwrap();
// Return asset contents and mime types based on file extentions
// If you don't want to do this manually, there are some crates for you.
// Such as `infer` and `mime_guess`.
let mimetype = if path_str.ends_with(".html") || path == PathBuf::from("/") {
"text/html"
} else if path_str.ends_with(".js") {
"text/javascript"
} else if path_str.ends_with(".png") {
"image/png"
} else if path_str.ends_with(".wasm") {
"application/wasm"
} else {
"text/html"
};
println!("mimetype: {}", mimetype);
Response::builder()
.header(CONTENT_TYPE, mimetype)
.body(content)
.map_err(Into::into)
}

View File

@@ -0,0 +1,19 @@
use enum_dispatch::enum_dispatch;
use crate::implementors::html::HtmlPresenter;
// A Presenter takes data (in the form of MiZe Items) and presents them in the form of a gui.
// It can be put into a Space and provide sub Spaces, where other Presenters can be put into.
// It can provide different implementations for the different types of spaces
#[enum_dispatch]
pub trait PresenterTrait {
}
#[enum_dispatch(PresenterTrait)]
pub enum Presenter {
HtmlPresenter,
}
impl Presenter {
}

View File

@@ -0,0 +1,48 @@
use enum_dispatch::enum_dispatch;
#[cfg(features = "slint")]
use crate::implementors::slint_widget::SlintWidget;
#[cfg(features = "qt")]
use crate::implementors::qt_widget::QtWidgetSlot;
use crate::implementors::html::HtmlSlot;
use crate::presenter::Presenter;
use mize::MizeResult;
// common behaviour for all SlotTypes
#[enum_dispatch]
pub trait SlotTrait {
fn load(&mut self, presenter: Presenter) -> MizeResult<()>;
//pub fn load_html(pressenter: HtmlPresenter) -> MizeResult<()> {}
}
// this is the main type of this project
// a Widget represents any kind of "screen realestate"
// be it a Webview, slint widget, Xwindow, ...
// an enum over all of what types such "screen realestate" could have
#[enum_dispatch(SlotTrait)]
pub enum Slot {
//Xwindow {},
//WaylandWindow {},
//SlintWidget,
#[cfg(features = "qt")]
QtWidgetSlot,
//GtkWidget {},
HtmlSlot,
//QuarzWindow {},
//NtWindow {},
//Activity {},
}
pub struct Position {
x: u32,
y: u32,
z: u32,
}

View File

@@ -0,0 +1,12 @@
<html>
<head>
<!-- script src="https://c2vi.dev/mize/wasm32-none-unknown/mize.js"></script --!>
<script src="file:///home/me/work/mize/pkg/mize.js"></script>
<script>
console.log("from script")
</script>
</head>
<body>
hello world...............
</body>
</html>

View File

@@ -0,0 +1,20 @@
{ mize_url, ... }: ''
<html>
<head>
<script src="${mize_url}"></script>
<script>
init_mize({
load_modules: "mme",
mod: {
mme: {
webview_con: true
}
}
})
</script>
</head>
<body>
hello world...............
</body>
</html>
''

View File

@@ -0,0 +1,162 @@
use std::path::PathBuf;
use comandr::Comandr;
use crate::slot::SlotTrait;
use crate::mme::Mme;
use mize::MizeResult;
pub mod webview_con;
pub struct HtmlPresenter {
pub path: PathBuf,
}
impl HtmlPresenter {
pub fn from_folder(path: PathBuf) -> MizeResult<HtmlPresenter> {
Ok(HtmlPresenter { path })
}
}
pub struct HtmlSlot {
}
impl SlotTrait for HtmlSlot {
fn load(&mut self,presenter:crate::presenter::Presenter) -> MizeResult<()> {
Ok(())
}
}
#[cfg(feature = "wasm-target")]
pub mod wasm {
use comandr::Comandr;
use comandr::Command;
use web_sys::console;
use web_sys::EventTarget;
use web_sys::js_sys::Function;
use std::panic;
use std::ptr::NonNull;
use std::slice::Iter;
use comandr::Module;
use comandr::ComandrResult;
use crate::mme::Mme;
// console log
use wasm_bindgen::prelude::*;
use super::webview_con::msg_from_string;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
}
// end of console log
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
pub struct MmeJs {
pub inner: NonNull<Mme>,
pub webview_con_id: u64,
}
#[wasm_bindgen]
impl MmeJs {
#[wasm_bindgen]
pub unsafe fn webview_msg_recv_fn(&mut self, msg_string: String) -> () {
let mize = &self.inner.as_mut().mize;
let msg = match msg_from_string(msg_string, self.webview_con_id) {
Ok(val) => val,
Err(err) => {
mize.report_err(err.into());
return;
},
};
mize.got_msg(msg);
}
#[wasm_bindgen]
pub unsafe fn comandr_search(&mut self, string: String) -> Vec<String> {
//self.inner.as_mut().comandr.search(string)
Vec::new()
}
pub unsafe fn comandr_list(&mut self) -> Vec<String> {
//self.inner.as_mut().comandr.list_commands()
Vec::new()
}
#[wasm_bindgen]
pub unsafe fn comandr_run(&mut self, name: String, args: Vec<String>) -> () {
//self.inner.as_mut().comandr.execute(name, args)
}
}
pub struct MmeComandrModule {
commands: Vec<Command>
}
fn reload_page() -> ComandrResult<()>{
let js_fn_str = r#"
window.location.reload()
"#;
let js_fn = Function::new_no_args(js_fn_str);
js_fn.call0(&web_sys::wasm_bindgen::JsValue::NULL);
Ok(())
}
impl MmeComandrModule {
pub fn new() -> MmeComandrModule {
let commands = vec![
Command { name: "reload".to_owned(), closure: Box::new(reload_page) },
];
MmeComandrModule { commands }
}
}
impl Module for MmeComandrModule {
fn name(&self) -> String {
"mme".to_owned()
}
fn commands(&self) -> Iter<'_, Command> {
self.commands.iter()
}
fn get_command(&mut self, name: String) -> Option<&mut Command> {
for command in self.commands.iter_mut() {
if command.name == name {
return Some(command);
}
}
return None;
}
}
}

View File

@@ -0,0 +1,132 @@
use base64::Engine;
use mize::{mize_err, MizeResult};
use mize::proto::MizeMessage;
use base64::engine::general_purpose::STANDARD;
use tracing::trace;
use ciborium::Value as CborValue;
use flume::{ Receiver, Sender };
use ciborium_io::Read;
#[cfg(feature = "os-target")]
use wry::http::Request;
#[cfg(feature = "os-target")]
use wry::WebView;
#[cfg(feature = "os-target")]
use tao::event_loop::EventLoopProxy;
#[cfg(feature = "wasm-target")]
use crate::implementors::html::wasm::MmeJs;
#[cfg(feature = "wasm-target")]
use web_sys::js_sys::Function;
#[cfg(feature = "wasm-target")]
use wasm_bindgen::JsValue;
// console_log macro
// that can be copied into other files for debugging purposes
#[cfg(feature = "wasm-target")]
use wasm_bindgen::prelude::*;
#[cfg(feature = "wasm-target")]
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[cfg(feature = "wasm-target")]
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (unsafe { log(&format_args!($($t)*).to_string())})
}
use crate::mme::Mme;
use mize::MizeError;
#[cfg(feature = "os-target")]
pub fn mme_setup_weview_con_host(mme: &mut Mme, rx: Receiver<MizeMessage>, event_loop_proxy: EventLoopProxy<MizeMessage>) -> MizeResult<()> {
let mize_clone = mme.mize.clone();
mme.mize.spawn("webview-con-outgoing", move || {
for msg in rx {
event_loop_proxy.send_event(msg);
}
Ok(())
});
return Ok(());
}
#[cfg(feature = "wasm-target")]
pub fn mme_setup_webiew_con_js(mme: &mut Mme) -> MizeResult<Sender<MizeMessage>> {
let (tx, rx): (Sender<MizeMessage>, Receiver<MizeMessage>) = flume::unbounded();
// send things from rx out by calling window.ipc.postMessage("msg here as string")
wasm_bindgen_futures::spawn_local(webview_con_js_send_out(mme.clone(), rx));
let conn_id = mme.mize.new_connection_join_namespace(tx.clone())?;
return Ok(tx);
}
#[cfg(feature = "wasm-target")]
pub async fn webview_con_js_send_out(mme: Mme, rx: Receiver<MizeMessage>) {
let func = Function::new_with_args("msg_string", r#"
fetch("/msg", { method: "POST", headers: { MizeMsg: msg_string}})
"#);
loop {
let msg = match rx.recv_async().await {
Ok(val) => val,
Err(err) => { mme.mize.report_err(err.into()); continue; },
};
console_log!("webview_con_js_send_out: got_msg: {:?}", msg);
let msg_string = match msg_to_string(msg) {
Ok(val) => val,
Err(err) => { mme.mize.report_err(err.into()); continue; },
};
func.call1(&JsValue::null(), &JsValue::from_str(msg_string.as_str()));
}
}
pub fn msg_to_string(msg: MizeMessage) -> MizeResult<String> {
let mut msg_bytes = Vec::new();
ciborium::into_writer(&msg.value(), &mut msg_bytes)?;
let msg_string = STANDARD.encode(msg_bytes);
return Ok(msg_string)
}
pub fn msg_from_string(msg_string: String, conn_id: u64) -> MizeResult<MizeMessage> {
let msg_bytes = STANDARD.decode(msg_string)?;
let value: CborValue = ciborium::from_reader(msg_bytes.as_slice())?;
let msg = MizeMessage::new(value, conn_id);
return Ok(msg);
}

View File

@@ -0,0 +1,152 @@
use qt_gui::cpp_core::Ptr;
use tracing::{error, debug};
use qt_core::{qs, QBox, QPointerOfQObject};
use qt_widgets::QWidget;
use qt_widgets::cpp_core::CppBox;
use cpp::cpp;
use std::ffi::{CStr, CString};
use crate::presenter::Presenter;
use crate::slot::{Slot, SlotTrait};
use mize::MizeResult;
pub struct HtmlAdapter {
}
impl HtmlAdapter {
pub fn sub_slot(&self) -> MizeResult<Slot> {
todo!()
}
}
pub struct QtWidgetSlot {
widget: QBox<QWidget>,
}
impl QtWidgetSlot {
pub fn from_widget(widget: QBox<QWidget>) -> MizeResult<QtWidgetSlot> {
Ok(QtWidgetSlot { widget })
}
}
cpp! {{
#include <stdint.h>
#include <stdio.h>
#include <cstdio>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QGridLayout>
#include <QtCore/QPointer>
#include <QtCore/QDebug>
#include <QtCore/QTimer>
//#include <QtWebEngine/QtWebEngine>
#include <QtWebEngineWidgets/QWebEngineView>
#include <QtCore/QUrl>
}}
impl SlotTrait for QtWidgetSlot {
fn load(&mut self, presenter: Presenter) -> MizeResult<()> {
match presenter {
Presenter::HtmlPresenter(html) => {
// here would go the code, to load the index.html of the HtmlPresenter's path into
// the self.widget....
println!("loading html into widget....");
let url = format!("file://{}/index.html", html.path.display());
let c_string: CString = CString::new(url.as_str()).unwrap();
let c_str: &CStr = c_string.as_c_str();
unsafe {
create_webview(self.widget.as_ptr(), c_str.as_ptr());
self.widget.set_style_sheet(&qs("border: 2px solid blue;"));
//let widget_full = QWidget::new_0a();
//let widget = widget_full.as_raw_ptr();
//
//widget_fill(&mut self.widget);
//cpp_widget_fill(&mut self.widget);
}
}
}
Ok(())
}
}
extern "C" { fn create_webview(widget: Ptr<QWidget>, url: * const i8); }
pub unsafe fn widget_fill(widget: &mut QBox<QWidget>) {
let grid_layout = unsafe { qt_widgets::QGridLayout::new_0a() };
widget.set_layout(&grid_layout);
let button = unsafe { qt_widgets::QPushButton::new() };
button.set_text(&qs("hello from rust button"));
let button2 = unsafe { qt_widgets::QPushButton::new() };
button2.set_text(&qs("hello from another button"));
grid_layout.add_widget_3a(&button, 0, 1);
grid_layout.add_widget_3a(&button2, 1, 0);
}
/*
pub unsafe fn cpp_widget_fill(widget: &mut QBox<QWidget>) {
let a: i32 = 5;
let widget = widget.as_raw_ptr();
let x: i32 = cpp!(unsafe [widget as "QWidget*", a as "int32_t"] -> i32 as "int32_t" {
printf("hello from macro\n");
//QWidget * mywidget = new QWidget();
//QUrl url;
//url.setScheme("http");
//url.setHost("www.orf.at");
//QWebEngineView view = QWebEngineView(widget);
//view.setUrl(url);
//view.resize(1024, 750);
//view.show();
/*
QGridLayout *layout = new QGridLayout(widget);
widget->setLayout(layout);
QPushButton * button = new QPushButton(widget);
button->setText("My text");
button->setToolTip("A tooltip");
QPushButton * button2 = new QPushButton(widget);
button2->setText("My text 2");
button2->setToolTip("A tooltip 2");
QPushButton * button3 = new QPushButton(widget);
button3->setText("My text 3");
button3->setToolTip("A tooltip 3");
layout->addWidget (button, 0, 0);
layout->addWidget (button2, 0, 1);
layout->addWidget (button3, 1, 1);
*/
widget->show();
return a;
});
}
*/

View File

@@ -0,0 +1,60 @@
use std::path::{Path, PathBuf};
use qt_gui::q_touch_event::touch_point;
use slint_interpreter::{ComponentInstance, ComponentDefinition, ComponentCompiler, Value, SharedString, ComponentHandle};
use crate::presenter::Presenter;
use crate::slot::SlotTrait;
use crate::slot::Position;
use mize::MizeResult;
//pub mod qt_backend;
pub struct SlintWidget {
inner: ComponentInstance,
}
impl SlintWidget {
fn from_slint_file(path: PathBuf) -> MizeResult<SlintWidget> {
todo!()
}
fn sample() -> MizeResult<SlintWidget> {
let code = r#"
export component MyWin inherits Window {
in property <string> my_name;
Text {
text: "Hello, " + my_name;
}
}
"#;
let mut compiler = ComponentCompiler::default();
let definition = spin_on::spin_on(compiler.build_from_source(code.into(), Default::default()));
assert!(compiler.diagnostics().is_empty());
let instance = definition.unwrap().create().unwrap();
instance.set_property("my_name", Value::from(SharedString::from("World"))).unwrap();
return SlintWidget::from_instance(instance);
}
fn from_instance(instance: ComponentInstance) -> MizeResult<SlintWidget> {
Ok(SlintWidget {
inner: instance,
})
}
}
impl SlotTrait for SlintWidget {
fn load(&mut self,presenter:Presenter) -> MizeResult<()> {
todo!()
}
}

33
crates/mme/src/lib.rs Normal file
View File

@@ -0,0 +1,33 @@
#![ allow( warnings ) ]
//#![no_std]
//extern crate std;
mod core {
pub mod mme;
pub mod slot;
pub mod presenter;
pub mod layout;
pub mod adapter;
}
pub use core::slot;
pub use core::presenter;
pub use core::layout;
pub use core::adapter;
pub use core::mme;
pub mod implementors {
pub mod html;
#[cfg(feature = "qt")]
pub mod qt_widget;
#[cfg(feature = "slint")]
pub mod slint_widget;
#[cfg(feature = "x11")]
pub mod x_window;
}

254
crates/mme/src/logging.rs Normal file
View File

@@ -0,0 +1,254 @@
use std::path::PathBuf;
use clap::{ArgAction, ArgMatches};
use clap::{Arg, crate_version, Command};
use std::sync::Arc;
use std::io::Write;
use colored::Colorize;
use std::env;
use tracing_subscriber::fmt::Subscriber;
use tracing::Level;
use tracing::level_filters::LevelFilter;
use tracing_subscriber::filter::EnvFilter;
use tracing_subscriber::fmt::FormatEvent;
use tracing_subscriber::registry::LookupSpan;
use tracing_subscriber::fmt::FormatFields;
use tracing_subscriber::fmt::FmtContext;
use tracing_subscriber::fmt::format;
use tracing::Event;
use core::fmt;
use tracing_subscriber::fmt::FormattedFields;
use tracing::{trace, debug, info, warn, error};
use crate::DEFAULT_LOG_LEVEL;
pub fn init_logger(cli_matches: &ArgMatches) {
// to save log messages, before the logger is setup
let mut log_messages: Vec<(Level, String)> = Vec::new();
log_messages.push((Level::INFO, "Starting MME".to_owned()));
// builder with DEFAULT_LOG_LEVEL
let mut builder = tracing_subscriber::fmt::Subscriber::builder();
// set loglevel
let mut log_level = DEFAULT_LOG_LEVEL;
log_messages.push((Level::TRACE, format!("set log level from DEFAULT_LOG_LEVEL to {}", DEFAULT_LOG_LEVEL)));
// check env RUST_LOG
let mut val_rust_log = level_from_env("RUST_LOG", log_level);
if let Some(level_rust_log) = val_rust_log.0 {
log_level = level_rust_log;
log_messages.push((Level::TRACE, format!("set log level from the Variable RUST_LOG to {}", level_rust_log)));
}
log_messages.append(&mut val_rust_log.1);
// check env MME_LOG
let mut val_mme_log = level_from_env("MME_LOG", log_level);
if let Some(level_mme_log) = val_mme_log.0 {
log_level = level_mme_log;
log_messages.push((Level::TRACE, format!("set log level from the Variable MME_LOG to {}", level_mme_log)));
}
log_messages.append(&mut val_mme_log.1);
// check -vvvvv flags
let v_flag_count = cli_matches.get_count("verbose");
let default_log_level_as_num = match DEFAULT_LOG_LEVEL {
LevelFilter::OFF => 0,
LevelFilter::ERROR => 1,
LevelFilter::WARN => 2,
LevelFilter::INFO => 3,
LevelFilter::DEBUG => 4,
LevelFilter::TRACE => 5,
};
let new_log_level_num = default_log_level_as_num + v_flag_count;
log_level = match new_log_level_num {
0 => LevelFilter::OFF,
1 => LevelFilter::ERROR,
2 => LevelFilter::WARN,
3 => LevelFilter::INFO,
4 => LevelFilter::DEBUG,
5 => LevelFilter::TRACE,
_ => {
log_messages.push((Level::TRACE, format!("the number of verbose (-v) flags passed ({}) exeeds the maximumg log_level", v_flag_count)));
LevelFilter::TRACE
},
};
log_messages.push((Level::TRACE, format!("set log level from the verbose flags to {}", log_level)));
// check --log-level arg
if let Some(log_level_arg_string) = cli_matches.get_one::<String>("log-level") {
let log_level_from_arg = match log_level_arg_string.to_lowercase().as_str() {
"none" => LevelFilter::OFF,
"trace" => LevelFilter::TRACE,
"debug" => LevelFilter::DEBUG,
"info" => LevelFilter::INFO,
"warn" => LevelFilter::WARN,
"error" => LevelFilter::ERROR,
_ => {
log_messages.push((Level::WARN, format!(
"The argument to --log-level \"{}\" is not a valid log-level. loglevel stays at: {}"
, log_level_arg_string
, log_level
)));
log_level
}
};
log_level = log_level_from_arg;
log_messages.push((Level::TRACE, format!("set log level from the --log-level arg to {}", log_level_from_arg)));
}
// check --silent flag
if cli_matches.get_flag("silent") {
if log_level != DEFAULT_LOG_LEVEL {
log_messages.push((Level::WARN, format!(
"The loglevel was set by some method (it's not the DEFAULT_LOG_LEVEL) and is now overwritten by the --siltne to be OFF"
)))
}
log_level = LevelFilter::OFF;
}
// actually set the log_level on the builder
log_messages.push((Level::INFO, format!("loglevel is now {}", log_level)));
// filter loging
let mut my_env_filter = tracing_subscriber::filter::EnvFilter::new("")
.add_directive("[get_raw_from_cbor]=debug".parse().expect("error parsing log directive"))
//.add_directive("[MemStore::get_value_raw]=trace".parse().expect("error parsing log directive"))
.add_directive("trace".parse().unwrap())
.add_directive("[get_raw_from_cbor]=debug".parse().expect("error parsing log directive"))
;
builder
.with_env_filter(my_env_filter)
.without_time()
.event_format(MyFormatter)
//.with_max_level(log_level)
.init();
// write out all log messages from log_messages
for (level, msg) in log_messages {
match level {
Level::ERROR => error!("{}", msg),
Level::WARN => warn!("{}", msg),
Level::INFO => info!("{}", msg),
Level::DEBUG => debug!("{}", msg),
Level::TRACE => trace!("{}", msg),
}
}
}
fn level_from_env(var_name: &str, log_level: LevelFilter) -> (Option<LevelFilter>, Vec<(Level, String)>) {
let mut log_messages: Vec<(Level, String)> = Vec::new();
let var_value = env::var(var_name);
match var_value {
Ok(val) => {
// set loglevel acording to RUST_LOG
let level = match val.to_lowercase().as_str() {
"none" => LevelFilter::OFF,
"trace" => LevelFilter::TRACE,
"debug" => LevelFilter::DEBUG,
"info" => LevelFilter::INFO,
"warn" => LevelFilter::WARN,
"error" => LevelFilter::ERROR,
_ => {
log_messages.push((Level::WARN, format!(
"The value of Environment Variable {}: \"{}\" is not a valid log-level. loglevel stays at: {}"
, var_name
, val
, log_level
)));
log_level
}
};
return (Some(level), log_messages)
},
Err(env::VarError::NotPresent) => {},
Err(env::VarError::NotUnicode(os_string)) => {
let os_string_as_hex : String = os_string.clone().into_encoded_bytes().iter()
.map(|b| format!("{:02x}", b).to_string())
.collect::<Vec<String>>()
.join("");
log_messages.push((Level::DEBUG, format!(
"value of Environment Variable {} was not a unicode valid string. Therefore ignoring it.
\n value with replacement char U+FFFD: {}
\n the WTF-8 raw bytes as hex: {}"
, var_name
, os_string.to_string_lossy(), os_string_as_hex
)));
},
};
return (None, log_messages);
}
struct MyFormatter;
impl<S, N> FormatEvent<S, N> for MyFormatter
where
S: tracing::Subscriber + for<'a> LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static,
{
fn format_event(
&self,
ctx: &FmtContext<'_, S, N>,
mut writer: format::Writer<'_>,
event: &Event<'_>,
) -> fmt::Result {
// Format values from the event's's metadata:
let metadata = event.metadata();
// set format
/*
builder.format(|buf, record| {
match record.level() {
}
});
*/
let level_str = match metadata.level() {
&Level::TRACE => format!("[ {} ]", "TRACE".yellow()),
&Level::DEBUG => format!("[ {} ]", "DEBUG".green()),
&Level::INFO => format!("[ {} ]", "INFO".blue()),
&Level::WARN => format!("[ {} ]", "WARN".truecolor(245, 164, 66)),
&Level::ERROR => format!("[ {} ]", "ERROR".red()),
};
// with target
// write!(&mut writer, "{} {}: ", level_str, metadata.target())?;
write!(&mut writer, "{} ", level_str)?;
// Format all the spans in the event's span context.
if let Some(scope) = ctx.event_scope() {
for span in scope.from_root() {
write!(writer, "{}", span.name())?;
// `FormattedFields` is a formatted representation of the span's
// fields, which is stored in its extensions by the `fmt` layer's
// `new_span` method. The fields will have been formatted
// by the same field formatter that's provided to the event
// formatter in the `FmtContext`.
let ext = span.extensions();
let fields = &ext
.get::<FormattedFields<N>>()
.expect("will never be `None`");
// Skip formatting the fields if the span had no fields.
if !fields.is_empty() {
//write!(writer, "{{{}}}", fields)?;
}
write!(writer, ": ")?;
}
}
// Write fields on the event
ctx.field_format().format_fields(writer.by_ref(), event)?;
writeln!(writer)
}
}

233
crates/mme/src/main.cpp Normal file
View File

@@ -0,0 +1,233 @@
#include <stdint.h>
#include <stdio.h>
#include <iostream>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QGridLayout>
#include <QtCore/QPointer>
#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtCore/QString>
//#include <QtWebEngine/QtWebEngine>
#include <QtWebEngineWidgets/QWebEngineView>
#include <QtCore/QUrl>
extern "C" void run_my_event_loop( QPointer<QApplication> my_app );
extern "C" void hello_two();
extern "C" void hello_three();
extern "C" QPointer<QWidget> get_stuff();
extern "C" void create_webview(QWidget *widget, char * url_raw) {
printf("in create_webview\n");
QString * url_string = new QString(url_raw);
QUrl url = QUrl::fromUserInput(*url_string);
QWebEngineView * view = new QWebEngineView(widget);
view->setUrl(url);
//view->resize(1024, 750);
QGridLayout *layout = new QGridLayout(widget);
layout->setContentsMargins(0, 0, 0, 0);
widget->layout()->setContentsMargins(0, 0, 0, 0);
QWidget * view_widget = (QWidget*) view;
view_widget->layout()->setContentsMargins(0, 0, 0, 0);
layout->addWidget ((QWidget*)view, 0, 0);
return;
QPushButton * button = new QPushButton(widget);
button->setText("My text");
button->setToolTip("A tooltip");
QPushButton * button2 = new QPushButton(widget);
button2->setText("My text 2");
button2->setToolTip("A tooltip 2");
QPushButton * button3 = new QPushButton(widget);
button3->setText("My text 3");
button3->setToolTip("A tooltip 3");
layout->addWidget (button, 0, 0);
layout->addWidget (button2, 0, 1);
layout->addWidget (button3, 1, 1);
layout->addWidget ((QWidget*)view, 1, 0);
}
/*
class Foo : public QObject
{
Q_OBJECT
public:
Foo( QObject* parent = 0 ) : QObject( parent )
{}
private:
void doStuff()
{
qDebug() << "Emit signal one";
emit signal1();
qDebug() << "Emit finished";
emit finished();
qDebug() << "Emit signal two";
emit signal2();
}
signals:
void signal1();
void signal2();
void finished();
public slots:
void slot1()
{
qDebug() << "Execute slot one";
}
void slot2()
{
qDebug() << "Execute slot two";
}
void start()
{
printf("in start of foo");
//doStuff();
qDebug() << "Bye!";
}
};
*/
//extern "C" void place_slint_widget(QWidget * slint_widget) {
//printf("hello from test\n");
//}
extern "C" QPointer<QApplication> init_app() {
int argc = 0;
char hi = 'c';
char * two = &hi;
QPointer<QApplication> my_app = new QApplication (argc, &two);
QPointer<QWidget> main_widget = get_stuff();
QMainWindow * my_window = new QMainWindow();
my_window->setCentralWidget(main_widget);
//my_window->show();
//my_app->exec();
//run_my_event_loop(my_app);
return my_app;
}
extern "C" QPointer<QWidget> get_stuff() {
QPointer<QWidget> centralWidget = new QWidget();
QGridLayout *layout = new QGridLayout();
centralWidget->setLayout(layout);
QPushButton button;
button.setText("My text");
button.setToolTip("A tooltip");
QPushButton button2;
button2.setText("My text 2");
button2.setToolTip("A tooltip 2");
QPushButton button3;
button3.setText("My text 3");
button3.setToolTip("A tooltip 3");
layout->addWidget (&button, 0, 0);
layout->addWidget (&button2, 0, 1);
layout->addWidget (&button3, 1, 1);
return centralWidget;
}
extern "C" void hello_three() {
QWidget *centralWidget = new QWidget();
QGridLayout *layout = new QGridLayout();
centralWidget->setLayout(layout);
QPushButton button;
button.setText("My text");
button.setToolTip("A tooltip");
QPushButton button2;
button2.setText("My text 2");
button2.setToolTip("A tooltip 2");
QPushButton button3;
button3.setText("My text 3");
button3.setToolTip("A tooltip 3");
layout->addWidget (&button, 0, 0);
layout->addWidget (&button2, 0, 1);
layout->addWidget (&button3, 1, 1);
centralWidget->show();
}
extern "C" void hello_two() {
QCoreApplication * app = QApplication::instance();
QPushButton button;
button.setText("My text");
button.setToolTip("A tooltip");
button.show();
/*
Foo foo;
QObject::connect( &foo, &Foo::signal1, &foo, &Foo::slot1 );
QObject::connect( &foo, &Foo::signal2, &foo, &Foo::slot2 );
//QObject::connect( &foo, &Foo::finished, app, &QCoreApplication::quit );
QTimer::singleShot( 0, &foo, &Foo::start );
*/
}
extern "C" void run_my_event_loop( QPointer<QApplication> my_app ) {
//QCoreApplication * app = QApplication::instance();
//QPushButton other_button;
//other_button.setText("My text");
//other_button.setToolTip("A tooltip");
//other_button.show();
//printf("app exec\n");
int result = my_app->exec();
printf("app exited with: %d\n", result);
}
//#include "main.moc"

156
crates/mme/src/main.rs Normal file
View File

@@ -0,0 +1,156 @@
#![ allow( warnings ) ]
use std::path::PathBuf;
use clap::{ArgAction, ArgMatches};
use clap::{Arg, crate_version, Command};
//use cpp::cpp;
//use slint::ComponentHandle;
use std::sync::Arc;
use std::io::Write;
use colored::Colorize;
use std::env;
use tracing_subscriber::fmt::Subscriber;
use tracing::Level;
use tracing::level_filters::LevelFilter;
use tracing_subscriber::filter::EnvFilter;
use crate::logging::init_logger;
use mize_module_mme::mme::Mme;
use mize::{mize_err, Instance};
use mize::MizeResult;
use mize::MizeError;
use tracing::{trace, debug, info, warn, error};
//use slint::platform::Platform;
//use qt_core::{qs, QString, QTimer, SlotNoArgs};
//use qt_widgets::{QApplication, QGridLayout, QWidget};
mod cli {
}
mod logging;
static APPNAME: &str = "mme";
static DEFAULT_LOG_LEVEL: LevelFilter = LevelFilter::WARN;
fn main() {
let cli_matches = cli_matches();
init_logger(&cli_matches);
// match command
let result = match cli_matches.subcommand() {
// mi daemon
//Some(("run", sub_matches)) => cli::run(sub_matches),
// some unknown command passed
Some((cmd, sub_matches)) => Err(mize_err!("The subcommand: {} is not known. use --help to list availavle commands", cmd)),
None => {
unsafe { default_cmd() }
},
};
if let Err(err) = result {
err.log();
}
}
fn default_cmd() -> MizeResult<()> {
let mize = Instance::new()?;
let mut mme = Mme::new(mize)?;
mme.create_x_window()?;
Ok(())
}
/*
#[no_mangle]
unsafe extern "C" fn place_slint_widget(slint_widget: *mut QWidget) {
println!("i am here");
let mme_widget = get_widget_by_title("place_slint");
println!("mme_widget: {:?}", mme_widget);
println!("mme_widget title: {}", qstring_to_rust((*mme_widget).window_title()));
let layout = (*mme_widget).layout();
println!("layout: {:?}", layout);
let grid_layout = layout.dynamic_cast::<QGridLayout>();
println!("grid_layout: {:?}", grid_layout);
println!("slint_widget: {:?}", slint_widget);
(*grid_layout).add_widget_3a(slint_widget, 0, 0);
}
unsafe extern "C" fn get_widget_by_title(title: &str) -> * mut QWidget {
let widgets = QApplication::top_level_widgets();
let mut mme_widget: *mut QWidget = *widgets.index_mut(0);
let widgets_size = widgets.size();
for i in 0..widgets_size {
let widget = *widgets.index(i);
let widget_title = qstring_to_rust((*widget).window_title());
println!("get_mme_main_widget: window_title: {}", widget_title);
if widget_title == title.to_owned() {
println!("found: {:?}", widget);
mme_widget = widget
}
}
return mme_widget;
}
*/
fn cli_matches() -> clap::ArgMatches {
let main = Command::new(APPNAME)
.version(crate_version!())
.author("Sebastian Moser")
.about("The Main Mize Explorer or Mize Ui Framework")
.arg(Arg::new("verbose")
.long("verbose")
.short('v')
.action(ArgAction::Count)
.global(true)
)
.arg(Arg::new("log-level")
.long("log-level")
.value_name("LOGLEVEL")
.help("set the log-level to one of OFF, ERROR, WARN, INFO, DEBUG, TRACE")
.global(true)
)
.arg(Arg::new("silent")
.long("silent")
.action(ArgAction::SetTrue)
.help("set the log-level to OFF")
.global(true)
)
.arg(Arg::new("folder")
.short('f')
.long("folder")
.help("The folder the Instance stores all it's data and the socket for connections")
.global(true)
)
.arg(Arg::new("config")
.short('c')
.long("config")
.help("overwrite config options")
.global(true)
)
.arg(Arg::new("config-file")
.long("config-file")
.help("specify a config file")
.global(true)
);
return main.get_matches();
}

3
crates/mme/test.html Normal file
View File

@@ -0,0 +1,3 @@
<h1>Hello World</h1>
<p>hiiiiiiiiiiiiiiiii</p>