Compare commits

..

No commits in common. "309060a5ce06be531e12cc82e4a0a519c8580663" and "676594f9bf6ff346c185fdfc1c55ceafd22bacb1" have entirely different histories.

53 changed files with 1024 additions and 1239 deletions

Binary file not shown.

View File

@ -1,54 +0,0 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\msys64\\home\\doryan\\AIT\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\msys64\\home\\doryan\\AIT\\src\\main.rs||{3B902123-F8A7-4915-9F01-361F908088D0}",
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:src\\main.rs||{3B902123-F8A7-4915-9F01-361F908088D0}"
},
{
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\msys64\\home\\doryan\\AIT\\.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}",
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}"
}
],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 1,
"Children": [
{
"$type": "Document",
"DocumentIndex": 1,
"Title": ".gitignore",
"DocumentMoniker": "C:\\msys64\\home\\doryan\\AIT\\.gitignore",
"RelativeDocumentMoniker": ".gitignore",
"ToolTip": "C:\\msys64\\home\\doryan\\AIT\\.gitignore",
"RelativeToolTip": ".gitignore",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "00000000-0000-0000-0000-000000000000.000000|iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAF8SURBVDhPjVNLTgJBEG1lwpoFB3GNK9fieA48hD8iwT/ihwgSDAIHgAGXXsEV18CNzL/LquqZdsYM6kteXqcy3fWqpmpNRBgOhyABBEgpAFVKPIMUcYzUyOU\u002BXM/b2qtU3vkSfRjjZTCAMAw1A2LwzdFoBPP5HNqdzuL27n4juibWI\u002BUshBA1DIkhEx9iEorFotgslQqGYbxxAGFEqt1MxmPWJLbLZdZ\u002Bv89q5PMFPiTR6z2zdaxR0fXA0XTBcVywkb4fwHXjRteecIDNQ7UmExVYAdPcxYaqclN46na5WenMKjtlVnTYwcXlVYaDqImW9beD5N/TeGy32QHXm6hZ03ZgiSQHp2fnWQ4oBmJqWSqwAqZpZjt4aLXAD4J0VqyZsmoubfB8H2r1eoaD6NXZ9HcHO\u002BSA3f4AjifXl8rItOETM8ckB9WTWpYD9RdeZ1PWVWAHWXPQaDb59f/w8LiqHeh1pvGkCaP6qB8yXusoxmuNZ7XmII4O9vGuEF86osuDYRkpYQAAAABJRU5ErkJggg==",
"WhenOpened": "2024-08-18T21:59:06.655Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "main.rs",
"DocumentMoniker": "C:\\msys64\\home\\doryan\\AIT\\src\\main.rs",
"RelativeDocumentMoniker": "src\\main.rs",
"ToolTip": "C:\\msys64\\home\\doryan\\AIT\\src\\main.rs",
"RelativeToolTip": "src\\main.rs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
"WhenOpened": "2024-08-18T21:59:04.875Z",
"EditorCaption": ""
}
]
}
]
}
]
}

View File

@ -1,53 +0,0 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\msys64\\home\\doryan\\AIT\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\msys64\\home\\doryan\\AIT\\src\\main.rs||{3B902123-F8A7-4915-9F01-361F908088D0}",
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:src\\main.rs||{3B902123-F8A7-4915-9F01-361F908088D0}"
},
{
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\msys64\\home\\doryan\\AIT\\.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}",
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}"
}
],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 1,
"Children": [
{
"$type": "Document",
"DocumentIndex": 1,
"Title": ".gitignore",
"DocumentMoniker": "C:\\msys64\\home\\doryan\\AIT\\.gitignore",
"RelativeDocumentMoniker": ".gitignore",
"ToolTip": "C:\\msys64\\home\\doryan\\AIT\\.gitignore",
"RelativeToolTip": ".gitignore",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "00000000-0000-0000-0000-000000000000.000000|iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAF8SURBVDhPjVNLTgJBEG1lwpoFB3GNK9fieA48hD8iwT/ihwgSDAIHgAGXXsEV18CNzL/LquqZdsYM6kteXqcy3fWqpmpNRBgOhyABBEgpAFVKPIMUcYzUyOU\u002BXM/b2qtU3vkSfRjjZTCAMAw1A2LwzdFoBPP5HNqdzuL27n4juibWI\u002BUshBA1DIkhEx9iEorFotgslQqGYbxxAGFEqt1MxmPWJLbLZdZ\u002Bv89q5PMFPiTR6z2zdaxR0fXA0XTBcVywkb4fwHXjRteecIDNQ7UmExVYAdPcxYaqclN46na5WenMKjtlVnTYwcXlVYaDqImW9beD5N/TeGy32QHXm6hZ03ZgiSQHp2fnWQ4oBmJqWSqwAqZpZjt4aLXAD4J0VqyZsmoubfB8H2r1eoaD6NXZ9HcHO\u002BSA3f4AjifXl8rItOETM8ckB9WTWpYD9RdeZ1PWVWAHWXPQaDb59f/w8LiqHeh1pvGkCaP6qB8yXusoxmuNZ7XmII4O9vGuEF86osuDYRkpYQAAAABJRU5ErkJggg==",
"WhenOpened": "2024-08-18T21:59:06.655Z"
},
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "main.rs",
"DocumentMoniker": "C:\\msys64\\home\\doryan\\AIT\\src\\main.rs",
"RelativeDocumentMoniker": "src\\main.rs",
"ToolTip": "C:\\msys64\\home\\doryan\\AIT\\src\\main.rs",
"RelativeToolTip": "src\\main.rs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
"WhenOpened": "2024-08-18T21:59:04.875Z",
"EditorCaption": ""
}
]
}
]
}
]
}

View File

@ -1,3 +0,0 @@
{
"CurrentProjectSetting": null
}

View File

@ -1,7 +0,0 @@
{
"ExpandedNodes": [
"",
"\\src"
],
"PreviewInSolutionExplorer": false
}

Binary file not shown.

45
.vscode/launch.json vendored
View File

