Neue Funktion: Leere Workflows ausblenden

- Hinzufügen der Eigenschaft `Hide_Empty_Workflows` in `ClassConfig` zur Steuerung der Sichtbarkeit leerer Workflows.
- Neues Ribbon-Element `Bchkitm_load_empty_wf` zur Aktivierung/Deaktivierung der Funktion.
- Asynchrone Aktualisierung der Knotenanzahlen in `TreeList_Cockpit` mit `_treeNodeCounts`.
- Sichtbarkeitssteuerung für Knoten basierend auf der Checkbox `Bchkitm_load_empty_wf`.
- Verbesserte Benutzerfreundlichkeit durch Tooltips und Logging.
- Optimierung von SQL-Abfragen und Bereinigung von Knotenbezeichnungen.
This commit is contained in:
Developer01
2026-05-29 12:44:11 +02:00
parent 3dd884096b
commit ab0ff0f851
7 changed files with 4567 additions and 3128 deletions

View File

@@ -43,6 +43,7 @@ Public Class ClassConfig
Public Property LastExportPath As String = "" Public Property LastExportPath As String = ""
Public Property ADDITIONAL_SEARCHES_LOAD_ONCLICK As Boolean = True Public Property ADDITIONAL_SEARCHES_LOAD_ONCLICK As Boolean = True
Public Property NOTES_ONCLICK As Boolean = True Public Property NOTES_ONCLICK As Boolean = True
Public Property Hide_Empty_Workflows As Boolean = True
Public Property GridFontSizeDelta As Integer = 0 Public Property GridFontSizeDelta As Integer = 0
Public Property ProfileConfig As New ProfileUserConfig Public Property ProfileConfig As New ProfileUserConfig
Public Property InvDashboardSplitterPositions As New List(Of InvDashboardSplitterPosition) Public Property InvDashboardSplitterPositions As New List(Of InvDashboardSplitterPosition)

File diff suppressed because it is too large Load Diff

View File

