diff --git a/Furious/Externals/GenTranslation.py b/Furious/Externals/GenTranslation.py
index d6932a6..32460c3 100644
--- a/Furious/Externals/GenTranslation.py
+++ b/Furious/Externals/GenTranslation.py
@@ -191,6 +191,14 @@ TRANSLATION = {
"ZH": "从剪贴板导入JSON配置",
"isReviewed": "True"
},
+ "Scan QR Code On The Screen": {
+ "source": [
+ "Furious.TrayActions.Import"
+ ],
+ "RU": "Отсканируйте QR-код на экране",
+ "ZH": "扫描屏幕上的二维码",
+ "isReviewed": "True"
+ },
"Set Indent": {
"source": [
"Furious.Widget.IndentSpinBox"
diff --git a/Furious/Frozenlib/AppResources.py b/Furious/Frozenlib/AppResources.py
index 60e4e56..a9a42d5 100644
--- a/Furious/Frozenlib/AppResources.py
+++ b/Furious/Frozenlib/AppResources.py
@@ -280,7 +280,7 @@ a.5.5 0 0 1-.478\
-.647L9.89 2.41 \
4.157 8.5z\x22/>\x0d\x0a<\
/svg>\
-\x00\x00\x03\xd7\
+\x00\x00\x03\xd9\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
@@ -290,60 +290,60 @@ ll=\x22currentColor\
\x22 class=\x22bi bi-p\
erson-gear\x22 view\
Box=\x220 0 16 16\x22>\
-\x0a \x0a\
-\
+\x0d\x0a \
+\x0d\x0a\
\x00\x00\x02\x12\
<\
svg xmlns=\x22http:\
@@ -914,7 +914,7 @@ zM3 4a1 1 0 0 1 \
-1 1H4a1 1 0 0 1\
-1-1V4z\x22/>\x0d\x0a\
-\x00\x00\x01\xcc\
+\x00\x00\x01\xce\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
@@ -923,28 +923,28 @@ svg xmlns=\x22http:\
ll=\x22currentColor\
\x22 class=\x22bi bi-f\
older2\x22 viewBox=\
-\x220 0 16 16\x22>\x0a <\
-path d=\x22M1 3.5A1\
-.5 1.5 0 0 1 2.5\
- 2h2.764c.958 0 \
-1.76.56 2.311 1.\
-184C7.985 3.648 \
-8.48 4 9 4h4.5A1\
-.5 1.5 0 0 1 15 \
-5.5v7a1.5 1.5 0 \
-0 1-1.5 1.5h-11A\
-1.5 1.5 0 0 1 1 \
-12.5zM2.5 3a.5.5\
- 0 0 0-.5.5V6h12\
-v-.5a.5.5 0 0 0-\
-.5-.5H9c-.964 0-\
-1.71-.629-2.174-\
-1.154C6.374 3.33\
-4 5.82 3 5.264 3\
-zM14 7H2v5.5a.5.\
-5 0 0 0 .5.5h11a\
-.5.5 0 0 0 .5-.5\
-z\x22/>\x0a\
+\x220 0 16 16\x22>\x0d\x0a \
+\x0d\x0a\
\x00\x00\x02U\
<\
svg xmlns=\x22http:\
@@ -1462,7 +1462,7 @@ A7.568 7.568 0 0\
96 5.054-1.902Z\x22\
/>\x0d\x0a \x0d\x0a\
-\x00\x00\x01]\
+\x00\x00\x01`\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
@@ -1472,20 +1472,20 @@ ll=\x22currentColor\
\x22 class=\x22bi bi-a\
rrow-clockwise\x22 \
viewBox=\x220 0 16 \
-16\x22>\x0a \x0a \x0a\
+16\x22>\x0d\x0a \x0d\x0a \x0d\x0a\
\x00\x00\x02<\
<\
svg xmlns=\x22http:\
@@ -1696,6 +1696,53 @@ c-.625.626-.94 1\
.896 5.054-1.902\
Z\x22 />\x0d\x0a \x0d\x0a<\
/svg>\
+\x00\x00\x02\xc9\
+<\
+svg xmlns=\x22http:\
+//www.w3.org/200\
+0/svg\x22 width=\x2216\
+\x22 height=\x2216\x22 fi\
+ll=\x22currentColor\
+\x22 class=\x22bi bi-q\
+r-code-scan\x22 vie\
+wBox=\x220 0 16 16\x22\
+>\x0a \x0a \
+ \x0a \
+ \
+\x0a \x0a \x0a\
\x00\x00\x03\x8b\
<\
svg xmlns=\x22http:\
@@ -2674,7 +2721,7 @@ l5.732-6.09H9a.5\
47L9.89 2.41 4.1\
57 8.5z\x22/>\x0d\x0a\
-\x00\x00\x03\xe4\
+\x00\x00\x03\xe6\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
@@ -2684,61 +2731,61 @@ ll=\x22currentColor\
\x22 class=\x22bi bi-p\
erson-gear\x22 view\
Box=\x220 0 16 16\x22>\
-\x0a \x0a\
+\x0d\x0a \x0d\x0a<\
+/svg>\
\x00\x00\x02,\
<\
svg xmlns=\x22http:\
@@ -3185,7 +3232,7 @@ h7a1 1 0 0 1 1 1\
v10a1 1 0 0 1-1 \
1H4a1 1 0 0 1-1-\
1V4z\x22/>\x0d\x0a\
-\x00\x00\x01\xd9\
+\x00\x00\x01\xdb\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
@@ -3194,29 +3241,29 @@ svg xmlns=\x22http:\
ll=\x22currentColor\
\x22 class=\x22bi bi-f\
older2\x22 viewBox=\
-\x220 0 16 16\x22>\x0a <\
-path fill=\x22white\
-\x22 d=\x22M1 3.5A1.5 \
-1.5 0 0 1 2.5 2h\
-2.764c.958 0 1.7\
-6.56 2.311 1.184\
-C7.985 3.648 8.4\
-8 4 9 4h4.5A1.5 \
-1.5 0 0 1 15 5.5\
-v7a1.5 1.5 0 0 1\
--1.5 1.5h-11A1.5\
- 1.5 0 0 1 1 12.\
-5zM2.5 3a.5.5 0 \
-0 0-.5.5V6h12v-.\
-5a.5.5 0 0 0-.5-\
-.5H9c-.964 0-1.7\
-1-.629-2.174-1.1\
-54C6.374 3.334 5\
-.82 3 5.264 3zM1\
-4 7H2v5.5a.5.5 0\
- 0 0 .5.5h11a.5.\
-5 0 0 0 .5-.5z\x22/\
->\x0a\
+\x220 0 16 16\x22>\x0d\x0a \
+\x0d\x0a\
\x00\x00\x02\x96\
<\
svg xmlns=\x22http:\
@@ -3485,7 +3532,7 @@ white\x22 d=\x22M7.009\
.126 3.936-.896 \
5.054-1.902Z\x22/>\x0d\
\x0a\
-\x00\x00\x01w\
+\x00\x00\x01z\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
@@ -3495,22 +3542,22 @@ ll=\x22currentColor\
\x22 class=\x22bi bi-a\
rrow-clockwise\x22 \
viewBox=\x220 0 16 \
-16\x22>\x0a \x0a \x0a\
-\
+16\x22>\x0d\x0a \x0d\x0a \x0d\x0a\
\x00\x00\x02I\
<\
svg xmlns=\x22http:\
@@ -3593,6 +3640,57 @@ white\x22 d=\x22M11 1a\
4a.5.5 0 0 1-1 0\
V3a2 2 0 0 0-2-2\
z\x22/>\x0d\x0a\
+\x00\x00\x03\x0a\
+<\
+svg xmlns=\x22http:\
+//www.w3.org/200\
+0/svg\x22 width=\x2216\
+\x22 height=\x2216\x22 fi\
+ll=\x22currentColor\
+\x22 class=\x22bi bi-q\
+r-code-scan\x22 vie\
+wBox=\x220 0 16 16\x22\
+>\x0a \x0a \x0a \x0a \x0a \x0a\
\x00\x00\x03\xa5\
<\
svg xmlns=\x22http:\
@@ -4182,6 +4280,10 @@ qt_resource_name = b"\
\x00r\
\x00o\x00c\x00k\x00e\x00t\x00-\x00t\x00a\x00k\x00e\x00o\x00f\x00f\x00-\x00d\x00a\
\x00r\x00k\x00.\x00s\x00v\x00g\
+\x00\x10\
+\x0d\xeaG\x07\
+\x00q\
+\x00r\x00-\x00c\x00o\x00d\x00e\x00-\x00s\x00c\x00a\x00n\x00.\x00s\x00v\x00g\
\x00\x0b\
\x0d\xd7\xadG\
\x00s\
@@ -4251,162 +4353,166 @@ qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x10\x00\x02\x00\x00\x00*\x00\x00\x00\x03\
+\x00\x00\x00\x10\x00\x02\x00\x00\x00+\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x01\x00\x00+\xd6\
-\x00\x00\x01\x93\xdal,\x95\
-\x00\x00\x04\xa0\x00\x02\x00\x00\x00#\x00\x00\x00-\
+\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x01\x00\x00+\xd8\
+\x00\x00\x01\x96\xd8gH\x1b\
+\x00\x00\x04\xc6\x00\x02\x00\x00\x00$\x00\x00\x00.\
\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x03 \x00\x00\x00\x00\x00\x01\x00\x00I_\
-\x00\x00\x01\x93\xdal,\x96\
-\x00\x00\x03`\x00\x00\x00\x00\x00\x01\x00\x00O\xb4\
-\x00\x00\x01\x93\xdal,\x97\
-\x00\x00\x04:\x00\x00\x00\x00\x00\x01\x00\x00]\xa7\
-\x00\x00\x01\x93\xdal,\x98\
-\x00\x00\x03\xd4\x00\x00\x00\x00\x00\x01\x00\x00Y\x0d\
-\x00\x00\x01\x93\xdal,\x93\
-\x00\x00\x02H\x00\x00\x00\x00\x00\x01\x00\x005\x07\
-\x00\x00\x01\x93\xdal,\x94\
-\x00\x00\x02\xfa\x00\x00\x00\x00\x00\x01\x00\x00F\xe2\
-\x00\x00\x01\x93\xdal,\x94\
+\x00\x00\x03 \x00\x00\x00\x00\x00\x01\x00\x00Ic\
+\x00\x00\x01\x96\xd8gH\x1c\
+\x00\x00\x03`\x00\x00\x00\x00\x00\x01\x00\x00O\xb8\
+\x00\x00\x01\x96\xd8gH\x1e\
+\x00\x00\x04:\x00\x00\x00\x00\x00\x01\x00\x00]\xae\
+\x00\x00\x01\x96\xd8gH\x1e\
+\x00\x00\x03\xd4\x00\x00\x00\x00\x00\x01\x00\x00Y\x14\
+\x00\x00\x01\x96\xd8gH\x19\
+\x00\x00\x02H\x00\x00\x00\x00\x00\x01\x00\x005\x09\
+\x00\x00\x01\x96\xd8gH\x1a\
+\x00\x00\x02\xfa\x00\x00\x00\x00\x00\x01\x00\x00F\xe6\
+\x00\x00\x01\x96\xd8gH\x1a\
\x00\x00\x00\x98\x00\x00\x00\x00\x00\x01\x00\x00\x0a\xea\
-\x00\x00\x01\x93\xdal,\x96\
-\x00\x00\x02&\x00\x00\x00\x00\x00\x01\x00\x003l\
-\x00\x00\x01\x93\xdal,\x93\
-\x00\x00\x04\xf8\x00\x00\x00\x00\x00\x01\x00\x00q\xe1\
-\x00\x00\x01\x93\xdal,\x95\
-\x00\x00\x05\xce\x00\x00\x00\x00\x00\x01\x00\x00\x82\x97\
-\x00\x00\x01\x93\xdal,\x98\
-\x00\x00\x02\x98\x00\x00\x00\x00\x00\x01\x00\x00:\xb7\
-\x00\x00\x01\x93\xdal,\x98\
-\x00\x00\x02|\x00\x00\x00\x00\x00\x01\x00\x008^\
-\x00\x00\x01\x93\xdal,\x96\
-\x00\x00\x01\xd2\x00\x00\x00\x00\x00\x01\x00\x00'\x15\
-\x00\x00\x01\x93\xdal,\x93\
-\x00\x00\x01\xba\x00\x00\x00\x00\x00\x01\x00\x00#u\
-\x00\x00\x01\x93\xdal,\x99\
-\x00\x00\x03\xa8\x00\x00\x00\x00\x00\x01\x00\x00W\xac\
-\x00\x00\x01\x9a\xd9\x08\xa4\xd1\
-\x00\x00\x04\xd0\x00\x00\x00\x00\x00\x01\x00\x00o\x98\
-\x00\x00\x01\x93\xdal,\x96\
+\x00\x00\x01\x96\xd8gH\x1d\
+\x00\x00\x02&\x00\x00\x00\x00\x00\x01\x00\x003n\
+\x00\x00\x01\x96\xd8gH\x18\
+\x00\x00\x05\x1e\x00\x00\x00\x00\x00\x01\x00\x00t\xb5\
+\x00\x00\x01\x96\xd8gH\x1c\
+\x00\x00\x05\xf4\x00\x00\x00\x00\x00\x01\x00\x00\x85k\
+\x00\x00\x01\x96\xd8gH\x1e\
+\x00\x00\x02\x98\x00\x00\x00\x00\x00\x01\x00\x00:\xbb\
+\x00\x00\x01\x96\xd8gH\x1f\
+\x00\x00\x02|\x00\x00\x00\x00\x00\x01\x00\x008b\
+\x00\x00\x01\x96\xd8gH\x1d\
+\x00\x00\x01\xd2\x00\x00\x00\x00\x00\x01\x00\x00'\x17\
+\x00\x00\x01\x96\xd8gH\x19\
+\x00\x00\x01\xba\x00\x00\x00\x00\x00\x01\x00\x00#w\
+\x00\x00\x01\x96\xd8gH \
+\x00\x00\x03\xa8\x00\x00\x00\x00\x00\x01\x00\x00W\xb0\
+\x00\x00\x01\x9a\xdc\xa9\xf2\xb4\
+\x00\x00\x04\xf6\x00\x00\x00\x00\x00\x01\x00\x00rl\
+\x00\x00\x01\x96\xd8gH\x1d\
\x00\x00\x00t\x00\x00\x00\x00\x00\x01\x00\x00\x08\x90\
-\x00\x00\x01\x93\xdal,\x95\
-\x00\x00\x05\x1c\x00\x00\x00\x00\x00\x01\x00\x00s\xb4\
-\x00\x00\x01\x93\xdal,\x94\
+\x00\x00\x01\x96\xd8gH\x1a\
+\x00\x00\x05B\x00\x00\x00\x00\x00\x01\x00\x00v\x88\
+\x00\x00\x01\x96\xd8gH\x19\
\x00\x00\x00Z\x00\x00\x00\x00\x00\x01\x00\x00\x01z\
-\x00\x00\x01\x93\xdal,\x95\
-\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x14?\
-\x00\x00\x01\x93\xdal,\x95\
-\x00\x00\x06\x5c\x00\x00\x00\x00\x00\x01\x00\x00\x8d\xd5\
-\x00\x00\x01\x93\xdal,\x98\
+\x00\x00\x01\x96\xd8gH\x1a\
+\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x14A\
+\x00\x00\x01\x96\xd8gH\x1c\
+\x00\x00\x06\x82\x00\x00\x00\x00\x00\x01\x00\x00\x90\xa9\
+\x00\x00\x01\x96\xd8gH\x1f\
\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x10d\
-\x00\x00\x01\x9a\xd5bh\x19\
-\x00\x00\x03\xf0\x00\x00\x00\x00\x00\x01\x00\x00[M\
-\x00\x00\x01\x93\xdal,\x94\
-\x00\x00\x02\xc2\x00\x00\x00\x00\x00\x01\x00\x00B\xb1\
-\x00\x00\x01\x93\xdal,\x99\
-\x00\x00\x05\x84\x00\x00\x00\x00\x00\x01\x00\x00}a\
-\x00\x00\x01\x93\xdal,\x93\
-\x00\x00\x01N\x00\x00\x00\x00\x00\x01\x00\x00\x16U\
-\x00\x00\x01\x93\xdal,\x98\
-\x00\x00\x04\x8a\x00\x00\x00\x00\x00\x01\x00\x00i0\
-\x00\x00\x01\x93\xdal,\x99\
-\x00\x00\x06<\x00\x00\x00\x00\x00\x01\x00\x00\x8c\xbe\
-\x00\x00\x01\x93\xdal,\x96\
-\x00\x00\x04\x16\x00\x00\x00\x00\x00\x01\x00\x00\x5c\x83\
-\x00\x00\x01\x93\xdal,\x99\
-\x00\x00\x05\xb4\x00\x00\x00\x00\x00\x01\x00\x00~\xdc\
-\x00\x00\x01\x93\xdal,\x98\
-\x00\x00\x06\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x8a\x8f\
-\x00\x00\x01\x93\xdal,\x93\
-\x00\x00\x05:\x00\x00\x00\x00\x00\x01\x00\x00uf\
-\x00\x00\x01\x93\xdal,\x97\
-\x00\x00\x02`\x00\x00\x00\x00\x00\x01\x00\x006\x8e\
-\x00\x00\x01\x9a\xd9\x08\xac.\
-\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00D`\
-\x00\x00\x01\x93\xdal,\x99\
-\x00\x00\x04n\x00\x00\x00\x00\x00\x01\x00\x00e\xa1\
-\x00\x00\x01\x93\xdal,\x99\
-\x00\x00\x04\xb0\x00\x00\x00\x00\x00\x01\x00\x00k\xb1\
-\x00\x00\x01\x96\xe7\xdc\x22W\
-\x00\x00\x01\x86\x00\x00\x00\x00\x00\x01\x00\x00\x1eO\
-\x00\x00\x01\x93\xdal,\x94\
+\x00\x00\x01\x9a\xdc\xa9\xf2\xb4\
+\x00\x00\x03\xf0\x00\x00\x00\x00\x00\x01\x00\x00[T\
+\x00\x00\x01\x96\xd8gH\x1a\
+\x00\x00\x02\xc2\x00\x00\x00\x00\x00\x01\x00\x00B\xb5\
+\x00\x00\x01\x96\xd8gH\x1f\
+\x00\x00\x05\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x805\
+\x00\x00\x01\x96\xd8gH\x17\
+\x00\x00\x01N\x00\x00\x00\x00\x00\x01\x00\x00\x16W\
+\x00\x00\x01\x96\xd8gH\x1e\
+\x00\x00\x04\xb0\x00\x00\x00\x00\x00\x01\x00\x00l\x04\
+\x00\x00\x01\x96\xd8gH \
+\x00\x00\x06b\x00\x00\x00\x00\x00\x01\x00\x00\x8f\x92\
+\x00\x00\x01\x96\xd8gH\x1c\
+\x00\x00\x04\x16\x00\x00\x00\x00\x00\x01\x00\x00\x5c\x8a\
+\x00\x00\x01\x96\xd8gH!\
+\x00\x00\x05\xda\x00\x00\x00\x00\x00\x01\x00\x00\x81\xb0\
+\x00\x00\x01\x96\xd8gH\x1f\
+\x00\x00\x062\x00\x00\x00\x00\x00\x01\x00\x00\x8dc\
+\x00\x00\x01\x96\xd8gH\x18\
+\x00\x00\x05`\x00\x00\x00\x00\x00\x01\x00\x00x:\
+\x00\x00\x01\x96\xd8gH\x1d\
+\x00\x00\x02`\x00\x00\x00\x00\x00\x01\x00\x006\x90\
+\x00\x00\x01\x9a\xdc\xa9\xf2\xb4\
+\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00Dd\
+\x00\x00\x01\x96\xd8gH \
+\x00\x00\x04\x94\x00\x00\x00\x00\x00\x01\x00\x00hu\
+\x00\x00\x01\x96\xd8gH \
+\x00\x00\x04n\x00\x00\x00\x00\x00\x01\x00\x00e\xa8\
+\x00\x00\x01\x9a\xe4\x8d\x18\x03\
+\x00\x00\x04\xd6\x00\x00\x00\x00\x00\x01\x00\x00n\x85\
+\x00\x00\x01\x9a\x8f\x9c\xac\x94\
+\x00\x00\x01\x86\x00\x00\x00\x00\x00\x01\x00\x00\x1eQ\
+\x00\x00\x01\x96\xd8gH\x1a\
\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xca\
-\x00\x00\x01\x93\xdal,\x95\
+\x00\x00\x01\x96\xd8gH\x1c\
\x00\x00\x00(\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01\x93\xdal,\x93\
-\x00\x00\x02\x10\x00\x00\x00\x00\x00\x01\x00\x00/\xd6\
-\x00\x00\x01\x93\xdal,\x9f\
-\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x01\x00\x00\xb4\x0a\
-\x00\x00\x01\x93\xdal,\x9c\
-\x00\x00\x03 \x00\x00\x00\x00\x00\x01\x00\x00\xcai\
-\x00\x00\x01\x93\xdal,\x9d\
-\x00\x00\x03\xd4\x00\x00\x00\x00\x00\x01\x00\x00\xd2`\
-\x00\x00\x01\x93\xdal,\x9a\
-\x00\x00\x02H\x00\x00\x00\x00\x00\x01\x00\x00\xbdo\
-\x00\x00\x01\x93\xdal,\x9b\
-\x00\x00\x02\xfa\x00\x00\x00\x00\x00\x01\x00\x00\xc7\xdf\
-\x00\x00\x01\x93\xdal,\x9b\
-\x00\x00\x00\x98\x00\x00\x00\x00\x00\x01\x00\x00\x9a\xb0\
-\x00\x00\x01\x93\xdal,\x9d\
-\x00\x00\x02&\x00\x00\x00\x00\x00\x01\x00\x00\xbb\xc7\
-\x00\x00\x01\x93\xdal,\x9a\
-\x00\x00\x04\xf8\x00\x00\x00\x00\x00\x01\x00\x00\xe3\xaf\
-\x00\x00\x01\x93\xdal,\x9c\
-\x00\x00\x02|\x00\x00\x00\x00\x00\x01\x00\x00\xc0\xe0\
-\x00\x00\x01\x93\xdal,\x9d\
-\x00\x00\x01\xd2\x00\x00\x00\x00\x00\x01\x00\x00\xaf<\
-\x00\x00\x01\x93\xdal,\x9a\
-\x00\x00\x01\xba\x00\x00\x00\x00\x00\x01\x00\x00\xab\x8f\
-\x00\x00\x01\x93\xdal,\x9e\
-\x00\x00\x03\xa8\x00\x00\x00\x00\x00\x01\x00\x00\xd0\xe5\
-\x00\x00\x01\x9a\xd9\x09m\x86\
-\x00\x00\x04\xd0\x00\x00\x00\x00\x00\x01\x00\x00\xe1L\
-\x00\x00\x01\x93\xdal,\x9d\
-\x00\x00\x00t\x00\x00\x00\x00\x00\x01\x00\x00\x98<\
-\x00\x00\x01\x93\xdal,\x9c\
-\x00\x00\x05\x1c\x00\x00\x00\x00\x00\x01\x00\x00\xe5\x9c\
-\x00\x00\x01\x93\xdal,\x9b\
-\x00\x00\x00Z\x00\x00\x00\x00\x00\x01\x00\x00\x91\x19\
-\x00\x00\x01\x93\xdal,\x9b\
-\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\xa4,\
-\x00\x00\x01\x93\xdal,\x9c\
-\x00\x00\x06\x5c\x00\x00\x00\x00\x00\x01\x00\x00\xf0L\
-\x00\x00\x01\x93\xdal,\x9d\
-\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\xa0D\
-\x00\x00\x01\x9a\xd5c1\xd5\
-\x00\x00\x03\xf0\x00\x00\x00\x00\x00\x01\x00\x00\xd4\xad\
-\x00\x00\x01\x93\xdal,\x9b\
-\x00\x00\x02\xc2\x00\x00\x00\x00\x00\x01\x00\x00\xc3z\
-\x00\x00\x01\x93\xdal,\x9e\
-\x00\x00\x05\x84\x00\x00\x00\x00\x00\x01\x00\x00\xe7h\
-\x00\x00\x01\x93\xdal,\x9a\
-\x00\x00\x04\x8a\x00\x00\x00\x00\x00\x01\x00\x00\xda\xca\
-\x00\x00\x01\x93\xdal,\x9e\
-\x00\x00\x06<\x00\x00\x00\x00\x00\x01\x00\x00\xef(\
-\x00\x00\x01\x93\xdal,\x9d\
-\x00\x00\x04\x16\x00\x00\x00\x00\x00\x01\x00\x00\xd5\xf0\
-\x00\x00\x01\x93\xdal,\x9f\
-\x00\x00\x05\xb4\x00\x00\x00\x00\x00\x01\x00\x00\xe8\xf0\
-\x00\x00\x01\x93\xdal,\x9d\
-\x00\x00\x06\x0c\x00\x00\x00\x00\x00\x01\x00\x00\xec\xdf\
-\x00\x00\x01\x93\xdal,\x9a\
-\x00\x00\x02`\x00\x00\x00\x00\x00\x01\x00\x00\xbf\x03\
-\x00\x00\x01\x9a\xd9\x09\x9e\xcd\
-\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00\xc56\
-\x00\x00\x01\x93\xdal,\x9e\
-\x00\x00\x04n\x00\x00\x00\x00\x00\x01\x00\x00\xd7!\
-\x00\x00\x01\x93\xdal,\x9e\
-\x00\x00\x04\xb0\x00\x00\x00\x00\x00\x01\x00\x00\xddX\
-\x00\x00\x01\x96\xe7\xdc\x22W\
-\x00\x00\x01\x86\x00\x00\x00\x00\x00\x01\x00\x00\xa6\x5c\
-\x00\x00\x01\x93\xdal,\x9b\
-\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x01\x00\x00\x9e\x9d\
-\x00\x00\x01\x93\xdal,\x9c\
-\x00\x00\x00(\x00\x00\x00\x00\x00\x01\x00\x00\x8f\x92\
-\x00\x00\x01\x93\xdal,\x9a\
-\x00\x00\x02\x10\x00\x00\x00\x00\x00\x01\x00\x00\xb8\x17\
-\x00\x00\x01\x93\xdal,\x9f\
+\x00\x00\x01\x96\xd8gH\x17\
+\x00\x00\x02\x10\x00\x00\x00\x00\x00\x01\x00\x00/\xd8\
+\x00\x00\x01\x96\xd8gH(\
+\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x01\x00\x00\xb6\xe0\
+\x00\x00\x01\x96\xd8gH$\
+\x00\x00\x03 \x00\x00\x00\x00\x00\x01\x00\x00\xcdA\
+\x00\x00\x01\x96\xd8gH%\
+\x00\x00\x03\xd4\x00\x00\x00\x00\x00\x01\x00\x00\xd5;\
+\x00\x00\x01\x96\xd8gH\x22\
+\x00\x00\x02H\x00\x00\x00\x00\x00\x01\x00\x00\xc0E\
+\x00\x00\x01\x96\xd8gH#\
+\x00\x00\x02\xfa\x00\x00\x00\x00\x00\x01\x00\x00\xca\xb7\
+\x00\x00\x01\x96\xd8gH#\
+\x00\x00\x00\x98\x00\x00\x00\x00\x00\x01\x00\x00\x9d\x84\
+\x00\x00\x01\x96\xd8gH%\
+\x00\x00\x02&\x00\x00\x00\x00\x00\x01\x00\x00\xbe\x9d\
+\x00\x00\x01\x96\xd8gH!\
+\x00\x00\x05\x1e\x00\x00\x00\x00\x00\x01\x00\x00\xe9\x98\
+\x00\x00\x01\x96\xd8gH$\
+\x00\x00\x02|\x00\x00\x00\x00\x00\x01\x00\x00\xc3\xb8\
+\x00\x00\x01\x96\xd8gH&\
+\x00\x00\x01\xd2\x00\x00\x00\x00\x00\x01\x00\x00\xb2\x12\
+\x00\x00\x01\x96\xd8gH!\
+\x00\x00\x01\xba\x00\x00\x00\x00\x00\x01\x00\x00\xaee\
+\x00\x00\x01\x96\xd8gH'\
+\x00\x00\x03\xa8\x00\x00\x00\x00\x00\x01\x00\x00\xd3\xbd\
+\x00\x00\x01\x9a\xdc\xa9\xf2\xb4\
+\x00\x00\x04\xf6\x00\x00\x00\x00\x00\x01\x00\x00\xe75\
+\x00\x00\x01\x96\xd8gH%\
+\x00\x00\x00t\x00\x00\x00\x00\x00\x01\x00\x00\x9b\x10\
+\x00\x00\x01\x96\xd8gH$\
+\x00\x00\x05B\x00\x00\x00\x00\x00\x01\x00\x00\xeb\x85\
+\x00\x00\x01\x96\xd8gH\x22\
+\x00\x00\x00Z\x00\x00\x00\x00\x00\x01\x00\x00\x93\xed\
+\x00\x00\x01\x96\xd8gH#\
+\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\xa7\x02\
+\x00\x00\x01\x96\xd8gH$\
+\x00\x00\x06\x82\x00\x00\x00\x00\x00\x01\x00\x00\xf65\
+\x00\x00\x01\x96\xd8gH&\
+\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\xa3\x18\
+\x00\x00\x01\x9a\xdc\xa9\xf2\xb5\
+\x00\x00\x03\xf0\x00\x00\x00\x00\x00\x01\x00\x00\xd7\x88\
+\x00\x00\x01\x96\xd8gH\x22\
+\x00\x00\x02\xc2\x00\x00\x00\x00\x00\x01\x00\x00\xc6R\
+\x00\x00\x01\x96\xd8gH&\
+\x00\x00\x05\xaa\x00\x00\x00\x00\x00\x01\x00\x00\xedQ\
+\x00\x00\x01\x96\xd8gH!\
+\x00\x00\x04\xb0\x00\x00\x00\x00\x00\x01\x00\x00\xe0\xb3\
+\x00\x00\x01\x96\xd8gH'\
+\x00\x00\x06b\x00\x00\x00\x00\x00\x01\x00\x00\xf5\x11\
+\x00\x00\x01\x96\xd8gH%\
+\x00\x00\x04\x16\x00\x00\x00\x00\x00\x01\x00\x00\xd8\xcb\
+\x00\x00\x01\x96\xd8gH(\
+\x00\x00\x05\xda\x00\x00\x00\x00\x00\x01\x00\x00\xee\xd9\
+\x00\x00\x01\x96\xd8gH&\
+\x00\x00\x062\x00\x00\x00\x00\x00\x01\x00\x00\xf2\xc8\
+\x00\x00\x01\x96\xd8gH!\
+\x00\x00\x02`\x00\x00\x00\x00\x00\x01\x00\x00\xc1\xd9\
+\x00\x00\x01\x9a\xdc\xa9\xf2\xb5\
+\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00\xc8\x0e\
+\x00\x00\x01\x96\xd8gH'\
+\x00\x00\x04\x94\x00\x00\x00\x00\x00\x01\x00\x00\xdd\x0a\
+\x00\x00\x01\x96\xd8gH'\
+\x00\x00\x04n\x00\x00\x00\x00\x00\x01\x00\x00\xd9\xfc\
+\x00\x00\x01\x9a\xe4\x8e\x91\xcc\
+\x00\x00\x04\xd6\x00\x00\x00\x00\x00\x01\x00\x00\xe3A\
+\x00\x00\x01\x9a\x8f\x9c\xac\x94\
+\x00\x00\x01\x86\x00\x00\x00\x00\x00\x01\x00\x00\xa92\
+\x00\x00\x01\x96\xd8gH#\
+\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x01\x00\x00\xa1q\
+\x00\x00\x01\x96\xd8gH%\
+\x00\x00\x00(\x00\x00\x00\x00\x00\x01\x00\x00\x92f\
+\x00\x00\x01\x96\xd8gH!\
+\x00\x00\x02\x10\x00\x00\x00\x00\x00\x01\x00\x00\xba\xed\
+\x00\x00\x01\x96\xd8gH(\
"
def qInitResources():
diff --git a/Furious/TrayActions/Import.py b/Furious/TrayActions/Import.py
index b2fcb42..42f0bd0 100644
--- a/Furious/TrayActions/Import.py
+++ b/Furious/TrayActions/Import.py
@@ -24,13 +24,21 @@ from Furious.Qt import gettext as _
from PySide6.QtWidgets import QApplication, QFileDialog
+from PIL import Image
+
+from typing import Callable, Union
+
import os
+import mss
+import zxingcpp
import logging
+import functools
__all__ = [
'ImportFromFileAction',
'ImportURIFromClipboardAction',
'ImportJSONFromClipboardAction',
+ 'ImportQRCodeOnTheScreenAction',
'ImportAction',
]
@@ -52,7 +60,7 @@ def showMBoxImportError(clipboard: str):
mbox.open()
-def importItemFromClipboard(clipboard: str):
+def importURIFromClipboard(clipboard: str):
factory = configFactoryFromAny(clipboard)
if not factory.isValid():
@@ -68,6 +76,40 @@ def importItemFromClipboard(clipboard: str):
mbox.open()
+def importURIs(*uris, failureCallback: Union[Callable[[], None], None] = None):
+ imported = list()
+ rowIndex = len(Storage.UserServers())
+
+ for uri in uris:
+ factory = configFactoryFromAny(uri)
+
+ if factory.isValid():
+ APP().mainWindow.appendNewItemByFactory(factory)
+
+ imported.append(factory.getExtras('remark'))
+
+ if len(imported) == 0:
+ if callable(failureCallback):
+ failureCallback()
+ else:
+ if len(imported) == 1:
+ # Fall back to single
+ mbox = MBoxImportSuccess(icon=AppQMessageBox.Icon.Information)
+ mbox.remark = imported[0]
+ mbox.setText(mbox.customText())
+
+ # Show the MessageBox asynchronously
+ mbox.open()
+ else:
+ mbox = MBoxImportMultiSuccess(icon=AppQMessageBox.Icon.Information)
+ mbox.imported = imported
+ mbox.rowIndex = rowIndex
+ mbox.setText(mbox.customText())
+
+ # Show the MessageBox asynchronously
+ mbox.open()
+
+
class MBoxImportError(AppQMessageBox):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -87,8 +129,8 @@ class MBoxImportMultiSuccess(AppQMessageBox):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- self.imported = []
- self.rowCount = 0
+ self.imported = list()
+ self.rowIndex = 0
self.setWindowTitle(_('Import'))
self.setIcon(AppQMessageBox.Icon.Information)
@@ -101,7 +143,7 @@ class MBoxImportMultiSuccess(AppQMessageBox):
list(
f'{index + 1} - {remark}. '
+ _('Imported to row')
- + f' {self.rowCount + index + 1}'
+ + f' {self.rowIndex + index + 1}'
for index, remark in enumerate(self.imported)
)
)
@@ -204,42 +246,16 @@ class ImportURIFromClipboardAction(AppQAction):
clipboard = QApplication.clipboard().text().strip()
try:
- split = clipboard.split('\n')
+ uris = clipboard.split('\n')
except Exception:
# Any non-exit exceptions
- importItemFromClipboard(clipboard)
+ importURIFromClipboard(clipboard)
else:
- imported = list()
- rowCount = len(Storage.UserServers())
-
- for uri in split:
- factory = configFactoryFromAny(uri)
-
- if factory.isValid():
- APP().mainWindow.appendNewItemByFactory(factory)
-
- imported.append(factory.getExtras('remark'))
-
- if len(imported) == 0:
- showMBoxImportError(clipboard)
- else:
- if len(imported) == 1:
- # Fall back to single
- mbox = MBoxImportSuccess(icon=AppQMessageBox.Icon.Information)
- mbox.remark = imported[0]
- mbox.setText(mbox.customText())
-
- # Show the MessageBox asynchronously
- mbox.open()
- else:
- mbox = MBoxImportMultiSuccess(icon=AppQMessageBox.Icon.Information)
- mbox.imported = imported
- mbox.rowCount = rowCount
- mbox.setText(mbox.customText())
-
- # Show the MessageBox asynchronously
- mbox.open()
+ importURIs(
+ *uris,
+ failureCallback=functools.partial(showMBoxImportError, clipboard),
+ )
class ImportJSONFromClipboardAction(AppQAction):
@@ -249,7 +265,39 @@ class ImportJSONFromClipboardAction(AppQAction):
def triggeredCallback(self, checked):
clipboard = QApplication.clipboard().text().strip()
- importItemFromClipboard(clipboard)
+ importURIFromClipboard(clipboard)
+
+
+class ImportQRCodeOnTheScreenAction(AppQAction):
+ def __init__(self, **kwargs):
+ super().__init__(
+ _('Scan QR Code On The Screen'),
+ icon=bootstrapIcon('qr-code-scan.svg'),
+ **kwargs,
+ )
+
+ self.sct = mss.mss()
+
+ def triggeredCallback(self, checked):
+ uris = list()
+
+ for index, monitor in enumerate(self.sct.monitors[1:], start=1):
+ frame = self.sct.grab(monitor)
+ # Convert raw BGRA bytes to PIL Image
+ image = Image.frombytes(
+ 'RGB', (frame.width, frame.height), frame.bgra, 'raw', 'BGRX'
+ )
+
+ barcodes = zxingcpp.read_barcodes(image)
+
+ for barcode in barcodes:
+ data = barcode.text
+
+ logger.debug(f'found QR code on monitor \'{index}\': {data}')
+
+ uris.append(data)
+
+ importURIs(*uris)
class ImportAction(AppQAction):
@@ -260,6 +308,8 @@ class ImportAction(AppQAction):
menu=AppQMenu(
ImportURIFromClipboardAction(),
ImportJSONFromClipboardAction(),
+ AppQSeperator(),
+ ImportQRCodeOnTheScreenAction(),
),
useActionGroup=False,
checkable=True,
diff --git a/Furious/Widget/UserServersQTableWidget.py b/Furious/Widget/UserServersQTableWidget.py
index 9bd2306..13a1caf 100644
--- a/Furious/Widget/UserServersQTableWidget.py
+++ b/Furious/Widget/UserServersQTableWidget.py
@@ -1006,6 +1006,7 @@ class UserServersQTableWidget(Mixins.QTranslatable, AppQTableWidget):
QtCore.Qt.Key.Key_J,
),
),
+ ImportQRCodeOnTheScreenAction(),
AppQSeperator(),
AppQAction(
_('Export Share Link To Clipboard'),
diff --git a/Icons/bootstrap/qr-code-scan.svg b/Icons/bootstrap/qr-code-scan.svg
new file mode 100644
index 0000000..3c53387
--- /dev/null
+++ b/Icons/bootstrap/qr-code-scan.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/Icons/bootstrap/white/qr-code-scan.svg b/Icons/bootstrap/white/qr-code-scan.svg
new file mode 100644
index 0000000..3848743
--- /dev/null
+++ b/Icons/bootstrap/white/qr-code-scan.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/Resources.qrc b/Resources.qrc
index 93ad760..d99b82d 100644
--- a/Resources.qrc
+++ b/Resources.qrc
@@ -27,6 +27,7 @@
Icons/bootstrap/person-gear.svg
Icons/bootstrap/pin-angle.svg
Icons/bootstrap/qr-code.svg
+ Icons/bootstrap/qr-code-scan.svg
Icons/bootstrap/rocket-takeoff.svg
Icons/bootstrap/rocket-takeoff-admin-connected.svg
Icons/bootstrap/rocket-takeoff-connected.svg
@@ -70,6 +71,7 @@
Icons/bootstrap/white/person-gear.svg
Icons/bootstrap/white/pin-angle.svg
Icons/bootstrap/white/qr-code.svg
+ Icons/bootstrap/white/qr-code-scan.svg
Icons/bootstrap/white/router.svg
Icons/bootstrap/white/save.svg
Icons/bootstrap/white/scissors.svg
diff --git a/requirements.txt b/requirements.txt
index 07df7a6..8bdc300 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,6 +5,9 @@ pybase64
pyqrcode
pypng
icmplib
+mss
+zxing-cpp
+pillow
sysproxy; sys_platform == "win32"
win32session; sys_platform == "win32"
darkdetect; sys_platform != "darwin"