Commit Diff


commit - a1b35ca2bd3f1953d506890c8b0f942ac6061ea7
commit + 0da769c81f1e75bc2c77e7abdbe29cf9716a1818
blob - 9cfba16e02fb0cd74f90c6a1f950c0b4469a68de
blob + d6a4e7d653d80be2a8c5c94a63b59efe73d4f837
--- Cargo.lock
+++ Cargo.lock
@@ -23,6 +23,8 @@ name = "accounthing2"
 version = "0.1.0"
 dependencies = [
  "chrono",
+ "csv",
+ "datev-types",
  "genpdf",
  "iced",
  "iced_aw",
@@ -48,9 +50,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8ce
 
 [[package]]
 name = "ahash"
-version = "0.8.6"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
+checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
 dependencies = [
  "cfg-if",
  "once_cell",
@@ -59,6 +61,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "aho-corasick"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "allocator-api2"
 version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -192,9 +203,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8
 
 [[package]]
 name = "bitflags"
-version = "2.4.1"
+version = "2.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
 
 [[package]]
 name = "block"
@@ -223,9 +234,9 @@ dependencies = [
 
 [[package]]
 name = "bstr"
-version = "1.8.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
+checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
 dependencies = [
  "memchr",
  "regex-automata",
@@ -240,9 +251,9 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d917
 
 [[package]]
 name = "bytemuck"
-version = "1.14.0"
+version = "1.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
+checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9"
 dependencies = [
  "bytemuck_derive",
 ]
@@ -255,7 +266,7 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -276,9 +287,35 @@ dependencies = [
  "slotmap",
  "thiserror",
  "vec_map",
+]
+
+[[package]]
+name = "calloop"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298"
+dependencies = [
+ "bitflags 2.4.2",
+ "log",
+ "polling",
+ "rustix",
+ "slab",
+ "thiserror",
 ]
 
 [[package]]
+name = "calloop-wayland-source"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02"
+dependencies = [
+ "calloop 0.12.4",
+ "rustix",
+ "wayland-backend 0.3.3",
+ "wayland-client 0.31.2",
+]
+
+[[package]]
 name = "cc"
 version = "1.0.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -302,9 +339,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce795
 
 [[package]]
 name = "chrono"
-version = "0.4.31"
+version = "0.4.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
+checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
 dependencies = [
  "android-tzdata",
  "iana-time-zone",
@@ -312,7 +349,7 @@ dependencies = [
  "num-traits",
  "serde",
  "wasm-bindgen",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.0",
 ]
 
 [[package]]
@@ -339,21 +376,21 @@ dependencies = [
 
 [[package]]
 name = "clipboard_wayland"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f6364a9f7a66f2ac1a1a098aa1c7f6b686f2496c6ac5e5c0d773445df912747"
+checksum = "8134163bd07c47ae3cc29babc42c255fdb315facc790950ae2d0e561ea6f2ec0"
 dependencies = [
  "smithay-clipboard",
 ]
 
 [[package]]
 name = "clipboard_x11"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "983a7010836ecd04dde2c6d27a0cb56ec5d21572177e782bdcb24a600124e921"
+checksum = "5cf45b436634fee64c6d3981639b46a87eeea3c64e422643273fcefd1baef56c"
 dependencies = [
  "thiserror",
- "x11rb 0.9.0",
+ "x11rb 0.13.0",
 ]
 
 [[package]]
@@ -403,6 +440,15 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642"
 
 [[package]]
+name = "concurrent-queue"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
 name = "const_fn"
 version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -477,10 +523,43 @@ dependencies = [
 ]
 
 [[package]]
+name = "crossbeam-utils"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+
+[[package]]
 name = "crunchy"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
+[[package]]
+name = "csv"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
+dependencies = [
+ "csv-core",
+ "itoa 1.0.10",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "cursor-icon"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
 
 [[package]]
 name = "d3d12"
@@ -494,10 +573,24 @@ dependencies = [
 ]
 
 [[package]]
+name = "datev-types"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5a6a14d068cde322e0762e2d6e9e94c57b023d81b332e680a24a95859fbb58e"
+dependencies = [
+ "chrono",
+ "csv",
+ "lazy_static",
+ "regex",
+ "serde",
+ "validator",
+]
+
+[[package]]
 name = "deranged"
-version = "0.3.10"
+version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
 dependencies = [
  "powerfmt",
 ]
@@ -617,6 +710,16 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 
 [[package]]
+name = "errno"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
 name = "error-code"
 version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -662,9 +765,9 @@ dependencies = [
 
 [[package]]
 name = "fdeflate"
-version = "0.3.1"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868"
+checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"
 dependencies = [
  "simd-adler32",
 ]
@@ -686,10 +789,16 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8"
 
 [[package]]
+name = "font-types"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bd7f3ea17572640b606b35df42cfb6ecdf003704b062580e59918692190b73d"
+
+[[package]]
 name = "fontconfig-parser"
-version = "0.5.3"
+version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "674e258f4b5d2dcd63888c01c68413c51f565e8af99d2f7701c7b81d79ef41c4"
+checksum = "6a595cb550439a117696039dfc69830492058211b771a2a165379f2a1a53d84d"
 dependencies = [
  "roxmltree",
 ]
@@ -724,10 +833,19 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
 
 [[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
 name = "futures"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
+checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -740,9 +858,9 @@ dependencies = [
 
 [[package]]
 name = "futures-channel"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -750,15 +868,15 @@ dependencies = [
 
 [[package]]
 name = "futures-core"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
+checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -768,38 +886,38 @@ dependencies = [
 
 [[package]]
 name = "futures-io"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
+checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
 
 [[package]]
 name = "futures-macro"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
 ]
 
 [[package]]
 name = "futures-sink"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
+checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
 
 [[package]]
 name = "futures-task"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
 
 [[package]]
 name = "futures-util"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -836,11 +954,21 @@ dependencies = [
 ]
 
 [[package]]
-name = "getrandom"
-version = "0.2.11"
+name = "gethostname"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
+checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
 dependencies = [
+ "libc",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
+dependencies = [
  "cfg-if",
  "libc",
  "wasi",
@@ -920,7 +1048,7 @@ version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c"
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "gpu-descriptor-types",
  "hashbrown 0.14.3",
 ]
@@ -931,7 +1059,7 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c"
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
 ]
 
 [[package]]
@@ -987,9 +1115,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.3.3"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
+checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f"
 
 [[package]]
 name = "hexf-parse"
@@ -999,9 +1127,9 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4c
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.58"
+version = "0.1.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
@@ -1044,7 +1172,7 @@ dependencies = [
  "iced_widget",
  "num-traits",
  "once_cell",
- "time 0.3.30",
+ "time 0.3.34",
 ]
 
 [[package]]
@@ -1200,6 +1328,33 @@ dependencies = [
 ]
 
 [[package]]
+name = "idna"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
+dependencies = [
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "if_chain"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
+
+[[package]]
 name = "indexmap"
 version = "1.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1211,9 +1366,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.1.0"
+version = "2.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
+checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
 dependencies = [
  "equivalent",
  "hashbrown 0.14.3",
@@ -1290,9 +1445,9 @@ dependencies = [
 
 [[package]]
 name = "js-sys"
-version = "0.3.66"
+version = "0.3.67"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
+checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -1325,9 +1480,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb06
 
 [[package]]
 name = "libc"
-version = "0.2.151"
+version = "0.2.153"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
 
 [[package]]
 name = "libloading"
@@ -1361,7 +1516,7 @@ version = "0.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "libc",
  "redox_syscall 0.4.1",
 ]
@@ -1373,6 +1528,12 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
 [[package]]
+name = "linux-raw-sys"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+
+[[package]]
 name = "lock_api"
 version = "0.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1437,9 +1598,9 @@ dependencies = [
 
 [[package]]
 name = "lyon_geom"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74df1ff0a0147282eb10699537a03baa7d31972b58984a1d44ce0624043fe8ad"
+checksum = "edecfb8d234a2b0be031ab02ebcdd9f3b9ee418fb35e265f7a540a48d197bff9"
 dependencies = [
  "arrayvec",
  "euclid",
@@ -1483,10 +1644,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "matches"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
+
+[[package]]
 name = "memchr"
-version = "2.6.4"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
 
 [[package]]
 name = "memmap2"
@@ -1502,6 +1669,15 @@ name = "memmap2"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "memmap2"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
 dependencies = [
  "libc",
 ]
@@ -1540,9 +1716,9 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
 dependencies = [
  "adler",
  "simd-adler32",
@@ -1607,19 +1783,6 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3"
 dependencies = [
  "jni-sys",
-]
-
-[[package]]
-name = "nix"
-version = "0.22.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf"
-dependencies = [
- "bitflags 1.3.2",
- "cc",
- "cfg-if",
- "libc",
- "memoffset 0.6.5",
 ]
 
 [[package]]
@@ -1661,6 +1824,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
 name = "num-traits"
 version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1719,7 +1888,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -1798,9 +1967,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.32.1"
+version = "0.32.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
 dependencies = [
  "memchr",
 ]
@@ -1851,9 +2020,9 @@ dependencies = [
 
 [[package]]
 name = "palette"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2e2f34147767aa758aa649415b50a69eeb46a67f9dc7db8011eeb3d84b351dc"
+checksum = "3d38e6e5ca1612e2081cc31188f08c3cba630ce4ba44709a153f1a0f38d678f2"
 dependencies = [
  "approx 0.5.1",
  "fast-srgb8",
@@ -1863,13 +2032,13 @@ dependencies = [
 
 [[package]]
 name = "palette_derive"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7db010ec5ff3d4385e4f133916faacd9dad0f6a09394c92d825b3aed310fa0a"
+checksum = "e05d1c929301fee6830dafa764341118829b2535c216b0571e3821ecac5c885b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -1962,7 +2131,7 @@ dependencies = [
  "phf_shared",
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -1988,15 +2157,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c
 
 [[package]]
 name = "pkg-config"
-version = "0.3.27"
+version = "0.3.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
+checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
 
 [[package]]
 name = "png"
-version = "0.17.10"
+version = "0.17.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64"
+checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a"
 dependencies = [
  "bitflags 1.3.2",
  "crc32fast",
@@ -2006,6 +2175,20 @@ dependencies = [
 ]
 
 [[package]]
+name = "polling"
+version = "3.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "545c980a3880efd47b2e262f6a4bb6daad6555cf3367aa9c4e52895f69537a41"
+dependencies = [
+ "cfg-if",
+ "concurrent-queue",
+ "pin-project-lite",
+ "rustix",
+ "tracing",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
 name = "pom"
 version = "3.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2049,6 +2232,30 @@ dependencies = [
 ]
 
 [[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+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-macro-hack"
 version = "0.5.20+deprecated"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2056,18 +2263,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc07
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.70"
+version = "1.0.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "profiling"
-version = "1.0.12"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1de09527cd2ea2c2d59fb6c2f8c1ab8c71709ed9d1b6d60b0e1c9fbb6fdcb33c"
+checksum = "0f0f7f43585c34e4fdd7497d746bc32e14458cf11c69341cc0587b1d825dde42"
 
 [[package]]
 name = "quick-xml"
@@ -2079,10 +2286,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "quick-xml"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "quote"
-version = "1.0.33"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
 dependencies = [
  "proc-macro2",
 ]
@@ -2136,6 +2352,15 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
 
 [[package]]
+name = "read-fonts"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7555e052e772f964a1c99f1434f6a2c3a47a5f8e4292236921f121a7753cb2b5"
+dependencies = [
+ "font-types",
+]
+
+[[package]]
 name = "redox_syscall"
 version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2163,10 +2388,33 @@ dependencies = [
 ]
 
 [[package]]
+name = "regex"
+version = "1.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
 name = "regex-automata"
-version = "0.4.3"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
+checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
 
 [[package]]
 name = "renderdoc-sys"
@@ -2176,12 +2424,9 @@ checksum = "216080ab382b992234dda86873c18d4c48358f5cfc
 
 [[package]]
 name = "roxmltree"
-version = "0.18.1"
+version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "862340e351ce1b271a378ec53f304a5558f7db87f3769dc655a8f6ecbb68b302"
-dependencies = [
- "xmlparser",
-]
+checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
 
 [[package]]
 name = "rustc-demangle"
@@ -2205,6 +2450,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustix"
+version = "0.38.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
+dependencies = [
+ "bitflags 2.4.2",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
 name = "rusttype"
 version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2259,15 +2517,15 @@ dependencies = [
  "ab_glyph",
  "log",
  "memmap2 0.5.10",
- "smithay-client-toolkit",
+ "smithay-client-toolkit 0.16.1",
  "tiny-skia 0.8.4",
 ]
 
 [[package]]
 name = "self_cell"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6"
+checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba"
 
 [[package]]
 name = "semver"
@@ -2286,29 +2544,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41
 
 [[package]]
 name = "serde"
-version = "1.0.193"
+version = "1.0.196"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
+checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.193"
+version = "1.0.196"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
+checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.108"
+version = "1.0.113"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
+checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
 dependencies = [
  "itoa 1.0.10",
  "ryu",
@@ -2362,9 +2620,9 @@ dependencies = [
 
 [[package]]
 name = "smallvec"
-version = "1.11.2"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
 
 [[package]]
 name = "smithay-client-toolkit"
@@ -2373,7 +2631,7 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9"
 dependencies = [
  "bitflags 1.3.2",
- "calloop",
+ "calloop 0.10.6",
  "dlib",
  "lazy_static",
  "log",
@@ -2381,18 +2639,44 @@ dependencies = [
  "nix 0.24.3",
  "pkg-config",
  "wayland-client 0.29.5",
- "wayland-cursor",
- "wayland-protocols",
+ "wayland-cursor 0.29.5",
+ "wayland-protocols 0.29.5",
 ]
 
 [[package]]
+name = "smithay-client-toolkit"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60e3d9941fa3bacf7c2bf4b065304faa14164151254cd16ce1b1bc8fc381600f"
+dependencies = [
+ "bitflags 2.4.2",
+ "calloop 0.12.4",
+ "calloop-wayland-source",
+ "cursor-icon",
+ "libc",
+ "log",
+ "memmap2 0.9.4",
+ "rustix",
+ "thiserror",
+ "wayland-backend 0.3.3",
+ "wayland-client 0.31.2",
+ "wayland-csd-frame",
+ "wayland-cursor 0.31.1",
+ "wayland-protocols 0.31.2",
+ "wayland-protocols-wlr",
+ "wayland-scanner 0.31.1",
+ "xkeysym",
+]
+
+[[package]]
 name = "smithay-clipboard"
-version = "0.6.6"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8"
+checksum = "0bb62b280ce5a5cba847669933a0948d00904cf83845c944eae96a4738cea1a6"
 dependencies = [
- "smithay-client-toolkit",
- "wayland-client 0.29.5",
+ "libc",
+ "smithay-client-toolkit 0.18.0",
+ "wayland-backend 0.3.3",
 ]
 
 [[package]]
@@ -2414,7 +2698,7 @@ dependencies = [
  "redox_syscall 0.3.5",
  "thiserror",
  "wasm-bindgen",
- "wayland-backend",
+ "wayland-backend 0.1.2",
  "wayland-client 0.30.2",
  "wayland-sys 0.30.1",
  "web-sys",
@@ -2526,10 +2810,11 @@ checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe
 
 [[package]]
 name = "swash"
-version = "0.1.8"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b7c73c813353c347272919aa1af2885068b05e625e5532b43049e4f641ae77f"
+checksum = "d06ff4664af8923625604261c645f5c4cc610cc83c84bec74b50d76237089de7"
 dependencies = [
+ "read-fonts",
  "yazi",
  "zeno",
 ]
@@ -2547,9 +2832,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.41"
+version = "2.0.48"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2567,31 +2852,31 @@ dependencies = [
 
 [[package]]
 name = "termcolor"
-version = "1.4.0"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
 dependencies = [
  "winapi-util",
 ]
 
 [[package]]
 name = "thiserror"
-version = "1.0.51"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
+checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.51"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
+checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -2611,12 +2896,13 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.30"
+version = "0.3.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
+checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
 dependencies = [
  "deranged",
  "libc",
+ "num-conv",
  "num_threads",
  "powerfmt",
  "serde",
@@ -2730,12 +3016,28 @@ version = "0.19.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
 dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "toml_datetime",
  "winnow",
 ]
 
 [[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "pin-project-lite",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+
+[[package]]
 name = "ttf-parser"
 version = "0.19.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2760,9 +3062,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.14"
+version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
 
 [[package]]
 name = "unicode-bidi-mirroring"
@@ -2789,10 +3091,19 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
 
 [[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
 name = "unicode-properties"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0"
+checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291"
 
 [[package]]
 name = "unicode-script"
@@ -2819,6 +3130,60 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
 
 [[package]]
+name = "url"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
+dependencies = [
+ "form_urlencoded",
+ "idna 0.5.0",
+ "percent-encoding",
+]
+
+[[package]]
+name = "validator"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d0f08911ab0fee2c5009580f04615fa868898ee57de10692a45da0c3bcc3e5e"
+dependencies = [
+ "idna 0.2.3",
+ "lazy_static",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "url",
+ "validator_derive",
+ "validator_types",
+]
+
+[[package]]
+name = "validator_derive"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d85135714dba11a1bd0b3eb1744169266f1a38977bf4e3ff5e2e1acb8c2b7eee"
+dependencies = [
+ "if_chain",
+ "lazy_static",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "syn 1.0.109",
+ "validator_types",
+]
+
+[[package]]
+name = "validator_types"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ded9d97e1d42327632f5f3bae6403c04886e2de3036261ef42deebd931a6a291"
+dependencies = [
+ "proc-macro2",
+ "syn 1.0.109",
+]
+
+[[package]]
 name = "vec_map"
 version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2838,9 +3203,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
+checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -2848,24 +3213,24 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
+checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
 dependencies = [
  "bumpalo",
  "log",
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.39"
+version = "0.4.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
+checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -2875,9 +3240,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
+checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -2885,22 +3250,22 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
+checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
+checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
 
 [[package]]
 name = "wasm-timer"
@@ -2933,6 +3298,20 @@ dependencies = [
 ]
 
 [[package]]
+name = "wayland-backend"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40"
+dependencies = [
+ "cc",
+ "downcast-rs",
+ "rustix",
+ "scoped-tls",
+ "smallvec",
+ "wayland-sys 0.31.1",
+]
+
+[[package]]
 name = "wayland-client"
 version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2956,11 +3335,23 @@ checksum = "489c9654770f674fc7e266b3c579f4053d7551df0c
 dependencies = [
  "bitflags 1.3.2",
  "nix 0.26.4",
- "wayland-backend",
+ "wayland-backend 0.1.2",
  "wayland-scanner 0.30.1",
 ]
 
 [[package]]
+name = "wayland-client"
+version = "0.31.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f"
+dependencies = [
+ "bitflags 2.4.2",
+ "rustix",
+ "wayland-backend 0.3.3",
+ "wayland-scanner 0.31.1",
+]
+
+[[package]]
 name = "wayland-commons"
 version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2970,6 +3361,17 @@ dependencies = [
  "once_cell",
  "smallvec",
  "wayland-sys 0.29.5",
+]
+
+[[package]]
+name = "wayland-csd-frame"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
+dependencies = [
+ "bitflags 2.4.2",
+ "cursor-icon",
+ "wayland-backend 0.3.3",
 ]
 
 [[package]]
@@ -2984,6 +3386,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "wayland-cursor"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba"
+dependencies = [
+ "rustix",
+ "wayland-client 0.31.2",
+ "xcursor",
+]
+
+[[package]]
 name = "wayland-protocols"
 version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2996,6 +3409,31 @@ dependencies = [
 ]
 
 [[package]]
+name = "wayland-protocols"
+version = "0.31.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4"
+dependencies = [
+ "bitflags 2.4.2",
+ "wayland-backend 0.3.3",
+ "wayland-client 0.31.2",
+ "wayland-scanner 0.31.1",
+]
+
+[[package]]
+name = "wayland-protocols-wlr"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6"
+dependencies = [
+ "bitflags 2.4.2",
+ "wayland-backend 0.3.3",
+ "wayland-client 0.31.2",
+ "wayland-protocols 0.31.2",
+ "wayland-scanner 0.31.1",
+]
+
+[[package]]
 name = "wayland-scanner"
 version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3013,11 +3451,22 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "b9b873b257fbc32ec909c0eb80dea312076a67014e65e245f5eb69a6b8ab330e"
 dependencies = [
  "proc-macro2",
- "quick-xml",
+ "quick-xml 0.28.2",
  "quote",
 ]
 
 [[package]]
+name = "wayland-scanner"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283"
+dependencies = [
+ "proc-macro2",
+ "quick-xml 0.31.0",
+ "quote",
+]
+
+[[package]]
 name = "wayland-sys"
 version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3041,10 +3490,22 @@ dependencies = [
 ]
 
 [[package]]
-name = "web-sys"
-version = "0.3.66"
+name = "wayland-sys"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af"
+dependencies = [
+ "dlib",
+ "log",
+ "once_cell",
+ "pkg-config",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.67"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f"
+checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -3082,7 +3543,7 @@ checksum = "8f478237b4bf0d5b70a39898a66fa67ca3a007d79f
 dependencies = [
  "arrayvec",
  "bit-vec",
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "codespan-reporting",
  "log",
  "naga",
@@ -3107,7 +3568,7 @@ dependencies = [
  "arrayvec",
  "ash",
  "bit-set",
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "block",
  "core-graphics-types",
  "d3d12",
@@ -3145,7 +3606,7 @@ version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d0c153280bb108c2979eb5c7391cb18c56642dd3c072e55f52065e13e2a1252a"
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "js-sys",
  "web-sys",
 ]
@@ -3221,11 +3682,11 @@ dependencies = [
 
 [[package]]
 name = "windows-core"
-version = "0.51.1"
+version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
 dependencies = [
- "windows-targets 0.48.5",
+ "windows-targets 0.52.0",
 ]
 
 [[package]]
@@ -3244,6 +3705,15 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
 dependencies = [
  "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.0",
 ]
 
 [[package]]
@@ -3277,6 +3747,21 @@ dependencies = [
 ]
 
 [[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
+]
+
+[[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3287,6 +3772,12 @@ name = "windows_aarch64_gnullvm"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -3301,6 +3792,12 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+
+[[package]]
 name = "windows_i686_gnu"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3313,6 +3810,12 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+
+[[package]]
 name = "windows_i686_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3325,6 +3828,12 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+
+[[package]]
 name = "windows_x86_64_gnu"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3337,6 +3846,12 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+
+[[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3349,6 +3864,12 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+
+[[package]]
 name = "windows_x86_64_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3361,6 +3882,12 @@ source = "registry+https://github.com/rust-lang/crates
 checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+
+[[package]]
 name = "winit"
 version = "0.28.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3384,11 +3911,11 @@ dependencies = [
  "raw-window-handle",
  "redox_syscall 0.3.5",
  "sctk-adwaita",
- "smithay-client-toolkit",
+ "smithay-client-toolkit 0.16.1",
  "wasm-bindgen",
  "wayland-client 0.29.5",
  "wayland-commons",
- "wayland-protocols",
+ "wayland-protocols 0.29.5",
  "wayland-scanner 0.29.5",
  "web-sys",
  "windows-sys 0.45.0",
@@ -3397,9 +3924,9 @@ dependencies = [
 
 [[package]]
 name = "winnow"
-version = "0.5.28"
+version = "0.5.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2"
+checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5"
 dependencies = [
  "memchr",
 ]
@@ -3417,33 +3944,32 @@ dependencies = [
 
 [[package]]
 name = "x11rb"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e99be55648b3ae2a52342f9a870c0e138709a3493261ce9b469afe6e4df6d8a"
-dependencies = [
- "gethostname",
- "nix 0.22.3",
- "winapi",
- "winapi-wsapoll",
-]
-
-[[package]]
-name = "x11rb"
 version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cdf3c79412dd91bae7a7366b8ad1565a85e35dd049affc3a6a2c549e97419617"
 dependencies = [
- "gethostname",
+ "gethostname 0.2.3",
  "libc",
  "libloading 0.7.4",
  "nix 0.25.1",
  "once_cell",
  "winapi",
  "winapi-wsapoll",
- "x11rb-protocol",
+ "x11rb-protocol 0.11.1",
 ]
 
 [[package]]
+name = "x11rb"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a"
+dependencies = [
+ "gethostname 0.4.3",
+ "rustix",
+ "x11rb-protocol 0.13.0",
+]
+
+[[package]]
 name = "x11rb-protocol"
 version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3453,24 +3979,30 @@ dependencies = [
 ]
 
 [[package]]
+name = "x11rb-protocol"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34"
+
+[[package]]
 name = "xcursor"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911"
 
 [[package]]
+name = "xkeysym"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "054a8e68b76250b253f671d1268cb7f1ae089ec35e195b2efb2a4e9a836d0621"
+
+[[package]]
 name = "xml-rs"
 version = "0.8.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a"
 
 [[package]]
-name = "xmlparser"
-version = "0.13.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
-
-[[package]]
 name = "yazi"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3484,20 +4016,20 @@ checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b6
 
 [[package]]
 name = "zerocopy"
-version = "0.7.31"
+version = "0.7.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d"
+checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
 dependencies = [
  "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.7.31"
+version = "0.7.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a"
+checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.41",
+ "syn 2.0.48",
 ]
blob - f03536d40ab75b1b23c4f70b217093862dbcbe54
blob + 962a18554c08af729476c1a6c7b9e178a389361d
--- Cargo.toml
+++ Cargo.toml
@@ -5,6 +5,8 @@ edition = "2021"
 
 [dependencies]
 chrono = { version = "0.4.31", features = ["serde"] }
+csv = "1.3.0"
+datev-types = "0.4.0"
 genpdf = "0.2.0"
 iced = "0.10.0"
 iced_aw = "0.7.0"
blob - 21ac2d2fdd0eabd05a2e2d306ca0042e34b42abe
blob + 9fb7b17b8cd7d33aeae532eec72152b4a2c0c148
--- src/data.rs
+++ src/data.rs
@@ -22,6 +22,10 @@ pub struct CustomerId(pub usize);
 pub struct Customer {
     pub id: CustomerId,
     pub name: String,
+    #[serde(default)]
+    pub name2: String,
+    #[serde(default)]
+    pub name3: String,
     pub address: String,
     pub zip_city: String,
 }
blob - 4bd6c5ca8c02a300ff619a875a4d7c56e5cd5954
blob + 396fafd15a60d50d59bc258b0a03e0c594824353
--- src/gui/business.rs
+++ src/gui/business.rs
@@ -1,4 +1,4 @@
-use iced::{Element, widget::{column, button, row, text_input, container, Container}};
+use iced::{Element, widget::{column, button, row, text_input, container}};
 use iced_aw::{Grid, Strategy};
 use crate::data::Business;
 
@@ -80,15 +80,15 @@ impl Tab for BusinessTab {
 	match &self.page {
 	    Page::Show => {
 		let grid = [
-		    ("Name",		&biz.name),
-		    ("Owner",		&biz.owner_name),
-		    ("Address",		&biz.address),
-		    ("ZIP/City",	&biz.zip_city),
-		    ("Email",		&biz.email),
-		    ("IBAN",		&biz.iban),
-		    ("BIC",		&biz.bic),
-		    ("Bank",		&biz.bank),
-		    ("Steuer-Nr.",	&biz.ustid),
+		    ("Name:",		&biz.name),
+		    ("Owner:",		&biz.owner_name),
+		    ("Address:",	&biz.address),
+		    ("ZIP/City:",	&biz.zip_city),
+		    ("Email:",		&biz.email),
+		    ("IBAN:",		&biz.iban),
+		    ("BIC:",		&biz.bic),
+		    ("Bank:",		&biz.bank),
+		    ("Steuer-Nr.:",	&biz.ustid),
 		];
 		let grid = grid
 		    .into_iter()
blob - b7bb38d0a13d08a12757986a63b15d2b6ce7b086
blob + 608f3990c33473e192624e125fdfdc5ea8fd4210
--- src/gui/customers.rs
+++ src/gui/customers.rs
@@ -1,5 +1,5 @@
 use CustomersMessage as M;
-use iced::{Element, widget::{text, row, column, button, text_input}};
+use iced::{Element, widget::{text, row, column, button, text_input, container}, alignment::Vertical};
 use iced_aw::Grid;
 use crate::data::{Customer, CustomerId};
 use super::{Tab, store::Store};
@@ -11,6 +11,8 @@ pub enum CustomersMessage {
     Confirm(Customer),
     SetID(String),
     SetName(String),
+    SetName2(String),
+    SetName3(String),
     SetAddress(String),
     SetZIPCity(String),
     Show(CustomerId),
@@ -20,6 +22,8 @@ pub enum CustomersMessage {
 struct New {
     id: String,
     name: String,
+    name2: String,
+    name3: String,
     address: String,
     zip_city: String,
 }
@@ -42,6 +46,8 @@ impl New {
 	Self {
 	    id: id.to_string(),
 	    name: String::new(),
+	    name2: String::new(),
+	    name3: String::new(),
 	    address: String::new(),
 	    zip_city: String::new(),
 	}
@@ -62,6 +68,8 @@ impl New {
 	let c = Customer {
 	    id: CustomerId(self.id.parse().ok()?),
 	    name: self.name.clone(),
+	    name2: self.name2.clone(),
+	    name3: self.name3.clone(),
 	    address: self.address.clone(),
 	    zip_city: self.zip_city.clone(),
 	};
@@ -78,6 +86,8 @@ impl Tab for Customers {
 	    M::Back		=> self.page = Page::List,
 	    M::SetID(x)		=> self.edit(|c| c.id = x),
 	    M::SetName(x)	=> self.edit(|c| c.name = x),
+	    M::SetName2(x)	=> self.edit(|c| c.name2 = x),
+	    M::SetName3(x)	=> self.edit(|c| c.name3 = x),
 	    M::SetAddress(x)	=> self.edit(|c| c.address = x),
 	    M::SetZIPCity(x)	=> self.edit(|c| c.zip_city = x),
 	    M::Confirm(c)	=> {
@@ -98,18 +108,29 @@ impl Tab for Customers {
 	    Page::List	=> {
 		let mut grid = Grid::with_columns(4);
 
+		fn pad<'b>(e: impl Into<Element<'b, M>>) -> Element<'b, M> {
+		    container(e)
+			.padding([0, 0, 0, 10])
+			.align_y(Vertical::Center)
+			.into()
+		}
+
 		for c in store.customers() {
-		    grid.insert(text(c.id.to_string()));
-		    grid.insert(c.name.as_str());
-		    grid.insert(
-			button("Show")
-			    .on_press(M::Show(c.id))
-		    );
-		    grid.insert(
-			button("Delete")
+		    let row = [
+			text(c.id.to_string()).into(),
+			pad(text(c.name.as_str())),
+			pad(
+			    button("Show")
+				.on_press(M::Show(c.id))
+			),
+			button("x")
 			    .style(iced::theme::Button::Destructive)
 			    .on_press(M::Delete(c.id))
-		    );
+			    .into()
+		    ];
+		    for r in row {
+			grid.insert(r);
+		    }
 		}
 		
 		column![
@@ -125,6 +146,8 @@ impl Tab for Customers {
 		column![
 		    ti("ID",		&c.id,		M::SetID),
 		    ti("Name",		&c.name,	M::SetName),
+		    ti("Name2",		&c.name2,	M::SetName2),
+		    ti("Name3",		&c.name3,	M::SetName3),
 		    ti("Address",	&c.address,	M::SetAddress),
 		    ti("ZIP/City",	&c.zip_city,	M::SetZIPCity),
 		    row![
blob - b5c6cb040e9d2e85916633e70f2e93d4933a9079
blob + 5fb0fb496dd70352a004527dadc249e7d440ab85
--- src/gui/invoices.rs
+++ src/gui/invoices.rs
@@ -1,6 +1,6 @@
 use InvoicesMessage as M;
 use chrono::{NaiveDate, Local};
-use iced::{Element, widget::{container, text, column, button, row, text_input, checkbox, PickList, TextInput, Column, Container}, Length};
+use iced::{Element, widget::{container, text, column, button, row, text_input, checkbox, PickList, TextInput, Column, Container, Scrollable}, Length, alignment::Vertical};
 use iced_aw::{Grid, DatePicker, date_picker::Date, Modal};
 use crate::{data::{Invoice, InvoiceId, CustomerId, Record}, pdf::render_to_file};
 use super::{Tab, store::Store};
@@ -12,6 +12,8 @@ pub enum InvoicesMessage {
     Add,
     View(InvoiceId),
     Generate(InvoiceId),
+    Export(InvoiceId),
+    Delete(InvoiceId),
     Create((Invoice, bool)), 
     SetId(String),
     SetCustomer(CustomerId),
@@ -23,8 +25,10 @@ pub enum InvoicesMessage {
     RecordSetAmount(usize, String),
     RecordSetPrice(usize, String),
     RecordRemove(usize),
+    RecordCopy(usize),
 }
 
+#[derive(Clone)]
 struct NewRecord {
     description: String,
     date: Date, 
@@ -155,6 +159,18 @@ impl Tab for Invoices {
 		let i = store.invoice(id).unwrap();
 		self.page = generate(i, store);
 	    },
+	    M::Export(id)			=> {
+		// TODO: proper erorr handling
+		let i = store.invoice(id).unwrap();
+		let dir = store.output_dir();
+		if !dir.exists() {
+		    std::fs::create_dir_all(&dir)
+			.unwrap();
+		}
+		let path = dir.join(i.file_name().replace(".pdf", ".csv"));
+		i.export(&path).unwrap();
+		open::that_detached(path).unwrap();
+	    },
 	    M::Create((i, g))			=> {
 		let next_page = if g {
 		    generate(&i, store)
@@ -166,6 +182,10 @@ impl Tab for Invoices {
 		store.save();
 		self.page = next_page;
 	    },
+	    M::Delete(id)			=> {
+		store.remove_invoice(id);
+		store.save();
+	    },
 	    M::SetId(x)				=> self.edit(|i| i.id = x),
 	    M::SetCustomer(x)			=> self.edit(|i| i.customer = Some(x)),
 	    M::SetGenerate(x)			=> self.edit(|i| i.generate = x),
@@ -177,31 +197,56 @@ impl Tab for Invoices {
 	    M::RecordSetAmount(i, x)		=> self.edit_record(i, |r| r.amount = x),
 	    M::RecordSetPrice(i, x)		=> self.edit_record(i, |r| r.price = x),
 	    M::RecordRemove(n)			=> self.edit(|i| { i.records.remove(n); }),
+	    M::RecordCopy(n)			=> self.edit(|i| { i.records.push(i.records[n].clone()); }),
 	}
     }
 
     fn view<'a>(&'a self, store: &'a Store) -> Element<'a, Self::Message> {
 	let list = || {
-	    let mut grid = Grid::with_columns(5);
+	    fn pad<'b>(e: impl Into<Element<'b, M>>) -> Element<'b, M> {
+		container(e)
+		    .padding([0, 0, 0, 10])
+		    .align_y(Vertical::Center)
+		    .into()
+	    }
+	    let mut grid = Grid::with_columns(7);
 
 	    for i in store.invoices() {
-		grid.insert(text(i.id.to_string()));
-		grid.insert(i.customer.name.as_str());
-		grid.insert(text(i.date.format("%Y-%m-%d")));
-		grid.insert(
-		    button("View")
-			.on_press(M::View(i.id.clone()))
-		);
-		grid.insert(
+		let row = [
+		    text(i.id.to_string())
+			.vertical_alignment(Vertical::Center)
+			.into(),
+		    pad(i.customer.name.as_str()),
+		    pad(text(i.date.format("%Y-%m-%d"))),
+		    pad(
+			button("View")
+			    .on_press(M::View(i.id))
+		    ),
 		    button("Generate")
-			.on_press(M::Generate(i.id.clone()))
-		);
+			.on_press(M::Generate(i.id))
+			.into(),
+		    button("Export")
+			.on_press(M::Export(i.id))
+			.style(iced::theme::Button::Secondary)
+			.into(),
+		    button("X")
+			.style(iced::theme::Button::Destructive)
+			.on_press(M::Delete(i.id))
+			.into(),
+		];
+
+		for e in row {
+		    grid.insert(e);
+		}
 	    }
 
 	    column![
 		button("New")
 		    .on_press(M::New),
-		grid,
+                Scrollable::new(
+                    container(grid)
+                        .width(Length::Fill),
+                )
 	    ].into()
 	};
 	match &self.page {
@@ -234,6 +279,9 @@ impl Tab for Invoices {
 		    	),
 			ti("Amount",	&r.amount,	move |x| M::RecordSetAmount(n, x)),
 			ti("Price",	&r.price,	move |x| M::RecordSetPrice(n, x)),
+			button("C")
+			    .style(iced::theme::Button::Secondary)
+			    .on_press(M::RecordCopy(n)),
 			button("X")
 			    .style(iced::theme::Button::Destructive)
 			    .on_press(M::RecordRemove(n)),
blob - 1e547d8e0dfd7aefe0fad488d0f7570b271829be
blob + b1cb8bec6d6f795198fb842b918f58bf7de4a36e
--- src/gui/mod.rs
+++ src/gui/mod.rs
@@ -1,6 +1,6 @@
 use std::fmt::Debug;
 
-use iced::{font::Family, Font, Sandbox, Element, Settings};
+use iced::{font::Family, Theme, Font, Sandbox, Element, Settings};
 use iced_aw::{Tabs, TabLabel};
 use self::business::{BusinessTab, BusinessMessage};
 use self::overview::{Overview, OverviewMessage};
@@ -103,6 +103,10 @@ impl Sandbox for App {
 
 	header.into()
     }
+
+    fn theme(&self) -> Theme {
+	self.store.data().theme.into()
+    }
 }
 
 #[cfg(target_os = "openbsd")]
blob - b46678c910d30fe6d4156d57b2b03fc112d5ec2f
blob + 05713691edc77b71908e1ebbea616338d5c73e20
--- src/gui/overview.rs
+++ src/gui/overview.rs
@@ -1,4 +1,4 @@
-use iced::{Element, widget::{text, column}};
+use iced::{Element, widget::{text, column, radio}};
 use OverviewMessage as M;
 
 // Features:
@@ -8,10 +8,11 @@ use OverviewMessage as M;
 
 #[derive(Debug, Clone)]
 pub enum OverviewMessage {
+    SelectTheme(MyTheme),
 }
 
 
-use super::{Tab, store::Store};
+use super::{Tab, store::{Store, MyTheme}};
 
 #[derive(Default)]
 pub struct Overview {
@@ -19,14 +20,34 @@ pub struct Overview {
 
 impl Tab for Overview {
     type Message = M;
-    fn update(&mut self, msg: Self::Message, _store: &mut Store) {
+    fn update(&mut self, msg: Self::Message, store: &mut Store) {
 	match msg {
+	    M::SelectTheme(t)	=> {
+		store.data_mut().theme = t;
+		store.save();
+	    },
 	}
     }
 
-    fn view<'a>(&'a self, _store: &'a Store) -> Element<'a, Self::Message> {
+    fn view<'a>(&'a self, store: &'a Store) -> Element<'a, Self::Message> {
+	let rs = 10;
 	column![
 	    text("This will be an overview"),
+	    text("Select a theme:"),
+	    radio(
+		"Light",
+		MyTheme::Light,
+		Some(store.data().theme),
+		M::SelectTheme,
+	    )
+		.size(rs),
+	    radio(
+		"Dark",
+		MyTheme::Dark,
+		Some(store.data().theme),
+		M::SelectTheme,
+	    )
+		.size(rs),
 	].into()
     }
 }
blob - 7427421bfeefa423eb09759466d9a62c28242836
blob + 06a8726bc4ec464caba1c098717e9573ba20c132
--- src/gui/store.rs
+++ src/gui/store.rs
@@ -1,9 +1,16 @@
-use std::{io::{self, BufReader, BufWriter}, path::{Path, PathBuf}, fs::File};
+use std::{io::{self, BufReader, BufWriter}, path::{Path, PathBuf}, fs::File, ops::Not};
 use chrono::{Utc, Datelike};
+use iced::Theme;
 use serde::{Serialize, Deserialize};
-
 use crate::data::{Customer, Business, Invoice, InvoiceId, CustomerId};
 
+#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
+pub enum MyTheme {
+    #[default]
+    Light,
+    Dark
+}
+
 #[derive(Default, Serialize, Deserialize)]
 pub struct Data {
     #[serde(default = "default_output_dir")]
@@ -11,6 +18,8 @@ pub struct Data {
     pub business: Business,
     pub customers: Vec<Customer>,
     pub invoices: Vec<Invoice>,
+    #[serde(default)]
+    pub theme: MyTheme,
 }
 
 fn default_output_dir() -> PathBuf {
@@ -52,6 +61,13 @@ impl Store {
 	}
     }
 
+    pub fn data(&self) -> &Data {
+	&self.data
+    }
+    pub fn data_mut(&mut self) -> &mut Data {
+	&mut self.data
+    }
+
     pub fn output_dir(&self) -> &Path {
 	&self.data.output_dir
     }
@@ -123,6 +139,11 @@ impl Store {
 	    },
 	}
     }
+    pub fn remove_invoice(&mut self, id: InvoiceId) {
+	self
+	    .invoices_mut()
+	    .retain(|i| i.id != id)
+    }
     pub fn next_invoice_id(&self) -> InvoiceId {
 	let now = Utc::now();
 	let year = now.year() as u16;
@@ -140,3 +161,24 @@ impl Store {
 	}
     }
 }
+
+
+impl Not for MyTheme {
+    type Output = Self;
+
+    fn not(self) -> Self::Output {
+	match self {
+	    Self::Light	=> Self::Dark,
+	    Self::Dark	=> Self::Light,
+	}
+    }
+}
+
+impl Into<Theme> for MyTheme {
+    fn into(self) -> Theme {
+	match self {
+	    Self::Light	=> Theme::Light,
+	    Self::Dark	=> Theme::Dark,
+	}
+    }
+}
blob - /dev/null
blob + 7a7de2361f2f014e95bb23ba8eb801f7ac786427 (mode 644)
--- /dev/null
+++ src/datev.rs
@@ -0,0 +1,51 @@
+use std::{io::Result, path::Path};
+use chrono::{NaiveDateTime, NaiveTime};
+use datev_types::{buchung::{Buchung, SollHabenKennzeichen}, Buchungsstapel, header::{Header, Kennzeichen, BuchungsTyp}};
+use crate::data::{Invoice, Record};
+
+impl Invoice {
+    pub fn export(&self, path: &Path) -> Result<()> {
+	let buchung = |r: &Record| {
+	    let money = r.count * r.price;
+	    let soll_haben_kennzeichen = if money >= 0.0 {
+		SollHabenKennzeichen::Soll
+	    } else {
+		SollHabenKennzeichen::Haben
+	    };
+	    Buchung {
+		soll_haben_kennzeichen,
+		stück: Some(r.count.into()),
+		umsatz: money.into(),
+		beleg_datum: r.date,
+		sachverhalt: Some(r.description.clone()),
+		..Buchung::default()
+	    }
+	};
+	let b = Buchungsstapel {
+	    header: Header {
+		kennzeichen: Kennzeichen::DTVF,
+		format_name: "Rechnung".into(),
+		format_kategorie: 21,
+		format_version: 12,
+		erzeugt_am: NaiveDateTime::new(self.date, NaiveTime::MIN),
+		mandantennummer: self.customer.id.0 as u32,
+		bezeichnung: Some(format!("Rechnung für {}", self.customer.name)),
+		buchungstyp: Some(BuchungsTyp::Finanzbuchführung),
+		anwendungsinformation: Some("Accounthing2".into()),
+		..Header::default()
+	    },
+	    buchungen: self
+		.records
+		.iter()
+		.map(buchung)
+		.collect(),
+	};
+
+	let mut wtr = csv::Writer::from_path(path)?;
+	wtr.serialize(b.header)?;
+	for b in b.buchungen {
+	    wtr.serialize(b)?;
+	}
+	wtr.flush()
+    }
+}
blob - 52192092b6802ebfef2974a674ae328f7affec5e
blob + 66af9654178600949c54f28509efb8d82a6a4e84
--- src/main.rs
+++ src/main.rs
@@ -2,6 +2,7 @@
 mod data;
 mod gui;
 mod pdf;
+mod datev;
 
 fn main() -> iced::Result {
     crate::gui::run()
blob - 4564718cb38342c87b6993b7df6a0e5987a273d2
blob + db051763565916da6f02e5884337402e88d54431
--- src/pdf/mod.rs
+++ src/pdf/mod.rs
@@ -1,4 +1,4 @@
 mod elements;
 mod render;
 
-pub use render::{render, render_to_file};
+pub use render::render_to_file;
blob - 58ca314a3aaa94c102422f811ff5020eb76ef8d0
blob + 990d7a2f83d4724350d97346e92d90be001905ae
--- src/pdf/render.rs
+++ src/pdf/render.rs
@@ -21,6 +21,39 @@ const FONT_DIRS: &[&str] = &[
 ];
 const DEFAULT_FONT_NAME: &str = "LiberationSans";
 
+enum OptElem<E: Element> {
+    Some(E),
+    None,
+}
+
+impl<E: Element> OptElem<E> {
+    fn has(&self) -> bool {
+	matches!(self, Self::Some(_))
+    }
+}
+
+trait Elem: Sized {
+    type E: Element;
+    fn get(self) -> Option<Self::E>;
+}
+
+impl<E: Element> Elem for E {
+    type E = Self;
+    fn get(self) -> Option<Self::E> {
+	Some(self)
+    }
+}
+
+impl<E: Element> Elem for OptElem<E> {
+    type E = E;
+    fn get(self) -> Option<Self::E> {
+	match self {
+	    Self::Some(x) => Some(x),
+	    Self::None => None,
+	}
+    }
+}
+
 macro_rules! doc {
     [$($e:expr),* $(,)?] => {
 	{
@@ -32,7 +65,10 @@ macro_rules! doc {
 		.unwrap();
 	    let mut doc = Document::new(default_font);
 	    $(
-		doc.push($e);
+		match $e.get() {
+		    Some(e) => doc.push(e),
+		    None => {},
+		}
 	    )*
 	    doc
 	}
@@ -53,6 +89,15 @@ fn text(text: impl Into<String>, style: Style) -> Text
     Text::new(StyledString::new(text, style))
 }
 
+fn opttext(text: impl Into<String>, style: Style) -> OptElem<Text> {
+    let s = text.into();
+    if s.is_empty() {
+	OptElem::None
+    } else {
+	OptElem::Some(Text::new(StyledString::new(s, style)))
+    }
+}
+
 pub fn render_to_file(invoice: &Invoice, path: &Path) -> Result<(), Error> {
     let doc = render(invoice);
     doc.render_to_file(path)
@@ -69,11 +114,23 @@ pub fn render(invoice: &Invoice) -> Document {
     let s16 = Style::new().with_font_size(16);
     let s28 = Style::new().with_font_size(28);
 
+    let o1 = opttext(&cus.name2, s10);
+    let o2 = opttext(&cus.name3, s10);
+    let mut len = invoice.records.len() as i32;
+    if o1.has() {
+	len += 1;
+    }
+    if o2.has() {
+	len += 1;
+    }
+
     let mut doc = doc! [
 	Paragraph::new(&biz.name).aligned(Alignment::Center).styled(s28.bold()),
 	Break::new(3),
 	UnderlinedText::new(format!("{}, {}, {}", biz.owner_name, biz.address, biz.zip_city), s8),
 	text(&cus.name, s12),
+	o1,
+	o2,
 	text(&cus.address, s12),
 	text(&cus.zip_city, s12),
 	Break::new(1),
@@ -89,7 +146,7 @@ pub fn render(invoice: &Invoice) -> Document {
 	text("da Kleinunternehmer gemäß $ 19 USTG.", s10),
 	text("", s10),
 	text("Vielen Dank für Ihren Auftrag und Ihr Vertrauen.", s10),
-	Break::new(18 - invoice.records.len() as i32),
+	Break::new(18 - len),
 	HorizontalLine,
 	footer(&biz, s10),
     ];
@@ -156,7 +213,7 @@ fn table2(records: &[Record], style: Style) -> TableLa
     let mut table = table! {
 	(1, 1) => [
 	    vec![
-		Box::new(Paragraph::new(" Netto").styled(style)),
+		Box::new(Paragraph::new(" Brutto").styled(style)),
 		Box::new(Paragraph::new(format!("{total:.2} EUR ")).aligned(Alignment::Right).styled(style)),
 	    ]
 	]