@@ -1704,6 +1704,37 @@
NS42LTIuNGwzLjYtMy42SDguNEg0LjRINC4ydjEwbDMuNS0zLjVjMi4yLDIuMiw1LjIsMy41LDguNSwz NS42LTIuNGwzLjYtMy42SDguNEg0LjRINC4ydjEwbDMuNS0zLjVjMi4yLDIuMiw1LjIsMy41LDguNSwz
LjUgICBDMjIuMSwyOCwyNywyMy43LDI4LDE4aC00LjFDMjMsMjEuNCwxOS45LDI0LDE2LjIsMjR6IiBj LjUgICBDMjIuMSwyOCwyNywyMy43LDI4LDE4aC00LjFDMjMsMjEuNCwxOS45LDI0LDE2LjIsMjR6IiBj
bGFzcz0iR3JlZW4iIC8+DQogIDwvZz4NCjwvc3ZnPgs= bGFzcz0iR3JlZW4iIC8+DQogIDwvZz4NCjwvc3ZnPgs=
</value>
</data>
<data name="Bchkitm_load_empty_wf.Caption" xml:space="preserve">
<value>Hide empty workflows</value>
</data>
<data name="Bchkitm_load_empty_wf.ImageOptions.ImageIndex" type="System.Int32, mscorlib">
<value>-1</value>
</data>
<data name="Bchkitm_load_empty_wf.ImageOptions.LargeImageIndex" type="System.Int32, mscorlib">
<value>-1</value>
</data>
<data name="Bchkitm_load_empty_wf.ImageOptions.SvgImage" type="DevExpress.Utils.Svg.SvgImage, DevExpress.Data.v21.2" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFlEZXZFeHByZXNzLkRhdGEudjIxLjIsIFZlcnNpb249MjEuMi40
LjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjg4ZDE3NTRkNzAwZTQ5YQUBAAAAHURl
dkV4cHJlc3MuVXRpbHMuU3ZnLlN2Z0ltYWdlAQAAAAREYXRhBwICAAAACQMAAAAPAwAAAHoDAAAC77u/
PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz4NCjxzdmcgeD0iMHB4IiB5PSIwcHgi
IHZpZXdCb3g9IjAgMCAzMiAzMiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv
MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3Bh
Y2U9InByZXNlcnZlIiBpZD0iTGF5ZXJfMSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAg
MzIgMzIiPg0KICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLkdyZWVue2ZpbGw6IzAzOUMyMzt9Cgku
QmxhY2t7ZmlsbDojNzI3MjcyO30KCS5SZWR7ZmlsbDojRDExQzFDO30KCS5ZZWxsb3d7ZmlsbDojRkZC
MTE1O30KCS5CbHVle2ZpbGw6IzExNzdENzt9CgkuV2hpdGV7ZmlsbDojRkZGRkZGO30KCS5zdDB7b3Bh
Y2l0eTowLjU7fQoJLnN0MXtvcGFjaXR5OjAuNzU7fQo8L3N0eWxlPg0KICA8ZyBpZD0iQXV0b0V4cGFu
ZCI+DQogICAgPHBhdGggZD0iTTE5LDEwaC04Yy0wLjYsMC0xLTAuNC0xLTFWNWMwLTAuNiwwLjQtMSwx
LTFoOGMwLjUsMCwxLDAuNCwxLDF2NEMyMCw5LjYsMTkuNSwxMCwxOSwxMHogTTMyLDE5di00ICAgYzAt
MC42LTAuNS0xLTEtMWgtOGMtMC41LDAtMSwwLjQtMSwxdjRjMCwwLjUsMC41LDEsMSwxaDhDMzEuNSwy
MCwzMiwxOS41LDMyLDE5eiBNMzIsMjd2LTRjMC0wLjUtMC41LTEtMS0xaC04Yy0wLjUsMC0xLDAuNS0x
LDEgICB2NGMwLDAuNSwwLjUsMSwxLDFoOEMzMS41LDI4LDMyLDI3LjUsMzIsMjd6IiBjbGFzcz0iWWVs
bG93IiAvPg0KICAgIDxwYXRoIGQ9Ik0wLDRoOEw0LDhMMCw0eiBNMTYsMjR2LTZoNHYtMmgtNHYtNGgt
MnYxNGg2di0ySDE2eiIgY2xhc3M9IkJsYWNrIiAvPg0KICA8L2c+DQo8L3N2Zz4L
</value> </value>
</data> </data>
<data name="RibbonPageGroup1.Text" xml:space="preserve"> <data name="RibbonPageGroup1.Text" xml:space="preserve">
@@ -1746,7 +1777,7 @@
cmVhbWVyAgAAAAlJbWFnZVNpemUERGF0YQQHE1N5c3RlbS5EcmF3aW5nLlNpemUDAAAAAgIAAAAF/P// cmVhbWVyAgAAAAlJbWFnZVNpemUERGF0YQQHE1N5c3RlbS5EcmF3aW5nLlNpemUDAAAAAgIAAAAF/P//
/xNTeXN0ZW0uRHJhd2luZy5TaXplAgAAAAV3aWR0aAZoZWlnaHQAAAgIAwAAABgAAAAYAAAACQUAAAAP /xNTeXN0ZW0uRHJhd2luZy5TaXplAgAAAAV3aWR0aAZoZWlnaHQAAAgIAwAAABgAAAAYAAAACQUAAAAP
BQAAAGkYAAAC/QUAAIlQTkcNChoKAAAADUlIRFIAAAAYAAAAGAgGAAAA4Hc9+AAAAARnQU1BAACxjwv8 BQAAAGkYAAAC/QUAAIlQTkcNChoKAAAADUlIRFIAAAAYAAAAGAgGAAAA4Hc9+AAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADr4AAA6+AepCscAAAAWfSURBVEhLvZZpUFNXGIYvVbtvM92kdqa1rVUr42hbay1j YQUAAAAJcEhZcwAADr0AAA69AUf7kK0AAAWfSURBVEhLvZZpUFNXGIYvVbtvM92kdqa1rVUr42hbay1j
rXVsi61LW+qCrEaQQWAAiRsC4oJiBNlVigurIkkwCghFUdkCAYKI4MqWsINAFrKQ5e2cmxsItJ3pr96Z rXVsi61LW+qCrEaQQWAAiRsC4oJiBNlVigurIkkwCghFUdkCAYKI4MqWsINAFrKQ5e2cmxsItJ3pr96Z
d5JJJs/z5TvfOfdS1P90WVEU9YxFpkzK1H/JNIs8Oynkd4RLWYWm3rEJu/TwzP6sJm5oVhM35EIjd19m d5JJJs/z5TvfOfdS1P90WVEU9YxFpkzK1H/JNIs8Oynkd4RLWYWm3rEJu/TwzP6sJm5oVhM35EIjd19m
Izcos5G7J72RuzvtHpd9vp7HPlfPCzhTR8cvWczzTarh+Zyu4XmfEvG9Eiv5ngmVfI+ESr57vJDveuyG Izcos5G7J72RuzvtHpd9vp7HPlfPCzhTR8cvWczzTarh+Zyu4XmfEvG9Eiv5ngmVfI+ESr57vJDveuyG
@@ -1771,7 +1802,7 @@
BM29I3jSo8TjHiUedSvRKJFjbUj+WIumbAjOtvNIEPVtS6yBR3wNtsaJwIqtwpaYKrhGV8LlhBDOUUI4 BM29I3jSo8TjHiUedSvRKJFjbUj+WIumbAjOtvNIEPVtS6yBR3wNtsaJwIqtwpaYKrhGV8LlhBDOUUI4
RlZg8/FyOHDKselYGTZGlGJDRCnWHymh83v4bdgzsdt1kWM+KsiN+Tlmxd+gKOpNi7zF5G0m71hkOhNr RlZg8/FyOHDKselYGTZGlGJDRCnWHymh83v4bdgzsdt1kWM+KsiN+Tlmxd+gKOpNi7zF5G0m71hkOhNr
Ju9ahHxPRpS+J5sl//Q08V8z+WmDfEZ41F8VtFHlC52srAAAAABJRU5ErkJggq0GAACJUE5HDQoaCgAA Ju9ahHxPRpS+J5sl//Q08V8z+WmDfEZ41F8VtFHlC52srAAAAABJRU5ErkJggq0GAACJUE5HDQoaCgAA
AA1JSERSAAAAGAAAABgIBgAAAOB3PfgAAAAEZ0FNQQAAsY8L/GEFAAAACXBIWXMAAA6+AAAOvgHqQrHA AA1JSERSAAAAGAAAABgIBgAAAOB3PfgAAAAEZ0FNQQAAsY8L/GEFAAAACXBIWXMAAA69AAAOvQFH+5Ct
AAAGT0lEQVRIS81VeVCTVxx8aq31qCLBoCCXBFCr4llEqijEqxSpFQ+CEQiXXAHkKBoEEYy0IFKhteBR AAAGT0lEQVRIS81VeVCTVxx8aq31qCLBoCCXBFCr4llEqijEqxSpFQ+CEQiXXAHkKBoEEYy0IFKhteBR
6okiDiAiIOBUDoEEEMIZDgVJCIcgChSv2c4XcIZpx7b2r+7M98/3Znb3t++9fYT8XxAcTMYnOOuo3nBf 6okiDiAiIOBUDoEEEMIZDgVJCIcgChSv2c4XcIZpx7b2r+7M98/3Znb3t++9fYT8XxAcTMYnOOuo3nBf
wExyXWCa4MjQ9tjCmEQIGTf6/WeMu+G3VCc1YEVIYbxlflmid68oYWtPfaK5MC1APyWOpekbaaG+hhDy wExyXWCa4MjQ9tjCmEQIGTf6/WeMu+G3VCc1YEVIYbxlflmid68oYWtPfaK5MC1APyWOpekbaaG+hhDy
@@ -1800,7 +1831,7 @@
+XwTXLOjv+VtmFnM1JhiR5s2bf68tRzbpbsiBw0dL1KxVM5QX2X6T+RjQU1DZUjXpk3Y4Gmg8MBm8bRz +XwTXLOjv+VtmFnM1JhiR5s2bf68tRzbpbsiBw0dL1KxVM5QX2X6T+RjQU1DZUjXpk3Y4Gmg8MBm8bRz
ClOIPiFEYdTEJ9Pnrtoyexn74QzVz03eF8vf4d001N4oE0KUCCFT/kREmaDWJ47598GghD7sMR+DPwBL ClOIPiFEYdTEJ9Pnrtoyexn74QzVz03eF8vf4d001N4oE0KUCCFT/kREmaDWJ47598GghD7sMR+DPwBL
DL6/Ppn6BAAAAABJRU5ErkJgghcFAACJUE5HDQoaCgAAAA1JSERSAAAAGAAAABgIBgAAAOB3PfgAAAAE DL6/Ppn6BAAAAABJRU5ErkJgghcFAACJUE5HDQoaCgAAAA1JSERSAAAAGAAAABgIBgAAAOB3PfgAAAAE
Z0FNQQAAsY8L/GEFAAAACXBIWXMAAA6+AAAOvgHqQrHAAAAEuUlEQVRIS6WVeVBTVxTGbxWpS5fpMm3t Z0FNQQAAsY8L/GEFAAAACXBIWXMAAA69AAAOvQFH+5CtAAAEuUlEQVRIS6WVeVBTVxTGbxWpS5fpMm3t
0L86pVtcW5wygNRpy2hlEwUUXJAUKARcKGKEkBAgoFAxAxVQIAkhgDqIKJC8hADKqiCLVAGDEGCKMELo 0L86pVtcW5wygNRpy2hlEwUUXJAUKARcKGKEkBAgoFAxAxVQIAkhgDqIKJC8hADKqiCLVAGDEGCKMELo
Iu2/X+eGhAaolaHfzO+9uXPvne+dd849l5B/9AIhZNl/QOeXrGUt4oPrO7K/29eWyfa7QxEHmDhgpD51 Iu2/X+eGhAaolaHfzO+9uXPvne+dd849l5B/9AIhZNl/QOeXrGUt4oPrO7K/29eWyfa7QxEHmDhgpD51
73qT0ZK0vDllt2Sq8zKmOi/B0FEMQ3sRDHcVMLQVwtAmR0OCm4QQYjV/42JlpT35zdW/BpWYvpeP6W4p 73qT0ZK0vDllt2Sq8zKmOi/B0FEMQ3sRDHcVMLQVwtAmR0OCm4QQYjV/42JlpT35zdW/BpWYvpeP6W4p
@@ -1822,7 +1853,7 @@
7g9duB90HMo+PKSE+c4Q6ouHIT5G+ijB3kZULi7PNViZZrtBlPPxZ5hhM7IpH21G9oebTGxElq0FH2yY 7g9duB90HMo+PKSE+c4Q6ouHIT5G+ijB3kZULi7PNViZZrtBlPPxZ5hhM7IpH21G9oebTGxElq0FH2yY
Rfz+uh5CyGvzT6+l6AQ9eXTR66bebwltCc/CfE/Q225BD7IUrVlqtBSeebv9DSPp72MGtFSzAAAAAElF Rfz+uh5CyGvzT6+l6AQ9eXTR66bebwltCc/CfE/Q225BD7IUrVlqtBSeebv9DSPp72MGtFSzAAAAAElF
TkSuQmCCmAYAAIlQTkcNChoKAAAADUlIRFIAAAAYAAAAGAgGAAAA4Hc9+AAAAARnQU1BAACxjwv8YQUA TkSuQmCCmAYAAIlQTkcNChoKAAAADUlIRFIAAAAYAAAAGAgGAAAA4Hc9+AAAAARnQU1BAACxjwv8YQUA
AAAJcEhZcwAADsEAAA7BAbiRa+0AAAY6SURBVEhLlVZ7TFNnFP90c1P3VOeyOA3Z/pjGTJNtWZZsxmXZ AAAJcEhZcwAADsAAAA7AAWrWiQkAAAY6SURBVEhLlVZ7TFNnFP90c1P3VOeyOA3Z/pjGTJNtWZZsxmXZ
I5mKj6n44CmMqQgTwflkMBWQTcZQC0oR5RFApTJwKM/CQCoPbWlLodhSSh/0/aCF0lYdv+W7thvLNNlO I5mKj6n44CmMqQgTwflkMBWQTcZQC0oR5RFApTJwKM/CQCoPbWlLodhSSh/0/aCF0lYdv+W7thvLNNlO
8rv35t4vv9/5zjnfOZeQJ9s0Qsh0QsjThJBnCSGzCCGzfaDP9B39Rtf8L6PET+3Zkz4vK78+sKSyO+NG 8rv35t4vv9/5zjnfOZeQJ9s0Qsh0QsjThJBnCSGzCCGzfaDP9B39Rtf8L6PET+3Zkz4vK78+sKSyO+NG
i5Rff0s+0sRT3G9ol9lvtkplV2r4FacLGnYnZZa9896aNVT0PwlNCwj4eOapnJrVFyu6a/m9WuuI0QnH i5Rff0s+0sRT3G9ol9lvtkplV2r4FacLGnYnZZa9896aNVT0PwlNCwj4eOapnJrVFyu6a/m9WuuI0QnH
@@ -1906,7 +1937,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADw ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADw
CAAAAk1TRnQBSQFMAgEBAgEAASwBBQEsAQUBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo CAAAAk1TRnQBSQFMAgEBAgEAATQBBQE0AQUBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA

View File

@@ -1324,6 +1324,31 @@
NS42LTIuNGwzLjYtMy42SDguNEg0LjRINC4ydjEwbDMuNS0zLjVjMi4yLDIuMiw1LjIsMy41LDguNSwz NS42LTIuNGwzLjYtMy42SDguNEg0LjRINC4ydjEwbDMuNS0zLjVjMi4yLDIuMiw1LjIsMy41LDguNSwz
LjUgICBDMjIuMSwyOCwyNywyMy43LDI4LDE4aC00LjFDMjMsMjEuNCwxOS45LDI0LDE2LjIsMjR6IiBj LjUgICBDMjIuMSwyOCwyNywyMy43LDI4LDE4aC00LjFDMjMsMjEuNCwxOS45LDI0LDE2LjIsMjR6IiBj
bGFzcz0iR3JlZW4iIC8+DQogIDwvZz4NCjwvc3ZnPgs= bGFzcz0iR3JlZW4iIC8+DQogIDwvZz4NCjwvc3ZnPgs=
</value>
</data>
<data name="Bchkitm_load_empty_wf.Caption" xml:space="preserve">
<value>Masquer les flux de travail vides</value>
</data>
<data name="Bchkitm_load_empty_wf.ImageOptions.SvgImage" type="DevExpress.Utils.Svg.SvgImage, DevExpress.Data.v21.2" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFlEZXZFeHByZXNzLkRhdGEudjIxLjIsIFZlcnNpb249MjEuMi40
LjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjg4ZDE3NTRkNzAwZTQ5YQUBAAAAHURl
dkV4cHJlc3MuVXRpbHMuU3ZnLlN2Z0ltYWdlAQAAAAREYXRhBwICAAAACQMAAAAPAwAAAHoDAAAC77u/
PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz4NCjxzdmcgeD0iMHB4IiB5PSIwcHgi
IHZpZXdCb3g9IjAgMCAzMiAzMiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv
MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3Bh
Y2U9InByZXNlcnZlIiBpZD0iTGF5ZXJfMSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAg
MzIgMzIiPg0KICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLkdyZWVue2ZpbGw6IzAzOUMyMzt9Cgku
QmxhY2t7ZmlsbDojNzI3MjcyO30KCS5SZWR7ZmlsbDojRDExQzFDO30KCS5ZZWxsb3d7ZmlsbDojRkZC
MTE1O30KCS5CbHVle2ZpbGw6IzExNzdENzt9CgkuV2hpdGV7ZmlsbDojRkZGRkZGO30KCS5zdDB7b3Bh
Y2l0eTowLjU7fQoJLnN0MXtvcGFjaXR5OjAuNzU7fQo8L3N0eWxlPg0KICA8ZyBpZD0iQXV0b0V4cGFu
ZCI+DQogICAgPHBhdGggZD0iTTE5LDEwaC04Yy0wLjYsMC0xLTAuNC0xLTFWNWMwLTAuNiwwLjQtMSwx
LTFoOGMwLjUsMCwxLDAuNCwxLDF2NEMyMCw5LjYsMTkuNSwxMCwxOSwxMHogTTMyLDE5di00ICAgYzAt
MC42LTAuNS0xLTEtMWgtOGMtMC41LDAtMSwwLjQtMSwxdjRjMCwwLjUsMC41LDEsMSwxaDhDMzEuNSwy
MCwzMiwxOS41LDMyLDE5eiBNMzIsMjd2LTRjMC0wLjUtMC41LTEtMS0xaC04Yy0wLjUsMC0xLDAuNS0x
LDEgICB2NGMwLDAuNSwwLjUsMSwxLDFoOEMzMS41LDI4LDMyLDI3LjUsMzIsMjd6IiBjbGFzcz0iWWVs
bG93IiAvPg0KICAgIDxwYXRoIGQ9Ik0wLDRoOEw0LDhMMCw0eiBNMTYsMjR2LTZoNHYtMmgtNHYtNGgt
MnYxNGg2di0ySDE2eiIgY2xhc3M9IkJsYWNrIiAvPg0KICA8L2c+DQo8L3N2Zz4L
</value> </value>
</data> </data>
<data name="RibbonPageGroup1.Text" xml:space="preserve"> <data name="RibbonPageGroup1.Text" xml:space="preserve">
@@ -1366,7 +1391,7 @@
cmVhbWVyAgAAAAlJbWFnZVNpemUERGF0YQQHE1N5c3RlbS5EcmF3aW5nLlNpemUDAAAAAgIAAAAF/P// cmVhbWVyAgAAAAlJbWFnZVNpemUERGF0YQQHE1N5c3RlbS5EcmF3aW5nLlNpemUDAAAAAgIAAAAF/P//
/xNTeXN0ZW0uRHJhd2luZy5TaXplAgAAAAV3aWR0aAZoZWlnaHQAAAgIAwAAABgAAAAYAAAACQUAAAAP /xNTeXN0ZW0uRHJhd2luZy5TaXplAgAAAAV3aWR0aAZoZWlnaHQAAAgIAwAAABgAAAAYAAAACQUAAAAP
BQAAAGkYAAAC/QUAAIlQTkcNChoKAAAADUlIRFIAAAAYAAAAGAgGAAAA4Hc9+AAAAARnQU1BAACxjwv8 BQAAAGkYAAAC/QUAAIlQTkcNChoKAAAADUlIRFIAAAAYAAAAGAgGAAAA4Hc9+AAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADr0AAA69AUf7kK0AAAWfSURBVEhLvZZpUFNXGIYvVbtvM92kdqa1rVUr42hbay1j YQUAAAAJcEhZcwAADrwAAA68AZW8ckkAAAWfSURBVEhLvZZpUFNXGIYvVbtvM92kdqa1rVUr42hbay1j
rXVsi61LW+qCrEaQQWAAiRsC4oJiBNlVigurIkkwCghFUdkCAYKI4MqWsINAFrKQ5e2cmxsItJ3pr96Z rXVsi61LW+qCrEaQQWAAiRsC4oJiBNlVigurIkkwCghFUdkCAYKI4MqWsINAFrKQ5e2cmxsItJ3pr96Z
d5JJJs/z5TvfOfdS1P90WVEU9YxFpkzK1H/JNIs8Oynkd4RLWYWm3rEJu/TwzP6sJm5oVhM35EIjd19m d5JJJs/z5TvfOfdS1P90WVEU9YxFpkzK1H/JNIs8Oynkd4RLWYWm3rEJu/TwzP6sJm5oVhM35EIjd19m
Izcos5G7J72RuzvtHpd9vp7HPlfPCzhTR8cvWczzTarh+Zyu4XmfEvG9Eiv5ngmVfI+ESr57vJDveuyG Izcos5G7J72RuzvtHpd9vp7HPlfPCzhTR8cvWczzTarh+Zyu4XmfEvG9Eiv5ngmVfI+ESr57vJDveuyG
@@ -1391,7 +1416,7 @@
BM29I3jSo8TjHiUedSvRKJFjbUj+WIumbAjOtvNIEPVtS6yBR3wNtsaJwIqtwpaYKrhGV8LlhBDOUUI4 BM29I3jSo8TjHiUedSvRKJFjbUj+WIumbAjOtvNIEPVtS6yBR3wNtsaJwIqtwpaYKrhGV8LlhBDOUUI4
RlZg8/FyOHDKselYGTZGlGJDRCnWHymh83v4bdgzsdt1kWM+KsiN+Tlmxd+gKOpNi7zF5G0m71hkOhNr RlZg8/FyOHDKselYGTZGlGJDRCnWHymh83v4bdgzsdt1kWM+KsiN+Tlmxd+gKOpNi7zF5G0m71hkOhNr
Ju9ahHxPRpS+J5sl//Q08V8z+WmDfEZ41F8VtFHlC52srAAAAABJRU5ErkJggq0GAACJUE5HDQoaCgAA Ju9ahHxPRpS+J5sl//Q08V8z+WmDfEZ41F8VtFHlC52srAAAAABJRU5ErkJggq0GAACJUE5HDQoaCgAA
AA1JSERSAAAAGAAAABgIBgAAAOB3PfgAAAAEZ0FNQQAAsY8L/GEFAAAACXBIWXMAAA69AAAOvQFH+5Ct AA1JSERSAAAAGAAAABgIBgAAAOB3PfgAAAAEZ0FNQQAAsY8L/GEFAAAACXBIWXMAAA68AAAOvAGVvHJJ
AAAGT0lEQVRIS81VeVCTVxx8aq31qCLBoCCXBFCr4llEqijEqxSpFQ+CEQiXXAHkKBoEEYy0IFKhteBR AAAGT0lEQVRIS81VeVCTVxx8aq31qCLBoCCXBFCr4llEqijEqxSpFQ+CEQiXXAHkKBoEEYy0IFKhteBR
6okiDiAiIOBUDoEEEMIZDgVJCIcgChSv2c4XcIZpx7b2r+7M98/3Znb3t++9fYT8XxAcTMYnOOuo3nBf 6okiDiAiIOBUDoEEEMIZDgVJCIcgChSv2c4XcIZpx7b2r+7M98/3Znb3t++9fYT8XxAcTMYnOOuo3nBf
wExyXWCa4MjQ9tjCmEQIGTf6/WeMu+G3VCc1YEVIYbxlflmid68oYWtPfaK5MC1APyWOpekbaaG+hhDy wExyXWCa4MjQ9tjCmEQIGTf6/WeMu+G3VCc1YEVIYbxlflmid68oYWtPfaK5MC1APyWOpekbaaG+hhDy
@@ -1420,7 +1445,7 @@
+XwTXLOjv+VtmFnM1JhiR5s2bf68tRzbpbsiBw0dL1KxVM5QX2X6T+RjQU1DZUjXpk3Y4Gmg8MBm8bRz +XwTXLOjv+VtmFnM1JhiR5s2bf68tRzbpbsiBw0dL1KxVM5QX2X6T+RjQU1DZUjXpk3Y4Gmg8MBm8bRz
ClOIPiFEYdTEJ9Pnrtoyexn74QzVz03eF8vf4d001N4oE0KUCCFT/kREmaDWJ47598GghD7sMR+DPwBL ClOIPiFEYdTEJ9Pnrtoyexn74QzVz03eF8vf4d001N4oE0KUCCFT/kREmaDWJ47598GghD7sMR+DPwBL
DL6/Ppn6BAAAAABJRU5ErkJgghcFAACJUE5HDQoaCgAAAA1JSERSAAAAGAAAABgIBgAAAOB3PfgAAAAE DL6/Ppn6BAAAAABJRU5ErkJgghcFAACJUE5HDQoaCgAAAA1JSERSAAAAGAAAABgIBgAAAOB3PfgAAAAE
Z0FNQQAAsY8L/GEFAAAACXBIWXMAAA69AAAOvQFH+5CtAAAEuUlEQVRIS6WVeVBTVxTGbxWpS5fpMm3t Z0FNQQAAsY8L/GEFAAAACXBIWXMAAA68AAAOvAGVvHJJAAAEuUlEQVRIS6WVeVBTVxTGbxWpS5fpMm3t
0L86pVtcW5wygNRpy2hlEwUUXJAUKARcKGKEkBAgoFAxAxVQIAkhgDqIKJC8hADKqiCLVAGDEGCKMELo 0L86pVtcW5wygNRpy2hlEwUUXJAUKARcKGKEkBAgoFAxAxVQIAkhgDqIKJC8hADKqiCLVAGDEGCKMELo
Iu2/X+eGhAaolaHfzO+9uXPvne+dd849l5B/9AIhZNl/QOeXrGUt4oPrO7K/29eWyfa7QxEHmDhgpD51 Iu2/X+eGhAaolaHfzO+9uXPvne+dd849l5B/9AIhZNl/QOeXrGUt4oPrO7K/29eWyfa7QxEHmDhgpD51
73qT0ZK0vDllt2Sq8zKmOi/B0FEMQ3sRDHcVMLQVwtAmR0OCm4QQYjV/42JlpT35zdW/BpWYvpeP6W4p 73qT0ZK0vDllt2Sq8zKmOi/B0FEMQ3sRDHcVMLQVwtAmR0OCm4QQYjV/42JlpT35zdW/BpWYvpeP6W4p
@@ -1442,7 +1467,7 @@
7g9duB90HMo+PKSE+c4Q6ouHIT5G+ijB3kZULi7PNViZZrtBlPPxZ5hhM7IpH21G9oebTGxElq0FH2yY 7g9duB90HMo+PKSE+c4Q6ouHIT5G+ijB3kZULi7PNViZZrtBlPPxZ5hhM7IpH21G9oebTGxElq0FH2yY
Rfz+uh5CyGvzT6+l6AQ9eXTR66bebwltCc/CfE/Q225BD7IUrVlqtBSeebv9DSPp72MGtFSzAAAAAElF Rfz+uh5CyGvzT6+l6AQ9eXTR66bebwltCc/CfE/Q225BD7IUrVlqtBSeebv9DSPp72MGtFSzAAAAAElF
TkSuQmCCmAYAAIlQTkcNChoKAAAADUlIRFIAAAAYAAAAGAgGAAAA4Hc9+AAAAARnQU1BAACxjwv8YQUA TkSuQmCCmAYAAIlQTkcNChoKAAAADUlIRFIAAAAYAAAAGAgGAAAA4Hc9+AAAAARnQU1BAACxjwv8YQUA
AAAJcEhZcwAADsAAAA7AAWrWiQkAAAY6SURBVEhLlVZ7TFNnFP90c1P3VOeyOA3Z/pjGTJNtWZZsxmXZ AAAJcEhZcwAADr8AAA6/ATgFUyQAAAY6SURBVEhLlVZ7TFNnFP90c1P3VOeyOA3Z/pjGTJNtWZZsxmXZ
I5mKj6n44CmMqQgTwflkMBWQTcZQC0oR5RFApTJwKM/CQCoPbWlLodhSSh/0/aCF0lYdv+W7thvLNNlO I5mKj6n44CmMqQgTwflkMBWQTcZQC0oR5RFApTJwKM/CQCoPbWlLodhSSh/0/aCF0lYdv+W7thvLNNlO
8rv35t4vv9/5zjnfOZeQJ9s0Qsh0QsjThJBnCSGzCCGzfaDP9B39Rtf8L6PET+3Zkz4vK78+sKSyO+NG 8rv35t4vv9/5zjnfOZeQJ9s0Qsh0QsjThJBnCSGzCCGzfaDP9B39Rtf8L6PET+3Zkz4vK78+sKSyO+NG
i5Rff0s+0sRT3G9ol9lvtkplV2r4FacLGnYnZZa9896aNVT0PwlNCwj4eOapnJrVFyu6a/m9WuuI0QnH i5Rff0s+0sRT3G9ol9lvtkplV2r4FacLGnYnZZa9896aNVT0PwlNCwj4eOapnJrVFyu6a/m9WuuI0QnH
@@ -1477,7 +1502,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADw ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADw
CAAAAk1TRnQBSQFMAgEBAgEAASQBBQEkAQUBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo CAAAAk1TRnQBSQFMAgEBAgEAASwBBQEsAQUBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,8 @@ Public Class frmMain
Private CURR_DT_VWPM_PROFILE_ACTIVE As DataTable Private CURR_DT_VWPM_PROFILE_ACTIVE As DataTable
Private CURR_DT_VWPM_PROFILE_AH_WORKFLOW As DataTable Private CURR_DT_VWPM_PROFILE_AH_WORKFLOW As DataTable
Private DT_CURR_WF_ITEMS As DataTable Private DT_CURR_WF_ITEMS As DataTable
Private _treeNodeCounts As New Dictionary(Of Integer, Integer)
Private OVERVIEW_ADDED_WHEN As String Private OVERVIEW_ADDED_WHEN As String
Private OVERVIEW_CHANGED_WHEN As String Private OVERVIEW_CHANGED_WHEN As String
Private OVERVIEW_COUNT As Integer = 0 Private OVERVIEW_COUNT As Integer = 0
@@ -515,6 +517,14 @@ Public Class frmMain
Else Else
bbtnitmLanguage_Change.Visibility = DevExpress.XtraBars.BarItemVisibility.Never bbtnitmLanguage_Change.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
End If End If
' ===== CHECKBOX AUS CONFIG INITIALISIEREN (VOR Decide_Load) =====
' Ohne diesen Block ist Checked immer False nach Neustart, unabhängig vom gespeicherten Config-Wert
Try
Bchkitm_load_empty_wf.Checked = CONFIG.Config.Hide_Empty_Workflows
LOGGER.Debug($"frmMain_Shown: Bchkitm_load_empty_wf.Checked initialized from config: [{CONFIG.Config.Hide_Empty_Workflows}]")
Catch ex As Exception
LOGGER.Warn($"frmMain_Shown: Could not initialize Bchkitm_load_empty_wf.Checked - {ex.Message}")
End Try
LoadCURRENT_DT_PROFILES() LoadCURRENT_DT_PROFILES()
LoadVWPM_CONTROL_INDEX() LoadVWPM_CONTROL_INDEX()
@@ -577,6 +587,7 @@ Public Class frmMain
TreeList_Cockpit.BeginUpdate() TreeList_Cockpit.BeginUpdate()
Try Try
TreeList_Cockpit.DataSource = oDT_STRUCTURE_NODES TreeList_Cockpit.DataSource = oDT_STRUCTURE_NODES
AddHandler TreeList_Cockpit.CustomDrawNodeCell, AddressOf TreeList_Cockpit_CustomDrawNodeCell
TreeList_Cockpit.KeyFieldName = "PK_CFG_COCKPIT_DEFINITION_ID" TreeList_Cockpit.KeyFieldName = "PK_CFG_COCKPIT_DEFINITION_ID"
TreeList_Cockpit.ParentFieldName = "PARENT_ID" TreeList_Cockpit.ParentFieldName = "PARENT_ID"
TreeList_Cockpit.Columns("PK_RESULT_ID").SortOrder = SortOrder.Ascending TreeList_Cockpit.Columns("PK_RESULT_ID").SortOrder = SortOrder.Ascending
@@ -634,17 +645,35 @@ Public Class frmMain
End Try End Try
End Sub End Sub
Private Sub TreeList_Cockpit_CustomDrawNodeCell(sender As Object, e As DevExpress.XtraTreeList.CustomDrawNodeCellEventArgs)
Try
Dim oPk As Object = e.Node.GetValue("PK_CFG_COCKPIT_DEFINITION_ID")
If oPk Is Nothing OrElse IsDBNull(oPk) Then
Exit Sub
End If
Dim oPkInt As Integer = CInt(oPk)
If Not _treeNodeCounts.ContainsKey(oPkInt) Then
Exit Sub
End If
If _treeNodeCounts(oPkInt) > 0 Then
e.Appearance.Font = New Font(e.Appearance.Font, FontStyle.Bold)
Else
e.Appearance.Font = New Font(e.Appearance.Font, FontStyle.Regular)
End If
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
Private Async Sub AppendCountsToTreeAsync() Private Async Sub AppendCountsToTreeAsync()
Try Try
LOGGER.Debug("AppendCountsToTreeAsync: Starting background count queries...") LOGGER.Debug("AppendCountsToTreeAsync: Starting background count queries...")
' Alle Knoten mit ihren SQL-Befehlen im UI-Thread über NodesIterator einsammeln
Dim oWorkItems As New List(Of (Node As DevExpress.XtraTreeList.Nodes.TreeListNode, SQL As String, OriginalName As String)) Dim oWorkItems As New List(Of (Node As DevExpress.XtraTreeList.Nodes.TreeListNode, SQL As String, OriginalName As String))
TreeList_Cockpit.NodesIterator.DoOperation( TreeList_Cockpit.NodesIterator.DoOperation(
Sub(oNode As DevExpress.XtraTreeList.Nodes.TreeListNode) Sub(oNode As DevExpress.XtraTreeList.Nodes.TreeListNode)
' ===== NUR KNOTEN MIT TYPE_ID = 0 ODER 1 VERARBEITEN =====
Dim oTypeId As Object = oNode.GetValue("TYPE_ID") Dim oTypeId As Object = oNode.GetValue("TYPE_ID")
Dim oProfileID As Object = oNode.GetValue("FK_PROFILE_ID") Dim oProfileID As Object = oNode.GetValue("FK_PROFILE_ID")
If oTypeId Is Nothing OrElse IsDBNull(oTypeId) Then If oTypeId Is Nothing OrElse IsDBNull(oTypeId) Then
@@ -659,9 +688,14 @@ Public Class frmMain
Dim oSqlCount As Object = oNode.GetValue("SQL_QUERY_COUNT") Dim oSqlCount As Object = oNode.GetValue("SQL_QUERY_COUNT")
If oSqlCount IsNot Nothing AndAlso Not IsDBNull(oSqlCount) AndAlso Not String.IsNullOrWhiteSpace(oSqlCount.ToString()) Then If oSqlCount IsNot Nothing AndAlso Not IsDBNull(oSqlCount) AndAlso Not String.IsNullOrWhiteSpace(oSqlCount.ToString()) Then
Dim oPreparedSQL As String = PrepareSQLWithReplacements(oSqlCount.ToString(), CInt(oProfileID)) Dim oPreparedSQL As String = PrepareSQLWithReplacements(oSqlCount.ToString(), CInt(oProfileID))
Dim oName As String = oNode.GetValue("NAME")?.ToString()
If Not String.IsNullOrWhiteSpace(oName) Then ' ===== COUNT-SUFFIX VOM VORHERIGEN DURCHLAUF ENTFERNEN =====
oWorkItems.Add((oNode, oPreparedSQL, oName)) Dim oRawName As String = oNode.GetValue("NAME")?.ToString()
Dim oSuffixMatch = System.Text.RegularExpressions.Regex.Match(oRawName, "^(.*)\s+\(\d+\)$")
Dim oCleanName As String = If(oSuffixMatch.Success, oSuffixMatch.Groups(1).Value.Trim(), oRawName)
If Not String.IsNullOrWhiteSpace(oCleanName) Then
oWorkItems.Add((oNode, oPreparedSQL, oCleanName))
End If End If
Else Else
LOGGER.Debug($"AppendCountsToTreeAsync: Node [{oNode.GetValue("NAME")}] has no valid SQL_QUERY_COUNT, skipping.") LOGGER.Debug($"AppendCountsToTreeAsync: Node [{oNode.GetValue("NAME")}] has no valid SQL_QUERY_COUNT, skipping.")
@@ -669,12 +703,12 @@ Public Class frmMain
End Sub) End Sub)
If oWorkItems.Count = 0 Then If oWorkItems.Count = 0 Then
LOGGER.Debug("AppendCountsToTreeAsync: No nodes with SQL_QUERY_COUNT found, exiting.")
Exit Sub Exit Sub
End If End If
LOGGER.Debug($"AppendCountsToTreeAsync: {oWorkItems.Count} node(s) with SQL_QUERY_COUNT found") LOGGER.Debug($"AppendCountsToTreeAsync: {oWorkItems.Count} node(s) with SQL_QUERY_COUNT found")
' DB-Abfragen parallel im Hintergrund ausführen
Dim oResults As New List(Of (Node As DevExpress.XtraTreeList.Nodes.TreeListNode, OriginalName As String, Count As String)) Dim oResults As New List(Of (Node As DevExpress.XtraTreeList.Nodes.TreeListNode, OriginalName As String, Count As String))
Await Task.Run(Sub() Await Task.Run(Sub()
@@ -692,10 +726,17 @@ Public Class frmMain
Next Next
End Sub) End Sub)
' Ergebnisse zurück im UI-Thread auf die Knoten schreiben _treeNodeCounts.Clear()
TreeList_Cockpit.BeginUpdate() TreeList_Cockpit.BeginUpdate()
Try Try
For Each oResult In oResults For Each oResult In oResults
Dim oPk As Object = oResult.Node.GetValue("PK_CFG_COCKPIT_DEFINITION_ID")
If oPk IsNot Nothing AndAlso Not IsDBNull(oPk) Then
Dim oCount As Integer = 0
Integer.TryParse(oResult.Count, oCount)
_treeNodeCounts(CInt(oPk)) = oCount
End If
oResult.Node.SetValue("NAME", $"{oResult.OriginalName} ({oResult.Count})") oResult.Node.SetValue("NAME", $"{oResult.OriginalName} ({oResult.Count})")
LOGGER.Debug($"AppendCountsToTreeAsync: Node [{oResult.OriginalName}] → [{oResult.OriginalName} ({oResult.Count})]") LOGGER.Debug($"AppendCountsToTreeAsync: Node [{oResult.OriginalName}] → [{oResult.OriginalName} ({oResult.Count})]")
Next Next
@@ -705,7 +746,7 @@ Public Class frmMain
TreeList_Cockpit.Refresh() TreeList_Cockpit.Refresh()
LOGGER.Debug("AppendCountsToTreeAsync: Finished") LOGGER.Debug("AppendCountsToTreeAsync: Finished")
Decide_Show_Empty_Workflows(Not CONFIG.Config.Hide_Empty_Workflows)
Catch ex As Exception Catch ex As Exception
LOGGER.Error(ex) LOGGER.Error(ex)
End Try End Try
@@ -1553,6 +1594,13 @@ Public Class frmMain
'bwSync.ReportProgress(95) 'bwSync.ReportProgress(95)
If GridControlWorkflows.Visible = True And FormOpenClose = False Then RefreshHelper.LoadViewInfo() If GridControlWorkflows.Visible = True And FormOpenClose = False Then RefreshHelper.LoadViewInfo()
' ===== TREELIST COUNTS AKTUALISIEREN =====
' Nur ausführen wenn TreeList Knoten mit SQL_QUERY_COUNT vorhanden sind
Dim oDatasource As DataTable = TryCast(TreeList_Cockpit.DataSource, DataTable)
If oDatasource IsNot Nothing AndAlso oDatasource.Columns.Contains("SQL_QUERY_COUNT") Then
LOGGER.Debug("TimerRefresh_Tick: Refreshing TreeList node counts...")
AppendCountsToTreeAsync()
End If
Handling_DEBUG_USER() Handling_DEBUG_USER()
Catch ex As Exception Catch ex As Exception
@@ -3495,24 +3543,22 @@ FROM VWPM_PROFILE_ACTIVE T WHERE T.GUID IN (SELECT PROFILE_ID FROM [dbo].[FNPM_G
End Sub End Sub
Private Async Sub frmMain_Shown(sender As Object, e As EventArgs) Handles Me.Shown Private Async Sub frmMain_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Me.Text = ADDITIONAL_TITLE Me.Text = ADDITIONAL_TITLE
' CurrNavBarGroup = NavBarControl1.Groups(1)
FormShown = True FormShown = True
Try Try
If CONFIG.Config.MainTreeList_Width > 0 Then If CONFIG.Config.MainTreeList_Width > 0 Then
TreeList_Cockpit.Width = CONFIG.Config.MainTreeList_Width TreeList_Cockpit.Width = CONFIG.Config.MainTreeList_Width
End If End If
Catch ex As Exception Catch ex As Exception
End Try End Try
Timer_Inactivity_Reset_Disable("Decide_Load") Timer_Inactivity_Reset_Disable("Decide_Load")
' ===== ERSTEN KNOTEN AUSWÄHLEN (löst FocusedNodeChanged → Decide_Load aus) =====
Dim oFirstNode As DevExpress.XtraTreeList.Nodes.TreeListNode = TreeList_Cockpit.Nodes.FirstOrDefault() Dim oFirstNode As DevExpress.XtraTreeList.Nodes.TreeListNode = TreeList_Cockpit.Nodes.FirstOrDefault()
If oFirstNode IsNot Nothing Then If oFirstNode IsNot Nothing Then
LOGGER.Debug($"Selecting first TreeList node: [{oFirstNode.GetValue("NAME")}]") LOGGER.Debug($"Selecting first TreeList node: [{oFirstNode.GetValue("NAME")}]")
TreeList_Cockpit.FocusedNode = oFirstNode TreeList_Cockpit.FocusedNode = oFirstNode
' FocusedNodeChanged nicht zuverlässig bei programmatischer Zuweisung → direkt aufrufen
Await ProcessTreeListNodeAsync(oFirstNode) Await ProcessTreeListNodeAsync(oFirstNode)
Else Else
LOGGER.Debug("No TreeList nodes found - falling back to Decide_Load") LOGGER.Debug("No TreeList nodes found - falling back to Decide_Load")
@@ -3524,6 +3570,14 @@ FROM VWPM_PROFILE_ACTIVE T WHERE T.GUID IN (SELECT PROFILE_ID FROM [dbo].[FNPM_G
Create_GroupBy_Parts() Create_GroupBy_Parts()
End If End If
' ===== SICHTBARKEIT NACH LADEVORGANG NOCHMALS ANWENDEN =====
' AppendCountsToTreeAsync könnte bereits vor frmMain_Shown abgeschlossen sein (Race Condition),
' daher hier sicherstellen, dass die korrekte Sichtbarkeit gesetzt ist
If _treeNodeCounts.Count > 0 Then
LOGGER.Debug($"frmMain_Shown: Applying node visibility after load (Hide_Empty_Workflows=[{CONFIG.Config.Hide_Empty_Workflows}])")
Decide_Show_Empty_Workflows(Not CONFIG.Config.Hide_Empty_Workflows)
End If
Handling_DEBUG_USER() Handling_DEBUG_USER()
Dim oSQL = $"SELECT * FROM TBDD_NOTIFICATIONS_SYSTEM NOTE WITH (NOLOCK) Dim oSQL = $"SELECT * FROM TBDD_NOTIFICATIONS_SYSTEM NOTE WITH (NOLOCK)
@@ -3538,7 +3592,6 @@ FROM VWPM_PROFILE_ACTIVE T WHERE T.GUID IN (SELECT PROFILE_ID FROM [dbo].[FNPM_G
BBtnItmNotfications.Visibility = DevExpress.XtraBars.BarItemVisibility.Always BBtnItmNotfications.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
Open_Notifications_Form() Open_Notifications_Form()
End If End If
End If End If
End Sub End Sub
@@ -4596,4 +4649,49 @@ FROM VWPM_PROFILE_ACTIVE T WHERE T.GUID IN (SELECT PROFILE_ID FROM [dbo].[FNPM_G
Private Sub BarButtonItemCock_refresh_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemCock_refresh.ItemClick Private Sub BarButtonItemCock_refresh_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemCock_refresh.ItemClick
Load_Treeview() Load_Treeview()
End Sub End Sub
Private Sub Bchkitm_load_empty_wf_CheckedChanged(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles Bchkitm_load_empty_wf.CheckedChanged
If FormShown = False Then
Exit Sub
End If
CONFIG.Config.Hide_Empty_Workflows = Bchkitm_load_empty_wf.Checked
CONFIG.Save()
End Sub
Private Sub Bchkitm_load_empty_wf_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles Bchkitm_load_empty_wf.ItemClick
Decide_Show_Empty_Workflows(Not Bchkitm_load_empty_wf.Checked)
End Sub
Sub Decide_Show_Empty_Workflows(pShow As Boolean)
Try
LOGGER.Debug($"Decide_Show_Empty_Workflows: pShow=[{pShow}], cached node counts: [{_treeNodeCounts.Count}]")
TreeList_Cockpit.BeginUpdate()
Try
TreeList_Cockpit.NodesIterator.DoOperation(
Sub(oNode As DevExpress.XtraTreeList.Nodes.TreeListNode)
Dim oPk As Object = oNode.GetValue("PK_CFG_COCKPIT_DEFINITION_ID")
If oPk Is Nothing OrElse IsDBNull(oPk) Then
oNode.Visible = True
LOGGER.Debug($"Decide_Show_Empty_Workflows: oPk is Nothing/DBNull - Node visible set to True")
Exit Sub
End If
Dim oPkInt As Integer = CInt(oPk)
If Not _treeNodeCounts.ContainsKey(oPkInt) Then
oNode.Visible = True
LOGGER.Debug($"Decide_Show_Empty_Workflows: oPkInt [{oPkInt}] not found in _treeNodeCounts - Node visible set to True")
Exit Sub
End If
oNode.Visible = pShow OrElse (_treeNodeCounts(oPkInt) > 0)
End Sub)
Finally
TreeList_Cockpit.EndUpdate()
End Try
TreeList_Cockpit.Refresh()
Catch ex As Exception
LOGGER.Error(ex)
End Try
End Sub
End Class End Class

View File

@@ -1,150 +1 @@
13:45:45.0872|frmValidator|INFO >> Load_Additional_Searches -> ✓ SQL-Search 'Inhalte ZUGFeRD-XML': 67 Ergebnisse gefunden
13:45:45.0872|taskFLOW|DEBUG >> ReplaceAllValues -> input BEFORE replacing: [Select T.DocID,T.FULL_FILENAME,T.Doctype from TBPM_CUST_ATTACHMENTS T WITH (NOLOCK) INNER JOIN idb.dbo.VWIDB_DOC_DATA T1 ON T.EmailMessageID = T1.EmailMessageID WHERE T1.IDB_OBJ_ID = {#IDBA#ObjectID}]
13:45:45.0872|taskFLOW|DEBUG >> ReplaceIDBAttributes -> Starting ReplaceIDBAttributes with input: [Select T.DocID,T.FULL_FILENAME,T.Doctype from TBPM_CUST_ATTACHMENTS T WITH (NOLOCK) INNER JOIN idb.dbo.VWIDB_DOC_DATA T1 ON T.EmailMessageID = T1.EmailMessageID WHERE T1.IDB_OBJ_ID = {#IDBA#ObjectID}] for document ID: 4511694
13:45:45.0872|taskFLOW|DEBUG >> ReplaceIDBAttributes -> IS_SQL = True - oReplaceValue = [{#IDBA#ObjectID}]
13:45:45.0872|taskFLOW|DEBUG >> ReplaceIDBAttributes -> oIDBValue = 4511694
13:45:45.0872|taskFLOW|DEBUG >> ReplaceIDBAttributes -> sql after ReplaceIDBAttributes: Select T.DocID,T.FULL_FILENAME,T.Doctype from TBPM_CUST_ATTACHMENTS T WITH (NOLOCK) INNER JOIN idb.dbo.VWIDB_DOC_DATA T1 ON T.EmailMessageID = T1.EmailMessageID WHERE T1.IDB_OBJ_ID = {#IDBA#ObjectID}
13:45:45.0872|taskFLOW|DEBUG >> ReplaceControlValues -> Starting ReplaceControlValues with input: [Select T.DocID,T.FULL_FILENAME,T.Doctype from TBPM_CUST_ATTACHMENTS T WITH (NOLOCK) INNER JOIN idb.dbo.VWIDB_DOC_DATA T1 ON T.EmailMessageID = T1.EmailMessageID WHERE T1.IDB_OBJ_ID = 4511694] for document ID: 4511694
13:45:45.0872|taskFLOW|DEBUG >> ReplaceAllValues -> input AFTER replacing: [Select T.DocID,T.FULL_FILENAME,T.Doctype from TBPM_CUST_ATTACHMENTS T WITH (NOLOCK) INNER JOIN idb.dbo.VWIDB_DOC_DATA T1 ON T.EmailMessageID = T1.EmailMessageID WHERE T1.IDB_OBJ_ID = 4511694]
13:45:45.0872|DatabaseWithFallback|DEBUG >> GetDatatable -> ForceFallback is True, falling back to direct database access.
13:45:45.0872|DatabaseWithFallback|DEBUG >> GetDatatableFromDatabase -> Fetching data from database [ECM] with Connection Id [ECM]
13:45:45.0872|DatabaseWithFallback|DEBUG >> GetDatatableFromDatabase -> Retrieving Connection String from Connection Id [1]
13:45:45.0872|MSSQLServer|DEBUG >> Get_ConnectionStringforID -> Getting ConnectionString for ConnectionId [1]
13:45:45.0872|MSSQLServer|DEBUG >> GetConnection -> The Following Connection is open: Server=W2K19SRV398;Database=DD_ECM;User Id=EDMAdmin;Password=XXXXX;Application Name=DD_EDMIAppService;Workstation ID=W2K19SRV391;
13:45:45.0872|MSSQLServer|DEBUG >> MaybeGetTransaction -> Transaction Mode: [WithTransaction]
13:45:45.0872|MSSQLServer|DEBUG >> GetDatatableWithConnectionObject -> GetDatatableWithConnectionObject: Running Query [SELECT * FROM TBDD_CONNECTION WHERE GUID = 1] and Parameters []
13:45:45.0872|MSSQLServer|DEBUG >> GetConnection -> The Following Connection is open: Data Source=w2k19srv398;Initial Catalog=DD_ECM;User ID=EDMAdmin;Password=XXXXX
13:45:45.0872|MSSQLServer|DEBUG >> MaybeGetTransaction -> Transaction Mode: [WithTransaction]
13:45:45.0872|MSSQLServer|DEBUG >> GetDatatableWithConnectionObject -> GetDatatableWithConnectionObject: Running Query [Select T.DocID,T.FULL_FILENAME,T.Doctype from TBPM_CUST_ATTACHMENTS T WITH (NOLOCK) INNER JOIN idb.dbo.VWIDB_DOC_DATA T1 ON T.EmailMessageID = T1.EmailMessageID WHERE T1.IDB_OBJ_ID = 4511694] and Parameters []
13:45:45.5262|frmValidator|DEBUG >> Load_Additional_Searches -> Doc-Search 'Attachments': Keine Ergebnisse gefunden
13:45:45.5262|frmValidator|DEBUG >> Load_Additional_Searches -> Ergebnisprüfung abgeschlossen: AdditionalDataResultsExist=True, AdditionalDocResultsExist=False
13:45:45.5262|frmValidator|DEBUG >> Load_Additional_Searches -> rbnPgGroupAttmt.Visible gesetzt auf: True | Stack:
at taskFLOW.frmValidator.FillIndexValues(Boolean first, String SingleAttribute)
13:45:45.5262|frmValidator|DEBUG >> Load_Additional_Searches -> --- NORMAL-MODUS aktiviert (nur vorbereiten, NICHT Show) ---
13:45:45.5262|taskFLOW|DEBUG >> TabPreload -> === TabPreload START ===
13:45:45.5262|taskFLOW|DEBUG >> TabPreload -> Parameters: TabCountSQL=1, TabCountDoc=0, DTSQL.Rows=1, DTDOC.Rows=0
13:45:45.5262|taskFLOW|DEBUG >> TabPreload -> Ausführung auf UI-Thread
13:45:45.5262|taskFLOW|DEBUG >> TabPreload -> 🚫 Tab-Events deaktiviert
13:45:45.5262|taskFLOW|DEBUG >> TabPreload -> ✓ _DTDATASearches und _DTDocSearches zugewiesen: SQL=1, Doc=0
13:45:45.5322|taskFLOW|DEBUG >> TabPreload -> Panel1Collapsed (SQL)=False, Panel2Collapsed (Doc)=True
13:45:45.5322|taskFLOW|DEBUG >> TabPreload -> Konfiguriere SQL-Tabs: 1 Definitionen
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlSQL_SelectedPageChanged -> 🚫 XtraTabControlSQL_SelectedPageChanged unterdrückt (SelectedTabPageIndex=1)
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlSQL_SelectedPageChanged -> 🚫 XtraTabControlSQL_SelectedPageChanged unterdrückt (SelectedTabPageIndex=2)
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlSQL_SelectedPageChanged -> 🚫 XtraTabControlSQL_SelectedPageChanged unterdrückt (SelectedTabPageIndex=3)
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlSQL_SelectedPageChanged -> 🚫 XtraTabControlSQL_SelectedPageChanged unterdrückt (SelectedTabPageIndex=4)
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlSQL_SelectedPageChanged -> 🚫 XtraTabControlSQL_SelectedPageChanged unterdrückt (SelectedTabPageIndex=-1)
13:45:45.5322|taskFLOW|DEBUG >> TabPreload -> Alle 5 SQL-Tabs auf PageVisible=False gesetzt
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlSQL_SelectedPageChanged -> 🚫 XtraTabControlSQL_SelectedPageChanged unterdrückt (SelectedTabPageIndex=0)
13:45:45.5322|taskFLOW|DEBUG >> TabPreload -> SQL-Tab 0: Text='Inhalte ZUGFeRD-XML', PageVisible=True
13:45:45.5322|taskFLOW|INFO >> TabPreload -> ✓ 1 SQL-Tabs konfiguriert
13:45:45.5322|taskFLOW|DEBUG >> TabPreload -> Keine Doc-Daten, alle Tabs ausblenden
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlDocs_SelectedPageChanged_1 -> 🚫 XtraTabControlDocs_SelectedPageChanged unterdrückt (SelectedTabPageIndex=1)
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlDocs_SelectedPageChanged_1 -> 🚫 XtraTabControlDocs_SelectedPageChanged unterdrückt (SelectedTabPageIndex=2)
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlDocs_SelectedPageChanged_1 -> 🚫 XtraTabControlDocs_SelectedPageChanged unterdrückt (SelectedTabPageIndex=3)
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlDocs_SelectedPageChanged_1 -> 🚫 XtraTabControlDocs_SelectedPageChanged unterdrückt (SelectedTabPageIndex=4)
13:45:45.5322|taskFLOW|DEBUG >> XtraTabControlDocs_SelectedPageChanged_1 -> 🚫 XtraTabControlDocs_SelectedPageChanged unterdrückt (SelectedTabPageIndex=-1)
13:45:45.5322|taskFLOW|DEBUG >> TabPreload -> ✓ Tab-Events reaktiviert
13:45:45.5322|taskFLOW|DEBUG >> TabPreload -> Setze SQL SelectedTabPageIndex manuell auf 0
13:45:45.5322|taskFLOW|DEBUG >> ReplaceAllValues -> input BEFORE replacing: [SELECT
SPEC_NAME [Definitions-Name],
ITEM_DESCRIPTION [Beschreibung],
CASE
WHEN SPEC_NAME = 'INVOICE_POSITION_NOTE' THEN
REPLACE(REPLACE(ITEM_VALUE, CHAR(13),' '),CHAR(10),' ')
ELSE
ITEM_VALUE
END [Inhalt xml],
GROUP_COUNTER [Gruppenzähler],
IS_REQUIRED [Pflichtangabe],
CREATEDWHEN [Erstellt]
FROM dbo.TBEDMI_ITEM_VALUE WITH (NOLOCK)
WHERE REFERENCE_GUID = (SELECT EmailMessageID FROM IDB.dbo.VWIDB_DOC_DATA WHERE IDB_OBJ_ID = {#IDBA#ObjectID})
ORDER BY GROUP_COUNTER, SPEC_NAME]
13:45:45.5322|taskFLOW|DEBUG >> ReplaceIDBAttributes -> Starting ReplaceIDBAttributes with input: [SELECT
SPEC_NAME [Definitions-Name],
ITEM_DESCRIPTION [Beschreibung],
CASE
WHEN SPEC_NAME = 'INVOICE_POSITION_NOTE' THEN
REPLACE(REPLACE(ITEM_VALUE, CHAR(13),' '),CHAR(10),' ')
ELSE
ITEM_VALUE
END [Inhalt xml],
GROUP_COUNTER [Gruppenzähler],
IS_REQUIRED [Pflichtangabe],
CREATEDWHEN [Erstellt]
FROM dbo.TBEDMI_ITEM_VALUE WITH (NOLOCK)
WHERE REFERENCE_GUID = (SELECT EmailMessageID FROM IDB.dbo.VWIDB_DOC_DATA WHERE IDB_OBJ_ID = {#IDBA#ObjectID})
ORDER BY GROUP_COUNTER, SPEC_NAME] for document ID: 4511694
13:45:45.5322|taskFLOW|DEBUG >> ReplaceIDBAttributes -> IS_SQL = True - oReplaceValue = [{#IDBA#ObjectID}]
13:45:45.5322|taskFLOW|DEBUG >> ReplaceIDBAttributes -> oIDBValue = 4511694
13:45:45.5322|taskFLOW|DEBUG >> ReplaceIDBAttributes -> sql after ReplaceIDBAttributes: SELECT
SPEC_NAME [Definitions-Name],
ITEM_DESCRIPTION [Beschreibung],
CASE
WHEN SPEC_NAME = 'INVOICE_POSITION_NOTE' THEN
REPLACE(REPLACE(ITEM_VALUE, CHAR(13),' '),CHAR(10),' ')
ELSE
ITEM_VALUE
END [Inhalt xml],
GROUP_COUNTER [Gruppenzähler],
IS_REQUIRED [Pflichtangabe],
CREATEDWHEN [Erstellt]
FROM dbo.TBEDMI_ITEM_VALUE WITH (NOLOCK)
WHERE REFERENCE_GUID = (SELECT EmailMessageID FROM IDB.dbo.VWIDB_DOC_DATA WHERE IDB_OBJ_ID = {#IDBA#ObjectID})
ORDER BY GROUP_COUNTER, SPEC_NAME
13:45:45.5322|taskFLOW|DEBUG >> ReplaceControlValues -> Starting ReplaceControlValues with input: [SELECT
SPEC_NAME [Definitions-Name],
ITEM_DESCRIPTION [Beschreibung],
CASE
WHEN SPEC_NAME = 'INVOICE_POSITION_NOTE' THEN
REPLACE(REPLACE(ITEM_VALUE, CHAR(13),' '),CHAR(10),' ')
ELSE
ITEM_VALUE
END [Inhalt xml],
GROUP_COUNTER [Gruppenzähler],
IS_REQUIRED [Pflichtangabe],
CREATEDWHEN [Erstellt]
FROM dbo.TBEDMI_ITEM_VALUE WITH (NOLOCK)
WHERE REFERENCE_GUID = (SELECT EmailMessageID FROM IDB.dbo.VWIDB_DOC_DATA WHERE IDB_OBJ_ID = 4511694)
ORDER BY GROUP_COUNTER, SPEC_NAME] for document ID: 4511694
13:45:45.5322|taskFLOW|DEBUG >> ReplaceAllValues -> input AFTER replacing: [SELECT
SPEC_NAME [Definitions-Name],
ITEM_DESCRIPTION [Beschreibung],
CASE
WHEN SPEC_NAME = 'INVOICE_POSITION_NOTE' THEN
REPLACE(REPLACE(ITEM_VALUE, CHAR(13),' '),CHAR(10),' ')
ELSE
ITEM_VALUE
END [Inhalt xml],
GROUP_COUNTER [Gruppenzähler],
IS_REQUIRED [Pflichtangabe],
CREATEDWHEN [Erstellt]
FROM dbo.TBEDMI_ITEM_VALUE WITH (NOLOCK)
WHERE REFERENCE_GUID = (SELECT EmailMessageID FROM IDB.dbo.VWIDB_DOC_DATA WHERE IDB_OBJ_ID = 4511694)
ORDER BY GROUP_COUNTER, SPEC_NAME]
13:45:45.5322|taskFLOW|DEBUG >> TabPreload -> SQL-Tab 0: erzwungener Initial-Refresh
13:45:45.5322|DatabaseWithFallback|DEBUG >> GetDatatable -> ForceFallback is True, falling back to direct database access.
13:45:45.5322|DatabaseWithFallback|DEBUG >> GetDatatableFromDatabase -> Fetching data from database [ECM] with Connection Id [ECM]
13:45:45.5322|DatabaseWithFallback|DEBUG >> GetDatatableFromDatabase -> Retrieving Connection String from Connection Id [1]
13:45:45.5322|MSSQLServer|DEBUG >> Get_ConnectionStringforID -> Getting ConnectionString for ConnectionId [1]
13:45:45.5322|MSSQLServer|DEBUG >> GetConnection -> The Following Connection is open: Server=W2K19SRV398;Database=DD_ECM;User Id=EDMAdmin;Password=XXXXX;Application Name=DD_EDMIAppService;Workstation ID=W2K19SRV391;
13:45:45.5322|MSSQLServer|DEBUG >> MaybeGetTransaction -> Transaction Mode: [WithTransaction]
13:45:45.5322|MSSQLServer|DEBUG >> GetDatatableWithConnectionObject -> GetDatatableWithConnectionObject: Running Query [SELECT * FROM TBDD_CONNECTION WHERE GUID = 1] and Parameters []
13:45:45.5322|MSSQLServer|DEBUG >> GetConnection -> The Following Connection is open: Data Source=w2k19srv398;Initial Catalog=DD_ECM;User ID=EDMAdmin;Password=XXXXX
13:45:45.5322|MSSQLServer|DEBUG >> MaybeGetTransaction -> Transaction Mode: [WithTransaction]
13:45:45.5322|MSSQLServer|DEBUG >> GetDatatableWithConnectionObject -> GetDatatableWithConnectionObject: Running Query [SELECT
SPEC_NAME [Definitions-Name],
ITEM_DESCRIPTION [Beschreibung],
CASE
WHEN SPEC_NAME = 'INVOICE_POSITION_NOTE' THEN
REPLACE(REPLACE(ITEM_VALUE, CHAR(13),' '),CHAR(10),' ')
ELSE
ITEM_VALUE
END [Inhalt xml],
GROUP_COUNTER [Gruppenzähler],
IS_REQUIRED [Pflichtangabe],
CREATEDWHEN [Erstellt]
FROM dbo.TBEDMI_ITEM_VALUE WITH (NOLOCK)
WHERE REFERENCE_GUID = (SELECT EmailMessageID FROM IDB.dbo.VWIDB_DOC_DATA WHERE IDB_OBJ_ID = 4511694)
ORDER BY GROUP_COUNTER, SPEC_NAME] and Parameters []
13:45:45.5832|taskFLOW|DEBUG >> TabPreload -> === TabPreload END ===