@ -1,45 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'AIT'",
"cargo": {
"args": [
"build",
"--bin=AIT",
"--package=AIT"
],
"filter": {
"name": "AIT",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'AIT'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=AIT",
"--package=AIT"
],
"filter": {
"name": "AIT",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

378
Cargo.lock generated
View File

@ -2,23 +2,11 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "AIT"
version = "0.1.0"
dependencies = [
"bitvec",
"gio",
"gtk4",
"libadwaita",
"tokio",
"winres",
]
[[package]] [[package]]
name = "addr2line" name = "addr2line"
version = "0.22.0" version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [ dependencies = [
"gimli", "gimli",
] ]
@ -30,16 +18,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "autocfg" name = "anyhow"
version = "1.3.0" version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
[[package]]
name = "autocfg"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.73" version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"cc", "cc",
@ -52,9 +46,9 @@ dependencies = [
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.6.0" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]] [[package]]
name = "bitvec" name = "bitvec"
@ -70,21 +64,22 @@ dependencies = [
[[package]] [[package]]
name = "cairo-rs" name = "cairo-rs"
version = "0.20.1" version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a0ea147c94108c9613235388f540e4d14c327f7081c9e471fc8ee8a2533e69" checksum = "b2ac2a4d0e69036cf0062976f6efcba1aaee3e448594e6514bb2ddf87acce562"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cairo-sys-rs", "cairo-sys-rs",
"glib", "glib",
"libc", "libc",
"thiserror",
] ]
[[package]] [[package]]
name = "cairo-sys-rs" name = "cairo-sys-rs"
version = "0.20.0" version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "428290f914b9b86089f60f5d8a9f6e440508e1bcff23b25afd51502b0a2da88f" checksum = "fd3bb3119664efbd78b5e6c93957447944f16bdbced84c17a9f41c7829b81e64"
dependencies = [ dependencies = [
"glib-sys", "glib-sys",
"libc", "libc",
@ -93,18 +88,15 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.1.13" version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
dependencies = [
"shlex",
]
[[package]] [[package]]
name = "cfg-expr" name = "cfg-expr"
version = "0.16.0" version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345c78335be0624ed29012dc10c49102196c6882c12dde65d9f35b02da2aada8" checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02"
dependencies = [ dependencies = [
"smallvec", "smallvec",
"target-lexicon", "target-lexicon",
@ -178,7 +170,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -203,9 +195,9 @@ dependencies = [
[[package]] [[package]]
name = "gdk-pixbuf" name = "gdk-pixbuf"
version = "0.20.1" version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8730751991b97419fc3f0c2dca2c9e45b48edf46e48e0f965964ecf33889812f" checksum = "f6a23f8a0b5090494fd04924662d463f8386cc678dd3915015a838c1a3679b92"
dependencies = [ dependencies = [
"gdk-pixbuf-sys", "gdk-pixbuf-sys",
"gio", "gio",
@ -215,9 +207,9 @@ dependencies = [
[[package]] [[package]]
name = "gdk-pixbuf-sys" name = "gdk-pixbuf-sys"
version = "0.20.1" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ffbf649fd5b1c8c0f0feeb015b7533c3ef92da2887fb95ddd338bc2b1644a7c" checksum = "3dcbd04c1b2c4834cc008b4828bc917d062483b88d26effde6342e5622028f96"
dependencies = [ dependencies = [
"gio-sys", "gio-sys",
"glib-sys", "glib-sys",
@ -228,9 +220,9 @@ dependencies = [
[[package]] [[package]]
name = "gdk4" name = "gdk4"
version = "0.9.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b7d7237c1487ed4b300aac7744efcbf1319e12d60d7afcd6f505414bd5b5dea" checksum = "9100b25604183f2fd97f55ef087fae96ab4934d7215118a35303e422688e6e4b"
dependencies = [ dependencies = [
"cairo-rs", "cairo-rs",
"gdk-pixbuf", "gdk-pixbuf",
@ -243,9 +235,9 @@ dependencies = [
[[package]] [[package]]
name = "gdk4-sys" name = "gdk4-sys"
version = "0.9.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a67576c8ec012156d7f680e201a807b4432a77babb3157e0555e990ab6bcd878" checksum = "d0b76874c40bb8d1c7d03a7231e23ac75fa577a456cd53af32ec17ec8f121626"
dependencies = [ dependencies = [
"cairo-sys-rs", "cairo-sys-rs",
"gdk-pixbuf-sys", "gdk-pixbuf-sys",
@ -260,15 +252,15 @@ dependencies = [
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.29.0" version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]] [[package]]
name = "gio" name = "gio"
version = "0.20.1" version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcacaa37401cad0a95aadd266bc39c72a131d454fc012f6dfd217f891d76cc52" checksum = "3f91a0518c2ec539f099d3f945ab2d6a83ec372a9ef40a21906343b191182845"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@ -279,13 +271,14 @@ dependencies = [
"libc", "libc",
"pin-project-lite", "pin-project-lite",
"smallvec", "smallvec",
"thiserror",
] ]
[[package]] [[package]]
name = "gio-sys" name = "gio-sys"
version = "0.20.1" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5237611e97e9b86ab5768adc3eef853ae713ea797aa3835404acdfacffc9fb38" checksum = "bcf8e1d9219bb294636753d307b030c1e8a032062cba74f493c431a5c8b81ce4"
dependencies = [ dependencies = [
"glib-sys", "glib-sys",
"gobject-sys", "gobject-sys",
@ -296,9 +289,9 @@ dependencies = [
[[package]] [[package]]
name = "glib" name = "glib"
version = "0.20.1" version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b19429cb83fcbf1f00b31ae3a123fab5cd3761bdd15b0cc07905804742f0d0e4" checksum = "ae1407b2ce171e654720be10d57d4054d3ff2f10a13d5b37e6819b41439832f7"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"futures-channel", "futures-channel",
@ -313,26 +306,27 @@ dependencies = [
"libc", "libc",
"memchr", "memchr",
"smallvec", "smallvec",
"thiserror",
] ]
[[package]] [[package]]
name = "glib-macros" name = "glib-macros"
version = "0.20.1" version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960349f56469b75794157e93bf04f0bc8a622d0a6612d6a8f8d7eac41e0e1ee1" checksum = "d8bba315e8ce8aa59631545358450f4962557e89b5f7db7442e7153b47037f71"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.58",
] ]
[[package]] [[package]]
name = "glib-sys" name = "glib-sys"
version = "0.20.1" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44edae63bea922f18f7e63977ee60a257ec27c4613aff1a6a9bb572ad0d88269" checksum = "630f097773d7c7a0bb3258df4e8157b47dc98bbfa0e60ad9ab56174813feced4"
dependencies = [ dependencies = [
"libc", "libc",
"system-deps", "system-deps",
@ -340,9 +334,9 @@ dependencies = [
[[package]] [[package]]
name = "gobject-sys" name = "gobject-sys"
version = "0.20.1" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa3d1dcd8a1eb2e7c22be3d5e792b14b186f3524f79b25631730f9a8c169d49a" checksum = "c85e2b1080b9418dd0c58b498da3a5c826030343e0ef07bde6a955d28de54979"
dependencies = [ dependencies = [
"glib-sys", "glib-sys",
"libc", "libc",
@ -351,9 +345,9 @@ dependencies = [
[[package]] [[package]]
name = "graphene-rs" name = "graphene-rs"
version = "0.20.1" version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80aac87f74e81c0e13433e892a047237abdc37945c86887f5eed905038356e69" checksum = "99e4d388e96c5f29e2b2f67045d229ddf826d0a8d6d282f94ed3b34452222c91"
dependencies = [ dependencies = [
"glib", "glib",
"graphene-sys", "graphene-sys",
@ -362,9 +356,9 @@ dependencies = [
[[package]] [[package]]
name = "graphene-sys" name = "graphene-sys"
version = "0.20.1" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2f91ecd32989efad60326cc20a8fb252bd2852239a08e4e70cde8c100de9ca" checksum = "236ed66cc9b18d8adf233716f75de803d0bf6fc806f60d14d948974a12e240d0"
dependencies = [ dependencies = [
"glib-sys", "glib-sys",
"libc", "libc",
@ -374,9 +368,9 @@ dependencies = [
[[package]] [[package]]
name = "gsk4" name = "gsk4"
version = "0.9.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3cf2091e1af185b347b3450817d93dea6fe435df7abd4c2cd7fb5bcb4cfda8" checksum = "c65036fc8f99579e8cb37b12487969b707ab23ec8ab953682ff347cbd15d396e"
dependencies = [ dependencies = [
"cairo-rs", "cairo-rs",
"gdk4", "gdk4",
@ -389,9 +383,9 @@ dependencies = [
[[package]] [[package]]
name = "gsk4-sys" name = "gsk4-sys"
version = "0.9.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aa69614a26d8760c186c3690f1b0fbb917572ca23ef83137445770ceddf8cde" checksum = "bd24c814379f9c3199dc53e52253ee8d0f657eae389ab282c330505289d24738"
dependencies = [ dependencies = [
"cairo-sys-rs", "cairo-sys-rs",
"gdk4-sys", "gdk4-sys",
@ -405,9 +399,9 @@ dependencies = [
[[package]] [[package]]
name = "gtk4" name = "gtk4"
version = "0.9.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaffc6c743c9160514cc9b67eace364e5dc5798369fa809cdb04e035c21c5c5d" checksum = "aa82753b8c26277e4af1446c70e35b19aad4fb794a7b143859e7eeb9a4025d83"
dependencies = [ dependencies = [
"cairo-rs", "cairo-rs",
"field-offset", "field-offset",
@ -426,21 +420,23 @@ dependencies = [
[[package]] [[package]]
name = "gtk4-macros" name = "gtk4-macros"
version = "0.9.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "188211f546ce5801f6d0245c37b6249143a2cb4fa040e54829ca1e76796e9f09" checksum = "40300bf071d2fcd4c94eacc09e84ec6fe73129d2ceb635cf7e55b026b5443567"
dependencies = [ dependencies = [
"anyhow",
"proc-macro-crate", "proc-macro-crate",
"proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
] ]
[[package]] [[package]]
name = "gtk4-sys" name = "gtk4-sys"
version = "0.9.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1114a207af8ada02cf4658a76692f4190f06f093380d5be07e3ca8b43aa7c666" checksum = "0db1b104138f087ccdc81d2c332de5dd049b89de3d384437cc1093b17cd2da18"
dependencies = [ dependencies = [
"cairo-sys-rs", "cairo-sys-rs",
"gdk-pixbuf-sys", "gdk-pixbuf-sys",
@ -457,9 +453,9 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.5" version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]] [[package]]
name = "heck" name = "heck"
@ -469,20 +465,31 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.4.0" version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
] ]
[[package]] [[package]]
name = "libadwaita" name = "laboratory_works"
version = "0.7.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ff9c222b5c783729de45185f07b2fec2d43a7f9c63961e777d3667e20443878"
dependencies = [ dependencies = [
"bitvec",
"gtk4",
"libadwaita",
"tokio",
]
[[package]]
name = "libadwaita"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91b4990248b9e1ec5e72094a2ccaea70ec3809f88f6fd52192f2af306b87c5d9"
dependencies = [
"gdk-pixbuf",
"gdk4", "gdk4",
"gio", "gio",
"glib", "glib",
@ -494,9 +501,9 @@ dependencies = [
[[package]] [[package]]
name = "libadwaita-sys" name = "libadwaita-sys"
version = "0.7.0" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c44d8bdbad31d6639e1f20cc9c1424f1a8e02d751fc28d44659bf743fb9eca6" checksum = "23a748e4e92be1265cd9e93d569c0b5dfc7814107985aa6743d670ab281ea1a8"
dependencies = [ dependencies = [
"gdk4-sys", "gdk4-sys",
"gio-sys", "gio-sys",
@ -510,15 +517,15 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.156" version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.4" version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]] [[package]]
name = "memoffset" name = "memoffset"
@ -531,27 +538,27 @@ dependencies = [
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.4" version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [ dependencies = [
"adler", "adler",
] ]
[[package]] [[package]]
name = "object" name = "object"
version = "0.36.3" version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]] [[package]]
name = "pango" name = "pango"
version = "0.20.1" version = "0.19.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5764e5a174a5a0ec054fe5962ce6d4fc7052e2d0dcc23bbc77202b40a4a403d3" checksum = "b1264d13deb823cc652f26cfe59afb1ec4b9db2a5bd27c41b738c879cc1bfaa1"
dependencies = [ dependencies = [
"gio", "gio",
"glib", "glib",
@ -561,9 +568,9 @@ dependencies = [
[[package]] [[package]]
name = "pango-sys" name = "pango-sys"
version = "0.20.1" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd317e1de76b14b3d3efe05518c08b360327f1ab7fec150473a89ffcad4b072d" checksum = "f52ef6a881c19fbfe3b1484df5cad411acaaba29dbec843941c3110d19f340ea"
dependencies = [ dependencies = [
"glib-sys", "glib-sys",
"gobject-sys", "gobject-sys",
@ -599,10 +606,34 @@ dependencies = [
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro-error"
version = "1.0.86" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -624,9 +655,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.24" version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
@ -639,45 +670,39 @@ dependencies = [
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.23" version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.208" version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.208" version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.58",
] ]
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.7" version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
dependencies = [ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@ -695,9 +720,20 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.74" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -706,14 +742,14 @@ dependencies = [
[[package]] [[package]]
name = "system-deps" name = "system-deps"
version = "7.0.2" version = "6.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "070a0a5e7da2d24be457809c4b3baa57a835fd2829ad8b86f9a049052fe71031" checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
dependencies = [ dependencies = [
"cfg-expr", "cfg-expr",
"heck", "heck",
"pkg-config", "pkg-config",
"toml 0.8.19", "toml",
"version-compare", "version-compare",
] ]
@ -725,9 +761,29 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.12.16" version = "0.12.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
[[package]]
name = "thiserror"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
@ -748,35 +804,26 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.58",
] ]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.11" version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
dependencies = [
"serde",
]
[[package]]
name = "toml"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_edit 0.22.20", "toml_edit 0.22.9",
] ]
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "0.6.8" version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -794,15 +841,15 @@ dependencies = [
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.20" version = "0.22.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"winnow 0.6.18", "winnow 0.6.6",
] ]
[[package]] [[package]]
@ -817,6 +864,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.52.0"
@ -828,9 +881,9 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm", "windows_aarch64_gnullvm",
"windows_aarch64_msvc", "windows_aarch64_msvc",
@ -844,51 +897,51 @@ dependencies = [
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]] [[package]]
name = "windows_i686_gnullvm" name = "windows_i686_gnullvm"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]] [[package]]
name = "winnow" name = "winnow"
@ -901,22 +954,13 @@ dependencies = [
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.18" version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "winres"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
dependencies = [
"toml 0.5.11",
]
[[package]] [[package]]
name = "wyz" name = "wyz"
version = "0.5.1" version = "0.5.1"

View File

@ -1,16 +1,13 @@
[package] [package]
name = "AIT" name = "laboratory_works"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
adw = { version = "0.7.0", package = "libadwaita"} adw = { version = "0.6.0", package = "libadwaita", features = ["v1_4"] }
bitvec = "1.0.1" bitvec = "1.0.1"
gio = { version = "0.20.0", features = ["v2_74"] } gtk4 = "0.8.1"
gtk = { version = "0.9.0", package = "gtk4", features = ["v4_12"] }
tokio = { version = "1.39.2", features = ["rt", "time", "rt-multi-thread", "macros", "sync"] } tokio = { version = "1.39.2", features = ["rt", "time", "rt-multi-thread", "macros", "sync"] }
[build-dependencies]
winres = "0.1"

View File

@ -1,9 +0,0 @@
extern crate winres;
fn main() {
if cfg!(target_os = "windows") {
let mut res = winres::WindowsResource::new();
res.set_icon("./src/view/resources/icon.ico"); // Replace this with the filename of your .ico file.
res.compile().unwrap();
}
}

View File

@ -0,0 +1,10 @@
use gtk::*;
use gtk4 as gtk;
pub fn state_controller(switch: &Switch, label: &Label) {
if switch.state() {
label.set_label("Режим: проверка");
} else {
label.set_label("Режим: кодирование");
}
}

View File

@ -0,0 +1,28 @@
use crate::{gtk::prelude::*, model::models::*};
impl<F, C> EventHandler<F, C>
where
F: Fn(&C) + FnOnce(&C) + FnMut(&C),
{
pub fn new(component: C, callback: F) -> Self {
Self {
component,
callback,
}
}
}
pub trait BtnEventHandler {
fn on_click(self);
}
impl<F, C> BtnEventHandler for EventHandler<F, C>
where
F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static,
C: ButtonExt + WidgetExt,
{
fn on_click(self) {
self.component
.connect_clicked(move |button| (self.callback)(button));
}
}

View File

@ -0,0 +1,2 @@
pub mod button_event_handlers;
pub mod switch_event_handlers;

View File

@ -0,0 +1,16 @@
use crate::{gtk::prelude::*, model::models::*, view::components::switch::SwitchExt};
pub trait SwEventHandler {
fn on_toggle(self);
}
impl<F, C> SwEventHandler for EventHandler<F, C>
where
F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static,
C: SwitchExt + WidgetExt,
{
fn on_toggle(self) {
self.component
.connect_state_notify(move |switch| (self.callback)(switch));
}
}

View File

@ -1,2 +1,4 @@
pub mod model_utils; pub mod controller;
pub mod view_utils; pub mod view_utils;
pub mod model_utils;
pub mod event_handlers;

View File

@ -1,48 +1,52 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::LazyLock;
use crate::{ use crate::{
controller::view_utils::{hamming_code_utils::*, input_utils::*}, controller::view_utils::{hamming_code_input_utils::*, input_utils::*},
model::{models::*, Result}, model::models::*,
}; };
static SYNDROMES: LazyLock<HashMap<usize, (bool, bool, bool)>> = LazyLock::new(|| { /// **Синдромы**
HashMap::from([ ///
(1, (false, true, true)), /// ошибочная позиция 1 false true true.
(2, (false, false, true)), ///
(3, (true, false, true)), /// ошибочная позиция 2 false false true.
(4, (false, true, false)), ///
(5, (true, true, false)), /// ошибочная позиция 3 true false true.
(6, (true, false, false)), ///
(7, (false, false, false)), /// ошибочная позиция 4 false true false.
]) ///
}); /// ошибочная позиция 5 true true false.
///
/// ошибочная позиция 6 true false false.
///
/// ошибочная позиция 7 false false false.
pub fn hamming(raw_input: String, mode: HammingMode) -> Result<String> { pub fn hamming(raw_input: String, mode: HammingMode) -> Result<String, String> {
let length_of_code: usize = mode.clone() as usize; let length_of_code: usize = mode.clone() as usize;
let prepared_input: String = processing_input(&raw_input); let prepared_input: String = processing_input(&raw_input);
let (first_condition, second_condition): (bool, bool) = let (fc, sc): (bool, bool) =
check_correct_binary_code(&prepared_input, length_of_code); check_correct_binary_code(&raw_input, &prepared_input, length_of_code);
if raw_input.is_empty() { if !fc || !sc {
Err("Введите код.".into()) Err("Ошибка. Проверьте корректность ввода.".to_string())
} else if !first_condition || !second_condition {
Err("Проверьте корректность ввода.".into())
} else { } else {
let mut data: String = String::new();
let prepared_data: Vec<u8> = from_string_to_vec_bits(prepared_input); let prepared_data: Vec<u8> = from_string_to_vec_bits(prepared_input);
match mode { match mode {
HammingMode::Encrypt => Ok(hamming_encrypt_data(&prepared_data, length_of_code)), HammingMode::Encrypt => hamming_encrypt_data(&prepared_data, &mut data, length_of_code),
HammingMode::Decrypt => Ok(hamming_decrypt_data(&prepared_data, length_of_code)), HammingMode::Decrypt => hamming_decrypt_data(&prepared_data, &mut data, length_of_code),
} }
Ok(data)
} }
} }
pub fn hamming_encrypt_data(data: &[u8], length_of_code: usize) -> String { pub fn hamming_encrypt_data(data: &Vec<u8>, result_string: &mut String, length_of_code: usize) {
let mut i: usize = length_of_code; let mut i: usize = length_of_code;
let mut result = String::new();
while i <= data.len() { while i <= data.len() {
let data_bits: &[u8] = &data[i - length_of_code..i]; let data_bits: &[u8] = &data[i - length_of_code..i];
@ -51,23 +55,26 @@ pub fn hamming_encrypt_data(data: &[u8], length_of_code: usize) -> String {
data_bits[0] ^ data_bits[2] ^ data_bits[3], data_bits[0] ^ data_bits[2] ^ data_bits[3],
data_bits[1] ^ data_bits[2] ^ data_bits[3], data_bits[1] ^ data_bits[2] ^ data_bits[3],
); );
result_string.push_str(&*format!(
result.push_str(
format!(
"{check_bit_1}{}{check_bit_2}{}{check_bit_3}{}{} ", "{check_bit_1}{}{check_bit_2}{}{check_bit_3}{}{} ",
data_bits[0], data_bits[1], data_bits[2], data_bits[3] data_bits[0], data_bits[1], data_bits[2], data_bits[3]
) ));
.as_str(),
);
i += length_of_code; i += length_of_code;
} }
result
} }
pub fn hamming_decrypt_data(data: &[u8], length_of_code: usize) -> String { pub fn hamming_decrypt_data(data: &Vec<u8>, result_string: &mut String, length_of_code: usize) {
let mut general_length: usize = length_of_code; let mut general_length: usize = length_of_code;
let mut result = String::new();
let syndromes: HashMap<usize, (bool, bool, bool)> = HashMap::from([
(1, (false, true, true)),
(2, (false, false, true)),
(3, (true, false, true)),
(4, (false, true, false)),
(5, (true, true, false)),
(6, (true, false, false)),
(7, (false, false, false)),
]);
let mut errors: String = String::new(); let mut errors: String = String::new();
@ -84,7 +91,7 @@ pub fn hamming_decrypt_data(data: &[u8], length_of_code: usize) -> String {
general_length += length_of_code; general_length += length_of_code;
continue; continue;
} else { } else {
let error_position: &usize = SYNDROMES let error_position: &usize = syndromes
.iter() .iter()
.find(move |&(&_error_position, &error)| error == checked_bits) .find(move |&(&_error_position, &error)| error == checked_bits)
.unwrap() .unwrap()
@ -120,11 +127,11 @@ pub fn hamming_decrypt_data(data: &[u8], length_of_code: usize) -> String {
if !data.is_empty() { if !data.is_empty() {
if errors.is_empty() { if errors.is_empty() {
result.push_str("Все коды корректны."); result_string.push_str("Все коды корректны.");
} else { } else {
result.push_str(errors.as_str()); result_string.push_str(errors.as_str());
}
} else {
result_string.push_str("Введите код для проверки.")
} }
} }
result
}

View File

@ -1,7 +1,3 @@
use crate::model::Frequency;
use gio::{prelude::Cast, ListStore};
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn reactive_resistance_of_capacitor(Cm: f64, L: f64, f: f64) -> f64 { pub fn reactive_resistance_of_capacitor(Cm: f64, L: f64, f: f64) -> f64 {
if f == 0.0 || Cm == 0.0 || L == 0.0 { if f == 0.0 || Cm == 0.0 || L == 0.0 {
@ -13,7 +9,7 @@ pub fn reactive_resistance_of_capacitor(Cm: f64, L: f64, f: f64) -> f64 {
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn full_resistance_of_capacitor(Xc: f64, Rs: f64, Rm: f64, L: f64) -> f64 { pub fn full_resistance_of_capacitor(Xc: f64, Rs: f64, Rm: f64, L: f64) -> f64 {
(Xc.powi(2) + (Rs + Rm * L).powi(2)).sqrt() (Xc.powf(2f64) + (Rs + Rm * L).powf(2f64)).sqrt()
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -33,19 +29,3 @@ pub fn coef_of_signal_reduce(Vs: f64, V: f64) -> f64 {
Vs / V Vs / V
} }
} }
pub fn set_default_values(model: &ListStore) {
for number in (0..=100).step_by(5) {
if number == 0 {
model.append(&Frequency::new(1.0));
} else if (number >= 70 && number % 10 == 0) || (number < 70 && number % 5 == 0) {
model.append(&Frequency::new(number as f64));
}
}
}
pub fn find_by_frequency_value(model: &ListStore, new_elem: &Frequency) -> Option<u32> {
model.find_with_equal_func(|elem| {
elem.downcast_ref::<Frequency>().unwrap().frequency() == new_elem.frequency()
})
}

View File

@ -0,0 +1,41 @@
use gtk4 as gtk;
use crate::{model::models::*, model_utils::hamming_code_seven_four::*};
use gtk::{prelude::*, *};
pub fn start_hamming_algorithm(input: &TextView, output: &TextView, mode: bool) {
let (iter_start, iter_end) = input.buffer().bounds();
let parsed_input: String = input
.buffer()
.text(&iter_start, &iter_end, false)
.to_string()
.trim()
.parse()
.unwrap();
let operation = if mode {
HammingMode::Encrypt
} else {
HammingMode::Decrypt
};
match hamming(parsed_input, operation) {
Ok(res) => output.buffer().set_text(res.trim_end()),
Err(rej) => output.buffer().set_text(rej.as_str()),
}
}
pub fn check_correct_binary_code(
input: &String,
prepared_input: &String,
l: usize,
) -> (bool, bool) {
let first_condition: bool = input
.as_str()
.chars()
.all(|c| c == '1' || c == '0' || c == ' ');
let second_condition: bool = prepared_input.len() % l == 0;
(first_condition, second_condition)
}

View File

@ -1,32 +0,0 @@
use crate::{
model::{models::*, Result},
model_utils::hamming_code_seven_four::*,
};
use gtk::{prelude::*, *};
pub fn start_hamming_algorithm(input: &TextView, state: bool) -> Result<String> {
let (iter_start, iter_end) = input.buffer().bounds();
let parsed_input: String = input
.buffer()
.text(&iter_start, &iter_end, false)
.to_string()
.trim()
.parse()
.unwrap();
let operation = if !state {
HammingMode::Encrypt
} else {
HammingMode::Decrypt
};
hamming(parsed_input, operation)
}
pub fn check_correct_binary_code(prepared_input: &str, l: usize) -> (bool, bool) {
let first_condition: bool = prepared_input.len() % l == 0;
let second_condition: bool = prepared_input.chars().all(|c| c == '1' || c == '0');
(first_condition, second_condition)
}

View File

@ -1,14 +1,15 @@
use gtk4 as gtk;
use bitvec::{order::Lsb0, view::AsBits}; use bitvec::{order::Lsb0, view::AsBits};
use gtk::{prelude::*, *}; use gtk::{prelude::*, *};
use std::ops::Deref; use std::ops::Deref;
const ASCII_ZERO_CHAR_POSITION: u8 = 48; const ASCII_ZERO_CHAR_POSITION: u8 = 48;
pub fn processing_input(input: impl Into<String>) -> String { pub fn processing_input(input: &String) -> String {
input input
.into() .split_ascii_whitespace()
.split(&[' ', '\n'][..]) .filter(|&x| x.is_empty())
.filter(|x| !x.is_empty())
.fold(String::new(), |c: String, n: &str| c + n) .fold(String::new(), |c: String, n: &str| c + n)
} }
@ -19,9 +20,8 @@ pub fn from_vec_bits_to_string(raw_data: &[u8]) -> String {
.collect() .collect()
} }
pub fn from_string_to_vec_bits(raw_data: impl Into<String>) -> Vec<u8> { pub fn from_string_to_vec_bits(raw_data: String) -> Vec<u8> {
raw_data raw_data
.into()
.as_bits::<Lsb0>() .as_bits::<Lsb0>()
.iter() .iter()
.step_by(8) .step_by(8)

View File

@ -1,3 +1,4 @@
pub mod hamming_code_utils; pub mod hamming_code_input_utils;
pub mod input_utils; pub mod input_utils;
pub mod signal_reduce_utils; pub mod signal_reduce_input_utils;

View File

@ -0,0 +1,44 @@
use gtk4 as gtk;
use std::{num::ParseFloatError, str::FromStr};
use gtk::{
prelude::{TextBufferExt, TextViewExt},
TextBuffer,
};
use crate::{model::models::SignalReduce, view::components::input::Input};
pub fn get_error_message(error_instance: ParseFloatError) -> Option<&'static str> {
match error_instance.to_string().as_str() {
"cannot parse float from empty string" => Some("Вы не ввели данные в поле/-я"),
"invalid float literal" => Some("Вы ввели не корректные данные в поле/-я"),
_ => None,
}
}
pub fn parse_fields(all_inputs: Vec<Input>) -> Result<SignalReduce, ParseFloatError> {
let mut values: [f64; 6] = [0f64; 6];
for (i, input) in all_inputs.iter().enumerate() {
let input_text_buffer: TextBuffer = input.clone().get_input().buffer();
let try_extract_value = f64::from_str(
input_text_buffer
.text(
&input_text_buffer.start_iter(),
&input_text_buffer.end_iter(),
false,
)
.as_str()
.trim(),
);
match try_extract_value {
Ok(value) => values[i] = value,
Err(error) => return Err(error),
}
}
Ok(SignalReduce(
values[0], values[1], values[2], values[3], values[4], values[5],
))
}

View File

@ -1,124 +0,0 @@
use gio::glib::Object;
use std::str::FromStr;
use crate::{
model::{models::SignalReduce, Error, Frequency, Result},
model_utils::signal_reducer::*,
view::components::input::Input,
};
use gtk::{
prelude::{Cast, CastNone, EditableExt, ListItemExt, WidgetExt},
ColumnView, Entry, Label, ListItem, SignalListItemFactory,
};
pub fn get_error_message(error: Error) -> Option<&'static str> {
match error.to_string().as_str() {
"cannot parse float from empty string" => Some("Вы не ввели данные в поле/-я"),
"invalid float literal" => Some("Вы ввели не корректные данные в поле/-я"),
_ => None,
}
}
pub fn parse_fields(all_inputs: Vec<Input<Entry>>) -> Result<SignalReduce> {
let mut values: [f64; 6] = [0.0; 6];
for (i, input) in all_inputs.iter().enumerate() {
let input_text_buffer = input.get_input();
let extracted_value =
f64::from_str(input_text_buffer.text().replace(',', ".").as_str().trim())?;
values[i] = extracted_value;
}
Ok(SignalReduce {
length: values[0],
wire_resistance: values[1],
wire_capacity: values[2],
source_resistance: values[3],
source_voltage: values[4],
frequency: values[5],
})
}
#[inline]
pub fn update_column_view(column_view: &ColumnView) {
column_view.set_visible(false);
column_view.set_visible(true);
}
#[inline]
pub fn column_view_setup_factory(_factory: &SignalListItemFactory, list_item: &Object) {
list_item
.downcast_ref::<ListItem>()
.expect("Needs to be ListItem")
.set_child(Some(&Label::new(None)));
}
pub fn get_cell_data(list_item: &Object) -> (Frequency, Label) {
let cell_value = list_item
.downcast_ref::<ListItem>()
.expect("Needs to be ListItem")
.item()
.and_downcast::<Frequency>()
.expect("The item has to be an `IntegerObject`.");
let cell_label = list_item
.downcast_ref::<ListItem>()
.expect("Needs to be ListItem")
.child()
.and_downcast::<Label>()
.expect("The child has to be a `Label`.");
cell_label.set_selectable(true);
(cell_value, cell_label)
}
pub fn frequency_column_fabric(list_item: &Object) {
let (cell_value, cell_label) = get_cell_data(list_item);
cell_label.set_label(&cell_value.frequency().to_string());
}
pub fn reactive_resist_fabric(list_item: &Object, values: SignalReduce) {
let (cell_value, cell_label) = get_cell_data(list_item);
cell_value.set_reactive_resist(reactive_resistance_of_capacitor(
values.wire_capacity * 10f64.powi(-12),
values.length,
cell_value.frequency() * 10f64.powi(6),
));
cell_label.set_label(format!("{0:.1$}", cell_value.reactive_resist(), 6).as_str());
}
pub fn signal_source_voltage_fabric(list_item: &Object, values: SignalReduce) {
let (cell_value, cell_label) = get_cell_data(list_item);
cell_value.set_full_resistance(full_resistance_of_capacitor(
cell_value.reactive_resist(),
values.source_resistance,
values.wire_resistance,
values.length,
));
cell_value.set_signal_source_voltage(
voltage_from_signal_source(
values.source_voltage * 10f64.powi(-3),
cell_value.reactive_resist(),
cell_value.full_resistance(),
) * 1000.0,
);
cell_label.set_label(format!("{0:.1$}", cell_value.signal_source_voltage(), 6).as_str());
}
pub fn coef_fabric(list_item: &Object, values: SignalReduce) {
let (cell_value, cell_label) = get_cell_data(list_item);
let coef: f64 =
coef_of_signal_reduce(values.source_voltage, cell_value.signal_source_voltage());
cell_label.set_label(format!("{0:.1$}", coef, 6).as_str());
}

View File

@ -1,6 +1,4 @@
#![windows_subsystem = "windows"] use gtk4 as gtk;
extern crate gio;
use gtk::prelude::*; use gtk::prelude::*;
@ -9,12 +7,12 @@ mod model;
mod view; mod view;
use controller::*; use controller::*;
use view::ui::*; use view::view::*;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let app: adw::Application = adw::Application::builder() let app: adw::Application = adw::Application::builder()
.application_id("org.gtk-rs.AIT") .application_id("com.github.gtk-rs.examples.basic")
.build(); .build();
app.connect_activate(ui); app.connect_activate(ui);

View File

@ -1,10 +1,9 @@
pub trait Product<B, T> { pub trait Product<B, T> {
fn builder() -> B; fn builder() -> B;
fn get(&self) -> &T; fn get(self) -> T;
} }
#[allow(dead_code)]
pub trait Builder<T, I, P> { pub trait Builder<T, I, P> {
fn build(&self, build_arg: P) -> T; fn build(&self, build_arg: P) -> T;

View File

@ -1,21 +1,15 @@
pub mod builder_traits; pub mod builder_traits;
pub mod models; pub mod models;
use gtk::glib::{Object, wrapper}; use crate::gtk::glib;
use glib::Object;
pub type Result<T> = core::result::Result<T, Error>; glib::wrapper! {
pub type Error = std::boxed::Box<dyn std::error::Error>; pub struct ResultValue(ObjectSubclass<models::ResultValue>);
wrapper! {
pub struct Frequency(ObjectSubclass<models::Frequency>);
} }
impl Frequency { impl ResultValue {
pub fn new(frequency: f64) -> Self { pub fn new(val: f64) -> Self {
Object::builder().property("frequency", frequency).build() Object::builder().property("value", val).build()
}
pub fn default() -> Self {
Object::new()
} }
} }

View File

@ -1,10 +1,11 @@
use std::cell::Cell; use std::cell::Cell;
use gtk::{ use crate::gtk;
glib::{self, Properties},
prelude::*, use glib::Properties;
subclass::prelude::*, use gtk::glib;
}; use gtk::prelude::*;
use gtk::subclass::prelude::*;
#[repr(usize)] #[repr(usize)]
#[derive(Clone)] #[derive(Clone)]
@ -13,35 +14,33 @@ pub enum HammingMode {
Decrypt = 7, Decrypt = 7,
} }
#[allow(dead_code)] pub struct EventHandler<F, C> {
#[derive(Default, Copy, Clone, Debug, PartialEq)] pub(crate) component: C,
pub struct SignalReduce { pub(crate) callback: F,
pub length: f64, }
pub wire_resistance: f64,
pub wire_capacity: f64, #[derive(Default, Copy, Clone)]
pub source_voltage: f64, pub struct SignalReduce(pub f64, pub f64, pub f64, pub f64, pub f64, pub f64);
pub source_resistance: f64,
pub frequency: f64, impl SignalReduce {
pub fn new() -> Self {
Self(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
}
} }
#[derive(Properties, Default)] #[derive(Properties, Default)]
#[properties(wrapper_type = super::Frequency)] #[properties(wrapper_type = super::ResultValue)]
pub struct Frequency { pub struct ResultValue {
#[property(get, set)] #[property(get, set)]
frequency: Cell<f64>, value: Cell<f64>,
#[property(get, set)] }
reactive_resist: Cell<f64>,
#[property(get, set)] // The central trait for subclassing a GObject
full_resistance: Cell<f64>, #[glib::object_subclass]
#[property(get, set)] impl ObjectSubclass for ResultValue {
signal_source_voltage: Cell<f64>, const NAME: &'static str = "MyGtkAppCustomButton";
type Type = super::ResultValue;
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for Frequency {} impl ObjectImpl for ResultValue {}
#[glib::object_subclass]
impl ObjectSubclass for Frequency {
const NAME: &'static str = "FrequencyValue";
type Type = super::Frequency;
}

View File

@ -1,68 +0,0 @@
use adw::HeaderBar;
use gio::{glib::Variant, SimpleAction};
use gtk::{
prelude::{BoxExt, GtkWindowExt},
AboutDialog, Box, Image, Label, Orientation, ScrolledWindow, Window, License, NaturalWrapMode, PolicyType
};
use std::path::Path;
use crate::view::properties::Setters;
#[cfg(debug_assertions)]
const PATH: &str = "./src/view/resources/logo.png";
#[cfg(not(debug_assertions))]
const PATH: &str = "./resources/logo.png";
pub fn open_about_dialogue(_action: &SimpleAction, _var: Option<&Variant>) {
let logo = Image::from_file(Path::new(PATH)).paintable().unwrap();
AboutDialog::builder()
.authors(vec!["Сагиев А.Д.", "Ефимов И.П."])
.version("1.0-beta")
.program_name("Прикладная теория информации")
.license_type(License::Apache20)
.logo(&logo)
.website("https://gitea.doryan04.ru/doryan/AIT")
.build()
.present();
}
pub fn open_help_dialogue(_action: &SimpleAction, _var: Option<&Variant>) {
let help = Box::builder()
.width_request(400)
.orientation(Orientation::Vertical)
.set_margin(crate::view::properties::MarginData::EqualsMargin(15))
.build();
let label = Label::builder()
.use_markup(true)
.wrap(true)
.width_request(400)
.max_width_chars(50)
.single_line_mode(false)
.natural_wrap_mode(NaturalWrapMode::Word)
.label(crate::view::resources::HELP)
.build();
help.append(&label);
let scrollable = ScrolledWindow::builder()
.child(&help)
.hscrollbar_policy(PolicyType::Never)
.build();
let custom_header = HeaderBar::new();
Window::builder()
.width_request(800)
.height_request(600)
.name("help")
.title("Помощь")
.titlebar(&custom_header)
.child(&scrollable)
.build()
.present();
}

View File

@ -1,14 +1,17 @@
use gio::glib::clone; use gtk4 as gtk;
use std::{collections::VecDeque, sync::LazyLock}; use std::{collections::VecDeque, sync::LazyLock};
use gtk::{ use gtk::{
builders::{BoxBuilder, ButtonBuilder, LabelBuilder}, builders::{BoxBuilder, ButtonBuilder, LabelBuilder},
prelude::{BoxExt, ButtonExt, ObjectExt, WidgetExt}, prelude::{BoxExt, ObjectExt, WidgetExt},
Box, Button, Label, Revealer, RevealerTransitionType Box, Button, Label, Revealer, RevealerTransitionType,
}; };
use crate::model::builder_traits::Product; use crate::{
event_handlers::button_event_handlers::BtnEventHandler,
model::{builder_traits::Product, models::EventHandler},
};
use tokio::{ use tokio::{
task::{spawn, JoinHandle}, task::{spawn, JoinHandle},
@ -26,6 +29,8 @@ pub struct InfoBarBuilder {
button: ButtonBuilder, button: ButtonBuilder,
} }
// TODO: Develop a method to safely mutate static.
// Not necessary.
static mut TASKS_QUEUE: VecDeque<JoinHandle<()>> = VecDeque::new(); static mut TASKS_QUEUE: VecDeque<JoinHandle<()>> = VecDeque::new();
// //
@ -94,20 +99,21 @@ impl InfoBarBuilder {
info_bar_box.append(&info_bar_label); info_bar_box.append(&info_bar_label);
info_bar_box.append(&info_bar_close_btn); info_bar_box.append(&info_bar_close_btn);
info_bar_box.set_widget_name("info_bar");
let info_bar: &Revealer = &INFO_BAR_INSTANCE.instance; let info_bar: &Revealer = &INFO_BAR_INSTANCE.instance;
info_bar.set_transition_type(RevealerTransitionType::SlideUp); info_bar.set_transition_type(RevealerTransitionType::SlideUp);
info_bar.set_transition_duration(200); info_bar.set_transition_duration(200);
info_bar.set_child(Some(&info_bar_box));
info_bar.set_widget_name("infobar");
info_bar.set_css_classes(&[".warning"]);
info_bar_close_btn.connect_clicked(clone!( info_bar.set_child(Some(&info_bar_box));
#[strong]
info_bar, let info_bar_to_close = info_bar.clone();
move |_| info_bar.set_reveal_child(false)
)); EventHandler::new(info_bar_close_btn.clone(), move |_| {
info_bar_to_close.set_reveal_child(false);
})
.on_click();
&INFO_BAR_INSTANCE &INFO_BAR_INSTANCE
} }
@ -125,7 +131,7 @@ impl InfoBarBuilder {
} }
} }
impl Product<InfoBarBuilder, Revealer> for InfoBar { impl Product<InfoBarBuilder, &'static Revealer> for InfoBar {
fn builder() -> InfoBarBuilder { fn builder() -> InfoBarBuilder {
InfoBarBuilder { InfoBarBuilder {
label: Label::builder(), label: Label::builder(),
@ -134,7 +140,7 @@ impl Product<InfoBarBuilder, Revealer> for InfoBar {
} }
} }
fn get(&self) -> &'static Revealer { fn get(self) -> &'static Revealer {
&INFO_BAR_INSTANCE.instance &INFO_BAR_INSTANCE.instance
} }
} }

View File

@ -1,59 +1,23 @@
use gtk4 as gtk;
use crate::{model::builder_traits::*, view::properties::*}; use crate::{model::builder_traits::*, view::properties::*};
use gtk::{prelude::*, *}; use gtk::{prelude::*, *};
pub type InputLabel = String; pub type InputLabel = String;
macro_rules! build_for { #[derive(Clone)]
( $(($comp:ty,$name:ident)),* ) => { pub struct Input {
$(
pub fn $name(self, input_height: Option<i32>) -> Input<$comp> {
let input_component = Box::new(Orientation::Vertical, 0);
let input_label = Label::builder()
.halign(self.align.horizontal)
.valign(self.align.vertical)
.set_margin(self.margins)
.use_markup(self.markup)
.label(self.label)
.build();
let mut input_builder = <$comp>::builder()
.set_margin(MarginData::EqualsMargin(6));
if let Some(height) = input_height {
input_builder = input_builder.height_request(height);
}
let input = input_builder.build();
input_component.append(&input_label);
input_component.append(&input);
Input {
component: input_component,
input: input.clone(),
input_label: input_label.clone(),
}
}
)*
};
}
#[derive(Clone, Debug)]
pub struct Input<I> {
component: Box, component: Box,
input: I, input: TextView,
input_label: Label,
} }
pub struct InputBuilder { pub struct InputBuilder {
align: Alignment, align: Alignment,
label: InputLabel, label: InputLabel,
margins: MarginData, margins: MarginData,
markup: bool,
} }
impl<I> Product<InputBuilder, Box> for Input<I> { impl Product<InputBuilder, Box> for Input {
fn builder() -> InputBuilder { fn builder() -> InputBuilder {
InputBuilder { InputBuilder {
align: Alignment { align: Alignment {
@ -62,53 +26,67 @@ impl<I> Product<InputBuilder, Box> for Input<I> {
}, },
label: String::new(), label: String::new(),
margins: MarginData::EqualsMargin(5), margins: MarginData::EqualsMargin(5),
markup: false,
} }
} }
fn get(&self) -> &Box { fn get(self) -> Box {
&self.component self.component
} }
} }
impl<I> Input<I> { impl Input {
pub fn get_component(&self) -> &Box { pub fn get_input(self) -> TextView {
&self.component self.input
}
pub fn get_input(&self) -> &I {
&self.input
}
pub fn get_label(&self) -> &Label {
&self.input_label
} }
} }
impl InputBuilder { impl InputBuilder {
pub fn label(mut self, label: &str) -> Self { pub fn set_label(mut self, label: &str) -> Self {
self.label = label.into(); self.label = String::from(label);
self self
} }
pub fn markup(mut self, toggle: bool) -> Self { pub fn set_align(mut self, align: Alignment) -> Self {
self.markup = toggle;
self
}
pub fn align(mut self, align: Alignment) -> Self {
self.align = align; self.align = align;
self self
} }
pub fn margins(mut self, margin: MarginData) -> Self { pub fn set_margins(mut self, margin: MarginData) -> Self {
self.margins = margin; self.margins = margin;
self self
} }
build_for!((TextView, build), (Entry, build_entry)); pub fn build(self, monospace: bool, wrap_mode: WrapMode, input_height: i32) -> Input {
let input_component = Box::new(Orientation::Vertical, 0);
let input_label = Label::builder()
.halign(self.align.horizontal)
.valign(self.align.vertical)
.set_margin(self.margins)
.label(self.label)
.build();
let text_view_input = TextView::builder()
.monospace(monospace)
.height_request(input_height)
.set_text_view_margin(MarginData::EqualsMargin(6))
.wrap_mode(wrap_mode)
.build();
let text_view_input_frame = Frame::builder()
.child(&text_view_input)
.set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
.build();
input_component.append(&input_label);
input_component.append(&text_view_input_frame);
Input {
component: input_component,
input: text_view_input,
}
}
} }

View File

@ -1,79 +0,0 @@
use std::fmt::{Debug, Display};
use gio::{
glib::Variant, prelude::ActionMapExtManual, ActionEntry, Menu, SimpleAction, SimpleActionGroup,
};
use gtk::{MenuButton, PopoverMenu};
pub struct HeaderMenu<T> {
model: Menu,
actions_group: (SimpleActionGroup, Option<T>),
button: MenuButton,
}
impl<T> HeaderMenu<T>
where
T: Into<String> + Debug + Display + Clone,
{
pub fn new() -> Self {
let menu_btn = MenuButton::builder().icon_name("open-menu").build();
let menu_model = Menu::new();
let menu_popover = PopoverMenu::from_model(Some(&menu_model));
menu_btn.set_popover(Some(&menu_popover));
let action_group = SimpleActionGroup::new();
Self {
model: menu_model,
actions_group: (action_group, None),
button: menu_btn,
}
}
#[inline]
pub fn set_action_group_name(&mut self, name: Option<T>) {
self.actions_group.1 = name;
}
#[inline]
pub fn get_button(&self) -> &MenuButton {
&self.button
}
#[inline]
pub fn get_model(&self) -> &Menu {
&self.model
}
#[inline]
pub fn get_actions_group(&self) -> &SimpleActionGroup {
&self.actions_group.0
}
pub fn append_items<F, I>(&self, items: I)
where
F: Fn(&SimpleAction, Option<&Variant>) + 'static,
I: IntoIterator<Item = &'static (F, &'static str, &'static str)>,
{
for (callback, action_name, action_label) in items {
let action = ActionEntry::<SimpleActionGroup>::builder(action_name)
.activate(move |_, a, b| callback(a, b))
.build();
let action_path = &*format!(
"{}.{}",
self.actions_group
.1
.clone()
.expect("ActionGroupName isn't defined"),
action_name
);
self.actions_group.0.add_action_entries([action]);
self.model.append(Some(action_label), Some(action_path));
}
}
}

View File

@ -1,12 +1,8 @@
pub mod dialogues;
pub mod info_bar; pub mod info_bar;
pub mod input; pub mod input;
pub mod menu;
pub mod pages; pub mod pages;
pub mod switch;
pub mod tabs; pub mod tabs;
pub mod wrapper;
pub type MenuActions<'a> = (fn(&SimpleAction, Option<&Variant>), &'a str, &'a str);
use gio::{glib::Variant, SimpleAction};
use crate::model::builder_traits; use crate::model::builder_traits;

View File

@ -1,6 +1,8 @@
use gtk4::{self as gtk, prelude::WidgetExt, Align};
#[allow(unused)] #[allow(unused)]
use gtk::{ use gtk::{
prelude::{BoxExt, IsA, WidgetExt}, prelude::{BoxExt, IsA},
Box, Orientation, Stack, StackSidebar, StackSwitcher, StackTransitionType, Widget, Box, Orientation, Stack, StackSidebar, StackSwitcher, StackTransitionType, Widget,
}; };
@ -23,8 +25,8 @@ impl Product<PagesBuilder, Box> for Pages {
} }
} }
fn get(&self) -> &Box { fn get(self) -> Box {
&self.wrapper self.wrapper
} }
} }

View File

@ -0,0 +1,150 @@
use gtk4 as gtk;
use gtk::{*, prelude::*};
use glib::{
signal::{connect_raw, SignalHandlerId},
translate::*,
};
use std::boxed::Box as Box_;
mod sealed {
pub trait Sealed {}
impl<T: super::IsA<super::Switch>> Sealed for T {}
}
pub trait SwitchExt: IsA<Switch> + sealed::Sealed + 'static {
#[doc(alias = "gtk_switch_get_active")]
#[doc(alias = "get_active")]
fn is_active(&self) -> bool {
unsafe { from_glib(ffi::gtk_switch_get_active(self.as_ref().to_glib_none().0)) }
}
#[doc(alias = "gtk_switch_get_state")]
#[doc(alias = "get_state")]
fn state(&self) -> bool {
unsafe { from_glib(ffi::gtk_switch_get_state(self.as_ref().to_glib_none().0)) }
}
#[doc(alias = "gtk_switch_set_active")]
fn set_active(&self, is_active: bool) {
unsafe {
ffi::gtk_switch_set_active(self.as_ref().to_glib_none().0, is_active.into_glib());
}
}
#[doc(alias = "gtk_switch_set_state")]
fn set_state(&self, state: bool) {
unsafe {
ffi::gtk_switch_set_state(self.as_ref().to_glib_none().0, state.into_glib());
}
}
#[doc(alias = "activate")]
fn connect_activate<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
unsafe extern "C" fn activate_trampoline<P: IsA<Switch>, F: Fn(&P) + 'static>(
this: *mut ffi::GtkSwitch,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(Switch::from_glib_borrow(this).unsafe_cast_ref())
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
b"activate\0".as_ptr() as *const _,
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
activate_trampoline::<Self, F> as *const (),
)),
Box_::into_raw(f),
)
}
}
fn emit_activate(&self) {
self.emit_by_name::<()>("activate", &[]);
}
#[doc(alias = "state-set")]
fn connect_state_set<F: Fn(&Self, bool) -> glib::Propagation + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn state_set_trampoline<
P: IsA<Switch>,
F: Fn(&P, bool) -> glib::Propagation + 'static,
>(
this: *mut ffi::GtkSwitch,
state: glib::ffi::gboolean,
f: glib::ffi::gpointer,
) -> glib::ffi::gboolean {
let f: &F = &*(f as *const F);
f(
Switch::from_glib_borrow(this).unsafe_cast_ref(),
from_glib(state),
)
.into_glib()
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
b"state-set\0".as_ptr() as *const _,
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
state_set_trampoline::<Self, F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "active")]
fn connect_active_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
unsafe extern "C" fn notify_active_trampoline<P: IsA<Switch>, F: Fn(&P) + 'static>(
this: *mut ffi::GtkSwitch,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(Switch::from_glib_borrow(this).unsafe_cast_ref())
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
b"notify::active\0".as_ptr() as *const _,
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
notify_active_trampoline::<Self, F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "state")]
fn connect_state_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
unsafe extern "C" fn notify_state_trampoline<P: IsA<Switch>, F: Fn(&P) + 'static>(
this: *mut ffi::GtkSwitch,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(Switch::from_glib_borrow(this).unsafe_cast_ref())
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
b"notify::state\0".as_ptr() as *const _,
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
notify_state_trampoline::<Self, F> as *const (),
)),
Box_::into_raw(f),
)
}
}
}
impl<O: IsA<Switch>> SwitchExt for O {}

View File

@ -1,3 +1,5 @@
use gtk4 as gtk;
use super::builder_traits::*; use super::builder_traits::*;
use gtk::{Box, Label, Notebook}; use gtk::{Box, Label, Notebook};
@ -19,8 +21,8 @@ impl Product<TabsBuilder, Notebook> for Tabs {
TabsBuilder { tabs: Vec::new() } TabsBuilder { tabs: Vec::new() }
} }
fn get(&self) -> &Notebook { fn get(self) -> Notebook {
&self.tabs_wrapper self.tabs_wrapper
} }
} }
@ -56,3 +58,4 @@ impl TabsBuilder {
self.tabs.push((tab_label, item.1)); self.tabs.push((tab_label, item.1));
} }
} }

View File

@ -0,0 +1,18 @@
use gtk4 as gtk;
use gtk::{Orientation, builders::BoxBuilder, Box};
#[allow(dead_code)]
pub struct Wrapper;
impl Wrapper{
pub fn row_builder() -> BoxBuilder {
Box::builder().orientation(Orientation::Vertical)
}
pub fn col_builder() -> BoxBuilder {
Box::builder().orientation(Orientation::Horizontal)
}
}

View File

@ -1,6 +1,5 @@
pub mod components; pub mod components;
pub mod pages; pub mod pages;
pub mod properties; pub mod properties;
pub mod resources;
pub mod styles; pub mod styles;
pub mod ui; pub mod view;

View File

@ -1,35 +1,60 @@
use gtk4 as gtk;
use crate::{ use crate::{
model::builder_traits::Product, controller::{
view::{ controller::*,
components::{info_bar::InfoBar, input::Input}, event_handlers::{button_event_handlers::*, switch_event_handlers::*},
properties::*, view_utils::{hamming_code_input_utils::*, input_utils::*},
}, },
view_utils::{hamming_code_utils::start_hamming_algorithm, input_utils::clearing}, model::models::*,
view::{components::wrapper::*, properties::*},
}; };
use gtk::{glib::clone, prelude::*, *}; use gtk::{prelude::*, *};
pub fn hamming_code_page(wrapper: &Box) { pub fn hamming_code_page(wrapper: &Box) {
let info_bar = InfoBar::get_instance(); // input
let input_code = Input::<TextView>::builder() let hamming_text_view_input_label = Label::builder()
.label("Поле ввода для кода:") .halign(Align::Start)
.margins(MarginData::EqualsMargin(6)) .set_margin(MarginData::MultipleMargin((10, 5, 0, 0)))
.align(Alignment::new(Align::Start, Align::Start)) .label(String::from("Поле ввода для кода:"))
.build(Some(64)); .build();
let output_code = Input::<TextView>::builder() let hamming_text_view_input = TextView::builder()
.label("Результат:") .monospace(true)
.margins(MarginData::EqualsMargin(6)) .set_text_view_margin(MarginData::EqualsMargin(6))
.align(Alignment::new(Align::Start, Align::Start)) .wrap_mode(WrapMode::Word)
.build(Some(64)); .build();
output_code.get_input().set_editable(false); let hamming_text_view_input_frame = Frame::builder()
.child(&hamming_text_view_input)
.height_request(64)
.set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
.build();
for input in [&input_code, &output_code] { // output
input.get_input().set_monospace(true);
input.get_input().set_wrap_mode(WrapMode::Word); let hamming_text_view_output_label = Label::builder()
} .halign(Align::Start)
.set_margin(MarginData::MultipleMargin((10, 5, 0, 0)))
.label(String::from("Результат:"))
.build();
let hamming_text_view_output = TextView::builder()
.monospace(true)
.editable(false)
.set_text_view_margin(MarginData::EqualsMargin(6))
.wrap_mode(WrapMode::Word)
.build();
let hamming_text_view_output_frame = Frame::builder()
.child(&hamming_text_view_output)
.height_request(64)
.set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
.build();
// interactive panel
let clear_input_button = Button::builder() let clear_input_button = Button::builder()
.set_align(Alignment::new(Align::Fill, Align::Fill)) .set_align(Alignment::new(Align::Fill, Align::Fill))
@ -45,74 +70,67 @@ pub fn hamming_code_page(wrapper: &Box) {
let crypt_mode_label = Label::builder().label("Режим: кодирование").build(); let crypt_mode_label = Label::builder().label("Режим: кодирование").build();
let crypt_mode_wrapper = Box::builder() // references for binding actions
.orientation(Orientation::Horizontal)
let clear_input_button_to_handle = clear_input_button.clone();
let crypt_mode_label_to_handle = crypt_mode_label.clone();
let crypt_mode_switch_to_handle = crypt_mode_switch.clone();
let text_view_input_for_parse = hamming_text_view_input.clone();
let text_view_output_for_output = hamming_text_view_output.clone();
let text_view_input_for_clearing = hamming_text_view_input.clone();
let text_view_output_for_clearing = hamming_text_view_output.clone();
// actions
EventHandler::new(clear_input_button_to_handle, move |_| {
clearing(
&text_view_input_for_clearing,
&text_view_output_for_clearing,
);
})
.on_click();
EventHandler::new(hamming_crypt_button.clone(), move |_button: &Button| {
start_hamming_algorithm(
&text_view_input_for_parse,
&text_view_output_for_output,
crypt_mode_switch_to_handle.state(),
)
})
.on_click();
EventHandler::new(crypt_mode_switch.clone(), move |s: &Switch| {
state_controller(s, &crypt_mode_label_to_handle);
})
.on_toggle();
// wrappers
let crypt_mode_wrapper = Wrapper::col_builder()
.set_align(Alignment::new(Align::Fill, Align::Center)) .set_align(Alignment::new(Align::Fill, Align::Center))
.hexpand(true) .hexpand(true)
.spacing(10) .spacing(10)
.build(); .build();
let action_components_wrapper = Box::builder() let interactive_components_wrapper = Wrapper::col_builder()
.orientation(Orientation::Horizontal)
.set_align(Alignment::new(Align::Fill, Align::Fill)) .set_align(Alignment::new(Align::Fill, Align::Fill))
.set_margin(MarginData::MultipleMargin((0, 5, 0, 5))) .set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
.spacing(10) .spacing(10)
.build(); .build();
crypt_mode_switch.connect_state_set(clone!(
#[strong]
crypt_mode_label,
move |_, toggled| {
if toggled {
crypt_mode_label.set_label("Режим: проверка");
} else {
crypt_mode_label.set_label("Режим: кодирование");
}
glib::Propagation::Proceed
}
));
clear_input_button.connect_clicked(clone!(
#[strong]
input_code,
#[strong]
output_code,
move |_| {
clearing(input_code.get_input(), output_code.get_input());
}
));
hamming_crypt_button.connect_clicked(clone!(
#[strong]
input_code,
#[strong]
output_code,
#[strong]
crypt_mode_switch,
#[strong]
info_bar,
move |_| {
let result = start_hamming_algorithm(input_code.get_input(), crypt_mode_switch.state());
match result {
Ok(result) => {
output_code.get_input().buffer().set_text(result.trim_end());
}
Err(reject) => {
info_bar.set_text_label(Some(&*format!("{reject}")));
info_bar.show_infobar(5);
}
}
}
));
crypt_mode_wrapper.append(&crypt_mode_switch); crypt_mode_wrapper.append(&crypt_mode_switch);
crypt_mode_wrapper.append(&crypt_mode_label); crypt_mode_wrapper.append(&crypt_mode_label);
action_components_wrapper.append(&clear_input_button); interactive_components_wrapper.append(&clear_input_button);
action_components_wrapper.append(&crypt_mode_wrapper); interactive_components_wrapper.append(&crypt_mode_wrapper);
action_components_wrapper.append(&hamming_crypt_button); interactive_components_wrapper.append(&hamming_crypt_button);
wrapper.append(input_code.get()); wrapper.append(&hamming_text_view_input_label);
wrapper.append(&action_components_wrapper); wrapper.append(&hamming_text_view_input_frame);
wrapper.append(output_code.get()); wrapper.append(&interactive_components_wrapper);
wrapper.append(&hamming_text_view_output_label);
wrapper.append(&hamming_text_view_output_frame);
} }

View File

@ -1,29 +1,39 @@
use std::{cell::Cell, rc::Rc}; use std::{cell::Cell, rc::Rc};
use crate::{ use crate::{
model::{builder_traits::Product, models::SignalReduce, Frequency}, event_handlers::button_event_handlers::BtnEventHandler,
model_utils::signal_reducer::{find_by_frequency_value, set_default_values}, model::{
builder_traits::Product,
models::{EventHandler, SignalReduce},
ResultValue,
},
model_utils::signal_reducer::{
coef_of_signal_reduce, full_resistance_of_capacitor, reactive_resistance_of_capacitor,
voltage_from_signal_source,
},
view::{ view::{
components::{info_bar::InfoBar, input::Input}, components::{info_bar::InfoBar, input::Input},
properties::*, properties::*,
}, },
view_utils::signal_reduce_utils::*, view_utils::signal_reduce_input_utils::{get_error_message, parse_fields},
}; };
use glib::clone;
use gio::ListStore;
use gtk::{ use gtk::{
prelude::{BoxExt, ButtonExt, Cast, GridExt, SorterExt}, prelude::{BoxExt, Cast, CastNone, GridExt, ListItemExt},
Align, *, Align, WrapMode, *,
}; };
use gtk4 as gtk;
pub fn signal_reducing_page(wrapper: &Box) { pub fn signal_reducing_page(wrapper: &Box) {
let values = Rc::new(Cell::new(SignalReduce::default())); let values = Rc::new(Cell::new(SignalReduce::default()));
let last_query: Vec<TreeIter> = Vec::new();
let info_bar = InfoBar::get_instance(); let info_bar = InfoBar::get_instance();
let (input_height, monospace, input_wrapping): (i32, bool, WrapMode) =
(24, true, WrapMode::Word);
let input_block: Grid = Grid::new(); let input_block: Grid = Grid::new();
input_block.set_column_homogeneous(true); input_block.set_column_homogeneous(true);
@ -36,80 +46,118 @@ pub fn signal_reducing_page(wrapper: &Box) {
let input_labels: [&str; 6] = [ let input_labels: [&str; 6] = [
"l, м:", "l, м:",
"R<sub>м</sub>, Ом", "Rм, Ом:",
"C<sub>м</sub>, пФ:", "Cм, пФ:",
"R<sub>и</sub>, Ом:", "Vи, мВ",
"V<sub>и</sub>, мВ", "Rи, Ом:",
"f, мГц:", "f, мГц:",
]; ];
let all_inputs: Vec<Input<Entry>> = input_labels let all_inputs: Vec<Input> = input_labels
.iter() .iter()
.enumerate() .map(move |label| {
.map(|(index, label)| { Input::builder()
let elem = Input::<Entry>::builder() .set_label(label)
.label(label) .set_margins(MarginData::EqualsMargin(5))
.markup(true) .set_align(input_label_alignment)
.margins(MarginData::EqualsMargin(6)) .build(monospace, input_wrapping, input_height)
.align(input_label_alignment)
.build_entry(None);
let row = index as i32 / 3;
input_block.attach(elem.get(), (index as i32) - (3 * row), row, 1, 1);
elem
}) })
.collect(); .collect();
let mut row_position = 0i32;
for (id, elem) in all_inputs.iter().enumerate() {
if id % 3 == 0 {
row_position += 1;
}
input_block.attach(
&elem.clone().get(),
(id as i32) - (3 * row_position),
row_position,
1,
1,
);
}
let calculate_button = Button::builder().label("Расчитать").build(); let calculate_button = Button::builder().label("Расчитать").build();
let result_table_headers_labels: [&str; 4] = ["f, МГц", "Xc, Ом", "Vп, мВ", "ζ"]; let result_table_headers_labels: [&str; 4] = ["f, МГц", "Xc, пФ", "Vп, мВ", "ζ"];
let model = ListStore::new::<Frequency>(); let model = gio::ListStore::new::<ResultValue>();
set_default_values(&model); let cloned_model = model.clone();
let numeric_sorter = CustomSorter::new(|a, b| { let selection_model = SingleSelection::new(Some(model));
let a = a.downcast_ref::<Frequency>().unwrap().frequency();
let b = b.downcast_ref::<Frequency>().unwrap().frequency();
a.total_cmp(&b).into()
});
let sorted_model = SortListModel::new(Some(model.clone()), Some(numeric_sorter.clone()));
let selection_model = NoSelection::new(Some(sorted_model.clone()));
let result_table = ColumnView::builder() let result_table = ColumnView::builder()
.show_row_separators(true) .reorderable(true)
.model(&selection_model) .model(&selection_model)
.build(); .build();
result_table.connect_activate(clone!(
#[strong]
numeric_sorter,
move |_, _| numeric_sorter.changed(SorterChange::Different)
));
for label in result_table_headers_labels { for label in result_table_headers_labels {
let factory = SignalListItemFactory::new(); let factory = SignalListItemFactory::new();
factory.connect_setup(column_view_setup_factory); factory.connect_setup(move |_, list_item| {
list_item
.downcast_ref::<ListItem>()
.expect("Needs to be ListItem")
.set_child(Some(&Label::new(None)));
});
let values_for_factory = values.clone();
factory.connect_bind(move |_, list_item| {
let cell_value = list_item
.downcast_ref::<ListItem>()
.expect("Needs to be ListItem")
.item()
.and_downcast::<ResultValue>()
.expect("The item has to be an `IntegerObject`.");
let cell_label = list_item
.downcast_ref::<ListItem>()
.expect("Needs to be ListItem")
.child()
.and_downcast::<Label>()
.expect("The child has to be a `Label`.");
let result_values = values_for_factory.clone().get();
let reactive_resist: f64 = reactive_resistance_of_capacitor(
result_values.2,
result_values.0,
cell_value.value(),
);
let full_resistance: f64 = full_resistance_of_capacitor(
reactive_resist,
result_values.4,
result_values.1,
result_values.0,
);
let signal_source_voltage: f64 =
voltage_from_signal_source(result_values.3, reactive_resist, full_resistance);
let coef: f64 = coef_of_signal_reduce(signal_source_voltage, signal_source_voltage);
factory.connect_bind(clone!(
#[strong]
values,
move |_, list| {
match label { match label {
"f, МГц" => frequency_column_fabric(list), "f, МГц" => {
"Xc, Ом" => reactive_resist_fabric(list, values.get()), cell_label.set_label(&cell_value.value().to_string());
"Vп, мВ" => signal_source_voltage_fabric(list, values.get()), }
"ζ" => coef_fabric(list, values.get()), "Xc, пФ" => {
cell_label.set_label(&reactive_resist.to_string());
}
"Vп, мВ" => {
cell_label.set_label(&signal_source_voltage.to_string());
}
"ζ" => {
cell_label.set_label(&coef.to_string());
}
_ => {} _ => {}
} }
} });
));
let column = ColumnViewColumn::builder() let column = ColumnViewColumn::builder()
.title(label) .title(label)
@ -131,26 +179,14 @@ pub fn signal_reducing_page(wrapper: &Box) {
.vexpand(true) .vexpand(true)
.build(); .build();
calculate_button.connect_clicked(clone!( EventHandler::new(calculate_button.clone(), move |_| {
#[strong] match parse_fields(all_inputs.clone()) {
model,
#[strong]
result_table,
move |_| match parse_fields(all_inputs.clone()) {
Ok(results) => { Ok(results) => {
if values.get() == results {
info_bar.set_text_label(Some("Эти данные уже были введены."));
info_bar.show_infobar(5u64);
} else {
values.set(results); values.set(results);
let new_elem = Frequency::new(values.get().frequency); let tree_iter: TreeIter = cloned_model.append(&ResultValue::new(results.5));
if find_by_frequency_value(&model, &new_elem).is_none() { last_query.append(tree_iter);
model.append(&new_elem);
}
update_column_view(&result_table);
}
} }
Err(error) => { Err(error) => {
let error_kind: Option<&str> = get_error_message(error); let error_kind: Option<&str> = get_error_message(error);
@ -159,7 +195,8 @@ pub fn signal_reducing_page(wrapper: &Box) {
info_bar.show_infobar(5u64); info_bar.show_infobar(5u64);
} }
} }
)); })
.on_click();
wrapper.append(&input_block); wrapper.append(&input_block);
wrapper.append(&calculate_button); wrapper.append(&calculate_button);

View File

@ -1,3 +1,5 @@
use gtk4 as gtk;
use gtk::builders::*; use gtk::builders::*;
use gtk::Align; use gtk::Align;
@ -21,6 +23,7 @@ pub enum MarginData {
*/ */
#[allow(dead_code)] #[allow(dead_code)]
pub struct Size { pub struct Size {
pub width: i32, pub width: i32,
pub height: i32, pub height: i32,
@ -41,6 +44,27 @@ pub trait Setters {
fn set_align(self, align: Alignment) -> Self; fn set_align(self, align: Alignment) -> Self;
} }
pub trait TextViewSetters {
fn set_text_view_margin(self, margin: MarginData) -> Self;
}
impl TextViewSetters for TextViewBuilder {
fn set_text_view_margin(self, margin: MarginData) -> Self {
match margin {
MarginData::EqualsMargin(margin) => self
.top_margin(margin)
.left_margin(margin)
.bottom_margin(margin)
.right_margin(margin),
MarginData::MultipleMargin(margins) => self
.top_margin(margins.0)
.left_margin(margins.1)
.bottom_margin(margins.2)
.right_margin(margins.3),
}
}
}
/** /**
* Macros * Macros
*/ */
@ -73,7 +97,7 @@ macro_rules! impl_setters {
} }
impl_setters! {ButtonBuilder, EntryBuilder, TextViewBuilder, impl_setters! {ButtonBuilder, EntryBuilder, TextViewBuilder,
BoxBuilder, SwitchBuilder, FrameBuilder, LabelBuilder, PasswordEntryBuilder} BoxBuilder, SwitchBuilder, FrameBuilder, LabelBuilder}
#[allow(dead_code)] #[allow(dead_code)]
impl Size { impl Size {

View File

@ -1,51 +0,0 @@
<span size="x-large"><b> Код Хэмминга </b></span>
В данной лабораторной работе используется код Хэмминга 7-4, другими словами, код, который нужно закодировать, имеет длину в 4 бита, в то же время выходной код будет иметь 7 бит.
Программа умеет как кодировать ключевые слова, так и проверять их.
<b> Режим кодирования </b>
В этом режиме мы вводим код, в котором каждое "слово" имеет 4 бита. Это может выглядеть следующим образом:
<tt>1010 1100 1110 0000</tt>
Мы получим следующее:
<tt>1100110 0111100 0101010 0000000</tt>
В противном случае появится информационный блок с предупреждением: "Проверьте корректность кода".
<b> Режим проверки </b>
Данный режим проверяет код на ошибки. Проверка в лучшем случае пишет: "Все коды корректны". При ошибочно введённом коде, программа построчно отобразит в каких кодах есть ошибка.
Пример ввода аналогичен предыдущему:
<tt>1100110 0111100 0101010 0000000</tt>
Результат:
<tt>Все коды корректны.</tt>
Если мы поменяем какой-либо бит в одном или в нескольких "словах":
<tt>1100110 0011100 0101110 0000010</tt>
Мы получим результат:
<tt>
Ошибка в коде 2 [0011100], позиция ошибки 2, корректный код: [0111100];
Ошибка в коде 3 [0101110], позиция ошибки 5, корректный код: [0101010];
Ошибка в коде 4 [0000010], позиция ошибки 6, корректный код: [0000000];
</tt>
<span size="x-large"><b> Затухание сигнала </b></span>
Лабораторная работа подразумевает рассчитать для каждого из девятнадцати значений частоты реактивного сопротивление конденсатора X<sub>c</sub>, напряжение сигнала на стороне приёмника информации V<sub>п</sub> и коэффициент затухания сигнала ζ.
Значения вводятся согласно исходным данным для расчёта затухания сигнала. Значения можно вводить как с ",", так и с ".".
При вводе одних и тех же данных без изменений, будет показано предупреждение и операция расчёта не будет выполнена. Можно не менять данные в случае частоты, чтобы обновить данные расчёта в соответствии с новыми (К примеру, в случае длины провода, или сопротивления провода).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1023 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1 +0,0 @@
pub static HELP: &str = include_str!("help.html");

View File

@ -1,22 +0,0 @@
label{
font-size: 11pt;
}
textview {
border-radius: 7px;
padding: 7px 8px;
background: rgba(90, 90, 90, 0.5);
outline-offset: 2px;
outline: 2px solid #81ABDF00;
transition-duration: .15s;
transition-timing-function: ease-in-out;
}
textview:focus-within {
outline-offset: -2px;
outline: 2px solid #81ABDF;
}
revealer#infobar > box {
padding: 8px;
border-spacing: 12px;
border-bottom: 1px solid lighten(darken(#f6f5f4, 10%), 5%);
background-color: #4a351b;
}

View File

@ -1,22 +0,0 @@
label{
font-size: 11pt;
}
textview {
border-radius: 7px;
padding: 7px 8px;
background: rgba(141, 141, 141, 0.18);
outline-offset: 2px;
outline: 2px solid #81ABDF00;
transition-duration: .15s;
transition-timing-function: ease-in-out;
}
textview:focus-within {
outline-offset: -2px;
outline: 2px solid #81ABDF;
}
revealer#infobar > box {
padding: 8px;
border-spacing: 12px;
border-bottom: 1px solid lighten(darken(#f6f5f4, 18%), 5%);
background-color: #f1e6d9;
}

View File

@ -0,0 +1,15 @@
#info_bar{
background-color:#F1E6D9;
padding: 5px;
font-size: 11pt;
}
#info_bar > button {
transform: scale(0.9);
background-color: transparent;
}
#info_bar > button:hover {
background-color: #00000010;
}
#info_bar > button:active {
background-color: #00000020;
}

View File

@ -1,25 +1,15 @@
use adw::gdk::Display; use adw::gdk::Display;
use gtk4 as gtk;
use std::path::Path;
use gtk::{ use gtk::{
style_context_add_provider_for_display, CssProvider, STYLE_PROVIDER_PRIORITY_APPLICATION, Settings style_context_add_provider_for_display, CssProvider, STYLE_PROVIDER_PRIORITY_APPLICATION,
}; };
pub fn load_css(settings: &Settings) { pub fn load_css() {
let style_provider = CssProvider::new(); let style_provider = CssProvider::new();
style_provider.load_from_path(Path::new("./src/view/styles/info_bar.css"));
let theme = settings.gtk_theme_name();
match theme {
Some(theme_type) => {
let theme_string = theme_type.to_string();
if theme_string.contains("dark") || settings.is_gtk_application_prefer_dark_theme() {
style_provider.load_from_string(include_str!("base_dark.css"));
} else {
style_provider.load_from_string(include_str!("base_light.css"));
}
},
None => eprintln!("Theme hasn't been determined."),
}
style_context_add_provider_for_display( style_context_add_provider_for_display(
&Display::default().expect("Could not connect to a display"), &Display::default().expect("Could not connect to a display"),

View File

@ -1,107 +0,0 @@
use crate::model::builder_traits::*;
use adw::HeaderBar;
use gtk::{prelude::*, StackTransitionType::SlideLeftRight, *};
use crate::view::{
components::{
dialogues::{open_about_dialogue, open_help_dialogue},
info_bar::InfoBar,
menu::HeaderMenu,
pages::Pages,
},
pages::*,
properties::*,
};
use super::{components::MenuActions, styles::load_css};
pub fn ui(application: &adw::Application) {
let default_settings = Settings::default();
if let Some(settings) = default_settings {
{
#[cfg(target_os = "windows")]
settings.set_gtk_font_name(Some("Segoe UI 9"));
}
settings.connect_gtk_application_prefer_dark_theme_notify(load_css);
settings.connect_gtk_theme_name_notify(load_css);
load_css(&settings);
}
let hamming_code = Box::builder()
.orientation(Orientation::Vertical)
.set_align(Alignment::new(Align::Fill, Align::Fill))
.set_margin(MarginData::EqualsMargin(15))
.spacing(10)
.build();
let info_bar = InfoBar::builder()
.set_text_label("Sample text")
.set_button_icon("window-close-symbolic")
.build();
hamming_code::hamming_code_page(&hamming_code);
let signal_reducing = Box::builder()
.orientation(Orientation::Vertical)
.set_align(Alignment::new(Align::Fill, Align::Fill))
.set_margin(MarginData::EqualsMargin(15))
.spacing(10)
.build();
signal_reducing::signal_reducing_page(&signal_reducing);
let pages = Pages::builder()
.set_transition(SlideLeftRight, 200)
.append_items(vec![
("Код Хэмминга", "Код Хэмминга", &hamming_code),
("Затухание сигнала", "Затухание сигнала", &signal_reducing),
])
.build(5);
let application_box = Box::new(Orientation::Vertical, 0);
application_box.append(info_bar.get());
application_box.append(pages.get());
let title_bar = Box::new(Orientation::Horizontal, 0);
let mut menu_button = HeaderMenu::<&str>::new();
let actions: &[MenuActions] = &[
(open_about_dialogue, "about_software", "О программе"),
(open_help_dialogue, "help", "Помощь"),
];
menu_button.set_action_group_name(Some("menu_group_action"));
menu_button.append_items(actions);
title_bar.append(
&Label::builder()
.css_name("title")
.set_align(Alignment::new(Align::Center, Align::Center))
.hexpand(true)
.vexpand(true)
.use_markup(true)
.label("<span size=\"larger\"><b>Комплексная программа для лаб. работ</b></span>")
.build(),
);
title_bar.append(menu_button.get_button());
let header_bar = HeaderBar::builder().title_widget(&title_bar).build();
let window = ApplicationWindow::builder()
.width_request(800)
.height_request(600)
.application(application)
.titlebar(&header_bar)
.child(&application_box)
.build();
window.insert_action_group("menu_group_action", Some(menu_button.get_actions_group()));
window.present();
}

64
src/view/view.rs Normal file
View File

@ -0,0 +1,64 @@
use crate::model::builder_traits::*;
use gtk4 as gtk;
use gtk::{prelude::*, StackTransitionType::SlideLeftRight, *};
use info_bar::InfoBar;
#[allow(unused)]
use crate::view::{
components::{pages::Pages, wrapper::*, *},
pages::*,
properties::*,
};
use super::styles::load_css;
pub fn ui(application: &adw::Application) {
load_css();
let hamming_code = Wrapper::row_builder()
.set_align(Alignment::new(Align::Fill, Align::Fill))
.set_margin(MarginData::EqualsMargin(15))
.spacing(10)
.build();
let info_bar = InfoBar::builder()
.set_text_label("Sample text")
.set_button_icon("close")
.build();
hamming_code::hamming_code_page(&hamming_code);
let signal_reducing = Wrapper::row_builder()
.set_align(Alignment::new(Align::Fill, Align::Fill))
.set_margin(MarginData::EqualsMargin(15))
.spacing(10)
.build();
signal_reducing::signal_reducing_page(&signal_reducing);
let pages = Pages::builder()
.set_transition(SlideLeftRight, 200)
.append_items(vec![
("Код Хэмминга", "Код Хэмминга", &hamming_code),
("Затухание сигнала", "Затухание сигнала", &signal_reducing),
])
.build(5)
.get();
let application_box = Box::new(Orientation::Vertical, 0);
application_box.append(info_bar.clone().get());
application_box.append(&pages);
let window = ApplicationWindow::builder()
.title("Комплексная программа для лаб. работ")
.width_request(700)
.height_request(400)
.application(application)
.child(&application_box)
.build();
window.show();
}