diff options
91 files changed, 7542 insertions, 6609 deletions
@@ -5,7 +5,7 @@ the ones mentioned below. The remaining issues that are yet to be fixed are list ---------------- -| libcurl 7.86| +| libcurl 7.87| ---------------- __________________________________________________________________________________________________________ /lib/ftp.c @@ -62,6 +62,12 @@ move the following constants from src/sftp.h to include/libssh2_sftp.h: #define MAX_SFTP_OUTGOING_SIZE 30000 #define MAX_SFTP_READ_SIZE 30000 __________________________________________________________________________________________________________ +src/sftp.c +Always clear SFTP protocol error: https://github.com/libssh2/libssh2/pull/787 +__________________________________________________________________________________________________________ +src/openssl.c +Fix misleading error message if wrong passphrase: https://github.com/libssh2/libssh2/pull/789 +__________________________________________________________________________________________________________ ------------------- diff --git a/Changelog.txt b/Changelog.txt index 23f4142f..601c33dd 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,21 @@ +FreeFileSync 12.0 [2022-01-21] +------------------------------ +Don't save password and show prompt instead for (S)FTP +Fast path check failure on access errors +Support PuTTY private key file version 3 +Respect timeout during SFTP connect +Removed 20-sec timeout while checking directory existence +Avoid hitting (S)FTP connection limit for non-uniform configs +Fixed middle grid tooltip icon not always showing (Linux) +Optimized file accesses when checking file path existence +Fixed overview navigation marker not always showing on main grid +Clear all grid selections after view filter toggle +Fixed mouse selection starting on folder group +Don't require sudo during non-root installation (Linux) +Stricter type checking when deleting file/folder/symlinks +Succinct error messages when path component is not existing + + FreeFileSync 11.29 [2022-12-16] ------------------------------- Fixed crash after 1-byte file copy from MTP device diff --git a/FreeFileSync/Build/Resources/Icons.zip b/FreeFileSync/Build/Resources/Icons.zip Binary files differindex 6447ca6f..bbf8f526 100644 --- a/FreeFileSync/Build/Resources/Icons.zip +++ b/FreeFileSync/Build/Resources/Icons.zip diff --git a/FreeFileSync/Build/Resources/Languages.zip b/FreeFileSync/Build/Resources/Languages.zip Binary files differindex cb417052..c2293e8f 100644 --- a/FreeFileSync/Build/Resources/Languages.zip +++ b/FreeFileSync/Build/Resources/Languages.zip diff --git a/FreeFileSync/Build/Resources/cacert.pem b/FreeFileSync/Build/Resources/cacert.pem index 0c69f9fc..2ae7b6cb 100644 --- a/FreeFileSync/Build/Resources/cacert.pem +++ b/FreeFileSync/Build/Resources/cacert.pem @@ -1,7 +1,7 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Tue Oct 11 03:12:05 2022 GMT +## Certificate data from Mozilla as of: Tue Jan 10 04:12:06 2023 GMT ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -14,7 +14,7 @@ ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.29. -## SHA256: 3ff8bd209b5f2e739b9f2b96eacb694a774114685b02978257824f37ff528f71 +## SHA256: 90c470e705b4b5f36f09684dc50e2b79c8b86989a848b62cd1a7bd6460ee65f6 ## @@ -489,29 +489,6 @@ IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== -----END CERTIFICATE----- -Network Solutions Certificate Authority -======================================= ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG -EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr -IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx -MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx -jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT -aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT -crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc -/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB -AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv -bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA -A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q -4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ -GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD -ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- - COMODO ECC Certification Authority ================================== -----BEGIN CERTIFICATE----- @@ -1654,36 +1631,6 @@ uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 -----END CERTIFICATE----- -Staat der Nederlanden EV Root CA -================================ ------BEGIN CERTIFICATE----- -MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE -CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g -RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M -MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl -cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk -SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW -O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r -0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8 -Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV -XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr -08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV -0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd -74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx -fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa -ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI -eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu -c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq -5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN -b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN -f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi -5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4 -WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK -DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy -eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg== ------END CERTIFICATE----- - IdenTrust Commercial Root CA 1 ============================== -----BEGIN CERTIFICATE----- @@ -2135,87 +2082,6 @@ F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== -----END CERTIFICATE----- -TrustCor RootCert CA-1 -====================== ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP -MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig -U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx -MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu -YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe -VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy -dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq -jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4 -pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0 -JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h -gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw -/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j -BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5 -mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf -ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C -qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P -3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk= ------END CERTIFICATE----- - -TrustCor RootCert CA-2 -====================== ------BEGIN CERTIFICATE----- -MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w -DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT -eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0 -eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy -MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h -bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U -cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0 -IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb -ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk -RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1 -oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb -XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1 -/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q -jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP -eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg -rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh -8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU -2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h -Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp -kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv -2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3 -S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw -PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv -DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU -RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE -xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX -RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ ------END CERTIFICATE----- - -TrustCor ECA-1 -============== ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP -MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig -U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw -N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5 -MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y -IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR -MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23 -xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc -p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+ -fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj -YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL -f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF -AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u -/ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F -hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs -J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC -jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g== ------END CERTIFICATE----- - SSL.com Root Certification Authority RSA ======================================== -----BEGIN CERTIFICATE----- diff --git a/FreeFileSync/Source/Makefile b/FreeFileSync/Source/Makefile index eb6a6dbe..5d253171 100644 --- a/FreeFileSync/Source/Makefile +++ b/FreeFileSync/Source/Makefile @@ -79,6 +79,7 @@ cppFiles+=ui/tray_icon.cpp cppFiles+=ui/triple_splitter.cpp cppFiles+=ui/version_check.cpp cppFiles+=../../libcurl/curl_wrap.cpp +cppFiles+=../../zen/argon2.cpp cppFiles+=../../zen/file_access.cpp cppFiles+=../../zen/file_io.cpp cppFiles+=../../zen/file_path.cpp diff --git a/FreeFileSync/Source/RealTimeSync/application.cpp b/FreeFileSync/Source/RealTimeSync/application.cpp index 7a058714..a7289497 100644 --- a/FreeFileSync/Source/RealTimeSync/application.cpp +++ b/FreeFileSync/Source/RealTimeSync/application.cpp @@ -10,6 +10,7 @@ #include <zen/thread.h> #include <zen/shutdown.h> #include <zen/resolve_path.h> +#include <wx/clipbrd.h> #include <wx/event.h> #include <wx/log.h> #include <wx/tooltip.h> @@ -189,7 +190,8 @@ void Application::onEnterEventLoop(wxEvent& event) commandArgs.push_back(filePath); else throw FileError(replaceCpy(_("Cannot open file %x."), L"%x", fmtPath(filePath)), - _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(filePath))); + _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(filePath)) + L'\n' + + _("Expected:") + L" ffs_real, ffs_batch"); } Zstring cfgFilePath; @@ -207,6 +209,8 @@ void Application::onEnterEventLoop(wxEvent& event) int Application::OnExit() { + [[maybe_unused]] const bool rv = wxClipboard::Get()->Flush(); //see wx+/context_menu.h + //assert(rv); -> fails if clipboard wasn't used fff::localizationCleanup(); imageResourcesCleanup(); return wxApp::OnExit(); diff --git a/FreeFileSync/Source/RealTimeSync/config.cpp b/FreeFileSync/Source/RealTimeSync/config.cpp index 3101e62b..75b819ce 100644 --- a/FreeFileSync/Source/RealTimeSync/config.cpp +++ b/FreeFileSync/Source/RealTimeSync/config.cpp @@ -96,9 +96,9 @@ void rts::readConfig(const Zstring& filePath, XmlRealConfig& cfg, std::wstring& warn_static("at least log on failure!") } catch (const FileError& e) - { - warningMsg = replaceCpy(_("Configuration file %x is incomplete. The missing elements have been set to their default values."), L"%x", fmtPath(filePath)) + - L"\n\n" + e.toString(); + { + warningMsg = replaceCpy(_("Configuration file %x is incomplete. The missing elements have been set to their default values."), L"%x", fmtPath(filePath)) + + L"\n\n" + e.toString(); } } @@ -140,11 +140,11 @@ void rts::readRealOrBatchConfig(const Zstring& filePath, XmlRealConfig& cfg, std uniqueFolders.insert(folderPathPhraseRight); } - try - { - checkXmlMappingErrors(in); //throw FileError - } - catch (const FileError& e) { throw FileError(replaceCpy(_("File %x does not contain a valid configuration."), L"%x", fmtPath(filePath)) + L"\n\n" + e.toString()); } + try + { + checkXmlMappingErrors(in); //throw FileError + } + catch (const FileError& e) { throw FileError(replaceCpy(_("File %x does not contain a valid configuration."), L"%x", fmtPath(filePath)) + L"\n\n" + e.toString()); } //--------------------------------------------------------------------------------------- std::erase_if(uniqueFolders, [](const Zstring& str) { return trimCpy(str).empty(); }); @@ -167,7 +167,7 @@ wxLanguage rts::getProgramLanguage() //throw FileError } catch (FileError&) { - if (!itemStillExists(filePath)) //throw FileError + if (!itemExists(filePath)) //throw FileError return fff::getDefaultLanguage(); throw; } @@ -179,7 +179,7 @@ wxLanguage rts::getProgramLanguage() //throw FileError wxLanguage lng = wxLANGUAGE_UNKNOWN; in["Language"].attribute("Code", lng); - + try { checkXmlMappingErrors(in); //throw FileError diff --git a/FreeFileSync/Source/RealTimeSync/folder_selector2.cpp b/FreeFileSync/Source/RealTimeSync/folder_selector2.cpp index 671ce606..2d8a3999 100644 --- a/FreeFileSync/Source/RealTimeSync/folder_selector2.cpp +++ b/FreeFileSync/Source/RealTimeSync/folder_selector2.cpp @@ -89,8 +89,7 @@ void FolderSelector2::onMouseWheel(wxMouseEvent& event) //redirect to parent scrolled window! for (wxWindow* wnd = folderPathCtrl_.GetParent(); wnd; wnd = wnd->GetParent()) if (dynamic_cast<wxScrolledWindow*>(wnd) != nullptr) - if (wxEvtHandler* evtHandler = wnd->GetEventHandler()) - return evtHandler->AddPendingEvent(event); + return wnd->GetEventHandler()->AddPendingEvent(event); assert(false); event.Skip(); } @@ -133,7 +132,7 @@ void FolderSelector2::onSelectDir(wxCommandEvent& event) //IFileDialog requirements for default path: 1. accepts native paths only!!! 2. path must exist! Zstring defaultFolderPath; { - auto folderAccessible = [waitEndTime = std::chrono::steady_clock::now() + FOLDER_SELECTED_EXISTENCE_CHECK_TIME_MAX](const Zstring& folderPath) + auto folderAccessible = [stopTime = std::chrono::steady_clock::now() + FOLDER_SELECTED_EXISTENCE_CHECK_TIME_MAX](const Zstring& folderPath) { auto ft = runAsync([folderPath] { @@ -144,7 +143,7 @@ void FolderSelector2::onSelectDir(wxCommandEvent& event) catch (FileError&) { return false; } }); - return ft.wait_until(waitEndTime) == std::future_status::ready && ft.get(); //potentially slow network access: wait 200ms at most + return ft.wait_until(stopTime) == std::future_status::ready && ft.get(); //potentially slow network access: wait 200ms at most }; auto trySetDefaultPath = [&](const Zstring& folderPathPhrase) diff --git a/FreeFileSync/Source/RealTimeSync/gui_generated.cpp b/FreeFileSync/Source/RealTimeSync/gui_generated.cpp index fcb5c6a8..0f91a13d 100644 --- a/FreeFileSync/Source/RealTimeSync/gui_generated.cpp +++ b/FreeFileSync/Source/RealTimeSync/gui_generated.cpp @@ -102,7 +102,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr wxBoxSizer* bSizer152; bSizer152 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText811 = new wxStaticText( this, wxID_ANY, _("To get started just import a \"ffs_batch\" file."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText811 = new wxStaticText( this, wxID_ANY, _("To get started, just import a \"ffs_batch\" file."), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText811->Wrap( -1 ); m_staticText811->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); diff --git a/FreeFileSync/Source/RealTimeSync/main_dlg.cpp b/FreeFileSync/Source/RealTimeSync/main_dlg.cpp index 95a4bc4b..707442fc 100644 --- a/FreeFileSync/Source/RealTimeSync/main_dlg.cpp +++ b/FreeFileSync/Source/RealTimeSync/main_dlg.cpp @@ -36,7 +36,7 @@ namespace std::wstring extractJobName(const Zstring& cfgFilePath) { - const Zstring fileName = afterLast(cfgFilePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all); + const Zstring fileName = getItemName(cfgFilePath); const Zstring jobName = beforeLast(fileName, Zstr('.'), IfNotFoundReturn::all); return utfTo<std::wstring>(jobName); } @@ -110,7 +110,7 @@ MainDialog::MainDialog(const Zstring& cfgFilePath) : if (currentConfigFile.empty()) try { - if (itemStillExists(lastRunConfigPath_)) //throw FileError + if (itemExists(lastRunConfigPath_)) //throw FileError currentConfigFile = lastRunConfigPath_; } catch (FileError&) { currentConfigFile = lastRunConfigPath_; } //access error? => user should be informed @@ -246,7 +246,7 @@ void MainDialog::onConfigSave(wxCommandEvent& event) std::optional<Zstring> defaultFolderPath = getParentFolderPath(activeCfgFilePath); Zstring defaultFileName = !activeCfgFilePath.empty() ? - afterLast(activeCfgFilePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all) : + getItemName(activeCfgFilePath) : Zstr("RealTime.ffs_real"); //attention: activeConfigFile_ may be an imported *.ffs_batch file! We don't want to overwrite it with a RTS config! diff --git a/FreeFileSync/Source/RealTimeSync/monitor.cpp b/FreeFileSync/Source/RealTimeSync/monitor.cpp index 9ea02d63..63b35c91 100644 --- a/FreeFileSync/Source/RealTimeSync/monitor.cpp +++ b/FreeFileSync/Source/RealTimeSync/monitor.cpp @@ -47,7 +47,16 @@ std::set<Zstring, LessNativePath> waitForMissingDirs(const std::vector<Zstring>& //start all folder checks asynchronously (non-existent network path may block) if (!folderInfos.contains(folderPath)) - folderInfos[folderPath] = { phrase, runAsync([folderPath]{ return dirAvailable(folderPath); }) }; + folderInfos[folderPath] = { phrase, runAsync([folderPath] + { + try + { + getItemType(folderPath); //throw FileError + return true; + } + catch (FileError&) { return false; } + }) + }; } std::set<Zstring, LessNativePath> availablePaths; @@ -85,7 +94,12 @@ std::set<Zstring, LessNativePath> waitForMissingDirs(const std::vector<Zstring>& std::future<bool> folderAvailable = runAsync([folderPath] { - return dirAvailable(folderPath); + try + { + getItemType(folderPath); //throw FileError + return true; + } + catch (FileError&) { return false; } }); while (folderAvailable.wait_for(cbInterval) == std::future_status::timeout) @@ -104,7 +118,6 @@ std::set<Zstring, LessNativePath> waitForMissingDirs(const std::vector<Zstring>& DirWatcher::Change waitForChanges(const std::set<Zstring, LessNativePath>& folderPaths, //throw FileError const std::function<void(bool readyForSync)>& requestUiUpdate, std::chrono::milliseconds cbInterval) { - assert(std::all_of(folderPaths.begin(), folderPaths.end(), [](const Zstring& folderPath) { return dirAvailable(folderPath); })); if (folderPaths.empty()) //pathological case, but we have to check else this function will wait endlessly throw FileError(_("A folder input field is empty.")); //should have been checked by caller! @@ -117,8 +130,13 @@ DirWatcher::Change waitForChanges(const std::set<Zstring, LessNativePath>& folde } catch (FileError&) { - if (!dirAvailable(folderPath)) //folder not existing or can't access + try { getItemType(folderPath); } //throw FileError + catch (FileError&) + { + assert(false); //why "unavailable"!? violating waitForChanges() precondition! return {DirWatcher::ChangeType::baseFolderUnavailable, folderPath}; + } + throw; } @@ -140,8 +158,12 @@ DirWatcher::Change waitForChanges(const std::set<Zstring, LessNativePath>& folde { //IMPORTANT CHECK: DirWatcher has problems detecting removal of top watched directories! if (checkDirNow) - if (!dirAvailable(folderPath)) //catch errors related to directory removal, e.g. ERROR_NETNAME_DELETED - return {DirWatcher::ChangeType::baseFolderUnavailable, folderPath}; + try //catch errors related to directory removal, e.g. ERROR_NETNAME_DELETED + { + getItemType(folderPath); //throw FileError + } + catch (FileError&) { return {DirWatcher::ChangeType::baseFolderUnavailable, folderPath}; } + try { std::vector<DirWatcher::Change> changes = watcher->fetchChanges([&] { requestUiUpdate(false /*readyForSync*/); /*throw X*/ }, @@ -166,8 +188,9 @@ DirWatcher::Change waitForChanges(const std::set<Zstring, LessNativePath>& folde } catch (FileError&) { - if (!dirAvailable(folderPath)) //a benign(?) race condition with FileError - return {DirWatcher::ChangeType::baseFolderUnavailable, folderPath}; + try { getItemType(folderPath); } //throw FileError + catch (FileError&) { return {DirWatcher::ChangeType::baseFolderUnavailable, folderPath}; } + throw; } } diff --git a/FreeFileSync/Source/afs/abstract.cpp b/FreeFileSync/Source/afs/abstract.cpp index a6b8ae1a..17dd4f4c 100644 --- a/FreeFileSync/Source/afs/abstract.cpp +++ b/FreeFileSync/Source/afs/abstract.cpp @@ -38,8 +38,8 @@ std::weak_ordering AFS::compareDevice(const AbstractFileSystem& lhs, const Abstr std::optional<AbstractPath> AFS::getParentPath(const AbstractPath& itemPath) { - if (const std::optional<AfsPath> parentAfsPath = getParentPath(itemPath.afsPath)) - return AbstractPath(itemPath.afsDevice, *parentAfsPath); + if (const std::optional<AfsPath> parentPath = getParentPath(itemPath.afsPath)) + return AbstractPath(itemPath.afsDevice, *parentPath); return {}; } @@ -80,10 +80,10 @@ private: } -void AFS::traverseFolderFlat(const AfsPath& folderPath, //throw FileError - const std::function<void(const FileInfo& fi)>& onFile, - const std::function<void(const FolderInfo& fi)>& onFolder, - const std::function<void(const SymlinkInfo& si)>& onSymlink) const +void AFS::traverseFolder(const AfsPath& folderPath, //throw FileError + const std::function<void(const FileInfo& fi)>& onFile, + const std::function<void(const FolderInfo& fi)>& onFolder, + const std::function<void(const SymlinkInfo& si)>& onSymlink) const { auto ft = std::make_shared<FlatTraverserCallback>(onFile, onFolder, onSymlink); //throw FileError traverseFolderRecursive({{folderPath, ft}}, 1 /*parallelOps*/); //throw FileError @@ -133,9 +133,8 @@ AFS::FileCopyResult AFS::copyFileAsStream(const AfsPath& sourcePath, const Strea //check incomplete input *before* failing with (slightly) misleading error message in OutputStream::finalize() if (totalBytesRead != makeSigned(attrSourceNew.fileSize)) throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(getDisplayPath(sourcePath))), - replaceCpy(replaceCpy(_("Unexpected size of data stream.\nExpected: %x bytes\nActual: %y bytes"), - L"%x", formatNumber(attrSourceNew.fileSize)), - L"%y", formatNumber(totalBytesRead)) + L" [notifyUnbufferedRead]"); + _("Unexpected size of data stream:") + L' ' + formatNumber(totalBytesRead) + L'\n' + + _("Expected:") + L' ' + formatNumber(attrSourceNew.fileSize) + L" [notifyUnbufferedRead]"); const FinalizeResult finResult = streamOut->finalize(notifyUnbufferedWrite); //throw FileError, X @@ -146,9 +145,8 @@ AFS::FileCopyResult AFS::copyFileAsStream(const AfsPath& sourcePath, const Strea //catch file I/O bugs + read/write conflicts: (note: different check than inside AFS::OutputStream::finalize() => checks notifyUnbufferedIO()!) if (totalBytesWritten != totalBytesRead) throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(getDisplayPath(targetPath))), - replaceCpy(replaceCpy(_("Unexpected size of data stream.\nExpected: %x bytes\nActual: %y bytes"), - L"%x", formatNumber(totalBytesRead)), - L"%y", formatNumber(totalBytesWritten)) + L" [notifyUnbufferedWrite]"); + _("Unexpected size of data stream:") + L' ' + formatNumber(totalBytesWritten) + L'\n' + + _("Expected:") + L' ' + formatNumber(totalBytesRead) + L" [notifyUnbufferedWrite]"); return { .fileSize = attrSourceNew.fileSize, @@ -248,115 +246,101 @@ AFS::FileCopyResult AFS::copyFileTransactional(const AbstractPath& sourcePath, c } -bool AFS::createFolderIfMissingRecursion(const AbstractPath& folderPath) //throw FileError +void AFS::createFolderIfMissingRecursion(const AbstractPath& folderPath) //throw FileError { - const std::optional<AbstractPath> parentPath = getParentPath(folderPath); - if (!parentPath) //device root - return false; - - try //generally we expect that path already exists (see: versioning, base folder, log file path) => check first - { - if (getItemType(folderPath) != ItemType::file) //throw FileError - return false; - } - catch (FileError&) {} //not yet existing or access error? let's find out... - - createFolderIfMissingRecursion(*parentPath); //throw FileError + //expect that path already exists (see: versioning, base folder, log file path) => check first + const std::variant<ItemType, AfsPath /*last existing parent path*/> typeOrPath = getItemTypeIfExists(folderPath); //throw FileError try { - //already existing: fail - createFolderPlain(folderPath); //throw FileError - return true; - } - catch (FileError&) - { - try + if (const ItemType* type = std::get_if<ItemType>(&typeOrPath)) { - if (getItemType(folderPath) != ItemType::file) //throw FileError - return true; //already existing => possible, if createFolderIfMissingRecursion() is run in parallel + if (*type == ItemType::file /*obscure, but possible*/) + throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(getItemName(folderPath)))); + } + else + { + const AfsPath existingFolderPath = std::get<AfsPath>(typeOrPath); + assert(startsWith(folderPath.afsPath.value, existingFolderPath.value)); + + const ZstringView relPathTmp = makeStringView(folderPath.afsPath.value.begin() + existingFolderPath.value.size(), folderPath.afsPath.value.end()); + const std::vector<ZstringView> relPathComp = splitCpy(relPathTmp, FILE_NAME_SEPARATOR, SplitOnEmpty::skip); //sanitize! relPathTmp starts with FILE_NAME_SEPARATOR unless existingFolderPath.empty() + assert(!relPathComp.empty()); + + AbstractPath folderPathNew{folderPath.afsDevice, existingFolderPath}; + for (const ZstringView folderName : relPathComp) + try + { + folderPathNew = appendRelPath(folderPathNew, Zstring(folderName)); + + createFolderPlain(folderPathNew); //throw FileError + } + catch (FileError&) + { + try + { + if (getItemType(folderPathNew) == ItemType::file /*obscure, but possible*/) //throw FileError + throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(getItemName(folderPathNew)))); + else + continue; //already existing => possible, if createFolderIfMissingRecursion() is run in parallel + } + catch (FileError&) {} //not yet existing or access error + + throw; + } } - catch (FileError&) {} //not yet existing or access error - - throw; } -} - - -//default implementation: folder traversal -std::optional<AFS::ItemType> AFS::itemStillExists(const AfsPath& itemPath) const //throw FileError -{ - try + catch (const SysError& e) { - //fast check: 1. perf 2. expected by getFolderStatusNonBlocking() 3. traversing non-existing folder below MIGHT NOT FAIL (e.g. for SFTP on AWS) - return getItemType(itemPath); //throw FileError + throw FileError(replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(getDisplayPath(folderPath))), e.toString()); } - catch (const FileError& e) //not existing or access error - { - const std::optional<AfsPath> parentAfsPath = getParentPath(itemPath); - if (!parentAfsPath) //device root - throw; - //else: let's dig deeper... don't bother checking Win32 codes; e.g. not existing item may have the codes: - // ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, ERROR_INVALID_NAME, ERROR_INVALID_DRIVE, - // ERROR_NOT_READY, ERROR_INVALID_PARAMETER, ERROR_BAD_PATHNAME, ERROR_BAD_NETPATH => not reliable - - const std::optional<ItemType> parentType = itemStillExists(*parentAfsPath); //throw FileError +} - if (parentType && *parentType != ItemType::file /*obscure, but possible (and not an error)*/) - try - { - const Zstring itemName = getItemName(itemPath); - assert(!itemName.empty()); - traverseFolderFlat(*parentAfsPath, //throw FileError - [&](const FileInfo& fi) { if (fi.itemName == itemName) throw ItemType::file; }, - [&](const FolderInfo& fi) { if (fi.itemName == itemName) throw ItemType::folder; }, - [&](const SymlinkInfo& si) { if (si.itemName == itemName) throw ItemType::symlink; }); - } - catch (const ItemType&) //finding the item after getItemType() previously failed is exceptional - { - throw FileError(_("Temporary access error:") + L' ' + e.toString()); - } - return {}; - } +bool AFS::itemExists(const AfsPath& itemPath) const //throw FileError +{ + const std::variant<ItemType, AfsPath /*last existing parent path*/> typeOrPath = getItemTypeIfExists(itemPath); //throw FileError + return std::get_if<ItemType>(&typeOrPath); } //default implementation: folder traversal void AFS::removeFolderIfExistsRecursion(const AfsPath& folderPath, //throw FileError - const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, //optional - const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion) const //one call for each object! + const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, // + const std::function<void(const std::wstring& displayPath)>& onBeforeSymlinkDeletion /*throw X*/, //optional; one call for each object! + const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion /*throw X*/) const { - //deferred recursion => save stack space and allow deletion of extremely deep hierarchies! std::function<void(const AfsPath& folderPath2)> removeFolderRecursionImpl; - removeFolderRecursionImpl = [this, &onBeforeFileDeletion, &onBeforeFolderDeletion, &removeFolderRecursionImpl](const AfsPath& folderPath2) //throw FileError + removeFolderRecursionImpl = [this, &onBeforeFileDeletion, &onBeforeSymlinkDeletion, &onBeforeFolderDeletion, &removeFolderRecursionImpl](const AfsPath& folderPath2) //throw FileError { - std::vector<Zstring> fileNames; std::vector<Zstring> folderNames; - std::vector<Zstring> symlinkNames; + { + std::vector<Zstring> fileNames; + std::vector<Zstring> symlinkNames; - traverseFolderFlat(folderPath2, //throw FileError - [&](const FileInfo& fi) { fileNames.push_back(fi.itemName); }, - [&](const FolderInfo& fi) { folderNames.push_back(fi.itemName); }, - [&](const SymlinkInfo& si) { symlinkNames.push_back(si.itemName); }); + traverseFolder(folderPath2, //throw FileError + [&](const FileInfo& fi) { fileNames.push_back(fi.itemName); }, + [&](const FolderInfo& fi) { folderNames.push_back(fi.itemName); }, + [&](const SymlinkInfo& si) { symlinkNames.push_back(si.itemName); }); - for (const Zstring& fileName : fileNames) - { - const AfsPath filePath(appendPath(folderPath2.value, fileName)); - if (onBeforeFileDeletion) - onBeforeFileDeletion(getDisplayPath(filePath)); //throw X + for (const Zstring& fileName : fileNames) + { + const AfsPath filePath(appendPath(folderPath2.value, fileName)); + if (onBeforeFileDeletion) + onBeforeFileDeletion(getDisplayPath(filePath)); //throw X - removeFilePlain(filePath); //throw FileError - } + removeFilePlain(filePath); //throw FileError + } - for (const Zstring& symlinkName : symlinkNames) - { - const AfsPath linkPath(appendPath(folderPath2.value, symlinkName)); - if (onBeforeFileDeletion) - onBeforeFileDeletion(getDisplayPath(linkPath)); //throw X + for (const Zstring& symlinkName : symlinkNames) + { + const AfsPath linkPath(appendPath(folderPath2.value, symlinkName)); + if (onBeforeSymlinkDeletion) + onBeforeSymlinkDeletion(getDisplayPath(linkPath)); //throw X - removeSymlinkPlain(linkPath); //throw FileError - } + removeSymlinkPlain(linkPath); //throw FileError + } + } //=> save stack space and allow deletion of extremely deep hierarchies! for (const Zstring& folderName : folderNames) removeFolderRecursionImpl(AfsPath(appendPath(folderPath2.value, folderName))); //throw FileError @@ -369,19 +353,22 @@ void AFS::removeFolderIfExistsRecursion(const AfsPath& folderPath, //throw FileE //-------------------------------------------------------------------------------------------------------------- //no error situation if directory is not existing! manual deletion relies on it! - if (std::optional<ItemType> type = itemStillExists(folderPath)) //throw FileError + const std::variant<ItemType, AfsPath /*last existing parent path*/> typeOrPath = getItemTypeIfExists(folderPath); //throw FileError + if (const ItemType* type = std::get_if<ItemType>(&typeOrPath)) { + assert(*type != ItemType::symlink); + if (*type == ItemType::symlink) { - if (onBeforeFileDeletion) - onBeforeFileDeletion(getDisplayPath(folderPath)); //throw X + if (onBeforeSymlinkDeletion) + onBeforeSymlinkDeletion(getDisplayPath(folderPath)); //throw X removeSymlinkPlain(folderPath); //throw FileError } else removeFolderRecursionImpl(folderPath); //throw FileError } - else //even if the folder did not exist anymore, significant I/O work was done => report + else //even if the folder does not exist anymore, significant I/O work was done => report if (onBeforeFolderDeletion) onBeforeFolderDeletion(getDisplayPath(folderPath)); //throw X } @@ -396,7 +383,7 @@ void AFS::removeFileIfExists(const AbstractPath& filePath) //throw FileError { try { - if (!itemStillExists(filePath)) //throw FileError + if (!itemExists(filePath)) //throw FileError return; } //abstract context => unclear which exception is more relevant/useless: @@ -417,7 +404,7 @@ void AFS::removeSymlinkIfExists(const AbstractPath& linkPath) //throw FileError { try { - if (!itemStillExists(linkPath)) //throw FileError + if (!itemExists(linkPath)) //throw FileError return; } //abstract context => unclear which exception is more relevant/useless: @@ -438,7 +425,7 @@ void AFS::removeEmptyFolderIfExists(const AbstractPath& folderPath) //throw File { try { - if (!itemStillExists(folderPath)) //throw FileError + if (!itemExists(folderPath)) //throw FileError return; } //abstract context => unclear which exception is more relevant/useless: @@ -455,12 +442,12 @@ void AFS::RecycleSession::moveToRecycleBinIfExists(const AbstractPath& itemPath, { moveToRecycleBin(itemPath, logicalRelPath); //throw FileError, RecycleBinUnavailable } - catch (RecycleBinUnavailable&) { throw; } //[!] no need for itemStillExists() file access! + catch (RecycleBinUnavailable&) { throw; } //[!] no need for itemExists() file access! catch (const FileError& e) { try { - if (!itemStillExists(itemPath)) //throw FileError + if (!itemExists(itemPath)) //throw FileError return; } //abstract context => unclear which exception is more relevant/useless: @@ -477,12 +464,12 @@ void AFS::moveToRecycleBinIfExists(const AbstractPath& itemPath) //throw FileErr { moveToRecycleBin(itemPath); //throw FileError, RecycleBinUnavailable } - catch (RecycleBinUnavailable&) { throw; } //[!] no need for itemStillExists() file access! + catch (RecycleBinUnavailable&) { throw; } //[!] no need for itemExists() file access! catch (const FileError& e) { try { - if (!itemStillExists(itemPath)) //throw FileError + if (!itemExists(itemPath)) //throw FileError return; } //abstract context => unclear which exception is more relevant/useless: diff --git a/FreeFileSync/Source/afs/abstract.h b/FreeFileSync/Source/afs/abstract.h index 91d30284..2d43736a 100644 --- a/FreeFileSync/Source/afs/abstract.h +++ b/FreeFileSync/Source/afs/abstract.h @@ -9,6 +9,7 @@ #include <functional> #include <chrono> +#include <variant> #include <zen/file_error.h> #include <zen/file_path.h> #include <zen/serialize.h> //InputStream/OutputStream support buffered stream concept @@ -71,10 +72,9 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t static std::vector<Zstring> getPathPhraseAliases(const AbstractPath& itemPath) { return itemPath.afsDevice.ref().getPathPhraseAliases(itemPath.afsPath); } //---------------------------------------------------------------------------------------------------------------- - static void authenticateAccess(const AfsDevice& afsDevice, bool allowUserInteraction) //throw FileError - { return afsDevice.ref().authenticateAccess(allowUserInteraction); } - - static int getAccessTimeout(const AbstractPath& itemPath) { return itemPath.afsDevice.ref().getAccessTimeout(); } //returns "0" if no timeout in force + using RequestPasswordFun = std::function<Zstring(const std::wstring& msg, const std::wstring& lastErrorMsg)>; //throw X + static void authenticateAccess(const AfsDevice& afsDevice, const RequestPasswordFun& requestPassword /*throw X*/) //throw FileError, X + { return afsDevice.ref().authenticateAccess(requestPassword); } static bool supportPermissionCopy(const AbstractPath& sourcePath, const AbstractPath& targetPath); //throw FileError @@ -93,11 +93,14 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t //root path? => do access test static ItemType getItemType(const AbstractPath& itemPath) { return itemPath.afsDevice.ref().getItemType(itemPath.afsPath); } //throw FileError - //assumes: - base path still exists + //assumes: - folder traversal access right (=> yes, because we can assume base path exist at this point; e.g. avoids problem when SFTP parent paths might deny access) // - all child item path parts must correspond to folder traversal - // => we can conclude whether an item is *not* existing anymore by doing a *case-sensitive* name search => potentially SLOW! - // root path? => do access test - static std::optional<ItemType> itemStillExists(const AbstractPath& itemPath) { return itemPath.afsDevice.ref().itemStillExists(itemPath.afsPath); } //throw FileError + // => conclude whether an item is *not* existing anymore by doing a *case-sensitive* name search => potentially SLOW! + // - root path? => do access test + static std::variant<ItemType, AfsPath /*last existing parent path*/> getItemTypeIfExists(const AbstractPath& itemPath) + { return itemPath.afsDevice.ref().getItemTypeIfExists(itemPath.afsPath); } //throw FileError + + static bool itemExists(const AbstractPath& itemPath) { return itemPath.afsDevice.ref().itemExists(itemPath.afsPath); } //throw FileError //---------------------------------------------------------------------------------------------------------------- //already existing: fail @@ -106,12 +109,13 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t //creates directories recursively if not existing //returns false if folder already exists - static bool createFolderIfMissingRecursion(const AbstractPath& folderPath); //throw FileError + static void createFolderIfMissingRecursion(const AbstractPath& folderPath); //throw FileError static void removeFolderIfExistsRecursion(const AbstractPath& folderPath, //throw FileError - const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, //optional - const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion) //one call for each object! - { return folderPath.afsDevice.ref().removeFolderIfExistsRecursion(folderPath.afsPath, onBeforeFileDeletion, onBeforeFolderDeletion); } + const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, // + const std::function<void(const std::wstring& displayPath)>& onBeforeSymlinkDeletion /*throw X*/, //optional; one call for each object! + const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion /*throw X*/) // + { return folderPath.afsDevice.ref().removeFolderIfExistsRecursion(folderPath.afsPath, onBeforeFileDeletion, onBeforeSymlinkDeletion, onBeforeFolderDeletion); } static void removeFileIfExists (const AbstractPath& filePath); // static void removeSymlinkIfExists (const AbstractPath& linkPath); //throw FileError @@ -247,11 +251,11 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t //- client needs to handle duplicate file reports! (FilePlusTraverser fallback, retrying to read directory contents, ...) static void traverseFolderRecursive(const AfsDevice& afsDevice, const TraverserWorkload& workload /*throw X*/, size_t parallelOps) { afsDevice.ref().traverseFolderRecursive(workload, parallelOps); } - static void traverseFolderFlat(const AbstractPath& folderPath, //throw FileError - const std::function<void(const FileInfo& fi)>& onFile, // - const std::function<void(const FolderInfo& fi)>& onFolder, //optional - const std::function<void(const SymlinkInfo& si)>& onSymlink) // - { folderPath.afsDevice.ref().traverseFolderFlat(folderPath.afsPath, onFile, onFolder, onSymlink); } + static void traverseFolder(const AbstractPath& folderPath, //throw FileError + const std::function<void(const FileInfo& fi)>& onFile, // + const std::function<void(const FolderInfo& fi)>& onFolder, //optional + const std::function<void(const SymlinkInfo& si)>& onSymlink) // + { folderPath.afsDevice.ref().traverseFolder(folderPath.afsPath, onFile, onFolder, onSymlink); } //---------------------------------------------------------------------------------------------------------------- //already existing: undefined behavior! (e.g. fail/overwrite) @@ -304,7 +308,7 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t //- multi-threaded access: internally synchronized! void moveToRecycleBinIfExists(const AbstractPath& itemPath, const Zstring& logicalRelPath); //throw FileError, RecycleBinUnavailable - //- fails if item is not existing + //- fails if item is not existing: don't leave user wonder why it isn't in the recycle bin! //- multi-threaded access: internally synchronized! virtual void moveToRecycleBin(const AbstractPath& itemPath, const Zstring& logicalRelPath) = 0; //throw FileError, RecycleBinUnavailable @@ -328,18 +332,18 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t protected: - //default implementation: folder traversal - virtual std::optional<ItemType> itemStillExists(const AfsPath& itemPath) const = 0; //throw FileError + bool itemExists(const AfsPath& itemPath) const; //throw FileError //default implementation: folder traversal virtual void removeFolderIfExistsRecursion(const AfsPath& folderPath, //throw FileError - const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion, //optional - const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion) const = 0; //one call for each object! + const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion, + const std::function<void(const std::wstring& displayPath)>& onBeforeSymlinkDeletion, + const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion) const = 0; - void traverseFolderFlat(const AfsPath& folderPath, //throw FileError - const std::function<void(const FileInfo& fi)>& onFile, // - const std::function<void(const FolderInfo& fi)>& onFolder, //optional - const std::function<void(const SymlinkInfo& si)>& onSymlink) const; // + void traverseFolder(const AfsPath& folderPath, //throw FileError + const std::function<void(const FileInfo& fi)>& onFile, // + const std::function<void(const FolderInfo& fi)>& onFolder, //optional + const std::function<void(const SymlinkInfo& si)>& onSymlink) const; // //already existing: undefined behavior! (e.g. fail/overwrite/auto-rename) FileCopyResult copyFileAsStream(const AfsPath& sourcePath, const StreamAttributes& attrSource, //throw FileError, ErrorFileLocked, X @@ -360,7 +364,8 @@ private: //---------------------------------------------------------------------------------------------------------------- virtual ItemType getItemType(const AfsPath& itemPath) const = 0; //throw FileError - //---------------------------------------------------------------------------------------------------------------- + + virtual std::variant<ItemType, AfsPath /*last existing parent path*/> getItemTypeIfExists(const AfsPath& itemPath) const = 0; //throw FileError //already existing: fail virtual void createFolderPlain(const AfsPath& folderPath) const = 0; //throw FileError @@ -410,9 +415,7 @@ private: virtual zen::FileIconHolder getFileIcon (const AfsPath& filePath, int pixelSize) const = 0; //throw FileError; optional return value virtual zen::ImageHolder getThumbnailImage(const AfsPath& filePath, int pixelSize) const = 0; //throw FileError; optional return value - virtual void authenticateAccess(bool allowUserInteraction) const = 0; //throw FileError - - virtual int getAccessTimeout() const = 0; //returns "0" if no timeout in force + virtual void authenticateAccess(const RequestPasswordFun& requestPassword /*throw X*/) const = 0; //throw FileError, X virtual bool hasNativeTransactionalCopy() const = 0; //---------------------------------------------------------------------------------------------------------------- @@ -491,9 +494,8 @@ AbstractFileSystem::FinalizeResult AbstractFileSystem::OutputStream::finalize(co //important check: catches corrupt SFTP download with libssh2! if (bytesExpected_ && *bytesExpected_ != bytesWrittenTotal_) throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(getDisplayPath(filePath_))), //instead we should report the source file, but don't have it here... - replaceCpy(replaceCpy(_("Unexpected size of data stream.\nExpected: %x bytes\nActual: %y bytes"), - L"%x", formatNumber(*bytesExpected_)), - L"%y", formatNumber(bytesWrittenTotal_))); + _("Unexpected size of data stream:") + L' ' + formatNumber(bytesWrittenTotal_) + L'\n' + + _("Expected:") + L' ' + formatNumber(*bytesExpected_)); const FinalizeResult result = outStream_->finalize(notifyUnbufferedIO); //throw FileError, X finalizeSucceeded_ = true; diff --git a/FreeFileSync/Source/afs/abstract_impl.h b/FreeFileSync/Source/afs/abstract_impl.h index 95f21301..f4e7a883 100644 --- a/FreeFileSync/Source/afs/abstract_impl.h +++ b/FreeFileSync/Source/afs/abstract_impl.h @@ -15,12 +15,12 @@ namespace fff { template <class Function> inline //return ignored error message if available -std::wstring tryReportingDirError(Function cmd /*throw FileError*/, AbstractFileSystem::TraverserCallback& cb /*throw X*/) +std::wstring tryReportingDirError(Function cmd /*throw FileError, X*/, AbstractFileSystem::TraverserCallback& cb /*throw X*/) { for (size_t retryNumber = 0;; ++retryNumber) try { - cmd(); //throw FileError + cmd(); //throw FileError, X return std::wstring(); } catch (const zen::FileError& e) @@ -91,7 +91,7 @@ public: using namespace zen; if (const std::shared_ptr<PathAccessLocker> pal = getGlobalInstance()) - pal->pathLocks_.access([&](std::map<NativePath, std::weak_ptr<BlockInfo>>& pathLocks) + pal->protPathLocks_.access([&](std::map<NativePath, std::weak_ptr<BlockInfo>>& pathLocks) { //clean up obsolete entries std::erase_if(pathLocks, [](const auto& v) { return !v.second.lock(); }); @@ -146,7 +146,7 @@ private: static std::shared_ptr<PathAccessLocker> getGlobalInstance(); static Zstring getItemName(const NativePath& nativePath); - zen::Protected<std::map<NativePath, std::weak_ptr<BlockInfo>>> pathLocks_; + zen::Protected<std::map<NativePath, std::weak_ptr<BlockInfo>>> protPathLocks_; }; } diff --git a/FreeFileSync/Source/afs/ftp.cpp b/FreeFileSync/Source/afs/ftp.cpp index ab33a6f7..ca3e147e 100644 --- a/FreeFileSync/Source/afs/ftp.cpp +++ b/FreeFileSync/Source/afs/ftp.cpp @@ -47,35 +47,54 @@ enum class ServerEncoding inline -int getEffectivePort(int portOption) +uint16_t getEffectivePort(int portOption) { if (portOption > 0) - return portOption; + return static_cast<uint16_t>(portOption); return DEFAULT_PORT_FTP; } -} -namespace fff +struct FtpDeviceId //= what defines a unique FTP location { -std::weak_ordering operator<=>(const FtpSessionId& lhs, const FtpSessionId& rhs) + FtpDeviceId(const FtpLogin& login) : + server(login.server), + port(getEffectivePort(login.portCfg)), + username(login.username) {} + + Zstring server; + uint16_t port; //must be valid port! + Zstring username; +}; +std::weak_ordering operator<=>(const FtpDeviceId& lhs, const FtpDeviceId& rhs) { - //exactly the type of case insensitive comparison we need for server names! - if (const std::weak_ordering cmp = compareAsciiNoCase(lhs.server, rhs.server); //https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfow#IDNs + //exactly the type of case insensitive comparison we need for server names! https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfow#IDNs + if (const std::weak_ordering cmp = compareAsciiNoCase(lhs.server, rhs.server); cmp != std::weak_ordering::equivalent) return cmp; - const int portLhs = getEffectivePort(lhs.port); - const int portRhs = getEffectivePort(rhs.port); - - return std::tie(portLhs, lhs.username, lhs.password, lhs.useTls) <=> //username, password: case sensitive! - std::tie(portRhs, rhs.username, rhs.password, rhs.useTls); -} + return std::tie(lhs.port, lhs.username) <=> //username: case sensitive! + std::tie(rhs.port, rhs.username); } +//also needed by compareDeviceSameAfsType(), so can't just replace with hash and use std::unordered_map -namespace +struct FtpSessionCfg //= config for buffered FTP session +{ + FtpDeviceId deviceId; + Zstring password; + bool useTls = false; +}; +bool operator==(const FtpSessionCfg& lhs, const FtpSessionCfg& rhs) { + if (lhs.deviceId <=> rhs.deviceId != std::weak_ordering::equivalent) + return false; + + return std::tie(lhs.password, lhs.useTls) == //password: case sensitive! + std::tie(rhs.password, rhs.useTls); +} + + Zstring concatenateFtpFolderPathPhrase(const FtpLogin& login, const AfsPath& itemPath); //noexcept @@ -134,18 +153,17 @@ std::string utfToAnsiEncoding(const Zstring& str) //throw SysError } -std::wstring getCurlDisplayPath(const FtpSessionId& sessionId, const AfsPath& itemPath) +std::wstring getCurlDisplayPath(const FtpDeviceId& deviceId, const AfsPath& itemPath) { Zstring displayPath = Zstring(ftpPrefix) + Zstr("//"); - if (!sessionId.username.empty()) //show username! consider AFS::compareDeviceSameAfsType() - displayPath += sessionId.username + Zstr('@'); + if (!deviceId.username.empty()) //show username! consider AFS::compareDeviceSameAfsType() + displayPath += deviceId.username + Zstr('@'); - displayPath += sessionId.server; + displayPath += deviceId.server; - if (const int port = getEffectivePort(sessionId.port); - port != DEFAULT_PORT_FTP) - displayPath += Zstr(':') + numberTo<Zstring>(port); + if (deviceId.port != DEFAULT_PORT_FTP) + displayPath += Zstr(':') + numberTo<Zstring>(deviceId.port); const Zstring& relPath = getServerRelPath(itemPath); if (relPath != Zstr("/")) @@ -263,6 +281,16 @@ std::wstring formatFtpStatus(int sc) //================================================================================================================ //================================================================================================================ +struct SysErrorFtpProtocol : public zen::SysError +{ + SysErrorFtpProtocol(const std::wstring& msg, long ftpError) : SysError(msg), ftpErrorCode(ftpError) {} + + long ftpErrorCode; +}; + +DEFINE_NEW_SYS_ERROR(SysErrorPassword) + + constinit Global<UniSessionCounter> globalFtpSessionCount; GLOBAL_RUN_ONCE(globalFtpSessionCount.set(createUniSessionCounter())); @@ -270,8 +298,8 @@ GLOBAL_RUN_ONCE(globalFtpSessionCount.set(createUniSessionCounter())); class FtpSession { public: - explicit FtpSession(const FtpSessionId& sessionId) : //throw SysError - sessionId_(sessionId) + explicit FtpSession(const FtpSessionCfg& sessionCfg) : //throw SysError + sessionCfg_(sessionCfg) { lastSuccessfulUseTime_ = std::chrono::steady_clock::now(); } @@ -282,15 +310,17 @@ public: ::curl_easy_cleanup(easyHandle_); } + const FtpSessionCfg& getSessionCfg() const { return sessionCfg_; } + //set *before* calling any of the subsequent functions; see FtpSessionManager::access() void setContextTimeout(const std::weak_ptr<int>& timeoutSec) { timeoutSec_ = timeoutSec; } //returns server response (header data) std::string perform(const AfsPath& itemPath, bool isDir, curl_ftpmethod pathMethod, - const std::vector<CurlOption>& extraOptions, bool requiresUtf8) //throw SysError + const std::vector<CurlOption>& extraOptions, bool requiresUtf8) //throw SysError, SysErrorPassword, SysErrorFtpProtocol { if (requiresUtf8) //avoid endless recursion - requestUtf8(); //throw SysError + requestUtf8(); //throw SysError, SysErrorFtpProtocol if (!easyHandle_) { @@ -327,15 +357,15 @@ public: // "modern" FTP servers (implementing RFC 2640) have UTF8 enabled by default => pray and hope for the best. // What about ANSI-FTP servers and "Microsoft FTP Service" which requires "OPTS UTF8 ON"? => *psh* // CURLOPT_PREQUOTE to the rescue? Nope, issued long after USER/PASS - const auto& username = utfTo<std::string>(sessionId_.username); - const auto& password = utfTo<std::string>(sessionId_.password); - if (!username.empty()) //else: libcurl handles anonymous login for us (including fake email as password) + const auto& username = utfTo<std::string>(sessionCfg_.deviceId.username); + const auto& password = utfTo<std::string>(sessionCfg_.password); + if (!username.empty()) //else: libcurl will default to CURL_DEFAULT_USER("anonymous") and CURL_DEFAULT_PASSWORD("ftp@example.com") { options.emplace_back(CURLOPT_USERNAME, username.c_str()); - options.emplace_back(CURLOPT_PASSWORD, password.c_str()); + options.emplace_back(CURLOPT_PASSWORD, password.c_str()); //curious: libcurl will *not* default to CURL_DEFAULT_USER when setting password but no username } - options.emplace_back(CURLOPT_PORT, getEffectivePort(sessionId_.port)); + options.emplace_back(CURLOPT_PORT, sessionCfg_.deviceId.port); options.emplace_back(CURLOPT_NOSIGNAL, 1); //thread-safety: https://curl.haxx.se/libcurl/c/threadsafe.html @@ -359,14 +389,14 @@ public: options.emplace_back(CURLOPT_TCP_KEEPALIVE, 1); //=> CURLOPT_TCP_KEEPIDLE (=delay) and CURLOPT_TCP_KEEPINTVL both default to 60 sec - std::optional<SysError> callbackException; + std::optional<SysError> socketException; //libcurl does *not* set FD_CLOEXEC for us! https://github.com/curl/curl/issues/2252 auto onSocketCreate = [&](curl_socket_t curlfd, curlsocktype purpose) { assert(::fcntl(curlfd, F_GETFD) == 0); if (::fcntl(curlfd, F_SETFD, FD_CLOEXEC) == -1) //=> RACE-condition if other thread calls fork/execv before this thread sets FD_CLOEXEC! { - callbackException = SysError(formatSystemError("fcntl(FD_CLOEXEC)", errno)); + socketException = SysError(formatSystemError("fcntl(FD_CLOEXEC)", errno)); return CURL_SOCKOPT_ERROR; } return CURL_SOCKOPT_OK; @@ -462,7 +492,7 @@ public: // => may fail with: "CURLE_PEER_FAILED_VERIFICATION: SSL: no alternative certificate subject name matches target host name 'freefilesync.org'" options.emplace_back(CURLOPT_SSL_VERIFYHOST, 0); #endif - if (sessionId_.useTls) //https://tools.ietf.org/html/rfc4217 + if (sessionCfg_.useTls) //https://tools.ietf.org/html/rfc4217 { options.emplace_back(CURLOPT_USE_SSL, CURLUSESSL_ALL); //require SSL for both control and data options.emplace_back(CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS); //try TLS first, then SSL (currently: CURLFTPAUTH_DEFAULT == CURLFTPAUTH_SSL) @@ -482,11 +512,8 @@ public: //WTF: curl_easy_perform() considers FTP response codes 4XX, 5XX as failure, but for HTTP response codes 4XX are considered success!! CONSISTENCY, people!!! //note: CURLOPT_FAILONERROR(default:off) is only available for HTTP => BUT at least we can prefix FTP commands with * for same effect - if (callbackException) - throw* callbackException; //throw SysError - - //long ftpStatusCode = 0; //optional - ///*const CURLcode rc =*/ ::curl_easy_getinfo(easyHandle_, CURLINFO_RESPONSE_CODE, &ftpStatusCode); + if (socketException) + throw* socketException; //throw SysError //======================================================================================================= if (rcPerf != CURLE_OK) @@ -506,6 +533,14 @@ public: if (nativeErrorCode != 0) errorMsg += (errorMsg.empty() ? L"" : L"\n") + std::wstring(L"Native error code: ") + numberTo<std::wstring>(nativeErrorCode); #endif + if (rcPerf == CURLE_LOGIN_DENIED) + throw SysErrorPassword(formatSystemError("curl_easy_perform", formatCurlStatusCode(rcPerf), errorMsg)); + + long ftpStatusCode = CURLE_OK; //optional + /*const CURLcode rc =*/ ::curl_easy_getinfo(easyHandle_, CURLINFO_RESPONSE_CODE, &ftpStatusCode); + if (ftpStatusCode != CURLE_OK) + throw SysErrorFtpProtocol(formatSystemError("curl_easy_perform", formatCurlStatusCode(rcPerf), errorMsg), ftpStatusCode); + throw SysError(formatSystemError("curl_easy_perform", formatCurlStatusCode(rcPerf), errorMsg)); } @@ -514,7 +549,7 @@ public: } //returns server response (header data) - std::string runSingleFtpCommand(const std::string& ftpCmd, bool requiresUtf8) //throw SysError + std::string runSingleFtpCommand(const std::string& ftpCmd, bool requiresUtf8) //throw SysError, SysErrorFtpProtocol { curl_slist* quote = nullptr; ZEN_ON_SCOPE_EXIT(::curl_slist_free_all(quote)); @@ -524,7 +559,7 @@ public: { {CURLOPT_NOBODY, 1L}, {CURLOPT_QUOTE, quote}, - }, requiresUtf8); //throw SysError + }, requiresUtf8); //throw SysError, SysErrorPassword, SysErrorFtpProtocol } void testConnection() //throw SysError @@ -538,8 +573,8 @@ public: => are there servers supporting neither FEAT nor HELP? only time will tell... ... and it tells! FUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU https://freefilesync.org/forum/viewtopic.php?t=8041 */ - //=> * to the rescue: as long as we get an FTP response - *any* FTP response (including 550) - the connection itself is fine! - const std::string& featBuf = runSingleFtpCommand("*FEAT", false /*requiresUtf8*/); //throw SysError + //=> '*' to the rescue: as long as we get an FTP response - *any* FTP response (including 550) - the connection itself is fine! + const std::string& featBuf = runSingleFtpCommand("*FEAT", false /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol for (const std::string_view& line : splitFtpResponse(featBuf)) if (startsWith(line, "211-") || @@ -573,7 +608,7 @@ public: easyHandle_ = nullptr; } - const std::string& pwdBuf = runSingleFtpCommand("PWD", true /*requiresUtf8*/); //throw SysError + const std::string& pwdBuf = runSingleFtpCommand("PWD", true /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol for (const std::string_view& line : splitFtpResponse(pwdBuf)) if (startsWith(line, "257 ")) @@ -609,7 +644,7 @@ public: if (*currentSocket == binaryEnabledSocket_) return; - runSingleFtpCommand("TYPE I", false /*requiresUtf8*/); //throw SysError + runSingleFtpCommand("TYPE I", false /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol //make sure our binary-enabled session is still there (== libcurl behaves as we expect) std::optional<curl_socket_t> currentSocket = getActiveSocket(); //throw SysError @@ -725,19 +760,22 @@ private: } }); + if (trimCpy(sessionCfg_.deviceId.server).empty()) + throw SysError(_("Server name must not be empty.")); + static_assert(LIBCURL_VERSION_MAJOR > 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 67)); /* 1. CURLFTPMETHOD_NOCWD requires absolute paths to unconditionally skip CWDs: https://github.com/curl/curl/pull/4382 2. CURLFTPMETHOD_SINGLECWD requires absolute paths to skip one needless "CWD entry path": https://github.com/curl/curl/pull/4332 => https://curl.haxx.se/docs/faq.html#How_do_I_list_the_root_dir_of_an => use // because /%2f had bugs (but they should be fixed: https://github.com/curl/curl/pull/4348) */ - std::string path = utfTo<std::string>(Zstring(ftpPrefix) + Zstr("//") + sessionId_.server) + "//" + curlRelPath; + std::string path = utfTo<std::string>(Zstring(ftpPrefix) + Zstr("//") + sessionCfg_.deviceId.server) + "//" + curlRelPath; if (isDir && !endsWith(path, '/')) //curl-FTP needs directory paths to end with a slash path += '/'; return path; } - void requestUtf8() //throw SysError + void requestUtf8() //throw SysError, SysErrorFtpProtocol { //Some RFC-2640-non-compliant servers require UTF8 to be explicitly enabled: https://wiki.filezilla-project.org/Character_Encoding#Conflicting_specification //e.g. this one (Microsoft FTP Service): https://freefilesync.org/forum/viewtopic.php?t=4303 @@ -754,12 +792,12 @@ private: //some servers even require "CLNT" before accepting "OPTS UTF8 ON": https://social.msdn.microsoft.com/Forums/en-US/d602574f-8a69-4d69-b337-52b6081902cf/problem-with-ftpwebrequestopts-utf8-on-501-please-clnt-first if (supportsClnt()) //throw SysError - runSingleFtpCommand("CLNT FreeFileSync", false /*requiresUtf8*/); //throw SysError + runSingleFtpCommand("CLNT FreeFileSync", false /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol //"prefix the command with an asterisk to make libcurl continue even if the command fails" //-> ignore if server does not know this legacy command (but report all *other* issues; else getActiveSocket() below won't return value and hide real error!) //"If an RFC 2640 compliant client sends OPTS UTF-8 ON, it has to use UTF-8 regardless whether OPTS UTF-8 ON succeeds or not. " - runSingleFtpCommand("*OPTS UTF8 ON", false /*requiresUtf8*/); //throw SysError + runSingleFtpCommand("*OPTS UTF8 ON", false /*requiresUtf8*/); //throw SysError, (SysErrorFtpProtocol) //make sure our Unicode-enabled session is still there (== libcurl behaves as we expect) std::optional<curl_socket_t> currentSocket = getActiveSocket(); //throw SysError @@ -791,7 +829,7 @@ private: bool clnt = false; bool utf8 = false; }; - using FeatureList = std::unordered_map<Zstring /*server name*/, std::optional<Features>, StringHashAsciiNoCase, StringEqualAsciiNoCase>; + using FeatureList = std::unordered_map<Zstring /*server name*/, Features, StringHashAsciiNoCase, StringEqualAsciiNoCase>; bool getFeatureSupport(bool Features::* status) //throw SysError { @@ -804,15 +842,20 @@ private: if (!sf) throw SysError(formatSystemError("FtpSession::getFeatureSupport", L"", L"Function call not allowed during init/shutdown.")); - sf->access([&](FeatureList& feat) { featureCache_ = feat[sessionId_.server]; }); + sf->access([&](const FeatureList& featList) + { + auto it = featList.find(sessionCfg_.deviceId.server); + if (it != featList.end()) + featureCache_ = it->second; + }); if (!featureCache_) { //*: ignore error if server does not support/allow FEAT - featureCache_ = parseFeatResponse(runSingleFtpCommand("*FEAT", false /*requiresUtf8*/)); //throw SysError + featureCache_ = parseFeatResponse(runSingleFtpCommand("*FEAT", false /*requiresUtf8*/)); //throw SysError, (SysErrorFtpProtocol) //used by requestUtf8()! => requiresUtf8 = false!!! - sf->access([&](FeatureList& feat) { feat[sessionId_.server] = featureCache_; }); + sf->access([&](FeatureList& feat) { feat.emplace(sessionCfg_.deviceId.server, *featureCache_); }); } } return (*featureCache_).*status; @@ -864,7 +907,7 @@ private: return output; } - const FtpSessionId sessionId_; + const FtpSessionCfg sessionCfg_; CURL* easyHandle_ = nullptr; curl_socket_t utf8RequestedSocket_ = 0; @@ -875,7 +918,7 @@ private: std::optional<Features> featureCache_; std::optional<AfsPath> homePathCached_; - const std::shared_ptr<UniCounterCookie> libsshCurlUnifiedInitCookie_{getLibsshCurlUnifiedInitCookie(globalFtpSessionCount)}; //throw SysError + const std::shared_ptr<UniCounterCookie> libsshCurlUnifiedInitCookie_{getLibsshCurlUnifiedInitCookie(globalFtpSessionCount)}; //throw SysError std::chrono::steady_clock::time_point lastSuccessfulUseTime_; std::weak_ptr<int> timeoutSec_; }; @@ -885,7 +928,7 @@ private: class FtpSessionManager //reuse (healthy) FTP sessions globally { - using IdleFtpSessions = std::vector<std::unique_ptr<FtpSession>>; + struct FtpSessionCache; public: FtpSessionManager() : sessionCleaner_([this] @@ -896,50 +939,104 @@ public: void access(const FtpLogin& login, const std::function<void(FtpSession& session)>& useFtpSession /*throw X*/) //throw SysError, X { - Protected<IdleFtpSessions>& sessionStore = getSessionStore(login); + Protected<FtpSessionCache>& sessionCache = getSessionCache(login); - std::unique_ptr<FtpSession> ftpSession; + std::unique_ptr<FtpSession> ftpSession; //either or + std::optional<FtpSessionCfg> sessionCfg; // - sessionStore.access([&](IdleFtpSessions& sessions) + sessionCache.access([&](FtpSessionCache& cache) { + if (!cache.activeCfg) //AFS::authenticateAccess() not called => authenticate implicitly! + setActiveConfig(cache, login); + //assume "isHealthy()" to avoid hitting server connection limits: (clean up of !isHealthy() after use, idle sessions via worker thread) - if (!sessions.empty()) + if (!cache.idleFtpSessions.empty()) { - ftpSession = std::move(sessions.back ()); - /**/ sessions.pop_back(); + ftpSession = std::move(cache.idleFtpSessions.back ()); + /**/ cache.idleFtpSessions.pop_back(); } + else + sessionCfg = *cache.activeCfg; }); - //create new FTP session outside the lock: 1. don't block other threads 2. non-atomic regarding "sessionStore"! => one session too many is not a problem! + //create new FTP session outside the lock: 1. don't block other threads 2. non-atomic regarding "sessionCache"! => one session too many is not a problem! if (!ftpSession) - ftpSession = std::make_unique<FtpSession>(login); //throw SysError + ftpSession = std::make_unique<FtpSession>(*sessionCfg); //throw SysError const std::shared_ptr<int> timeoutSec = std::make_shared<int>(login.timeoutSec); //context option: valid only for duration of this call! ftpSession->setContextTimeout(timeoutSec); - ZEN_ON_SCOPE_EXIT( + ZEN_ON_SCOPE_EXIT + ( + //*INDENT-OFF* if (ftpSession->isHealthy()) //thread that created the "!isHealthy()" session is responsible for clean up (avoid hitting server connection limits!) - sessionStore.access([&](IdleFtpSessions& sessions) { sessions.push_back(std::move(ftpSession)); }); ); + sessionCache.access([&](FtpSessionCache& cache) + { + if (ftpSession->getSessionCfg() == *cache.activeCfg) //created outside the lock => check *again* + cache.idleFtpSessions.push_back(std::move(ftpSession)); //pass ownership + }); + //*INDENT-ON* + ); useFtpSession(*ftpSession); //throw X } + void setActiveConfig(const FtpLogin& login) + { + getSessionCache(login).access([&](FtpSessionCache& cache) { setActiveConfig(cache, login); }); + } + + void setSessionPassword(const FtpLogin& login, const Zstring& password) + { + getSessionCache(login).access([&](FtpSessionCache& cache) + { + cache.sessionPassword = password; + setActiveConfig(cache, login); + }); + } + private: FtpSessionManager (const FtpSessionManager&) = delete; FtpSessionManager& operator=(const FtpSessionManager&) = delete; - Protected<IdleFtpSessions>& getSessionStore(const FtpSessionId& sessionId) + Protected<FtpSessionCache>& getSessionCache(const FtpDeviceId& deviceId) { - //single global session store per login; life-time bound to globalInstance => never remove a sessionStore!!! - Protected<IdleFtpSessions>* store = nullptr; + //single global session cache per login; life-time bound to globalInstance => never remove a sessionCache!!! + Protected<FtpSessionCache>* sessionCache = nullptr; - globalSessionStore_.access([&](GlobalFtpSessions& sessionsById) + globalSessionCache_.access([&](GlobalFtpSessions& sessionsById) { - store = &sessionsById[sessionId]; //get or create + sessionCache = &sessionsById[deviceId]; //get or create }); - static_assert(std::is_same_v<GlobalFtpSessions, std::map<FtpSessionId, Protected<IdleFtpSessions>>>, "require std::map so that the pointers we return remain stable"); + static_assert(std::is_same_v<GlobalFtpSessions, std::map<FtpDeviceId, Protected<FtpSessionCache>>>, "require std::map so that the pointers we return remain stable"); - return *store; + return *sessionCache; + } + + void setActiveConfig(FtpSessionCache& cache, const FtpLogin& login) + { + if (cache.activeCfg) + assert(std::all_of(cache.idleFtpSessions.begin(), cache.idleFtpSessions.end(), + [&](const std::unique_ptr<FtpSession>& session) { return session->getSessionCfg() == cache.activeCfg; })); + else + assert(cache.idleFtpSessions.empty()); + + const std::optional<FtpSessionCfg> prevCfg = cache.activeCfg; + + cache.activeCfg = + { + .deviceId{login}, + .password = login.password ? *login.password : cache.sessionPassword, + .useTls = login.useTls, + }; + + /* remove incompatible sessions: + - avoid hitting FTP connection limit if some config uses TLS, but not the other: https://freefilesync.org/forum/viewtopic.php?t=8532 + - logically consistent with AFS::compareDevice() + - don't allow different authentication methods, when authenticateAccess() is called *once* per device in getFolderStatusParallel() + - what user expects, e.g. when tesing changed settings in FTP login dialog */ + if (cache.activeCfg != prevCfg) + cache.idleFtpSessions.clear(); //run ~FtpSession *inside* the lock! => avoid hitting server limits! } //run a dedicated clean-up thread => it's unclear when the server let's a connection time out, so we do it preemptively @@ -956,34 +1053,47 @@ private: lastCleanupTime = std::chrono::steady_clock::now(); - std::vector<Protected<IdleFtpSessions>*> sessionStores; //pointers remain stable, thanks to std::unordered_map<> + std::vector<Protected<FtpSessionCache>*> sessionCaches; //pointers remain stable, thanks to std::map<> - globalSessionStore_.access([&](GlobalFtpSessions& sessionsById) + globalSessionCache_.access([&](GlobalFtpSessions& sessionsById) { for (auto& [sessionId, idleSession] : sessionsById) - sessionStores.push_back(&idleSession); + sessionCaches.push_back(&idleSession); }); - for (Protected<IdleFtpSessions>* sessionStore : sessionStores) - for (bool done = false; !done;) - sessionStore->access([&](IdleFtpSessions& sessions) + for (Protected<FtpSessionCache>* sessionCache : sessionCaches) + for (;;) { - for (std::unique_ptr<FtpSession>& sshSession : sessions) - if (!sshSession->isHealthy()) //!isHealthy() sessions are destroyed after use => in this context this means they have been idle for too long - { - sshSession.swap(sessions.back()); - /**/ sessions.pop_back(); //run ~FtpSession *inside* the lock! => avoid hitting server limits! - std::this_thread::yield(); - return; //don't hold lock for too long: delete only one session at a time, then yield... - } - done = true; - }); + bool done = false; + sessionCache->access([&](FtpSessionCache& cache) + { + for (std::unique_ptr<FtpSession>& ftpSession : cache.idleFtpSessions) + if (!ftpSession->isHealthy()) //!isHealthy() sessions are destroyed after use => in this context this means they have been idle for too long + { + ftpSession.swap(cache.idleFtpSessions.back()); + /**/ cache.idleFtpSessions.pop_back(); //run ~FtpSession *inside* the lock! => avoid hitting server limits! + return; //don't hold lock for too long: delete only one session at a time, then yield... + } + done = true; + }); + if (done) + break; + std::this_thread::yield(); //outside the lock + } } } - using GlobalFtpSessions = std::map<FtpSessionId, Protected<IdleFtpSessions>>; + struct FtpSessionCache + { + //invariant: all cached sessions correspond to activeCfg at any time! + std::vector<std::unique_ptr<FtpSession>> idleFtpSessions; //extract *temporarily* from this list during use + std::optional<FtpSessionCfg> activeCfg; + Zstring sessionPassword; + }; + + using GlobalFtpSessions = std::map<FtpDeviceId, Protected<FtpSessionCache>>; + Protected<GlobalFtpSessions> globalSessionCache_; - Protected<GlobalFtpSessions> globalSessionStore_; InterruptibleThread sessionCleaner_; }; @@ -1033,7 +1143,7 @@ FtpItem getFtpSymlinkInfo(const FtpLogin& login, const AfsPath& linkPath) //thro session.ensureBinaryMode(); //throw SysError //...or some server return ASCII size or fail with '550 SIZE not allowed in ASCII mode: https://freefilesync.org/forum/viewtopic.php?t=7669&start=30#p27742 const std::string sizeBuf = session.runSingleFtpCommand("*SIZE " + session.getServerPathInternal(linkPath), - true /*requiresUtf8*/); //throw SysError + true /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol //alternative: use libcurl + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T? => nah, suprise (motherfucker)! libcurl adds needless "REST 0" command! for (const std::string_view& line : splitFtpResponse(sizeBuf)) if (startsWith(line, "213 ")) // 213<space>[rubbish]<file size> according to libcurl @@ -1044,7 +1154,7 @@ FtpItem getFtpSymlinkInfo(const FtpLogin& login, const AfsPath& linkPath) //thro output.fileSize = stringTo<uint64_t>(makeStringView(it.base(), line.end())); mdtmBuf = session.runSingleFtpCommand("MDTM " + session.getServerPathInternal(linkPath), - true /*requiresUtf8*/); //throw SysError + true /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol return; } break; @@ -1090,7 +1200,7 @@ FtpItem getFtpSymlinkInfo(const FtpLogin& login, const AfsPath& linkPath) //thro class FtpDirectoryReader { public: - static std::vector<FtpItem> execute(const FtpLogin& login, const AfsPath& afsDirPath) //throw FileError + static std::vector<FtpItem> execute(const FtpLogin& login, const AfsPath& dirPath) //throw SysError, SysErrorFtpProtocol { std::string rawListing; //get raw FTP directory listing @@ -1103,51 +1213,46 @@ public: }; std::vector<FtpItem> output; - try + + accessFtpSession(login, [&](FtpSession& session) //throw SysError { - accessFtpSession(login, [&](FtpSession& session) //throw SysError + std::vector<CurlOption> options = { - std::vector<CurlOption> options = - { - {CURLOPT_WRITEDATA, &rawListing}, - {CURLOPT_WRITEFUNCTION, onBytesReceived}, - }; - curl_ftpmethod pathMethod = CURLFTPMETHOD_SINGLECWD; + {CURLOPT_WRITEDATA, &rawListing}, + {CURLOPT_WRITEFUNCTION, onBytesReceived}, + }; + curl_ftpmethod pathMethod = CURLFTPMETHOD_SINGLECWD; - if (session.supportsMlsd()) //throw SysError - { - options.emplace_back(CURLOPT_CUSTOMREQUEST, "MLSD"); - - //some FTP servers abuse https://tools.ietf.org/html/rfc3659#section-7.1 - //and process wildcards characters inside the "dirpath"; see http://www.proftpd.org/docs/howto/Globbing.html - // [] matches any character in the character set enclosed in the brackets - // * (not between brackets) matches any string, including the empty string - // ? (not between brackets) matches any single character - // - //of course this "helpfulness" blows up with MLSD + paths that incidentally contain wildcards: https://freefilesync.org/forum/viewtopic.php?t=5575 - const bool pathHasWildcards = //=> globbing is reproducible even with freefilesync.org's FTP! - contains(afterFirst<ZstringView>(afsDirPath.value, Zstr('['), IfNotFoundReturn::none), Zstr(']')) || - contains(afsDirPath.value, Zstr('*')) || - contains(afsDirPath.value, Zstr('?')); - - if (!pathHasWildcards) - pathMethod = CURLFTPMETHOD_NOCWD; //16% faster traversal compared to CURLFTPMETHOD_SINGLECWD (35% faster than CURLFTPMETHOD_MULTICWD) - } - //else: use "LIST" + CURLFTPMETHOD_SINGLECWD - //caveat: let's better not use LIST parameters: https://cr.yp.to/ftp/list.html + if (session.supportsMlsd()) //throw SysError + { + options.emplace_back(CURLOPT_CUSTOMREQUEST, "MLSD"); + + //some FTP servers abuse https://tools.ietf.org/html/rfc3659#section-7.1 + //and process wildcards characters inside the "dirpath"; see http://www.proftpd.org/docs/howto/Globbing.html + // [] matches any character in the character set enclosed in the brackets + // * (not between brackets) matches any string, including the empty string + // ? (not between brackets) matches any single character + // + //of course this "helpfulness" blows up with MLSD + paths that incidentally contain wildcards: https://freefilesync.org/forum/viewtopic.php?t=5575 + const bool pathHasWildcards = //=> globbing is reproducible even with freefilesync.org's FTP! + contains(afterFirst<ZstringView>(dirPath.value, Zstr('['), IfNotFoundReturn::none), Zstr(']')) || + contains(dirPath.value, Zstr('*')) || + contains(dirPath.value, Zstr('?')); + + if (!pathHasWildcards) + pathMethod = CURLFTPMETHOD_NOCWD; //16% faster traversal compared to CURLFTPMETHOD_SINGLECWD (35% faster than CURLFTPMETHOD_MULTICWD) + } + //else: use "LIST" + CURLFTPMETHOD_SINGLECWD + //caveat: let's better not use LIST parameters: https://cr.yp.to/ftp/list.html - session.perform(afsDirPath, true /*isDir*/, pathMethod, options, true /*requiresUtf8*/); //throw SysError + session.perform(dirPath, true /*isDir*/, pathMethod, options, true /*requiresUtf8*/); //throw SysError, SysErrorPassword, SysErrorFtpProtocol + + if (session.supportsMlsd()) //throw SysError + output = parseMlsd(rawListing, session); //throw SysError + else + output = parseUnknown(rawListing, session); //throw SysError + }); - if (session.supportsMlsd()) //throw SysError - output = parseMlsd(rawListing, session); //throw SysError - else - output = parseUnknown(rawListing, session); //throw SysError - }); - } - catch (const SysError& e) - { - throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(getCurlDisplayPath(login, afsDirPath))), e.toString()); - } return output; } @@ -1628,7 +1733,17 @@ private: void traverseWithException(const AfsPath& dirPath, AFS::TraverserCallback& cb) //throw FileError, X { - for (const FtpItem& item : FtpDirectoryReader::execute(login_, dirPath)) //throw FileError + std::vector<FtpItem> items; + try + { + items = FtpDirectoryReader::execute(login_, dirPath); //throw SysError, SysErrorFtpProtocol + } + catch (const SysError& e) + { + throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(getCurlDisplayPath(login_, dirPath))), e.toString()); + } + + for (const FtpItem& item : items) { const AfsPath itemPath(appendPath(dirPath.value, item.itemName)); @@ -1722,7 +1837,7 @@ void ftpFileDownload(const FtpLogin& login, const AfsPath& afsFilePath, //throw //{CURLOPT_BUFFERSIZE, 256 * 1024} -> defaults is 16 kB which seems to correspond to SSL packet size //=> setting larget buffers size does nothing (recv still returns only 16 kB) - }, true /*requiresUtf8*/); //throw SysError + }, true /*requiresUtf8*/); //throw SysError, SysErrorPassword, SysErrorFtpProtocol }); } catch (const SysError& e) @@ -1793,7 +1908,7 @@ void ftpFileUpload(const FtpLogin& login, const AfsPath& afsFilePath, //{CURLOPT_PREQUOTE, quote}, //{CURLOPT_POSTQUOTE, quote}, - }, true /*requiresUtf8*/); //throw SysError + }, true /*requiresUtf8*/); //throw SysError, SysErrorPassword, SysErrorFtpProtocol }); } catch (const SysError& e) @@ -1876,12 +1991,12 @@ struct OutputStreamFtp : public AFS::OutputStreamImpl filePath_(filePath), modTime_(modTime) { - std::promise<void> pUploadDone; - futUploadDone_ = pUploadDone.get_future(); + std::promise<void> promUploadDone; + futUploadDone_ = promUploadDone.get_future(); worker_ = InterruptibleThread([login, filePath, asyncStreamIn = this->asyncStreamOut_, - pUploadDone = std::move(pUploadDone)]() mutable + pUploadDone = std::move(promUploadDone)]() mutable { setCurrentThreadName(Zstr("Ostream ") + utfTo<Zstring>(getCurlDisplayPath(login, filePath))); try @@ -1975,7 +2090,7 @@ private: throw SysError(L"Server does not support the MFMT command."); session.runSingleFtpCommand("MFMT " + isoTime + ' ' + session.getServerPathInternal(filePath_), - true /*requiresUtf8*/); //throw SysError + true /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol //not relevant for OutputStreamFtp, but: does MFMT follow symlinks? for Linux FTP server (using utime) it does }); } @@ -2018,80 +2133,118 @@ private: const FtpLogin& lhs = login_; const FtpLogin& rhs = static_cast<const FtpFileSystem&>(afsRhs).login_; - //exactly the type of case insensitive comparison we need for server names! - if (const std::weak_ordering cmp = compareAsciiNoCase(lhs.server, rhs.server); //https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfow#IDNs - cmp != std::weak_ordering::equivalent) - return cmp; - - //port DOES create a *different* data source! https://freefilesync.org/forum/viewtopic.php?t=9047 - const int portLhs = getEffectivePort(lhs.port); - const int portRhs = getEffectivePort(rhs.port); - - //username: usually creates different folder view for FTP - return std::tie(portLhs, lhs.username) <=> //username: case sensitive! - std::tie(portRhs, rhs.username); + return FtpDeviceId(lhs) <=> FtpDeviceId(rhs); } //---------------------------------------------------------------------------------------------------------------- + ItemType getItemType(const AfsPath& itemPath) const override //throw FileError { - //don't use MLST: broken for Pure-FTPd: https://freefilesync.org/forum/viewtopic.php?t=4287 - - const std::optional<AfsPath> parentAfsPath = getParentPath(itemPath); - if (!parentAfsPath) //device root => do a quick access tests to see if the server responds at all! - try + try + { + const std::optional<AfsPath> parentPath = getParentPath(itemPath); + if (!parentPath) //device root => quick access test { - accessFtpSession(login_, [&](FtpSession& session) //throw SysError - { - session.testConnection(); //throw SysError - }); + try { accessFtpSession(login_, [](FtpSession& session) { session.testConnection(); }); /*throw SysError*/ } + catch (const SysError& e) { throw SysError(replaceCpy(_("Unable to connect to %x."), L"%x", fmtPath(login_.server)) + L'\n' + e.toString()); } + return ItemType::folder; } - catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(getCurlDisplayPath(login_, itemPath))), e.toString()); } - const Zstring itemName = getItemName(itemPath); - assert(!itemName.empty()); - try - { + const std::vector<FtpItem> items = [&] + { + try + { + //don't use MLST: broken for Pure-FTPd: https://freefilesync.org/forum/viewtopic.php?t=4287 + return FtpDirectoryReader::execute(login_, *parentPath); //throw SysError, SysErrorFtpProtocol + } + catch (const SysError& e) //add context: error might be folder-specific + { throw SysError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(getItemName(*parentPath))) + L'\n' + e.toString()); } + }(); + + const Zstring itemName = getItemName(itemPath); + assert(!itemName.empty()); //is the underlying file system case-sensitive? we don't know => assume "case-sensitive" - //=> all path parts (except the base folder part!) can be expected to have the right case anyway after traversal - traverseFolderFlat(*parentAfsPath, //throw FileError - [&](const FileInfo& fi) { if (fi.itemName == itemName) throw ItemType::file; }, - [&](const FolderInfo& fi) { if (fi.itemName == itemName) throw ItemType::folder; }, - [&](const SymlinkInfo& si) { if (si.itemName == itemName) throw ItemType::symlink; }); - } - catch (const ItemType& type) { return type; } //yes, exceptions for control-flow are bad design... but, but... + //all path components (except the base folder part!) can be expected to have the right case anyway after traversal + for (const FtpItem& item : items) + if (item.itemName == itemName) + return item.type; - throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(getDisplayPath(itemPath))), L"File not found."); + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(itemName))); + } + catch (const SysError& e) + { + throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(getDisplayPath(itemPath))), e.toString()); + } } - std::optional<ItemType> itemStillExists(const AfsPath& itemPath) const override //throw FileError + std::variant<ItemType, AfsPath /*last existing parent path*/> getItemTypeIfExistsImpl(const AfsPath& itemPath) const //throw SysError { - const std::optional<AfsPath> parentAfsPath = getParentPath(itemPath); - if (!parentAfsPath) //device root - return getItemType(itemPath); //throw FileError; do a simple access test + const std::optional<AfsPath> parentPath = getParentPath(itemPath); + if (!parentPath) //device root => quick access test + { + try { accessFtpSession(login_, [](FtpSession& session) { session.testConnection(); }); /*throw SysError*/ } + catch (const SysError& e) { throw SysError(replaceCpy(_("Unable to connect to %x."), L"%x", fmtPath(login_.server)) + L'\n' + e.toString()); } + + return ItemType::folder; + } + std::optional<SysErrorFtpProtocol> lastFtpError; try { - const Zstring itemName = getItemName(itemPath); - assert(!itemName.empty()); + try + { + const Zstring itemName = getItemName(itemPath); + assert(!itemName.empty()); + + for (const FtpItem& item : FtpDirectoryReader::execute(login_, *parentPath)) //throw SysError, SysErrorFtpProtocol + if (item.itemName == itemName) //case-sensitive comparison! itemPath must be normalized! + return item.type; - traverseFolderFlat(*parentAfsPath, //throw FileError - [&](const FileInfo& fi) { if (fi.itemName == itemName) throw ItemType::file; }, - [&](const FolderInfo& fi) { if (fi.itemName == itemName) throw ItemType::folder; }, - [&](const SymlinkInfo& si) { if (si.itemName == itemName) throw ItemType::symlink; }); + return *parentPath; + } + catch (const SysErrorFtpProtocol& e) + { + //let's dig deeper, but *only* for SysErrorFtpProtocol, not for general connection issues + //+ check if FTP error code sounds like "not existing" + if (e.ftpErrorCode == 550) //FTP 550 No such file or directory + //501? "pathname that exists but is not a directory to a MLSD command generates a 501 reply": https://www.rfc-editor.org/rfc/rfc3659 + //=> really? cannot reproduce, getting: "550 '/filename.txt' is not a directory" or "550 Can't check for file existence" + lastFtpError = e; //-> get out of catch clause + else + throw; + } } - catch (const ItemType& type) { return type; } //yes, exceptions for control-flow are bad design... but, but... - catch (FileError&) + catch (const SysError& e) //add context: error might be folder-specific + { throw SysError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(getItemName(*parentPath))) + L'\n' + e.toString()); } + + //---------------------------------------------------------------- + const std::variant<ItemType, AfsPath /*last existing parent path*/> parentTypeOrPath = getItemTypeIfExistsImpl(*parentPath); //throw SysError + + if (const ItemType* parentType = std::get_if<ItemType>(&parentTypeOrPath)) { - const std::optional<ItemType> parentType = itemStillExists(*parentAfsPath); //throw FileError - if (parentType && *parentType != ItemType::file) //obscure, but possible (and not an error) - throw; //parent path existing, so traversal should not have failed! + if (*parentType == ItemType::file /*obscure, but possible*/) + throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(getItemName(*parentPath)))); + + throw* lastFtpError; //throw SysError; parent path existing, so traversal should not have failed! + } + else + return parentTypeOrPath; + } + + std::variant<ItemType, AfsPath /*last existing parent path*/> getItemTypeIfExists(const AfsPath& itemPath) const override //throw FileError + { + try + { + return getItemTypeIfExistsImpl(itemPath); //throw SysError + } + catch (const SysError& e) + { + throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(getDisplayPath(itemPath))), e.toString()); } - return {}; } - //---------------------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------------------- //already existing: fail //=> FTP will (most likely) fail and give a clear error message: // freefilesync.org: "550 Can't create directory: File exists" @@ -2103,8 +2256,7 @@ private: { accessFtpSession(login_, [&](FtpSession& session) //throw SysError { - session.runSingleFtpCommand("MKD " + session.getServerPathInternal(folderPath), - true /*requiresUtf8*/); //throw SysError + session.runSingleFtpCommand("MKD " + session.getServerPathInternal(folderPath), true /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol }); } catch (const SysError& e) @@ -2119,8 +2271,7 @@ private: { accessFtpSession(login_, [&](FtpSession& session) //throw SysError { - session.runSingleFtpCommand("DELE " + session.getServerPathInternal(filePath), - true /*requiresUtf8*/); //throw SysError + session.runSingleFtpCommand("DELE " + session.getServerPathInternal(filePath), true /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol }); } catch (const SysError& e) @@ -2131,39 +2282,31 @@ private: void removeSymlinkPlain(const AfsPath& linkPath) const override //throw FileError { - this->removeFilePlain(linkPath); //throw FileError - //works fine for Linux hosts, but what about Windows-hosted FTP??? Distinguish DELE/RMD? - //Windows test, FileZilla Server and Windows IIS FTP: all symlinks are reported as regular folders + try + { + accessFtpSession(login_, [&](FtpSession& session) //throw SysError + { + //works fine for Linux hosts, but what about Windows-hosted FTP??? Distinguish DELE/RMD? + //Windows test, FileZilla Server and Windows IIS FTP: all symlinks are reported as regular folders + session.runSingleFtpCommand("DELE " + session.getServerPathInternal(linkPath), true /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol + }); + } + catch (const SysError& e) + { + throw FileError(replaceCpy(_("Cannot delete symbolic link %x."), L"%x", fmtPath(getDisplayPath(linkPath))), e.toString()); + } } void removeFolderPlain(const AfsPath& folderPath) const override //throw FileError { try { - std::optional<SysError> delError; - accessFtpSession(login_, [&](FtpSession& session) //throw SysError { - try - { - session.runSingleFtpCommand("RMD " + session.getServerPathInternal(folderPath), - true /*requiresUtf8*/); //throw SysError - } - catch (const SysError& e) { delError = e; } + //Windows server: FileZilla Server and Windows IIS FTP: all symlinks are reported as regular folders + //Linux server (freefilesync.org): RMD will fail for symlinks! + session.runSingleFtpCommand("RMD " + session.getServerPathInternal(folderPath), true /*requiresUtf8*/); //throw SysError, SysErrorFtpProtocol }); - - if (delError) - { - //Windows test, FileZilla Server and Windows IIS FTP: all symlinks are reported as regular folders - //tested freefilesync.org: RMD will fail for symlinks! - bool symlinkExists = false; - try { symlinkExists = getItemType(folderPath) == ItemType::symlink; } /*throw FileError*/ catch (FileError&) {} //previous exception is more relevant - - if (symlinkExists) - return removeSymlinkPlain(folderPath); //throw FileError - else - throw* delError; - } } catch (const SysError& e) { @@ -2172,11 +2315,12 @@ private: } void removeFolderIfExistsRecursion(const AfsPath& folderPath, //throw FileError - const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, //optional - const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion) const override //one call for each object! + const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, + const std::function<void(const std::wstring& displayPath)>& onBeforeSymlinkDeletion/*throw X*/, + const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion /*throw X*/) const override { //default implementation: folder traversal - AFS::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeFolderDeletion); //throw FileError, X + AFS::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeSymlinkDeletion, onBeforeFolderDeletion); //throw FileError, X } //---------------------------------------------------------------------------------------------------------------- @@ -2278,7 +2422,7 @@ private: { {CURLOPT_NOBODY, 1L}, {CURLOPT_QUOTE, quote}, - }, true /*requiresUtf8*/); //throw SysError + }, true /*requiresUtf8*/); //throw SysError, SysErrorPassword, SysErrorFtpProtocol }); } catch (const SysError& e) @@ -2294,9 +2438,60 @@ private: FileIconHolder getFileIcon (const AfsPath& filePath, int pixelSize) const override { return {}; } //throw FileError; optional return value ImageHolder getThumbnailImage(const AfsPath& filePath, int pixelSize) const override { return {}; } //throw FileError; optional return value - void authenticateAccess(bool allowUserInteraction) const override {} //throw FileError + void authenticateAccess(const RequestPasswordFun& requestPassword /*throw X*/) const override //throw FileError, X + { + auto connectServer = [&] //throw SysError, SysErrorPassword + { + accessFtpSession(login_, [](FtpSession& session) //connect with FTP server, *unless* already connected (in which case *nothing* is sent) + { + session.perform(AfsPath(), true /*isDir*/, CURLFTPMETHOD_NOCWD, + {{CURLOPT_NOBODY, 1L}, {CURLOPT_SERVER_RESPONSE_TIMEOUT, 0}}, false /*requiresUtf8*/); + //caveat: connection phase only, so disable CURLOPT_SERVER_RESPONSE_TIMEOUT, or next access may fail with CURLE_OPERATION_TIMEDOUT! + }); //throw SysError, SysErrorPassword, SysErrorFtpProtocol + }; + + try + { + const std::shared_ptr<FtpSessionManager> mgr = globalFtpSessionManager.get(); + if (!mgr) + throw SysError(formatSystemError("getSessionPassword", L"", L"Function call not allowed during init/shutdown.")); + + mgr->setActiveConfig(login_); + + if (!login_.password) + { + try //1. test for connection error *before* bothering user to enter a password + { + connectServer(); //throw SysError, SysErrorPassword + return; //got new FtpSession (connected in constructor) or already connected session from cache + } + catch (SysErrorPassword&) {} + + if (!requestPassword) + throw SysError(_("Password prompt not permitted by current settings.")); + + std::wstring lastErrorMsg; + for (;;) + { + //2. request (new) password + std::wstring msg = replaceCpy(_("Please enter your password to connect to %x"), L"%x", fmtPath(getDisplayPath(AfsPath()))); + if (lastErrorMsg.empty()) + msg += L"\n" + _("The password will only be remembered until FreeFileSync is closed."); - int getAccessTimeout() const override { return login_.timeoutSec; } //returns "0" if no timeout in force + const Zstring password = requestPassword(msg, lastErrorMsg); //throw X + mgr->setSessionPassword(login_, password); + + try //3. test access: + { + connectServer(); //throw SysError, SysErrorPassword + return; + } + catch (const SysErrorPassword& e) { lastErrorMsg = e.toString(); } + } + } + } + catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to connect to %x."), L"%x", fmtPath(getDisplayPath(AfsPath()))), e.toString()); } + } bool hasNativeTransactionalCopy() const override { return false; } //---------------------------------------------------------------------------------------------------------------- @@ -2328,8 +2523,8 @@ Zstring concatenateFtpFolderPathPhrase(const FtpLogin& login, const AfsPath& fol username = encodeFtpUsername(login.username) + Zstr("@"); Zstring port; - if (login.port > 0) - port = Zstr(':') + numberTo<Zstring>(login.port); + if (login.portCfg > 0) + port = Zstr(':') + numberTo<Zstring>(login.portCfg); Zstring relPath = getServerRelPath(folderPath); if (relPath == Zstr("/")) @@ -2342,8 +2537,13 @@ Zstring concatenateFtpFolderPathPhrase(const FtpLogin& login, const AfsPath& fol if (login.useTls) options += Zstr("|ssl"); - if (!login.password.empty()) //password always last => visually truncated by folder input field - options += Zstr("|pass64=") + encodePasswordBase64(login.password); + if (login.password) + { + if (!login.password->empty()) //password always last => visually truncated by folder input field + options += Zstr("|pass64=") + encodePasswordBase64(*login.password); + } + else + options += Zstr("|pwprompt"); return Zstring(ftpPrefix) + Zstr("//") + username + login.server + port + relPath + options; } @@ -2448,7 +2648,7 @@ AbstractPath fff::createItemPathFtp(const Zstring& itemPathPhrase) //noexcept login.server = Zstring(beforeLast(serverPort, Zstr(':'), IfNotFoundReturn::all)); const ZstringView port = afterLast(serverPort, Zstr(':'), IfNotFoundReturn::none); - login.port = stringTo<int>(port); //0 if empty + login.portCfg = stringTo<int>(port); //0 if empty split(options, Zstr('|'), [&](const ZstringView optPhrase) { @@ -2460,6 +2660,8 @@ AbstractPath fff::createItemPathFtp(const Zstring& itemPathPhrase) //noexcept login.useTls = true; else if (startsWith(optPhrase, Zstr("pass64="))) login.password = decodePasswordBase64(afterFirst(optPhrase, Zstr("="), IfNotFoundReturn::none)); + else if (optPhrase == Zstr("pwprompt")) + login.password = std::nullopt; else assert(false); } diff --git a/FreeFileSync/Source/afs/ftp.h b/FreeFileSync/Source/afs/ftp.h index 9660bdf6..f8df01f1 100644 --- a/FreeFileSync/Source/afs/ftp.h +++ b/FreeFileSync/Source/afs/ftp.h @@ -20,21 +20,17 @@ void ftpTeardown(); //------------------------------------------------------- -//use all configuration data that *defines* an SFTP session as key when buffering sessions! This is what user expects, e.g. when changing settings in FTP login dialog -struct FtpSessionId +const int DEFAULT_PORT_FTP = 21; //TLS enabled? => same for explicit FTP, but *implicit* FTP uses port 990 + +struct FtpLogin { Zstring server; - int port = 0; // > 0 if set + int portCfg = 0; //use if > 0, DEFAULT_PORT_FTP otherwise Zstring username; - Zstring password; + std::optional<Zstring> password = Zstr(""); //none given => prompt during AFS::authenticateAccess() bool useTls = false; -}; -const int DEFAULT_PORT_FTP = 21; //TLS enabled? => same for explicit FTP, but *implicit* FTP uses port 990 - -struct FtpLogin : FtpSessionId -{ //other settings not specific to FTP session: - int timeoutSec = 15; + int timeoutSec = 10; }; AfsDevice condenseToFtpDevice(const FtpLogin& login); //noexcept; potentially messy user input FtpLogin extractFtpLogin(const AfsDevice& afsDevice); //noexcept diff --git a/FreeFileSync/Source/afs/ftp_common.h b/FreeFileSync/Source/afs/ftp_common.h index 211844c0..b2ff0ae3 100644 --- a/FreeFileSync/Source/afs/ftp_common.h +++ b/FreeFileSync/Source/afs/ftp_common.h @@ -29,7 +29,7 @@ Zstring decodePasswordBase64(const ZstringView pass) } -//according to the SFTP path syntax, the user name must not contain raw @ and : +//according to the SFTP path syntax, the username must not contain raw @ and : //-> we don't need a full urlencode! inline Zstring encodeFtpUsername(Zstring name) diff --git a/FreeFileSync/Source/afs/gdrive.cpp b/FreeFileSync/Source/afs/gdrive.cpp index ae89f367..33849de9 100644 --- a/FreeFileSync/Source/afs/gdrive.cpp +++ b/FreeFileSync/Source/afs/gdrive.cpp @@ -97,18 +97,23 @@ std::string getGdriveClientSecret() { return ""; } // struct HttpSessionId { - /*explicit*/ HttpSessionId(const Zstring& serverName) : + explicit HttpSessionId(const Zstring& serverName) : server(serverName) {} Zstring server; }; -std::weak_ordering operator<=>(const HttpSessionId& lhs, const HttpSessionId& rhs) -{ - //exactly the type of case insensitive comparison we need for server names! - return compareAsciiNoCase(lhs.server, rhs.server); //https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfow#IDNs + +inline +bool operator==(const HttpSessionId& lhs, const HttpSessionId& rhs) { return equalAsciiNoCase(lhs.server, rhs.server); } } +//exactly the type of case insensitive comparison we need for server names! +//https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfow#IDNs +template<> struct std::hash<HttpSessionId> { size_t operator()(const HttpSessionId& sessionId) const { return StringHashAsciiNoCase()(sessionId.server); } }; + +namespace +{ Zstring concatenateGdriveFolderPathPhrase(const GdrivePath& gdrivePath); //noexcept @@ -195,13 +200,13 @@ public: runGlobalSessionCleanUp(); //throw ThreadStopRequest }) {} - void access(const HttpSessionId& login, const std::function<void(HttpSession& session)>& useHttpSession /*throw X*/) //throw SysError, X + void access(const HttpSessionId& sessionId, const std::function<void(HttpSession& session)>& useHttpSession /*throw X*/) //throw SysError, X { - Protected<HttpSessionManager::IdleHttpSessions>& sessionStore = getSessionStore(login); + Protected<HttpSessionManager::HttpSessionCache>& sessionCache = getSessionCache(sessionId); std::unique_ptr<HttpInitSession> httpSession; - sessionStore.access([&](HttpSessionManager::IdleHttpSessions& sessions) + sessionCache.access([&](HttpSessionManager::HttpSessionCache& sessions) { //assume "isHealthy()" to avoid hitting server connection limits: (clean up of !isHealthy() after use, idle sessions via worker thread) if (!sessions.empty()) @@ -211,13 +216,13 @@ public: } }); - //create new HTTP session outside the lock: 1. don't block other threads 2. non-atomic regarding "sessionStore"! => one session too many is not a problem! + //create new HTTP session outside the lock: 1. don't block other threads 2. non-atomic regarding "sessionCache"! => one session too many is not a problem! if (!httpSession) - httpSession = std::make_unique<HttpInitSession>(login.server, caCertFilePath_); //throw SysError + httpSession = std::make_unique<HttpInitSession>(sessionId.server, caCertFilePath_); //throw SysError ZEN_ON_SCOPE_EXIT( if (isHealthy(httpSession->session)) //thread that created the "!isHealthy()" session is responsible for clean up (avoid hitting server connection limits!) - sessionStore.access([&](HttpSessionManager::IdleHttpSessions& sessions) { sessions.push_back(std::move(httpSession)); }); ); + sessionCache.access([&](HttpSessionManager::HttpSessionCache& sessions) { sessions.push_back(std::move(httpSession)); }); ); useHttpSession(httpSession->session); //throw X } @@ -237,20 +242,20 @@ private: }; static bool isHealthy(const HttpSession& s) { return std::chrono::steady_clock::now() - s.getLastUseTime() <= HTTP_SESSION_MAX_IDLE_TIME; } - using IdleHttpSessions = std::vector<std::unique_ptr<HttpInitSession>>; + using HttpSessionCache = std::vector<std::unique_ptr<HttpInitSession>>; - Protected<IdleHttpSessions>& getSessionStore(const HttpSessionId& login) + Protected<HttpSessionCache>& getSessionCache(const HttpSessionId& sessionId) { - //single global session store per login; life-time bound to globalInstance => never remove a sessionStore!!! - Protected<IdleHttpSessions>* store = nullptr; + //single global session store per sessionId; life-time bound to globalInstance => never remove a sessionCache!!! + Protected<HttpSessionCache>* sessionCache = nullptr; - globalSessionStore_.access([&](GlobalHttpSessions& sessionsById) + globalSessionCache_.access([&](GlobalHttpSessions& sessionsById) { - store = &sessionsById[login]; //get or create + sessionCache = &sessionsById[sessionId]; //get or create }); - static_assert(std::is_same_v<GlobalHttpSessions, std::map<HttpSessionId, Protected<IdleHttpSessions>>>, "require std::map so that the pointers we return remain stable"); + static_assert(std::is_same_v<GlobalHttpSessions, std::unordered_map<HttpSessionId, Protected<HttpSessionCache>>>, "require std::unordered_map so that the pointers we return remain stable"); - return *store; + return *sessionCache; } //run a dedicated clean-up thread => it's unclear when the server let's a connection time out, so we do it preemptively @@ -267,34 +272,39 @@ private: lastCleanupTime = std::chrono::steady_clock::now(); - std::vector<Protected<IdleHttpSessions>*> sessionStores; //pointers remain stable, thanks to std::unordered_map<> + std::vector<Protected<HttpSessionCache>*> sessionCaches; //pointers remain stable, thanks to std::unordered_map<> - globalSessionStore_.access([&](GlobalHttpSessions& sessionsById) + globalSessionCache_.access([&](GlobalHttpSessions& sessionsByCfg) { - for (auto& [sessionId, idleSession] : sessionsById) - sessionStores.push_back(&idleSession); + for (auto& [sessionCfg, idleSession] : sessionsByCfg) + sessionCaches.push_back(&idleSession); }); - for (Protected<IdleHttpSessions>* sessionStore : sessionStores) - for (bool done = false; !done;) - sessionStore->access([&](IdleHttpSessions& sessions) + for (Protected<HttpSessionCache>* sessionCache : sessionCaches) + for (;;) { - for (std::unique_ptr<HttpInitSession>& sshSession : sessions) - if (!isHealthy(sshSession->session)) //!isHealthy() sessions are destroyed after use => in this context this means they have been idle for too long - { - sshSession.swap(sessions.back()); - /**/ sessions.pop_back(); //run ~HttpSession *inside* the lock! => avoid hitting server limits! - std::this_thread::yield(); - return; //don't hold lock for too long: delete only one session at a time, then yield... - } - done = true; - }); + bool done = false; + sessionCache->access([&](HttpSessionCache& sessions) + { + for (std::unique_ptr<HttpInitSession>& sshSession : sessions) + if (!isHealthy(sshSession->session)) //!isHealthy() sessions are destroyed after use => in this context this means they have been idle for too long + { + sshSession.swap(sessions.back()); + /**/ sessions.pop_back(); //run ~HttpSession *inside* the lock! => avoid hitting server limits! + return; //don't hold lock for too long: delete only one session at a time, then yield... + } + done = true; + }); + if (done) + break; + std::this_thread::yield(); + } } } - using GlobalHttpSessions = std::map<HttpSessionId, Protected<IdleHttpSessions>>; + using GlobalHttpSessions = std::unordered_map<HttpSessionId, Protected<HttpSessionCache>>; - Protected<GlobalHttpSessions> globalSessionStore_; + Protected<GlobalHttpSessions> globalSessionCache_; const Zstring caCertFilePath_; InterruptibleThread sessionCleaner_; }; @@ -448,15 +458,15 @@ GdriveAccessInfo gdriveExchangeAuthCode(const GdriveAuthCode& authCode, int time GdriveAccessInfo gdriveAuthorizeAccess(const std::string& gdriveLoginHint, const std::function<void()>& updateGui /*throw X*/, int timeoutSec) //throw SysError, X { //spin up a web server to wait for the HTTP GET after Google authentication - const ::addrinfo hints + const addrinfo hints { - .ai_flags = AI_PASSIVE //the returned socket addresses will be suitable for bind(2)ing a socket that will accept(2) connections. - | AI_ADDRCONFIG //no such issue on Linux: https://bugs.chromium.org/p/chromium/issues/detail?id=5234 - , - .ai_family = AF_INET, //make sure our server is reached by IPv4 127.0.0.1, not IPv6 [::1] - .ai_socktype = SOCK_STREAM, //we *do* care about this one! + .ai_flags = + AI_ADDRCONFIG | //no such issue on Linux: https://bugs.chromium.org/p/chromium/issues/detail?id=5234 + AI_PASSIVE, //the returned socket addresses will be suitable for bind(2)ing a socket that will accept(2) connections. + .ai_family = AF_INET, //make sure our server is reached by IPv4 127.0.0.1, not IPv6 [::1] + .ai_socktype = SOCK_STREAM, //we *do* care about this one! }; - ::addrinfo* servinfo = nullptr; + addrinfo* servinfo = nullptr; ZEN_ON_SCOPE_EXIT(if (servinfo) ::freeaddrinfo(servinfo)); //ServiceName == "0" => open the next best free port @@ -471,10 +481,10 @@ GdriveAccessInfo gdriveAuthorizeAccess(const std::string& gdriveLoginHint, const const auto getBoundSocket = [](const auto& /*::addrinfo*/ ai) { - SocketType testSocket = ::socket(ai.ai_family, //int socket_family - SOCK_CLOEXEC | - ai.ai_socktype, //int socket_type - ai.ai_protocol); //int protocol + SocketType testSocket = ::socket(ai.ai_family, //int socket_family + SOCK_CLOEXEC | + ai.ai_socktype, //int socket_type + ai.ai_protocol); //int protocol if (testSocket == invalidSocket) THROW_LAST_SYS_ERROR_WSA("socket"); ZEN_ON_SCOPE_FAIL(closeSocket(testSocket)); @@ -553,11 +563,11 @@ GdriveAccessInfo gdriveAuthorizeAccess(const std::string& gdriveLoginHint, const if (updateGui) updateGui(); //throw X const int waitTimeMs = 100; - pollfd fds[] = {{socket, POLLIN}}; + pollfd fds[] = {{socket, POLLIN}}; const char* functionName = "poll"; - if (const int rv = ::poll(fds, std::size(fds), waitTimeMs); //int timeout - rv < 0) + const int rv = ::poll(fds, std::size(fds), waitTimeMs); //int timeout + if (rv < 0) THROW_LAST_SYS_ERROR_WSA(functionName); else if (rv != 0) break; @@ -1970,8 +1980,7 @@ public: if (ps.relPath.empty()) return ps.existingItemId; - const AfsPath itemPathMissingChild(appendPath(ps.existingPath.value, ps.relPath.front())); - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", fmtPath(getShortDisplayPath(itemPathMissingChild)))); + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(ps.relPath.front()))); } std::pair<std::string /*itemId*/, GdriveItemDetails> getFileAttributes(const std::string& locationRootId, const AfsPath& itemPath, bool followLeafShortcut) //throw SysError @@ -1992,7 +2001,7 @@ public: it != itemDetails_.end()) return *it; - //itemId was found! => (must either be a location root) or buffered in itemDetails_ + //itemId was already found! => (must either be a location root) or buffered in itemDetails_ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ':' + numberTo<std::string>(__LINE__)); } @@ -2129,11 +2138,6 @@ private: friend class GdriveDrivesBuffer; - std::wstring getShortDisplayPath(const AfsPath& itemPath) const - { - return utfTo<std::wstring>(FILE_NAME_SEPARATOR + itemPath.value); //sufficient info for SysError + we don't have a locationName anyway - } - void notifyItemUpdated(const FileStateDelta& stateDelta, const std::string& itemId, const GdriveItemDetails* details) { if (!stateDelta.changedIds->contains(itemId)) //no conflicting changes in the meantime? @@ -2195,9 +2199,7 @@ private: if (equalNativePath(itChild->second.itemName, relPath.front())) { if (itFound != itemDetails_.end()) - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", - fmtPath(getShortDisplayPath(AfsPath(appendPath(folderPath.value, relPath.front()))))) + L' ' + - replaceCpy(_("The name %x is used by more than one item in the folder."), L"%x", fmtPath(relPath.front()))); + throw SysError(replaceCpy(_("The name %x is used by more than one item in the folder."), L"%x", fmtPath(relPath.front()))); itFound = itChild; } @@ -2233,8 +2235,8 @@ private: switch (childDetails.type) { - case GdriveItemType::file: //parent/file/child-rel-path... => obscure, but possible (and not an error) - return {childId, childDetails.type, childItemPath, childRelPath}; + case GdriveItemType::file: //parent/file/child-rel-path... => obscure, but possible + throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(AFS::getItemName(childItemPath)))); case GdriveItemType::folder: return getPathStatusSub(childId, childItemPath, childRelPath, followLeafShortcut); //throw SysError @@ -2242,16 +2244,14 @@ private: case GdriveItemType::shortcut: switch (getItemDetailsBuffered(childDetails.targetId).type) { - case GdriveItemType::file: //parent/file-symlink/child-rel-path... => obscure, but possible (and not an error) - return {childDetails.targetId, GdriveItemType::file, childItemPath, childRelPath}; //resolve symlinks if in the *middle* of a path! + case GdriveItemType::file: //parent/file-symlink/child-rel-path... => obscure, but possible + throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(AFS::getItemName(childItemPath)))); case GdriveItemType::folder: //parent/folder-symlink/child-rel-path... => always follow return getPathStatusSub(childDetails.targetId, childItemPath, childRelPath, followLeafShortcut); //throw SysError case GdriveItemType::shortcut: //should never happen: creating shortcuts to shortcuts fails with "Internal Error" - throw SysError(replaceCpy(_("Cannot resolve symbolic link %x."), L"%x", - fmtPath(getShortDisplayPath(AfsPath(appendPath(folderPath.value, relPath.front()))))) + L' ' + - L"Google Drive Shortcut points to another Shortcut."); + throw SysError(replaceCpy<std::wstring>(L"Google Drive Shortcut %x is pointing to another Shortcut.", L"%x", fmtPath(AFS::getItemName(childItemPath)))); } break; } @@ -2504,9 +2504,7 @@ private: if (equalNativePath(fileStateRef.ref().getSharedDriveName(), locationName)) { if (fileState) - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", - fmtPath(getGdriveDisplayPath({{accessBuf_.getUserEmail(), locationName}, AfsPath()}))) + L' ' + - replaceCpy(_("The name %x is used by more than one item in the folder."), L"%x", fmtPath(locationName))); + throw SysError(replaceCpy(_("The name %x is used by more than one item in the folder."), L"%x", fmtPath(locationName))); fileState = &fileStateRef.ref(); locationRootId = driveId; @@ -2516,9 +2514,7 @@ private: if (equalNativePath(sfd.folderName, locationName)) { if (fileState) - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", - fmtPath(getGdriveDisplayPath({{accessBuf_.getUserEmail(), locationName}, AfsPath()}))) + L' ' + - replaceCpy(_("The name %x is used by more than one item in the folder."), L"%x", fmtPath(locationName))); + throw SysError(replaceCpy(_("The name %x is used by more than one item in the folder."), L"%x", fmtPath(locationName))); if (sfd.sharedDriveId.empty()) //=> My Drive fileState = &myDrive_; @@ -2534,8 +2530,7 @@ private: } if (!fileState) - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", - fmtPath(getGdriveDisplayPath({{accessBuf_.getUserEmail(), locationName}, AfsPath()})))); + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(locationName))); return {*fileState, locationRootId}; } @@ -2637,7 +2632,7 @@ public: } catch (FileError&) { - if (itemStillExists(dbFilePath)) //throw FileError + if (itemExists(dbFilePath)) //throw FileError throw; } } @@ -2670,19 +2665,22 @@ public: }); //also include available, but not-yet-loaded sessions - traverseFolder(configDirPath_, - [&](const FileInfo& fi) { if (endsWith(fi.itemName, Zstr(".db"))) emails.push_back(utfTo<std::string>(beforeLast(fi.itemName, Zstr('.'), IfNotFoundReturn::none))); }, - [&](const FolderInfo& fi) {}, - [&](const SymlinkInfo& si) {}, - [&](const std::wstring& errorMsg) + try + { + traverseFolder(configDirPath_, + [&](const FileInfo& fi) { if (endsWith(fi.itemName, Zstr(".db"))) emails.push_back(utfTo<std::string>(beforeLast(fi.itemName, Zstr('.'), IfNotFoundReturn::none))); }, + [&](const FolderInfo& fi) {}, + [&](const SymlinkInfo& si) {}); //throw FileError + } + catch (FileError&) { try { - if (itemStillExists(configDirPath_)) //throw FileError - throw FileError(errorMsg); + if (itemExists(configDirPath_)) //throw FileError + throw; } catch (const FileError& e) { throw SysError(replaceCpy(e.toString(), L"\n\n", L'\n')); } //file access errors should be further enriched by context info => SysError - }); + } removeDuplicates(emails, LessAsciiNoCase()); return emails; @@ -2792,7 +2790,7 @@ private: } catch (FileError&) { - if (itemStillExists(dbFilePath)) //throw FileError + if (itemExists(dbFilePath)) //throw FileError throw; return std::nullopt; @@ -3184,8 +3182,8 @@ struct OutputStreamGdrive : public AFS::OutputStreamImpl std::optional<time_t> modTime, std::unique_ptr<PathAccessLock>&& pal) //throw SysError { - std::promise<AFS::FingerPrint> pFilePrint; - futFilePrint_ = pFilePrint.get_future(); + std::promise<AFS::FingerPrint> promFilePrint; + futFilePrint_ = promFilePrint.get_future(); //CAVEAT: if file is already existing, OutputStreamGdrive *constructor* must fail, not OutputStreamGdrive::write(), // otherwise ~OutputStreamImpl() will delete the already existing file! => don't check asynchronously! @@ -3198,13 +3196,13 @@ struct OutputStreamGdrive : public AFS::OutputStreamImpl throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(fileName))); if (ps.relPath.size() > 1) //parent folder missing - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", - fmtPath(getGdriveDisplayPath({gdrivePath.gdriveLogin, AfsPath(appendPath(ps.existingPath.value, ps.relPath.front()))})))); + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(ps.relPath.front()))); + parentId = ps.existingItemId; }); worker_ = InterruptibleThread([gdrivePath, modTime, fileName, asyncStreamIn = this->asyncStreamOut_, - pFilePrint = std::move(pFilePrint), + pFilePrint = std::move(promFilePrint), parentId = std::move(parentId), aai = std::move(aai), pal = std::move(pal)]() mutable @@ -3330,10 +3328,11 @@ public: }); if (!ps.relPath.empty()) - throw FileError(replaceCpy(_("Cannot find %x."), L"%x", fmtPath(getDisplayPath(folderPath)))); + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(ps.relPath.front()))); if (ps.existingType != GdriveItemType::folder) throw SysError(replaceCpy<std::wstring>(L"%x is not a folder.", L"%x", fmtPath(getItemName(folderPath)))); + warn_static("weird in combination with 'file attributes'") return Zstr("https://drive.google.com/drive/folders/") + utfTo<Zstring>(ps.existingItemId); } @@ -3380,12 +3379,29 @@ private: //---------------------------------------------------------------------------------------------------------------- ItemType getItemType(const AfsPath& itemPath) const override //throw FileError { - if (const std::optional<ItemType> type = itemStillExists(itemPath)) //throw FileError - return *type; - throw FileError(replaceCpy(_("Cannot find %x."), L"%x", fmtPath(getDisplayPath(itemPath)))); + try + { + GdriveFileState::PathStatus ps; + accessGlobalFileState(gdriveLogin_, [&](GdriveFileStateAtLocation& fileState) //throw SysError + { + ps = fileState.getPathStatus(itemPath, false /*followLeafShortcut*/); //throw SysError + }); + if (ps.relPath.empty()) + switch (ps.existingType) + { + //*INDENT-OFF* + case GdriveItemType::file: return ItemType::file; + case GdriveItemType::folder: return ItemType::folder; + case GdriveItemType::shortcut: return ItemType::symlink; + //*INDENT-ON* + } + + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(Zstring(ps.relPath.front())))); + } + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(getDisplayPath(itemPath))), e.toString()); } } - std::optional<ItemType> itemStillExists(const AfsPath& itemPath) const override //throw FileError + std::variant<ItemType, AfsPath /*last existing parent path*/> getItemTypeIfExists(const AfsPath& itemPath) const override //throw FileError { try { @@ -3403,12 +3419,12 @@ private: case GdriveItemType::shortcut: return ItemType::symlink; //*INDENT-ON* } - return {}; + return ps.existingPath; } catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(getDisplayPath(itemPath))), e.toString()); } } - //---------------------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------------------- //already existing: 1. fails or 2. creates duplicate (unlikely) void createFolderPlain(const AfsPath& folderPath) const override //throw FileError { @@ -3426,7 +3442,8 @@ private: throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(folderName))); if (ps.relPath.size() > 1) //parent folder missing - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", fmtPath(getDisplayPath(AfsPath(appendPath(ps.existingPath.value, ps.relPath.front())))))); + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(ps.relPath.front()))); + parentId = ps.existingItemId; }); @@ -3442,23 +3459,44 @@ private: catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(getDisplayPath(folderPath))), e.toString()); } } - void removeItemPlainImpl(const AfsPath& folderPath, bool permanent /*...or move to trash*/) const //throw SysError + void removeItemPlainImpl(const AfsPath& itemPath, std::optional<GdriveItemType> expectedType, bool permanent /*...or move to trash*/, bool failIfNotExist) const //throw SysError { + const std::optional<AfsPath> parentPath = getParentPath(itemPath); + if (!parentPath) throw SysError(L"Item is device root"); + std::string itemId; std::optional<std::string> parentIdToUnlink; const GdrivePersistentSessions::AsyncAccessInfo aai = accessGlobalFileState(gdriveLogin_, [&](GdriveFileStateAtLocation& fileState) //throw SysError { - const std::optional<AfsPath> parentPath = getParentPath(folderPath); - if (!parentPath) throw SysError(L"Item is device root"); + const GdriveFileState::PathStatus ps = fileState.getPathStatus(itemPath, false /*followLeafShortcut*/); //throw SysError + if (!ps.relPath.empty()) + { + if (failIfNotExist) + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(ps.relPath.front()))); + else + return; + } GdriveItemDetails itemDetails; - std::tie(itemId, itemDetails) = fileState.getFileAttributes(folderPath, false /*followLeafShortcut*/); //throw SysError + std::tie(itemId, itemDetails) = fileState.getFileAttributes(itemPath, false /*followLeafShortcut*/); //throw SysError assert(std::find(itemDetails.parentIds.begin(), itemDetails.parentIds.end(), fileState.getItemId(*parentPath, true /*followLeafShortcut*/)) != itemDetails.parentIds.end()); + if (expectedType && itemDetails.type != *expectedType) + switch (*expectedType) + { + //*INDENT-OFF* + case GdriveItemType::file: throw SysError(L"Item is not a file"); + case GdriveItemType::folder: throw SysError(L"Item is not a folder"); + case GdriveItemType::shortcut: throw SysError(L"Item is not a shortcut"); + //*INDENT-ON* + } + //hard-link handling applies to shared files as well: 1. it's the right thing (TM) 2. if we're not the owner: deleting would fail if (itemDetails.parentIds.size() > 1 || itemDetails.owner == FileOwner::other) //FileOwner::other behaves like a followed symlink! i.e. vanishes if owner deletes it! parentIdToUnlink = fileState.getItemId(*parentPath, true /*followLeafShortcut*/); //throw SysError }); + if (itemId.empty()) + return; if (parentIdToUnlink) { @@ -3487,37 +3525,31 @@ private: void removeFilePlain(const AfsPath& filePath) const override //throw FileError { - try { removeItemPlainImpl(filePath, true /*permanent*/); /*throw SysError*/ } + try { removeItemPlainImpl(filePath, GdriveItemType::file, true /*permanent*/, false /*failIfNotExist*/); /*throw SysError*/ } catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot delete file %x."), L"%x", fmtPath(getDisplayPath(filePath))), e.toString()); } } void removeSymlinkPlain(const AfsPath& linkPath) const override //throw FileError { - try { removeItemPlainImpl(linkPath, true /*permanent*/); /*throw SysError*/ } + try { removeItemPlainImpl(linkPath, GdriveItemType::shortcut, true /*permanent*/, false /*failIfNotExist*/); /*throw SysError*/ } catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot delete symbolic link %x."), L"%x", fmtPath(getDisplayPath(linkPath))), e.toString()); } } void removeFolderPlain(const AfsPath& folderPath) const override //throw FileError { - try { removeItemPlainImpl(folderPath, true /*permanent*/); /*throw SysError*/ } + try { removeItemPlainImpl(folderPath, GdriveItemType::folder, true /*permanent*/, false /*failIfNotExist*/); /*throw SysError*/ } catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot delete directory %x."), L"%x", fmtPath(getDisplayPath(folderPath))), e.toString()); } } void removeFolderIfExistsRecursion(const AfsPath& folderPath, //throw FileError - const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, //optional - const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion) const override //one call for each object! + const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, + const std::function<void(const std::wstring& displayPath)>& onBeforeSymlinkDeletion/*throw X*/, + const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion /*throw X*/) const override { if (onBeforeFolderDeletion) onBeforeFolderDeletion(getDisplayPath(folderPath)); //throw X - try - { - //deletes recursively with a single call! - removeFolderPlain(folderPath); //throw FileError - } - catch (const FileError&) - { - if (itemStillExists(folderPath)) //throw FileError - throw; - } + + try { removeItemPlainImpl(folderPath, GdriveItemType::folder, true /*permanent*/, false /*failIfNotExist*/); /*throw SysError*/ } + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot delete directory %x."), L"%x", fmtPath(getDisplayPath(folderPath))), e.toString()); } } //---------------------------------------------------------------------------------------------------------------- @@ -3630,8 +3662,8 @@ private: throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(itemNameNew))); if (psTo.relPath.size() > 1) //parent folder missing - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", - fmtPath(fsTarget.getDisplayPath(AfsPath(appendPath(psTo.existingPath.value, psTo.relPath.front())))))); + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(psTo.relPath.front()))); + parentIdTrg = psTo.existingItemId; }); @@ -3713,7 +3745,8 @@ private: throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(shortcutName))); if (ps.relPath.size() > 1) //parent folder missing - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", fmtPath(fsTarget.getDisplayPath(AfsPath(appendPath(ps.existingPath.value, ps.relPath.front())))))); + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(ps.relPath.front()))); + parentId = ps.existingItemId; }); @@ -3783,8 +3816,8 @@ private: throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(itemNameNew))); if (psTo.relPath.size() > 1) //parent folder missing - throw SysError(replaceCpy(_("Cannot find %x."), L"%x", - fmtPath(fsTarget.getDisplayPath(AfsPath(appendPath(psTo.existingPath.value, psTo.relPath.front())))))); + throw SysError(replaceCpy(_("%x does not exist."), L"%x", fmtPath(psTo.relPath.front()))); + parentIdTo = psTo.existingItemId; } }); @@ -3810,27 +3843,29 @@ private: FileIconHolder getFileIcon (const AfsPath& filePath, int pixelSize) const override { return {}; } //throw FileError; optional return value ImageHolder getThumbnailImage(const AfsPath& filePath, int pixelSize) const override { return {}; } //throw FileError; optional return value - void authenticateAccess(bool allowUserInteraction) const override //throw FileError + void authenticateAccess(const RequestPasswordFun& requestPassword /*throw X*/) const override //throw FileError, (X) { - if (allowUserInteraction) - try - { - const std::shared_ptr<GdrivePersistentSessions> gps = globalGdriveSessions.get(); - if (!gps) - throw SysError(formatSystemError("GdriveFileSystem::authenticateAccess", L"", L"Function call not allowed during init/shutdown.")); + try + { + const std::shared_ptr<GdrivePersistentSessions> gps = globalGdriveSessions.get(); + if (!gps) + throw SysError(formatSystemError("GdriveFileSystem::authenticateAccess", L"", L"Function call not allowed during init/shutdown.")); - for (const std::string& accountEmail : gps->listAccounts()) //throw SysError - if (equalAsciiNoCase(accountEmail, gdriveLogin_.email)) - return; + for (const std::string& accountEmail : gps->listAccounts()) //throw SysError + if (equalAsciiNoCase(accountEmail, gdriveLogin_.email)) + return; + + const bool allowUserInteraction = static_cast<bool>(requestPassword); + if (allowUserInteraction) gps->addUserSession(gdriveLogin_.email /*gdriveLoginHint*/, nullptr /*updateGui*/, gdriveLogin_.timeoutSec); //throw SysError - //error messages will be lost after time out in dir_exist_async.h! However: - //The most-likely-to-fail parts (web access) are reported by gdriveAuthorizeAccess() via the browser! - } - catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to connect to %x."), L"%x", fmtPath(getDisplayPath(AfsPath()))), e.toString()); } + //error messages will be lost if user cancels in dir_exist_async.h! However: + //The most-likely-to-fail parts (web access) are reported by gdriveAuthorizeAccess() via the browser! + else + throw SysError(replaceCpy(_("Please add a connection to user account %x first."), L"%x", utfTo<std::wstring>(gdriveLogin_.email))); + } + catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to connect to %x."), L"%x", fmtPath(getDisplayPath(AfsPath()))), e.toString()); } } - int getAccessTimeout() const override { return gdriveLogin_.timeoutSec; } //returns "0" if no timeout in force - bool hasNativeTransactionalCopy() const override { return true; } //---------------------------------------------------------------------------------------------------------------- @@ -3867,7 +3902,7 @@ private: { try { - removeItemPlainImpl(itemPath, false /*permanent*/); //throw SysError + removeItemPlainImpl(itemPath, std::nullopt /*expectedType*/, false /*permanent*/, true /*failIfNotExist*/); //throw SysError } catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", fmtPath(getDisplayPath(itemPath))), e.toString()); } } @@ -3964,7 +3999,7 @@ std::vector<std::string /*account email*/> fff::gdriveListAccounts() //throw Fil throw SysError(formatSystemError("gdriveListAccounts", L"", L"Function call not allowed during init/shutdown.")); } - catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to access %x."), L"%x", L"Google Drive"), e.toString()); } + catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to connect to %x."), L"%x", L"Google Drive"), e.toString()); } } @@ -3977,7 +4012,7 @@ std::vector<Zstring /*locationName*/> fff::gdriveListLocations(const std::string throw SysError(formatSystemError("gdriveListLocations", L"", L"Function call not allowed during init/shutdown.")); } - catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to access %x."), L"%x", fmtPath(getGdriveDisplayPath({{accountEmail, Zstr("")}, AfsPath()}))), e.toString()); } + catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to connect to %x."), L"%x", fmtPath(getGdriveDisplayPath({{accountEmail, Zstr("")}, AfsPath()}))), e.toString()); } } diff --git a/FreeFileSync/Source/afs/gdrive.h b/FreeFileSync/Source/afs/gdrive.h index 648c6d9e..a5ebbba8 100644 --- a/FreeFileSync/Source/afs/gdrive.h +++ b/FreeFileSync/Source/afs/gdrive.h @@ -31,7 +31,7 @@ struct GdriveLogin { std::string email; Zstring locationName; //empty for "My Drive"; can be a shared drive or starred folder name - int timeoutSec = 15; //Gdrive can "hang" for 20 seconds when "scanning for viruses": https://freefilesync.org/forum/viewtopic.php?t=9116 + int timeoutSec = 10; //Gdrive can "hang" for 20 seconds when "scanning for viruses": https://freefilesync.org/forum/viewtopic.php?t=9116 }; AfsDevice condenseToGdriveDevice(const GdriveLogin& login); //noexcept; potentially messy user input diff --git a/FreeFileSync/Source/afs/native.cpp b/FreeFileSync/Source/afs/native.cpp index e62df793..bbcd82e9 100644 --- a/FreeFileSync/Source/afs/native.cpp +++ b/FreeFileSync/Source/afs/native.cpp @@ -182,7 +182,8 @@ FsItemDetails getItemDetails(const Zstring& itemPath) //throw FileError THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), "lstat"); return {S_ISLNK(itemInfo.st_mode) ? ItemType::symlink : //on Linux there is no distinction between file and directory symlinks! - /**/ (S_ISDIR(itemInfo.st_mode) ? ItemType::folder : ItemType::file), //a file or named pipe, etc. => dont't check using S_ISREG(): see comment in file_traverser.cpp + /**/ (S_ISDIR(itemInfo.st_mode) ? ItemType::folder : ItemType::file), //a file or named pipe, etc. S_ISREG, S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK + //=> dont't check using S_ISREG(): see comment in file_traverser.cpp itemInfo.st_mtime, makeUnsigned(itemInfo.st_size), getFileFingerprint(itemInfo.st_ino)}; @@ -426,10 +427,9 @@ private: } //---------------------------------------------------------------------------------------------------------------- - ItemType getItemType(const AfsPath& itemPath) const override //throw FileError + static ItemType zenToAfsItemType(zen::ItemType type) { - initComForThread(); //throw FileError - switch (zen::getItemType(getNativePath(itemPath))) //throw FileError + switch (type) { case zen::ItemType::file: return AFS::ItemType::file; @@ -439,16 +439,30 @@ private: return AFS::ItemType::symlink; } assert(false); - return AFS::ItemType::file; + return static_cast<AFS::ItemType>(type); } - std::optional<ItemType> itemStillExists(const AfsPath& itemPath) const override //throw FileError + ItemType getItemType(const AfsPath& itemPath) const override //throw FileError { - //default implementation: folder traversal - return AFS::itemStillExists(itemPath); //throw FileError + initComForThread(); //throw FileError + return zenToAfsItemType(zen::getItemType(getNativePath(itemPath))); //throw FileError } - //---------------------------------------------------------------------------------------------------------------- + std::variant<ItemType, AfsPath /*last existing parent path*/> getItemTypeIfExists(const AfsPath& itemPath) const override //throw FileError + { + initComForThread(); //throw FileError + std::variant<zen::ItemType, Zstring /*last existing parent path*/> typeOrPath = zen::getItemTypeIfExists(getNativePath(itemPath)); //throw FileError + + if (const zen::ItemType* type = std::get_if<zen::ItemType>(&typeOrPath)) + return zenToAfsItemType(*type); + + const Zstring existingFolderPath = std::get<Zstring>(typeOrPath); + + assert(startsWith(existingFolderPath, rootPath_)); //"reverse" getNativePath() => safer than parsePathComponents()->relPath!? + return sanitizeDeviceRelativePath({existingFolderPath.begin() + rootPath_.size(), existingFolderPath.end()}); + } + + //---------------------------------------------------------------------------------------------------------------- //already existing: fail void createFolderPlain(const AfsPath& folderPath) const override //throw FileError { @@ -475,11 +489,12 @@ private: } void removeFolderIfExistsRecursion(const AfsPath& folderPath, //throw FileError - const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, //optional - const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion) const override //one call for each object! + const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, + const std::function<void(const std::wstring& displayPath)>& onBeforeSymlinkDeletion/*throw X*/, + const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion /*throw X*/) const override { //default implementation: folder traversal - AFS::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeFolderDeletion); //throw FileError, X + AFS::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeSymlinkDeletion, onBeforeFolderDeletion); //throw FileError, X } //---------------------------------------------------------------------------------------------------------------- @@ -657,12 +672,10 @@ private: catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(getDisplayPath(filePath))), e.toString()); } } - void authenticateAccess(bool allowUserInteraction) const override //throw FileError + void authenticateAccess(const RequestPasswordFun& requestPassword /*throw X*/) const override //throw FileError, (X) { } - int getAccessTimeout() const override { return 0; } //returns "0" if no timeout in force - bool hasNativeTransactionalCopy() const override { return false; } //---------------------------------------------------------------------------------------------------------------- diff --git a/FreeFileSync/Source/afs/sftp.cpp b/FreeFileSync/Source/afs/sftp.cpp index a2047575..86cc8d32 100644 --- a/FreeFileSync/Source/afs/sftp.cpp +++ b/FreeFileSync/Source/afs/sftp.cpp @@ -99,55 +99,75 @@ SFTP_OPTIMAL_BLOCK_SIZE_READ: SFTP_OPTIMAL_BLOCK_SIZE_WRITE: DSL maximum download speed: 12,9 MB/s DSL maximum upload speed: 4,7 MB/s => libssh2_sftp_read/libssh2_sftp_write may take quite long for 16x and larger => use smallest multiple that fills bandwidth! */ -} -namespace fff -{ inline -int getEffectivePort(int portOption) +uint16_t getEffectivePort(int portOption) { if (portOption > 0) - return portOption; + return static_cast<uint16_t>(portOption); return DEFAULT_PORT_SFTP; } -std::weak_ordering operator<=>(const SshSessionId& lhs, const SshSessionId& rhs) +struct SshDeviceId //= what defines a unique SFTP location +{ + /*explicit*/ SshDeviceId(const SftpLogin& login) : + server(login.server), + port(getEffectivePort(login.portCfg)), + username(login.username) {} + + Zstring server; + uint16_t port; //must be valid port! + Zstring username; +}; +std::weak_ordering operator<=>(const SshDeviceId& lhs, const SshDeviceId& rhs) { - //exactly the type of case insensitive comparison we need for server names! - if (const std::weak_ordering cmp = compareAsciiNoCase(lhs.server, rhs.server); //https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfow#IDNs + //exactly the type of case insensitive comparison we need for server names! https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfow#IDNs + if (const std::weak_ordering cmp = compareAsciiNoCase(lhs.server, rhs.server); cmp != std::weak_ordering::equivalent) return cmp; - const int portLhs = getEffectivePort(lhs.port); - const int portRhs = getEffectivePort(rhs.port); + return std::tie(lhs.port, lhs.username) <=> //username: case sensitive! + std::tie(rhs.port, rhs.username); +} +//also needed by compareDeviceSameAfsType(), so can't just replace with hash and use std::unordered_map - if (const std::strong_ordering cmp = std::tie(portLhs, lhs.username, lhs.authType, lhs.allowZlib) <=> //username: case sensitive! - std::tie(portRhs, rhs.username, rhs.authType, rhs.allowZlib); - cmp != std::strong_ordering::equal) - return cmp; + +struct SshSessionCfg //= config for buffered SFTP session +{ + SshDeviceId deviceId; + SftpAuthType authType = SftpAuthType::password; + Zstring password; //authType == password or keyFile + Zstring privateKeyFilePath; //authType == keyFile: use PEM-encoded private key (protected by password) for authentication + bool allowZlib = false; +}; +bool operator==(const SshSessionCfg& lhs, const SshSessionCfg& rhs) +{ + if (lhs.deviceId <=> rhs.deviceId != std::weak_ordering::equivalent) + return false; + + if (std::tie(lhs.authType, lhs.allowZlib) != + std::tie(rhs.authType, rhs.allowZlib)) + return false; switch (lhs.authType) { case SftpAuthType::password: - return lhs.password <=> rhs.password; //case sensitive! + return lhs.password == rhs.password; //case sensitive! case SftpAuthType::keyFile: - return std::tie(lhs.password, lhs.privateKeyFilePath) <=> //case sensitive! - std::tie(rhs.password, rhs.privateKeyFilePath); // + return std::tie(lhs.password, lhs.privateKeyFilePath) == //case sensitive! + std::tie(rhs.password, rhs.privateKeyFilePath); // case SftpAuthType::agent: - return std::weak_ordering::equivalent; + return true; } assert(false); - return std::weak_ordering::equivalent; -} + return true; } -namespace -{ Zstring concatenateSftpFolderPathPhrase(const SftpLogin& login, const AfsPath& itemPath); //noexcept @@ -157,18 +177,17 @@ std::string getLibssh2Path(const AfsPath& itemPath) } -std::wstring getSftpDisplayPath(const SshSessionId& sessionId, const AfsPath& itemPath) +std::wstring getSftpDisplayPath(const SshDeviceId& deviceId, const AfsPath& itemPath) { Zstring displayPath = Zstring(sftpPrefix) + Zstr("//"); - if (!sessionId.username.empty()) //show username! consider AFS::compareDeviceSameAfsType() - displayPath += sessionId.username + Zstr('@'); + if (!deviceId.username.empty()) //show username! consider AFS::compareDeviceSameAfsType() + displayPath += deviceId.username + Zstr('@'); - displayPath += sessionId.server; + displayPath += deviceId.server; - if (const int port = getEffectivePort(sessionId.port); - port != DEFAULT_PORT_SFTP) - displayPath += Zstr(':') + numberTo<Zstring>(port); + if (deviceId.port != DEFAULT_PORT_SFTP) + displayPath += Zstr(':') + numberTo<Zstring>(deviceId.port); const Zstring& relPath = getServerRelPath(itemPath); if (relPath != Zstr("/")) @@ -179,16 +198,16 @@ std::wstring getSftpDisplayPath(const SshSessionId& sessionId, const AfsPath& it //=========================================================================================================================== -class FatalSshError //=> consider SshSession corrupted and stop use ASAP! same conceptual level like SysError +//=> most likely *not* a connection issue +struct SysErrorSftpProtocol : public zen::SysError { -public: - explicit FatalSshError(const std::wstring& details) : details_(details) {} - const std::wstring& toString() const { return details_; } + SysErrorSftpProtocol(const std::wstring& msg, unsigned long sftpError) : SysError(msg), sftpErrorCode(sftpError) {} -private: - std::wstring details_; + const unsigned long sftpErrorCode; }; +DEFINE_NEW_SYS_ERROR(SysErrorPassword) + constinit Global<UniSessionCounter> globalSftpSessionCount; GLOBAL_RUN_ONCE(globalSftpSessionCount.set(createUniSessionCounter())); @@ -197,14 +216,14 @@ GLOBAL_RUN_ONCE(globalSftpSessionCount.set(createUniSessionCounter())); class SshSession { public: - SshSession(const SshSessionId& sessionId, int timeoutSec) : //throw SysError - sessionId_(sessionId) + SshSession(const SshSessionCfg& sessionCfg, int timeoutSec) : //throw SysError, SysErrorPassword + sessionCfg_(sessionCfg) { ZEN_ON_SCOPE_FAIL(cleanup()); //destructor call would lead to member double clean-up!!! - const Zstring& serviceName = numberTo<Zstring>(getEffectivePort(sessionId_.port)); + const Zstring& serviceName = numberTo<Zstring>(sessionCfg_.deviceId.port); - socket_ = std::make_unique<Socket>(sessionId_.server, serviceName); //throw SysError + socket_ = std::make_unique<Socket>(sessionCfg_.deviceId.server, serviceName, timeoutSec); //throw SysError sshSession_ = ::libssh2_session_init(); if (!sshSession_) //does not set ssh last error; source: only memory allocation may fail @@ -212,7 +231,7 @@ public: //if zlib compression causes trouble, make it a user setting: https://freefilesync.org/forum/viewtopic.php?t=6663 //=> surprise: it IS causing trouble: slow-down in local syncs: https://freefilesync.org/forum/viewtopic.php?t=7244#p24250 - if (sessionId.allowZlib) + if (sessionCfg_.allowZlib) if (const int rc = ::libssh2_session_flag(sshSession_, LIBSSH2_FLAG_COMPRESS, 1); rc != 0) //does not set SSH last error throw SysError(formatSystemError("libssh2_session_flag", formatSshStatusCode(rc), L"")); @@ -228,13 +247,13 @@ public: //evaluate fingerprint = libssh2_hostkey_hash(sshSession_, LIBSSH2_HOSTKEY_HASH_SHA1) ??? - const auto usernameUtf8 = utfTo<std::string>(sessionId_.username); - const auto passwordUtf8 = utfTo<std::string>(sessionId_.password); + const auto usernameUtf8 = utfTo<std::string>(sessionCfg_.deviceId.username); + const auto passwordUtf8 = utfTo<std::string>(sessionCfg_.password); const char* authList = ::libssh2_userauth_list(sshSession_, usernameUtf8); if (!authList) { - if (::libssh2_userauth_authenticated(sshSession_) == 0) + if (::libssh2_userauth_authenticated(sshSession_) != 1) throw SysError(formatLastSshError("libssh2_userauth_list", nullptr)); //else: SSH_USERAUTH_NONE has authenticated successfully => we're already done } @@ -257,14 +276,14 @@ public: } }); - switch (sessionId_.authType) + switch (sessionCfg_.authType) { case SftpAuthType::password: { if (supportAuthPassword) { if (::libssh2_userauth_password(sshSession_, usernameUtf8, passwordUtf8) != 0) - throw SysError(formatLastSshError("libssh2_userauth_password", nullptr)); + throw SysErrorPassword(formatLastSshError("libssh2_userauth_password", nullptr)); } else if (supportAuthInteractive) //some servers, e.g. web.sourceforge.net, support "keyboard-interactive", but not "password" { @@ -304,8 +323,8 @@ public: ZEN_ON_SCOPE_EXIT(*::libssh2_session_abstract(sshSession_) = nullptr); if (::libssh2_userauth_keyboard_interactive(sshSession_, usernameUtf8, authCallbackWrapper) != 0) - throw SysError(formatLastSshError("libssh2_userauth_keyboard_interactive", nullptr) + - (unexpectedPrompts.empty() ? L"" : L"\nUnexpected prompts: " + unexpectedPrompts)); + throw SysErrorPassword(formatLastSshError("libssh2_userauth_keyboard_interactive", nullptr) + + (unexpectedPrompts.empty() ? L"" : L"\nUnexpected prompts: " + unexpectedPrompts)); } else throw SysError(replaceCpy(_("The server does not support authentication via %x."), L"%x", L"\"username/password\"") + @@ -323,7 +342,7 @@ public: std::string pkStream; try { - pkStream = getFileContent(sessionId_.privateKeyFilePath, nullptr /*notifyUnbufferedIO*/); //throw FileError + pkStream = getFileContent(sessionCfg_.privateKeyFilePath, nullptr /*notifyUnbufferedIO*/); //throw FileError trim(pkStream); } catch (const FileError& e) { throw SysError(replaceCpy(e.toString(), L"\n\n", L'\n')); } //errors should be further enriched by context info => SysError @@ -331,14 +350,14 @@ public: //libssh2 doesn't support the PuTTY key file format, but we do! if (isPuttyKeyStream(pkStream)) try - { - pkStream = convertPuttyKeyToPkix(pkStream, passphrase); //throw SysError - passphrase.clear(); - } - catch (const SysError& e) //add file path to error message: - { - throw SysError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(sessionId_.privateKeyFilePath)) + L' ' + e.toString()); - } + { + pkStream = convertPuttyKeyToPkix(pkStream, passphrase); //throw SysError + passphrase.clear(); + } + catch (const SysError& e) //add context + { + throw SysErrorPassword(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(sessionCfg_.privateKeyFilePath)) + L' ' + e.toString()); + } if (::libssh2_userauth_publickey_frommemory(sshSession_, usernameUtf8, pkStream, passphrase) != 0) //const char* passphrase { @@ -353,12 +372,13 @@ public: if (contains(firstLine, "PUBLIC KEY")) return L"OpenSSH public key"; - if (startsWith(pkStream, "ssh-") || //ssh-rsa, ssh-dss, ssh-ed25519 + if (startsWith(pkStream, "rsa-") || //rsa-sha2-256, rsa-sha2-512 + startsWith(pkStream, "ssh-") || //ssh-rsa, ssh-dss, ssh-ed25519, ssh-ed448 startsWith(pkStream, "ecdsa-")) //ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521 return L"OpenSSH public key"; //OpenSSH SSH-2 public key if (std::count(pkStream.begin(), pkStream.end(), ' ') == 2 && - std::all_of(pkStream.begin(), pkStream.end(), [](char c) { return isDigit(c) || c == ' '; })) + /**/std::all_of(pkStream.begin(), pkStream.end(), [](char c) { return isDigit(c) || c == ' '; })) return L"SSH-1 public key"; //"-----BEGIN PRIVATE KEY-----" => OpenSSH SSH-2 private key (PKCS#8 PrivateKeyInfo) => should work @@ -374,9 +394,12 @@ public: if (invalidKeyFormat) throw SysError(_("Authentication failed.") + L' ' + replaceCpy<std::wstring>(L"%x is not an OpenSSH or PuTTY private key file.", L"%x", - fmtPath(sessionId_.privateKeyFilePath) + L" [" + invalidKeyFormat + L']')); - - throw SysError(formatLastSshError("libssh2_userauth_publickey_frommemory", nullptr)); + fmtPath(sessionCfg_.privateKeyFilePath) + L" [" + invalidKeyFormat + L']')); + if (isPuttyKeyStream(pkStream)) + throw SysError(formatLastSshError("libssh2_userauth_publickey_frommemory", nullptr)); + else + //can't rely on LIBSSH2_ERROR_AUTHENTICATION_FAILED: https://github.com/libssh2/libssh2/pull/789 + throw SysErrorPassword(formatLastSshError("libssh2_userauth_publickey_frommemory", nullptr)); } } break; @@ -422,7 +445,11 @@ public: ~SshSession() { cleanup(); } - const SshSessionId& getSessionId() const { return sessionId_; } + const SshSessionCfg& getSessionCfg() const + { + static_assert(std::is_const_v<decltype(sessionCfg_)>, "keep this function thread-safe!"); + return sessionCfg_; + } bool isHealthy() const { @@ -454,7 +481,7 @@ public: //return "false" if pending bool tryNonBlocking(size_t channelNo, std::chrono::steady_clock::time_point commandStartTime, const char* functionName, - const std::function<int(const SshSession::Details& sd)>& sftpCommand /*noexcept!*/, int timeoutSec) //throw SysError, FatalSshError + const std::function<int(const SshSession::Details& sd)>& sftpCommand /*noexcept!*/, int timeoutSec) //throw SysError, SysErrorSftpProtocol { assert(::libssh2_session_get_blocking(sshSession_)); ::libssh2_session_set_blocking(sshSession_, 0); @@ -490,32 +517,32 @@ public: if (rc < 0 && ::libssh2_session_last_errno(sshSession_) != rc) //when libssh2 fails to properly set last error; e.g. https://github.com/libssh2/libssh2/pull/123 ::libssh2_session_set_last_error(sshSession_, rc, nullptr); - //note: even when non-blocking, libssh2 may return LIBSSH2_ERROR_TIMEOUT, but this seems to be an ordinary SSH error - - if (rc >= LIBSSH2_ERROR_NONE || rc == LIBSSH2_ERROR_SFTP_PROTOCOL) + if (rc >= LIBSSH2_ERROR_NONE || + (rc == LIBSSH2_ERROR_SFTP_PROTOCOL && ::libssh2_sftp_last_error(sftpChannel) != LIBSSH2_FX_OK)) + //libssh2 source: LIBSSH2_ERROR_SFTP_PROTOCOL *without* setting LIBSSH2_SFTP::last_errno indicates a corrupted connection! { nbInfo.commandPending = false; // lastSuccessfulUseTime_ = std::chrono::steady_clock::now(); //[!] LIBSSH2_ERROR_SFTP_PROTOCOL is NOT an SSH error => the SSH session is just fine! if (rc == LIBSSH2_ERROR_SFTP_PROTOCOL) - throw SysError(formatLastSshError(functionName, sftpChannel)); + throw SysErrorSftpProtocol(formatLastSshError(functionName, sftpChannel), ::libssh2_sftp_last_error(sftpChannel)); return true; } else if (rc == LIBSSH2_ERROR_EAGAIN) { if (std::chrono::steady_clock::now() > nbInfo.commandStartTime + std::chrono::seconds(timeoutSec)) //consider SSH session corrupted! => isHealthy() will see pending command - throw FatalSshError(formatSystemError(functionName, formatSshStatusCode(LIBSSH2_ERROR_TIMEOUT), - _P("Operation timed out after 1 second.", "Operation timed out after %x seconds.", timeoutSec))); + throw SysError(formatSystemError(functionName, formatSshStatusCode(LIBSSH2_ERROR_TIMEOUT), + _P("Operation timed out after 1 second.", "Operation timed out after %x seconds.", timeoutSec))); return false; } else //=> SSH session errors only (hopefully!) e.g. LIBSSH2_ERROR_SOCKET_RECV //consider SSH session corrupted! => isHealthy() will see pending command - throw FatalSshError(formatLastSshError(functionName, sftpChannel)); + throw SysError(formatLastSshError(functionName, sftpChannel)); } //returns when traffic is available or time out: both cases are handled by next tryNonBlocking() call - static void waitForTraffic(const std::vector<SshSession*>& sshSessions, int timeoutSec) //throw FatalSshError + static void waitForTraffic(const std::vector<SshSession*>& sshSessions, int timeoutSec) //throw SysError { //reference: session.c: _libssh2_wait_socket() std::vector<pollfd> fds; @@ -549,10 +576,10 @@ public: { assert(startTimeMin != std::chrono::steady_clock::time_point::max()); const auto now = std::chrono::steady_clock::now(); - const auto endTime = startTimeMin + std::chrono::seconds(timeoutSec); - if (now >= endTime) + const auto stopTime = startTimeMin + std::chrono::seconds(timeoutSec); + if (now >= stopTime) return; //time-out! => let next tryNonBlocking() call fail with detailed error! - const auto waitTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - now).count(); + const auto waitTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(stopTime - now).count(); //is poll() on macOS broken? https://daniel.haxx.se/blog/2016/10/11/poll-on-mac-10-12-is-broken/ // it seems Daniel only takes issue with "empty" input handling!? => not an issue for us @@ -560,15 +587,16 @@ public: const int rv = ::poll(fds.data(), //struct pollfd* fds fds.size(), //nfds_t nfds waitTimeMs); //int timeout [ms] + if (rv < 0) //consider SSH sessions corrupted! => isHealthy() will see pending commands + throw SysError(formatSystemError(functionName, getLastError())); + if (rv == 0) //time-out! => let next tryNonBlocking() call fail with detailed error! return; - if (rv < 0) //consider SSH sessions corrupted! => isHealthy() will see pending commands - throw FatalSshError(formatSystemError(functionName, getLastError())); } else assert(false); } - static void addSftpChannel(const std::vector<SshSession*>& sshSessions, int timeoutSec) //throw SysError, FatalSshError + static void addSftpChannel(const std::vector<SshSession*>& sshSessions, int timeoutSec) //throw SysError { auto addChannelDetails = [](const std::wstring& msg, SshSession& sshSession) //when hitting the server's SFTP channel limit, inform user about channel number { @@ -577,8 +605,7 @@ public: return msg + L' ' + replaceCpy(_("Failed to open SFTP channel number %x."), L"%x", formatNumber(sshSession.sftpChannels_.size() + 1)); }; - std::optional<SysError> firstSysError; - std::optional<FatalSshError> firstFatalError; + std::optional<SysError> firstSysError; std::vector<SshSession*> pendingSessions = sshSessions; const auto sftpCommandStartTime = std::chrono::steady_clock::now(); @@ -600,32 +627,26 @@ public: pendingSessions[pos]->sftpChannels_.emplace_back(sftpChannelNew); return LIBSSH2_ERROR_NONE; - }, timeoutSec)) //throw SysError, FatalSshError + }, timeoutSec)) //throw SysError, (SysErrorSftpProtocol) pendingSessions.erase(pendingSessions.begin() + pos); //= not pending } catch (const SysError& e) { if (!firstSysError) //don't throw yet and corrupt other valid, but pending SshSessions! We also don't want to leak LIBSSH2_SFTP* waiting in libssh2 code firstSysError = SysError(addChannelDetails(e.toString(), *pendingSessions[pos])); - pendingSessions.erase(pendingSessions.begin() + pos); - } - catch (const FatalSshError& e) - { - if (!firstFatalError) - firstFatalError = FatalSshError(addChannelDetails(e.toString(), *pendingSessions[pos])); + //SysErrorSftpProtocol? unexpected during libssh2_sftp_init() + //-> still occuring for whatever reason!? => "slice" down to SysError pendingSessions.erase(pendingSessions.begin() + pos); } if (pendingSessions.empty()) { - if (firstFatalError) //throw FatalSshError *before* SysError (later can be retried) - throw* firstFatalError; if (firstSysError) throw* firstSysError; return; } - waitForTraffic(pendingSessions, timeoutSec); //throw FatalSshError + waitForTraffic(pendingSessions, timeoutSec); //throw SysError } } @@ -662,8 +683,14 @@ private: if (lastErrorMsg) errorMsg = trimCpy(utfTo<std::wstring>(lastErrorMsg)); - if (sftpChannel && sshStatusCode == LIBSSH2_ERROR_SFTP_PROTOCOL) - errorMsg += (errorMsg.empty() ? L"" : L" - ") + formatSftpStatusCode(::libssh2_sftp_last_error(sftpChannel)); + //LIBSSH2_ERROR_SFTP_PROTOCOL does *not* mean libssh2_sftp_last_error() is also available! + //But if it's not, we have a broken connection, and lastErrorMsg contains meaningful details! + if (sshStatusCode == LIBSSH2_ERROR_SFTP_PROTOCOL && ::libssh2_sftp_last_error(sftpChannel) != LIBSSH2_FX_OK) + { + if (errorMsg == L"SFTP Protocol Error") //that's trite! + errorMsg.clear(); + return formatSystemError(functionName, formatSftpStatusCode(::libssh2_sftp_last_error(sftpChannel)), errorMsg); + } return formatSystemError(functionName, formatSshStatusCode(sshStatusCode), errorMsg); } @@ -690,7 +717,7 @@ private: SftpNonBlockInfo nbInfo_; //for SSH session, e.g. libssh2_sftp_init() - const SshSessionId sessionId_; + const SshSessionCfg sessionCfg_; const std::shared_ptr<UniCounterCookie> libsshCurlUnifiedInitCookie_{(getLibsshCurlUnifiedInitCookie(globalSftpSessionCount))}; //throw SysError std::chrono::steady_clock::time_point lastSuccessfulUseTime_; //...of the SSH session (but not necessarily the SFTP functionality!) }; @@ -700,7 +727,7 @@ private: class SftpSessionManager //reuse (healthy) SFTP sessions globally { - struct IdleSshSessions; + struct SshSessionCache; public: SftpSessionManager() : sessionCleaner_([this] @@ -721,27 +748,27 @@ public: session_(std::move(idleSession)) /*bound!*/, timeoutSec_(timeoutSec) { /*assert(session_->isHealthy());*/ } //we need two-step initialization: 1. constructor is FAST and noexcept 2. init() is SLOW and throws - void init() //throw SysError, FatalSshError + void initSftpChannel() //throw SysError { if (session_->getSftpChannelCount() == 0) //make sure the SSH session contains at least one SFTP channel - SshSession::addSftpChannel({session_.get()}, timeoutSec_); //throw SysError, FatalSshError + SshSession::addSftpChannel({session_.get()}, timeoutSec_); //throw SysError } - //bool isHealthy() const { return session_->isHealthy(); } - - void executeBlocking(const char* functionName, const std::function<int(const SshSession::Details& sd)>& sftpCommand /*noexcept!*/) //throw SysError, FatalSshError + void executeBlocking(const char* functionName, const std::function<int(const SshSession::Details& sd)>& sftpCommand /*noexcept!*/) //throw SysError, SysErrorSftpProtocol { assert(threadId_ == std::this_thread::get_id()); assert(session_->getSftpChannelCount() > 0); const auto sftpCommandStartTime = std::chrono::steady_clock::now(); for (;;) - if (session_->tryNonBlocking(0, sftpCommandStartTime, functionName, sftpCommand, timeoutSec_)) //throw SysError, FatalSshError + if (session_->tryNonBlocking(0 /*channelNo*/, sftpCommandStartTime, functionName, sftpCommand, timeoutSec_)) //throw SysError, SysErrorSftpProtocol return; else //pending - SshSession::waitForTraffic({session_.get()}, timeoutSec_); //throw FatalSshError + SshSession::waitForTraffic({session_.get()}, timeoutSec_); //throw SysError } + const SshSessionCfg& getSessionCfg() const { return session_->getSessionCfg(); } //thread-safe + private: std::unique_ptr<SshSession, ReUseOnDelete> session_; //bound! const std::thread::id threadId_ = std::this_thread::get_id(); @@ -754,10 +781,10 @@ public: SshSessionExclusive(std::unique_ptr<SshSession, ReUseOnDelete>&& idleSession, int timeoutSec) : session_(std::move(idleSession)) /*bound!*/, timeoutSec_(timeoutSec) { /*assert(session_->isHealthy());*/ } - bool tryNonBlocking(size_t channelNo, std::chrono::steady_clock::time_point commandStartTime, const char* functionName, //throw SysError, FatalSshError + bool tryNonBlocking(size_t channelNo, std::chrono::steady_clock::time_point commandStartTime, const char* functionName, //throw SysError, SysErrorSftpProtocol const std::function<int(const SshSession::Details& sd)>& sftpCommand /*noexcept!*/) { - return session_->tryNonBlocking(channelNo, commandStartTime, functionName, sftpCommand, timeoutSec_); //throw SysError, FatalSshError + return session_->tryNonBlocking(channelNo, commandStartTime, functionName, sftpCommand, timeoutSec_); //throw SysError, SysErrorSftpProtocol } void finishBlocking(size_t channelNo, std::chrono::steady_clock::time_point commandStartTime, const char* functionName, @@ -766,20 +793,20 @@ public: for (;;) try { - if (session_->tryNonBlocking(channelNo, commandStartTime, functionName, sftpCommand, timeoutSec_)) //throw SysError, FatalSshError + if (session_->tryNonBlocking(channelNo, commandStartTime, functionName, sftpCommand, timeoutSec_)) //throw SysError, SysErrorSftpProtocol return; else //pending - SshSession::waitForTraffic({session_.get()}, timeoutSec_); //throw FatalSshError + SshSession::waitForTraffic({session_.get()}, timeoutSec_); //throw SysError } - catch (const SysError& ) { return; } - catch (const FatalSshError&) { return; } + catch (SysError&) { return; } warn_static("log on error!") } size_t getSftpChannelCount() const { return session_->getSftpChannelCount(); } + void markAsCorrupted() { session_->markAsCorrupted(); } - static void addSftpChannel(const std::vector<SshSessionExclusive*>& exSessions) //throw SysError, FatalSshError + static void addSftpChannel(const std::vector<SshSessionExclusive*>& exSessions) //throw SysError { std::vector<SshSession*> sshSessions; for (SshSessionExclusive* exSession : exSessions) @@ -789,10 +816,10 @@ public: for (SshSessionExclusive* exSession : exSessions) timeoutSec = std::max(timeoutSec, exSession->timeoutSec_); - SshSession::addSftpChannel(sshSessions, timeoutSec); //throw SysError, FatalSshError + SshSession::addSftpChannel(sshSessions, timeoutSec); //throw SysError } - static void waitForTraffic(const std::vector<SshSessionExclusive*>& exSessions) //throw FatalSshError + static void waitForTraffic(const std::vector<SshSessionExclusive*>& exSessions) //throw SysError { std::vector<SshSession*> sshSessions; for (SshSessionExclusive* exSession : exSessions) @@ -802,10 +829,10 @@ public: for (SshSessionExclusive* exSession : exSessions) timeoutSec = std::max(timeoutSec, exSession->timeoutSec_); - SshSession::waitForTraffic(sshSessions, timeoutSec); //throw FatalSshError + SshSession::waitForTraffic(sshSessions, timeoutSec); //throw SysError } - const SshSessionId& getSessionId() const { return session_->getSessionId(); } + const SshSessionCfg& getSessionCfg() const { return session_->getSessionCfg(); } //thread-safe private: std::unique_ptr<SshSession, ReUseOnDelete> session_; //bound! @@ -813,16 +840,20 @@ public: }; - std::shared_ptr<SshSessionShared> getSharedSession(const SftpLogin& login) //throw SysError + std::shared_ptr<SshSessionShared> getSharedSession(const SftpLogin& login) //throw SysError, SysErrorPassword { - Protected<IdleSshSessions>& sessionStore = getSessionStore(login); + Protected<SshSessionCache>& sessionCache = getSessionCache(login); const std::thread::id threadId = std::this_thread::get_id(); - std::shared_ptr<SshSessionShared> sharedSession; //no need to protect against concurrency: same thread! + std::shared_ptr<SshSessionShared> sharedSession; //either or + std::optional<SshSessionCfg> sessionCfg; // - sessionStore.access([&](IdleSshSessions& sessions) + sessionCache.access([&](SshSessionCache& cache) { - std::weak_ptr<SshSessionShared>& sharedSessionWeak = sessions.sshSessionsWithThreadAffinity[threadId]; //get or create + if (!cache.activeCfg) //AFS::authenticateAccess() not called => authenticate implicitly! + setActiveConfig(cache, login); + + std::weak_ptr<SshSessionShared>& sharedSessionWeak = cache.sshSessionsWithThreadAffinity[threadId]; //get or create if (auto session = sharedSessionWeak.lock()) //dereference session ONLY after affinity to THIS thread was confirmed!!! //assume "isHealthy()" to avoid hitting server connection limits: (clean up of !isHealthy() after use; idle sessions via worker thread) @@ -830,30 +861,30 @@ public: if (!sharedSession) //assume "isHealthy()" to avoid hitting server connection limits: (clean up of !isHealthy() after use; idle sessions via worker thread) - if (!sessions.idleSshSessions.empty()) + if (!cache.idleSshSessions.empty()) { - std::unique_ptr<SshSession, ReUseOnDelete> sshSession(sessions.idleSshSessions.back().release()); - /**/ sessions.idleSshSessions.pop_back(); + std::unique_ptr<SshSession, ReUseOnDelete> sshSession(cache.idleSshSessions.back().release()); + /**/ cache.idleSshSessions.pop_back(); sharedSessionWeak = sharedSession = std::make_shared<SshSessionShared>(std::move(sshSession), login.timeoutSec); //still holding lock => constructor must be *fast*! } + if (!sharedSession) + sessionCfg = *cache.activeCfg; }); - //create new SFTP session outside the lock: 1. don't block other threads 2. non-atomic regarding "sessionStore"! => one session too many is not a problem! + //create new SFTP session outside the lock: 1. don't block other threads 2. non-atomic regarding "sessionCache"! => one session too many is not a problem! if (!sharedSession) { - sharedSession = std::make_shared<SshSessionShared>(std::unique_ptr<SshSession, ReUseOnDelete>(new SshSession(login, login.timeoutSec)), login.timeoutSec); //throw SysError - sessionStore.access([&](IdleSshSessions& sessions) + sharedSession = std::make_shared<SshSessionShared>(std::unique_ptr<SshSession, ReUseOnDelete>(new SshSession(*sessionCfg, login.timeoutSec)), login.timeoutSec); //throw SysError, SysErrorPassword + + sessionCache.access([&](SshSessionCache& cache) { - sessions.sshSessionsWithThreadAffinity[threadId] = sharedSession; + if (sharedSession->getSessionCfg() == *cache.activeCfg) //created outside the lock => check *again* + cache.sshSessionsWithThreadAffinity[threadId] = sharedSession; }); } - //finish two-step initialization outside the lock: SLOW! - try - { - sharedSession->init(); //throw SysError, FatalSshError - } - catch (const FatalSshError& e) { throw SysError(e.toString()); } //session corrupted => is not returned => no special handling required + //finish two-step initialization outside the lock: BLOCKING! + sharedSession->initSftpChannel(); //throw SysError return sharedSession; } @@ -861,43 +892,115 @@ public: std::unique_ptr<SshSessionExclusive> getExclusiveSession(const SftpLogin& login) //throw SysError { - Protected<IdleSshSessions>& sessionStore = getSessionStore(login); + std::unique_ptr<SshSession, ReUseOnDelete> sshSession; //either or + std::optional<SshSessionCfg> sessionCfg; // - std::unique_ptr<SshSession, ReUseOnDelete> sshSession; - - sessionStore.access([&](IdleSshSessions& sessions) + getSessionCache(login).access([&](SshSessionCache& cache) { + if (!cache.activeCfg) //AFS::authenticateAccess() not called => authenticate implicitly! + setActiveConfig(cache, login); + //assume "isHealthy()" to avoid hitting server connection limits: (clean up of !isHealthy() after use, idle sessions via worker thread) - if (!sessions.idleSshSessions.empty()) + if (!cache.idleSshSessions.empty()) { - sshSession.reset(sessions.idleSshSessions.back().release()); - /**/ sessions.idleSshSessions.pop_back(); + sshSession.reset(cache.idleSshSessions.back().release()); + /**/ cache.idleSshSessions.pop_back(); } + else + sessionCfg = *cache.activeCfg; }); - //create new SFTP session outside the lock: 1. don't block other threads 2. non-atomic regarding "sessionStore"! => one session too many is not a problem! + //create new SFTP session outside the lock: 1. don't block other threads 2. non-atomic regarding "sessionCache"! => one session too many is not a problem! if (!sshSession) - sshSession.reset(new SshSession(login, login.timeoutSec)); //throw SysError + sshSession.reset(new SshSession(*sessionCfg, login.timeoutSec)); //throw SysError, SysErrorPassword return std::make_unique<SshSessionExclusive>(std::move(sshSession), login.timeoutSec); } + void setActiveConfig(const SftpLogin& login) + { + getSessionCache(login).access([&](SshSessionCache& cache) { setActiveConfig(cache, login); }); + } + + void setSessionPassword(const SftpLogin& login, const Zstring& password, SftpAuthType authType) + { + getSessionCache(login).access([&](SshSessionCache& cache) + { + (authType == SftpAuthType::password ? cache.sessionPassword : cache.sessionPassphrase) = password; + setActiveConfig(cache, login); + }); + } + private: SftpSessionManager (const SftpSessionManager&) = delete; SftpSessionManager& operator=(const SftpSessionManager&) = delete; - Protected<IdleSshSessions>& getSessionStore(const SshSessionId& sessionId) + Protected<SshSessionCache>& getSessionCache(const SshDeviceId& deviceId) { - //single global session store per login; life-time bound to globalInstance => never remove a sessionStore!!! - Protected<IdleSshSessions>* store = nullptr; + //single global session store per login; life-time bound to globalInstance => never remove a sessionCache!!! + Protected<SshSessionCache>* sessionCache = nullptr; - globalSessionStore_.access([&](GlobalSshSessions& sessionsById) + globalSessionCache_.access([&](GlobalSshSessions& sessionsById) { - store = &sessionsById[sessionId]; //get or create + sessionCache = &sessionsById[deviceId]; //get or create }); - static_assert(std::is_same_v<GlobalSshSessions, std::map<SshSessionId, Protected<IdleSshSessions>>>, "require std::map so that the pointers we return remain stable"); + static_assert(std::is_same_v<GlobalSshSessions, std::map<SshDeviceId, Protected<SshSessionCache>>>, "require std::map so that the pointers we return remain stable"); - return *store; + return *sessionCache; + } + + void setActiveConfig(SshSessionCache& cache, const SftpLogin& login) + { + const Zstring password = [&] + { + if (login.authType == SftpAuthType::password || + login.authType == SftpAuthType::keyFile) + { + if (login.password) + return *login.password; + + return login.authType == SftpAuthType::password ? cache.sessionPassword : cache.sessionPassphrase; + } + return Zstring(); + }(); + + if (cache.activeCfg) + { + assert(std::all_of(cache.idleSshSessions.begin(), cache.idleSshSessions.end(), + [&](const std::unique_ptr<SshSession>& session) { return session->getSessionCfg() == cache.activeCfg; })); + + assert(std::all_of(cache.sshSessionsWithThreadAffinity.begin(), cache.sshSessionsWithThreadAffinity.end(), [&](const auto& v) + { + if (std::shared_ptr<SshSessionShared> sharedSession = v.second.lock()) + return sharedSession->getSessionCfg() /*thread-safe!*/ == cache.activeCfg; + return true; + })); + } + else + assert(cache.idleSshSessions.empty() && cache.sshSessionsWithThreadAffinity.empty()); + + const std::optional<SshSessionCfg> prevCfg = cache.activeCfg; + + cache.activeCfg = + { + .deviceId{login}, + .authType = login.authType, + .password = password, + .privateKeyFilePath = login.privateKeyFilePath, + .allowZlib = login.allowZlib, + }; + + /* remove incompatible sessions: + - avoid hitting FTP connection limit if some config uses TLS, but not the other: https://freefilesync.org/forum/viewtopic.php?t=8532 + - logically consistent with AFS::compareDevice() + - don't allow different authentication methods, when authenticateAccess() is called *once* per device in getFolderStatusParallel() + - what user expects, e.g. when tesing changed settings in SFTP login dialog */ + if (cache.activeCfg != prevCfg) + { + cache.idleSshSessions .clear(); //run ~SshSession *inside* the lock! => avoid hitting server limits! + cache.sshSessionsWithThreadAffinity.clear(); // + //=> incompatible sessions will be deleted by ReUseOnDelete(); until then: additionally counts towards SFTP connection limit :( + } } //run a dedicated clean-up thread => it's unclear when the server let's a connection time out, so we do it preemptively @@ -914,41 +1017,51 @@ private: lastCleanupTime = std::chrono::steady_clock::now(); - std::vector<Protected<IdleSshSessions>*> sessionStores; //pointers remain stable, thanks to std::unordered_map<> + std::vector<Protected<SshSessionCache>*> sessionCaches; //pointers remain stable, thanks to std::map<> - globalSessionStore_.access([&](GlobalSshSessions& sessionsById) + globalSessionCache_.access([&](GlobalSshSessions& sessionsById) { for (auto& [sessionId, idleSession] : sessionsById) - sessionStores.push_back(&idleSession); + sessionCaches.push_back(&idleSession); }); - - for (Protected<IdleSshSessions>* sessionStore : sessionStores) - for (bool done = false; !done;) - sessionStore->access([&](IdleSshSessions& sessions) + for (Protected<SshSessionCache>* sessionCache : sessionCaches) + for (;;) { - for (std::unique_ptr<SshSession>& sshSession : sessions.idleSshSessions) - if (!sshSession->isHealthy()) //!isHealthy() sessions are destroyed after use => in this context this means they have been idle for too long - { - sshSession.swap(sessions.idleSshSessions.back()); - /**/ sessions.idleSshSessions.pop_back(); //run ~SshSession *inside* the lock! => avoid hitting server limits! - std::this_thread::yield(); - return; //don't hold lock for too long: delete only one session at a time, then yield... - } - std::erase_if(sessions.sshSessionsWithThreadAffinity, [](const auto& v) { return !v.second.lock(); }); //clean up dangling weak pointer - done = true; - }); + bool done = false; + sessionCache->access([&](SshSessionCache& cache) + { + for (std::unique_ptr<SshSession>& sshSession : cache.idleSshSessions) + if (!sshSession->isHealthy()) //!isHealthy() sessions are destroyed after use => in this context this means they have been idle for too long + { + sshSession.swap(cache.idleSshSessions.back()); + /**/ cache.idleSshSessions.pop_back(); //run ~SshSession *inside* the lock! => avoid hitting server limits! + return; //don't hold lock for too long: delete only one session at a time, then yield... + } + std::erase_if(cache.sshSessionsWithThreadAffinity, [](const auto& v) { return !v.second.lock(); }); //clean up dangling weak pointer + done = true; + }); + if (done) + break; + std::this_thread::yield(); //outside the lock + } } } - struct IdleSshSessions + struct SshSessionCache { + //invariant: all cached sessions correspond to activeCfg at any time! std::vector<std::unique_ptr<SshSession>> idleSshSessions; //extract *temporarily* from this list during use std::map<std::thread::id, std::weak_ptr<SshSessionShared>> sshSessionsWithThreadAffinity; //Win32 thread IDs may be REUSED! still, shouldn't be a problem... + + std::optional<SshSessionCfg> activeCfg; + + Zstring sessionPassword; //user/password + Zstring sessionPassphrase; //keyfile/passphrase }; - using GlobalSshSessions = std::map<SshSessionId, Protected<IdleSshSessions>>; + using GlobalSshSessions = std::map<SshDeviceId, Protected<SshSessionCache>>; + Protected<GlobalSshSessions> globalSessionCache_; - Protected<GlobalSshSessions> globalSessionStore_; InterruptibleThread sessionCleaner_; }; @@ -959,28 +1072,25 @@ constinit Global<SftpSessionManager> globalSftpSessionManager; //caveat: life ti //-------------------------------------------------------------------------------------- -void SftpSessionManager::ReUseOnDelete::operator()(SshSession* s) const +void SftpSessionManager::ReUseOnDelete::operator()(SshSession* session) const { - //assert(s); -> custom deleter is only called on non-null pointer - if (s->isHealthy()) //thread that created the "!isHealthy()" session is responsible for clean up (avoid hitting server connection limits!) + //assert(session); -> custom deleter is only called on non-null pointer + if (session->isHealthy()) //thread that created the "!isHealthy()" session is responsible for clean up (avoid hitting server connection limits!) if (std::shared_ptr<SftpSessionManager> mgr = globalSftpSessionManager.get()) + mgr->getSessionCache(session->getSessionCfg().deviceId).access([&](SshSessionCache& cache) { - Protected<IdleSshSessions>& sessionStore = mgr->getSessionStore(s->getSessionId()); - sessionStore.access([&](IdleSshSessions& sessions) - { - sessions.idleSshSessions.emplace_back(s); //pass ownership - }); - return; - } - - delete s; + assert(cache.activeCfg); + if (cache.activeCfg && session->getSessionCfg() == *cache.activeCfg) + cache.idleSshSessions.emplace_back(std::exchange(session, nullptr)); //pass ownership + }); + delete session; } std::shared_ptr<SftpSessionManager::SshSessionShared> getSharedSftpSession(const SftpLogin& login) //throw SysError { if (const std::shared_ptr<SftpSessionManager> mgr = globalSftpSessionManager.get()) - return mgr->getSharedSession(login); //throw SysError + return mgr->getSharedSession(login); //throw SysError, SysErrorPassword throw SysError(formatSystemError("getSharedSftpSession", L"", L"Function call not allowed during init/shutdown.")); } @@ -996,15 +1106,12 @@ std::unique_ptr<SftpSessionManager::SshSessionExclusive> getExclusiveSftpSession void runSftpCommand(const SftpLogin& login, const char* functionName, - const std::function<int(const SshSession::Details& sd)>& sftpCommand /*noexcept!*/) //throw SysError + const std::function<int(const SshSession::Details& sd)>& sftpCommand /*noexcept!*/) //throw SysError, SysErrorSftpProtocol { std::shared_ptr<SftpSessionManager::SshSessionShared> asyncSession = getSharedSftpSession(login); //throw SysError //no need to protect against concurrency: shared session is (temporarily) bound to current thread - try - { - asyncSession->executeBlocking(functionName, sftpCommand); //throw SysError, FatalSshError - } - catch (const FatalSshError& e) { throw SysError(e.toString()); } //SSH session corrupted! => we stop using session => map to SysError is okay + + asyncSession->executeBlocking(functionName, sftpCommand); //throw SysError, SysErrorSftpProtocol } //=========================================================================================================================== @@ -1025,7 +1132,7 @@ std::vector<SftpItem> getDirContentFlat(const SftpLogin& login, const AfsPath& d LIBSSH2_SFTP_HANDLE* dirHandle = nullptr; try { - runSftpCommand(login, "libssh2_sftp_opendir", //throw SysError + runSftpCommand(login, "libssh2_sftp_opendir", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) //noexcept! { dirHandle = ::libssh2_sftp_opendir(sd.sftpChannel, getLibssh2Path(dirPath)); @@ -1038,7 +1145,7 @@ std::vector<SftpItem> getDirContentFlat(const SftpLogin& login, const AfsPath& d ZEN_ON_SCOPE_EXIT(try { - runSftpCommand(login, "libssh2_sftp_closedir", //throw SysError + runSftpCommand(login, "libssh2_sftp_closedir", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return ::libssh2_sftp_closedir(dirHandle); }); //noexcept! } catch (SysError&) {}); @@ -1052,7 +1159,7 @@ std::vector<SftpItem> getDirContentFlat(const SftpLogin& login, const AfsPath& d int rc = 0; try { - runSftpCommand(login, "libssh2_sftp_readdir", //throw SysError + runSftpCommand(login, "libssh2_sftp_readdir", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return rc = ::libssh2_sftp_readdir(dirHandle, buf.data(), buf.size(), &attribs); }); //noexcept! } catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(getSftpDisplayPath(login, dirPath))), e.toString()); } @@ -1096,7 +1203,7 @@ SftpItemDetails getSymlinkTargetDetails(const SftpLogin& login, const AfsPath& l LIBSSH2_SFTP_ATTRIBUTES attribsTrg = {}; try { - runSftpCommand(login, "libssh2_sftp_stat", //throw SysError + runSftpCommand(login, "libssh2_sftp_stat", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return ::libssh2_sftp_stat(sd.sftpChannel, getLibssh2Path(linkPath), &attribsTrg); }); //noexcept! } catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot resolve symbolic link %x."), L"%x", fmtPath(getSftpDisplayPath(login, linkPath))), e.toString()); } @@ -1214,7 +1321,7 @@ struct InputStreamSftp : public AFS::InputStream { session_ = getSharedSftpSession(login); //throw SysError - session_->executeBlocking("libssh2_sftp_open", //throw SysError, FatalSshError + session_->executeBlocking("libssh2_sftp_open", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) //noexcept! { fileHandle_ = ::libssh2_sftp_open(sd.sftpChannel, getLibssh2Path(filePath), LIBSSH2_FXF_READ, 0); @@ -1223,19 +1330,17 @@ struct InputStreamSftp : public AFS::InputStream return LIBSSH2_ERROR_NONE; }); } - catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot open file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } - catch (const FatalSshError& e) { throw FileError(replaceCpy(_("Cannot open file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } //SSH session corrupted! => stop using session + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot open file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } } ~InputStreamSftp() { try { - session_->executeBlocking("libssh2_sftp_close", //throw SysError, FatalSshError + session_->executeBlocking("libssh2_sftp_close", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return ::libssh2_sftp_close(fileHandle_); }); //noexcept! } catch (const SysError&) {} - catch (const FatalSshError&) {} //SSH session corrupted! => stop using session warn_static("log on error?") } @@ -1252,7 +1357,7 @@ struct InputStreamSftp : public AFS::InputStream ssize_t bytesRead = 0; try { - session_->executeBlocking("libssh2_sftp_read", //throw SysError, FatalSshError + session_->executeBlocking("libssh2_sftp_read", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) //noexcept! { bytesRead = ::libssh2_sftp_read(fileHandle_, static_cast<char*>(buffer), bytesToRead); @@ -1262,8 +1367,7 @@ struct InputStreamSftp : public AFS::InputStream if (makeUnsigned(bytesRead) > bytesToRead) //better safe than sorry throw SysError(formatSystemError("libssh2_sftp_read", L"", L"Buffer overflow.")); //user should never see this } - catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } - catch (const FatalSshError& e) { throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } //SSH session corrupted! => caller (will/should) stop using session + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } if (notifyUnbufferedIO) notifyUnbufferedIO(bytesRead); //throw X return bytesRead; //"zero indicates end of file" @@ -1295,7 +1399,7 @@ struct OutputStreamSftp : public AFS::OutputStreamImpl { session_ = getSharedSftpSession(login); //throw SysError - session_->executeBlocking("libssh2_sftp_open", //throw SysError, FatalSshError + session_->executeBlocking("libssh2_sftp_open", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) //noexcept! { fileHandle_ = ::libssh2_sftp_open(sd.sftpChannel, getLibssh2Path(filePath), @@ -1306,8 +1410,7 @@ struct OutputStreamSftp : public AFS::OutputStreamImpl return LIBSSH2_ERROR_NONE; }); } - catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } - catch (const FatalSshError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } //SSH session corrupted! => stop using session + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } //NOTE: fileHandle_ still unowned until end of constructor!!! @@ -1336,7 +1439,7 @@ struct OutputStreamSftp : public AFS::OutputStreamImpl ssize_t bytesWritten = 0; try { - session_->executeBlocking("libssh2_sftp_write", //throw SysError, FatalSshError + session_->executeBlocking("libssh2_sftp_write", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) //noexcept! { bytesWritten = ::libssh2_sftp_write(fileHandle_, static_cast<const char*>(buffer), bytesToWrite); @@ -1350,8 +1453,7 @@ struct OutputStreamSftp : public AFS::OutputStreamImpl if (makeUnsigned(bytesWritten) > bytesToWrite) //better safe than sorry throw SysError(formatSystemError("libssh2_sftp_write", L"", L"Buffer overflow.")); } - catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } - catch (const FatalSshError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } //SSH session corrupted! => caller (will/should) stop using session + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } if (notifyUnbufferedIO) notifyUnbufferedIO(bytesWritten); //throw X! @@ -1387,11 +1489,10 @@ private: { ZEN_ON_SCOPE_EXIT(fileHandle_ = nullptr); //reset on failure, too! there's no point in, calling libssh2_sftp_close() a second time in ~OutputStreamSftp() - session_->executeBlocking("libssh2_sftp_close", //throw SysError, FatalSshError + session_->executeBlocking("libssh2_sftp_close", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return ::libssh2_sftp_close(fileHandle_); }); //noexcept! } - catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } - catch (const FatalSshError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } //SSH session corrupted! => caller (will/should) stop using session + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(displayPath_)), e.toString()); } } void setModTimeIfAvailable() const //throw FileError, follows symlinks @@ -1406,11 +1507,10 @@ private: try { - session_->executeBlocking("libssh2_sftp_setstat", //throw SysError, FatalSshError + session_->executeBlocking("libssh2_sftp_setstat", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return ::libssh2_sftp_setstat(sd.sftpChannel, getLibssh2Path(filePath_), &attribNew); }); //noexcept! } - catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(displayPath_)), e.toString()); } - catch (const FatalSshError& e) { throw FileError(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(displayPath_)), e.toString()); } //SSH session corrupted! => caller (will/should) stop using session + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(displayPath_)), e.toString()); } } } @@ -1470,37 +1570,31 @@ private: const SftpLogin& lhs = login_; const SftpLogin& rhs = static_cast<const SftpFileSystem&>(afsRhs).login_; - //exactly the type of case insensitive comparison we need for server names! - if (const std::weak_ordering cmp = compareAsciiNoCase(lhs.server, rhs.server); //https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfow#IDNs - cmp != std::weak_ordering::equivalent) - return cmp; + return SshDeviceId(lhs) <=> SshDeviceId(rhs); + } - //port DOES create a *different* data source! https://freefilesync.org/forum/viewtopic.php?t=9047 - const int portLhs = getEffectivePort(lhs.port); - const int portRhs = getEffectivePort(rhs.port); + //---------------------------------------------------------------------------------------------------------------- + ItemType getItemTypeImpl(const AfsPath& itemPath) const //throw SysError, SysErrorSftpProtocol + { + LIBSSH2_SFTP_ATTRIBUTES attr = {}; + runSftpCommand(login_, "libssh2_sftp_lstat", //throw SysError, SysErrorSftpProtocol + [&](const SshSession::Details& sd) { return ::libssh2_sftp_lstat(sd.sftpChannel, getLibssh2Path(itemPath), &attr); }); //noexcept! - //consider username: different users may have different views and folder access rights! - return std::tie(portLhs, lhs.username) <=> //username: case sensitive! - std::tie(portRhs, rhs.username); + if ((attr.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) == 0) + throw SysError(formatSystemError("libssh2_sftp_lstat", L"", L"File attributes not available.")); + + if (LIBSSH2_SFTP_S_ISLNK(attr.permissions)) + return ItemType::symlink; + if (LIBSSH2_SFTP_S_ISDIR(attr.permissions)) + return ItemType::folder; + return ItemType::file; //LIBSSH2_SFTP_S_ISREG || LIBSSH2_SFTP_S_ISCHR || LIBSSH2_SFTP_S_ISBLK || LIBSSH2_SFTP_S_ISFIFO || LIBSSH2_SFTP_S_ISSOCK } - //---------------------------------------------------------------------------------------------------------------- ItemType getItemType(const AfsPath& itemPath) const override //throw FileError { try { - LIBSSH2_SFTP_ATTRIBUTES attr = {}; - runSftpCommand(login_, "libssh2_sftp_lstat", //throw SysError - [&](const SshSession::Details& sd) { return ::libssh2_sftp_lstat(sd.sftpChannel, getLibssh2Path(itemPath), &attr); }); //noexcept! - - if ((attr.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) == 0) - throw SysError(formatSystemError("libssh2_sftp_lstat", L"", L"File attributes not available.")); - - if (LIBSSH2_SFTP_S_ISLNK(attr.permissions)) - return ItemType::symlink; - if (LIBSSH2_SFTP_S_ISDIR(attr.permissions)) - return ItemType::folder; - return ItemType::file; //LIBSSH2_SFTP_S_ISREG || LIBSSH2_SFTP_S_ISCHR || LIBSSH2_SFTP_S_ISBLK || LIBSSH2_SFTP_S_ISFIFO || LIBSSH2_SFTP_S_ISSOCK + return getItemTypeImpl(itemPath); //throw SysError, SysErrorSftpProtocol } catch (const SysError& e) { @@ -1508,20 +1602,65 @@ private: } } - std::optional<ItemType> itemStillExists(const AfsPath& itemPath) const override //throw FileError + std::variant<ItemType, AfsPath /*last existing parent path*/> getItemTypeIfExists(const AfsPath& itemPath) const override //throw FileError { - //default implementation: folder traversal - return AFS::itemStillExists(itemPath); //throw FileError + try + { + try + { + //fast check: 1. perf 2. expected by getFolderStatusNonBlocking() 3. traversing non-existing folder below MIGHT NOT FAIL (e.g. for SFTP on AWS) + return getItemTypeImpl(itemPath); //throw SysError, SysErrorSftpProtocol + } + catch (const SysErrorSftpProtocol& e) + { + const std::optional<AfsPath> parentPath = getParentPath(itemPath); + if (!parentPath) //device root => quick access test + throw; + //let's dig deeper, but *only* for SysErrorSftpProtocol, not for general connection issues + //+ check if SFTP error code sounds like "not existing" + if (e.sftpErrorCode == LIBSSH2_FX_NO_SUCH_FILE || + e.sftpErrorCode == LIBSSH2_FX_NO_SUCH_PATH) //-> not seen yet, but sounds reasonable + { + const std::variant<ItemType, AfsPath /*last existing parent path*/> parentTypeOrPath = getItemTypeIfExists(*parentPath); //throw FileError + + if (const ItemType* parentType = std::get_if<ItemType>(&parentTypeOrPath)) + { + if (*parentType == ItemType::file /*obscure, but possible*/) + throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(getItemName(*parentPath)))); + + const Zstring itemName = getItemName(itemPath); + assert(!itemName.empty()); + + traverseFolder(*parentPath, //throw FileError + [&](const FileInfo& fi) { if (fi.itemName == itemName) throw SysError(_("Temporary access error:") + L' ' + e.toString()); }, + [&](const FolderInfo& fi) { if (fi.itemName == itemName) throw SysError(_("Temporary access error:") + L' ' + e.toString()); }, + [&](const SymlinkInfo& si) { if (si.itemName == itemName) throw SysError(_("Temporary access error:") + L' ' + e.toString()); }); + //- case-sensitive comparison! itemPath must be normalized! + //- finding the item after getItemType() previously failed is exceptional + + return *parentPath; + } + else + return parentTypeOrPath; + } + else + throw; + } + } + catch (const SysError& e) + { + throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(getDisplayPath(itemPath))), e.toString()); + } } - //---------------------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------------------- //already existing: fail void createFolderPlain(const AfsPath& folderPath) const override //throw FileError { try { //fails with obscure LIBSSH2_FX_FAILURE if already existing - runSftpCommand(login_, "libssh2_sftp_mkdir", //throw SysError + runSftpCommand(login_, "libssh2_sftp_mkdir", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) //noexcept! { return ::libssh2_sftp_mkdir(sd.sftpChannel, getLibssh2Path(folderPath), SFTP_DEFAULT_PERMISSION_FOLDER); @@ -1538,7 +1677,7 @@ private: { try { - runSftpCommand(login_, "libssh2_sftp_unlink", //throw SysError + runSftpCommand(login_, "libssh2_sftp_unlink", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return ::libssh2_sftp_unlink(sd.sftpChannel, getLibssh2Path(filePath)); }); //noexcept! } catch (const SysError& e) @@ -1549,39 +1688,38 @@ private: void removeSymlinkPlain(const AfsPath& linkPath) const override //throw FileError { - this->removeFilePlain(linkPath); //throw FileError + try + { + runSftpCommand(login_, "libssh2_sftp_unlink", //throw SysError, SysErrorSftpProtocol + [&](const SshSession::Details& sd) { return ::libssh2_sftp_unlink(sd.sftpChannel, getLibssh2Path(linkPath)); }); //noexcept! + } + catch (const SysError& e) + { + throw FileError(replaceCpy(_("Cannot delete symbolic link %x."), L"%x", fmtPath(getDisplayPath(linkPath))), e.toString()); + } } void removeFolderPlain(const AfsPath& folderPath) const override //throw FileError { - int delResult = LIBSSH2_ERROR_NONE; try { - runSftpCommand(login_, "libssh2_sftp_rmdir", //throw SysError - [&](const SshSession::Details& sd) { return delResult = ::libssh2_sftp_rmdir(sd.sftpChannel, getLibssh2Path(folderPath)); }); //noexcept! + //libssh2_sftp_rmdir fails for symlinks! (LIBSSH2_ERROR_SFTP_PROTOCOL: LIBSSH2_FX_NO_SUCH_FILE) + runSftpCommand(login_, "libssh2_sftp_rmdir", //throw SysError, SysErrorSftpProtocol + [&](const SshSession::Details& sd) { return ::libssh2_sftp_rmdir(sd.sftpChannel, getLibssh2Path(folderPath)); }); //noexcept! } catch (const SysError& e) { - if (delResult < 0) - { - //tested: libssh2_sftp_rmdir will fail for symlinks! - bool symlinkExists = false; - try { symlinkExists = getItemType(folderPath) == ItemType::symlink; } /*throw FileError*/ catch (FileError&) {} //previous exception is more relevant - - if (symlinkExists) - return removeSymlinkPlain(folderPath); //throw FileError - } - throw FileError(replaceCpy(_("Cannot delete directory %x."), L"%x", fmtPath(getDisplayPath(folderPath))), e.toString()); } } void removeFolderIfExistsRecursion(const AfsPath& folderPath, //throw FileError - const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, //optional - const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion) const override //one call for each object! + const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, + const std::function<void(const std::wstring& displayPath)>& onBeforeSymlinkDeletion/*throw X*/, + const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion /*throw X*/) const override { //default implementation: folder traversal - AFS::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeFolderDeletion); //throw FileError, X + AFS::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeSymlinkDeletion, onBeforeFolderDeletion); //throw FileError, X } //---------------------------------------------------------------------------------------------------------------- @@ -1591,7 +1729,7 @@ private: std::vector<char> buf(bufSize + 1); //ensure buffer is always null-terminated since we don't evaluate the byte count returned by libssh2_sftp_realpath()! int rc = 0; - runSftpCommand(login_, "libssh2_sftp_realpath", //throw SysError + runSftpCommand(login_, "libssh2_sftp_realpath", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return rc = ::libssh2_sftp_realpath(sd.sftpChannel, sftpPath, buf.data(), bufSize); }); //noexcept! const std::string_view sftpPathTrg = makeStringView(buf.data(), rc); @@ -1619,7 +1757,7 @@ private: int rc = 0; try { - runSftpCommand(sftpFs.login_, "libssh2_sftp_readlink", //throw SysError + runSftpCommand(sftpFs.login_, "libssh2_sftp_readlink", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return rc = ::libssh2_sftp_readlink(sd.sftpChannel, getLibssh2Path(linkPath), buf.data(), buf.size()); }); //noexcept! if (makeUnsigned(rc) > buf.size()) //better safe than sorry @@ -1703,7 +1841,7 @@ private: try { - runSftpCommand(login_, "libssh2_sftp_rename", //throw SysError + runSftpCommand(login_, "libssh2_sftp_rename", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) //noexcept! { /* LIBSSH2_SFTP_RENAME_NATIVE: "The server is free to do the rename operation in whatever way it chooses. Any other set flags are to be taken as hints to the server." No, thanks! @@ -1733,9 +1871,52 @@ private: FileIconHolder getFileIcon (const AfsPath& filePath, int pixelSize) const override { return {}; } //throw FileError; optional return value ImageHolder getThumbnailImage(const AfsPath& filePath, int pixelSize) const override { return {}; } //throw FileError; optional return value - void authenticateAccess(bool allowUserInteraction) const override {} //throw FileError + void authenticateAccess(const RequestPasswordFun& requestPassword /*throw X*/) const override //throw FileError, X + { + try + { + const std::shared_ptr<SftpSessionManager> mgr = globalSftpSessionManager.get(); + if (!mgr) + throw SysError(formatSystemError("getSessionPassword", L"", L"Function call not allowed during init/shutdown.")); + + mgr->setActiveConfig(login_); + + if (login_.authType == SftpAuthType::password || + login_.authType == SftpAuthType::keyFile) + if (!login_.password) + { + try //1. test for connection error *before* bothering user to enter a password + { + /*auto session =*/ mgr->getSharedSession(login_); //throw SysError, SysErrorPassword + return; //got new SshSession (connected in constructor) or already connected session from cache + } + catch (SysErrorPassword&) {} + + if (!requestPassword) + throw SysError(_("Password prompt not permitted by current settings.")); + + std::wstring lastErrorMsg; + for (;;) + { + //2. request (new) password + std::wstring msg = replaceCpy(_("Please enter your password to connect to %x"), L"%x", fmtPath(getDisplayPath(AfsPath()))); + if (lastErrorMsg.empty()) + msg += L"\n" + _("The password will only be remembered until FreeFileSync is closed."); - int getAccessTimeout() const override { return login_.timeoutSec; } //returns "0" if no timeout in force + const Zstring password = requestPassword(msg, lastErrorMsg); //throw X + mgr->setSessionPassword(login_, password, login_.authType); + + try //3. test access: + { + /*auto session =*/ mgr->getSharedSession(login_); //throw SysError, SysErrorPassword + return; + } + catch (const SysErrorPassword& e) { lastErrorMsg = e.toString(); } + } + } + } + catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to connect to %x."), L"%x", fmtPath(getDisplayPath(AfsPath()))), e.toString()); } + } bool hasNativeTransactionalCopy() const override { return false; } //---------------------------------------------------------------------------------------------------------------- @@ -1756,7 +1937,7 @@ private: LIBSSH2_SFTP_STATVFS fsStats = {}; try { - runSftpCommand(login_, "libssh2_sftp_statvfs", //throw SysError + runSftpCommand(login_, "libssh2_sftp_statvfs", //throw SysError, SysErrorSftpProtocol [&](const SshSession::Details& sd) { return ::libssh2_sftp_statvfs(sd.sftpChannel, sftpPath.c_str(), sftpPath.size(), &fsStats); }); //noexcept! } catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot determine free disk space for %x."), L"%x", fmtPath(getDisplayPath(L"/"))), e.toString()); } @@ -1791,8 +1972,8 @@ Zstring concatenateSftpFolderPathPhrase(const SftpLogin& login, const AfsPath& f username = encodeFtpUsername(login.username) + Zstr("@"); Zstring port; - if (login.port > 0) - port = Zstr(':') + numberTo<Zstring>(login.port); + if (login.portCfg > 0) + port = Zstr(':') + numberTo<Zstring>(login.portCfg); Zstring relPath = getServerRelPath(folderPath); if (relPath == Zstr("/")) @@ -1825,8 +2006,15 @@ Zstring concatenateSftpFolderPathPhrase(const SftpLogin& login, const AfsPath& f } if (login.authType != SftpAuthType::agent) - if (!login.password.empty()) //password always last => visually truncated by folder input field - options += Zstr("|pass64=") + encodePasswordBase64(login.password); + { + if (login.password) + { + if (!login.password->empty()) //password always last => visually truncated by folder input field + options += Zstr("|pass64=") + encodePasswordBase64(*login.password); + } + else + options += Zstr("|pwprompt"); + } return Zstring(sftpPrefix) + Zstr("//") + username + login.server + port + relPath + options; } @@ -1900,10 +2088,9 @@ int fff::getServerMaxChannelsPerConnection(const SftpLogin& login) //throw FileE { try { - SftpSessionManager::SshSessionExclusive::addSftpChannel({exSession.get()}); //throw SysError, FatalSshError + SftpSessionManager::SshSessionExclusive::addSftpChannel({exSession.get()}); //throw SysError } - catch (const SysError& ) { if (exSession->getSftpChannelCount() == 0) throw; return static_cast<int>(exSession->getSftpChannelCount()); } - catch (const FatalSshError& e) { if (exSession->getSftpChannelCount() == 0) throw SysError(e.toString()); return static_cast<int>(exSession->getSftpChannelCount()); } + catch (SysError&) { if (exSession->getSftpChannelCount() == 0) throw; return static_cast<int>(exSession->getSftpChannelCount()); } if (std::chrono::steady_clock::now() > timeoutTime) throw SysError(_P("Operation timed out after 1 second.", "Operation timed out after %x seconds.", @@ -1955,7 +2142,7 @@ AbstractPath fff::createItemPathSftp(const Zstring& itemPathPhrase) //noexcept login.server = Zstring(beforeLast(serverPort, Zstr(':'), IfNotFoundReturn::all)); const ZstringView port = afterLast(serverPort, Zstr(':'), IfNotFoundReturn::none); - login.port = stringTo<int>(port); //0 if empty + login.portCfg = stringTo<int>(port); //0 if empty assert(login.allowZlib == false); @@ -1976,6 +2163,8 @@ AbstractPath fff::createItemPathSftp(const Zstring& itemPathPhrase) //noexcept login.authType = SftpAuthType::agent; else if (startsWith(optPhrase, Zstr("pass64="))) login.password = decodePasswordBase64(afterFirst(optPhrase, Zstr("="), IfNotFoundReturn::none)); + else if (optPhrase == Zstr("pwprompt")) + login.password = std::nullopt; else if (optPhrase == Zstr("zlib")) login.allowZlib = true; else diff --git a/FreeFileSync/Source/afs/sftp.h b/FreeFileSync/Source/afs/sftp.h index 0a03ec47..8d0c62dd 100644 --- a/FreeFileSync/Source/afs/sftp.h +++ b/FreeFileSync/Source/afs/sftp.h @@ -27,25 +27,21 @@ enum class SftpAuthType agent, }; -//use all configuration data that *defines* an SSH session as key when buffering sessions! This is what user expects, e.g. when changing settings in SFTP login dialog -struct SshSessionId -{ - Zstring server; - int port = 0; // > 0 if set - Zstring username; - SftpAuthType authType = SftpAuthType::password; - Zstring password; //authType == password or keyFile - Zstring privateKeyFilePath; //authType == keyFile: use PEM-encoded private key (protected by password) for authentication - bool allowZlib = false; -}; const int DEFAULT_PORT_SFTP = 22; //SFTP default port: 22, see %WINDIR%\system32\drivers\etc\services //=> we could use the "ssh" alias, but let's be explicit -struct SftpLogin : SshSessionId +struct SftpLogin { + Zstring server; + int portCfg = 0; //use if > 0, DEFAULT_PORT_SFTP otherwise + Zstring username; + SftpAuthType authType = SftpAuthType::password; + std::optional<Zstring> password = Zstr(""); //authType == password or keyFile: none given => prompt during AFS::authenticateAccess() + Zstring privateKeyFilePath; //authType == keyFile: use PEM-encoded private key (protected by password) for authentication + bool allowZlib = false; //other settings not specific to SFTP session: - int timeoutSec = 15; //valid range: [1, inf) + int timeoutSec = 10; //valid range: [1, inf) int traverserChannelsPerConnection = 1; //valid range: [1, inf) }; AfsDevice condenseToSftpDevice(const SftpLogin& login); //noexcept; potentially messy user input diff --git a/FreeFileSync/Source/application.cpp b/FreeFileSync/Source/application.cpp index 34e49d23..69d1c3fa 100644 --- a/FreeFileSync/Source/application.cpp +++ b/FreeFileSync/Source/application.cpp @@ -11,6 +11,7 @@ #include <zen/shutdown.h> #include <zen/process_exec.h> #include <zen/resolve_path.h> +#include <wx/clipbrd.h> #include <wx/tooltip.h> #include <wx/log.h> #include <wx+/app_main.h> @@ -23,6 +24,7 @@ #include "base/synchronization.h" #include "ui/batch_status_handler.h" #include "ui/main_dlg.h" +#include "ui/small_dlgs.h" #include "base_tools.h" #include "ffs_paths.h" #include "return_codes.h" @@ -41,8 +43,12 @@ namespace std::vector<Zstring> getCommandlineArgs(const wxApp& app) { std::vector<Zstring> args; - for (int i = 1; i < app.argc; ++i) //wxWidgets screws up once again making "argv implicitly convertible to a wxChar**" in 2.9.3, - args.push_back(utfTo<Zstring>(wxString(app.argv[i]))); //so we are forced to use this pitiful excuse for a range construction!! + for (const wxString& arg : app.argv.GetArguments()) + args.push_back(utfTo<Zstring>(arg)); + //remove first argument which is exe path by convention: https://devblogs.microsoft.com/oldnewthing/20060515-07/?p=31203 + if (!args.empty()) + args.erase(args.begin()); + return args; } @@ -221,6 +227,8 @@ void Application::onEnterEventLoop(wxEvent& event) int Application::OnExit() { + [[maybe_unused]] const bool rv = wxClipboard::Get()->Flush(); //see wx+/context_menu.h + //assert(rv); -> fails if clipboard wasn't used localizationCleanup(); imageResourcesCleanup(); @@ -364,7 +372,8 @@ void Application::launch(const std::vector<Zstring>& commandArgs) globalConfigFile = filePath; else throw FileError(replaceCpy(_("Cannot open file %x."), L"%x", fmtPath(filePath)), - _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(filePath))); + _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(filePath)) + L'\n' + + _("Expected:") + L" ffs_gui, ffs_batch, xml"); } } //---------------------------------------------------------------------------------------------------- @@ -494,7 +503,7 @@ void Application::runBatchMode(const Zstring& globalConfigFilePath, const XmlBat try { bool cfgFileExists = true; - try { cfgFileExists = !!itemStillExists(globalConfigFilePath); /*throw FileError*/ } //=> unclear which exception is more relevant/useless: + try { cfgFileExists = itemExists(globalConfigFilePath); /*throw FileError*/ } //=> unclear which exception is more relevant/useless: catch (const FileError& e2) { throw FileError(replaceCpy(e.toString(), L"\n\n", L'\n'), replaceCpy(e2.toString(), L"\n\n", L'\n')); } if (cfgFileExists) @@ -544,6 +553,21 @@ void Application::runBatchMode(const Zstring& globalConfigFilePath, const XmlBat batchCfg.batchExCfg.autoCloseSummary, batchCfg.batchExCfg.postSyncAction, batchCfg.batchExCfg.batchErrorHandling); + + const bool allowUserInteraction = !batchCfg.batchExCfg.autoCloseSummary || + (!batchCfg.mainCfg.ignoreErrors && batchCfg.batchExCfg.batchErrorHandling == BatchErrorHandling::showPopup); + + AFS::RequestPasswordFun requestPassword; //throw AbortProcess + if (allowUserInteraction) + requestPassword = [&, password = Zstring()](const std::wstring& msg, const std::wstring& lastErrorMsg) mutable + { + assert(runningOnMainThread()); + if (showPasswordPrompt(statusHandler.getWindowIfVisible(), msg, lastErrorMsg, password) != ConfirmationButton::accept) + statusHandler.abortProcessNow(AbortTrigger::user); //throw AbortProcess + + return password; + }; + try { //inform about (important) non-default global settings @@ -552,12 +576,10 @@ void Application::runBatchMode(const Zstring& globalConfigFilePath, const XmlBat //batch mode: place directory locks on directories during both comparison AND synchronization std::unique_ptr<LockHolder> dirLocks; - const bool allowUserInteraction = !batchCfg.mainCfg.ignoreErrors && batchCfg.batchExCfg.batchErrorHandling == BatchErrorHandling::showPopup; - //COMPARE DIRECTORIES FolderComparison cmpResult = compare(globalCfg.warnDlgs, globalCfg.fileTimeTolerance, - allowUserInteraction, + requestPassword, globalCfg.runWithBackgroundPriority, globalCfg.createLockFile, dirLocks, diff --git a/FreeFileSync/Source/base/algorithm.cpp b/FreeFileSync/Source/base/algorithm.cpp index 26d6e3b2..49cc4883 100644 --- a/FreeFileSync/Source/base/algorithm.cpp +++ b/FreeFileSync/Source/base/algorithm.cpp @@ -675,7 +675,7 @@ private: //need ref-counted strings! see FileSystemObject::syncDirectionConflict_ const Zstringc txtBothSidesChanged_ = utfTo<Zstringc>(_("Both sides have changed since last synchronization.")); const Zstringc txtNoSideChanged_ = utfTo<Zstringc>(_("Cannot determine sync-direction:") + L'\n' + TAB_SPACE + _("No change since last synchronization.")); - const Zstringc txtDbNotInSync_ = utfTo<Zstringc>(_("Cannot determine sync-direction:") + L'\n' + TAB_SPACE + _("The database entry is not in sync considering current settings.")); + const Zstringc txtDbNotInSync_ = utfTo<Zstringc>(_("Cannot determine sync-direction:") + L'\n' + TAB_SPACE + _("The database entry is not in sync, considering current settings.")); const Zstringc txtDbAmbiguous_ = utfTo<Zstringc>(_("Cannot determine sync-direction:") + L'\n' + TAB_SPACE + _("The database entry is ambiguous.")); const CompareVariant cmpVar_; @@ -1173,7 +1173,7 @@ void copyToAlternateFolderFrom(const std::vector<const FileSystemObject*>& rowsT } catch (FileError&) {} //=> not yet existing (=> fine, no path issue) or access error: //- let's pretend it doesn't happen :> if it does, worst case: the retry fails with (useless) already existing error - //- itemStillExists()? too expensive, considering that "already existing" is the most common case + //- itemExists()? too expensive, considering that "already existing" is the most common case if (alreadyExisting) { @@ -1293,7 +1293,7 @@ void fff::copyToAlternateFolder(std::span<const FileSystemObject* const> rowsToC namespace { template <SelectSide side> -void deleteFromGridAndHDOneSide(std::vector<FileSystemObject*>& rowsToDelete, +void deleteFromGridAndHdOneSide(std::vector<FileSystemObject*>& rowsToDelete, bool moveToRecycler, bool& recyclerMissingReportOnce, bool& warnRecyclerMissing, //WarningDialogs::warnRecyclerMissing @@ -1308,6 +1308,102 @@ void deleteFromGridAndHDOneSide(std::vector<FileSystemObject*>& rowsToDelete, const std::wstring txtDelFolderPermanent_ = _("Deleting folder %x"); const std::wstring txtDelFolderRecycler_ = _("Moving folder %x to the recycle bin"); + auto removeFile = [&](const AbstractPath& filePath, ItemStatReporter<PhaseCallback>& statReporter) + { + if (moveToRecycler) + try + { + reportInfo(replaceCpy(txtDelFileRecycler_, L"%x", fmtPath(AFS::getDisplayPath(filePath))), statReporter); //throw X + AFS::moveToRecycleBinIfExists(filePath); //throw FileError, RecycleBinUnavailable + } + catch (const RecycleBinUnavailable& e) + { + if (!recyclerMissingReportOnce) + { + recyclerMissingReportOnce = true; + callback.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing); //throw X + } + callback.logMessage(replaceCpy(txtDelFilePermanent_, L"%x", fmtPath(AFS::getDisplayPath(filePath))) + + L" [" + _("Recycle bin unavailable") + L']', PhaseCallback::MsgType::warning); //throw X + AFS::removeFileIfExists(filePath); //throw FileError + } + else + { + reportInfo(replaceCpy(txtDelFilePermanent_, L"%x", fmtPath(AFS::getDisplayPath(filePath))), statReporter); //throw X + AFS::removeFileIfExists(filePath); //throw FileError + } + statReporter.reportDelta(1, 0); + }; + + auto removeSymlink = [&](const AbstractPath& symlinkPath, ItemStatReporter<PhaseCallback>& statReporter) + { + if (moveToRecycler) + try + { + reportInfo(replaceCpy(txtDelSymlinkRecycler_, L"%x", fmtPath(AFS::getDisplayPath(symlinkPath))), statReporter); //throw X + AFS::moveToRecycleBinIfExists(symlinkPath); //throw FileError, RecycleBinUnavailable + } + catch (const RecycleBinUnavailable& e) + { + if (!recyclerMissingReportOnce) + { + recyclerMissingReportOnce = true; + callback.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing); //throw X + } + callback.logMessage(replaceCpy(txtDelSymlinkPermanent_, L"%x", fmtPath(AFS::getDisplayPath(symlinkPath))) + + L" [" + _("Recycle bin unavailable") + L']', PhaseCallback::MsgType::warning); //throw X + AFS::removeSymlinkIfExists(symlinkPath); //throw FileError + } + else + { + reportInfo(replaceCpy(txtDelSymlinkPermanent_, L"%x", fmtPath(AFS::getDisplayPath(symlinkPath))), statReporter); //throw X + AFS::removeSymlinkIfExists(symlinkPath); //throw FileError + } + statReporter.reportDelta(1, 0); + }; + + auto removeFolder = [&](const AbstractPath& folderPath, ItemStatReporter<PhaseCallback>& statReporter) + { + auto removeFolderPermanently = [&] + { + auto onBeforeDeletion = [&](const std::wstring& msgTemplate, const std::wstring& displayPath) + { + reportInfo(replaceCpy(msgTemplate, L"%x", fmtPath(displayPath)), statReporter); //throw X + statReporter.reportDelta(1, 0); //it would be more correct to report *after* work was done! + }; + + AFS::removeFolderIfExistsRecursion(folderPath, + [&](const std::wstring& displayPath) { onBeforeDeletion(txtDelFilePermanent_, displayPath); }, + [&](const std::wstring& displayPath) { onBeforeDeletion(txtDelSymlinkPermanent_, displayPath); }, + [&](const std::wstring& displayPath) { onBeforeDeletion(txtDelFolderPermanent_, displayPath); }); //throw FileError, X + }; + + if (moveToRecycler) + try + { + reportInfo(replaceCpy(txtDelFolderRecycler_, L"%x", fmtPath(AFS::getDisplayPath(folderPath))), statReporter); //throw X + AFS::moveToRecycleBinIfExists(folderPath); //throw FileError, RecycleBinUnavailable + statReporter.reportDelta(1, 0); + } + catch (const RecycleBinUnavailable& e) + { + if (!recyclerMissingReportOnce) + { + recyclerMissingReportOnce = true; + callback.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing); //throw X + } + callback.logMessage(replaceCpy(txtDelFolderPermanent_, L"%x", fmtPath(AFS::getDisplayPath(folderPath))) + + L" [" + _("Recycle bin unavailable") + L']', PhaseCallback::MsgType::warning); //throw X + removeFolderPermanently(); //throw FileError, X + } + else + { + reportInfo(replaceCpy(txtDelFolderPermanent_, L"%x", fmtPath(AFS::getDisplayPath(folderPath))), statReporter); //throw X + removeFolderPermanently(); //throw FileError, X + } + }; + + for (FileSystemObject* fsObj : rowsToDelete) //all pointers are required(!) to be bound tryReportingError([&] { @@ -1317,96 +1413,23 @@ void deleteFromGridAndHDOneSide(std::vector<FileSystemObject*>& rowsToDelete, { visitFSObject(*fsObj, [&](const FolderPair& folder) { - auto removeFolderPermanently = [&] - { - auto notifyDeletion = [&](const std::wstring& msgTemplate, const std::wstring& displayPath) - { - reportInfo(replaceCpy(msgTemplate, L"%x", fmtPath(displayPath)), statReporter); //throw X - statReporter.reportDelta(1, 0); //it would be more correct to report *after* work was done! - }; - - auto onBeforeFileDeletion = [&](const std::wstring& displayPath) { notifyDeletion(txtDelFilePermanent_, displayPath); }; - auto onBeforeDirDeletion = [&](const std::wstring& displayPath) { notifyDeletion(txtDelFolderPermanent_, displayPath); }; - AFS::removeFolderIfExistsRecursion(folder.getAbstractPath<side>(), onBeforeFileDeletion, onBeforeDirDeletion); //throw FileError - }; - - if (moveToRecycler) - try - { - reportInfo(replaceCpy(txtDelFolderRecycler_, L"%x", fmtPath(AFS::getDisplayPath(folder.getAbstractPath<side>()))), statReporter); //throw X - AFS::moveToRecycleBinIfExists(folder.getAbstractPath<side>()); //throw FileError, RecycleBinUnavailable - statReporter.reportDelta(1, 0); - } - catch (const RecycleBinUnavailable& e) - { - if (!recyclerMissingReportOnce) - { - recyclerMissingReportOnce = true; - callback.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing); //throw X - } - callback.logMessage(replaceCpy(txtDelFolderPermanent_, L"%x", fmtPath(AFS::getDisplayPath(folder.getAbstractPath<side>()))) + - L" [" + _("The recycle bin is not available") + L']', PhaseCallback::MsgType::warning); //throw X - removeFolderPermanently(); //throw FileError, X - } + if (folder.isFollowedSymlink<side>()) + removeSymlink(folder.getAbstractPath<side>(), statReporter); //throw FileError, X else - { - reportInfo(replaceCpy(txtDelFolderPermanent_, L"%x", fmtPath(AFS::getDisplayPath(folder.getAbstractPath<side>()))), statReporter); //throw X - removeFolderPermanently(); //throw FileError, X - } + removeFolder(folder.getAbstractPath<side>(), statReporter); //throw FileError, X }, [&](const FilePair& file) { - if (moveToRecycler) - try - { - reportInfo(replaceCpy(txtDelFileRecycler_, L"%x", fmtPath(AFS::getDisplayPath(file.getAbstractPath<side>()))), statReporter); //throw X - AFS::moveToRecycleBinIfExists(file.getAbstractPath<side>()); //throw FileError, RecycleBinUnavailable - } - catch (const RecycleBinUnavailable& e) - { - if (!recyclerMissingReportOnce) - { - recyclerMissingReportOnce = true; - callback.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing); //throw X - } - callback.logMessage(replaceCpy(txtDelFilePermanent_, L"%x", fmtPath(AFS::getDisplayPath(file.getAbstractPath<side>()))) + - L" [" + _("The recycle bin is not available") + L']', PhaseCallback::MsgType::warning); //throw X - AFS::removeFileIfExists(file.getAbstractPath<side>()); //throw FileError - } + if (file.isFollowedSymlink<side>()) + removeSymlink(file.getAbstractPath<side>(), statReporter); //throw FileError, X else - { - reportInfo(replaceCpy(txtDelFilePermanent_, L"%x", fmtPath(AFS::getDisplayPath(file.getAbstractPath<side>()))), statReporter); //throw X - AFS::removeFileIfExists(file.getAbstractPath<side>()); //throw FileError - } - statReporter.reportDelta(1, 0); + removeFile(file.getAbstractPath<side>(), statReporter); //throw FileError, X }, [&](const SymlinkPair& symlink) { - if (moveToRecycler) - try - { - reportInfo(replaceCpy(txtDelSymlinkRecycler_, L"%x", fmtPath(AFS::getDisplayPath(symlink.getAbstractPath<side>()))), statReporter); //throw X - AFS::moveToRecycleBinIfExists(symlink.getAbstractPath<side>()); //throw FileError, RecycleBinUnavailable - } - catch (const RecycleBinUnavailable& e) - { - if (!recyclerMissingReportOnce) - { - recyclerMissingReportOnce = true; - callback.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing); //throw X - } - callback.logMessage(replaceCpy(txtDelSymlinkPermanent_, L"%x", fmtPath(AFS::getDisplayPath(symlink.getAbstractPath<side>()))) + - L" [" + _("The recycle bin is not available") + L']', PhaseCallback::MsgType::warning); //throw X - AFS::removeSymlinkIfExists(symlink.getAbstractPath<side>()); //throw FileError - } - else - { - reportInfo(replaceCpy(txtDelSymlinkPermanent_, L"%x", fmtPath(AFS::getDisplayPath(symlink.getAbstractPath<side>()))), statReporter); //throw X - AFS::removeSymlinkIfExists(symlink.getAbstractPath<side>()); //throw FileError - } - statReporter.reportDelta(1, 0); + removeSymlink(symlink.getAbstractPath<side>(), statReporter); //throw FileError, X }); fsObj->removeObject<side>(); //if directory: removes recursively! @@ -1483,8 +1506,8 @@ void fff::deleteFromGridAndHD(const std::vector<FileSystemObject*>& rowsToDelete ZEN_ON_SCOPE_EXIT(updateDirection()); //MSVC: assert is a macro and it doesn't play nice with ZEN_ON_SCOPE_EXIT, surprise... wasn't there something about macros being "evil"? bool recyclerMissingReportOnce = false; - deleteFromGridAndHDOneSide<SelectSide::left >(deleteLeft, moveToRecycler, recyclerMissingReportOnce, warnRecyclerMissing, callback); //throw X - deleteFromGridAndHDOneSide<SelectSide::right>(deleteRight, moveToRecycler, recyclerMissingReportOnce, warnRecyclerMissing, callback); // + deleteFromGridAndHdOneSide<SelectSide::left >(deleteLeft, moveToRecycler, recyclerMissingReportOnce, warnRecyclerMissing, callback); //throw X + deleteFromGridAndHdOneSide<SelectSide::right>(deleteRight, moveToRecycler, recyclerMissingReportOnce, warnRecyclerMissing, callback); // } //############################################################################################################ @@ -1520,7 +1543,7 @@ void fff::deleteListOfFiles(const std::vector<Zstring>& filesToDeletePaths, cb.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing); //throw X } cb.logMessage(replaceCpy(_("Deleting file %x"), L"%x", fmtPath(AFS::getDisplayPath(cfgPath))) + - L" [" + _("The recycle bin is not available") + L']', PhaseCallback::MsgType::warning); //throw X + L" [" + _("Recycle bin unavailable") + L']', PhaseCallback::MsgType::warning); //throw X AFS::removeFileIfExists(cfgPath); //throw FileError } else diff --git a/FreeFileSync/Source/base/comparison.cpp b/FreeFileSync/Source/base/comparison.cpp index 51ee0237..74035b80 100644 --- a/FreeFileSync/Source/base/comparison.cpp +++ b/FreeFileSync/Source/base/comparison.cpp @@ -72,7 +72,7 @@ struct ResolvedBaseFolders ResolvedBaseFolders initializeBaseFolders(const std::vector<FolderPairCfg>& fpCfgList, - bool allowUserInteraction, + const AFS::RequestPasswordFun& requestPassword /*throw X*/, WarningDialogs& warnings, PhaseCallback& callback /*throw X*/) //throw X { @@ -95,8 +95,8 @@ ResolvedBaseFolders initializeBaseFolders(const std::vector<FolderPairCfg>& fpCf allFolders.insert(output.resolvedPairs.back().folderPathRight); } //--------------------------------------------------------------------------- - output.baseFolderStatus = getFolderStatusNonBlocking(allFolders, - allowUserInteraction, callback); //throw X + output.baseFolderStatus = getFolderStatusParallel(allFolders, + true /*authenticateAccess*/, requestPassword, callback); //throw X if (!output.baseFolderStatus.failedChecks.empty()) { std::wstring msg = _("Cannot find the following folders:") + L'\n'; @@ -691,7 +691,7 @@ private: const Zstringc* checkFailedRead(FileSystemObject& fsObj, const Zstringc* errorMsg); const std::unordered_map<ZstringNoCase, Zstringc>& errorsByRelPath_; //base-relative paths or empty if read-error for whole base directory - std::vector<FilePair*>& undefinedFiles_; + std::vector<FilePair*>& undefinedFiles_; std::vector<SymlinkPair*>& undefinedSymlinks_; }; @@ -700,9 +700,10 @@ inline const Zstringc* MergeSides::checkFailedRead(FileSystemObject& fsObj, const Zstringc* errorMsg) { if (!errorMsg) - if (const auto it = errorsByRelPath_.find(fsObj.getRelativePathAny()); - it != errorsByRelPath_.end()) - errorMsg = &it->second; + if (!errorsByRelPath_.empty()) //only pay for ZstringNoCase construction when needed + if (const auto it = errorsByRelPath_.find(fsObj.getRelativePathAny()); + it != errorsByRelPath_.end()) + errorMsg = &it->second; if (errorMsg) { @@ -1027,7 +1028,7 @@ std::shared_ptr<BaseFolderPair> ComparisonBuffer::performComparison(const Resolv FolderComparison fff::compare(WarningDialogs& warnings, int fileTimeTolerance, - bool allowUserInteraction, + const AFS::RequestPasswordFun& requestPassword /*throw X*/, bool runWithBackgroundPriority, bool createDirLocks, std::unique_ptr<LockHolder>& dirLocks, @@ -1063,7 +1064,7 @@ FolderComparison fff::compare(WarningDialogs& warnings, } const ResolvedBaseFolders& resInfo = initializeBaseFolders(fpCfgList, - allowUserInteraction, warnings, callback); //throw X + requestPassword, warnings, callback); //throw X //directory existence only checked *once* to avoid race conditions! if (resInfo.resolvedPairs.size() != fpCfgList.size()) throw std::logic_error("Contract violation! " + std::string(__FILE__) + ':' + numberTo<std::string>(__LINE__)); @@ -1112,8 +1113,8 @@ FolderComparison fff::compare(WarningDialogs& warnings, } if (!msg.empty()) - callback.reportWarning(_("One base folder of a folder pair is contained in the other one.") + - (shouldExclude ? L'\n' + _("The folder should be excluded from synchronization via filter.") : L"") + + callback.reportWarning(_("One folder of the folder pair is a subfolder of the other.") + + (shouldExclude ? L'\n' + _("The folder should be excluded via filter.") : L"") + msg, warnings.warnDependentFolderPair); //throw X } //-------------------end of basic checks------------------------------------------ @@ -1123,7 +1124,6 @@ FolderComparison fff::compare(WarningDialogs& warnings, { std::set<Zstring> folderPathsToLock; for (const AbstractPath& folderPath : resInfo.baseFolderStatus.existing) - if (const Zstring& nativePath = getNativeItemPath(folderPath); //restrict directory locking to native paths until further !nativePath.empty()) folderPathsToLock.insert(nativePath); diff --git a/FreeFileSync/Source/base/comparison.h b/FreeFileSync/Source/base/comparison.h index b1faf023..cca22eb5 100644 --- a/FreeFileSync/Source/base/comparison.h +++ b/FreeFileSync/Source/base/comparison.h @@ -49,7 +49,7 @@ std::vector<FolderPairCfg> extractCompareCfg(const MainConfiguration& mainCfg); //FFS core routine: output.size() == fpCfgList.size() or 0 on fatal error FolderComparison compare(WarningDialogs& warnings, int fileTimeTolerance, - bool allowUserInteraction, + const AFS::RequestPasswordFun& requestPassword /*throw X*/, bool runWithBackgroundPriority, bool createDirLocks, std::unique_ptr<LockHolder>& dirLocks, //out diff --git a/FreeFileSync/Source/base/db_file.cpp b/FreeFileSync/Source/base/db_file.cpp index 2f8b1048..d0037dec 100644 --- a/FreeFileSync/Source/base/db_file.cpp +++ b/FreeFileSync/Source/base/db_file.cpp @@ -121,7 +121,7 @@ DbStreams loadStreams(const AbstractPath& dbPath, const IoCallback& notifyUnbuff catch (const FileError& e) { bool dbNotYetExisting = false; - try { dbNotYetExisting = !AFS::itemStillExists(dbPath); /*throw FileError*/ } + try { dbNotYetExisting = !AFS::itemExists(dbPath); /*throw FileError*/ } //abstract context => unclear which exception is more relevant/useless: catch (const FileError& e2) { throw FileError(replaceCpy(e.toString(), L"\n\n", L'\n'), replaceCpy(e2.toString(), L"\n\n", L'\n')); } //caveat: merging FileError might create redundant error message: https://freefilesync.org/forum/viewtopic.php?t=9377 @@ -805,11 +805,11 @@ std::unordered_map<const BaseFolderPair*, SharedRef<const InSyncFolder>> fff::lo std::map<AbstractPath, DbStreams> dbStreamsByPath; //------------ (try to) load DB files in parallel ------------------------- { - Protected<std::map<AbstractPath, DbStreams>&> dbStreamsByPathShared(dbStreamsByPath); + Protected<std::map<AbstractPath, DbStreams>&> protDbStreamsByPath(dbStreamsByPath); std::vector<std::pair<AbstractPath, ParallelWorkItem>> parallelWorkload; for (const AbstractPath& dbPath : dbFilePaths) - parallelWorkload.emplace_back(dbPath, [&dbStreamsByPathShared](ParallelContext& ctx) //throw ThreadStopRequest + parallelWorkload.emplace_back(dbPath, [&protDbStreamsByPath](ParallelContext& ctx) //throw ThreadStopRequest { tryReportingError([&] //throw ThreadStopRequest { @@ -818,7 +818,7 @@ std::unordered_map<const BaseFolderPair*, SharedRef<const InSyncFolder>> fff::lo { DbStreams dbStreams = ::loadStreams(ctx.itemPath, notifyLoad); //throw FileError, FileErrorDatabaseNotExisting, FileErrorDatabaseCorrupted, ThreadStopRequest - dbStreamsByPathShared.access([&](auto& dbStreamsByPath2) { dbStreamsByPath2.emplace(ctx.itemPath, std::move(dbStreams)); }); + protDbStreamsByPath.access([&](auto& dbStreamsByPath2) { dbStreamsByPath2.emplace(ctx.itemPath, std::move(dbStreams)); }); } catch (FileErrorDatabaseNotExisting&) {} //redundant info => no reportInfo() }, ctx.acb); @@ -1022,8 +1022,7 @@ void fff::saveLastSynchronousState(const BaseFolderPair& baseFolder, bool transa }); //---------------------------------------------------------------------------- if (transactionalCopy && !AFS::hasNativeTransactionalCopy(dbPath)) - parallelWorkloadMove.emplace_back(dbPath, [&dbPathTmp = *dbPathTmp, - transactionalCopy](ParallelContext& ctx) //throw ThreadStopRequest + parallelWorkloadMove.emplace_back(dbPath, [&dbPathTmp = *dbPathTmp](ParallelContext& ctx) //throw ThreadStopRequest { tryReportingError([&] //throw ThreadStopRequest { diff --git a/FreeFileSync/Source/base/dir_exist_async.h b/FreeFileSync/Source/base/dir_exist_async.h index b005dbed..a344cc06 100644 --- a/FreeFileSync/Source/base/dir_exist_async.h +++ b/FreeFileSync/Source/base/dir_exist_async.h @@ -8,30 +8,28 @@ #define DIR_EXIST_ASYNC_H_0817328167343215806734213 #include <zen/thread.h> -#include <zen/file_error.h> #include "process_callback.h" #include "../afs/abstract.h" namespace fff { -const int DEFAULT_FOLDER_ACCESS_TIME_OUT_SEC = 20; //consider CD-ROM insert or hard disk spin up time from sleep - namespace { -//directory existence checking may hang for non-existent network drives => run asynchronously and update UI! -//- check existence of all directories in parallel! (avoid adding up search times if multiple network drives are not reachable) -//- add reasonable time-out time! struct FolderStatus { std::set<AbstractPath> existing; std::set<AbstractPath> notExisting; std::map<AbstractPath, zen::FileError> failedChecks; }; - - -FolderStatus getFolderStatusNonBlocking(const std::set<AbstractPath>& folderPaths, - bool allowUserInteraction, PhaseCallback& procCallback /*throw X*/) +//- directory existence checking may hang for non-existent network drives => run asynchronously and update UI! +//- check existence of all directories in parallel! (avoid adding up search times if multiple network drives are not reachable) +//- authenticateAccess() better be integrated into folder existence check: if fails, why bother to go on with the folder!? +//- probably don't need timeout: https://freefilesync.org/forum/viewtopic.php?t=7350#p36817 +// => benefit: waits until user login completed in AFS::authenticateAccess() +FolderStatus getFolderStatusParallel(const std::set<AbstractPath>& folderPaths, + bool authenticateAccess, const AFS::RequestPasswordFun& requestPassword /*throw X*/, + PhaseCallback& cb /*throw X*/) //throw X { using namespace zen; @@ -41,79 +39,115 @@ FolderStatus getFolderStatusNonBlocking(const std::set<AbstractPath>& folderPath for (const AbstractPath& folderPath : folderPaths) if (!AFS::isNullPath(folderPath)) //skip empty folders perDevicePaths[folderPath.afsDevice].insert(folderPath); + //---------------------------------------------------------------------- - std::vector<std::pair<AbstractPath, std::future<bool>>> futureDetails; + std::vector<std::pair<AbstractPath, std::future<bool>>> futFoldersExist; - std::vector<ThreadGroup<std::packaged_task<bool()>>> perDeviceThreads; - for (const auto& [afsDevice, deviceFolderPaths] : perDevicePaths) + struct AsyncPrompt + { + std::wstring msg; + std::wstring lastErrorMsg; + std::promise<Zstring> promPassword; + }; + auto protPromptsPending = authenticateAccess && requestPassword ? std::make_shared<Protected<RingBuffer<AsyncPrompt>>>() : nullptr; + + //---------------------------------------------------------------------- + std::vector<ThreadGroup<std::packaged_task<bool()>>> deviceThreadGroups; + for (const auto& [device, deviceFolderPaths] : perDevicePaths) { - perDeviceThreads.emplace_back(1, Zstr("DirExist: ") + utfTo<Zstring>(AFS::getDisplayPath(AbstractPath(afsDevice, AfsPath())))); - auto& threadGroup = perDeviceThreads.back(); - threadGroup.detach(); //don't wait on threads hanging longer than "folderAccessTimeout" + deviceThreadGroups.emplace_back(1, Zstr("DirExist: ") + utfTo<Zstring>(AFS::getDisplayPath(AbstractPath(device, AfsPath())))); + deviceThreadGroups.back().detach(); //don't wait on hanging threads if user cancels //1. login to network share, connect with Google Drive, etc. - std::shared_future<void> ftAuth = runAsync([afsDevice /*clang bug*/= afsDevice, allowUserInteraction] - { AFS::authenticateAccess(afsDevice, allowUserInteraction); /*throw FileError*/ }); + std::shared_future<void> futAuth; + if (authenticateAccess) + { + AFS::RequestPasswordFun threadRequestPassword; //throw std::future_error + if (requestPassword) + threadRequestPassword = [promptsPendingWeak = std::weak_ptr(protPromptsPending)](const std::wstring& msg, const std::wstring& lastErrorMsg) + { + std::future<Zstring> futPassword; + if (auto protPromptsPending2 = promptsPendingWeak.lock()) //[!] not owned by worker thread! + protPromptsPending2->access([&](RingBuffer<AsyncPrompt>& promptsPending) + { + promptsPending.push_back(AsyncPrompt{msg, lastErrorMsg, {}}); + futPassword = promptsPending.back().promPassword.get_future(); + }); + return futPassword.get(); //throw std::future_error -> if std::promise<Zstring> destroyed before password was set + }; + + futAuth = runAsync([device /*clang bug*/= device, threadRequestPassword] + { + setCurrentThreadName(Zstr("Auth: ") + utfTo<Zstring>(AFS::getDisplayPath(AbstractPath(device, AfsPath())))); + AFS::authenticateAccess(device, threadRequestPassword); //throw FileError, std::future_error + }); + } for (const AbstractPath& folderPath : deviceFolderPaths) { - std::packaged_task<bool()> pt([folderPath, ftAuth] + std::packaged_task<bool()> pt([folderPath, futAuth] { - ftAuth.get(); //throw FileError + if (futAuth.valid()) + futAuth.get(); //throw FileError, std::future_error /* 2. check dir existence: - CAVEAT: the case-sensitive semantics of AFS::itemStillExists() do not fit here! + CAVEAT: the case-sensitive semantics of AFS::itemExists() do not fit here! BUT: its implementation happens to be okay for our use: Assume we have a case-insensitive path match: - => AFS::itemStillExists() first checks AFS::getItemType() + => AFS::itemExists() first checks AFS::getItemType() => either succeeds (fine) or fails because of 1. not existing or 2. access error => if the subsequent case-sensitive folder search also doesn't find the folder: only a problem in case 2 => FFS tries to create the folder during sync and fails with I. access error (fine) or II. already existing (obscures the previous "access error") */ - return static_cast<bool>(AFS::itemStillExists(folderPath)); //throw FileError - //consider ItemType::file a failure instead? Meanwhile: return "false" IFF nothing (of any type) exists + return AFS::itemExists(folderPath); //throw FileError; return "false" IFF nothing (of any type) exists + + //check for ItemType::file? too pedantic? + // throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(getDisplayPath(folderPath))), + // replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(getItemName(folderPath)))); }); - auto ftIsExisting = pt.get_future(); - threadGroup.run(std::move(pt)); + auto futIsExisting = pt.get_future(); + deviceThreadGroups.back().run(std::move(pt)); - futureDetails.emplace_back(folderPath, std::move(ftIsExisting)); + futFoldersExist.emplace_back(folderPath, std::move(futIsExisting)); } } - - //don't wait (almost) endlessly like Win32 would on non-existing network shares: - const auto startTime = std::chrono::steady_clock::now(); + //---------------------------------------------------------------------- FolderStatus output; - for (auto& [folderPath, ftIsExisting] : futureDetails) + for (auto& [folderPath, futFolderExists] : futFoldersExist) { - const std::wstring& displayPathFmt = fmtPath(AFS::getDisplayPath(folderPath)); - - procCallback.updateStatus(replaceCpy(_("Searching for folder %x..."), L"%x", displayPathFmt)); //throw X + cb.updateStatus(replaceCpy(_("Searching for folder %x..."), L"%x", fmtPath(AFS::getDisplayPath(folderPath)))); //throw X - int deviceTimeOutSec = AFS::getAccessTimeout(folderPath); //0 if no timeout in force - if (deviceTimeOutSec <= 0) - deviceTimeOutSec = DEFAULT_FOLDER_ACCESS_TIME_OUT_SEC; - - const auto timeoutTime = startTime + std::chrono::seconds(deviceTimeOutSec); - - while (std::chrono::steady_clock::now() < timeoutTime && - ftIsExisting.wait_for(UI_UPDATE_INTERVAL / 2) == std::future_status::timeout) - procCallback.requestUiUpdate(); //throw X + while (futFolderExists.wait_for(UI_UPDATE_INTERVAL / 2) == std::future_status::timeout) + { + cb.requestUiUpdate(); //throw X - if (!isReady(ftIsExisting)) - output.failedChecks.emplace(folderPath, FileError(replaceCpy(_("Timeout while searching for folder %x."), L"%x", displayPathFmt) + - L" [" + _P("1 sec", "%x sec", deviceTimeOutSec) + L']')); - else - try + //marshal password prompt callback from current thread (probably main) to worker threads + //=> polling delay doesn't matter because user interaction is required + if (protPromptsPending) + protPromptsPending->access([&](RingBuffer<AsyncPrompt>& promptsPending) { - //call future::get() only *once*! otherwise: undefined behavior! - if (ftIsExisting.get()) //throw FileError - output.existing.insert(folderPath); - else - output.notExisting.insert(folderPath); - } - catch (const FileError& e) { output.failedChecks.emplace(folderPath, e); } + //do work while holding Protected<> lock!? device authentication threads blocking doesn't matter because prompts are serialized to GUI anyway + if (!promptsPending.empty()) + { + assert(requestPassword); //... in this context + const Zstring password = requestPassword(promptsPending.front().msg, promptsPending.front().lastErrorMsg); //throw X + promptsPending.front().promPassword.set_value(password); + promptsPending.pop_front(); + } + }); + } + + try + { + //call future::get() only *once*! otherwise: undefined behavior! + if (futFolderExists.get()) //throw FileError, (std::future_error) + output.existing.insert(folderPath); + else + output.notExisting.insert(folderPath); + } + catch (const FileError& e) { output.failedChecks.emplace(folderPath, e); } } return output; } diff --git a/FreeFileSync/Source/base/dir_lock.cpp b/FreeFileSync/Source/base/dir_lock.cpp index 41b1e908..0ab22486 100644 --- a/FreeFileSync/Source/base/dir_lock.cpp +++ b/FreeFileSync/Source/base/dir_lock.cpp @@ -331,7 +331,7 @@ void waitOnDirLock(const Zstring& lockFilePath, const DirLockCallback& notifySta { const LockInformation& lockInfo = retrieveLockInfo(lockFilePath); //throw FileError - infoMsg += SPACED_DASH + _("User name:") + L' ' + utfTo<std::wstring>(lockInfo.userId); + infoMsg += SPACED_DASH + _("Username:") + L' ' + utfTo<std::wstring>(lockInfo.userId); originalLockId = lockInfo.lockId; switch (getProcessStatus(lockInfo)) //throw FileError diff --git a/FreeFileSync/Source/base/file_hierarchy.cpp b/FreeFileSync/Source/base/file_hierarchy.cpp index 57102e98..e3ed5c88 100644 --- a/FreeFileSync/Source/base/file_hierarchy.cpp +++ b/FreeFileSync/Source/base/file_hierarchy.cpp @@ -494,8 +494,8 @@ std::wstring fff::getSyncOpDescription(const FileSystemObject& fsObj) (beforeLast(relPathFrom, FILE_NAME_SEPARATOR, IfNotFoundReturn::none) == beforeLast(relPathTo, FILE_NAME_SEPARATOR, IfNotFoundReturn::none) ? //detected pure "rename" - fmtPath(afterLast(relPathFrom, FILE_NAME_SEPARATOR, IfNotFoundReturn::all)) + L' ' + arrowRight + L'\n' + //show short name only - fmtPath(afterLast(relPathTo, FILE_NAME_SEPARATOR, IfNotFoundReturn::all)) : + fmtPath(getItemName(relPathFrom)) + L' ' + arrowRight + L'\n' + //show short name only + fmtPath(getItemName(relPathTo)) : //"move" or "move + rename" fmtPath(relPathFrom) + L' ' + arrowRight + L'\n' + fmtPath(relPathTo)) /*+ footer -> redundant */; diff --git a/FreeFileSync/Source/base/status_handler_impl.h b/FreeFileSync/Source/base/status_handler_impl.h index 88ee5e12..0504e649 100644 --- a/FreeFileSync/Source/base/status_handler_impl.h +++ b/FreeFileSync/Source/base/status_handler_impl.h @@ -449,7 +449,7 @@ private: { const double totalSecs = numeric::isNull(bytesPerSec) ? 0 : bytesTotal / bytesPerSec; const double expectedSteps = totalSecs * STATUS_PERCENT_MIN_CHANGES_PER_SEC; - + const int decPlaces = [&] //TODO? protect against format flickering!? { if (expectedSteps <= 100) return 0; diff --git a/FreeFileSync/Source/base/synchronization.cpp b/FreeFileSync/Source/base/synchronization.cpp index cc71e7df..982fcf15 100644 --- a/FreeFileSync/Source/base/synchronization.cpp +++ b/FreeFileSync/Source/base/synchronization.cpp @@ -12,7 +12,7 @@ #include <zen/crc.h> #include "algorithm.h" #include "db_file.h" -#include "dir_exist_async.h" +//#include "dir_exist_async.h" #include "status_handler_impl.h" #include "versioning.h" #include "binary.h" @@ -478,7 +478,7 @@ std::weak_ordering comparePathNoCase(const PathRaceItem& lhs, const PathRaceItem cmp != std::weak_ordering::equivalent) return cmp; - return compareNoCase(itemPathL.afsPath.value, + return compareNoCase(itemPathL.afsPath.value, //no hashing: want natural sort order! itemPathR.afsPath.value); } @@ -571,7 +571,7 @@ private: template <SelectSide sideL, SelectSide sideR> -std::weak_ordering compareHashedPath(const ChildPathRef& lhs, const ChildPathRef& rhs) +std::weak_ordering compareHashedPathNoCase(const ChildPathRef& lhs, const ChildPathRef& rhs) { assert(lhs.fsObj->getAbstractPath<sideL>().afsDevice == rhs.fsObj->getAbstractPath<sideR>().afsDevice); @@ -590,7 +590,7 @@ void sortAndRemoveDuplicates(std::vector<ChildPathRef>& pathRefs) { std::sort(pathRefs.begin(), pathRefs.end(), [](const ChildPathRef& lhs, const ChildPathRef& rhs) { - if (const std::weak_ordering cmp = compareHashedPath<side, side>(lhs, rhs); + if (const std::weak_ordering cmp = compareHashedPathNoCase<side, side>(lhs, rhs); cmp != std::weak_ordering::equivalent) return cmp < 0; @@ -600,7 +600,7 @@ void sortAndRemoveDuplicates(std::vector<ChildPathRef>& pathRefs) }); pathRefs.erase(std::unique(pathRefs.begin(), pathRefs.end(), - [](const ChildPathRef& lhs, const ChildPathRef& rhs) { return compareHashedPath<side, side>(lhs, rhs) == std::weak_ordering::equivalent; }), + [](const ChildPathRef& lhs, const ChildPathRef& rhs) { return compareHashedPathNoCase<side, side>(lhs, rhs) == std::weak_ordering::equivalent; }), pathRefs.end()); //let's not use removeDuplicates(): we rely too much on implementation details! @@ -653,7 +653,7 @@ void checkPathRaceCondition(const BaseFolderPair& baseFolderP, const BaseFolderP std::vector<ChildPathRef> pathRefsC = GetChildItemsHashed<sideC>::execute(baseFolderC); //--------------------------------------------------------------------------------------------------- - //use case-sensitive comparison because items were scanned by FFS (=> no messy user input)? + //case-sensitive comparison because items were scanned by FFS (=> no messy user input)? //not good enough! E.g. not-yet-existing files are set to be created with different case! // + (weird) a file and a folder are set to be created with same name // => (throw hands in the air) fine, check path only and don't consider case @@ -668,11 +668,11 @@ void checkPathRaceCondition(const BaseFolderPair& baseFolderP, const BaseFolderP if (plannedWriteAccess<sideP>(*lhs.fsObj) || plannedWriteAccess<sideC>(*rhs.fsObj)) { - pathRaceItems.emplace_back(lhs.fsObj, sideP); - pathRaceItems.emplace_back(rhs.fsObj, sideC); + pathRaceItems.push_back({lhs.fsObj, sideP}); + pathRaceItems.push_back({rhs.fsObj, sideC}); } }, - [](const ChildPathRef&) {} /*right only*/, compareHashedPath<sideP, sideC>); + [](const ChildPathRef&) {} /*right only*/, compareHashedPathNoCase<sideP, sideC>); } } } @@ -731,8 +731,8 @@ AFS::ItemType getItemType(const AbstractPath& itemPath, std::mutex& singleThread { return parallelScope([itemPath] { return AFS::getItemType(itemPath); /*throw FileError*/ }, singleThread); } inline -std::optional<AFS::ItemType> itemStillExists(const AbstractPath& itemPath, std::mutex& singleThread) //throw FileError -{ return parallelScope([itemPath] { return AFS::itemStillExists(itemPath); /*throw FileError*/ }, singleThread); } +bool itemExists(const AbstractPath& itemPath, std::mutex& singleThread) //throw FileError +{ return parallelScope([itemPath] { return AFS::itemExists(itemPath); /*throw FileError*/ }, singleThread); } inline void removeFileIfExists(const AbstractPath& filePath, std::mutex& singleThread) //throw FileError @@ -767,10 +767,14 @@ void removeFilePlain(const AbstractPath& filePath, std::mutex& singleThread) //t //-------------------------------------------------------------- inline void removeFolderIfExistsRecursion(const AbstractPath& folderPath, //throw FileError - const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion, //optional - const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion, //one call for each object! + const std::function<void(const std::wstring& displayPath)>& onBeforeFileDeletion /*throw X*/, // + const std::function<void(const std::wstring& displayPath)>& onBeforeSymlinkDeletion /*throw X*/, //optional + const std::function<void(const std::wstring& displayPath)>& onBeforeFolderDeletion /*throw X*/, // std::mutex& singleThread) -{ parallelScope([folderPath, onBeforeFileDeletion, onBeforeFolderDeletion] { AFS::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeFolderDeletion); /*throw FileError*/ }, singleThread); } +{ + parallelScope([folderPath, onBeforeFileDeletion, onBeforeSymlinkDeletion, onBeforeFolderDeletion] + { AFS::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeSymlinkDeletion, onBeforeFolderDeletion); /*throw FileError*/ }, singleThread); +} inline @@ -983,7 +987,7 @@ void DeletionHandler::removeFileWithCallback(const FileDescriptor& fileDescr, co statReporter.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing_); //throw ThreadStopRequest } if (!beforeOverwrite) statReporter.logMessage(replaceCpy(txtDelFilePermanent_, L"%x", fmtPath(AFS::getDisplayPath(fileDescr.path))) + - L" [" + _("The recycle bin is not available") + L']', PhaseCallback::MsgType::warning); //throw ThreadStopRequest + L" [" + _("Recycle bin unavailable") + L']', PhaseCallback::MsgType::warning); //throw ThreadStopRequest parallel::removeFileIfExists(fileDescr.path, singleThread); //throw FileError } break; @@ -1041,7 +1045,7 @@ void DeletionHandler::removeLinkWithCallback(const AbstractPath& linkPath, const statReporter.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing_); //throw ThreadStopRequest } if (!beforeOverwrite) statReporter.logMessage(replaceCpy(txtDelSymlinkPermanent_, L"%x", fmtPath(AFS::getDisplayPath(linkPath))) + - L" [" + _("The recycle bin is not available") + L']', PhaseCallback::MsgType::warning); //throw ThreadStopRequest + L" [" + _("Recycle bin unavailable") + L']', PhaseCallback::MsgType::warning); //throw ThreadStopRequest parallel::removeSymlinkIfExists(linkPath, singleThread); //throw FileError } break; @@ -1064,16 +1068,17 @@ void DeletionHandler::removeDirWithCallback(const AbstractPath& folderPath, cons auto removeFolderPermanently = [&] { //callbacks run *outside* singleThread_ lock! => fine - auto notifyDeletion = [&statReporter](const std::wstring& statusText, const std::wstring& displayPath) + auto onBeforeDeletion = [&statReporter](const std::wstring& statusText, const std::wstring& displayPath) { statReporter.updateStatus(replaceCpy(statusText, L"%x", fmtPath(displayPath))); //throw ThreadStopRequest statReporter.reportDelta(1, 0); //it would be more correct to report *after* work was done! }; static_assert(std::is_const_v<decltype(txtDelFilePermanent_)>, "callbacks better be thread-safe!"); - auto onBeforeFileDeletion = [&](const std::wstring& displayPath) { notifyDeletion(txtDelFilePermanent_, displayPath); }; - auto onBeforeDirDeletion = [&](const std::wstring& displayPath) { notifyDeletion(txtDelFolderPermanent_, displayPath); }; - parallel::removeFolderIfExistsRecursion(folderPath, onBeforeFileDeletion, onBeforeDirDeletion, singleThread); //throw FileError + parallel::removeFolderIfExistsRecursion(folderPath, + [&](const std::wstring& displayPath) { onBeforeDeletion(txtDelFilePermanent_, displayPath); }, + [&](const std::wstring& displayPath) { onBeforeDeletion(txtDelSymlinkPermanent_, displayPath); }, + [&](const std::wstring& displayPath) { onBeforeDeletion(txtDelFolderPermanent_, displayPath); }, singleThread); //throw FileError, ThreadStopRequest }; switch (deletionVariant_) @@ -1100,7 +1105,7 @@ void DeletionHandler::removeDirWithCallback(const AbstractPath& folderPath, cons statReporter.reportWarning(e.toString() + L"\n\n" + _("Ignore and delete permanently each time recycle bin is unavailable?"), warnRecyclerMissing_); //throw ThreadStopRequest } statReporter.logMessage(replaceCpy(txtDelFolderPermanent_, L"%x", fmtPath(AFS::getDisplayPath(folderPath))) + - L" [" + _("The recycle bin is not available") + L']', PhaseCallback::MsgType::warning); //throw ThreadStopRequest + L" [" + _("Recycle bin unavailable") + L']', PhaseCallback::MsgType::warning); //throw ThreadStopRequest removeFolderPermanently(); //throw FileError, ThreadStopRequest } break; @@ -1832,7 +1837,7 @@ void FolderPairSyncer::synchronizeFileInt(FilePair& file, SyncOperation syncOp) catch (const FileError& e) { bool sourceExists = true; - try { sourceExists = !!parallel::itemStillExists(file.getAbstractPath<sideSrc>(), singleThread_); /*throw FileError*/ } + try { sourceExists = parallel::itemExists(file.getAbstractPath<sideSrc>(), singleThread_); /*throw FileError*/ } //abstract context => unclear which exception is more relevant/useless: //e could be "item not found": doh; e2 devoid of any details after SFTP error: https://freefilesync.org/forum/viewtopic.php?t=7138#p24064 catch (const FileError& e2) { throw FileError(replaceCpy(e.toString(), L"\n\n", L'\n'), replaceCpy(e2.toString(), L"\n\n", L'\n')); } @@ -1858,8 +1863,13 @@ void FolderPairSyncer::synchronizeFileInt(FilePair& file, SyncOperation syncOp) { AsyncItemStatReporter statReporter(1, 0, acb_); - delHandlerTrg.removeFileWithCallback({file.getAbstractPath<sideTrg>(), file.getAttributes<sideTrg>()}, file.getRelativePath<sideTrg>(), - false /*beforeOverwrite*/, statReporter, singleThread_); //throw FileError, ThreadStopRequest + if (file.isFollowedSymlink<sideTrg>()) + delHandlerTrg.removeLinkWithCallback(file.getAbstractPath<sideTrg>(), file.getRelativePath<sideTrg>(), + false /*beforeOverwrite*/, statReporter, singleThread_); //throw FileError, ThreadStopRequest + else + delHandlerTrg.removeFileWithCallback({file.getAbstractPath<sideTrg>(), file.getAttributes<sideTrg>()}, file.getRelativePath<sideTrg>(), + false /*beforeOverwrite*/, statReporter, singleThread_); //throw FileError, ThreadStopRequest + file.removeObject<sideTrg>(); //update FilePair } break; @@ -1929,7 +1939,11 @@ void FolderPairSyncer::synchronizeFileInt(FilePair& file, SyncOperation syncOp) FileAttributes followedTargetAttr = file.getAttributes<sideTrg>(); followedTargetAttr.isFollowedSymlink = false; - delHandlerTrg.removeFileWithCallback({targetPathResolvedOld, followedTargetAttr}, file.getRelativePath<sideTrg>(), + if (file.isFollowedSymlink<sideTrg>()) + delHandlerTrg.removeLinkWithCallback(targetPathResolvedOld, file.getRelativePath<sideTrg>(), + true /*beforeOverwrite*/, statReporter, singleThread_); //throw FileError, ThreadStopRequest + else + delHandlerTrg.removeFileWithCallback({targetPathResolvedOld, followedTargetAttr}, file.getRelativePath<sideTrg>(), true /*beforeOverwrite*/, statReporter, singleThread_); //throw FileError, ThreadStopRequest //file.removeObject<sideTrg>(); -> doesn't make sense for isFollowedSymlink(); "file, sideTrg" evaluated below! @@ -2054,7 +2068,7 @@ void FolderPairSyncer::synchronizeLinkInt(SymlinkPair& symlink, SyncOperation sy catch (const FileError& e) { bool sourceExists = true; - try { sourceExists = !!parallel::itemStillExists(symlink.getAbstractPath<sideSrc>(), singleThread_); /*throw FileError*/ } + try { sourceExists = parallel::itemExists(symlink.getAbstractPath<sideSrc>(), singleThread_); /*throw FileError*/ } //abstract context => unclear which exception is more relevant/useless: catch (const FileError& e2) { throw FileError(replaceCpy(e.toString(), L"\n\n", L'\n'), replaceCpy(e2.toString(), L"\n\n", L'\n')); } @@ -2186,7 +2200,7 @@ void FolderPairSyncer::synchronizeFolderInt(FolderPair& folder, SyncOperation sy reportItemInfo(txtCreatingFolder_, targetPath); //throw ThreadStopRequest //shallow-"copying" a folder might not fail if source is missing, so we need to check this first: - if (parallel::itemStillExists(folder.getAbstractPath<sideSrc>(), singleThread_)) //throw FileError + if (parallel::itemExists(folder.getAbstractPath<sideSrc>(), singleThread_)) //throw FileError { AsyncItemStatReporter statReporter(1, 0, acb_); try @@ -2235,7 +2249,12 @@ void FolderPairSyncer::synchronizeFolderInt(FolderPair& folder, SyncOperation sy const SyncStatistics subStats(folder); //counts sub-objects only! AsyncItemStatReporter statReporter(1 + getCUD(subStats), subStats.getBytesToProcess(), acb_); - delHandlerTrg.removeDirWithCallback(folder.getAbstractPath<sideTrg>(), folder.getRelativePath<sideTrg>(), statReporter, singleThread_); //throw FileError, ThreadStopRequest + if (folder.isFollowedSymlink<sideTrg>()) + delHandlerTrg.removeLinkWithCallback(folder.getAbstractPath<sideTrg>(), folder.getRelativePath<sideTrg>(), + false /*beforeOverwrite*/, statReporter, singleThread_); //throw FileError, ThreadStopRequest + else + delHandlerTrg.removeDirWithCallback(folder.getAbstractPath<sideTrg>(), folder.getRelativePath<sideTrg>(), + statReporter, singleThread_); //throw FileError, ThreadStopRequest //TODO: implement parallel folder deletion @@ -2348,43 +2367,29 @@ bool checkBaseFolderStatus(BaseFolderPair& baseFolder, PhaseCallback& callback / { const AbstractPath folderPath = baseFolder.getAbstractPath<side>(); - if (baseFolder.getFolderStatus<side>() == BaseFolderStatus::failure) - { - //e.g. TEMPORARY network drop! base directory not found during comparison - //=> sync-directions are based on false assumptions! Abort. - callback.reportFatalError(replaceCpy(_("Skipping folder pair because %x could not be accessed during comparison."), - L"%x", fmtPath(AFS::getDisplayPath(folderPath)))); //throw X - return false; - } - - bool folderExisting = false; - - const std::wstring errMsg = tryReportingError([&] - { - const FolderStatus status = getFolderStatusNonBlocking({folderPath}, - false /*allowUserInteraction*/, callback); - - static_assert(std::is_same_v<decltype(status.failedChecks.begin()->second), FileError>); - if (!status.failedChecks.empty()) - throw status.failedChecks.begin()->second; //throw FileError - - folderExisting = status.existing.contains(folderPath); - }, callback); //throw X - if (!errMsg.empty()) - return false; - - switch (baseFolder.getFolderStatus<side>()) { case BaseFolderStatus::existing: - if (!folderExisting) + { + const std::wstring errMsg = tryReportingError([&] { - callback.reportFatalError(replaceCpy(_("Cannot find folder %x."), L"%x", fmtPath(AFS::getDisplayPath(folderPath)))); //throw X + AFS::getItemType(folderPath); //throw FileError + }, callback); //throw X + if (!errMsg.empty()) return false; - } - break; + } + break; case BaseFolderStatus::notExisting: + { + bool folderExisting = false; + + const std::wstring errMsg = tryReportingError([&] + { + folderExisting = AFS::itemExists(folderPath); //throw FileError + }, callback); //throw X + if (!errMsg.empty()) + return false; if (folderExisting) //=> somebody else created it: problem? { /* Is it possible we're catching a "false positive" here, could FFS have created the directory indirectly after comparison? @@ -2392,15 +2397,19 @@ bool checkBaseFolderStatus(BaseFolderPair& baseFolder, PhaseCallback& callback / 2. deletion handling: versioning -> " 3. log file creates containing folder -> no, log only created in batch mode, and only *before* comparison 4. yes, could be us! e.g. multiple folder pairs to non-yet-existing target folder => too obscure!? */ - callback.reportFatalError(replaceCpy(_("Base folder %x is already existing, but was not found earlier during comparison."), + callback.reportFatalError(replaceCpy(_("The folder %x is already existing, but was not found earlier during comparison."), L"%x", fmtPath(AFS::getDisplayPath(folderPath)))); //throw X return false; } - break; + } + break; case BaseFolderStatus::failure: - assert(false); //already handled above - break; + //e.g. TEMPORARY network drop! base directory not found during comparison + //=> sync-directions are based on false assumptions! Abort. + callback.reportFatalError(replaceCpy(_("Skipping folder pair because %x could not be accessed during comparison."), + L"%x", fmtPath(AFS::getDisplayPath(folderPath)))); //throw X + return false; } return true; } @@ -2625,8 +2634,7 @@ void fff::synchronize(const std::chrono::system_clock::time_point& syncStartTime if (folderPairCfg.handleDeletion == DeletionVariant::versioning) if (AFS::isNullPath(versioningFolderPath)) { - //should never arrive here: already checked in SyncCfgDialog - callback.reportFatalError(_("Please enter a target folder for versioning.")); + callback.reportFatalError(_("Please enter a target folder.")); //user should never see this: already checked in SyncCfgDialog skipFolderPair[folderIndex] = true; continue; } @@ -2781,8 +2789,8 @@ break2: if (!pathRaceItems.empty()) { - std::wstring msg = _("Some files will be synchronized as part of multiple base folders.") + L'\n' + - _("To avoid conflicts, set up exclude filters so that each updated file is included by only one base folder.") + L"\n\n"; + std::wstring msg = _("Some files will be synchronized as part of multiple folder pairs.") + L'\n' + + _("To avoid conflicts, set up exclude filters so that each updated file is included by only one folder pair.") + L"\n\n"; auto prevItem = pathRaceItems[0]; std::for_each(pathRaceItems.begin(), pathRaceItems.begin() + std::min(pathRaceItems.size(), CONFLICTS_PREVIEW_MAX), [&](const PathRaceItem& item) @@ -2804,7 +2812,7 @@ break2: } } - //check if versioning path itself will be synchronized (and was not excluded via filter) + //check if versioning folder itself will be synchronized (and was not excluded via filter) { std::wstring msg; bool shouldExclude = false; @@ -2819,7 +2827,7 @@ break2: inserted) { msg += L"\n\n" + - _("Base folder:") + L" \t" + AFS::getDisplayPath(folderPath) + L'\n' + + _("Selected folder:") + L" \t" + AFS::getDisplayPath(folderPath) + L'\n' + _("Versioning folder:") + L" \t" + AFS::getDisplayPath(versioningFolderPath); if (pd->folderPathParent == folderPath) //else: probably fine? :> if (!pd->relPath.empty()) @@ -2832,8 +2840,8 @@ break2: } } if (!msg.empty()) - callback.reportWarning(_("The versioning folder is contained in a base folder.") + - (shouldExclude ? L'\n' + _("The folder should be excluded from synchronization via filter.") : L"") + + callback.reportWarning(_("The versioning folder is part of the synchronization.") + + (shouldExclude ? L' ' + _("The folder should be excluded via filter.") : L"") + msg, warnings.warnVersioningFolderPartOfSync); //throw X } diff --git a/FreeFileSync/Source/base/versioning.cpp b/FreeFileSync/Source/base/versioning.cpp index 0a82c153..63af2cbb 100644 --- a/FreeFileSync/Source/base/versioning.cpp +++ b/FreeFileSync/Source/base/versioning.cpp @@ -89,8 +89,8 @@ AbstractPath FileVersioner::generateVersionedPath(const Zstring& relativePath) c break; case VersioningStyle::timestampFile: //assemble time-stamped version name versionedRelPath = relativePath + Zstr(' ') + timeStamp_ + getDotExtension(relativePath); - assert(impl::parseVersionedFileName(afterLast(versionedRelPath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all)) == - std::pair(syncStartTime_, afterLast(relativePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all))); + assert(impl::parseVersionedFileName(getItemName(versionedRelPath)) == + std::pair(syncStartTime_, getItemName(relativePath))); (void)syncStartTime_; //clang: -Wunused-private-field break; } @@ -125,7 +125,7 @@ void moveExistingItemToVersioning(const AbstractPath& sourcePath, const Abstract } catch (FileError&) {} //=> not yet existing (=> fine, no path issue) or access error: //- let's pretend it doesn't happen :> if it does, worst case: the retry fails with (useless) already existing error - //- AFS::itemStillExists()? too expensive, considering that "already existing" is the most common case + //- AFS::itemExists()? too expensive, considering that "already existing" is the most common case if (alreadyExisting) { @@ -183,8 +183,11 @@ void moveExistingItemToVersioning(const AbstractPath& sourcePath, const Abstract void FileVersioner::revisionFile(const FileDescriptor& fileDescr, const Zstring& relativePath, const IoCallback& notifyUnbufferedIO /*throw X*/) const //throw FileError, X { - if (std::optional<AFS::ItemType> type = AFS::itemStillExists(fileDescr.path)) //throw FileError + const std::variant<AFS::ItemType, AfsPath /*last existing parent path*/> typeOrPath = AFS::getItemTypeIfExists(fileDescr.path); //throw FileError + if (const AFS::ItemType* type = std::get_if<AFS::ItemType>(&typeOrPath)) { + assert(*type != AFS::ItemType::symlink); + if (*type == AFS::ItemType::symlink) revisionSymlinkImpl(fileDescr.path, relativePath, nullptr /*onBeforeMove*/); //throw FileError else @@ -222,7 +225,7 @@ void FileVersioner::revisionFileImpl(const FileDescriptor& fileDescr, const Zstr void FileVersioner::revisionSymlink(const AbstractPath& linkPath, const Zstring& relativePath) const //throw FileError { - if (AFS::itemStillExists(linkPath)) //throw FileError + if (AFS::itemExists(linkPath)) //throw FileError revisionSymlinkImpl(linkPath, relativePath, nullptr /*onBeforeMove*/); //throw FileError //else -> missing source item is not an error => check BEFORE deleting target } @@ -247,14 +250,17 @@ void FileVersioner::revisionFolder(const AbstractPath& folderPath, const Zstring const IoCallback& notifyUnbufferedIO /*throw X*/) const { //no error situation if directory is not existing! manual deletion relies on it! - if (std::optional<AFS::ItemType> type = AFS::itemStillExists(folderPath)) //throw FileError + const std::variant<AFS::ItemType, AfsPath /*last existing parent path*/> typeOrPath = AFS::getItemTypeIfExists(folderPath); //throw FileError + if (const AFS::ItemType* type = std::get_if<AFS::ItemType>(&typeOrPath)) { + assert(*type != AFS::ItemType::symlink); + if (*type == AFS::ItemType::symlink) //on Linux there is just one type of symlink, and since we do revision file symlinks, we should revision dir symlinks as well! revisionSymlinkImpl(folderPath, relativePath, onBeforeFileMove); //throw FileError else revisionFolderImpl(folderPath, relativePath, onBeforeFileMove, onBeforeFolderMove, notifyUnbufferedIO); //throw FileError, X } - else //even if the folder did not exist anymore, significant I/O work was done => report + else //even if the folder does not exist anymore, significant I/O work was done => report if (onBeforeFolderMove) onBeforeFolderMove(AFS::getDisplayPath(folderPath), AFS::getDisplayPath(AFS::appendRelPath(versioningFolderPath_, relativePath))); } @@ -266,26 +272,28 @@ void FileVersioner::revisionFolderImpl(const AbstractPath& folderPath, const Zst { //create target directories only when needed in moveFileToVersioning(): avoid empty directories! - std::vector<AFS::FileInfo> files; - std::vector<AFS::FolderInfo> folders; - std::vector<AFS::SymlinkInfo> symlinks; + std::vector<AFS::FolderInfo> folders; + { + std::vector<AFS::FileInfo> files; + std::vector<AFS::SymlinkInfo> symlinks; - AFS::traverseFolderFlat(folderPath, //throw FileError - [&](const AFS::FileInfo& fi) { files .push_back(fi); assert(!files.back().isFollowedSymlink); }, - [&](const AFS::FolderInfo& fi) { folders .push_back(fi); }, - [&](const AFS::SymlinkInfo& si) { symlinks.push_back(si); }); + AFS::traverseFolder(folderPath, //throw FileError + [&](const AFS::FileInfo& fi) { files .push_back(fi); assert(!files.back().isFollowedSymlink); }, + [&](const AFS::FolderInfo& fi) { folders .push_back(fi); }, + [&](const AFS::SymlinkInfo& si) { symlinks.push_back(si); }); - for (const AFS::FileInfo& fileInfo : files) - { - const FileDescriptor fileDescr{AFS::appendRelPath(folderPath, fileInfo.itemName), - FileAttributes(fileInfo.modTime, fileInfo.fileSize, fileInfo.filePrint, false /*isFollowedSymlink*/)}; + for (const AFS::FileInfo& fileInfo : files) + { + const FileDescriptor fileDescr{AFS::appendRelPath(folderPath, fileInfo.itemName), + FileAttributes(fileInfo.modTime, fileInfo.fileSize, fileInfo.filePrint, false /*isFollowedSymlink*/)}; - revisionFileImpl(fileDescr, appendPath(relPath, fileInfo.itemName), onBeforeFileMove, notifyUnbufferedIO); //throw FileError, X - } + revisionFileImpl(fileDescr, appendPath(relPath, fileInfo.itemName), onBeforeFileMove, notifyUnbufferedIO); //throw FileError, X + } - for (const AFS::SymlinkInfo& linkInfo : symlinks) - revisionSymlinkImpl(AFS::appendRelPath(folderPath, linkInfo.itemName), - appendPath(relPath, linkInfo.itemName), onBeforeFileMove); //throw FileError + for (const AFS::SymlinkInfo& linkInfo : symlinks) + revisionSymlinkImpl(AFS::appendRelPath(folderPath, linkInfo.itemName), + appendPath(relPath, linkInfo.itemName), onBeforeFileMove); //throw FileError + } //move folders recursively for (const AFS::FolderInfo& folderInfo : folders) @@ -419,8 +427,8 @@ void fff::applyVersioningLimit(const std::set<VersioningLimitFolder>& folderLimi //we don't want to show an error if version path does not yet exist! tryReportingError([&] { - const FolderStatus status = getFolderStatusNonBlocking(pathsToCheck, - false /*allowUserInteraction*/, callback); //throw X + const FolderStatus status = getFolderStatusParallel(pathsToCheck, + false /*authenticateAccess*/, nullptr /*requestPassword*/, callback); //throw X foldersToRead.clear(); for (const AbstractPath& folderPath : status.existing) foldersToRead.insert(DirectoryKey({folderPath, makeSharedRef<NullFilter>(), SymLinkHandling::asLink})); @@ -527,12 +535,12 @@ void fff::applyVersioningLimit(const std::set<VersioningLimitFolder>& folderLimi } //--------- remove excess file versions --------- - Protected<std::map<AbstractPath, size_t>&> folderItemCountShared(folderItemCount); + Protected<std::map<AbstractPath, size_t>&> protFolderItemCount(folderItemCount); const std::wstring txtRemoving = _("Removing old file versions:") + L' '; const std::wstring txtDeletingFolder = _("Deleting folder %x"); std::function<void(const AbstractPath& folderPath, AsyncCallback& acb)> deleteEmptyFolderTask; - deleteEmptyFolderTask = [&txtDeletingFolder, &folderItemCountShared, &deleteEmptyFolderTask](const AbstractPath& folderPath, AsyncCallback& acb) //throw ThreadStopRequest + deleteEmptyFolderTask = [&txtDeletingFolder, &protFolderItemCount, &deleteEmptyFolderTask](const AbstractPath& folderPath, AsyncCallback& acb) //throw ThreadStopRequest { const std::wstring errMsg = tryReportingError([&] //throw ThreadStopRequest { @@ -544,7 +552,7 @@ void fff::applyVersioningLimit(const std::set<VersioningLimitFolder>& folderLimi if (const std::optional<AbstractPath> parentPath = AFS::getParentPath(folderPath)) { bool deleteParent = false; - folderItemCountShared.access([&](auto& folderItemCount2) { deleteParent = --folderItemCount2[*parentPath] == 0; }); + protFolderItemCount.access([&](auto& folderItemCount2) { deleteParent = --folderItemCount2[*parentPath] == 0; }); if (deleteParent) //we're done here anyway => no need to schedule parent deletion in a separate task! deleteEmptyFolderTask(*parentPath, acb); //throw ThreadStopRequest } @@ -560,7 +568,7 @@ void fff::applyVersioningLimit(const std::set<VersioningLimitFolder>& folderLimi }); for (const auto& [itemPath, isSymlink] : itemsToDelete) - parallelWorkload.emplace_back(itemPath, [isSymlink /*clang bug*/= isSymlink, &txtRemoving, &folderItemCountShared, &deleteEmptyFolderTask](ParallelContext& ctx) //throw ThreadStopRequest + parallelWorkload.emplace_back(itemPath, [isSymlink /*clang bug*/= isSymlink, &txtRemoving, &protFolderItemCount, &deleteEmptyFolderTask](ParallelContext& ctx) //throw ThreadStopRequest { const std::wstring errMsg = tryReportingError([&] //throw ThreadStopRequest { @@ -575,7 +583,7 @@ void fff::applyVersioningLimit(const std::set<VersioningLimitFolder>& folderLimi if (const std::optional<AbstractPath> parentPath = AFS::getParentPath(ctx.itemPath)) { bool deleteParent = false; - folderItemCountShared.access([&](auto& folderItemCount2) { deleteParent = --folderItemCount2[*parentPath] == 0; }); + protFolderItemCount.access([&](auto& folderItemCount2) { deleteParent = --folderItemCount2[*parentPath] == 0; }); if (deleteParent) deleteEmptyFolderTask(*parentPath, ctx.acb); //throw ThreadStopRequest } diff --git a/FreeFileSync/Source/config.cpp b/FreeFileSync/Source/config.cpp index 8beb41bc..02b21343 100644 --- a/FreeFileSync/Source/config.cpp +++ b/FreeFileSync/Source/config.cpp @@ -2032,8 +2032,8 @@ std::pair<ConfigType, std::wstring /*warningMsg*/> parseConfig(const XmlDoc& doc } catch (const FileError& e) { - warningMsg = replaceCpy(_("Configuration file %x is incomplete. The missing elements have been set to their default values."), L"%x", fmtPath(filePath)) + - L"\n\n" + e.toString(); + warningMsg = replaceCpy(_("Configuration file %x is incomplete. The missing elements have been set to their default values."), L"%x", fmtPath(filePath)) + + L"\n\n" + e.toString(); } return {cfg, warningMsg}; @@ -2116,7 +2116,8 @@ std::pair<XmlGuiConfig, std::wstring /*warningMsg*/> fff::readAnyConfig(const st } else throw FileError(replaceCpy(_("Cannot open file %x."), L"%x", fmtPath(filePath)), - _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(filePath))); + _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(filePath)) + L'\n' + + _("Expected:") + L" ffs_gui, ffs_batch"); } cfg.mainCfg = merge(mainCfgs); @@ -2497,7 +2498,7 @@ void fff::writeConfig(const XmlGlobalSettings& cfg, const Zstring& filePath) std::wstring fff::extractJobName(const Zstring& cfgFilePath) { - const Zstring fileName = afterLast(cfgFilePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all); + const Zstring fileName = getItemName(cfgFilePath); const Zstring jobName = beforeLast(fileName, Zstr('.'), IfNotFoundReturn::all); return utfTo<std::wstring>(jobName); } @@ -2529,8 +2530,8 @@ std::optional<FilterConfig> fff::parseFilterBuf(const std::string& filterBuf) return filterCfg; } - catch (XmlParsingError&){} - catch (FileError&){} + catch (XmlParsingError&) {} + catch (FileError&) {} return std::nullopt; } diff --git a/FreeFileSync/Source/ffs_paths.cpp b/FreeFileSync/Source/ffs_paths.cpp index ec17c609..c70d57f7 100644 --- a/FreeFileSync/Source/ffs_paths.cpp +++ b/FreeFileSync/Source/ffs_paths.cpp @@ -65,8 +65,7 @@ Zstring fff::getConfigDirPath() { try { - return - appendPath(getUserDataPath(), Zstr("FreeFileSync")); //throw FileError + return appendPath(getUserDataPath(), Zstr("FreeFileSync")); //throw FileError } catch (const FileError& e) { diff --git a/FreeFileSync/Source/localization.cpp b/FreeFileSync/Source/localization.cpp index adbd1677..7c8bdd6b 100644 --- a/FreeFileSync/Source/localization.cpp +++ b/FreeFileSync/Source/localization.cpp @@ -117,7 +117,7 @@ std::vector<TranslationInfo> loadTranslations(const Zstring& zipPath) //throw Fi catch (FileError&) //fall back to folder: dev build (only!?) { const Zstring fallbackFolder = beforeLast(zipPath, Zstr(".zip"), IfNotFoundReturn::none); - if (!itemStillExists(fallbackFolder)) //throw FileError + if (!itemExists(fallbackFolder)) //throw FileError throw; traverseFolder(fallbackFolder, [&](const FileInfo& fi) @@ -127,7 +127,7 @@ std::vector<TranslationInfo> loadTranslations(const Zstring& zipPath) //throw Fi std::string stream = getFileContent(fi.fullPath, nullptr /*notifyUnbufferedIO*/); //throw FileError streams.emplace_back(fi.itemName, std::move(stream)); } - }, nullptr, nullptr, [](const std::wstring& errorMsg) { throw FileError(errorMsg); }); + }, nullptr, nullptr); //throw FileError } //-------------------------------------------------------------------- diff --git a/FreeFileSync/Source/log_file.cpp b/FreeFileSync/Source/log_file.cpp index fc22e6e3..5f268de0 100644 --- a/FreeFileSync/Source/log_file.cpp +++ b/FreeFileSync/Source/log_file.cpp @@ -481,7 +481,7 @@ std::vector<LogFileInfo> getLogFiles(const AbstractPath& logFolderPath) //throw { std::vector<LogFileInfo> logfiles; - AFS::traverseFolderFlat(logFolderPath, [&](const AFS::FileInfo& fi) //throw FileError + AFS::traverseFolder(logFolderPath, [&](const AFS::FileInfo& fi) //throw FileError { //"Backup FreeFileSync 2013-09-15 015052.123.html" //"Jobname1 + Jobname2 2013-09-15 015052.123.log" diff --git a/FreeFileSync/Source/ui/abstract_folder_picker.cpp b/FreeFileSync/Source/ui/abstract_folder_picker.cpp index f5e8721e..20647e72 100644 --- a/FreeFileSync/Source/ui/abstract_folder_picker.cpp +++ b/FreeFileSync/Source/ui/abstract_folder_picker.cpp @@ -6,7 +6,6 @@ #include "abstract_folder_picker.h" #include <wx+/async_task.h> -//#include <wx+/std_button_layout.h> #include <wx+/image_resources.h> #include <wx+/popup_dlg.h> #include <wx+/image_tools.h> diff --git a/FreeFileSync/Source/ui/batch_status_handler.cpp b/FreeFileSync/Source/ui/batch_status_handler.cpp index db4eb8ad..16ca24ea 100644 --- a/FreeFileSync/Source/ui/batch_status_handler.cpp +++ b/FreeFileSync/Source/ui/batch_status_handler.cpp @@ -251,6 +251,12 @@ BatchStatusHandler::Result BatchStatusHandler::reportResults(const Zstring& post } +wxWindow* BatchStatusHandler::getWindowIfVisible() +{ + return progressDlg_ ? progressDlg_->getWindowIfVisible() : nullptr; +} + + void BatchStatusHandler::initNewPhase(int itemsTotal, int64_t bytesTotal, ProcessPhase phaseID) { StatusHandler::initNewPhase(itemsTotal, bytesTotal, phaseID); diff --git a/FreeFileSync/Source/ui/batch_status_handler.h b/FreeFileSync/Source/ui/batch_status_handler.h index db35190f..02fa9ef4 100644 --- a/FreeFileSync/Source/ui/batch_status_handler.h +++ b/FreeFileSync/Source/ui/batch_status_handler.h @@ -63,6 +63,8 @@ public: const AbstractPath& logFolderPath, int logfilesMaxAgeDays, LogFileFormat logFormat, const std::set<AbstractPath>& logFilePathsToKeep, const std::string& emailNotifyAddress, ResultsNotification emailNotifyCondition); //noexcept!! + wxWindow* getWindowIfVisible(); + private: const std::wstring jobName_; const std::chrono::system_clock::time_point startTime_; diff --git a/FreeFileSync/Source/ui/cfg_grid.cpp b/FreeFileSync/Source/ui/cfg_grid.cpp index 00d5d33c..b50b114a 100644 --- a/FreeFileSync/Source/ui/cfg_grid.cpp +++ b/FreeFileSync/Source/ui/cfg_grid.cpp @@ -90,7 +90,7 @@ void ConfigView::addCfgFilesImpl(const std::vector<Zstring>& filePaths) if (equalNativePath(filePath, lastRunConfigPath_)) return std::make_tuple(utfTo<Zstring>(L'[' + _("Last session") + L']'), Details::CFG_TYPE_GUI, true); - const Zstring fileName = afterLast(filePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all); + const Zstring fileName = getItemName(filePath); if (endsWithAsciiNoCase(fileName, ".ffs_gui")) return std::make_tuple(beforeLast(fileName, Zstr('.'), IfNotFoundReturn::none), Details::CFG_TYPE_GUI, false); diff --git a/FreeFileSync/Source/ui/command_box.cpp b/FreeFileSync/Source/ui/command_box.cpp index 2e5407df..018a8311 100644 --- a/FreeFileSync/Source/ui/command_box.cpp +++ b/FreeFileSync/Source/ui/command_box.cpp @@ -128,9 +128,8 @@ void CommandBox::setValueAndUpdateList(const wxString& value) void CommandBox::onSelection(wxCommandEvent& event) { - wxCommandEvent dummy(EVENT_VALIDATE_USER_SELECTION); //we cannot replace built-in commands at this position in call stack, so defer to a later time! - if (auto handler = GetEventHandler()) - handler->AddPendingEvent(dummy); + //we cannot replace built-in commands at this position in call stack, so defer to a later time! + GetEventHandler()->AddPendingEvent(wxCommandEvent(EVENT_VALIDATE_USER_SELECTION)); event.Skip(); } diff --git a/FreeFileSync/Source/ui/file_grid.cpp b/FreeFileSync/Source/ui/file_grid.cpp index c350548f..21114308 100644 --- a/FreeFileSync/Source/ui/file_grid.cpp +++ b/FreeFileSync/Source/ui/file_grid.cpp @@ -794,6 +794,27 @@ private: } }; + bool navMarkerDrawn = false; + auto tryDrawNavMarker = [&](wxRect rectNav) + { + if (!navMarkerDrawn && + rectNav.x == rect.x && //draw marker *only* if current render group (group parent, group name, item name) is at beginning of a row! + isNavMarked(*pdi.fsObj) && + (!enabled || !selected)) + { + rectNav.width = std::min(rectNav.width, fastFromDIP(10)); + + if (row == pdi.groupLastRow - 1 /*last group item*/) //preserve the group separation line! + rectNav.height -= fastFromDIP(1); + + //wxColor backCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + //dc.GetPixel(rectNav.GetTopRight(), &backCol); //e.g. selected row! + + dc.GradientFillLinear(rectNav, getColorSelectionGradientFrom(), getColorSelectionGradientTo(), wxEAST); + navMarkerDrawn = true; + } + }; + auto drawIcon = [&](wxImage icon, wxRect rectIcon, bool drawActive) { if (!drawActive) @@ -893,22 +914,22 @@ private: //accessibility: always set *both* foreground AND background colors! } - if (isNavMarked(*pdi.fsObj)) //draw *after* clearing area for parent components - if (!enabled || !selected) - { - wxRect rectNav = rect; - rectNav.width = fastFromDIP(20); - - if (row == pdi.groupLastRow - 1 /*last group item*/) //preserve the group separation line! - rectNav.height -= fastFromDIP(1); + if (!groupParentFolder.empty() && + (( stackedGroupRender && row == groupFirstRow + 1) || + (!stackedGroupRender && row == groupFirstRow)) && + (groupName.empty() || !pdi.folderGroupObj->isEmpty<side>())) //don't show for missing folders + { + tryDrawNavMarker(rectGroupParent); - wxColor backCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - dc.GetPixel(rectNav.GetTopRight(), &backCol); //e.g. selected row! + wxRect rectGroupParentText = rectGroupParent; + rectGroupParentText.x += gapSize_; + rectGroupParentText.width -= stackedGroupRender ? gapSize_ + gapSizeWide_ : gapSize_; - dc.GradientFillLinear(rectNav, getColorSelectionGradientFrom(), backCol, wxEAST); - } + drawCellText(dc, rectGroupParentText, groupParentFolder, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, &getTextExtentBuffered(dc, groupParentFolder)); + } - if (!groupName.empty() && row == groupFirstRow) + if (!groupName.empty() && + row == groupFirstRow) { wxRect rectGroupNameBack = rectGroupName; @@ -926,6 +947,7 @@ private: textColorGroupName.Set(getColorInactiveText()); } drawCudHighlight(rectGroupNameBack, pdi.folderGroupObj->getSyncOperation()); + tryDrawNavMarker(rectGroupName); wxImage folderIcon; bool drawAsLink = false; @@ -946,18 +968,6 @@ private: if (!pdi.folderGroupObj->isEmpty<side>()) drawCellText(dc, rectGroupName, groupName, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, &getTextExtentBuffered(dc, groupName)); } - - if (!groupParentFolder.empty() && - (( stackedGroupRender && row == groupFirstRow + 1) || - (!stackedGroupRender && row == groupFirstRow)) && - (groupName.empty() || !pdi.folderGroupObj->isEmpty<side>())) //don't show for missing folders - { - wxRect rectGroupParentText = rectGroupParent; - rectGroupParentText.x += gapSize_; - rectGroupParentText.width -= stackedGroupRender ? gapSize_ + gapSizeWide_ : gapSize_; - - drawCellText(dc, rectGroupParentText, groupParentFolder, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, &getTextExtentBuffered(dc, groupParentFolder)); - } } //------------------------------------------------------------------------- @@ -981,6 +991,7 @@ private: rectItemsBack.height -= fastFromDIP(1); //preserve item separation lines! drawCudHighlight(rectItemsBack, pdi.fsObj->getSyncOperation()); + tryDrawNavMarker(rectGroupItems); if (IconBuffer* iconBuf = getIconManager().getIconBuffer()) //=> draw file icons { @@ -1028,6 +1039,9 @@ private: if (!pdi.fsObj->isEmpty<side>()) drawCellText(dc, rectGroupItems, itemName, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, &getTextExtentBuffered(dc, itemName)); } + + //if not done yet: + tryDrawNavMarker(rect); } break; @@ -1165,7 +1179,7 @@ private: if (const ColumnTypeRim* sortType = std::get_if<ColumnTypeRim>(&sortInfo->sortCol)) if (*sortType == static_cast<ColumnTypeRim>(colType) && sortInfo->onLeft == (side == SelectSide::left)) { - bool ascending = sortInfo->ascending; //work around MSVC 17.4 compiler bug :( "error C2039: 'sortCol': is not a member of 'fff::FileView::SortInfo'" + bool ascending = sortInfo->ascending; //work around MSVC 17.4 compiler bug :( "error C2039: 'sortCol': is not a member of 'fff::FileView::SortInfo'" const wxImage sortMarker = loadImage(ascending ? "sort_ascending" : "sort_descending"); drawBitmapRtlNoMirror(dc, enabled ? sortMarker : sortMarker.ConvertToDisabled(), rectInner, wxALIGN_CENTER_HORIZONTAL); @@ -1298,36 +1312,35 @@ public: //issue custom event if (selectionInProgress_) //don't process selections initiated by right-click if (rowFirst < rowLast && rowLast <= refGrid().getRowCount()) //empty? probably not in this context - if (wxEvtHandler* evtHandler = refGrid().GetEventHandler()) - switch (static_cast<HoverAreaCenter>(rowHover)) - { - case HoverAreaCenter::checkbox: - if (const FileSystemObject* fsObj = getFsObject(clickInitRow)) - { - const bool setIncluded = !fsObj->isActive(); - CheckRowsEvent evt(rowFirst, rowLast, setIncluded); - evtHandler->ProcessEvent(evt); - } - break; - case HoverAreaCenter::dirLeft: - { - SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::left); - evtHandler->ProcessEvent(evt); - } - break; - case HoverAreaCenter::dirNone: - { - SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::none); - evtHandler->ProcessEvent(evt); - } - break; - case HoverAreaCenter::dirRight: + switch (static_cast<HoverAreaCenter>(rowHover)) + { + case HoverAreaCenter::checkbox: + if (const FileSystemObject* fsObj = getFsObject(clickInitRow)) { - SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::right); - evtHandler->ProcessEvent(evt); + const bool setIncluded = !fsObj->isActive(); + CheckRowsEvent evt(rowFirst, rowLast, setIncluded); + refGrid().GetEventHandler()->ProcessEvent(evt); } break; + case HoverAreaCenter::dirLeft: + { + SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::left); + refGrid().GetEventHandler()->ProcessEvent(evt); + } + break; + case HoverAreaCenter::dirNone: + { + SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::none); + refGrid().GetEventHandler()->ProcessEvent(evt); + } + break; + case HoverAreaCenter::dirRight: + { + SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::right); + refGrid().GetEventHandler()->ProcessEvent(evt); } + break; + } selectionInProgress_ = false; //update highlight_ and tooltip: on OS X no mouse movement event is generated after a mouse button click (unlike on Windows) @@ -1703,8 +1716,13 @@ public: gridR_.Bind(EVENT_GRID_MOUSE_LEFT_DOWN, [this](GridClickEvent& event) { onGridClickRim(event, gridR_); }); //clear selection of other grid when selecting on - gridL_.Bind(EVENT_GRID_SELECT_RANGE, [this](GridSelectEvent& event) { onGridSelection(event, gridR_); }); - gridR_.Bind(EVENT_GRID_SELECT_RANGE, [this](GridSelectEvent& event) { onGridSelection(event, gridL_); }); + gridL_.Bind(EVENT_GRID_SELECT_RANGE, [this](GridSelectEvent& event) { onGridSelection(event, gridR_); }); + gridL_.Bind(EVENT_GRID_MOUSE_LEFT_DOWN, [this]( GridClickEvent& event) { onGridSelection(event, gridR_); }); //clear immediately, + gridL_.Bind(EVENT_GRID_MOUSE_RIGHT_DOWN, [this]( GridClickEvent& event) { onGridSelection(event, gridR_); }); //don't wait for GridSelectEvent + + gridR_.Bind(EVENT_GRID_SELECT_RANGE, [this](GridSelectEvent& event) { onGridSelection(event, gridL_); }); + gridR_.Bind(EVENT_GRID_MOUSE_LEFT_DOWN, [this]( GridClickEvent& event) { onGridSelection(event, gridL_); }); + gridR_.Bind(EVENT_GRID_MOUSE_RIGHT_DOWN, [this]( GridClickEvent& event) { onGridSelection(event, gridL_); }); //parallel grid scrolling: do NOT use DoPrepareDC() to align grids! GDI resource leak! Use regular paint event instead: gridL_.getMainWin().Bind(wxEVT_PAINT, [this](wxPaintEvent& event) { onPaintGrid(gridL_); event.Skip(); }); @@ -1788,13 +1806,23 @@ private: if (const FileView::PathDrawInfo pdi = provCenter_.getDataView().getDrawInfo(event.row_); pdi.fsObj) { - grid.setGridCursor(pdi.groupFirstRow, GridEventPolicy::allow); - return; + const ptrdiff_t topRowOld = grid.getRowAtWinPos(0); + grid.makeRowVisible(pdi.groupFirstRow); + const ptrdiff_t topRowNew = grid.getRowAtWinPos(0); + + if (topRowNew != topRowOld) //=> grid was scrolled: prevent AddPendingEvent() recursion! + { + assert(topRowNew == makeSigned(pdi.groupFirstRow)); + assert(topRowNew == grid.getRowAtWinPos((event.mousePos_ - grid.getMainWin().GetPosition()).y)); + //don't waste a click: simulate start of new selection at Grid::MainWin-relative position (0/0): + grid.getMainWin().GetEventHandler()->AddPendingEvent(wxMouseEvent(wxEVT_LEFT_DOWN)); + return; + } } event.Skip(); } - void onGridSelection(GridSelectEvent& event, Grid& gridOther) + void onGridSelection(wxEvent& event, Grid& gridOther) { if (!wxGetKeyState(WXK_CONTROL)) //clear other grid unless user is holding CTRL gridOther.clearSelection(GridEventPolicy::deny); //don't emit event, prevent recursion! diff --git a/FreeFileSync/Source/ui/folder_history_box.cpp b/FreeFileSync/Source/ui/folder_history_box.cpp index 24822b61..cd028c4a 100644 --- a/FreeFileSync/Source/ui/folder_history_box.cpp +++ b/FreeFileSync/Source/ui/folder_history_box.cpp @@ -61,13 +61,23 @@ void FolderHistoryBox::setValueAndUpdateList(const wxString& folderPathPhrase) { //populate selection list.... std::vector<wxString> items; - - const Zstring& pathPhraseTrimmed = utfTo<Zstring>(trimCpy(folderPathPhrase)); - - //path phrase aliases: allow user changing to volume name and back - for (const Zstring& pathPhrase : AFS::getPathPhraseAliases(createAbstractPath(pathPhraseTrimmed))) //may block when resolving [<volume name>] - if (!equalNoCase(appendSeparator(pathPhraseTrimmed), appendSeparator(pathPhrase))) //don't add redundant aliases - items.push_back(utfTo<wxString>(pathPhrase)); + { + auto trimTrailingSep = [](Zstring path) + { + if (endsWith(path, Zstr('/')) || + endsWith(path, Zstr('\\'))) + path.pop_back(); + return path; + }; + + const Zstring& folderPathPhraseTrimmed = trimTrailingSep(trimCpy(utfTo<Zstring>(folderPathPhrase))); + + //path phrase aliases: allow user changing to volume name and back + for (const Zstring& aliasPhrase : AFS::getPathPhraseAliases(createAbstractPath(utfTo<Zstring>(folderPathPhrase)))) //may block when resolving [<volume name>] + if (!equalNoCase(folderPathPhraseTrimmed, + trimTrailingSep(aliasPhrase))) //don't add redundant aliases + items.push_back(utfTo<wxString>(aliasPhrase)); + } if (sharedHistory_.get()) { diff --git a/FreeFileSync/Source/ui/folder_selector.cpp b/FreeFileSync/Source/ui/folder_selector.cpp index a180ed8a..880a7048 100644 --- a/FreeFileSync/Source/ui/folder_selector.cpp +++ b/FreeFileSync/Source/ui/folder_selector.cpp @@ -211,7 +211,7 @@ void FolderSelector::onSelectFolder(wxCommandEvent& event) Zstring defaultFolderNative; { //make sure default folder exists: don't let folder picker hang on non-existing network share! - auto folderAccessible = [waitEndTime = std::chrono::steady_clock::now() + FOLDER_SELECTED_EXISTENCE_CHECK_TIME_MAX](const AbstractPath& folderPath) + auto folderAccessible = [stopTime = std::chrono::steady_clock::now() + FOLDER_SELECTED_EXISTENCE_CHECK_TIME_MAX](const AbstractPath& folderPath) { if (AFS::isNullPath(folderPath)) return false; @@ -224,7 +224,7 @@ void FolderSelector::onSelectFolder(wxCommandEvent& event) } catch (FileError&) { return false; } }); - return ft.wait_until(waitEndTime) == std::future_status::ready && ft.get(); //potentially slow network access: wait 200ms at most + return ft.wait_until(stopTime) == std::future_status::ready && ft.get(); //potentially slow network access: wait 200ms at most }; auto trySetDefaultPath = [&](const Zstring& folderPathPhrase) diff --git a/FreeFileSync/Source/ui/gui_generated.cpp b/FreeFileSync/Source/ui/gui_generated.cpp index 3cd591cb..4b1ae973 100644 --- a/FreeFileSync/Source/ui/gui_generated.cpp +++ b/FreeFileSync/Source/ui/gui_generated.cpp @@ -11,1189 +11,1189 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - m_menubar = new wxMenuBar( 0 ); - m_menuFile = new wxMenu(); - m_menuItemNew = new wxMenuItem( m_menuFile, wxID_NEW, wxString( _("&New") ) + wxT('\t') + wxT("Ctrl+N"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemNew ); + m_menubar = new wxMenuBar( 0 ); + m_menuFile = new wxMenu(); + m_menuItemNew = new wxMenuItem( m_menuFile, wxID_NEW, wxString( _("&New") ) + wxT('\t') + wxT("Ctrl+N"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemNew ); - m_menuItemLoad = new wxMenuItem( m_menuFile, wxID_OPEN, wxString( _("&Open...") ) + wxT('\t') + wxT("Ctrl+O"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemLoad ); + m_menuItemLoad = new wxMenuItem( m_menuFile, wxID_OPEN, wxString( _("&Open...") ) + wxT('\t') + wxT("Ctrl+O"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemLoad ); - m_menuFile->AppendSeparator(); + m_menuFile->AppendSeparator(); - m_menuItemSave = new wxMenuItem( m_menuFile, wxID_SAVE, wxString( _("&Save") ) + wxT('\t') + wxT("Ctrl+S"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemSave ); + m_menuItemSave = new wxMenuItem( m_menuFile, wxID_SAVE, wxString( _("&Save") ) + wxT('\t') + wxT("Ctrl+S"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemSave ); - m_menuItemSaveAs = new wxMenuItem( m_menuFile, wxID_SAVEAS, wxString( _("Save &as...") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemSaveAs ); + m_menuItemSaveAs = new wxMenuItem( m_menuFile, wxID_SAVEAS, wxString( _("Save &as...") ), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemSaveAs ); - m_menuItemSaveAsBatch = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("Save as &batch job...") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemSaveAsBatch ); + m_menuItemSaveAsBatch = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("Save as &batch job...") ), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemSaveAsBatch ); - m_menuFile->AppendSeparator(); + m_menuFile->AppendSeparator(); - m_menuItemQuit = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemQuit ); + m_menuItemQuit = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemQuit ); - m_menubar->Append( m_menuFile, _("&File") ); + m_menubar->Append( m_menuFile, _("&File") ); - m_menuActions = new wxMenu(); - m_menuItemShowLog = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("Show &log") ) + wxT('\t') + wxT("F4"), wxEmptyString, wxITEM_NORMAL ); - m_menuActions->Append( m_menuItemShowLog ); + m_menuActions = new wxMenu(); + m_menuItemShowLog = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("Show &log") ) + wxT('\t') + wxT("F4"), wxEmptyString, wxITEM_NORMAL ); + m_menuActions->Append( m_menuItemShowLog ); - m_menuActions->AppendSeparator(); + m_menuActions->AppendSeparator(); - m_menuItemCompare = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("Start &comparison") ) + wxT('\t') + wxT("F5"), wxEmptyString, wxITEM_NORMAL ); - m_menuActions->Append( m_menuItemCompare ); + m_menuItemCompare = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("Start &comparison") ) + wxT('\t') + wxT("F5"), wxEmptyString, wxITEM_NORMAL ); + m_menuActions->Append( m_menuItemCompare ); - m_menuActions->AppendSeparator(); + m_menuActions->AppendSeparator(); - m_menuItemCompSettings = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("C&omparison settings") ) + wxT('\t') + wxT("F6"), wxEmptyString, wxITEM_NORMAL ); - m_menuActions->Append( m_menuItemCompSettings ); + m_menuItemCompSettings = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("C&omparison settings") ) + wxT('\t') + wxT("F6"), wxEmptyString, wxITEM_NORMAL ); + m_menuActions->Append( m_menuItemCompSettings ); - m_menuItemFilter = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("&Filter settings") ) + wxT('\t') + wxT("F7"), wxEmptyString, wxITEM_NORMAL ); - m_menuActions->Append( m_menuItemFilter ); + m_menuItemFilter = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("&Filter settings") ) + wxT('\t') + wxT("F7"), wxEmptyString, wxITEM_NORMAL ); + m_menuActions->Append( m_menuItemFilter ); - m_menuItemSyncSettings = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("S&ynchronization settings") ) + wxT('\t') + wxT("F8"), wxEmptyString, wxITEM_NORMAL ); - m_menuActions->Append( m_menuItemSyncSettings ); + m_menuItemSyncSettings = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("S&ynchronization settings") ) + wxT('\t') + wxT("F8"), wxEmptyString, wxITEM_NORMAL ); + m_menuActions->Append( m_menuItemSyncSettings ); - m_menuActions->AppendSeparator(); + m_menuActions->AppendSeparator(); - m_menuItemSynchronize = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("Start &synchronization") ) + wxT('\t') + wxT("F9"), wxEmptyString, wxITEM_NORMAL ); - m_menuActions->Append( m_menuItemSynchronize ); + m_menuItemSynchronize = new wxMenuItem( m_menuActions, wxID_ANY, wxString( _("Start &synchronization") ) + wxT('\t') + wxT("F9"), wxEmptyString, wxITEM_NORMAL ); + m_menuActions->Append( m_menuItemSynchronize ); - m_menubar->Append( m_menuActions, _("&Actions") ); + m_menubar->Append( m_menuActions, _("&Actions") ); - m_menuTools = new wxMenu(); - m_menuItemOptions = new wxMenuItem( m_menuTools, wxID_PREFERENCES, wxString( _("&Preferences") ) + wxT('\t') + wxT("Ctrl+,"), wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemOptions ); + m_menuTools = new wxMenu(); + m_menuItemOptions = new wxMenuItem( m_menuTools, wxID_PREFERENCES, wxString( _("&Preferences") ) + wxT('\t') + wxT("Ctrl+,"), wxEmptyString, wxITEM_NORMAL ); + m_menuTools->Append( m_menuItemOptions ); - m_menuLanguages = new wxMenu(); - wxMenuItem* m_menuLanguagesItem = new wxMenuItem( m_menuTools, wxID_ANY, _("&Language"), wxEmptyString, wxITEM_NORMAL, m_menuLanguages ); - m_menuTools->Append( m_menuLanguagesItem ); + m_menuLanguages = new wxMenu(); + wxMenuItem* m_menuLanguagesItem = new wxMenuItem( m_menuTools, wxID_ANY, _("&Language"), wxEmptyString, wxITEM_NORMAL, m_menuLanguages ); + m_menuTools->Append( m_menuLanguagesItem ); - m_menuTools->AppendSeparator(); + m_menuTools->AppendSeparator(); - m_menuItemFind = new wxMenuItem( m_menuTools, wxID_FIND, wxString( _("&Find...") ) + wxT('\t') + wxT("Ctrl+F"), wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemFind ); + m_menuItemFind = new wxMenuItem( m_menuTools, wxID_FIND, wxString( _("&Find...") ) + wxT('\t') + wxT("Ctrl+F"), wxEmptyString, wxITEM_NORMAL ); + m_menuTools->Append( m_menuItemFind ); - m_menuItemExportList = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("&Export file list") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemExportList ); + m_menuItemExportList = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("&Export file list") ), wxEmptyString, wxITEM_NORMAL ); + m_menuTools->Append( m_menuItemExportList ); - m_menuTools->AppendSeparator(); + m_menuTools->AppendSeparator(); - m_menuItemResetLayout = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("&Reset layout") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemResetLayout ); + m_menuItemResetLayout = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("&Reset layout") ), wxEmptyString, wxITEM_NORMAL ); + m_menuTools->Append( m_menuItemResetLayout ); - m_menuItemShowMain = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemShowMain ); + m_menuItemShowMain = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ), wxEmptyString, wxITEM_NORMAL ); + m_menuTools->Append( m_menuItemShowMain ); - m_menuItemShowFolders = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemShowFolders ); + m_menuItemShowFolders = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ), wxEmptyString, wxITEM_NORMAL ); + m_menuTools->Append( m_menuItemShowFolders ); - m_menuItemShowViewFilter = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemShowViewFilter ); + m_menuItemShowViewFilter = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ), wxEmptyString, wxITEM_NORMAL ); + m_menuTools->Append( m_menuItemShowViewFilter ); - m_menuItemShowConfig = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemShowConfig ); + m_menuItemShowConfig = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ), wxEmptyString, wxITEM_NORMAL ); + m_menuTools->Append( m_menuItemShowConfig ); - m_menuItemShowOverview = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemShowOverview ); + m_menuItemShowOverview = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("dummy") ), wxEmptyString, wxITEM_NORMAL ); + m_menuTools->Append( m_menuItemShowOverview ); - m_menubar->Append( m_menuTools, _("&Tools") ); + m_menubar->Append( m_menuTools, _("&Tools") ); - m_menuHelp = new wxMenu(); - m_menuItemHelp = new wxMenuItem( m_menuHelp, wxID_HELP, wxString( _("&View help") ) + wxT('\t') + wxT("F1"), wxEmptyString, wxITEM_NORMAL ); - m_menuHelp->Append( m_menuItemHelp ); + m_menuHelp = new wxMenu(); + m_menuItemHelp = new wxMenuItem( m_menuHelp, wxID_HELP, wxString( _("&View help") ) + wxT('\t') + wxT("F1"), wxEmptyString, wxITEM_NORMAL ); + m_menuHelp->Append( m_menuItemHelp ); - m_menuHelp->AppendSeparator(); + m_menuHelp->AppendSeparator(); - m_menuItemCheckVersionNow = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("&Check for updates now") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuHelp->Append( m_menuItemCheckVersionNow ); + m_menuItemCheckVersionNow = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("&Check for updates now") ), wxEmptyString, wxITEM_NORMAL ); + m_menuHelp->Append( m_menuItemCheckVersionNow ); - m_menuItemCheckVersionAuto = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("Check &automatically once a week") ) , wxEmptyString, wxITEM_CHECK ); - m_menuHelp->Append( m_menuItemCheckVersionAuto ); - m_menuItemCheckVersionAuto->Check( true ); + m_menuItemCheckVersionAuto = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("Check &automatically once a week") ), wxEmptyString, wxITEM_CHECK ); + m_menuHelp->Append( m_menuItemCheckVersionAuto ); + m_menuItemCheckVersionAuto->Check( true ); - m_menuHelp->AppendSeparator(); + m_menuHelp->AppendSeparator(); - m_menuItemAbout = new wxMenuItem( m_menuHelp, wxID_ABOUT, wxString( _("&About") ) + wxT('\t') + wxT("Shift+F1"), wxEmptyString, wxITEM_NORMAL ); - m_menuHelp->Append( m_menuItemAbout ); + m_menuItemAbout = new wxMenuItem( m_menuHelp, wxID_ABOUT, wxString( _("&About") ) + wxT('\t') + wxT("Shift+F1"), wxEmptyString, wxITEM_NORMAL ); + m_menuHelp->Append( m_menuItemAbout ); - m_menubar->Append( m_menuHelp, _("&Help") ); + m_menubar->Append( m_menuHelp, _("&Help") ); - this->SetMenuBar( m_menubar ); + this->SetMenuBar( m_menubar ); - bSizerPanelHolder = new wxBoxSizer( wxVERTICAL ); + bSizerPanelHolder = new wxBoxSizer( wxVERTICAL ); - m_panelTopButtons = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelTopButtons->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelTopButtons = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelTopButtons->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer1791; - bSizer1791 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer1791; + bSizer1791 = new wxBoxSizer( wxHORIZONTAL ); - bSizerTopButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerTopButtons = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer261; - bSizer261 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer261; + bSizer261 = new wxBoxSizer( wxHORIZONTAL ); - bSizer261->Add( 0, 0, 1, 0, 5 ); + bSizer261->Add( 0, 0, 1, 0, 5 ); - m_buttonCancel = new wxButton( m_panelTopButtons, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonCancel->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonCancel->Enable( false ); - m_buttonCancel->Hide(); + m_buttonCancel = new wxButton( m_panelTopButtons, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_buttonCancel->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonCancel->Enable( false ); + m_buttonCancel->Hide(); - bSizer261->Add( m_buttonCancel, 0, wxEXPAND, 5 ); + bSizer261->Add( m_buttonCancel, 0, wxEXPAND, 5 ); - m_buttonCompare = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Compare"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonCompare->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonCompare->SetToolTip( _("dummy") ); + m_buttonCompare = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Compare"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_buttonCompare->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonCompare->SetToolTip( _("dummy") ); - bSizer261->Add( m_buttonCompare, 0, wxEXPAND, 5 ); + bSizer261->Add( m_buttonCompare, 0, wxEXPAND, 5 ); - bSizerTopButtons->Add( bSizer261, 1, wxEXPAND, 5 ); + bSizerTopButtons->Add( bSizer261, 1, wxEXPAND, 5 ); - bSizerTopButtons->Add( 8, 8, 0, 0, 5 ); + bSizerTopButtons->Add( 8, 8, 0, 0, 5 ); - wxBoxSizer* bSizer2942; - bSizer2942 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer2942; + bSizer2942 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonCmpConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonCmpConfig->SetToolTip( _("dummy") ); + m_bpButtonCmpConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonCmpConfig->SetToolTip( _("dummy") ); - bSizer2942->Add( m_bpButtonCmpConfig, 0, wxEXPAND, 5 ); + bSizer2942->Add( m_bpButtonCmpConfig, 0, wxEXPAND, 5 ); - m_bpButtonCmpContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizer2942->Add( m_bpButtonCmpContext, 0, wxEXPAND, 5 ); + m_bpButtonCmpContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizer2942->Add( m_bpButtonCmpContext, 0, wxEXPAND, 5 ); - bSizer2942->Add( 0, 0, 1, 0, 5 ); + bSizer2942->Add( 0, 0, 1, 0, 5 ); - bSizer2942->Add( 8, 0, 0, 0, 5 ); + bSizer2942->Add( 8, 0, 0, 0, 5 ); - m_bpButtonFilter = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0|wxFULL_REPAINT_ON_RESIZE ); - m_bpButtonFilter->SetToolTip( _("dummy") ); + m_bpButtonFilter = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0|wxFULL_REPAINT_ON_RESIZE ); + m_bpButtonFilter->SetToolTip( _("dummy") ); - bSizer2942->Add( m_bpButtonFilter, 0, wxEXPAND, 5 ); + bSizer2942->Add( m_bpButtonFilter, 0, wxEXPAND, 5 ); - m_bpButtonFilterContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizer2942->Add( m_bpButtonFilterContext, 0, wxEXPAND, 5 ); + m_bpButtonFilterContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizer2942->Add( m_bpButtonFilterContext, 0, wxEXPAND, 5 ); - bSizer2942->Add( 8, 0, 0, 0, 5 ); + bSizer2942->Add( 8, 0, 0, 0, 5 ); - bSizer2942->Add( 0, 0, 1, 0, 5 ); + bSizer2942->Add( 0, 0, 1, 0, 5 ); - m_bpButtonSyncConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSyncConfig->SetToolTip( _("dummy") ); + m_bpButtonSyncConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSyncConfig->SetToolTip( _("dummy") ); - bSizer2942->Add( m_bpButtonSyncConfig, 0, wxEXPAND, 5 ); + bSizer2942->Add( m_bpButtonSyncConfig, 0, wxEXPAND, 5 ); - m_bpButtonSyncContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizer2942->Add( m_bpButtonSyncContext, 0, wxEXPAND, 5 ); + m_bpButtonSyncContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizer2942->Add( m_bpButtonSyncContext, 0, wxEXPAND, 5 ); - bSizerTopButtons->Add( bSizer2942, 1, wxEXPAND, 5 ); + bSizerTopButtons->Add( bSizer2942, 1, wxEXPAND, 5 ); - bSizerTopButtons->Add( 8, 8, 0, 0, 5 ); + bSizerTopButtons->Add( 8, 8, 0, 0, 5 ); - wxBoxSizer* bSizer262; - bSizer262 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer262; + bSizer262 = new wxBoxSizer( wxHORIZONTAL ); - m_buttonSync = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Synchronize"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonSync->SetToolTip( _("dummy") ); + m_buttonSync = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Synchronize"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_buttonSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonSync->SetToolTip( _("dummy") ); - bSizer262->Add( m_buttonSync, 0, wxEXPAND, 5 ); + bSizer262->Add( m_buttonSync, 0, wxEXPAND, 5 ); - bSizerTopButtons->Add( bSizer262, 1, wxEXPAND, 5 ); + bSizerTopButtons->Add( bSizer262, 1, wxEXPAND, 5 ); - bSizer1791->Add( bSizerTopButtons, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer1791->Add( bSizerTopButtons, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_panelTopButtons->SetSizer( bSizer1791 ); - m_panelTopButtons->Layout(); - bSizer1791->Fit( m_panelTopButtons ); - bSizerPanelHolder->Add( m_panelTopButtons, 0, wxEXPAND, 5 ); + m_panelTopButtons->SetSizer( bSizer1791 ); + m_panelTopButtons->Layout(); + bSizer1791->Fit( m_panelTopButtons ); + bSizerPanelHolder->Add( m_panelTopButtons, 0, wxEXPAND, 5 ); - m_panelDirectoryPairs = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_STATIC ); - wxBoxSizer* bSizer1601; - bSizer1601 = new wxBoxSizer( wxVERTICAL ); + m_panelDirectoryPairs = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_STATIC ); + wxBoxSizer* bSizer1601; + bSizer1601 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer91; - bSizer91 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer91; + bSizer91 = new wxBoxSizer( wxHORIZONTAL ); - m_panelTopLeft = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelTopLeft->SetMinSize( wxSize( 1,-1 ) ); + m_panelTopLeft = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelTopLeft->SetMinSize( wxSize( 1, -1 ) ); - wxFlexGridSizer* fgSizer8; - fgSizer8 = new wxFlexGridSizer( 0, 2, 0, 0 ); - fgSizer8->AddGrowableCol( 1 ); - fgSizer8->SetFlexibleDirection( wxBOTH ); - fgSizer8->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); + wxFlexGridSizer* fgSizer8; + fgSizer8 = new wxFlexGridSizer( 0, 2, 0, 0 ); + fgSizer8->AddGrowableCol( 1 ); + fgSizer8->SetFlexibleDirection( wxBOTH ); + fgSizer8->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); - fgSizer8->Add( 0, 0, 1, wxEXPAND, 5 ); + fgSizer8->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticTextResolvedPathL = new wxStaticText( m_panelTopLeft, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextResolvedPathL->Wrap( -1 ); - fgSizer8->Add( m_staticTextResolvedPathL, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 ); + m_staticTextResolvedPathL = new wxStaticText( m_panelTopLeft, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextResolvedPathL->Wrap( -1 ); + fgSizer8->Add( m_staticTextResolvedPathL, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 ); - wxBoxSizer* bSizer159; - bSizer159 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer159; + bSizer159 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonAddPair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); + m_bpButtonAddPair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); - bSizer159->Add( m_bpButtonAddPair, 0, wxEXPAND, 5 ); + bSizer159->Add( m_bpButtonAddPair, 0, wxEXPAND, 5 ); - m_bpButtonRemovePair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); + m_bpButtonRemovePair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); - bSizer159->Add( m_bpButtonRemovePair, 0, wxEXPAND, 5 ); + bSizer159->Add( m_bpButtonRemovePair, 0, wxEXPAND, 5 ); - fgSizer8->Add( bSizer159, 0, wxEXPAND, 5 ); + fgSizer8->Add( bSizer159, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer182; - bSizer182 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer182; + bSizer182 = new wxBoxSizer( wxHORIZONTAL ); - m_folderPathLeft = new fff::FolderHistoryBox( m_panelTopLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer182->Add( m_folderPathLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_folderPathLeft = new fff::FolderHistoryBox( m_panelTopLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer182->Add( m_folderPathLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectFolderLeft = new wxButton( m_panelTopLeft, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectFolderLeft->SetToolTip( _("Select a folder") ); + m_buttonSelectFolderLeft = new wxButton( m_panelTopLeft, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectFolderLeft->SetToolTip( _("Select a folder") ); - bSizer182->Add( m_buttonSelectFolderLeft, 0, wxEXPAND, 5 ); + bSizer182->Add( m_buttonSelectFolderLeft, 0, wxEXPAND, 5 ); - m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSelectAltFolderLeft->SetToolTip( _("Access online storage") ); + m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSelectAltFolderLeft->SetToolTip( _("Access online storage") ); - bSizer182->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 ); + bSizer182->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 ); - fgSizer8->Add( bSizer182, 0, wxEXPAND, 5 ); + fgSizer8->Add( bSizer182, 0, wxEXPAND, 5 ); - m_panelTopLeft->SetSizer( fgSizer8 ); - m_panelTopLeft->Layout(); - fgSizer8->Fit( m_panelTopLeft ); - bSizer91->Add( m_panelTopLeft, 1, wxLEFT|wxALIGN_BOTTOM, 5 ); + m_panelTopLeft->SetSizer( fgSizer8 ); + m_panelTopLeft->Layout(); + fgSizer8->Fit( m_panelTopLeft ); + bSizer91->Add( m_panelTopLeft, 1, wxLEFT|wxALIGN_BOTTOM, 5 ); - m_panelTopCenter = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1771; - bSizer1771 = new wxBoxSizer( wxVERTICAL ); + m_panelTopCenter = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1771; + bSizer1771 = new wxBoxSizer( wxVERTICAL ); - m_bpButtonSwapSides = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSwapSides->SetToolTip( _("dummy") ); + m_bpButtonSwapSides = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSwapSides->SetToolTip( _("dummy") ); - bSizer1771->Add( m_bpButtonSwapSides, 0, wxEXPAND, 5 ); + bSizer1771->Add( m_bpButtonSwapSides, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer160; - bSizer160 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer160; + bSizer160 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonLocalCompCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonLocalCompCfg->SetToolTip( _("dummy") ); + m_bpButtonLocalCompCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonLocalCompCfg->SetToolTip( _("dummy") ); - bSizer160->Add( m_bpButtonLocalCompCfg, 0, wxEXPAND, 5 ); + bSizer160->Add( m_bpButtonLocalCompCfg, 0, wxEXPAND, 5 ); - m_bpButtonLocalFilter = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonLocalFilter->SetToolTip( _("dummy") ); + m_bpButtonLocalFilter = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonLocalFilter->SetToolTip( _("dummy") ); - bSizer160->Add( m_bpButtonLocalFilter, 0, wxEXPAND, 5 ); + bSizer160->Add( m_bpButtonLocalFilter, 0, wxEXPAND, 5 ); - m_bpButtonLocalSyncCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonLocalSyncCfg->SetToolTip( _("dummy") ); + m_bpButtonLocalSyncCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonLocalSyncCfg->SetToolTip( _("dummy") ); - bSizer160->Add( m_bpButtonLocalSyncCfg, 0, wxEXPAND, 5 ); + bSizer160->Add( m_bpButtonLocalSyncCfg, 0, wxEXPAND, 5 ); - bSizer1771->Add( bSizer160, 1, wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer1771->Add( bSizer160, 1, wxALIGN_CENTER_HORIZONTAL, 5 ); - m_panelTopCenter->SetSizer( bSizer1771 ); - m_panelTopCenter->Layout(); - bSizer1771->Fit( m_panelTopCenter ); - bSizer91->Add( m_panelTopCenter, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + m_panelTopCenter->SetSizer( bSizer1771 ); + m_panelTopCenter->Layout(); + bSizer1771->Fit( m_panelTopCenter ); + bSizer91->Add( m_panelTopCenter, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - m_panelTopRight = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelTopRight->SetMinSize( wxSize( 1,-1 ) ); + m_panelTopRight = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelTopRight->SetMinSize( wxSize( 1, -1 ) ); - wxBoxSizer* bSizer183; - bSizer183 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer183; + bSizer183 = new wxBoxSizer( wxVERTICAL ); - m_staticTextResolvedPathR = new wxStaticText( m_panelTopRight, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextResolvedPathR->Wrap( -1 ); - bSizer183->Add( m_staticTextResolvedPathR, 0, wxALL, 2 ); + m_staticTextResolvedPathR = new wxStaticText( m_panelTopRight, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextResolvedPathR->Wrap( -1 ); + bSizer183->Add( m_staticTextResolvedPathR, 0, wxALL, 2 ); - wxBoxSizer* bSizer179; - bSizer179 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer179; + bSizer179 = new wxBoxSizer( wxHORIZONTAL ); - m_folderPathRight = new fff::FolderHistoryBox( m_panelTopRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer179->Add( m_folderPathRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_folderPathRight = new fff::FolderHistoryBox( m_panelTopRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer179->Add( m_folderPathRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectFolderRight = new wxButton( m_panelTopRight, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectFolderRight->SetToolTip( _("Select a folder") ); + m_buttonSelectFolderRight = new wxButton( m_panelTopRight, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectFolderRight->SetToolTip( _("Select a folder") ); - bSizer179->Add( m_buttonSelectFolderRight, 0, wxEXPAND, 5 ); + bSizer179->Add( m_buttonSelectFolderRight, 0, wxEXPAND, 5 ); - m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSelectAltFolderRight->SetToolTip( _("Access online storage") ); + m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSelectAltFolderRight->SetToolTip( _("Access online storage") ); - bSizer179->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 ); + bSizer179->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 ); - bSizer183->Add( bSizer179, 0, wxEXPAND, 5 ); + bSizer183->Add( bSizer179, 0, wxEXPAND, 5 ); - m_panelTopRight->SetSizer( bSizer183 ); - m_panelTopRight->Layout(); - bSizer183->Fit( m_panelTopRight ); - bSizer91->Add( m_panelTopRight, 1, wxRIGHT|wxALIGN_BOTTOM, 5 ); + m_panelTopRight->SetSizer( bSizer183 ); + m_panelTopRight->Layout(); + bSizer183->Fit( m_panelTopRight ); + bSizer91->Add( m_panelTopRight, 1, wxRIGHT|wxALIGN_BOTTOM, 5 ); - bSizer1601->Add( bSizer91, 0, wxEXPAND, 5 ); + bSizer1601->Add( bSizer91, 0, wxEXPAND, 5 ); - m_scrolledWindowFolderPairs = new wxScrolledWindow( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxHSCROLL|wxVSCROLL ); - m_scrolledWindowFolderPairs->SetScrollRate( 5, 5 ); - m_scrolledWindowFolderPairs->SetMinSize( wxSize( -1,0 ) ); + m_scrolledWindowFolderPairs = new wxScrolledWindow( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxHSCROLL|wxVSCROLL ); + m_scrolledWindowFolderPairs->SetScrollRate( 5, 5 ); + m_scrolledWindowFolderPairs->SetMinSize( wxSize( -1, 0 ) ); - bSizerAddFolderPairs = new wxBoxSizer( wxVERTICAL ); + bSizerAddFolderPairs = new wxBoxSizer( wxVERTICAL ); - m_scrolledWindowFolderPairs->SetSizer( bSizerAddFolderPairs ); - m_scrolledWindowFolderPairs->Layout(); - bSizerAddFolderPairs->Fit( m_scrolledWindowFolderPairs ); - bSizer1601->Add( m_scrolledWindowFolderPairs, 1, wxEXPAND, 5 ); + m_scrolledWindowFolderPairs->SetSizer( bSizerAddFolderPairs ); + m_scrolledWindowFolderPairs->Layout(); + bSizerAddFolderPairs->Fit( m_scrolledWindowFolderPairs ); + bSizer1601->Add( m_scrolledWindowFolderPairs, 1, wxEXPAND, 5 ); - m_panelDirectoryPairs->SetSizer( bSizer1601 ); - m_panelDirectoryPairs->Layout(); - bSizer1601->Fit( m_panelDirectoryPairs ); - bSizerPanelHolder->Add( m_panelDirectoryPairs, 0, wxEXPAND, 5 ); + m_panelDirectoryPairs->SetSizer( bSizer1601 ); + m_panelDirectoryPairs->Layout(); + bSizer1601->Fit( m_panelDirectoryPairs ); + bSizerPanelHolder->Add( m_panelDirectoryPairs, 0, wxEXPAND, 5 ); - m_gridOverview = new zen::Grid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridOverview->SetScrollRate( 5, 5 ); - bSizerPanelHolder->Add( m_gridOverview, 0, 0, 5 ); + m_gridOverview = new zen::Grid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_gridOverview->SetScrollRate( 5, 5 ); + bSizerPanelHolder->Add( m_gridOverview, 0, 0, 5 ); - m_panelCenter = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1711; - bSizer1711 = new wxBoxSizer( wxVERTICAL ); + m_panelCenter = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1711; + bSizer1711 = new wxBoxSizer( wxVERTICAL ); - m_splitterMain = new fff::TripleSplitter( m_panelCenter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1781; - bSizer1781 = new wxBoxSizer( wxHORIZONTAL ); + m_splitterMain = new fff::TripleSplitter( m_panelCenter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1781; + bSizer1781 = new wxBoxSizer( wxHORIZONTAL ); - m_gridMainL = new zen::Grid( m_splitterMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridMainL->SetScrollRate( 5, 5 ); - bSizer1781->Add( m_gridMainL, 1, wxEXPAND, 5 ); + m_gridMainL = new zen::Grid( m_splitterMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_gridMainL->SetScrollRate( 5, 5 ); + bSizer1781->Add( m_gridMainL, 1, wxEXPAND, 5 ); - m_gridMainC = new zen::Grid( m_splitterMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridMainC->SetScrollRate( 5, 5 ); - bSizer1781->Add( m_gridMainC, 0, wxEXPAND, 5 ); + m_gridMainC = new zen::Grid( m_splitterMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_gridMainC->SetScrollRate( 5, 5 ); + bSizer1781->Add( m_gridMainC, 0, wxEXPAND, 5 ); - m_gridMainR = new zen::Grid( m_splitterMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridMainR->SetScrollRate( 5, 5 ); - bSizer1781->Add( m_gridMainR, 1, wxEXPAND, 5 ); + m_gridMainR = new zen::Grid( m_splitterMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_gridMainR->SetScrollRate( 5, 5 ); + bSizer1781->Add( m_gridMainR, 1, wxEXPAND, 5 ); - m_splitterMain->SetSizer( bSizer1781 ); - m_splitterMain->Layout(); - bSizer1781->Fit( m_splitterMain ); - bSizer1711->Add( m_splitterMain, 1, wxEXPAND, 5 ); + m_splitterMain->SetSizer( bSizer1781 ); + m_splitterMain->Layout(); + bSizer1781->Fit( m_splitterMain ); + bSizer1711->Add( m_splitterMain, 1, wxEXPAND, 5 ); - m_panelStatusBar = new wxPanel( m_panelCenter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_STATIC ); - wxBoxSizer* bSizer451; - bSizer451 = new wxBoxSizer( wxHORIZONTAL ); + m_panelStatusBar = new wxPanel( m_panelCenter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_STATIC ); + wxBoxSizer* bSizer451; + bSizer451 = new wxBoxSizer( wxHORIZONTAL ); - bSizerFileStatus = new wxBoxSizer( wxHORIZONTAL ); + bSizerFileStatus = new wxBoxSizer( wxHORIZONTAL ); - bSizerStatusLeft = new wxBoxSizer( wxHORIZONTAL ); + bSizerStatusLeft = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer53; - bSizer53 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer53; + bSizer53 = new wxBoxSizer( wxHORIZONTAL ); - bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusLeftDirectories = new wxBoxSizer( wxHORIZONTAL ); + bSizerStatusLeftDirectories = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapSmallDirectoryLeft = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStatusLeftDirectories->Add( m_bitmapSmallDirectoryLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapSmallDirectoryLeft = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerStatusLeftDirectories->Add( m_bitmapSmallDirectoryLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusLeftDirectories->Add( 2, 0, 0, 0, 5 ); + bSizerStatusLeftDirectories->Add( 2, 0, 0, 0, 5 ); - m_staticTextStatusLeftDirs = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusLeftDirs->Wrap( -1 ); - bSizerStatusLeftDirectories->Add( m_staticTextStatusLeftDirs, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_staticTextStatusLeftDirs = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusLeftDirs->Wrap( -1 ); + bSizerStatusLeftDirectories->Add( m_staticTextStatusLeftDirs, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer53->Add( bSizerStatusLeftDirectories, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer53->Add( bSizerStatusLeftDirectories, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusLeftFiles = new wxBoxSizer( wxHORIZONTAL ); + bSizerStatusLeftFiles = new wxBoxSizer( wxHORIZONTAL ); - bSizerStatusLeftFiles->Add( 10, 0, 0, 0, 5 ); + bSizerStatusLeftFiles->Add( 10, 0, 0, 0, 5 ); - m_bitmapSmallFileLeft = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStatusLeftFiles->Add( m_bitmapSmallFileLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapSmallFileLeft = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerStatusLeftFiles->Add( m_bitmapSmallFileLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusLeftFiles->Add( 2, 0, 0, 0, 5 ); + bSizerStatusLeftFiles->Add( 2, 0, 0, 0, 5 ); - m_staticTextStatusLeftFiles = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusLeftFiles->Wrap( -1 ); - bSizerStatusLeftFiles->Add( m_staticTextStatusLeftFiles, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextStatusLeftFiles = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusLeftFiles->Wrap( -1 ); + bSizerStatusLeftFiles->Add( m_staticTextStatusLeftFiles, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusLeftFiles->Add( 4, 0, 0, 0, 5 ); + bSizerStatusLeftFiles->Add( 4, 0, 0, 0, 5 ); - m_staticTextStatusLeftBytes = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusLeftBytes->Wrap( -1 ); - bSizerStatusLeftFiles->Add( m_staticTextStatusLeftBytes, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextStatusLeftBytes = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusLeftBytes->Wrap( -1 ); + bSizerStatusLeftFiles->Add( m_staticTextStatusLeftBytes, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer53->Add( bSizerStatusLeftFiles, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer53->Add( bSizerStatusLeftFiles, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusLeft->Add( bSizer53, 1, wxEXPAND, 5 ); + bSizerStatusLeft->Add( bSizer53, 1, wxEXPAND, 5 ); - m_staticline9 = new wxStaticLine( m_panelStatusBar, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerStatusLeft->Add( m_staticline9, 0, wxEXPAND|wxTOP, 2 ); + m_staticline9 = new wxStaticLine( m_panelStatusBar, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizerStatusLeft->Add( m_staticline9, 0, wxEXPAND|wxTOP, 2 ); - bSizerFileStatus->Add( bSizerStatusLeft, 1, wxEXPAND, 5 ); + bSizerFileStatus->Add( bSizerStatusLeft, 1, wxEXPAND, 5 ); - bSizerFileStatus->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizerFileStatus->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextStatusCenter = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusCenter->Wrap( -1 ); - bSizerFileStatus->Add( m_staticTextStatusCenter, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextStatusCenter = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusCenter->Wrap( -1 ); + bSizerFileStatus->Add( m_staticTextStatusCenter, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerFileStatus->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizerFileStatus->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusRight = new wxBoxSizer( wxHORIZONTAL ); + bSizerStatusRight = new wxBoxSizer( wxHORIZONTAL ); - m_staticline10 = new wxStaticLine( m_panelStatusBar, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerStatusRight->Add( m_staticline10, 0, wxEXPAND|wxTOP, 2 ); + m_staticline10 = new wxStaticLine( m_panelStatusBar, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizerStatusRight->Add( m_staticline10, 0, wxEXPAND|wxTOP, 2 ); - wxBoxSizer* bSizer52; - bSizer52 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer52; + bSizer52 = new wxBoxSizer( wxHORIZONTAL ); - bSizer52->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer52->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusRightDirectories = new wxBoxSizer( wxHORIZONTAL ); + bSizerStatusRightDirectories = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapSmallDirectoryRight = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStatusRightDirectories->Add( m_bitmapSmallDirectoryRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapSmallDirectoryRight = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerStatusRightDirectories->Add( m_bitmapSmallDirectoryRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusRightDirectories->Add( 2, 0, 0, 0, 5 ); + bSizerStatusRightDirectories->Add( 2, 0, 0, 0, 5 ); - m_staticTextStatusRightDirs = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusRightDirs->Wrap( -1 ); - bSizerStatusRightDirectories->Add( m_staticTextStatusRightDirs, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextStatusRightDirs = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusRightDirs->Wrap( -1 ); + bSizerStatusRightDirectories->Add( m_staticTextStatusRightDirs, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer52->Add( bSizerStatusRightDirectories, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer52->Add( bSizerStatusRightDirectories, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusRightFiles = new wxBoxSizer( wxHORIZONTAL ); + bSizerStatusRightFiles = new wxBoxSizer( wxHORIZONTAL ); - bSizerStatusRightFiles->Add( 10, 0, 0, 0, 5 ); + bSizerStatusRightFiles->Add( 10, 0, 0, 0, 5 ); - m_bitmapSmallFileRight = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStatusRightFiles->Add( m_bitmapSmallFileRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapSmallFileRight = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerStatusRightFiles->Add( m_bitmapSmallFileRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusRightFiles->Add( 2, 0, 0, 0, 5 ); + bSizerStatusRightFiles->Add( 2, 0, 0, 0, 5 ); - m_staticTextStatusRightFiles = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusRightFiles->Wrap( -1 ); - bSizerStatusRightFiles->Add( m_staticTextStatusRightFiles, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextStatusRightFiles = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusRightFiles->Wrap( -1 ); + bSizerStatusRightFiles->Add( m_staticTextStatusRightFiles, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusRightFiles->Add( 4, 0, 0, 0, 5 ); + bSizerStatusRightFiles->Add( 4, 0, 0, 0, 5 ); - m_staticTextStatusRightBytes = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusRightBytes->Wrap( -1 ); - bSizerStatusRightFiles->Add( m_staticTextStatusRightBytes, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextStatusRightBytes = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusRightBytes->Wrap( -1 ); + bSizerStatusRightFiles->Add( m_staticTextStatusRightBytes, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer52->Add( bSizerStatusRightFiles, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer52->Add( bSizerStatusRightFiles, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer52->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer52->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatusRight->Add( bSizer52, 1, wxEXPAND, 5 ); + bSizerStatusRight->Add( bSizer52, 1, wxEXPAND, 5 ); - bSizerFileStatus->Add( bSizerStatusRight, 1, wxEXPAND, 5 ); + bSizerFileStatus->Add( bSizerStatusRight, 1, wxEXPAND, 5 ); - bSizer451->Add( bSizerFileStatus, 1, wxEXPAND, 5 ); + bSizer451->Add( bSizerFileStatus, 1, wxEXPAND, 5 ); - m_staticTextFullStatus = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextFullStatus->Wrap( -1 ); - m_staticTextFullStatus->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextFullStatus = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextFullStatus->Wrap( -1 ); + m_staticTextFullStatus->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer451->Add( m_staticTextFullStatus, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer451->Add( m_staticTextFullStatus, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_panelStatusBar->SetSizer( bSizer451 ); - m_panelStatusBar->Layout(); - bSizer451->Fit( m_panelStatusBar ); - bSizer1711->Add( m_panelStatusBar, 0, wxEXPAND, 5 ); + m_panelStatusBar->SetSizer( bSizer451 ); + m_panelStatusBar->Layout(); + bSizer451->Fit( m_panelStatusBar ); + bSizer1711->Add( m_panelStatusBar, 0, wxEXPAND, 5 ); - m_panelCenter->SetSizer( bSizer1711 ); - m_panelCenter->Layout(); - bSizer1711->Fit( m_panelCenter ); - bSizerPanelHolder->Add( m_panelCenter, 1, wxEXPAND, 5 ); + m_panelCenter->SetSizer( bSizer1711 ); + m_panelCenter->Layout(); + bSizer1711->Fit( m_panelCenter ); + bSizerPanelHolder->Add( m_panelCenter, 1, wxEXPAND, 5 ); - m_panelSearch = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1713; - bSizer1713 = new wxBoxSizer( wxHORIZONTAL ); + m_panelSearch = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1713; + bSizer1713 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonHideSearch = new wxBitmapButton( m_panelSearch, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonHideSearch->SetToolTip( _("Close search bar") ); + m_bpButtonHideSearch = new wxBitmapButton( m_panelSearch, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonHideSearch->SetToolTip( _("Close search bar") ); - bSizer1713->Add( m_bpButtonHideSearch, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer1713->Add( m_bpButtonHideSearch, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText101 = new wxStaticText( m_panelSearch, wxID_ANY, _("Find:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText101->Wrap( -1 ); - bSizer1713->Add( m_staticText101, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText101 = new wxStaticText( m_panelSearch, wxID_ANY, _("Find:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText101->Wrap( -1 ); + bSizer1713->Add( m_staticText101, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_textCtrlSearchTxt = new wxTextCtrl( m_panelSearch, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_PROCESS_ENTER|wxWANTS_CHARS ); - bSizer1713->Add( m_textCtrlSearchTxt, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + m_textCtrlSearchTxt = new wxTextCtrl( m_panelSearch, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_PROCESS_ENTER|wxWANTS_CHARS ); + bSizer1713->Add( m_textCtrlSearchTxt, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - m_checkBoxMatchCase = new wxCheckBox( m_panelSearch, wxID_ANY, _("Match case"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer1713->Add( m_checkBoxMatchCase, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_checkBoxMatchCase = new wxCheckBox( m_panelSearch, wxID_ANY, _("Match case"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer1713->Add( m_checkBoxMatchCase, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_panelSearch->SetSizer( bSizer1713 ); - m_panelSearch->Layout(); - bSizer1713->Fit( m_panelSearch ); - bSizerPanelHolder->Add( m_panelSearch, 0, 0, 5 ); + m_panelSearch->SetSizer( bSizer1713 ); + m_panelSearch->Layout(); + bSizer1713->Fit( m_panelSearch ); + bSizerPanelHolder->Add( m_panelSearch, 0, 0, 5 ); - m_panelLog = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelLog->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelLog = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelLog->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizerLog = new wxBoxSizer( wxVERTICAL ); + bSizerLog = new wxBoxSizer( wxVERTICAL ); - bSizer42 = new wxBoxSizer( wxHORIZONTAL ); + bSizer42 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapSyncResult = new wxStaticBitmap( m_panelLog, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer42->Add( m_bitmapSyncResult, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_bitmapSyncResult = new wxStaticBitmap( m_panelLog, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer42->Add( m_bitmapSyncResult, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_staticTextSyncResult = new wxStaticText( m_panelLog, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextSyncResult->Wrap( -1 ); - m_staticTextSyncResult->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextSyncResult = new wxStaticText( m_panelLog, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextSyncResult->Wrap( -1 ); + m_staticTextSyncResult->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer42->Add( m_staticTextSyncResult, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); + bSizer42->Add( m_staticTextSyncResult, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); - bSizer42->Add( 10, 0, 0, 0, 5 ); + bSizer42->Add( 10, 0, 0, 0, 5 ); - ffgSizer11 = new wxFlexGridSizer( 2, 0, 5, 5 ); - ffgSizer11->SetFlexibleDirection( wxBOTH ); - ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer11 = new wxFlexGridSizer( 2, 0, 5, 5 ); + ffgSizer11->SetFlexibleDirection( wxBOTH ); + ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticTextProcessed = new wxStaticText( m_panelLog, wxID_ANY, _("Processed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextProcessed->Wrap( -1 ); - ffgSizer11->Add( m_staticTextProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT, 5 ); + m_staticTextProcessed = new wxStaticText( m_panelLog, wxID_ANY, _("Processed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextProcessed->Wrap( -1 ); + ffgSizer11->Add( m_staticTextProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT, 5 ); - m_staticTextRemaining = new wxStaticText( m_panelLog, wxID_ANY, _("Remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextRemaining->Wrap( -1 ); - ffgSizer11->Add( m_staticTextRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_staticTextRemaining = new wxStaticText( m_panelLog, wxID_ANY, _("Remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextRemaining->Wrap( -1 ); + ffgSizer11->Add( m_staticTextRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer42->Add( ffgSizer11, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 10 ); + bSizer42->Add( ffgSizer11, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 10 ); - m_panelItemStats = new wxPanel( m_panelLog, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelItemStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_panelItemStats = new wxPanel( m_panelLog, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panelItemStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer291; - bSizer291 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer291; + bSizer291 = new wxBoxSizer( wxVERTICAL ); - ffgSizer111 = new wxFlexGridSizer( 0, 2, 5, 5 ); - ffgSizer111->SetFlexibleDirection( wxBOTH ); - ffgSizer111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer111 = new wxFlexGridSizer( 0, 2, 5, 5 ); + ffgSizer111->SetFlexibleDirection( wxBOTH ); + ffgSizer111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - wxBoxSizer* bSizer293; - bSizer293 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer293; + bSizer293 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapItemStat = new wxStaticBitmap( m_panelItemStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer293->Add( m_bitmapItemStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapItemStat = new wxStaticBitmap( m_panelItemStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer293->Add( m_bitmapItemStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer293->Add( 0, 0, 1, 0, 5 ); + bSizer293->Add( 0, 0, 1, 0, 5 ); - m_staticTextItemsProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextItemsProcessed->Wrap( -1 ); - m_staticTextItemsProcessed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextItemsProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticTextItemsProcessed->Wrap( -1 ); + m_staticTextItemsProcessed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer293->Add( m_staticTextItemsProcessed, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer293->Add( m_staticTextItemsProcessed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - ffgSizer111->Add( bSizer293, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + ffgSizer111->Add( bSizer293, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticTextBytesProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextBytesProcessed->Wrap( -1 ); - ffgSizer111->Add( m_staticTextBytesProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + m_staticTextBytesProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextBytesProcessed->Wrap( -1 ); + ffgSizer111->Add( m_staticTextBytesProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); - m_staticTextItemsRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextItemsRemaining->Wrap( -1 ); - m_staticTextItemsRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextItemsRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticTextItemsRemaining->Wrap( -1 ); + m_staticTextItemsRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - ffgSizer111->Add( m_staticTextItemsRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer111->Add( m_staticTextItemsRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextBytesRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextBytesRemaining->Wrap( -1 ); - ffgSizer111->Add( m_staticTextBytesRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextBytesRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextBytesRemaining->Wrap( -1 ); + ffgSizer111->Add( m_staticTextBytesRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer291->Add( ffgSizer111, 0, wxALL, 5 ); + bSizer291->Add( ffgSizer111, 0, wxALL, 5 ); - m_panelItemStats->SetSizer( bSizer291 ); - m_panelItemStats->Layout(); - bSizer291->Fit( m_panelItemStats ); - bSizer42->Add( m_panelItemStats, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); + m_panelItemStats->SetSizer( bSizer291 ); + m_panelItemStats->Layout(); + bSizer291->Fit( m_panelItemStats ); + bSizer42->Add( m_panelItemStats, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); - m_panelTimeStats = new wxPanel( m_panelLog, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelTimeStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_panelTimeStats = new wxPanel( m_panelLog, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panelTimeStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer292; - bSizer292 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer292; + bSizer292 = new wxBoxSizer( wxVERTICAL ); - ffgSizer112 = new wxFlexGridSizer( 0, 1, 5, 5 ); - ffgSizer112->SetFlexibleDirection( wxBOTH ); - ffgSizer112->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer112 = new wxFlexGridSizer( 0, 1, 5, 5 ); + ffgSizer112->SetFlexibleDirection( wxBOTH ); + ffgSizer112->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - wxBoxSizer* bSizer294; - bSizer294 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer294; + bSizer294 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapTimeStat = new wxStaticBitmap( m_panelTimeStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer294->Add( m_bitmapTimeStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapTimeStat = new wxStaticBitmap( m_panelTimeStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer294->Add( m_bitmapTimeStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer294->Add( 0, 0, 1, 0, 5 ); + bSizer294->Add( 0, 0, 1, 0, 5 ); - m_staticTextTimeElapsed = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeElapsed->Wrap( -1 ); - m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextTimeElapsed = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeElapsed->Wrap( -1 ); + m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer294->Add( m_staticTextTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer294->Add( m_staticTextTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - ffgSizer112->Add( bSizer294, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + ffgSizer112->Add( bSizer294, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - bSizer292->Add( ffgSizer112, 0, wxALL, 5 ); + bSizer292->Add( ffgSizer112, 0, wxALL, 5 ); - m_panelTimeStats->SetSizer( bSizer292 ); - m_panelTimeStats->Layout(); - bSizer292->Fit( m_panelTimeStats ); - bSizer42->Add( m_panelTimeStats, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); + m_panelTimeStats->SetSizer( bSizer292 ); + m_panelTimeStats->Layout(); + bSizer292->Fit( m_panelTimeStats ); + bSizer42->Add( m_panelTimeStats, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); - bSizerLog->Add( bSizer42, 0, wxLEFT, 5 ); + bSizerLog->Add( bSizer42, 0, wxLEFT, 5 ); - m_staticline70 = new wxStaticLine( m_panelLog, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerLog->Add( m_staticline70, 0, wxEXPAND, 5 ); + m_staticline70 = new wxStaticLine( m_panelLog, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerLog->Add( m_staticline70, 0, wxEXPAND, 5 ); - m_panelLog->SetSizer( bSizerLog ); - m_panelLog->Layout(); - bSizerLog->Fit( m_panelLog ); - bSizerPanelHolder->Add( m_panelLog, 0, 0, 5 ); + m_panelLog->SetSizer( bSizerLog ); + m_panelLog->Layout(); + bSizerLog->Fit( m_panelLog ); + bSizerPanelHolder->Add( m_panelLog, 0, 0, 5 ); - m_panelConfig = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelConfig->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelConfig = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelConfig->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizerConfig = new wxBoxSizer( wxVERTICAL ); + bSizerConfig = new wxBoxSizer( wxVERTICAL ); - bSizerCfgHistoryButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerCfgHistoryButtons = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer17611; - bSizer17611 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer17611; + bSizer17611 = new wxBoxSizer( wxVERTICAL ); - m_bpButtonNew = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonNew->SetToolTip( _("dummy") ); + m_bpButtonNew = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonNew->SetToolTip( _("dummy") ); - bSizer17611->Add( m_bpButtonNew, 0, wxEXPAND, 5 ); + bSizer17611->Add( m_bpButtonNew, 0, wxEXPAND, 5 ); - m_staticText951 = new wxStaticText( m_panelConfig, wxID_ANY, _("New"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText951->Wrap( -1 ); - bSizer17611->Add( m_staticText951, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 2 ); + m_staticText951 = new wxStaticText( m_panelConfig, wxID_ANY, _("New"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText951->Wrap( -1 ); + bSizer17611->Add( m_staticText951, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 2 ); - bSizerCfgHistoryButtons->Add( bSizer17611, 0, 0, 5 ); + bSizerCfgHistoryButtons->Add( bSizer17611, 0, 0, 5 ); - wxBoxSizer* bSizer1761; - bSizer1761 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer1761; + bSizer1761 = new wxBoxSizer( wxVERTICAL ); - m_bpButtonOpen = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonOpen->SetToolTip( _("dummy") ); + m_bpButtonOpen = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonOpen->SetToolTip( _("dummy") ); - bSizer1761->Add( m_bpButtonOpen, 0, wxEXPAND, 5 ); + bSizer1761->Add( m_bpButtonOpen, 0, wxEXPAND, 5 ); - m_staticText95 = new wxStaticText( m_panelConfig, wxID_ANY, _("Open..."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText95->Wrap( -1 ); - bSizer1761->Add( m_staticText95, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 2 ); + m_staticText95 = new wxStaticText( m_panelConfig, wxID_ANY, _("Open..."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText95->Wrap( -1 ); + bSizer1761->Add( m_staticText95, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 2 ); - bSizerCfgHistoryButtons->Add( bSizer1761, 0, 0, 5 ); + bSizerCfgHistoryButtons->Add( bSizer1761, 0, 0, 5 ); - wxBoxSizer* bSizer175; - bSizer175 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer175; + bSizer175 = new wxBoxSizer( wxVERTICAL ); - m_bpButtonSave = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSave->SetToolTip( _("dummy") ); + m_bpButtonSave = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSave->SetToolTip( _("dummy") ); - bSizer175->Add( m_bpButtonSave, 0, wxEXPAND, 5 ); + bSizer175->Add( m_bpButtonSave, 0, wxEXPAND, 5 ); - m_staticText961 = new wxStaticText( m_panelConfig, wxID_ANY, _("Save"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText961->Wrap( -1 ); - bSizer175->Add( m_staticText961, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 2 ); + m_staticText961 = new wxStaticText( m_panelConfig, wxID_ANY, _("Save"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText961->Wrap( -1 ); + bSizer175->Add( m_staticText961, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 2 ); - bSizerCfgHistoryButtons->Add( bSizer175, 0, 0, 5 ); + bSizerCfgHistoryButtons->Add( bSizer175, 0, 0, 5 ); - wxBoxSizer* bSizer174; - bSizer174 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer174; + bSizer174 = new wxBoxSizer( wxVERTICAL ); - bSizerSaveAs = new wxBoxSizer( wxHORIZONTAL ); + bSizerSaveAs = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonSaveAs = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSaveAs->SetToolTip( _("dummy") ); + m_bpButtonSaveAs = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSaveAs->SetToolTip( _("dummy") ); - bSizerSaveAs->Add( m_bpButtonSaveAs, 1, 0, 5 ); + bSizerSaveAs->Add( m_bpButtonSaveAs, 1, 0, 5 ); - m_bpButtonSaveAsBatch = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSaveAsBatch->SetToolTip( _("dummy") ); + m_bpButtonSaveAsBatch = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSaveAsBatch->SetToolTip( _("dummy") ); - bSizerSaveAs->Add( m_bpButtonSaveAsBatch, 1, 0, 5 ); + bSizerSaveAs->Add( m_bpButtonSaveAsBatch, 1, 0, 5 ); - bSizer174->Add( bSizerSaveAs, 0, wxEXPAND, 5 ); + bSizer174->Add( bSizerSaveAs, 0, wxEXPAND, 5 ); - m_staticText97 = new wxStaticText( m_panelConfig, wxID_ANY, _("Save as..."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText97->Wrap( -1 ); - bSizer174->Add( m_staticText97, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 2 ); + m_staticText97 = new wxStaticText( m_panelConfig, wxID_ANY, _("Save as..."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText97->Wrap( -1 ); + bSizer174->Add( m_staticText97, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 2 ); - bSizerCfgHistoryButtons->Add( bSizer174, 0, 0, 5 ); + bSizerCfgHistoryButtons->Add( bSizer174, 0, 0, 5 ); - bSizerConfig->Add( bSizerCfgHistoryButtons, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizerConfig->Add( bSizerCfgHistoryButtons, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - m_staticline81 = new wxStaticLine( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerConfig->Add( m_staticline81, 0, wxEXPAND|wxTOP, 5 ); + m_staticline81 = new wxStaticLine( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerConfig->Add( m_staticline81, 0, wxEXPAND|wxTOP, 5 ); - bSizerConfig->Add( 10, 0, 0, 0, 5 ); + bSizerConfig->Add( 10, 0, 0, 0, 5 ); - m_gridCfgHistory = new zen::Grid( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridCfgHistory->SetScrollRate( 5, 5 ); - bSizerConfig->Add( m_gridCfgHistory, 1, wxEXPAND, 5 ); + m_gridCfgHistory = new zen::Grid( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_gridCfgHistory->SetScrollRate( 5, 5 ); + bSizerConfig->Add( m_gridCfgHistory, 1, wxEXPAND, 5 ); - m_panelConfig->SetSizer( bSizerConfig ); - m_panelConfig->Layout(); - bSizerConfig->Fit( m_panelConfig ); - bSizerPanelHolder->Add( m_panelConfig, 0, 0, 5 ); + m_panelConfig->SetSizer( bSizerConfig ); + m_panelConfig->Layout(); + bSizerConfig->Fit( m_panelConfig ); + bSizerPanelHolder->Add( m_panelConfig, 0, 0, 5 ); - m_panelViewFilter = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelViewFilter->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelViewFilter = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelViewFilter->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizerViewFilter = new wxBoxSizer( wxHORIZONTAL ); + bSizerViewFilter = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonToggleLog = new wxBitmapButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizerViewFilter->Add( m_bpButtonToggleLog, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_bpButtonToggleLog = new wxBitmapButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizerViewFilter->Add( m_bpButtonToggleLog, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizerViewFilter->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizerViewFilter->Add( 0, 0, 1, wxEXPAND, 5 ); - bSizerViewButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerViewButtons = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonViewType = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonViewType, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bpButtonViewType = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonViewType, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerViewButtons->Add( 10, 10, 0, 0, 5 ); + bSizerViewButtons->Add( 10, 10, 0, 0, 5 ); - m_bpButtonShowExcluded = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowExcluded, 0, wxEXPAND, 5 ); + m_bpButtonShowExcluded = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowExcluded, 0, wxEXPAND, 5 ); - bSizerViewButtons->Add( 10, 10, 0, 0, 5 ); + bSizerViewButtons->Add( 10, 10, 0, 0, 5 ); - m_bpButtonShowDeleteLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowDeleteLeft, 0, wxEXPAND, 5 ); + m_bpButtonShowDeleteLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowDeleteLeft, 0, wxEXPAND, 5 ); - m_bpButtonShowUpdateLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowUpdateLeft, 0, wxEXPAND, 5 ); + m_bpButtonShowUpdateLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowUpdateLeft, 0, wxEXPAND, 5 ); - m_bpButtonShowCreateLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowCreateLeft, 0, wxEXPAND, 5 ); + m_bpButtonShowCreateLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowCreateLeft, 0, wxEXPAND, 5 ); - m_bpButtonShowLeftOnly = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowLeftOnly, 0, wxEXPAND, 5 ); + m_bpButtonShowLeftOnly = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowLeftOnly, 0, wxEXPAND, 5 ); - m_bpButtonShowLeftNewer = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowLeftNewer, 0, wxEXPAND, 5 ); + m_bpButtonShowLeftNewer = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowLeftNewer, 0, wxEXPAND, 5 ); - m_bpButtonShowEqual = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowEqual, 0, wxEXPAND, 5 ); + m_bpButtonShowEqual = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowEqual, 0, wxEXPAND, 5 ); - m_bpButtonShowDoNothing = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowDoNothing, 0, wxEXPAND, 5 ); + m_bpButtonShowDoNothing = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowDoNothing, 0, wxEXPAND, 5 ); - m_bpButtonShowDifferent = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowDifferent, 0, wxEXPAND, 5 ); + m_bpButtonShowDifferent = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowDifferent, 0, wxEXPAND, 5 ); - m_bpButtonShowRightNewer = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowRightNewer, 0, wxEXPAND, 5 ); + m_bpButtonShowRightNewer = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowRightNewer, 0, wxEXPAND, 5 ); - m_bpButtonShowRightOnly = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowRightOnly, 0, wxEXPAND, 5 ); + m_bpButtonShowRightOnly = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowRightOnly, 0, wxEXPAND, 5 ); - m_bpButtonShowCreateRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowCreateRight, 0, wxEXPAND, 5 ); + m_bpButtonShowCreateRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowCreateRight, 0, wxEXPAND, 5 ); - m_bpButtonShowUpdateRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowUpdateRight, 0, wxEXPAND, 5 ); + m_bpButtonShowUpdateRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowUpdateRight, 0, wxEXPAND, 5 ); - m_bpButtonShowDeleteRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowDeleteRight, 0, wxEXPAND, 5 ); + m_bpButtonShowDeleteRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowDeleteRight, 0, wxEXPAND, 5 ); - m_bpButtonShowConflict = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonShowConflict, 0, wxEXPAND, 5 ); + m_bpButtonShowConflict = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonShowConflict, 0, wxEXPAND, 5 ); - m_bpButtonViewFilterContext = new wxBitmapButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizerViewButtons->Add( m_bpButtonViewFilterContext, 0, wxEXPAND, 5 ); + m_bpButtonViewFilterContext = new wxBitmapButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizerViewButtons->Add( m_bpButtonViewFilterContext, 0, wxEXPAND, 5 ); - bSizerViewFilter->Add( bSizerViewButtons, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizerViewFilter->Add( bSizerViewButtons, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizerViewFilter->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizerViewFilter->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticText96 = new wxStaticText( m_panelViewFilter, wxID_ANY, _("Statistics:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText96->Wrap( -1 ); - bSizerViewFilter->Add( m_staticText96, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_staticText96 = new wxStaticText( m_panelViewFilter, wxID_ANY, _("Statistics:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText96->Wrap( -1 ); + bSizerViewFilter->Add( m_staticText96, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_panelStatistics = new wxPanel( m_panelViewFilter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_SUNKEN ); - m_panelStatistics->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelStatistics = new wxPanel( m_panelViewFilter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_SUNKEN ); + m_panelStatistics->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizer1801 = new wxBoxSizer( wxVERTICAL ); + bSizer1801 = new wxBoxSizer( wxVERTICAL ); - bSizerStatistics = new wxBoxSizer( wxHORIZONTAL ); + bSizerStatistics = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer173; - bSizer173 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer173; + bSizer173 = new wxBoxSizer( wxVERTICAL ); - m_bitmapDeleteLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); + m_bitmapDeleteLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); - bSizer173->Add( m_bitmapDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer173->Add( m_bitmapDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer173->Add( 5, 2, 0, 0, 5 ); + bSizer173->Add( 5, 2, 0, 0, 5 ); - bSizer173->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer173->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticTextDeleteLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDeleteLeft->Wrap( -1 ); - m_staticTextDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); + m_staticTextDeleteLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDeleteLeft->Wrap( -1 ); + m_staticTextDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); - bSizer173->Add( m_staticTextDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer173->Add( m_staticTextDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatistics->Add( bSizer173, 0, wxEXPAND, 5 ); + bSizerStatistics->Add( bSizer173, 0, wxEXPAND, 5 ); - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); + bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - wxBoxSizer* bSizer172; - bSizer172 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer172; + bSizer172 = new wxBoxSizer( wxVERTICAL ); - m_bitmapUpdateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdateLeft->SetToolTip( _("Number of files that will be updated") ); + m_bitmapUpdateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapUpdateLeft->SetToolTip( _("Number of files that will be updated") ); - bSizer172->Add( m_bitmapUpdateLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer172->Add( m_bitmapUpdateLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer172->Add( 5, 2, 0, 0, 5 ); + bSizer172->Add( 5, 2, 0, 0, 5 ); - bSizer172->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer172->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticTextUpdateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextUpdateLeft->Wrap( -1 ); - m_staticTextUpdateLeft->SetToolTip( _("Number of files that will be updated") ); + m_staticTextUpdateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextUpdateLeft->Wrap( -1 ); + m_staticTextUpdateLeft->SetToolTip( _("Number of files that will be updated") ); - bSizer172->Add( m_staticTextUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer172->Add( m_staticTextUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizerStatistics->Add( bSizer172, 0, wxEXPAND, 5 ); + bSizerStatistics->Add( bSizer172, 0, wxEXPAND, 5 ); - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); + bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - wxBoxSizer* bSizer1712; - bSizer1712 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer1712; + bSizer1712 = new wxBoxSizer( wxVERTICAL ); - m_bitmapCreateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); + m_bitmapCreateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); - bSizer1712->Add( m_bitmapCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer1712->Add( m_bitmapCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer1712->Add( 5, 2, 0, 0, 5 ); + bSizer1712->Add( 5, 2, 0, 0, 5 ); - bSizer1712->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer1712->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticTextCreateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCreateLeft->Wrap( -1 ); - m_staticTextCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); + m_staticTextCreateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCreateLeft->Wrap( -1 ); + m_staticTextCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); - bSizer1712->Add( m_staticTextCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer1712->Add( m_staticTextCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizerStatistics->Add( bSizer1712, 0, wxEXPAND, 5 ); + bSizerStatistics->Add( bSizer1712, 0, wxEXPAND, 5 ); - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); + bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - bSizerData = new wxBoxSizer( wxVERTICAL ); + bSizerData = new wxBoxSizer( wxVERTICAL ); - m_bitmapData = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapData->SetToolTip( _("Total bytes to copy") ); + m_bitmapData = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapData->SetToolTip( _("Total bytes to copy") ); - bSizerData->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizerData->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizerData->Add( 5, 2, 0, 0, 5 ); + bSizerData->Add( 5, 2, 0, 0, 5 ); - bSizerData->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizerData->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticTextData = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextData->Wrap( -1 ); - m_staticTextData->SetToolTip( _("Total bytes to copy") ); + m_staticTextData = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextData->Wrap( -1 ); + m_staticTextData->SetToolTip( _("Total bytes to copy") ); - bSizerData->Add( m_staticTextData, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerData->Add( m_staticTextData, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatistics->Add( bSizerData, 0, wxEXPAND, 5 ); + bSizerStatistics->Add( bSizerData, 0, wxEXPAND, 5 ); - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); + bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - wxBoxSizer* bSizer178; - bSizer178 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer178; + bSizer178 = new wxBoxSizer( wxVERTICAL ); - m_bitmapCreateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreateRight->SetToolTip( _("Number of files and folders that will be created") ); + m_bitmapCreateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapCreateRight->SetToolTip( _("Number of files and folders that will be created") ); - bSizer178->Add( m_bitmapCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer178->Add( m_bitmapCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer178->Add( 5, 2, 0, 0, 5 ); + bSizer178->Add( 5, 2, 0, 0, 5 ); - bSizer178->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer178->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticTextCreateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCreateRight->Wrap( -1 ); - m_staticTextCreateRight->SetToolTip( _("Number of files and folders that will be created") ); + m_staticTextCreateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCreateRight->Wrap( -1 ); + m_staticTextCreateRight->SetToolTip( _("Number of files and folders that will be created") ); - bSizer178->Add( m_staticTextCreateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer178->Add( m_staticTextCreateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatistics->Add( bSizer178, 0, wxEXPAND, 5 ); + bSizerStatistics->Add( bSizer178, 0, wxEXPAND, 5 ); - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); + bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - wxBoxSizer* bSizer177; - bSizer177 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer177; + bSizer177 = new wxBoxSizer( wxVERTICAL ); - m_bitmapUpdateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdateRight->SetToolTip( _("Number of files that will be updated") ); + m_bitmapUpdateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapUpdateRight->SetToolTip( _("Number of files that will be updated") ); - bSizer177->Add( m_bitmapUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer177->Add( m_bitmapUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer177->Add( 5, 2, 0, 0, 5 ); + bSizer177->Add( 5, 2, 0, 0, 5 ); - bSizer177->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer177->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticTextUpdateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextUpdateRight->Wrap( -1 ); - m_staticTextUpdateRight->SetToolTip( _("Number of files that will be updated") ); + m_staticTextUpdateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextUpdateRight->Wrap( -1 ); + m_staticTextUpdateRight->SetToolTip( _("Number of files that will be updated") ); - bSizer177->Add( m_staticTextUpdateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer177->Add( m_staticTextUpdateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatistics->Add( bSizer177, 0, wxEXPAND, 5 ); + bSizerStatistics->Add( bSizer177, 0, wxEXPAND, 5 ); - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); + bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - wxBoxSizer* bSizer176; - bSizer176 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer176; + bSizer176 = new wxBoxSizer( wxVERTICAL ); - m_bitmapDeleteRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); + m_bitmapDeleteRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); - bSizer176->Add( m_bitmapDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer176->Add( m_bitmapDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer176->Add( 5, 2, 0, 0, 5 ); + bSizer176->Add( 5, 2, 0, 0, 5 ); - bSizer176->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer176->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticTextDeleteRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDeleteRight->Wrap( -1 ); - m_staticTextDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); + m_staticTextDeleteRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDeleteRight->Wrap( -1 ); + m_staticTextDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); - bSizer176->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer176->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStatistics->Add( bSizer176, 0, wxEXPAND, 5 ); + bSizerStatistics->Add( bSizer176, 0, wxEXPAND, 5 ); - bSizer1801->Add( bSizerStatistics, 0, wxALL, 4 ); + bSizer1801->Add( bSizerStatistics, 0, wxALL, 4 ); - m_panelStatistics->SetSizer( bSizer1801 ); - m_panelStatistics->Layout(); - bSizer1801->Fit( m_panelStatistics ); - bSizerViewFilter->Add( m_panelStatistics, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_panelStatistics->SetSizer( bSizer1801 ); + m_panelStatistics->Layout(); + bSizer1801->Fit( m_panelStatistics ); + bSizerViewFilter->Add( m_panelStatistics, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_panelViewFilter->SetSizer( bSizerViewFilter ); - m_panelViewFilter->Layout(); - bSizerViewFilter->Fit( m_panelViewFilter ); - bSizerPanelHolder->Add( m_panelViewFilter, 0, 0, 5 ); + m_panelViewFilter->SetSizer( bSizerViewFilter ); + m_panelViewFilter->Layout(); + bSizerViewFilter->Fit( m_panelViewFilter ); + bSizerPanelHolder->Add( m_panelViewFilter, 0, 0, 5 ); - this->SetSizer( bSizerPanelHolder ); - this->Layout(); - bSizerPanelHolder->Fit( this ); + this->SetSizer( bSizerPanelHolder ); + this->Layout(); + bSizerPanelHolder->Fit( this ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDialogGenerated::onClose ) ); - m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigNew ), this, m_menuItemNew->GetId()); - m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigLoad ), this, m_menuItemLoad->GetId()); - m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigSave ), this, m_menuItemSave->GetId()); - m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigSaveAs ), this, m_menuItemSaveAs->GetId()); - m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onSaveAsBatchJob ), this, m_menuItemSaveAsBatch->GetId()); - m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuQuit ), this, m_menuItemQuit->GetId()); - m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onToggleLog ), this, m_menuItemShowLog->GetId()); - m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onCompare ), this, m_menuItemCompare->GetId()); - m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onCmpSettings ), this, m_menuItemCompSettings->GetId()); - m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigureFilter ), this, m_menuItemFilter->GetId()); - m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onSyncSettings ), this, m_menuItemSyncSettings->GetId()); - m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onStartSync ), this, m_menuItemSynchronize->GetId()); - m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuOptions ), this, m_menuItemOptions->GetId()); - m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuFindItem ), this, m_menuItemFind->GetId()); - m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuExportFileList ), this, m_menuItemExportList->GetId()); - m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuResetLayout ), this, m_menuItemResetLayout->GetId()); - m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onShowHelp ), this, m_menuItemHelp->GetId()); - m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuCheckVersion ), this, m_menuItemCheckVersionNow->GetId()); - m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuCheckVersionAutomatically ), this, m_menuItemCheckVersionAuto->GetId()); - m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuAbout ), this, m_menuItemAbout->GetId()); - m_buttonCompare->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onCompare ), NULL, this ); - m_bpButtonCmpConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onCmpSettings ), NULL, this ); - m_bpButtonCmpConfig->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onCompSettingsContextMouse ), NULL, this ); - m_bpButtonCmpContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onCompSettingsContext ), NULL, this ); - m_bpButtonCmpContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onCompSettingsContextMouse ), NULL, this ); - m_bpButtonFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigureFilter ), NULL, this ); - m_bpButtonFilter->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onGlobalFilterContextMouse ), NULL, this ); - m_bpButtonFilterContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onGlobalFilterContext ), NULL, this ); - m_bpButtonFilterContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onGlobalFilterContextMouse ), NULL, this ); - m_bpButtonSyncConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onSyncSettings ), NULL, this ); - m_bpButtonSyncConfig->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onSyncSettingsContextMouse ), NULL, this ); - m_bpButtonSyncContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onSyncSettingsContext ), NULL, this ); - m_bpButtonSyncContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onSyncSettingsContextMouse ), NULL, this ); - m_buttonSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onStartSync ), NULL, this ); - m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopFolderPairAdd ), NULL, this ); - m_bpButtonRemovePair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopFolderPairRemove ), NULL, this ); - m_bpButtonSwapSides->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onSwapSides ), NULL, this ); - m_bpButtonLocalCompCfg->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopLocalCompCfg ), NULL, this ); - m_bpButtonLocalFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopLocalFilterCfg ), NULL, this ); - m_bpButtonLocalSyncCfg->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopLocalSyncCfg ), NULL, this ); - m_bpButtonHideSearch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onHideSearchPanel ), NULL, this ); - m_textCtrlSearchTxt->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( MainDialogGenerated::onSearchGridEnter ), NULL, this ); - m_bpButtonNew->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigNew ), NULL, this ); - m_bpButtonOpen->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigLoad ), NULL, this ); - m_bpButtonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigSave ), NULL, this ); - m_bpButtonSaveAs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigSaveAs ), NULL, this ); - m_bpButtonSaveAsBatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onSaveAsBatchJob ), NULL, this ); - m_bpButtonToggleLog->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleLog ), NULL, this ); - m_bpButtonViewType->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewType ), NULL, this ); - m_bpButtonViewType->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewTypeContextMouse ), NULL, this ); - m_bpButtonShowExcluded->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowExcluded->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowDeleteLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowDeleteLeft->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowUpdateLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowUpdateLeft->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowCreateLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowCreateLeft->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowLeftOnly->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowLeftNewer->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowEqual->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowEqual->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowDoNothing->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowDoNothing->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowDifferent->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowRightNewer->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowRightOnly->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowCreateRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowCreateRight->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowUpdateRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowUpdateRight->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowDeleteRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowDeleteRight->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonShowConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); - m_bpButtonShowConflict->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); - m_bpButtonViewFilterContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onViewFilterContext ), NULL, this ); - m_bpButtonViewFilterContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDialogGenerated::onClose ) ); + m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigNew ), this, m_menuItemNew->GetId()); + m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigLoad ), this, m_menuItemLoad->GetId()); + m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigSave ), this, m_menuItemSave->GetId()); + m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigSaveAs ), this, m_menuItemSaveAs->GetId()); + m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onSaveAsBatchJob ), this, m_menuItemSaveAsBatch->GetId()); + m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuQuit ), this, m_menuItemQuit->GetId()); + m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onToggleLog ), this, m_menuItemShowLog->GetId()); + m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onCompare ), this, m_menuItemCompare->GetId()); + m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onCmpSettings ), this, m_menuItemCompSettings->GetId()); + m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onConfigureFilter ), this, m_menuItemFilter->GetId()); + m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onSyncSettings ), this, m_menuItemSyncSettings->GetId()); + m_menuActions->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onStartSync ), this, m_menuItemSynchronize->GetId()); + m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuOptions ), this, m_menuItemOptions->GetId()); + m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuFindItem ), this, m_menuItemFind->GetId()); + m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuExportFileList ), this, m_menuItemExportList->GetId()); + m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuResetLayout ), this, m_menuItemResetLayout->GetId()); + m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onShowHelp ), this, m_menuItemHelp->GetId()); + m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuCheckVersion ), this, m_menuItemCheckVersionNow->GetId()); + m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuCheckVersionAutomatically ), this, m_menuItemCheckVersionAuto->GetId()); + m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::onMenuAbout ), this, m_menuItemAbout->GetId()); + m_buttonCompare->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onCompare ), NULL, this ); + m_bpButtonCmpConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onCmpSettings ), NULL, this ); + m_bpButtonCmpConfig->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onCompSettingsContextMouse ), NULL, this ); + m_bpButtonCmpContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onCompSettingsContext ), NULL, this ); + m_bpButtonCmpContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onCompSettingsContextMouse ), NULL, this ); + m_bpButtonFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigureFilter ), NULL, this ); + m_bpButtonFilter->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onGlobalFilterContextMouse ), NULL, this ); + m_bpButtonFilterContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onGlobalFilterContext ), NULL, this ); + m_bpButtonFilterContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onGlobalFilterContextMouse ), NULL, this ); + m_bpButtonSyncConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onSyncSettings ), NULL, this ); + m_bpButtonSyncConfig->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onSyncSettingsContextMouse ), NULL, this ); + m_bpButtonSyncContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onSyncSettingsContext ), NULL, this ); + m_bpButtonSyncContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onSyncSettingsContextMouse ), NULL, this ); + m_buttonSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onStartSync ), NULL, this ); + m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopFolderPairAdd ), NULL, this ); + m_bpButtonRemovePair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopFolderPairRemove ), NULL, this ); + m_bpButtonSwapSides->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onSwapSides ), NULL, this ); + m_bpButtonLocalCompCfg->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopLocalCompCfg ), NULL, this ); + m_bpButtonLocalFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopLocalFilterCfg ), NULL, this ); + m_bpButtonLocalSyncCfg->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onTopLocalSyncCfg ), NULL, this ); + m_bpButtonHideSearch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onHideSearchPanel ), NULL, this ); + m_textCtrlSearchTxt->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( MainDialogGenerated::onSearchGridEnter ), NULL, this ); + m_bpButtonNew->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigNew ), NULL, this ); + m_bpButtonOpen->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigLoad ), NULL, this ); + m_bpButtonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigSave ), NULL, this ); + m_bpButtonSaveAs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onConfigSaveAs ), NULL, this ); + m_bpButtonSaveAsBatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onSaveAsBatchJob ), NULL, this ); + m_bpButtonToggleLog->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleLog ), NULL, this ); + m_bpButtonViewType->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewType ), NULL, this ); + m_bpButtonViewType->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewTypeContextMouse ), NULL, this ); + m_bpButtonShowExcluded->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowExcluded->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowDeleteLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowDeleteLeft->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowUpdateLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowUpdateLeft->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowCreateLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowCreateLeft->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowLeftOnly->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowLeftNewer->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowEqual->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowEqual->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowDoNothing->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowDoNothing->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowDifferent->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowRightNewer->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowRightOnly->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowCreateRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowCreateRight->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowUpdateRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowUpdateRight->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowDeleteRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowDeleteRight->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonShowConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onToggleViewButton ), NULL, this ); + m_bpButtonShowConflict->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); + m_bpButtonViewFilterContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::onViewFilterContext ), NULL, this ); + m_bpButtonViewFilterContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::onViewFilterContextMouse ), NULL, this ); } MainDialogGenerated::~MainDialogGenerated() @@ -1202,97 +1202,97 @@ MainDialogGenerated::~MainDialogGenerated() FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name ) { - wxBoxSizer* bSizer74; - bSizer74 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer74; + bSizer74 = new wxBoxSizer( wxHORIZONTAL ); - m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelLeft->SetMinSize( wxSize( 1,-1 ) ); + m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelLeft->SetMinSize( wxSize( 1, -1 ) ); - wxBoxSizer* bSizer134; - bSizer134 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer134; + bSizer134 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonFolderPairOptions = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonFolderPairOptions->SetToolTip( _("Arrange folder pair") ); + m_bpButtonFolderPairOptions = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonFolderPairOptions->SetToolTip( _("Arrange folder pair") ); - bSizer134->Add( m_bpButtonFolderPairOptions, 0, wxEXPAND, 5 ); + bSizer134->Add( m_bpButtonFolderPairOptions, 0, wxEXPAND, 5 ); - m_bpButtonRemovePair = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); + m_bpButtonRemovePair = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); - bSizer134->Add( m_bpButtonRemovePair, 0, wxEXPAND, 5 ); + bSizer134->Add( m_bpButtonRemovePair, 0, wxEXPAND, 5 ); - m_folderPathLeft = new fff::FolderHistoryBox( m_panelLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer134->Add( m_folderPathLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_folderPathLeft = new fff::FolderHistoryBox( m_panelLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer134->Add( m_folderPathLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectFolderLeft = new wxButton( m_panelLeft, wxID_ANY, _("Browse"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonSelectFolderLeft->SetToolTip( _("Select a folder") ); + m_buttonSelectFolderLeft = new wxButton( m_panelLeft, wxID_ANY, _("Browse"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_buttonSelectFolderLeft->SetToolTip( _("Select a folder") ); - bSizer134->Add( m_buttonSelectFolderLeft, 0, wxEXPAND, 5 ); + bSizer134->Add( m_buttonSelectFolderLeft, 0, wxEXPAND, 5 ); - m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSelectAltFolderLeft->SetToolTip( _("Access online storage") ); + m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSelectAltFolderLeft->SetToolTip( _("Access online storage") ); - bSizer134->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 ); + bSizer134->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 ); - m_panelLeft->SetSizer( bSizer134 ); - m_panelLeft->Layout(); - bSizer134->Fit( m_panelLeft ); - bSizer74->Add( m_panelLeft, 0, wxLEFT|wxEXPAND, 5 ); + m_panelLeft->SetSizer( bSizer134 ); + m_panelLeft->Layout(); + bSizer134->Fit( m_panelLeft ); + bSizer74->Add( m_panelLeft, 0, wxLEFT|wxEXPAND, 5 ); - m_panel20 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer95; - bSizer95 = new wxBoxSizer( wxHORIZONTAL ); + m_panel20 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer95; + bSizer95 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonLocalCompCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonLocalCompCfg->SetToolTip( _("dummy") ); + m_bpButtonLocalCompCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonLocalCompCfg->SetToolTip( _("dummy") ); - bSizer95->Add( m_bpButtonLocalCompCfg, 0, wxEXPAND, 5 ); + bSizer95->Add( m_bpButtonLocalCompCfg, 0, wxEXPAND, 5 ); - m_bpButtonLocalFilter = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonLocalFilter->SetToolTip( _("dummy") ); + m_bpButtonLocalFilter = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonLocalFilter->SetToolTip( _("dummy") ); - bSizer95->Add( m_bpButtonLocalFilter, 0, wxEXPAND, 5 ); + bSizer95->Add( m_bpButtonLocalFilter, 0, wxEXPAND, 5 ); - m_bpButtonLocalSyncCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonLocalSyncCfg->SetToolTip( _("dummy") ); + m_bpButtonLocalSyncCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonLocalSyncCfg->SetToolTip( _("dummy") ); - bSizer95->Add( m_bpButtonLocalSyncCfg, 0, wxEXPAND, 5 ); + bSizer95->Add( m_bpButtonLocalSyncCfg, 0, wxEXPAND, 5 ); - m_panel20->SetSizer( bSizer95 ); - m_panel20->Layout(); - bSizer95->Fit( m_panel20 ); - bSizer74->Add( m_panel20, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 ); + m_panel20->SetSizer( bSizer95 ); + m_panel20->Layout(); + bSizer95->Fit( m_panel20 ); + bSizer74->Add( m_panel20, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 ); - m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelRight->SetMinSize( wxSize( 1,-1 ) ); + m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelRight->SetMinSize( wxSize( 1, -1 ) ); - wxBoxSizer* bSizer135; - bSizer135 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer135; + bSizer135 = new wxBoxSizer( wxHORIZONTAL ); - m_folderPathRight = new fff::FolderHistoryBox( m_panelRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer135->Add( m_folderPathRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_folderPathRight = new fff::FolderHistoryBox( m_panelRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer135->Add( m_folderPathRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectFolderRight = new wxButton( m_panelRight, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectFolderRight->SetToolTip( _("Select a folder") ); + m_buttonSelectFolderRight = new wxButton( m_panelRight, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectFolderRight->SetToolTip( _("Select a folder") ); - bSizer135->Add( m_buttonSelectFolderRight, 0, wxEXPAND, 5 ); + bSizer135->Add( m_buttonSelectFolderRight, 0, wxEXPAND, 5 ); - m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSelectAltFolderRight->SetToolTip( _("Access online storage") ); + m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSelectAltFolderRight->SetToolTip( _("Access online storage") ); - bSizer135->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 ); + bSizer135->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 ); - m_panelRight->SetSizer( bSizer135 ); - m_panelRight->Layout(); - bSizer135->Fit( m_panelRight ); - bSizer74->Add( m_panelRight, 1, wxRIGHT|wxEXPAND, 5 ); + m_panelRight->SetSizer( bSizer135 ); + m_panelRight->Layout(); + bSizer135->Fit( m_panelRight ); + bSizer74->Add( m_panelRight, 1, wxRIGHT|wxEXPAND, 5 ); - this->SetSizer( bSizer74 ); - this->Layout(); + this->SetSizer( bSizer74 ); + this->Layout(); } FolderPairPanelGenerated::~FolderPairPanelGenerated() @@ -1301,1277 +1301,1277 @@ FolderPairPanelGenerated::~FolderPairPanelGenerated() ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer7; - bSizer7 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer190; - bSizer190 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer190; + bSizer190 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer1911; - bSizer1911 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer1911; + bSizer1911 = new wxBoxSizer( wxVERTICAL ); - m_staticTextFolderPairLabel = new wxStaticText( this, wxID_ANY, _("Folder pair:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextFolderPairLabel->Wrap( -1 ); - bSizer1911->Add( m_staticTextFolderPairLabel, 0, wxALL, 5 ); + m_staticTextFolderPairLabel = new wxStaticText( this, wxID_ANY, _("Folder pair:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextFolderPairLabel->Wrap( -1 ); + bSizer1911->Add( m_staticTextFolderPairLabel, 0, wxALL, 5 ); - m_listBoxFolderPair = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB ); - bSizer1911->Add( m_listBoxFolderPair, 1, 0, 5 ); + m_listBoxFolderPair = new wxListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB ); + bSizer1911->Add( m_listBoxFolderPair, 1, 0, 5 ); - bSizer190->Add( bSizer1911, 0, wxEXPAND|wxLEFT, 5 ); + bSizer190->Add( bSizer1911, 0, wxEXPAND|wxLEFT, 5 ); - m_notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelCompSettingsTab = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelCompSettingsTab->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panelCompSettingsTab = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelCompSettingsTab->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer275; - bSizer275 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer275; + bSizer275 = new wxBoxSizer( wxVERTICAL ); - bSizerHeaderCompSettings = new wxBoxSizer( wxVERTICAL ); + bSizerHeaderCompSettings = new wxBoxSizer( wxVERTICAL ); - m_staticTextMainCompSettings = new wxStaticText( m_panelCompSettingsTab, wxID_ANY, _("Main settings:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMainCompSettings->Wrap( -1 ); - bSizerHeaderCompSettings->Add( m_staticTextMainCompSettings, 0, wxALL, 10 ); + m_staticTextMainCompSettings = new wxStaticText( m_panelCompSettingsTab, wxID_ANY, _("Main settings:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextMainCompSettings->Wrap( -1 ); + bSizerHeaderCompSettings->Add( m_staticTextMainCompSettings, 0, wxALL, 10 ); - m_checkBoxUseLocalCmpOptions = new wxCheckBox( m_panelCompSettingsTab, wxID_ANY, _("Use local settings:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxUseLocalCmpOptions->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_checkBoxUseLocalCmpOptions = new wxCheckBox( m_panelCompSettingsTab, wxID_ANY, _("Use local settings:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxUseLocalCmpOptions->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizerHeaderCompSettings->Add( m_checkBoxUseLocalCmpOptions, 0, wxALL|wxEXPAND, 10 ); + bSizerHeaderCompSettings->Add( m_checkBoxUseLocalCmpOptions, 0, wxALL|wxEXPAND, 10 ); - m_staticlineCompHeader = new wxStaticLine( m_panelCompSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerHeaderCompSettings->Add( m_staticlineCompHeader, 0, wxEXPAND, 5 ); + m_staticlineCompHeader = new wxStaticLine( m_panelCompSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerHeaderCompSettings->Add( m_staticlineCompHeader, 0, wxEXPAND, 5 ); - bSizer275->Add( bSizerHeaderCompSettings, 0, wxEXPAND, 5 ); + bSizer275->Add( bSizerHeaderCompSettings, 0, wxEXPAND, 5 ); - m_panelComparisonSettings = new wxPanel( m_panelCompSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelComparisonSettings->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelComparisonSettings = new wxPanel( m_panelCompSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelComparisonSettings->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer2561; - bSizer2561 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer2561; + bSizer2561 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer159; - bSizer159 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer159; + bSizer159 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer178; - bSizer178 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer178; + bSizer178 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer182; - bSizer182 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer182; + bSizer182 = new wxBoxSizer( wxVERTICAL ); - m_staticText91 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Select a variant:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText91->Wrap( -1 ); - bSizer182->Add( m_staticText91, 0, wxALL, 5 ); + m_staticText91 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Select a variant:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText91->Wrap( -1 ); + bSizer182->Add( m_staticText91, 0, wxALL, 5 ); - wxGridSizer* gSizer2; - gSizer2 = new wxGridSizer( 0, 1, 0, 0 ); + wxGridSizer* gSizer2; + gSizer2 = new wxGridSizer( 0, 1, 0, 0 ); - m_buttonByTimeSize = new zen::ToggleButton( m_panelComparisonSettings, wxID_ANY, _("File time and size"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonByTimeSize = new zen::ToggleButton( m_panelComparisonSettings, wxID_ANY, _("File time and size"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonByTimeSize->SetDefault(); - m_buttonByTimeSize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonByTimeSize->SetToolTip( _("dummy") ); + m_buttonByTimeSize->SetDefault(); + m_buttonByTimeSize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonByTimeSize->SetToolTip( _("dummy") ); - gSizer2->Add( m_buttonByTimeSize, 0, wxEXPAND, 5 ); + gSizer2->Add( m_buttonByTimeSize, 0, wxEXPAND, 5 ); - m_buttonByContent = new zen::ToggleButton( m_panelComparisonSettings, wxID_ANY, _("File content"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonByContent = new zen::ToggleButton( m_panelComparisonSettings, wxID_ANY, _("File content"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonByContent->SetDefault(); - m_buttonByContent->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonByContent->SetToolTip( _("dummy") ); + m_buttonByContent->SetDefault(); + m_buttonByContent->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonByContent->SetToolTip( _("dummy") ); - gSizer2->Add( m_buttonByContent, 0, wxEXPAND, 5 ); + gSizer2->Add( m_buttonByContent, 0, wxEXPAND, 5 ); - m_buttonBySize = new zen::ToggleButton( m_panelComparisonSettings, wxID_ANY, _("File size"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonBySize = new zen::ToggleButton( m_panelComparisonSettings, wxID_ANY, _("File size"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonBySize->SetDefault(); - m_buttonBySize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonBySize->SetToolTip( _("dummy") ); + m_buttonBySize->SetDefault(); + m_buttonBySize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonBySize->SetToolTip( _("dummy") ); - gSizer2->Add( m_buttonBySize, 0, wxEXPAND, 5 ); + gSizer2->Add( m_buttonBySize, 0, wxEXPAND, 5 ); - bSizer182->Add( gSizer2, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizer182->Add( gSizer2, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer178->Add( bSizer182, 0, wxALL, 5 ); + bSizer178->Add( bSizer182, 0, wxALL, 5 ); - wxBoxSizer* bSizer2371; - bSizer2371 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer2371; + bSizer2371 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapCompVariant = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer2371->Add( m_bitmapCompVariant, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapCompVariant = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer2371->Add( m_bitmapCompVariant, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextCompVarDescription = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCompVarDescription->Wrap( -1 ); - m_staticTextCompVarDescription->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticTextCompVarDescription = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCompVarDescription->Wrap( -1 ); + m_staticTextCompVarDescription->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer2371->Add( m_staticTextCompVarDescription, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer2371->Add( m_staticTextCompVarDescription, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer178->Add( bSizer2371, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer178->Add( bSizer2371, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizer159->Add( bSizer178, 0, wxEXPAND, 5 ); + bSizer159->Add( bSizer178, 0, wxEXPAND, 5 ); - m_staticline33 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer159->Add( m_staticline33, 0, wxEXPAND, 5 ); + m_staticline33 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer159->Add( m_staticline33, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer1734; - bSizer1734 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer1734; + bSizer1734 = new wxBoxSizer( wxHORIZONTAL ); - bSizer1734->Add( 0, 0, 1, 0, 5 ); + bSizer1734->Add( 0, 0, 1, 0, 5 ); - wxBoxSizer* bSizer1721; - bSizer1721 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer1721; + bSizer1721 = new wxBoxSizer( wxVERTICAL ); - m_checkBoxSymlinksInclude = new wxCheckBox( m_panelComparisonSettings, wxID_ANY, _("Include &symbolic links:"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer1721->Add( m_checkBoxSymlinksInclude, 0, wxALL, 5 ); + m_checkBoxSymlinksInclude = new wxCheckBox( m_panelComparisonSettings, wxID_ANY, _("Include &symbolic links:"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer1721->Add( m_checkBoxSymlinksInclude, 0, wxALL, 5 ); - wxBoxSizer* bSizer176; - bSizer176 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer176; + bSizer176 = new wxBoxSizer( wxVERTICAL ); - m_radioBtnSymlinksFollow = new wxRadioButton( m_panelComparisonSettings, wxID_ANY, _("&Follow"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); - m_radioBtnSymlinksFollow->SetValue( true ); - bSizer176->Add( m_radioBtnSymlinksFollow, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_radioBtnSymlinksFollow = new wxRadioButton( m_panelComparisonSettings, wxID_ANY, _("&Follow"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); + m_radioBtnSymlinksFollow->SetValue( true ); + bSizer176->Add( m_radioBtnSymlinksFollow, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_radioBtnSymlinksDirect = new wxRadioButton( m_panelComparisonSettings, wxID_ANY, _("&Direct"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer176->Add( m_radioBtnSymlinksDirect, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_radioBtnSymlinksDirect = new wxRadioButton( m_panelComparisonSettings, wxID_ANY, _("As &link"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer176->Add( m_radioBtnSymlinksDirect, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer1721->Add( bSizer176, 0, wxLEFT|wxEXPAND, 15 ); + bSizer1721->Add( bSizer176, 0, wxLEFT|wxEXPAND, 15 ); - bSizer1721->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer1721->Add( 0, 0, 1, wxEXPAND, 5 ); - m_hyperlink24 = new wxHyperlinkCtrl( m_panelComparisonSettings, wxID_ANY, _("More information"), wxT("https://freefilesync.org/manual.php?topic=comparison-settings"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink24->SetToolTip( _("https://freefilesync.org/manual.php?topic=comparison-settings") ); + m_hyperlink24 = new wxHyperlinkCtrl( m_panelComparisonSettings, wxID_ANY, _("More information"), wxT("https://freefilesync.org/manual.php?topic=comparison-settings"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink24->SetToolTip( _("https://freefilesync.org/manual.php?topic=comparison-settings") ); - bSizer1721->Add( m_hyperlink24, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizer1721->Add( m_hyperlink24, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer1734->Add( bSizer1721, 0, wxALL|wxEXPAND, 5 ); + bSizer1734->Add( bSizer1721, 0, wxALL|wxEXPAND, 5 ); - bSizer1734->Add( 0, 0, 1, 0, 5 ); + bSizer1734->Add( 0, 0, 1, 0, 5 ); - m_staticline44 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer1734->Add( m_staticline44, 0, wxEXPAND, 5 ); + m_staticline44 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer1734->Add( m_staticline44, 0, wxEXPAND, 5 ); - bSizer1734->Add( 0, 0, 1, 0, 5 ); + bSizer1734->Add( 0, 0, 1, 0, 5 ); - wxBoxSizer* bSizer1733; - bSizer1733 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer1733; + bSizer1733 = new wxBoxSizer( wxVERTICAL ); - m_staticText112 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("&Ignore time shift [hh:mm]"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText112->Wrap( -1 ); - bSizer1733->Add( m_staticText112, 0, wxALL, 5 ); + m_staticText112 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("&Ignore time shift [hh:mm]"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText112->Wrap( -1 ); + bSizer1733->Add( m_staticText112, 0, wxALL, 5 ); - m_textCtrlTimeShift = new wxTextCtrl( m_panelComparisonSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_textCtrlTimeShift->SetToolTip( _("List of file time offsets to ignore") ); + m_textCtrlTimeShift = new wxTextCtrl( m_panelComparisonSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_textCtrlTimeShift->SetToolTip( _("List of file time offsets to ignore") ); - bSizer1733->Add( m_textCtrlTimeShift, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + bSizer1733->Add( m_textCtrlTimeShift, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - wxBoxSizer* bSizer197; - bSizer197 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer197; + bSizer197 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText1381 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Example:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1381->Wrap( -1 ); - m_staticText1381->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText1381 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Example:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1381->Wrap( -1 ); + m_staticText1381->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer197->Add( m_staticText1381, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizer197->Add( m_staticText1381, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_staticText13811 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("1, 2, 4:30"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText13811->Wrap( -1 ); - m_staticText13811->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText13811 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("1, 2, 4:30"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText13811->Wrap( -1 ); + m_staticText13811->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer197->Add( m_staticText13811, 0, wxBOTTOM|wxRIGHT, 5 ); + bSizer197->Add( m_staticText13811, 0, wxBOTTOM|wxRIGHT, 5 ); - bSizer1733->Add( bSizer197, 0, 0, 5 ); + bSizer1733->Add( bSizer197, 0, 0, 5 ); - bSizer1733->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer1733->Add( 0, 0, 1, wxEXPAND, 5 ); - m_hyperlink241 = new wxHyperlinkCtrl( m_panelComparisonSettings, wxID_ANY, _("Handle daylight saving time"), wxT("https://freefilesync.org/manual.php?topic=daylight-saving-time"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink241->SetToolTip( _("https://freefilesync.org/manual.php?topic=daylight-saving-time") ); + m_hyperlink241 = new wxHyperlinkCtrl( m_panelComparisonSettings, wxID_ANY, _("Handle daylight saving time"), wxT("https://freefilesync.org/manual.php?topic=daylight-saving-time"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink241->SetToolTip( _("https://freefilesync.org/manual.php?topic=daylight-saving-time") ); - bSizer1733->Add( m_hyperlink241, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizer1733->Add( m_hyperlink241, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer1734->Add( bSizer1733, 0, wxALL|wxEXPAND, 5 ); + bSizer1734->Add( bSizer1733, 0, wxALL|wxEXPAND, 5 ); - bSizer1734->Add( 0, 0, 1, 0, 5 ); + bSizer1734->Add( 0, 0, 1, 0, 5 ); - bSizer159->Add( bSizer1734, 0, wxEXPAND, 5 ); + bSizer159->Add( bSizer1734, 0, wxEXPAND, 5 ); - m_staticline331 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer159->Add( m_staticline331, 0, wxEXPAND, 5 ); + m_staticline331 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer159->Add( m_staticline331, 0, wxEXPAND, 5 ); - bSizer159->Add( 0, 0, 1, 0, 5 ); + bSizer159->Add( 0, 0, 1, 0, 5 ); - bSizerCompMisc = new wxBoxSizer( wxVERTICAL ); + bSizerCompMisc = new wxBoxSizer( wxVERTICAL ); - m_staticline3311 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerCompMisc->Add( m_staticline3311, 0, wxEXPAND, 5 ); + m_staticline3311 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerCompMisc->Add( m_staticline3311, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer2781; - bSizer2781 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer2781; + bSizer2781 = new wxBoxSizer( wxHORIZONTAL ); - wxFlexGridSizer* fgSizer61; - fgSizer61 = new wxFlexGridSizer( 0, 2, 5, 5 ); - fgSizer61->SetFlexibleDirection( wxBOTH ); - fgSizer61->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + wxFlexGridSizer* fgSizer61; + fgSizer61 = new wxFlexGridSizer( 0, 2, 5, 5 ); + fgSizer61->SetFlexibleDirection( wxBOTH ); + fgSizer61->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_bitmapIgnoreErrors = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer61->Add( m_bitmapIgnoreErrors, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapIgnoreErrors = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer61->Add( m_bitmapIgnoreErrors, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_checkBoxIgnoreErrors = new wxCheckBox( m_panelComparisonSettings, wxID_ANY, _("Ignore errors"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - fgSizer61->Add( m_checkBoxIgnoreErrors, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + m_checkBoxIgnoreErrors = new wxCheckBox( m_panelComparisonSettings, wxID_ANY, _("Ignore errors"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + fgSizer61->Add( m_checkBoxIgnoreErrors, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_bitmapRetryErrors = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer61->Add( m_bitmapRetryErrors, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_bitmapRetryErrors = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer61->Add( m_bitmapRetryErrors, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_checkBoxAutoRetry = new wxCheckBox( m_panelComparisonSettings, wxID_ANY, _("Automatic retry"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer61->Add( m_checkBoxAutoRetry, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + m_checkBoxAutoRetry = new wxCheckBox( m_panelComparisonSettings, wxID_ANY, _("Automatic retry"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer61->Add( m_checkBoxAutoRetry, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - bSizer2781->Add( fgSizer61, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + bSizer2781->Add( fgSizer61, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - fgSizerAutoRetry = new wxFlexGridSizer( 0, 2, 5, 10 ); - fgSizerAutoRetry->SetFlexibleDirection( wxBOTH ); - fgSizerAutoRetry->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + fgSizerAutoRetry = new wxFlexGridSizer( 0, 2, 5, 10 ); + fgSizerAutoRetry->SetFlexibleDirection( wxBOTH ); + fgSizerAutoRetry->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticText96 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Retry count:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText96->Wrap( -1 ); - fgSizerAutoRetry->Add( m_staticText96, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText96 = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Retry count:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText96->Wrap( -1 ); + fgSizerAutoRetry->Add( m_staticText96, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextAutoRetryDelay = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Delay (in seconds):"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextAutoRetryDelay->Wrap( -1 ); - fgSizerAutoRetry->Add( m_staticTextAutoRetryDelay, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextAutoRetryDelay = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Delay (in seconds):"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextAutoRetryDelay->Wrap( -1 ); + fgSizerAutoRetry->Add( m_staticTextAutoRetryDelay, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_spinCtrlAutoRetryCount = new wxSpinCtrl( m_panelComparisonSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); - fgSizerAutoRetry->Add( m_spinCtrlAutoRetryCount, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_spinCtrlAutoRetryCount = new wxSpinCtrl( m_panelComparisonSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); + fgSizerAutoRetry->Add( m_spinCtrlAutoRetryCount, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_spinCtrlAutoRetryDelay = new wxSpinCtrl( m_panelComparisonSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - fgSizerAutoRetry->Add( m_spinCtrlAutoRetryDelay, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_spinCtrlAutoRetryDelay = new wxSpinCtrl( m_panelComparisonSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxSP_ARROW_KEYS, 0, 2000000000, 0 ); + fgSizerAutoRetry->Add( m_spinCtrlAutoRetryDelay, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer2781->Add( fgSizerAutoRetry, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 10 ); + bSizer2781->Add( fgSizerAutoRetry, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 10 ); - bSizerCompMisc->Add( bSizer2781, 0, wxEXPAND, 5 ); + bSizerCompMisc->Add( bSizer2781, 0, wxEXPAND, 5 ); - bSizer159->Add( bSizerCompMisc, 0, wxEXPAND, 5 ); + bSizer159->Add( bSizerCompMisc, 0, wxEXPAND, 5 ); - bSizer2561->Add( bSizer159, 0, wxEXPAND, 5 ); + bSizer2561->Add( bSizer159, 0, wxEXPAND, 5 ); - m_staticline751 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer2561->Add( m_staticline751, 0, wxEXPAND, 5 ); + m_staticline751 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer2561->Add( m_staticline751, 0, wxEXPAND, 5 ); - bSizerPerformance = new wxBoxSizer( wxVERTICAL ); + bSizerPerformance = new wxBoxSizer( wxVERTICAL ); - m_panel57 = new wxPanel( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel57->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_panel57 = new wxPanel( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel57->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer2191; - bSizer2191 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer2191; + bSizer2191 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapPerf = new wxStaticBitmap( m_panel57, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer2191->Add( m_bitmapPerf, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_bitmapPerf = new wxStaticBitmap( m_panel57, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2191->Add( m_bitmapPerf, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_staticText13611 = new wxStaticText( m_panel57, wxID_ANY, _("Performance improvements:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText13611->Wrap( -1 ); - bSizer2191->Add( m_staticText13611, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); + m_staticText13611 = new wxStaticText( m_panel57, wxID_ANY, _("Performance improvements:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText13611->Wrap( -1 ); + bSizer2191->Add( m_staticText13611, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); - m_panel57->SetSizer( bSizer2191 ); - m_panel57->Layout(); - bSizer2191->Fit( m_panel57 ); - bSizerPerformance->Add( m_panel57, 0, wxEXPAND, 5 ); + m_panel57->SetSizer( bSizer2191 ); + m_panel57->Layout(); + bSizer2191->Fit( m_panel57 ); + bSizerPerformance->Add( m_panel57, 0, wxEXPAND, 5 ); - wxStaticLine* m_staticline75; - m_staticline75 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerPerformance->Add( m_staticline75, 0, wxEXPAND, 5 ); + wxStaticLine* m_staticline75; + m_staticline75 = new wxStaticLine( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerPerformance->Add( m_staticline75, 0, wxEXPAND, 5 ); - m_hyperlinkPerfDeRequired = new wxHyperlinkCtrl( m_panelComparisonSettings, wxID_ANY, _("Requires FreeFileSync Donation Edition"), wxT("https://freefilesync.org/faq.php#donation-edition"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlinkPerfDeRequired->SetToolTip( _("https://freefilesync.org/faq.php#donation-edition") ); + m_hyperlinkPerfDeRequired = new wxHyperlinkCtrl( m_panelComparisonSettings, wxID_ANY, _("Requires FreeFileSync Donation Edition"), wxT("https://freefilesync.org/faq.php#donation-edition"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlinkPerfDeRequired->SetToolTip( _("https://freefilesync.org/faq.php#donation-edition") ); - bSizerPerformance->Add( m_hyperlinkPerfDeRequired, 0, wxALL, 10 ); + bSizerPerformance->Add( m_hyperlinkPerfDeRequired, 0, wxALL, 10 ); - bSizer260 = new wxBoxSizer( wxVERTICAL ); + bSizer260 = new wxBoxSizer( wxVERTICAL ); - m_staticTextPerfParallelOps = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Parallel file operations:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextPerfParallelOps->Wrap( -1 ); - bSizer260->Add( m_staticTextPerfParallelOps, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + m_staticTextPerfParallelOps = new wxStaticText( m_panelComparisonSettings, wxID_ANY, _("Parallel file operations:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextPerfParallelOps->Wrap( -1 ); + bSizer260->Add( m_staticTextPerfParallelOps, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - m_scrolledWindowPerf = new wxScrolledWindow( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_scrolledWindowPerf->SetScrollRate( 5, 5 ); - m_scrolledWindowPerf->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_scrolledWindowPerf = new wxScrolledWindow( m_panelComparisonSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_scrolledWindowPerf->SetScrollRate( 5, 5 ); + m_scrolledWindowPerf->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - fgSizerPerf = new wxFlexGridSizer( 0, 2, 5, 5 ); - fgSizerPerf->SetFlexibleDirection( wxBOTH ); - fgSizerPerf->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + fgSizerPerf = new wxFlexGridSizer( 0, 2, 5, 5 ); + fgSizerPerf->SetFlexibleDirection( wxBOTH ); + fgSizerPerf->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_scrolledWindowPerf->SetSizer( fgSizerPerf ); - m_scrolledWindowPerf->Layout(); - fgSizerPerf->Fit( m_scrolledWindowPerf ); - bSizer260->Add( m_scrolledWindowPerf, 1, wxALL|wxEXPAND, 5 ); + m_scrolledWindowPerf->SetSizer( fgSizerPerf ); + m_scrolledWindowPerf->Layout(); + fgSizerPerf->Fit( m_scrolledWindowPerf ); + bSizer260->Add( m_scrolledWindowPerf, 1, wxALL|wxEXPAND, 5 ); - bSizerPerformance->Add( bSizer260, 1, wxALL|wxEXPAND, 5 ); + bSizerPerformance->Add( bSizer260, 1, wxALL|wxEXPAND, 5 ); - m_hyperlink1711 = new wxHyperlinkCtrl( m_panelComparisonSettings, wxID_ANY, _("How to get best performance?"), wxT("https://freefilesync.org/manual.php?topic=performance"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink1711->SetToolTip( _("https://freefilesync.org/manual.php?topic=performance") ); + m_hyperlink1711 = new wxHyperlinkCtrl( m_panelComparisonSettings, wxID_ANY, _("How to get the best performance?"), wxT("https://freefilesync.org/manual.php?topic=performance"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink1711->SetToolTip( _("https://freefilesync.org/manual.php?topic=performance") ); - bSizerPerformance->Add( m_hyperlink1711, 0, wxBOTTOM|wxRIGHT|wxLEFT, 10 ); + bSizerPerformance->Add( m_hyperlink1711, 0, wxBOTTOM|wxRIGHT|wxLEFT, 10 ); - bSizer2561->Add( bSizerPerformance, 1, wxEXPAND, 5 ); + bSizer2561->Add( bSizerPerformance, 1, wxEXPAND, 5 ); - m_panelComparisonSettings->SetSizer( bSizer2561 ); - m_panelComparisonSettings->Layout(); - bSizer2561->Fit( m_panelComparisonSettings ); - bSizer275->Add( m_panelComparisonSettings, 1, wxEXPAND, 5 ); + m_panelComparisonSettings->SetSizer( bSizer2561 ); + m_panelComparisonSettings->Layout(); + bSizer2561->Fit( m_panelComparisonSettings ); + bSizer275->Add( m_panelComparisonSettings, 1, wxEXPAND, 5 ); - m_panelCompSettingsTab->SetSizer( bSizer275 ); - m_panelCompSettingsTab->Layout(); - bSizer275->Fit( m_panelCompSettingsTab ); - m_notebook->AddPage( m_panelCompSettingsTab, _("dummy"), true ); - m_panelFilterSettingsTab = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelFilterSettingsTab->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelCompSettingsTab->SetSizer( bSizer275 ); + m_panelCompSettingsTab->Layout(); + bSizer275->Fit( m_panelCompSettingsTab ); + m_notebook->AddPage( m_panelCompSettingsTab, _("dummy"), true ); + m_panelFilterSettingsTab = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelFilterSettingsTab->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer278; - bSizer278 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer278; + bSizer278 = new wxBoxSizer( wxVERTICAL ); - bSizerHeaderFilterSettings = new wxBoxSizer( wxVERTICAL ); + bSizerHeaderFilterSettings = new wxBoxSizer( wxVERTICAL ); - m_staticTextMainFilterSettings = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Main settings:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMainFilterSettings->Wrap( -1 ); - bSizerHeaderFilterSettings->Add( m_staticTextMainFilterSettings, 0, wxALL, 10 ); + m_staticTextMainFilterSettings = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Main settings:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextMainFilterSettings->Wrap( -1 ); + bSizerHeaderFilterSettings->Add( m_staticTextMainFilterSettings, 0, wxALL, 10 ); - m_staticTextLocalFilterSettings = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Local settings:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextLocalFilterSettings->Wrap( -1 ); - bSizerHeaderFilterSettings->Add( m_staticTextLocalFilterSettings, 0, wxALL, 10 ); + m_staticTextLocalFilterSettings = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Local settings:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextLocalFilterSettings->Wrap( -1 ); + bSizerHeaderFilterSettings->Add( m_staticTextLocalFilterSettings, 0, wxALL, 10 ); - m_staticlineFilterHeader = new wxStaticLine( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerHeaderFilterSettings->Add( m_staticlineFilterHeader, 0, wxEXPAND, 5 ); + m_staticlineFilterHeader = new wxStaticLine( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerHeaderFilterSettings->Add( m_staticlineFilterHeader, 0, wxEXPAND, 5 ); - bSizer278->Add( bSizerHeaderFilterSettings, 0, wxEXPAND, 5 ); + bSizer278->Add( bSizerHeaderFilterSettings, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer301; - bSizer301 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer301; + bSizer301 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer166; - bSizer166 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer166; + bSizer166 = new wxBoxSizer( wxVERTICAL ); - bSizer166->Add( 0, 10, 0, 0, 5 ); + bSizer166->Add( 0, 10, 0, 0, 5 ); - wxBoxSizer* bSizer1661; - bSizer1661 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer1661; + bSizer1661 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapInclude = new wxStaticBitmap( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer1661->Add( m_bitmapInclude, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + m_bitmapInclude = new wxStaticBitmap( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer1661->Add( m_bitmapInclude, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - wxBoxSizer* bSizer1731; - bSizer1731 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer1731; + bSizer1731 = new wxBoxSizer( wxVERTICAL ); - m_staticText78 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Include:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText78->Wrap( -1 ); - bSizer1731->Add( m_staticText78, 0, 0, 5 ); + m_staticText78 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Include:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText78->Wrap( -1 ); + bSizer1731->Add( m_staticText78, 0, 0, 5 ); - m_textCtrlInclude = new wxTextCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); - bSizer1731->Add( m_textCtrlInclude, 1, wxEXPAND|wxTOP, 5 ); + m_textCtrlInclude = new wxTextCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_MULTILINE ); + bSizer1731->Add( m_textCtrlInclude, 1, wxEXPAND|wxTOP, 5 ); - bSizer1661->Add( bSizer1731, 1, wxEXPAND, 5 ); + bSizer1661->Add( bSizer1731, 1, wxEXPAND, 5 ); - bSizer166->Add( bSizer1661, 3, wxEXPAND|wxLEFT, 5 ); + bSizer166->Add( bSizer1661, 3, wxEXPAND|wxLEFT, 5 ); - bSizer166->Add( 0, 10, 0, 0, 5 ); + bSizer166->Add( 0, 10, 0, 0, 5 ); - wxBoxSizer* bSizer1651; - bSizer1651 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer1651; + bSizer1651 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapExclude = new wxStaticBitmap( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer1651->Add( m_bitmapExclude, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_bitmapExclude = new wxStaticBitmap( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer1651->Add( m_bitmapExclude, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - wxBoxSizer* bSizer1742; - bSizer1742 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer1742; + bSizer1742 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer189; - bSizer189 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer189; + bSizer189 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText77 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Exclude:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText77->Wrap( -1 ); - bSizer189->Add( m_staticText77, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText77 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Exclude:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText77->Wrap( -1 ); + bSizer189->Add( m_staticText77, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer189->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer189->Add( 0, 0, 1, wxEXPAND, 5 ); - m_hyperlink171 = new wxHyperlinkCtrl( m_panelFilterSettingsTab, wxID_ANY, _("Show examples"), wxT("https://freefilesync.org/manual.php?topic=exclude-files"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink171->SetToolTip( _("https://freefilesync.org/manual.php?topic=exclude-files") ); + m_hyperlink171 = new wxHyperlinkCtrl( m_panelFilterSettingsTab, wxID_ANY, _("Show examples"), wxT("https://freefilesync.org/manual.php?topic=exclude-files"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink171->SetToolTip( _("https://freefilesync.org/manual.php?topic=exclude-files") ); - bSizer189->Add( m_hyperlink171, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + bSizer189->Add( m_hyperlink171, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - bSizer1742->Add( bSizer189, 0, wxEXPAND, 5 ); + bSizer1742->Add( bSizer189, 0, wxEXPAND, 5 ); - m_textCtrlExclude = new wxTextCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); - bSizer1742->Add( m_textCtrlExclude, 1, wxEXPAND|wxTOP, 5 ); + m_textCtrlExclude = new wxTextCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_MULTILINE ); + bSizer1742->Add( m_textCtrlExclude, 1, wxEXPAND|wxTOP, 5 ); - bSizer1651->Add( bSizer1742, 1, wxEXPAND, 5 ); + bSizer1651->Add( bSizer1742, 1, wxEXPAND, 5 ); - bSizer166->Add( bSizer1651, 5, wxEXPAND|wxLEFT, 5 ); + bSizer166->Add( bSizer1651, 5, wxEXPAND|wxLEFT, 5 ); - bSizer301->Add( bSizer166, 1, wxEXPAND, 5 ); + bSizer301->Add( bSizer166, 1, wxEXPAND, 5 ); - m_staticline24 = new wxStaticLine( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer301->Add( m_staticline24, 0, wxEXPAND, 5 ); + m_staticline24 = new wxStaticLine( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer301->Add( m_staticline24, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer160; - bSizer160 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer160; + bSizer160 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer168; - bSizer168 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer168; + bSizer168 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapFilterSize = new wxStaticBitmap( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer168->Add( m_bitmapFilterSize, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + m_bitmapFilterSize = new wxStaticBitmap( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer168->Add( m_bitmapFilterSize, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - wxBoxSizer* bSizer158; - bSizer158 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer158; + bSizer158 = new wxBoxSizer( wxVERTICAL ); - m_staticText80 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("File size:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText80->Wrap( -1 ); - bSizer158->Add( m_staticText80, 0, wxBOTTOM, 5 ); + m_staticText80 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("File size:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText80->Wrap( -1 ); + bSizer158->Add( m_staticText80, 0, wxBOTTOM, 5 ); - wxBoxSizer* bSizer162; - bSizer162 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer162; + bSizer162 = new wxBoxSizer( wxVERTICAL ); - m_staticText101 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Minimum:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText101->Wrap( -1 ); - bSizer162->Add( m_staticText101, 0, wxBOTTOM, 2 ); + m_staticText101 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Minimum:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText101->Wrap( -1 ); + bSizer162->Add( m_staticText101, 0, wxBOTTOM, 2 ); - m_spinCtrlMinSize = new wxSpinCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - bSizer162->Add( m_spinCtrlMinSize, 0, wxEXPAND, 5 ); + m_spinCtrlMinSize = new wxSpinCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); + bSizer162->Add( m_spinCtrlMinSize, 0, wxEXPAND, 5 ); - wxArrayString m_choiceUnitMinSizeChoices; - m_choiceUnitMinSize = new wxChoice( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitMinSizeChoices, 0 ); - m_choiceUnitMinSize->SetSelection( 0 ); - bSizer162->Add( m_choiceUnitMinSize, 0, wxEXPAND, 5 ); + wxArrayString m_choiceUnitMinSizeChoices; + m_choiceUnitMinSize = new wxChoice( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitMinSizeChoices, 0 ); + m_choiceUnitMinSize->SetSelection( 0 ); + bSizer162->Add( m_choiceUnitMinSize, 0, wxEXPAND, 5 ); - bSizer158->Add( bSizer162, 0, wxBOTTOM|wxEXPAND, 5 ); + bSizer158->Add( bSizer162, 0, wxBOTTOM|wxEXPAND, 5 ); - wxBoxSizer* bSizer163; - bSizer163 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer163; + bSizer163 = new wxBoxSizer( wxVERTICAL ); - m_staticText102 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Maximum:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText102->Wrap( -1 ); - bSizer163->Add( m_staticText102, 0, wxBOTTOM, 2 ); + m_staticText102 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Maximum:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText102->Wrap( -1 ); + bSizer163->Add( m_staticText102, 0, wxBOTTOM, 2 ); - m_spinCtrlMaxSize = new wxSpinCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - bSizer163->Add( m_spinCtrlMaxSize, 0, wxEXPAND, 5 ); + m_spinCtrlMaxSize = new wxSpinCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); + bSizer163->Add( m_spinCtrlMaxSize, 0, wxEXPAND, 5 ); - wxArrayString m_choiceUnitMaxSizeChoices; - m_choiceUnitMaxSize = new wxChoice( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitMaxSizeChoices, 0 ); - m_choiceUnitMaxSize->SetSelection( 0 ); - bSizer163->Add( m_choiceUnitMaxSize, 0, wxEXPAND, 5 ); + wxArrayString m_choiceUnitMaxSizeChoices; + m_choiceUnitMaxSize = new wxChoice( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitMaxSizeChoices, 0 ); + m_choiceUnitMaxSize->SetSelection( 0 ); + bSizer163->Add( m_choiceUnitMaxSize, 0, wxEXPAND, 5 ); - bSizer158->Add( bSizer163, 0, wxEXPAND, 5 ); + bSizer158->Add( bSizer163, 0, wxEXPAND, 5 ); - bSizer168->Add( bSizer158, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer168->Add( bSizer158, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer160->Add( bSizer168, 2, wxEXPAND|wxALL, 5 ); + bSizer160->Add( bSizer168, 2, wxEXPAND|wxALL, 5 ); - m_staticline23 = new wxStaticLine( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer160->Add( m_staticline23, 0, wxEXPAND, 5 ); + m_staticline23 = new wxStaticLine( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer160->Add( m_staticline23, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer167; - bSizer167 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer167; + bSizer167 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapFilterDate = new wxStaticBitmap( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer167->Add( m_bitmapFilterDate, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_bitmapFilterDate = new wxStaticBitmap( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer167->Add( m_bitmapFilterDate, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - wxBoxSizer* bSizer165; - bSizer165 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer165; + bSizer165 = new wxBoxSizer( wxVERTICAL ); - m_staticText79 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Time span:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText79->Wrap( -1 ); - bSizer165->Add( m_staticText79, 0, wxBOTTOM, 5 ); + m_staticText79 = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Time span:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText79->Wrap( -1 ); + bSizer165->Add( m_staticText79, 0, wxBOTTOM, 5 ); - wxArrayString m_choiceUnitTimespanChoices; - m_choiceUnitTimespan = new wxChoice( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitTimespanChoices, 0 ); - m_choiceUnitTimespan->SetSelection( 0 ); - bSizer165->Add( m_choiceUnitTimespan, 0, wxEXPAND, 5 ); + wxArrayString m_choiceUnitTimespanChoices; + m_choiceUnitTimespan = new wxChoice( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitTimespanChoices, 0 ); + m_choiceUnitTimespan->SetSelection( 0 ); + bSizer165->Add( m_choiceUnitTimespan, 0, wxEXPAND, 5 ); - m_spinCtrlTimespan = new wxSpinCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - bSizer165->Add( m_spinCtrlTimespan, 0, wxEXPAND, 5 ); + m_spinCtrlTimespan = new wxSpinCtrl( m_panelFilterSettingsTab, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); + bSizer165->Add( m_spinCtrlTimespan, 0, wxEXPAND, 5 ); - bSizer167->Add( bSizer165, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer167->Add( bSizer165, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer160->Add( bSizer167, 1, wxEXPAND|wxALL, 5 ); + bSizer160->Add( bSizer167, 1, wxEXPAND|wxALL, 5 ); - m_staticline231 = new wxStaticLine( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer160->Add( m_staticline231, 0, wxEXPAND, 5 ); + m_staticline231 = new wxStaticLine( m_panelFilterSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer160->Add( m_staticline231, 0, wxEXPAND, 5 ); - bSizer301->Add( bSizer160, 0, wxEXPAND, 5 ); + bSizer301->Add( bSizer160, 0, wxEXPAND, 5 ); - bSizer278->Add( bSizer301, 1, wxEXPAND, 5 ); + bSizer278->Add( bSizer301, 1, wxEXPAND, 5 ); - wxBoxSizer* bSizer302; - bSizer302 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer302; + bSizer302 = new wxBoxSizer( wxHORIZONTAL ); - m_staticTextFilterDescr = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair."), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextFilterDescr->Wrap( -1 ); - m_staticTextFilterDescr->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticTextFilterDescr = new wxStaticText( m_panelFilterSettingsTab, wxID_ANY, _("Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair."), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticTextFilterDescr->Wrap( -1 ); + m_staticTextFilterDescr->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer302->Add( m_staticTextFilterDescr, 1, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); + bSizer302->Add( m_staticTextFilterDescr, 1, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); - wxBoxSizer* bSizer303; - bSizer303 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer303; + bSizer303 = new wxBoxSizer( wxHORIZONTAL ); - m_buttonDefault = new wxButton( m_panelFilterSettingsTab, wxID_ANY, _("&Default"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer303->Add( m_buttonDefault, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_buttonDefault = new wxButton( m_panelFilterSettingsTab, wxID_ANY, _("&Default"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer303->Add( m_buttonDefault, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonDefaultContext = new wxBitmapButton( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizer303->Add( m_bpButtonDefaultContext, 0, wxEXPAND, 5 ); + m_bpButtonDefaultContext = new wxBitmapButton( m_panelFilterSettingsTab, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizer303->Add( m_bpButtonDefaultContext, 0, wxEXPAND, 5 ); - bSizer302->Add( bSizer303, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 10 ); + bSizer302->Add( bSizer303, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 10 ); - m_buttonClear = new wxButton( m_panelFilterSettingsTab, wxID_ANY, _("C&lear"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer302->Add( m_buttonClear, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); + m_buttonClear = new wxButton( m_panelFilterSettingsTab, wxID_ANY, _("C&lear"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer302->Add( m_buttonClear, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); - bSizer278->Add( bSizer302, 0, wxEXPAND, 5 ); + bSizer278->Add( bSizer302, 0, wxEXPAND, 5 ); - m_panelFilterSettingsTab->SetSizer( bSizer278 ); - m_panelFilterSettingsTab->Layout(); - bSizer278->Fit( m_panelFilterSettingsTab ); - m_notebook->AddPage( m_panelFilterSettingsTab, _("dummy"), false ); - m_panelSyncSettingsTab = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelSyncSettingsTab->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelFilterSettingsTab->SetSizer( bSizer278 ); + m_panelFilterSettingsTab->Layout(); + bSizer278->Fit( m_panelFilterSettingsTab ); + m_notebook->AddPage( m_panelFilterSettingsTab, _("dummy"), false ); + m_panelSyncSettingsTab = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelSyncSettingsTab->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer276; - bSizer276 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer276; + bSizer276 = new wxBoxSizer( wxVERTICAL ); - bSizerHeaderSyncSettings = new wxBoxSizer( wxVERTICAL ); + bSizerHeaderSyncSettings = new wxBoxSizer( wxVERTICAL ); - m_staticTextMainSyncSettings = new wxStaticText( m_panelSyncSettingsTab, wxID_ANY, _("Main settings:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMainSyncSettings->Wrap( -1 ); - bSizerHeaderSyncSettings->Add( m_staticTextMainSyncSettings, 0, wxALL, 10 ); + m_staticTextMainSyncSettings = new wxStaticText( m_panelSyncSettingsTab, wxID_ANY, _("Main settings:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextMainSyncSettings->Wrap( -1 ); + bSizerHeaderSyncSettings->Add( m_staticTextMainSyncSettings, 0, wxALL, 10 ); - m_checkBoxUseLocalSyncOptions = new wxCheckBox( m_panelSyncSettingsTab, wxID_ANY, _("Use local settings:"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerHeaderSyncSettings->Add( m_checkBoxUseLocalSyncOptions, 0, wxALL|wxEXPAND, 10 ); + m_checkBoxUseLocalSyncOptions = new wxCheckBox( m_panelSyncSettingsTab, wxID_ANY, _("Use local settings:"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerHeaderSyncSettings->Add( m_checkBoxUseLocalSyncOptions, 0, wxALL|wxEXPAND, 10 ); - m_staticlineSyncHeader = new wxStaticLine( m_panelSyncSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerHeaderSyncSettings->Add( m_staticlineSyncHeader, 0, wxEXPAND, 5 ); + m_staticlineSyncHeader = new wxStaticLine( m_panelSyncSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerHeaderSyncSettings->Add( m_staticlineSyncHeader, 0, wxEXPAND, 5 ); - bSizer276->Add( bSizerHeaderSyncSettings, 0, wxEXPAND, 5 ); + bSizer276->Add( bSizerHeaderSyncSettings, 0, wxEXPAND, 5 ); - m_panelSyncSettings = new wxPanel( m_panelSyncSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelSyncSettings->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelSyncSettings = new wxPanel( m_panelSyncSettingsTab, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelSyncSettings->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer232; - bSizer232 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer232; + bSizer232 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer237; - bSizer237 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer237; + bSizer237 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer235; - bSizer235 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer235; + bSizer235 = new wxBoxSizer( wxVERTICAL ); - m_staticText86 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Select a variant:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText86->Wrap( -1 ); - bSizer235->Add( m_staticText86, 0, wxALL, 5 ); + m_staticText86 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Select a variant:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText86->Wrap( -1 ); + bSizer235->Add( m_staticText86, 0, wxALL, 5 ); - wxGridSizer* gSizer1; - gSizer1 = new wxGridSizer( 0, 1, 0, 0 ); + wxGridSizer* gSizer1; + gSizer1 = new wxGridSizer( 0, 1, 0, 0 ); - m_buttonTwoWay = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("Two way"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonTwoWay = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("Two way"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonTwoWay->SetDefault(); - m_buttonTwoWay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonTwoWay->SetToolTip( _("dummy") ); + m_buttonTwoWay->SetDefault(); + m_buttonTwoWay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonTwoWay->SetToolTip( _("dummy") ); - gSizer1->Add( m_buttonTwoWay, 0, wxEXPAND, 5 ); + gSizer1->Add( m_buttonTwoWay, 0, wxEXPAND, 5 ); - m_buttonMirror = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("Mirror"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonMirror = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("Mirror"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonMirror->SetDefault(); - m_buttonMirror->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonMirror->SetToolTip( _("dummy") ); + m_buttonMirror->SetDefault(); + m_buttonMirror->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonMirror->SetToolTip( _("dummy") ); - gSizer1->Add( m_buttonMirror, 0, wxEXPAND, 5 ); + gSizer1->Add( m_buttonMirror, 0, wxEXPAND, 5 ); - m_buttonUpdate = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("Update"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonUpdate = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("Update"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonUpdate->SetDefault(); - m_buttonUpdate->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonUpdate->SetToolTip( _("dummy") ); + m_buttonUpdate->SetDefault(); + m_buttonUpdate->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonUpdate->SetToolTip( _("dummy") ); - gSizer1->Add( m_buttonUpdate, 0, wxEXPAND, 5 ); + gSizer1->Add( m_buttonUpdate, 0, wxEXPAND, 5 ); - m_buttonCustom = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("Custom"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonCustom = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("Custom"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonCustom->SetDefault(); - m_buttonCustom->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonCustom->SetToolTip( _("dummy") ); + m_buttonCustom->SetDefault(); + m_buttonCustom->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonCustom->SetToolTip( _("dummy") ); - gSizer1->Add( m_buttonCustom, 0, wxEXPAND, 5 ); + gSizer1->Add( m_buttonCustom, 0, wxEXPAND, 5 ); - bSizer235->Add( gSizer1, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizer235->Add( gSizer1, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer237->Add( bSizer235, 0, wxALL, 5 ); + bSizer237->Add( bSizer235, 0, wxALL, 5 ); - bSizer237->Add( 10, 0, 0, 0, 5 ); + bSizer237->Add( 10, 0, 0, 0, 5 ); - wxBoxSizer* bSizer238; - bSizer238 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer238; + bSizer238 = new wxBoxSizer( wxVERTICAL ); - bSizer238->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer238->Add( 0, 0, 1, wxEXPAND, 5 ); - bSizerSyncDirHolder = new wxBoxSizer( wxHORIZONTAL ); + bSizerSyncDirHolder = new wxBoxSizer( wxHORIZONTAL ); - bSizerSyncDirections = new wxBoxSizer( wxVERTICAL ); + bSizerSyncDirections = new wxBoxSizer( wxVERTICAL ); - m_staticText184 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Difference"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText184->Wrap( -1 ); - bSizerSyncDirections->Add( m_staticText184, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + m_staticText184 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Difference"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText184->Wrap( -1 ); + bSizerSyncDirections->Add( m_staticText184, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - ffgSizer11 = new wxFlexGridSizer( 2, 0, 5, 5 ); - ffgSizer11->SetFlexibleDirection( wxBOTH ); - ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer11 = new wxFlexGridSizer( 2, 0, 5, 5 ); + ffgSizer11->SetFlexibleDirection( wxBOTH ); + ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_bitmapLeftOnly = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_bitmapLeftOnly->SetToolTip( _("Item exists on left side only") ); + m_bitmapLeftOnly = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_bitmapLeftOnly->SetToolTip( _("Item exists on left side only") ); - ffgSizer11->Add( m_bitmapLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer11->Add( m_bitmapLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapLeftNewer = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_bitmapLeftNewer->SetToolTip( _("Left side is newer") ); + m_bitmapLeftNewer = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_bitmapLeftNewer->SetToolTip( _("Left side is newer") ); - ffgSizer11->Add( m_bitmapLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer11->Add( m_bitmapLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapDifferent = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_bitmapDifferent->SetToolTip( _("Items have different content") ); + m_bitmapDifferent = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_bitmapDifferent->SetToolTip( _("Items have different content") ); - ffgSizer11->Add( m_bitmapDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer11->Add( m_bitmapDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapConflict = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_bitmapConflict->SetToolTip( _("Conflict/item cannot be categorized") ); + m_bitmapConflict = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_bitmapConflict->SetToolTip( _("Conflict/item cannot be categorized") ); - ffgSizer11->Add( m_bitmapConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer11->Add( m_bitmapConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapRightNewer = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_bitmapRightNewer->SetToolTip( _("Right side is newer") ); + m_bitmapRightNewer = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_bitmapRightNewer->SetToolTip( _("Right side is newer") ); - ffgSizer11->Add( m_bitmapRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer11->Add( m_bitmapRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapRightOnly = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_bitmapRightOnly->SetToolTip( _("Item exists on right side only") ); + m_bitmapRightOnly = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_bitmapRightOnly->SetToolTip( _("Item exists on right side only") ); - ffgSizer11->Add( m_bitmapRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer11->Add( m_bitmapRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonLeftOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - ffgSizer11->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bpButtonLeftOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + ffgSizer11->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonLeftNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - ffgSizer11->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bpButtonLeftNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + ffgSizer11->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonDifferent = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - ffgSizer11->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bpButtonDifferent = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + ffgSizer11->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonConflict = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - ffgSizer11->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bpButtonConflict = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + ffgSizer11->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonRightNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - ffgSizer11->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bpButtonRightNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + ffgSizer11->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonRightOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - ffgSizer11->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bpButtonRightOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + ffgSizer11->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerSyncDirections->Add( ffgSizer11, 0, 0, 5 ); + bSizerSyncDirections->Add( ffgSizer11, 0, 0, 5 ); - m_staticText120 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText120->Wrap( -1 ); - bSizerSyncDirections->Add( m_staticText120, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP, 5 ); + m_staticText120 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText120->Wrap( -1 ); + bSizerSyncDirections->Add( m_staticText120, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP, 5 ); - bSizerSyncDirHolder->Add( bSizerSyncDirections, 0, 0, 5 ); + bSizerSyncDirHolder->Add( bSizerSyncDirections, 0, 0, 5 ); - bSizerDatabase = new wxBoxSizer( wxVERTICAL ); + bSizerDatabase = new wxBoxSizer( wxVERTICAL ); - m_bitmapDatabase = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerDatabase->Add( m_bitmapDatabase, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + m_bitmapDatabase = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerDatabase->Add( m_bitmapDatabase, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizerDatabase->Add( 0, 3, 0, 0, 5 ); + bSizerDatabase->Add( 0, 3, 0, 0, 5 ); - m_staticText145 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("sync.ffs_db"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText145->Wrap( -1 ); - m_staticText145->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); - m_staticText145->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText145 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("sync.ffs_db"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText145->Wrap( -1 ); + m_staticText145->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); + m_staticText145->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizerDatabase->Add( m_staticText145, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizerDatabase->Add( m_staticText145, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizerSyncDirHolder->Add( bSizerDatabase, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerSyncDirHolder->Add( bSizerDatabase, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextSyncVarDescription = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextSyncVarDescription->Wrap( -1 ); - m_staticTextSyncVarDescription->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticTextSyncVarDescription = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticTextSyncVarDescription->Wrap( -1 ); + m_staticTextSyncVarDescription->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizerSyncDirHolder->Add( m_staticTextSyncVarDescription, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); + bSizerSyncDirHolder->Add( m_staticTextSyncVarDescription, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); - bSizer238->Add( bSizerSyncDirHolder, 0, wxTOP|wxBOTTOM|wxRIGHT, 10 ); + bSizer238->Add( bSizerSyncDirHolder, 0, wxTOP|wxBOTTOM|wxRIGHT, 10 ); - bSizer238->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer238->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticline431 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer238->Add( m_staticline431, 0, wxEXPAND, 5 ); + m_staticline431 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer238->Add( m_staticline431, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer201; - bSizer201 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer201; + bSizer201 = new wxBoxSizer( wxHORIZONTAL ); - m_staticline72 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer201->Add( m_staticline72, 0, wxEXPAND, 5 ); + m_staticline72 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer201->Add( m_staticline72, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer249; - bSizer249 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer249; + bSizer249 = new wxBoxSizer( wxHORIZONTAL ); - m_checkBoxDetectMove = new wxCheckBox( m_panelSyncSettings, wxID_ANY, _("Detect moved files"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxDetectMove->SetToolTip( _("- Not supported by all file systems\n- Requires and creates database files\n- Detection not available for first sync") ); + m_checkBoxDetectMove = new wxCheckBox( m_panelSyncSettings, wxID_ANY, _("Detect moved files"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxDetectMove->SetToolTip( _("- Not supported by all file systems\n- Requires and creates database files\n- Detection not available for first sync") ); - bSizer249->Add( m_checkBoxDetectMove, 0, wxALL|wxEXPAND, 5 ); + bSizer249->Add( m_checkBoxDetectMove, 0, wxALL|wxEXPAND, 5 ); - m_hyperlink242 = new wxHyperlinkCtrl( m_panelSyncSettings, wxID_ANY, _("More information"), wxT("https://freefilesync.org/manual.php?topic=synchronization-settings"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink242->SetToolTip( _("https://freefilesync.org/manual.php?topic=synchronization-settings") ); + m_hyperlink242 = new wxHyperlinkCtrl( m_panelSyncSettings, wxID_ANY, _("More information"), wxT("https://freefilesync.org/manual.php?topic=synchronization-settings"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink242->SetToolTip( _("https://freefilesync.org/manual.php?topic=synchronization-settings") ); - bSizer249->Add( m_hyperlink242, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer249->Add( m_hyperlink242, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer201->Add( bSizer249, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer201->Add( bSizer249, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer238->Add( bSizer201, 0, 0, 5 ); + bSizer238->Add( bSizer201, 0, 0, 5 ); - bSizer237->Add( bSizer238, 1, wxEXPAND, 5 ); + bSizer237->Add( bSizer238, 1, wxEXPAND, 5 ); - bSizer232->Add( bSizer237, 0, wxEXPAND, 5 ); + bSizer232->Add( bSizer237, 0, wxEXPAND, 5 ); - m_staticline54 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer232->Add( m_staticline54, 0, wxEXPAND, 5 ); + m_staticline54 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer232->Add( m_staticline54, 0, wxEXPAND, 5 ); - bSizer2361 = new wxBoxSizer( wxHORIZONTAL ); + bSizer2361 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer202; - bSizer202 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer202; + bSizer202 = new wxBoxSizer( wxVERTICAL ); - m_staticText87 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Delete files:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText87->Wrap( -1 ); - bSizer202->Add( m_staticText87, 0, wxALL, 5 ); + m_staticText87 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Delete and overwrite:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText87->Wrap( -1 ); + bSizer202->Add( m_staticText87, 0, wxALL, 5 ); - wxBoxSizer* bSizer234; - bSizer234 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer234; + bSizer234 = new wxBoxSizer( wxVERTICAL ); - m_buttonRecycler = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("&Recycle bin"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonRecycler = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("&Recycle bin"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonRecycler->SetDefault(); - m_buttonRecycler->SetToolTip( _("dummy") ); + m_buttonRecycler->SetDefault(); + m_buttonRecycler->SetToolTip( _("dummy") ); - bSizer234->Add( m_buttonRecycler, 0, wxEXPAND, 5 ); + bSizer234->Add( m_buttonRecycler, 0, wxEXPAND, 5 ); - m_buttonPermanent = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("&Permanent"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonPermanent = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("&Permanent"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonPermanent->SetDefault(); - m_buttonPermanent->SetToolTip( _("dummy") ); + m_buttonPermanent->SetDefault(); + m_buttonPermanent->SetToolTip( _("dummy") ); - bSizer234->Add( m_buttonPermanent, 0, wxEXPAND, 5 ); + bSizer234->Add( m_buttonPermanent, 0, wxEXPAND, 5 ); - m_buttonVersioning = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("&Versioning"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonVersioning = new zen::ToggleButton( m_panelSyncSettings, wxID_ANY, _("&Versioning"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonVersioning->SetDefault(); - m_buttonVersioning->SetToolTip( _("dummy") ); + m_buttonVersioning->SetDefault(); + m_buttonVersioning->SetToolTip( _("dummy") ); - bSizer234->Add( m_buttonVersioning, 0, wxEXPAND, 5 ); + bSizer234->Add( m_buttonVersioning, 0, wxEXPAND, 5 ); - bSizer202->Add( bSizer234, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizer202->Add( bSizer234, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer2361->Add( bSizer202, 0, wxALL, 5 ); + bSizer2361->Add( bSizer202, 0, wxALL, 5 ); - bSizerVersioningHolder = new wxBoxSizer( wxVERTICAL ); + bSizerVersioningHolder = new wxBoxSizer( wxVERTICAL ); - bSizerVersioningHolder->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizerVersioningHolder->Add( 0, 0, 1, wxEXPAND, 5 ); - wxBoxSizer* bSizer2331; - bSizer2331 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer2331; + bSizer2331 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapDeletionType = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer2331->Add( m_bitmapDeletionType, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_bitmapDeletionType = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2331->Add( m_bitmapDeletionType, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_staticTextDeletionTypeDescription = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDeletionTypeDescription->Wrap( -1 ); - m_staticTextDeletionTypeDescription->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticTextDeletionTypeDescription = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDeletionTypeDescription->Wrap( -1 ); + m_staticTextDeletionTypeDescription->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer2331->Add( m_staticTextDeletionTypeDescription, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer2331->Add( m_staticTextDeletionTypeDescription, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizerVersioningHolder->Add( bSizer2331, 0, wxALL|wxEXPAND, 5 ); + bSizerVersioningHolder->Add( bSizer2331, 0, wxALL|wxEXPAND, 5 ); - m_panelVersioning = new wxPanel( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelVersioning->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelVersioning = new wxPanel( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelVersioning->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer191; - bSizer191 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer191; + bSizer191 = new wxBoxSizer( wxVERTICAL ); - bSizer191->Add( 0, 5, 0, 0, 5 ); + bSizer191->Add( 0, 5, 0, 0, 5 ); - wxBoxSizer* bSizer252; - bSizer252 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer252; + bSizer252 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapVersioning = new wxStaticBitmap( m_panelVersioning, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer252->Add( m_bitmapVersioning, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_bitmapVersioning = new wxStaticBitmap( m_panelVersioning, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer252->Add( m_bitmapVersioning, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - wxBoxSizer* bSizer253; - bSizer253 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer253; + bSizer253 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer254; - bSizer254 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer254; + bSizer254 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText155 = new wxStaticText( m_panelVersioning, wxID_ANY, _("Move files to a user-defined folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText155->Wrap( -1 ); - m_staticText155->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText155 = new wxStaticText( m_panelVersioning, wxID_ANY, _("Move files to a user-defined folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText155->Wrap( -1 ); + m_staticText155->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer254->Add( m_staticText155, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizer254->Add( m_staticText155, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer254->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer254->Add( 0, 0, 1, wxEXPAND, 5 ); - m_hyperlink243 = new wxHyperlinkCtrl( m_panelVersioning, wxID_ANY, _("Show examples"), wxT("https://freefilesync.org/manual.php?topic=versioning"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink243->SetToolTip( _("https://freefilesync.org/manual.php?topic=versioning") ); + m_hyperlink243 = new wxHyperlinkCtrl( m_panelVersioning, wxID_ANY, _("Show examples"), wxT("https://freefilesync.org/manual.php?topic=versioning"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink243->SetToolTip( _("https://freefilesync.org/manual.php?topic=versioning") ); - bSizer254->Add( m_hyperlink243, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + bSizer254->Add( m_hyperlink243, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - bSizer253->Add( bSizer254, 0, wxEXPAND|wxBOTTOM, 5 ); + bSizer253->Add( bSizer254, 0, wxEXPAND|wxBOTTOM, 5 ); - wxBoxSizer* bSizer156; - bSizer156 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer156; + bSizer156 = new wxBoxSizer( wxHORIZONTAL ); - m_versioningFolderPath = new fff::FolderHistoryBox( m_panelVersioning, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer156->Add( m_versioningFolderPath, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_versioningFolderPath = new fff::FolderHistoryBox( m_panelVersioning, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer156->Add( m_versioningFolderPath, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectVersioningFolder = new wxButton( m_panelVersioning, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectVersioningFolder->SetToolTip( _("Select a folder") ); + m_buttonSelectVersioningFolder = new wxButton( m_panelVersioning, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectVersioningFolder->SetToolTip( _("Select a folder") ); - bSizer156->Add( m_buttonSelectVersioningFolder, 0, wxEXPAND, 5 ); + bSizer156->Add( m_buttonSelectVersioningFolder, 0, wxEXPAND, 5 ); - m_bpButtonSelectVersioningAltFolder = new wxBitmapButton( m_panelVersioning, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSelectVersioningAltFolder->SetToolTip( _("Access online storage") ); + m_bpButtonSelectVersioningAltFolder = new wxBitmapButton( m_panelVersioning, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSelectVersioningAltFolder->SetToolTip( _("Access online storage") ); - bSizer156->Add( m_bpButtonSelectVersioningAltFolder, 0, wxEXPAND, 5 ); + bSizer156->Add( m_bpButtonSelectVersioningAltFolder, 0, wxEXPAND, 5 ); - bSizer253->Add( bSizer156, 0, wxEXPAND, 5 ); + bSizer253->Add( bSizer156, 0, wxEXPAND, 5 ); - bSizer252->Add( bSizer253, 1, wxRIGHT, 5 ); + bSizer252->Add( bSizer253, 1, wxRIGHT, 5 ); - bSizer191->Add( bSizer252, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + bSizer191->Add( bSizer252, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - wxBoxSizer* bSizer198; - bSizer198 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer198; + bSizer198 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer255; - bSizer255 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer255; + bSizer255 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer256; - bSizer256 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer256; + bSizer256 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText93 = new wxStaticText( m_panelVersioning, wxID_ANY, _("Naming convention:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText93->Wrap( -1 ); - bSizer256->Add( m_staticText93, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_staticText93 = new wxStaticText( m_panelVersioning, wxID_ANY, _("Naming convention:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText93->Wrap( -1 ); + bSizer256->Add( m_staticText93, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - wxArrayString m_choiceVersioningStyleChoices; - m_choiceVersioningStyle = new wxChoice( m_panelVersioning, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceVersioningStyleChoices, 0 ); - m_choiceVersioningStyle->SetSelection( 0 ); - bSizer256->Add( m_choiceVersioningStyle, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxArrayString m_choiceVersioningStyleChoices; + m_choiceVersioningStyle = new wxChoice( m_panelVersioning, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceVersioningStyleChoices, 0 ); + m_choiceVersioningStyle->SetSelection( 0 ); + bSizer256->Add( m_choiceVersioningStyle, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer255->Add( bSizer256, 0, wxALL, 5 ); + bSizer255->Add( bSizer256, 0, wxALL, 5 ); - wxBoxSizer* bSizer257; - bSizer257 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer257; + bSizer257 = new wxBoxSizer( wxHORIZONTAL ); - m_staticTextNamingCvtPart1 = new wxStaticText( m_panelVersioning, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextNamingCvtPart1->Wrap( -1 ); - m_staticTextNamingCvtPart1->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticTextNamingCvtPart1 = new wxStaticText( m_panelVersioning, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextNamingCvtPart1->Wrap( -1 ); + m_staticTextNamingCvtPart1->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer257->Add( m_staticTextNamingCvtPart1, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer257->Add( m_staticTextNamingCvtPart1, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextNamingCvtPart2Bold = new wxStaticText( m_panelVersioning, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextNamingCvtPart2Bold->Wrap( -1 ); - m_staticTextNamingCvtPart2Bold->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_staticTextNamingCvtPart2Bold->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticTextNamingCvtPart2Bold = new wxStaticText( m_panelVersioning, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextNamingCvtPart2Bold->Wrap( -1 ); + m_staticTextNamingCvtPart2Bold->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextNamingCvtPart2Bold->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer257->Add( m_staticTextNamingCvtPart2Bold, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer257->Add( m_staticTextNamingCvtPart2Bold, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextNamingCvtPart3 = new wxStaticText( m_panelVersioning, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextNamingCvtPart3->Wrap( -1 ); - m_staticTextNamingCvtPart3->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticTextNamingCvtPart3 = new wxStaticText( m_panelVersioning, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextNamingCvtPart3->Wrap( -1 ); + m_staticTextNamingCvtPart3->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer257->Add( m_staticTextNamingCvtPart3, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer257->Add( m_staticTextNamingCvtPart3, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer255->Add( bSizer257, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizer255->Add( bSizer257, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer198->Add( bSizer255, 0, wxALL, 5 ); + bSizer198->Add( bSizer255, 0, wxALL, 5 ); - m_staticline69 = new wxStaticLine( m_panelVersioning, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer198->Add( m_staticline69, 0, wxEXPAND, 5 ); + m_staticline69 = new wxStaticLine( m_panelVersioning, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer198->Add( m_staticline69, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer258; - bSizer258 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer258; + bSizer258 = new wxBoxSizer( wxVERTICAL ); - m_staticTextLimitVersions = new wxStaticText( m_panelVersioning, wxID_ANY, _("Limit file versions:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextLimitVersions->Wrap( -1 ); - bSizer258->Add( m_staticTextLimitVersions, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + m_staticTextLimitVersions = new wxStaticText( m_panelVersioning, wxID_ANY, _("Limit file versions:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextLimitVersions->Wrap( -1 ); + bSizer258->Add( m_staticTextLimitVersions, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - fgSizer15 = new wxFlexGridSizer( 0, 3, 5, 10 ); - fgSizer15->SetFlexibleDirection( wxBOTH ); - fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + fgSizer15 = new wxFlexGridSizer( 0, 3, 5, 10 ); + fgSizer15->SetFlexibleDirection( wxBOTH ); + fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_checkBoxVersionMaxDays = new wxCheckBox( m_panelVersioning, wxID_ANY, _("Last x days:"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer15->Add( m_checkBoxVersionMaxDays, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_checkBoxVersionMaxDays = new wxCheckBox( m_panelVersioning, wxID_ANY, _("Last x days:"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer15->Add( m_checkBoxVersionMaxDays, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_checkBoxVersionCountMin = new wxCheckBox( m_panelVersioning, wxID_ANY, _("Minimum:"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer15->Add( m_checkBoxVersionCountMin, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_checkBoxVersionCountMin = new wxCheckBox( m_panelVersioning, wxID_ANY, _("Minimum:"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer15->Add( m_checkBoxVersionCountMin, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_checkBoxVersionCountMax = new wxCheckBox( m_panelVersioning, wxID_ANY, _("Maximum:"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer15->Add( m_checkBoxVersionCountMax, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_checkBoxVersionCountMax = new wxCheckBox( m_panelVersioning, wxID_ANY, _("Maximum:"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer15->Add( m_checkBoxVersionCountMax, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_spinCtrlVersionMaxDays = new wxSpinCtrl( m_panelVersioning, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); - fgSizer15->Add( m_spinCtrlVersionMaxDays, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_spinCtrlVersionMaxDays = new wxSpinCtrl( m_panelVersioning, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); + fgSizer15->Add( m_spinCtrlVersionMaxDays, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_spinCtrlVersionCountMin = new wxSpinCtrl( m_panelVersioning, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); - fgSizer15->Add( m_spinCtrlVersionCountMin, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_spinCtrlVersionCountMin = new wxSpinCtrl( m_panelVersioning, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); + fgSizer15->Add( m_spinCtrlVersionCountMin, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_spinCtrlVersionCountMax = new wxSpinCtrl( m_panelVersioning, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 2000000000, 1 ); - fgSizer15->Add( m_spinCtrlVersionCountMax, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_spinCtrlVersionCountMax = new wxSpinCtrl( m_panelVersioning, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 2000000000, 1 ); + fgSizer15->Add( m_spinCtrlVersionCountMax, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer258->Add( fgSizer15, 0, wxALL, 5 ); + bSizer258->Add( fgSizer15, 0, wxALL, 5 ); - bSizer198->Add( bSizer258, 0, wxALL, 5 ); + bSizer198->Add( bSizer258, 0, wxALL, 5 ); - bSizer191->Add( bSizer198, 0, wxEXPAND, 5 ); + bSizer191->Add( bSizer198, 0, wxEXPAND, 5 ); - m_panelVersioning->SetSizer( bSizer191 ); - m_panelVersioning->Layout(); - bSizer191->Fit( m_panelVersioning ); - bSizerVersioningHolder->Add( m_panelVersioning, 0, wxEXPAND, 5 ); + m_panelVersioning->SetSizer( bSizer191 ); + m_panelVersioning->Layout(); + bSizer191->Fit( m_panelVersioning ); + bSizerVersioningHolder->Add( m_panelVersioning, 0, wxEXPAND, 5 ); - bSizerVersioningHolder->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizerVersioningHolder->Add( 0, 0, 1, wxEXPAND, 5 ); - bSizer2361->Add( bSizerVersioningHolder, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer2361->Add( bSizerVersioningHolder, 1, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer232->Add( bSizer2361, 0, wxEXPAND, 5 ); + bSizer232->Add( bSizer2361, 0, wxEXPAND, 5 ); - m_staticline582 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer232->Add( m_staticline582, 0, wxEXPAND, 5 ); + m_staticline582 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer232->Add( m_staticline582, 0, wxEXPAND, 5 ); - bSizerSyncMisc = new wxBoxSizer( wxHORIZONTAL ); + bSizerSyncMisc = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer292; - bSizer292 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer292; + bSizer292 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer287; - bSizer287 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer287; + bSizer287 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer290; - bSizer290 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer290; + bSizer290 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer291; - bSizer291 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer291; + bSizer291 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapEmail = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer291->Add( m_bitmapEmail, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapEmail = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer291->Add( m_bitmapEmail, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_checkBoxSendEmail = new wxCheckBox( m_panelSyncSettings, wxID_ANY, _("Send email notification:"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer291->Add( m_checkBoxSendEmail, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + m_checkBoxSendEmail = new wxCheckBox( m_panelSyncSettings, wxID_ANY, _("Send email notification:"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer291->Add( m_checkBoxSendEmail, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - bSizer290->Add( bSizer291, 0, 0, 5 ); + bSizer290->Add( bSizer291, 0, 0, 5 ); - m_comboBoxEmail = new fff::CommandBox( m_panelSyncSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer290->Add( m_comboBoxEmail, 0, wxEXPAND|wxTOP, 5 ); + m_comboBoxEmail = new fff::CommandBox( m_panelSyncSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer290->Add( m_comboBoxEmail, 0, wxEXPAND|wxTOP, 5 ); - bSizer287->Add( bSizer290, 1, wxRIGHT, 5 ); + bSizer287->Add( bSizer290, 1, wxRIGHT, 5 ); - wxBoxSizer* bSizer289; - bSizer289 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer289; + bSizer289 = new wxBoxSizer( wxVERTICAL ); - m_bpButtonEmailAlways = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizer289->Add( m_bpButtonEmailAlways, 0, 0, 5 ); + m_bpButtonEmailAlways = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer289->Add( m_bpButtonEmailAlways, 0, 0, 5 ); - m_bpButtonEmailErrorWarning = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizer289->Add( m_bpButtonEmailErrorWarning, 0, 0, 5 ); + m_bpButtonEmailErrorWarning = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer289->Add( m_bpButtonEmailErrorWarning, 0, 0, 5 ); - m_bpButtonEmailErrorOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizer289->Add( m_bpButtonEmailErrorOnly, 0, 0, 5 ); + m_bpButtonEmailErrorOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer289->Add( m_bpButtonEmailErrorOnly, 0, 0, 5 ); - bSizer287->Add( bSizer289, 0, wxLEFT, 5 ); + bSizer287->Add( bSizer289, 0, wxLEFT, 5 ); - bSizer292->Add( bSizer287, 0, wxEXPAND, 5 ); + bSizer292->Add( bSizer287, 0, wxEXPAND, 5 ); - m_hyperlinkPerfDeRequired2 = new wxHyperlinkCtrl( m_panelSyncSettings, wxID_ANY, _("Requires FreeFileSync Donation Edition"), wxT("https://freefilesync.org/faq.php#donation-edition"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlinkPerfDeRequired2->SetToolTip( _("https://freefilesync.org/faq.php#donation-edition") ); + m_hyperlinkPerfDeRequired2 = new wxHyperlinkCtrl( m_panelSyncSettings, wxID_ANY, _("Requires FreeFileSync Donation Edition"), wxT("https://freefilesync.org/faq.php#donation-edition"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlinkPerfDeRequired2->SetToolTip( _("https://freefilesync.org/faq.php#donation-edition") ); - bSizer292->Add( m_hyperlinkPerfDeRequired2, 0, wxALL, 5 ); + bSizer292->Add( m_hyperlinkPerfDeRequired2, 0, wxALL, 5 ); - bSizerSyncMisc->Add( bSizer292, 0, wxEXPAND|wxALL, 10 ); + bSizerSyncMisc->Add( bSizer292, 0, wxEXPAND|wxALL, 10 ); - m_staticline57 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerSyncMisc->Add( m_staticline57, 0, wxEXPAND, 5 ); + m_staticline57 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizerSyncMisc->Add( m_staticline57, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer293; - bSizer293 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer293; + bSizer293 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer2372; - bSizer2372 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer2372; + bSizer2372 = new wxBoxSizer( wxHORIZONTAL ); - m_panelLogfile = new wxPanel( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelLogfile->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelLogfile = new wxPanel( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelLogfile->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer1912; - bSizer1912 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer1912; + bSizer1912 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer279; - bSizer279 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer279; + bSizer279 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapLogFile = new wxStaticBitmap( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer279->Add( m_bitmapLogFile, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapLogFile = new wxStaticBitmap( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer279->Add( m_bitmapLogFile, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_checkBoxOverrideLogPath = new wxCheckBox( m_panelLogfile, wxID_ANY, _("&Change log folder:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxOverrideLogPath->SetValue(true); - bSizer279->Add( m_checkBoxOverrideLogPath, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + m_checkBoxOverrideLogPath = new wxCheckBox( m_panelLogfile, wxID_ANY, _("&Change log folder:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxOverrideLogPath->SetValue(true); + bSizer279->Add( m_checkBoxOverrideLogPath, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - bSizer279->Add( 0, 0, 1, 0, 5 ); + bSizer279->Add( 0, 0, 1, 0, 5 ); - m_bpButtonShowLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonShowLogFolder->SetToolTip( _("dummy") ); + m_bpButtonShowLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonShowLogFolder->SetToolTip( _("dummy") ); - bSizer279->Add( m_bpButtonShowLogFolder, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer279->Add( m_bpButtonShowLogFolder, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer1912->Add( bSizer279, 0, wxEXPAND, 5 ); + bSizer1912->Add( bSizer279, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer297; - bSizer297 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer297; + bSizer297 = new wxBoxSizer( wxHORIZONTAL ); - m_logFolderPath = new fff::FolderHistoryBox( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer297->Add( m_logFolderPath, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_logFolderPath = new fff::FolderHistoryBox( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer297->Add( m_logFolderPath, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectLogFolder = new wxButton( m_panelLogfile, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectLogFolder->SetToolTip( _("Select a folder") ); + m_buttonSelectLogFolder = new wxButton( m_panelLogfile, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectLogFolder->SetToolTip( _("Select a folder") ); - bSizer297->Add( m_buttonSelectLogFolder, 0, wxEXPAND, 5 ); + bSizer297->Add( m_buttonSelectLogFolder, 0, wxEXPAND, 5 ); - m_bpButtonSelectAltLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSelectAltLogFolder->SetToolTip( _("Access online storage") ); + m_bpButtonSelectAltLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSelectAltLogFolder->SetToolTip( _("Access online storage") ); - bSizer297->Add( m_bpButtonSelectAltLogFolder, 0, wxEXPAND, 5 ); + bSizer297->Add( m_bpButtonSelectAltLogFolder, 0, wxEXPAND, 5 ); - bSizer1912->Add( bSizer297, 0, wxEXPAND|wxTOP, 5 ); + bSizer1912->Add( bSizer297, 0, wxEXPAND|wxTOP, 5 ); - m_panelLogfile->SetSizer( bSizer1912 ); - m_panelLogfile->Layout(); - bSizer1912->Fit( m_panelLogfile ); - bSizer2372->Add( m_panelLogfile, 1, 0, 5 ); + m_panelLogfile->SetSizer( bSizer1912 ); + m_panelLogfile->Layout(); + bSizer1912->Fit( m_panelLogfile ); + bSizer2372->Add( m_panelLogfile, 1, 0, 5 ); - bSizer293->Add( bSizer2372, 0, wxALL|wxEXPAND, 10 ); + bSizer293->Add( bSizer2372, 0, wxALL|wxEXPAND, 10 ); - m_staticline80 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer293->Add( m_staticline80, 0, wxEXPAND, 5 ); + m_staticline80 = new wxStaticLine( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer293->Add( m_staticline80, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer247; - bSizer247 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer247; + bSizer247 = new wxBoxSizer( wxHORIZONTAL ); - m_staticTextPostSync = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Run a command:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextPostSync->Wrap( -1 ); - bSizer247->Add( m_staticTextPostSync, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextPostSync = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Run a command:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextPostSync->Wrap( -1 ); + bSizer247->Add( m_staticTextPostSync, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - wxArrayString m_choicePostSyncConditionChoices; - m_choicePostSyncCondition = new wxChoice( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choicePostSyncConditionChoices, 0 ); - m_choicePostSyncCondition->SetSelection( 0 ); - bSizer247->Add( m_choicePostSyncCondition, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxArrayString m_choicePostSyncConditionChoices; + m_choicePostSyncCondition = new wxChoice( m_panelSyncSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choicePostSyncConditionChoices, 0 ); + m_choicePostSyncCondition->SetSelection( 0 ); + bSizer247->Add( m_choicePostSyncCondition, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_comboBoxPostSyncCommand = new fff::CommandBox( m_panelSyncSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer247->Add( m_comboBoxPostSyncCommand, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + m_comboBoxPostSyncCommand = new fff::CommandBox( m_panelSyncSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer247->Add( m_comboBoxPostSyncCommand, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer293->Add( bSizer247, 0, wxALL|wxEXPAND, 10 ); + bSizer293->Add( bSizer247, 0, wxALL|wxEXPAND, 10 ); - bSizerSyncMisc->Add( bSizer293, 1, 0, 5 ); + bSizerSyncMisc->Add( bSizer293, 1, 0, 5 ); - bSizer232->Add( bSizerSyncMisc, 1, wxEXPAND, 5 ); + bSizer232->Add( bSizerSyncMisc, 1, wxEXPAND, 5 ); - m_panelSyncSettings->SetSizer( bSizer232 ); - m_panelSyncSettings->Layout(); - bSizer232->Fit( m_panelSyncSettings ); - bSizer276->Add( m_panelSyncSettings, 1, wxEXPAND, 5 ); + m_panelSyncSettings->SetSizer( bSizer232 ); + m_panelSyncSettings->Layout(); + bSizer232->Fit( m_panelSyncSettings ); + bSizer276->Add( m_panelSyncSettings, 1, wxEXPAND, 5 ); - m_panelSyncSettingsTab->SetSizer( bSizer276 ); - m_panelSyncSettingsTab->Layout(); - bSizer276->Fit( m_panelSyncSettingsTab ); - m_notebook->AddPage( m_panelSyncSettingsTab, _("dummy"), false ); + m_panelSyncSettingsTab->SetSizer( bSizer276 ); + m_panelSyncSettingsTab->Layout(); + bSizer276->Fit( m_panelSyncSettingsTab ); + m_notebook->AddPage( m_panelSyncSettingsTab, _("dummy"), false ); - bSizer190->Add( m_notebook, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + bSizer190->Add( m_notebook, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - bSizer7->Add( bSizer190, 1, wxEXPAND, 5 ); + bSizer7->Add( bSizer190, 1, wxEXPAND, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonOkay->SetDefault(); + m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer7->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + bSizer7->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - this->SetSizer( bSizer7 ); - this->Layout(); - bSizer7->Fit( this ); + this->SetSizer( bSizer7 ); + this->Layout(); + bSizer7->Fit( this ); - this->Centre( wxBOTH ); + this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ConfigDlgGenerated::onClose ) ); - m_listBoxFolderPair->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( ConfigDlgGenerated::onListBoxKeyEvent ), NULL, this ); - m_listBoxFolderPair->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onSelectFolderPair ), NULL, this ); - m_checkBoxUseLocalCmpOptions->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleLocalCompSettings ), NULL, this ); - m_buttonByTimeSize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onCompByTimeSize ), NULL, this ); - m_buttonByTimeSize->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onCompByTimeSizeDouble ), NULL, this ); - m_buttonByContent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onCompByContent ), NULL, this ); - m_buttonByContent->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onCompByContentDouble ), NULL, this ); - m_buttonBySize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onCompBySize ), NULL, this ); - m_buttonBySize->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onCompBySizeDouble ), NULL, this ); - m_checkBoxSymlinksInclude->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onChangeCompOption ), NULL, this ); - m_checkBoxIgnoreErrors->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleIgnoreErrors ), NULL, this ); - m_checkBoxAutoRetry->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleAutoRetry ), NULL, this ); - m_textCtrlInclude->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); - m_textCtrlExclude->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); - m_choiceUnitMinSize->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); - m_choiceUnitMaxSize->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); - m_choiceUnitTimespan->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); - m_buttonDefault->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onFilterDefault ), NULL, this ); - m_buttonDefault->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( ConfigDlgGenerated::onFilterDefaultContextMouse ), NULL, this ); - m_bpButtonDefaultContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onFilterDefaultContext ), NULL, this ); - m_bpButtonDefaultContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( ConfigDlgGenerated::onFilterDefaultContextMouse ), NULL, this ); - m_buttonClear->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onFilterClear ), NULL, this ); - m_checkBoxUseLocalSyncOptions->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleLocalSyncSettings ), NULL, this ); - m_buttonTwoWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onSyncTwoWay ), NULL, this ); - m_buttonTwoWay->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onSyncTwoWayDouble ), NULL, this ); - m_buttonMirror->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onSyncMirror ), NULL, this ); - m_buttonMirror->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onSyncMirrorDouble ), NULL, this ); - m_buttonUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onSyncUpdate ), NULL, this ); - m_buttonUpdate->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onSyncUpdateDouble ), NULL, this ); - m_buttonCustom->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onSyncCustom ), NULL, this ); - m_buttonCustom->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onSyncCustomDouble ), NULL, this ); - m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onExLeftSideOnly ), NULL, this ); - m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onLeftNewer ), NULL, this ); - m_bpButtonDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onDifferent ), NULL, this ); - m_bpButtonConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onConflict ), NULL, this ); - m_bpButtonRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onRightNewer ), NULL, this ); - m_bpButtonRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onExRightSideOnly ), NULL, this ); - m_checkBoxDetectMove->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleDetectMovedFiles ), NULL, this ); - m_buttonRecycler->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onDeletionRecycler ), NULL, this ); - m_buttonPermanent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onDeletionPermanent ), NULL, this ); - m_buttonVersioning->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onDeletionVersioning ), NULL, this ); - m_choiceVersioningStyle->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onChanegVersioningStyle ), NULL, this ); - m_checkBoxVersionMaxDays->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleVersioningLimit ), NULL, this ); - m_checkBoxVersionCountMin->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleVersioningLimit ), NULL, this ); - m_checkBoxVersionCountMax->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleVersioningLimit ), NULL, this ); - m_checkBoxSendEmail->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleMiscEmail ), NULL, this ); - m_bpButtonEmailAlways->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onEmailAlways ), NULL, this ); - m_bpButtonEmailErrorWarning->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onEmailErrorWarning ), NULL, this ); - m_bpButtonEmailErrorOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onEmailErrorOnly ), NULL, this ); - m_checkBoxOverrideLogPath->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleMiscOption ), NULL, this ); - m_bpButtonShowLogFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onShowLogFolder ), NULL, this ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onCancel ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ConfigDlgGenerated::onClose ) ); + m_listBoxFolderPair->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( ConfigDlgGenerated::onListBoxKeyEvent ), NULL, this ); + m_listBoxFolderPair->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onSelectFolderPair ), NULL, this ); + m_checkBoxUseLocalCmpOptions->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleLocalCompSettings ), NULL, this ); + m_buttonByTimeSize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onCompByTimeSize ), NULL, this ); + m_buttonByTimeSize->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onCompByTimeSizeDouble ), NULL, this ); + m_buttonByContent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onCompByContent ), NULL, this ); + m_buttonByContent->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onCompByContentDouble ), NULL, this ); + m_buttonBySize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onCompBySize ), NULL, this ); + m_buttonBySize->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onCompBySizeDouble ), NULL, this ); + m_checkBoxSymlinksInclude->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onChangeCompOption ), NULL, this ); + m_checkBoxIgnoreErrors->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleIgnoreErrors ), NULL, this ); + m_checkBoxAutoRetry->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleAutoRetry ), NULL, this ); + m_textCtrlInclude->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); + m_textCtrlExclude->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); + m_choiceUnitMinSize->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); + m_choiceUnitMaxSize->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); + m_choiceUnitTimespan->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onChangeFilterOption ), NULL, this ); + m_buttonDefault->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onFilterDefault ), NULL, this ); + m_buttonDefault->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( ConfigDlgGenerated::onFilterDefaultContextMouse ), NULL, this ); + m_bpButtonDefaultContext->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onFilterDefaultContext ), NULL, this ); + m_bpButtonDefaultContext->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( ConfigDlgGenerated::onFilterDefaultContextMouse ), NULL, this ); + m_buttonClear->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onFilterClear ), NULL, this ); + m_checkBoxUseLocalSyncOptions->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleLocalSyncSettings ), NULL, this ); + m_buttonTwoWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onSyncTwoWay ), NULL, this ); + m_buttonTwoWay->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onSyncTwoWayDouble ), NULL, this ); + m_buttonMirror->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onSyncMirror ), NULL, this ); + m_buttonMirror->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onSyncMirrorDouble ), NULL, this ); + m_buttonUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onSyncUpdate ), NULL, this ); + m_buttonUpdate->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onSyncUpdateDouble ), NULL, this ); + m_buttonCustom->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onSyncCustom ), NULL, this ); + m_buttonCustom->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( ConfigDlgGenerated::onSyncCustomDouble ), NULL, this ); + m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onExLeftSideOnly ), NULL, this ); + m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onLeftNewer ), NULL, this ); + m_bpButtonDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onDifferent ), NULL, this ); + m_bpButtonConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onConflict ), NULL, this ); + m_bpButtonRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onRightNewer ), NULL, this ); + m_bpButtonRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onExRightSideOnly ), NULL, this ); + m_checkBoxDetectMove->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleDetectMovedFiles ), NULL, this ); + m_buttonRecycler->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onDeletionRecycler ), NULL, this ); + m_buttonPermanent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onDeletionPermanent ), NULL, this ); + m_buttonVersioning->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onDeletionVersioning ), NULL, this ); + m_choiceVersioningStyle->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( ConfigDlgGenerated::onChanegVersioningStyle ), NULL, this ); + m_checkBoxVersionMaxDays->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleVersioningLimit ), NULL, this ); + m_checkBoxVersionCountMin->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleVersioningLimit ), NULL, this ); + m_checkBoxVersionCountMax->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleVersioningLimit ), NULL, this ); + m_checkBoxSendEmail->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleMiscEmail ), NULL, this ); + m_bpButtonEmailAlways->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onEmailAlways ), NULL, this ); + m_bpButtonEmailErrorWarning->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onEmailErrorWarning ), NULL, this ); + m_bpButtonEmailErrorOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onEmailErrorOnly ), NULL, this ); + m_checkBoxOverrideLogPath->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onToggleMiscOption ), NULL, this ); + m_bpButtonShowLogFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onShowLogFolder ), NULL, this ); + m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onOkay ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDlgGenerated::onCancel ), NULL, this ); } ConfigDlgGenerated::~ConfigDlgGenerated() @@ -2580,537 +2580,543 @@ ConfigDlgGenerated::~ConfigDlgGenerated() CloudSetupDlgGenerated::CloudSetupDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer134; - bSizer134 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer134; + bSizer134 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapCloud = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer72->Add( m_bitmapCloud, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); + m_bitmapCloud = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer72->Add( m_bitmapCloud, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - wxBoxSizer* bSizer272; - bSizer272 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer272; + bSizer272 = new wxBoxSizer( wxVERTICAL ); - m_staticText136 = new wxStaticText( this, wxID_ANY, _("Connection type:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText136->Wrap( -1 ); - bSizer272->Add( m_staticText136, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + m_staticText136 = new wxStaticText( this, wxID_ANY, _("Connection type:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText136->Wrap( -1 ); + bSizer272->Add( m_staticText136, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - wxBoxSizer* bSizer231; - bSizer231 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer231; + bSizer231 = new wxBoxSizer( wxHORIZONTAL ); - m_toggleBtnGdrive = new wxToggleButton( this, wxID_ANY, _("Google Drive"), wxDefaultPosition, wxDefaultSize, 0 ); - m_toggleBtnGdrive->SetValue( true ); - m_toggleBtnGdrive->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_toggleBtnGdrive = new wxToggleButton( this, wxID_ANY, _("Google Drive"), wxDefaultPosition, wxDefaultSize, 0 ); + m_toggleBtnGdrive->SetValue( true ); + m_toggleBtnGdrive->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer231->Add( m_toggleBtnGdrive, 0, wxTOP|wxBOTTOM|wxLEFT|wxEXPAND, 5 ); + bSizer231->Add( m_toggleBtnGdrive, 0, wxTOP|wxBOTTOM|wxLEFT|wxEXPAND, 5 ); - m_toggleBtnSftp = new wxToggleButton( this, wxID_ANY, _("SFTP"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_toggleBtnSftp->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_toggleBtnSftp = new wxToggleButton( this, wxID_ANY, _("SFTP"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_toggleBtnSftp->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer231->Add( m_toggleBtnSftp, 0, wxTOP|wxBOTTOM|wxLEFT|wxEXPAND, 5 ); + bSizer231->Add( m_toggleBtnSftp, 0, wxTOP|wxBOTTOM|wxLEFT|wxEXPAND, 5 ); - m_toggleBtnFtp = new wxToggleButton( this, wxID_ANY, _("FTP"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_toggleBtnFtp->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_toggleBtnFtp = new wxToggleButton( this, wxID_ANY, _("FTP"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_toggleBtnFtp->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer231->Add( m_toggleBtnFtp, 0, wxALL|wxEXPAND, 5 ); + bSizer231->Add( m_toggleBtnFtp, 0, wxALL|wxEXPAND, 5 ); - bSizer272->Add( bSizer231, 0, 0, 5 ); + bSizer272->Add( bSizer231, 0, 0, 5 ); - bSizer72->Add( bSizer272, 0, wxALL, 5 ); + bSizer72->Add( bSizer272, 0, wxALL, 5 ); - bSizer134->Add( bSizer72, 0, wxEXPAND, 5 ); + bSizer134->Add( bSizer72, 0, wxEXPAND, 5 ); - m_staticline371 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline371, 0, wxEXPAND, 5 ); + m_staticline371 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxLI_HORIZONTAL ); + bSizer134->Add( m_staticline371, 0, wxEXPAND, 5 ); - m_panel41 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel41->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel41 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel41->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer185; - bSizer185 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer185; + bSizer185 = new wxBoxSizer( wxVERTICAL ); - bSizerGdrive = new wxBoxSizer( wxVERTICAL ); + bSizerGdrive = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer284; - bSizer284 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer284; + bSizer284 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer307; - bSizer307 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer307; + bSizer307 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer306; - bSizer306 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer306; + bSizer306 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapGdriveUser = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer306->Add( m_bitmapGdriveUser, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapGdriveUser = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer306->Add( m_bitmapGdriveUser, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_staticText166 = new wxStaticText( m_panel41, wxID_ANY, _("Connected user accounts:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText166->Wrap( -1 ); - bSizer306->Add( m_staticText166, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText166 = new wxStaticText( m_panel41, wxID_ANY, _("Connected user accounts:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText166->Wrap( -1 ); + bSizer306->Add( m_staticText166, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer307->Add( bSizer306, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer307->Add( bSizer306, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_listBoxGdriveUsers = new wxListBox( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB|wxLB_SINGLE|wxLB_SORT ); - bSizer307->Add( m_listBoxGdriveUsers, 1, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + m_listBoxGdriveUsers = new wxListBox( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB|wxLB_SINGLE|wxLB_SORT ); + bSizer307->Add( m_listBoxGdriveUsers, 1, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - wxBoxSizer* bSizer3002; - bSizer3002 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer3002; + bSizer3002 = new wxBoxSizer( wxHORIZONTAL ); - m_buttonGdriveAddUser = new zen::BitmapTextButton( m_panel41, wxID_ANY, _("&Add connection"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer3002->Add( m_buttonGdriveAddUser, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_buttonGdriveAddUser = new zen::BitmapTextButton( m_panel41, wxID_ANY, _("&Add connection"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer3002->Add( m_buttonGdriveAddUser, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonGdriveRemoveUser = new zen::BitmapTextButton( m_panel41, wxID_ANY, _("&Disconnect"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer3002->Add( m_buttonGdriveRemoveUser, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + m_buttonGdriveRemoveUser = new zen::BitmapTextButton( m_panel41, wxID_ANY, _("&Disconnect"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer3002->Add( m_buttonGdriveRemoveUser, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - bSizer307->Add( bSizer3002, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer307->Add( bSizer3002, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer284->Add( bSizer307, 0, wxALL|wxEXPAND, 5 ); + bSizer284->Add( bSizer307, 0, wxALL|wxEXPAND, 5 ); - m_staticline841 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer284->Add( m_staticline841, 0, wxEXPAND, 5 ); + m_staticline841 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer284->Add( m_staticline841, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer3041; - bSizer3041 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer3041; + bSizer3041 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer305; - bSizer305 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer305; + bSizer305 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapGdriveDrive = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer305->Add( m_bitmapGdriveDrive, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapGdriveDrive = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer305->Add( m_bitmapGdriveDrive, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText186 = new wxStaticText( m_panel41, wxID_ANY, _("Select drive:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText186->Wrap( -1 ); - bSizer305->Add( m_staticText186, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText186 = new wxStaticText( m_panel41, wxID_ANY, _("Select drive:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText186->Wrap( -1 ); + bSizer305->Add( m_staticText186, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer3041->Add( bSizer305, 0, wxALL, 5 ); + bSizer3041->Add( bSizer305, 0, wxALL, 5 ); - m_listBoxGdriveDrives = new wxListBox( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB|wxLB_SINGLE ); - bSizer3041->Add( m_listBoxGdriveDrives, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_listBoxGdriveDrives = new wxListBox( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB|wxLB_SINGLE ); + bSizer3041->Add( m_listBoxGdriveDrives, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer284->Add( bSizer3041, 1, wxALL|wxEXPAND, 5 ); + bSizer284->Add( bSizer3041, 1, wxALL|wxEXPAND, 5 ); - bSizerGdrive->Add( bSizer284, 1, wxEXPAND, 5 ); + bSizerGdrive->Add( bSizer284, 1, wxEXPAND, 5 ); - m_staticline73 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerGdrive->Add( m_staticline73, 0, wxEXPAND, 5 ); + m_staticline73 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerGdrive->Add( m_staticline73, 0, wxEXPAND, 5 ); - bSizer185->Add( bSizerGdrive, 1, wxEXPAND, 5 ); + bSizer185->Add( bSizerGdrive, 1, wxEXPAND, 5 ); - bSizerServer = new wxBoxSizer( wxVERTICAL ); + bSizerServer = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer276; - bSizer276 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer276; + bSizer276 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapServer = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer276->Add( m_bitmapServer, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapServer = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer276->Add( m_bitmapServer, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText12311 = new wxStaticText( m_panel41, wxID_ANY, _("Server name or IP address:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText12311->Wrap( -1 ); - bSizer276->Add( m_staticText12311, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + m_staticText12311 = new wxStaticText( m_panel41, wxID_ANY, _("Server name or IP address:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText12311->Wrap( -1 ); + bSizer276->Add( m_staticText12311, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - m_textCtrlServer = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer276->Add( m_textCtrlServer, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_textCtrlServer = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer276->Add( m_textCtrlServer, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText1233 = new wxStaticText( m_panel41, wxID_ANY, _("Port:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1233->Wrap( -1 ); - bSizer276->Add( m_staticText1233, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + m_staticText1233 = new wxStaticText( m_panel41, wxID_ANY, _("Port:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1233->Wrap( -1 ); + bSizer276->Add( m_staticText1233, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - m_textCtrlPort = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer276->Add( m_textCtrlPort, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_textCtrlPort = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer276->Add( m_textCtrlPort, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerServer->Add( bSizer276, 0, wxALL|wxEXPAND, 5 ); + bSizerServer->Add( bSizer276, 0, wxALL|wxEXPAND, 5 ); - m_staticline58 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerServer->Add( m_staticline58, 0, wxEXPAND, 5 ); + m_staticline58 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerServer->Add( m_staticline58, 0, wxEXPAND, 5 ); - bSizer185->Add( bSizerServer, 0, wxEXPAND, 5 ); + bSizer185->Add( bSizerServer, 0, wxEXPAND, 5 ); - bSizerAuth = new wxBoxSizer( wxVERTICAL ); + bSizerAuth = new wxBoxSizer( wxVERTICAL ); - bSizerAuthInner = new wxBoxSizer( wxHORIZONTAL ); + bSizerAuthInner = new wxBoxSizer( wxHORIZONTAL ); - bSizerFtpEncrypt = new wxBoxSizer( wxHORIZONTAL ); + bSizerFtpEncrypt = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer2181; - bSizer2181 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer2181; + bSizer2181 = new wxBoxSizer( wxVERTICAL ); - m_staticText1251 = new wxStaticText( m_panel41, wxID_ANY, _("Encryption:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1251->Wrap( -1 ); - bSizer2181->Add( m_staticText1251, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + m_staticText1251 = new wxStaticText( m_panel41, wxID_ANY, _("Encryption:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1251->Wrap( -1 ); + bSizer2181->Add( m_staticText1251, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - m_radioBtnEncryptNone = new wxRadioButton( m_panel41, wxID_ANY, _("&Disabled"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); - m_radioBtnEncryptNone->SetValue( true ); - bSizer2181->Add( m_radioBtnEncryptNone, 0, wxEXPAND|wxALL, 5 ); + m_radioBtnEncryptNone = new wxRadioButton( m_panel41, wxID_ANY, _("&Disabled"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); + m_radioBtnEncryptNone->SetValue( true ); + bSizer2181->Add( m_radioBtnEncryptNone, 0, wxEXPAND|wxALL, 5 ); - m_radioBtnEncryptSsl = new wxRadioButton( m_panel41, wxID_ANY, _("&Explicit SSL/TLS"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer2181->Add( m_radioBtnEncryptSsl, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + m_radioBtnEncryptSsl = new wxRadioButton( m_panel41, wxID_ANY, _("&Explicit SSL/TLS"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2181->Add( m_radioBtnEncryptSsl, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - bSizerFtpEncrypt->Add( bSizer2181, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerFtpEncrypt->Add( bSizer2181, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticline5721 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerFtpEncrypt->Add( m_staticline5721, 0, wxEXPAND, 5 ); + m_staticline5721 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizerFtpEncrypt->Add( m_staticline5721, 0, wxEXPAND, 5 ); - bSizerAuthInner->Add( bSizerFtpEncrypt, 0, wxEXPAND, 5 ); + bSizerAuthInner->Add( bSizerFtpEncrypt, 0, wxEXPAND, 5 ); - bSizerSftpAuth = new wxBoxSizer( wxHORIZONTAL ); + bSizerSftpAuth = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer218; - bSizer218 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer218; + bSizer218 = new wxBoxSizer( wxVERTICAL ); - m_staticText125 = new wxStaticText( m_panel41, wxID_ANY, _("Authentication:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText125->Wrap( -1 ); - bSizer218->Add( m_staticText125, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + m_staticText125 = new wxStaticText( m_panel41, wxID_ANY, _("Authentication:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText125->Wrap( -1 ); + bSizer218->Add( m_staticText125, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - m_radioBtnPassword = new wxRadioButton( m_panel41, wxID_ANY, _("&Password"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); - m_radioBtnPassword->SetValue( true ); - bSizer218->Add( m_radioBtnPassword, 0, wxEXPAND|wxALL, 5 ); + m_radioBtnPassword = new wxRadioButton( m_panel41, wxID_ANY, _("&Password"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); + m_radioBtnPassword->SetValue( true ); + bSizer218->Add( m_radioBtnPassword, 0, wxEXPAND|wxALL, 5 ); - m_radioBtnKeyfile = new wxRadioButton( m_panel41, wxID_ANY, _("&Key file"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer218->Add( m_radioBtnKeyfile, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + m_radioBtnKeyfile = new wxRadioButton( m_panel41, wxID_ANY, _("&Key file"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer218->Add( m_radioBtnKeyfile, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - m_radioBtnAgent = new wxRadioButton( m_panel41, wxID_ANY, _("&SSH agent"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer218->Add( m_radioBtnAgent, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_radioBtnAgent = new wxRadioButton( m_panel41, wxID_ANY, _("&SSH agent"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer218->Add( m_radioBtnAgent, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizerSftpAuth->Add( bSizer218, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerSftpAuth->Add( bSizer218, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticline572 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerSftpAuth->Add( m_staticline572, 0, wxEXPAND, 5 ); + m_staticline572 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizerSftpAuth->Add( m_staticline572, 0, wxEXPAND, 5 ); - bSizerAuthInner->Add( bSizerSftpAuth, 0, wxEXPAND, 5 ); + bSizerAuthInner->Add( bSizerSftpAuth, 0, wxEXPAND, 5 ); - m_panelAuth = new wxPanel( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelAuth->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelAuth = new wxPanel( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelAuth->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer221; - bSizer221 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer221; + bSizer221 = new wxBoxSizer( wxVERTICAL ); - wxFlexGridSizer* fgSizer161; - fgSizer161 = new wxFlexGridSizer( 0, 2, 0, 0 ); - fgSizer161->AddGrowableCol( 1 ); - fgSizer161->SetFlexibleDirection( wxBOTH ); - fgSizer161->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + wxFlexGridSizer* fgSizer161; + fgSizer161 = new wxFlexGridSizer( 0, 2, 0, 0 ); + fgSizer161->AddGrowableCol( 1 ); + fgSizer161->SetFlexibleDirection( wxBOTH ); + fgSizer161->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticText123 = new wxStaticText( m_panelAuth, wxID_ANY, _("User name:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText123->Wrap( -1 ); - fgSizer161->Add( m_staticText123, 0, wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText123 = new wxStaticText( m_panelAuth, wxID_ANY, _("Username:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText123->Wrap( -1 ); + fgSizer161->Add( m_staticText123, 0, wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - m_textCtrlUserName = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer161->Add( m_textCtrlUserName, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + m_textCtrlUserName = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer161->Add( m_textCtrlUserName, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextKeyfile = new wxStaticText( m_panelAuth, wxID_ANY, _("Private key file:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextKeyfile->Wrap( -1 ); - fgSizer161->Add( m_staticTextKeyfile, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + m_staticTextKeyfile = new wxStaticText( m_panelAuth, wxID_ANY, _("Private key file:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextKeyfile->Wrap( -1 ); + fgSizer161->Add( m_staticTextKeyfile, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); - bSizerKeyFile = new wxBoxSizer( wxHORIZONTAL ); + bSizerKeyFile = new wxBoxSizer( wxHORIZONTAL ); - m_textCtrlKeyfilePath = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerKeyFile->Add( m_textCtrlKeyfilePath, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_textCtrlKeyfilePath = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerKeyFile->Add( m_textCtrlKeyfilePath, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectKeyfile = new wxButton( m_panelAuth, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectKeyfile->SetToolTip( _("Select a folder") ); + m_buttonSelectKeyfile = new wxButton( m_panelAuth, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectKeyfile->SetToolTip( _("Select a folder") ); - bSizerKeyFile->Add( m_buttonSelectKeyfile, 0, wxEXPAND, 5 ); + bSizerKeyFile->Add( m_buttonSelectKeyfile, 0, wxEXPAND, 5 ); - fgSizer161->Add( bSizerKeyFile, 0, wxALL|wxEXPAND, 5 ); + fgSizer161->Add( bSizerKeyFile, 0, wxALL|wxEXPAND, 5 ); - m_staticTextPassword = new wxStaticText( m_panelAuth, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextPassword->Wrap( -1 ); - fgSizer161->Add( m_staticTextPassword, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + m_staticTextPassword = new wxStaticText( m_panelAuth, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextPassword->Wrap( -1 ); + fgSizer161->Add( m_staticTextPassword, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - bSizerPassword = new wxBoxSizer( wxHORIZONTAL ); + bSizerPassword = new wxBoxSizer( wxHORIZONTAL ); - m_textCtrlPasswordVisible = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerPassword->Add( m_textCtrlPasswordVisible, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + m_textCtrlPasswordVisible = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerPassword->Add( m_textCtrlPasswordVisible, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - m_textCtrlPasswordHidden = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD ); - bSizerPassword->Add( m_textCtrlPasswordHidden, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + m_textCtrlPasswordHidden = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD ); + bSizerPassword->Add( m_textCtrlPasswordHidden, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - m_checkBoxShowPassword = new wxCheckBox( m_panelAuth, wxID_ANY, _("&Show password"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerPassword->Add( m_checkBoxShowPassword, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_checkBoxShowPassword = new wxCheckBox( m_panelAuth, wxID_ANY, _("&Show password"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerPassword->Add( m_checkBoxShowPassword, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_checkBoxPasswordPrompt = new wxCheckBox( m_panelAuth, wxID_ANY, _("Enter at login"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerPassword->Add( m_checkBoxPasswordPrompt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - fgSizer161->Add( bSizerPassword, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + fgSizer161->Add( bSizerPassword, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - bSizer221->Add( fgSizer161, 0, wxALL|wxEXPAND, 5 ); + bSizer221->Add( fgSizer161, 0, wxALL|wxEXPAND, 5 ); - m_panelAuth->SetSizer( bSizer221 ); - m_panelAuth->Layout(); - bSizer221->Fit( m_panelAuth ); - bSizerAuthInner->Add( m_panelAuth, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_panelAuth->SetSizer( bSizer221 ); + m_panelAuth->Layout(); + bSizer221->Fit( m_panelAuth ); + bSizerAuthInner->Add( m_panelAuth, 1, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerAuth->Add( bSizerAuthInner, 0, wxEXPAND, 5 ); - m_staticline581 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerAuth->Add( m_staticline581, 0, wxEXPAND, 5 ); + bSizerAuth->Add( bSizerAuthInner, 0, wxEXPAND, 5 ); + m_staticline581 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerAuth->Add( m_staticline581, 0, wxEXPAND, 5 ); - bSizer185->Add( bSizerAuth, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer269; - bSizer269 = new wxBoxSizer( wxVERTICAL ); + bSizer185->Add( bSizerAuth, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer3051; - bSizer3051 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer269; + bSizer269 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer270; - bSizer270 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer3051; + bSizer3051 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapServerDir = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer270->Add( m_bitmapServerDir, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + wxBoxSizer* bSizer270; + bSizer270 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText1232 = new wxStaticText( m_panel41, wxID_ANY, _("Directory on server:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1232->Wrap( -1 ); - bSizer270->Add( m_staticText1232, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapServerDir = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer270->Add( m_bitmapServerDir, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText1232 = new wxStaticText( m_panel41, wxID_ANY, _("Directory on server:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1232->Wrap( -1 ); + bSizer270->Add( m_staticText1232, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer3051->Add( bSizer270, 0, wxTOP|wxRIGHT|wxLEFT|wxALIGN_BOTTOM, 5 ); + bSizer3051->Add( bSizer270, 0, wxTOP|wxRIGHT|wxLEFT|wxALIGN_BOTTOM, 5 ); - bSizer3051->Add( 0, 0, 1, 0, 5 ); - wxBoxSizer* bSizer3031; - bSizer3031 = new wxBoxSizer( wxVERTICAL ); + bSizer3051->Add( 0, 0, 1, 0, 5 ); - wxBoxSizer* bSizer303; - bSizer303 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer3031; + bSizer3031 = new wxBoxSizer( wxVERTICAL ); - m_staticline83 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer303->Add( m_staticline83, 0, wxEXPAND, 5 ); + wxBoxSizer* bSizer303; + bSizer303 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer3042; - bSizer3042 = new wxBoxSizer( wxHORIZONTAL ); + m_staticline83 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer303->Add( m_staticline83, 0, wxEXPAND, 5 ); - m_staticTextTimeout = new wxStaticText( m_panel41, wxID_ANY, _("Access timeout (in seconds):"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeout->Wrap( -1 ); - bSizer3042->Add( m_staticTextTimeout, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + wxBoxSizer* bSizer3042; + bSizer3042 = new wxBoxSizer( wxHORIZONTAL ); - m_spinCtrlTimeout = new wxSpinCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); - bSizer3042->Add( m_spinCtrlTimeout, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextTimeout = new wxStaticText( m_panel41, wxID_ANY, _("Access timeout (in seconds):"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeout->Wrap( -1 ); + bSizer3042->Add( m_staticTextTimeout, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + m_spinCtrlTimeout = new wxSpinCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); + bSizer3042->Add( m_spinCtrlTimeout, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer303->Add( bSizer3042, 0, wxALL, 5 ); + bSizer303->Add( bSizer3042, 0, wxALL, 5 ); - bSizer3031->Add( bSizer303, 0, wxALIGN_RIGHT, 5 ); - m_staticline82 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer3031->Add( m_staticline82, 0, wxEXPAND, 5 ); + bSizer3031->Add( bSizer303, 0, wxALIGN_RIGHT, 5 ); + m_staticline82 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer3031->Add( m_staticline82, 0, wxEXPAND, 5 ); - bSizer3051->Add( bSizer3031, 0, wxBOTTOM, 10 ); + bSizer3051->Add( bSizer3031, 0, wxBOTTOM, 10 ); - bSizer269->Add( bSizer3051, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer217; - bSizer217 = new wxBoxSizer( wxHORIZONTAL ); + bSizer269->Add( bSizer3051, 0, wxEXPAND, 5 ); - m_textCtrlServerPath = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer217->Add( m_textCtrlServerPath, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + wxBoxSizer* bSizer217; + bSizer217 = new wxBoxSizer( wxHORIZONTAL ); - m_buttonSelectFolder = new wxButton( m_panel41, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectFolder->SetToolTip( _("Select a folder") ); + m_textCtrlServerPath = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer217->Add( m_textCtrlServerPath, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - bSizer217->Add( m_buttonSelectFolder, 0, wxRIGHT|wxEXPAND, 5 ); + m_buttonSelectFolder = new wxButton( m_panel41, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectFolder->SetToolTip( _("Select a folder") ); + bSizer217->Add( m_buttonSelectFolder, 0, wxRIGHT|wxEXPAND, 5 ); - bSizer269->Add( bSizer217, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 ); + bSizer269->Add( bSizer217, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 ); - bSizer269->Add( 0, 10, 0, 0, 5 ); + bSizer269->Add( 0, 10, 0, 0, 5 ); - bSizer185->Add( bSizer269, 0, wxEXPAND, 5 ); + bSizer185->Add( bSizer269, 0, wxEXPAND, 5 ); - m_panel41->SetSizer( bSizer185 ); - m_panel41->Layout(); - bSizer185->Fit( m_panel41 ); - bSizer134->Add( m_panel41, 1, wxEXPAND, 5 ); - m_staticline571 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline571, 0, wxEXPAND, 5 ); + m_panel41->SetSizer( bSizer185 ); + m_panel41->Layout(); + bSizer185->Fit( m_panel41 ); + bSizer134->Add( m_panel41, 1, wxEXPAND, 5 ); - wxBoxSizer* bSizer219; - bSizer219 = new wxBoxSizer( wxHORIZONTAL ); + m_staticline571 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer134->Add( m_staticline571, 0, wxEXPAND, 5 ); + wxBoxSizer* bSizer219; + bSizer219 = new wxBoxSizer( wxHORIZONTAL ); - bSizer219->Add( 5, 0, 0, 0, 5 ); - m_bitmapPerf = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer219->Add( m_bitmapPerf, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer219->Add( 5, 0, 0, 0, 5 ); - m_staticText1361 = new wxStaticText( this, wxID_ANY, _("Performance improvements:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1361->Wrap( -1 ); - bSizer219->Add( m_staticText1361, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); + m_bitmapPerf = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer219->Add( m_bitmapPerf, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_staticText1361 = new wxStaticText( this, wxID_ANY, _("Performance improvements:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1361->Wrap( -1 ); + bSizer219->Add( m_staticText1361, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); - bSizer219->Add( 0, 0, 1, wxEXPAND, 5 ); - m_hyperlink171 = new wxHyperlinkCtrl( this, wxID_ANY, _("How to get best performance?"), wxT("https://freefilesync.org/manual.php?topic=ftp-setup"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink171->SetToolTip( _("https://freefilesync.org/manual.php?topic=ftp-setup") ); + bSizer219->Add( 0, 0, 1, wxEXPAND, 5 ); - bSizer219->Add( m_hyperlink171, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); + m_hyperlink171 = new wxHyperlinkCtrl( this, wxID_ANY, _("How to get the best performance?"), wxT("https://freefilesync.org/manual.php?topic=ftp-setup"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink171->SetToolTip( _("https://freefilesync.org/manual.php?topic=ftp-setup") ); + bSizer219->Add( m_hyperlink171, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); - bSizer134->Add( bSizer219, 0, wxEXPAND, 5 ); - m_staticline57 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline57, 0, wxEXPAND, 5 ); + bSizer134->Add( bSizer219, 0, wxEXPAND, 5 ); - m_panel411 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel411->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_staticline57 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer134->Add( m_staticline57, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer1851; - bSizer1851 = new wxBoxSizer( wxVERTICAL ); + m_panel411 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel411->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxFlexGridSizer* fgSizer1611; - fgSizer1611 = new wxFlexGridSizer( 0, 2, 0, 0 ); - fgSizer1611->AddGrowableCol( 1 ); - fgSizer1611->SetFlexibleDirection( wxBOTH ); - fgSizer1611->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + wxBoxSizer* bSizer1851; + bSizer1851 = new wxBoxSizer( wxVERTICAL ); - bSizerConnectionsLabel = new wxBoxSizer( wxVERTICAL ); + wxFlexGridSizer* fgSizer1611; + fgSizer1611 = new wxFlexGridSizer( 0, 2, 0, 0 ); + fgSizer1611->AddGrowableCol( 1 ); + fgSizer1611->SetFlexibleDirection( wxBOTH ); + fgSizer1611->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticTextConnectionsLabel = new wxStaticText( m_panel411, wxID_ANY, _("Parallel file operations:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextConnectionsLabel->Wrap( -1 ); - bSizerConnectionsLabel->Add( m_staticTextConnectionsLabel, 0, 0, 5 ); + bSizerConnectionsLabel = new wxBoxSizer( wxVERTICAL ); - m_staticTextConnectionsLabelSub = new wxStaticText( m_panel411, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextConnectionsLabelSub->Wrap( -1 ); - bSizerConnectionsLabel->Add( m_staticTextConnectionsLabelSub, 0, wxALIGN_RIGHT, 5 ); + m_staticTextConnectionsLabel = new wxStaticText( m_panel411, wxID_ANY, _("Parallel file operations:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextConnectionsLabel->Wrap( -1 ); + bSizerConnectionsLabel->Add( m_staticTextConnectionsLabel, 0, 0, 5 ); + m_staticTextConnectionsLabelSub = new wxStaticText( m_panel411, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextConnectionsLabelSub->Wrap( -1 ); + bSizerConnectionsLabel->Add( m_staticTextConnectionsLabelSub, 0, wxALIGN_RIGHT, 5 ); - fgSizer1611->Add( bSizerConnectionsLabel, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* bSizer300; - bSizer300 = new wxBoxSizer( wxHORIZONTAL ); + fgSizer1611->Add( bSizerConnectionsLabel, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - m_spinCtrlConnectionCount = new wxSpinCtrl( m_panel411, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); - bSizer300->Add( m_spinCtrlConnectionCount, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + wxBoxSizer* bSizer300; + bSizer300 = new wxBoxSizer( wxHORIZONTAL ); - m_staticTextConnectionCountDescr = new wxStaticText( m_panel411, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextConnectionCountDescr->Wrap( -1 ); - m_staticTextConnectionCountDescr->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_spinCtrlConnectionCount = new wxSpinCtrl( m_panel411, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); + bSizer300->Add( m_spinCtrlConnectionCount, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer300->Add( m_staticTextConnectionCountDescr, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_staticTextConnectionCountDescr = new wxStaticText( m_panel411, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextConnectionCountDescr->Wrap( -1 ); + m_staticTextConnectionCountDescr->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - m_hyperlinkDeRequired = new wxHyperlinkCtrl( m_panel411, wxID_ANY, _("Requires FreeFileSync Donation Edition"), wxT("https://freefilesync.org/faq.php#donation-edition"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlinkDeRequired->SetToolTip( _("https://freefilesync.org/faq.php#donation-edition") ); + bSizer300->Add( m_staticTextConnectionCountDescr, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizer300->Add( m_hyperlinkDeRequired, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_hyperlinkDeRequired = new wxHyperlinkCtrl( m_panel411, wxID_ANY, _("Requires FreeFileSync Donation Edition"), wxT("https://freefilesync.org/faq.php#donation-edition"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlinkDeRequired->SetToolTip( _("https://freefilesync.org/faq.php#donation-edition") ); + bSizer300->Add( m_hyperlinkDeRequired, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - fgSizer1611->Add( bSizer300, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextChannelCountSftp = new wxStaticText( m_panel411, wxID_ANY, _("SFTP channels per connection:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextChannelCountSftp->Wrap( -1 ); - fgSizer1611->Add( m_staticTextChannelCountSftp, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); + fgSizer1611->Add( bSizer300, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* bSizer3001; - bSizer3001 = new wxBoxSizer( wxHORIZONTAL ); + m_staticTextChannelCountSftp = new wxStaticText( m_panel411, wxID_ANY, _("SFTP channels per connection:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextChannelCountSftp->Wrap( -1 ); + fgSizer1611->Add( m_staticTextChannelCountSftp, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); - m_spinCtrlChannelCountSftp = new wxSpinCtrl( m_panel411, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); - bSizer3001->Add( m_spinCtrlChannelCountSftp, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + wxBoxSizer* bSizer3001; + bSizer3001 = new wxBoxSizer( wxHORIZONTAL ); - m_buttonChannelCountSftp = new wxButton( m_panel411, wxID_ANY, _("Detect server limit"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer3001->Add( m_buttonChannelCountSftp, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_spinCtrlChannelCountSftp = new wxSpinCtrl( m_panel411, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); + bSizer3001->Add( m_spinCtrlChannelCountSftp, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_buttonChannelCountSftp = new wxButton( m_panel411, wxID_ANY, _("Detect server limit"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer3001->Add( m_buttonChannelCountSftp, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - fgSizer1611->Add( bSizer3001, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer1611->Add( bSizer3001, 0, wxALIGN_CENTER_VERTICAL, 5 ); - fgSizer1611->Add( 0, 0, 0, 0, 5 ); - wxBoxSizer* bSizer304; - bSizer304 = new wxBoxSizer( wxHORIZONTAL ); + fgSizer1611->Add( 0, 0, 0, 0, 5 ); - m_checkBoxAllowZlib = new wxCheckBox( m_panel411, wxID_ANY, _("Enable &compression"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer304->Add( m_checkBoxAllowZlib, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + wxBoxSizer* bSizer304; + bSizer304 = new wxBoxSizer( wxHORIZONTAL ); - m_staticTextZlibDescr = new wxStaticText( m_panel411, wxID_ANY, _("(zlib)"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextZlibDescr->Wrap( -1 ); - m_staticTextZlibDescr->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_checkBoxAllowZlib = new wxCheckBox( m_panel411, wxID_ANY, _("Enable &compression"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer304->Add( m_checkBoxAllowZlib, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizer304->Add( m_staticTextZlibDescr, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_staticTextZlibDescr = new wxStaticText( m_panel411, wxID_ANY, _("(zlib)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextZlibDescr->Wrap( -1 ); + m_staticTextZlibDescr->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + bSizer304->Add( m_staticTextZlibDescr, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - fgSizer1611->Add( bSizer304, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer1611->Add( bSizer304, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer1851->Add( fgSizer1611, 0, wxALL, 5 ); + bSizer1851->Add( fgSizer1611, 0, wxALL, 5 ); - m_panel411->SetSizer( bSizer1851 ); - m_panel411->Layout(); - bSizer1851->Fit( m_panel411 ); - bSizer134->Add( m_panel411, 0, wxEXPAND, 5 ); - m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline12, 0, wxEXPAND, 5 ); + m_panel411->SetSizer( bSizer1851 ); + m_panel411->Layout(); + bSizer1851->Fit( m_panel411 ); + bSizer134->Add( m_panel411, 0, wxEXPAND, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer134->Add( m_staticline12, 0, wxEXPAND, 5 ); - m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - bSizerStdButtons->Add( m_buttonOkay, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_buttonOkay->SetDefault(); + m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizerStdButtons->Add( m_buttonOkay, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer134->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + bSizer134->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - this->SetSizer( bSizer134 ); - this->Layout(); - bSizer134->Fit( this ); - this->Centre( wxBOTH ); + this->SetSizer( bSizer134 ); + this->Layout(); + bSizer134->Fit( this ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CloudSetupDlgGenerated::onClose ) ); - m_toggleBtnGdrive->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onConnectionGdrive ), NULL, this ); - m_toggleBtnSftp->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onConnectionSftp ), NULL, this ); - m_toggleBtnFtp->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onConnectionFtp ), NULL, this ); - m_listBoxGdriveUsers->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( CloudSetupDlgGenerated::onGdriveUserSelect ), NULL, this ); - m_buttonGdriveAddUser->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onGdriveUserAdd ), NULL, this ); - m_buttonGdriveRemoveUser->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onGdriveUserRemove ), NULL, this ); - m_radioBtnPassword->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CloudSetupDlgGenerated::onAuthPassword ), NULL, this ); - m_radioBtnKeyfile->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CloudSetupDlgGenerated::onAuthKeyfile ), NULL, this ); - m_radioBtnAgent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CloudSetupDlgGenerated::onAuthAgent ), NULL, this ); - m_buttonSelectKeyfile->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onSelectKeyfile ), NULL, this ); - m_checkBoxShowPassword->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onToggleShowPassword ), NULL, this ); - m_buttonSelectFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onBrowseCloudFolder ), NULL, this ); - m_buttonChannelCountSftp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onDetectServerChannelLimit ), NULL, this ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onCancel ), NULL, this ); + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CloudSetupDlgGenerated::onClose ) ); + m_toggleBtnGdrive->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onConnectionGdrive ), NULL, this ); + m_toggleBtnSftp->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onConnectionSftp ), NULL, this ); + m_toggleBtnFtp->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onConnectionFtp ), NULL, this ); + m_listBoxGdriveUsers->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( CloudSetupDlgGenerated::onGdriveUserSelect ), NULL, this ); + m_buttonGdriveAddUser->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onGdriveUserAdd ), NULL, this ); + m_buttonGdriveRemoveUser->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onGdriveUserRemove ), NULL, this ); + m_radioBtnPassword->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CloudSetupDlgGenerated::onAuthPassword ), NULL, this ); + m_radioBtnKeyfile->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CloudSetupDlgGenerated::onAuthKeyfile ), NULL, this ); + m_radioBtnAgent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CloudSetupDlgGenerated::onAuthAgent ), NULL, this ); + m_buttonSelectKeyfile->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onSelectKeyfile ), NULL, this ); + m_textCtrlPasswordVisible->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( CloudSetupDlgGenerated::onTypingPassword ), NULL, this ); + m_textCtrlPasswordHidden->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( CloudSetupDlgGenerated::onTypingPassword ), NULL, this ); + m_checkBoxShowPassword->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onToggleShowPassword ), NULL, this ); + m_checkBoxPasswordPrompt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onTogglePasswordPrompt ), NULL, this ); + m_buttonSelectFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onBrowseCloudFolder ), NULL, this ); + m_buttonChannelCountSftp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onDetectServerChannelLimit ), NULL, this ); + m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onOkay ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CloudSetupDlgGenerated::onCancel ), NULL, this ); } CloudSetupDlgGenerated::~CloudSetupDlgGenerated() @@ -3119,61 +3125,61 @@ CloudSetupDlgGenerated::~CloudSetupDlgGenerated() AbstractFolderPickerGenerated::AbstractFolderPickerGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer134; - bSizer134 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer134; + bSizer134 = new wxBoxSizer( wxVERTICAL ); - m_panel41 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel41->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel41 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel41->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer185; - bSizer185 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer185; + bSizer185 = new wxBoxSizer( wxVERTICAL ); - m_staticTextStatus = new wxStaticText( m_panel41, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatus->Wrap( -1 ); - bSizer185->Add( m_staticTextStatus, 0, wxALL, 5 ); + m_staticTextStatus = new wxStaticText( m_panel41, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatus->Wrap( -1 ); + bSizer185->Add( m_staticTextStatus, 0, wxALL, 5 ); - m_treeCtrlFileSystem = new wxTreeCtrl( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxTR_FULL_ROW_HIGHLIGHT|wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxTR_NO_LINES|wxBORDER_NONE ); - bSizer185->Add( m_treeCtrlFileSystem, 1, wxEXPAND, 5 ); + m_treeCtrlFileSystem = new wxTreeCtrl( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxTR_FULL_ROW_HIGHLIGHT|wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxTR_NO_LINES|wxBORDER_NONE ); + bSizer185->Add( m_treeCtrlFileSystem, 1, wxEXPAND, 5 ); - m_panel41->SetSizer( bSizer185 ); - m_panel41->Layout(); - bSizer185->Fit( m_panel41 ); - bSizer134->Add( m_panel41, 1, wxEXPAND, 5 ); + m_panel41->SetSizer( bSizer185 ); + m_panel41->Layout(); + bSizer185->Fit( m_panel41 ); + bSizer134->Add( m_panel41, 1, wxEXPAND, 5 ); - m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline12, 0, wxEXPAND, 5 ); + m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer134->Add( m_staticline12, 0, wxEXPAND, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_buttonOkay = new wxButton( this, wxID_OK, _("Select Folder"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonOkay = new wxButton( this, wxID_OK, _("Select Folder"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonOkay->SetDefault(); + m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizerStdButtons->Add( m_buttonOkay, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerStdButtons->Add( m_buttonOkay, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer134->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + bSizer134->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - this->SetSizer( bSizer134 ); - this->Layout(); - bSizer134->Fit( this ); + this->SetSizer( bSizer134 ); + this->Layout(); + bSizer134->Fit( this ); - this->Centre( wxBOTH ); + this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AbstractFolderPickerGenerated::onClose ) ); - m_treeCtrlFileSystem->Connect( wxEVT_COMMAND_TREE_ITEM_EXPANDING, wxTreeEventHandler( AbstractFolderPickerGenerated::onExpandNode ), NULL, this ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AbstractFolderPickerGenerated::onOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AbstractFolderPickerGenerated::onCancel ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AbstractFolderPickerGenerated::onClose ) ); + m_treeCtrlFileSystem->Connect( wxEVT_COMMAND_TREE_ITEM_EXPANDING, wxTreeEventHandler( AbstractFolderPickerGenerated::onExpandNode ), NULL, this ); + m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AbstractFolderPickerGenerated::onOkay ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AbstractFolderPickerGenerated::onCancel ), NULL, this ); } AbstractFolderPickerGenerated::~AbstractFolderPickerGenerated() @@ -3182,225 +3188,225 @@ AbstractFolderPickerGenerated::~AbstractFolderPickerGenerated() SyncConfirmationDlgGenerated::SyncConfirmationDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer134; - bSizer134 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer134; + bSizer134 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapSync = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer72->Add( m_bitmapSync, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); + m_bitmapSync = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer72->Add( m_bitmapSync, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - m_staticTextCaption = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCaption->Wrap( -1 ); - bSizer72->Add( m_staticTextCaption, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + m_staticTextCaption = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCaption->Wrap( -1 ); + bSizer72->Add( m_staticTextCaption, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - bSizer134->Add( bSizer72, 0, 0, 5 ); + bSizer134->Add( bSizer72, 0, 0, 5 ); - m_staticline371 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline371, 0, wxEXPAND, 5 ); + m_staticline371 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer134->Add( m_staticline371, 0, wxEXPAND, 5 ); - m_panelStatistics = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelStatistics->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelStatistics = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panelStatistics->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer185; - bSizer185 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer185; + bSizer185 = new wxBoxSizer( wxHORIZONTAL ); - bSizer185->Add( 40, 0, 0, 0, 5 ); + bSizer185->Add( 40, 0, 0, 0, 5 ); - bSizer185->Add( 0, 0, 1, 0, 5 ); + bSizer185->Add( 0, 0, 1, 0, 5 ); - m_staticline38 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer185->Add( m_staticline38, 0, wxEXPAND, 5 ); + m_staticline38 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer185->Add( m_staticline38, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer162; - bSizer162 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer162; + bSizer162 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer182; - bSizer182 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer182; + bSizer182 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText84 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Variant:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText84->Wrap( -1 ); - bSizer182->Add( m_staticText84, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + m_staticText84 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Variant:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText84->Wrap( -1 ); + bSizer182->Add( m_staticText84, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - bSizer182->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer182->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticTextSyncVar = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextSyncVar->Wrap( -1 ); - m_staticTextSyncVar->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextSyncVar = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextSyncVar->Wrap( -1 ); + m_staticTextSyncVar->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer182->Add( m_staticTextSyncVar, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer182->Add( m_staticTextSyncVar, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_bitmapSyncVar = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer182->Add( m_bitmapSyncVar, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_bitmapSyncVar = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer182->Add( m_bitmapSyncVar, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer182->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer182->Add( 0, 0, 1, wxEXPAND, 5 ); - bSizer162->Add( bSizer182, 0, wxALL|wxEXPAND, 5 ); + bSizer162->Add( bSizer182, 0, wxALL|wxEXPAND, 5 ); - m_staticline14 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer162->Add( m_staticline14, 0, wxEXPAND, 5 ); + m_staticline14 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer162->Add( m_staticline14, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer181; - bSizer181 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer181; + bSizer181 = new wxBoxSizer( wxVERTICAL ); - m_staticText83 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Statistics:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText83->Wrap( -1 ); - bSizer181->Add( m_staticText83, 0, wxALL, 5 ); + m_staticText83 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Statistics:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText83->Wrap( -1 ); + bSizer181->Add( m_staticText83, 0, wxALL, 5 ); - wxFlexGridSizer* fgSizer11; - fgSizer11 = new wxFlexGridSizer( 2, 7, 2, 5 ); - fgSizer11->SetFlexibleDirection( wxBOTH ); - fgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + wxFlexGridSizer* fgSizer11; + fgSizer11 = new wxFlexGridSizer( 2, 7, 2, 5 ); + fgSizer11->SetFlexibleDirection( wxBOTH ); + fgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_bitmapDeleteLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); + m_bitmapDeleteLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); - fgSizer11->Add( m_bitmapDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer11->Add( m_bitmapDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapUpdateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdateLeft->SetToolTip( _("Number of files that will be updated") ); + m_bitmapUpdateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapUpdateLeft->SetToolTip( _("Number of files that will be updated") ); - fgSizer11->Add( m_bitmapUpdateLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer11->Add( m_bitmapUpdateLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapCreateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); + m_bitmapCreateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); - fgSizer11->Add( m_bitmapCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + fgSizer11->Add( m_bitmapCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_bitmapData = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapData->SetToolTip( _("Total bytes to copy") ); + m_bitmapData = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapData->SetToolTip( _("Total bytes to copy") ); - fgSizer11->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + fgSizer11->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_bitmapCreateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreateRight->SetToolTip( _("Number of files and folders that will be created") ); + m_bitmapCreateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapCreateRight->SetToolTip( _("Number of files and folders that will be created") ); - fgSizer11->Add( m_bitmapCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + fgSizer11->Add( m_bitmapCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_bitmapUpdateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdateRight->SetToolTip( _("Number of files that will be updated") ); + m_bitmapUpdateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapUpdateRight->SetToolTip( _("Number of files that will be updated") ); - fgSizer11->Add( m_bitmapUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + fgSizer11->Add( m_bitmapUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_bitmapDeleteRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); + m_bitmapDeleteRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); - fgSizer11->Add( m_bitmapDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer11->Add( m_bitmapDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextDeleteLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDeleteLeft->Wrap( -1 ); - m_staticTextDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); + m_staticTextDeleteLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDeleteLeft->Wrap( -1 ); + m_staticTextDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); - fgSizer11->Add( m_staticTextDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer11->Add( m_staticTextDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextUpdateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextUpdateLeft->Wrap( -1 ); - m_staticTextUpdateLeft->SetToolTip( _("Number of files that will be updated") ); + m_staticTextUpdateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextUpdateLeft->Wrap( -1 ); + m_staticTextUpdateLeft->SetToolTip( _("Number of files that will be updated") ); - fgSizer11->Add( m_staticTextUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + fgSizer11->Add( m_staticTextUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_staticTextCreateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCreateLeft->Wrap( -1 ); - m_staticTextCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); + m_staticTextCreateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCreateLeft->Wrap( -1 ); + m_staticTextCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); - fgSizer11->Add( m_staticTextCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + fgSizer11->Add( m_staticTextCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_staticTextData = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextData->Wrap( -1 ); - m_staticTextData->SetToolTip( _("Total bytes to copy") ); + m_staticTextData = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextData->Wrap( -1 ); + m_staticTextData->SetToolTip( _("Total bytes to copy") ); - fgSizer11->Add( m_staticTextData, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer11->Add( m_staticTextData, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextCreateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCreateRight->Wrap( -1 ); - m_staticTextCreateRight->SetToolTip( _("Number of files and folders that will be created") ); + m_staticTextCreateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCreateRight->Wrap( -1 ); + m_staticTextCreateRight->SetToolTip( _("Number of files and folders that will be created") ); - fgSizer11->Add( m_staticTextCreateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer11->Add( m_staticTextCreateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextUpdateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextUpdateRight->Wrap( -1 ); - m_staticTextUpdateRight->SetToolTip( _("Number of files that will be updated") ); + m_staticTextUpdateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextUpdateRight->Wrap( -1 ); + m_staticTextUpdateRight->SetToolTip( _("Number of files that will be updated") ); - fgSizer11->Add( m_staticTextUpdateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer11->Add( m_staticTextUpdateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextDeleteRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDeleteRight->Wrap( -1 ); - m_staticTextDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); + m_staticTextDeleteRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDeleteRight->Wrap( -1 ); + m_staticTextDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); - fgSizer11->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer11->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer181->Add( fgSizer11, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + bSizer181->Add( fgSizer11, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - bSizer162->Add( bSizer181, 0, wxEXPAND|wxALL, 5 ); + bSizer162->Add( bSizer181, 0, wxEXPAND|wxALL, 5 ); - bSizer185->Add( bSizer162, 0, 0, 5 ); + bSizer185->Add( bSizer162, 0, 0, 5 ); - m_staticline381 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer185->Add( m_staticline381, 0, wxEXPAND, 5 ); + m_staticline381 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer185->Add( m_staticline381, 0, wxEXPAND, 5 ); - bSizer185->Add( 0, 0, 1, 0, 5 ); + bSizer185->Add( 0, 0, 1, 0, 5 ); - bSizer185->Add( 40, 0, 0, 0, 5 ); + bSizer185->Add( 40, 0, 0, 0, 5 ); - m_panelStatistics->SetSizer( bSizer185 ); - m_panelStatistics->Layout(); - bSizer185->Fit( m_panelStatistics ); - bSizer134->Add( m_panelStatistics, 0, wxEXPAND, 5 ); + m_panelStatistics->SetSizer( bSizer185 ); + m_panelStatistics->Layout(); + bSizer185->Fit( m_panelStatistics ); + bSizer134->Add( m_panelStatistics, 0, wxEXPAND, 5 ); - m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline12, 0, wxEXPAND, 5 ); + m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer134->Add( m_staticline12, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer164; - bSizer164 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer164; + bSizer164 = new wxBoxSizer( wxVERTICAL ); - m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("&Don't show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer164->Add( m_checkBoxDontShowAgain, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("&Don't show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer164->Add( m_checkBoxDontShowAgain, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_buttonStartSync = new wxButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonStartSync = new wxButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonStartSync->SetDefault(); - m_buttonStartSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonStartSync->SetDefault(); + m_buttonStartSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizerStdButtons->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizerStdButtons->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); - bSizer164->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + bSizer164->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - bSizer134->Add( bSizer164, 1, wxEXPAND, 5 ); + bSizer134->Add( bSizer164, 1, wxEXPAND, 5 ); - this->SetSizer( bSizer134 ); - this->Layout(); - bSizer134->Fit( this ); + this->SetSizer( bSizer134 ); + this->Layout(); + bSizer134->Fit( this ); - this->Centre( wxBOTH ); + this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncConfirmationDlgGenerated::onClose ) ); - m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::onStartSync ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::onCancel ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncConfirmationDlgGenerated::onClose ) ); + m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::onStartSync ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::onCancel ), NULL, this ); } SyncConfirmationDlgGenerated::~SyncConfirmationDlgGenerated() @@ -3409,198 +3415,198 @@ SyncConfirmationDlgGenerated::~SyncConfirmationDlgGenerated() CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name ) { - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer1811; - bSizer1811 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer1811; + bSizer1811 = new wxBoxSizer( wxVERTICAL ); - bSizer1811->Add( 0, 0, 1, 0, 5 ); + bSizer1811->Add( 0, 0, 1, 0, 5 ); - m_staticTextStatus = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatus->Wrap( -1 ); - bSizer1811->Add( m_staticTextStatus, 0, wxTOP|wxRIGHT|wxLEFT, 10 ); + m_staticTextStatus = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatus->Wrap( -1 ); + bSizer1811->Add( m_staticTextStatus, 0, wxTOP|wxRIGHT|wxLEFT, 10 ); - wxBoxSizer* bSizer199; - bSizer199 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer199; + bSizer199 = new wxBoxSizer( wxHORIZONTAL ); - bSizer199->Add( 10, 0, 0, 0, 5 ); + bSizer199->Add( 10, 0, 0, 0, 5 ); - ffgSizer11 = new wxFlexGridSizer( 2, 0, 5, 5 ); - ffgSizer11->SetFlexibleDirection( wxBOTH ); - ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer11 = new wxFlexGridSizer( 2, 0, 5, 5 ); + ffgSizer11->SetFlexibleDirection( wxBOTH ); + ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticTextProcessed = new wxStaticText( this, wxID_ANY, _("Processed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextProcessed->Wrap( -1 ); - ffgSizer11->Add( m_staticTextProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT, 5 ); + m_staticTextProcessed = new wxStaticText( this, wxID_ANY, _("Processed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextProcessed->Wrap( -1 ); + ffgSizer11->Add( m_staticTextProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT, 5 ); - m_staticTextRemaining = new wxStaticText( this, wxID_ANY, _("Remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextRemaining->Wrap( -1 ); - ffgSizer11->Add( m_staticTextRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_staticTextRemaining = new wxStaticText( this, wxID_ANY, _("Remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextRemaining->Wrap( -1 ); + ffgSizer11->Add( m_staticTextRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer199->Add( ffgSizer11, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 10 ); + bSizer199->Add( ffgSizer11, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 10 ); - m_panelItemStats = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelItemStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_panelItemStats = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panelItemStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer291; - bSizer291 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer291; + bSizer291 = new wxBoxSizer( wxHORIZONTAL ); - ffgSizer111 = new wxFlexGridSizer( 0, 2, 5, 5 ); - ffgSizer111->SetFlexibleDirection( wxBOTH ); - ffgSizer111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer111 = new wxFlexGridSizer( 0, 2, 5, 5 ); + ffgSizer111->SetFlexibleDirection( wxBOTH ); + ffgSizer111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - wxBoxSizer* bSizer293; - bSizer293 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer293; + bSizer293 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapItemStat = new wxStaticBitmap( m_panelItemStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer293->Add( m_bitmapItemStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapItemStat = new wxStaticBitmap( m_panelItemStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer293->Add( m_bitmapItemStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer293->Add( 0, 0, 1, 0, 5 ); + bSizer293->Add( 0, 0, 1, 0, 5 ); - m_staticTextItemsProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextItemsProcessed->Wrap( -1 ); - m_staticTextItemsProcessed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextItemsProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticTextItemsProcessed->Wrap( -1 ); + m_staticTextItemsProcessed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer293->Add( m_staticTextItemsProcessed, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer293->Add( m_staticTextItemsProcessed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - ffgSizer111->Add( bSizer293, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + ffgSizer111->Add( bSizer293, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticTextBytesProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextBytesProcessed->Wrap( -1 ); - ffgSizer111->Add( m_staticTextBytesProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + m_staticTextBytesProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextBytesProcessed->Wrap( -1 ); + ffgSizer111->Add( m_staticTextBytesProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); - m_staticTextItemsRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextItemsRemaining->Wrap( -1 ); - m_staticTextItemsRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextItemsRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticTextItemsRemaining->Wrap( -1 ); + m_staticTextItemsRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - ffgSizer111->Add( m_staticTextItemsRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer111->Add( m_staticTextItemsRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextBytesRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextBytesRemaining->Wrap( -1 ); - ffgSizer111->Add( m_staticTextBytesRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextBytesRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextBytesRemaining->Wrap( -1 ); + ffgSizer111->Add( m_staticTextBytesRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer291->Add( ffgSizer111, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer291->Add( ffgSizer111, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_panelItemStats->SetSizer( bSizer291 ); - m_panelItemStats->Layout(); - bSizer291->Fit( m_panelItemStats ); - bSizer199->Add( m_panelItemStats, 0, wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND, 10 ); + m_panelItemStats->SetSizer( bSizer291 ); + m_panelItemStats->Layout(); + bSizer291->Fit( m_panelItemStats ); + bSizer199->Add( m_panelItemStats, 0, wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND, 10 ); - m_panelTimeStats = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelTimeStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_panelTimeStats = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panelTimeStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer292; - bSizer292 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer292; + bSizer292 = new wxBoxSizer( wxHORIZONTAL ); - ffgSizer112 = new wxFlexGridSizer( 0, 1, 5, 5 ); - ffgSizer112->SetFlexibleDirection( wxBOTH ); - ffgSizer112->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer112 = new wxFlexGridSizer( 0, 1, 5, 5 ); + ffgSizer112->SetFlexibleDirection( wxBOTH ); + ffgSizer112->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - wxBoxSizer* bSizer294; - bSizer294 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer294; + bSizer294 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapTimeStat = new wxStaticBitmap( m_panelTimeStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer294->Add( m_bitmapTimeStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapTimeStat = new wxStaticBitmap( m_panelTimeStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer294->Add( m_bitmapTimeStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer294->Add( 0, 0, 1, 0, 5 ); + bSizer294->Add( 0, 0, 1, 0, 5 ); - m_staticTextTimeElapsed = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeElapsed->Wrap( -1 ); - m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextTimeElapsed = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeElapsed->Wrap( -1 ); + m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer294->Add( m_staticTextTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer294->Add( m_staticTextTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - ffgSizer112->Add( bSizer294, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + ffgSizer112->Add( bSizer294, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticTextTimeRemaining = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeRemaining->Wrap( -1 ); - m_staticTextTimeRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextTimeRemaining = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeRemaining->Wrap( -1 ); + m_staticTextTimeRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - ffgSizer112->Add( m_staticTextTimeRemaining, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + ffgSizer112->Add( m_staticTextTimeRemaining, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); - bSizer292->Add( ffgSizer112, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer292->Add( ffgSizer112, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_panelTimeStats->SetSizer( bSizer292 ); - m_panelTimeStats->Layout(); - bSizer292->Fit( m_panelTimeStats ); - bSizer199->Add( m_panelTimeStats, 0, wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND, 10 ); + m_panelTimeStats->SetSizer( bSizer292 ); + m_panelTimeStats->Layout(); + bSizer292->Fit( m_panelTimeStats ); + bSizer199->Add( m_panelTimeStats, 0, wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND, 10 ); - bSizerErrorsRetry = new wxBoxSizer( wxHORIZONTAL ); + bSizerErrorsRetry = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapRetryErrors = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerErrorsRetry->Add( m_bitmapRetryErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapRetryErrors = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerErrorsRetry->Add( m_bitmapRetryErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText1461 = new wxStaticText( this, wxID_ANY, _("Automatic retry"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1461->Wrap( -1 ); - bSizerErrorsRetry->Add( m_staticText1461, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + m_staticText1461 = new wxStaticText( this, wxID_ANY, _("Automatic retry"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1461->Wrap( -1 ); + bSizerErrorsRetry->Add( m_staticText1461, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - m_staticTextRetryCount = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextRetryCount->Wrap( -1 ); - bSizerErrorsRetry->Add( m_staticTextRetryCount, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextRetryCount = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextRetryCount->Wrap( -1 ); + bSizerErrorsRetry->Add( m_staticTextRetryCount, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer199->Add( bSizerErrorsRetry, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); + bSizer199->Add( bSizerErrorsRetry, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); - bSizerErrorsIgnore = new wxBoxSizer( wxHORIZONTAL ); + bSizerErrorsIgnore = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapIgnoreErrors = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerErrorsIgnore->Add( m_bitmapIgnoreErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapIgnoreErrors = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerErrorsIgnore->Add( m_bitmapIgnoreErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText146 = new wxStaticText( this, wxID_ANY, _("Ignore errors"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText146->Wrap( -1 ); - bSizerErrorsIgnore->Add( m_staticText146, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + m_staticText146 = new wxStaticText( this, wxID_ANY, _("Ignore errors"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText146->Wrap( -1 ); + bSizerErrorsIgnore->Add( m_staticText146, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - bSizer199->Add( bSizerErrorsIgnore, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); + bSizer199->Add( bSizerErrorsIgnore, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); - bSizerProgressGraph = new wxBoxSizer( wxHORIZONTAL ); + bSizerProgressGraph = new wxBoxSizer( wxHORIZONTAL ); - ffgSizer113 = new wxFlexGridSizer( 2, 0, 5, 5 ); - ffgSizer113->SetFlexibleDirection( wxBOTH ); - ffgSizer113->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer113 = new wxFlexGridSizer( 2, 0, 5, 5 ); + ffgSizer113->SetFlexibleDirection( wxBOTH ); + ffgSizer113->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - wxStaticText* m_staticText99; - m_staticText99 = new wxStaticText( this, wxID_ANY, _("Bytes:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText99->Wrap( -1 ); - ffgSizer113->Add( m_staticText99, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + wxStaticText* m_staticText99; + m_staticText99 = new wxStaticText( this, wxID_ANY, _("Bytes:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText99->Wrap( -1 ); + ffgSizer113->Add( m_staticText99, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - wxStaticText* m_staticText100; - m_staticText100 = new wxStaticText( this, wxID_ANY, _("Items:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText100->Wrap( -1 ); - ffgSizer113->Add( m_staticText100, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + wxStaticText* m_staticText100; + m_staticText100 = new wxStaticText( this, wxID_ANY, _("Items:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText100->Wrap( -1 ); + ffgSizer113->Add( m_staticText100, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerProgressGraph->Add( ffgSizer113, 0, wxALL, 5 ); + bSizerProgressGraph->Add( ffgSizer113, 0, wxALL, 5 ); - m_panelProgressGraph = new zen::Graph2D( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_panelProgressGraph->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_panelProgressGraph = new zen::Graph2D( this, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_panelProgressGraph->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - bSizerProgressGraph->Add( m_panelProgressGraph, 1, wxEXPAND, 5 ); + bSizerProgressGraph->Add( m_panelProgressGraph, 1, wxEXPAND, 5 ); - bSizer199->Add( bSizerProgressGraph, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); + bSizer199->Add( bSizerProgressGraph, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 10 ); - bSizer1811->Add( bSizer199, 0, wxEXPAND, 5 ); + bSizer1811->Add( bSizer199, 0, wxEXPAND, 5 ); - bSizer1811->Add( 0, 0, 1, 0, 5 ); + bSizer1811->Add( 0, 0, 1, 0, 5 ); - this->SetSizer( bSizer1811 ); - this->Layout(); - bSizer1811->Fit( this ); + this->SetSizer( bSizer1811 ); + this->Layout(); + bSizer1811->Fit( this ); } CompareProgressDlgGenerated::~CompareProgressDlgGenerated() @@ -3609,336 +3615,336 @@ CompareProgressDlgGenerated::~CompareProgressDlgGenerated() SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name ) { - bSizerRoot = new wxBoxSizer( wxVERTICAL ); + bSizerRoot = new wxBoxSizer( wxVERTICAL ); - m_panel53 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel53->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel53 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel53->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer301; - bSizer301 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer301; + bSizer301 = new wxBoxSizer( wxVERTICAL ); - bSizer42 = new wxBoxSizer( wxHORIZONTAL ); + bSizer42 = new wxBoxSizer( wxHORIZONTAL ); - bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); - m_bitmapStatus = new wxStaticBitmap( m_panel53, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer42->Add( m_bitmapStatus, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 ); + m_bitmapStatus = new wxStaticBitmap( m_panel53, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer42->Add( m_bitmapStatus, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 ); - m_staticTextPhase = new wxStaticText( m_panel53, wxID_ANY, _("Synchronizing..."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextPhase->Wrap( -1 ); - m_staticTextPhase->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextPhase = new wxStaticText( m_panel53, wxID_ANY, _("Synchronizing..."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextPhase->Wrap( -1 ); + m_staticTextPhase->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer42->Add( m_staticTextPhase, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer42->Add( m_staticTextPhase, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - wxBoxSizer* bSizer247; - bSizer247 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer247; + bSizer247 = new wxBoxSizer( wxHORIZONTAL ); - bSizer247->Add( 0, 0, 1, 0, 5 ); + bSizer247->Add( 0, 0, 1, 0, 5 ); - m_bpButtonMinimizeToTray = new wxBitmapButton( m_panel53, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonMinimizeToTray->SetToolTip( _("Minimize to notification area") ); + m_bpButtonMinimizeToTray = new wxBitmapButton( m_panel53, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonMinimizeToTray->SetToolTip( _("Minimize to notification area") ); - bSizer247->Add( m_bpButtonMinimizeToTray, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); + bSizer247->Add( m_bpButtonMinimizeToTray, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); - bSizer42->Add( bSizer247, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer42->Add( bSizer247, 1, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer301->Add( bSizer42, 0, wxEXPAND, 5 ); + bSizer301->Add( bSizer42, 0, wxEXPAND, 5 ); - bSizerStatusText = new wxBoxSizer( wxVERTICAL ); + bSizerStatusText = new wxBoxSizer( wxVERTICAL ); - m_staticTextStatus = new wxStaticText( m_panel53, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatus->Wrap( -1 ); - bSizerStatusText->Add( m_staticTextStatus, 0, wxEXPAND|wxLEFT, 15 ); + m_staticTextStatus = new wxStaticText( m_panel53, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatus->Wrap( -1 ); + bSizerStatusText->Add( m_staticTextStatus, 0, wxEXPAND|wxLEFT, 15 ); - bSizerStatusText->Add( 0, 10, 0, 0, 5 ); + bSizerStatusText->Add( 0, 10, 0, 0, 5 ); - bSizer301->Add( bSizerStatusText, 0, wxEXPAND, 5 ); + bSizer301->Add( bSizerStatusText, 0, wxEXPAND, 5 ); - m_panel53->SetSizer( bSizer301 ); - m_panel53->Layout(); - bSizer301->Fit( m_panel53 ); - bSizerRoot->Add( m_panel53, 0, wxEXPAND, 5 ); + m_panel53->SetSizer( bSizer301 ); + m_panel53->Layout(); + bSizer301->Fit( m_panel53 ); + bSizerRoot->Add( m_panel53, 0, wxEXPAND, 5 ); - m_panelProgress = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelProgress->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelProgress = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelProgress->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer173; - bSizer173 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer173; + bSizer173 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer161; - bSizer161 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer161; + bSizer161 = new wxBoxSizer( wxVERTICAL ); - m_panelGraphBytes = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_panelGraphBytes->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelGraphBytes = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_panelGraphBytes->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizer161->Add( m_panelGraphBytes, 1, wxEXPAND|wxLEFT, 10 ); + bSizer161->Add( m_panelGraphBytes, 1, wxEXPAND|wxLEFT, 10 ); - wxBoxSizer* bSizer232; - bSizer232 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer232; + bSizer232 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer233; - bSizer233 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer233; + bSizer233 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer175; - bSizer175 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer175; + bSizer175 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapGraphKeyBytes = new wxStaticBitmap( m_panelProgress, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer175->Add( m_bitmapGraphKeyBytes, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapGraphKeyBytes = new wxStaticBitmap( m_panelProgress, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer175->Add( m_bitmapGraphKeyBytes, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - wxStaticText* m_staticText99; - m_staticText99 = new wxStaticText( m_panelProgress, wxID_ANY, _("Bytes"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText99->Wrap( -1 ); - bSizer175->Add( m_staticText99, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxStaticText* m_staticText99; + m_staticText99 = new wxStaticText( m_panelProgress, wxID_ANY, _("Bytes"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText99->Wrap( -1 ); + bSizer175->Add( m_staticText99, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer233->Add( bSizer175, 0, wxALL, 5 ); + bSizer233->Add( bSizer175, 0, wxALL, 5 ); - bSizer233->Add( 0, 0, 1, 0, 5 ); + bSizer233->Add( 0, 0, 1, 0, 5 ); - wxBoxSizer* bSizer174; - bSizer174 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer174; + bSizer174 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapGraphKeyItems = new wxStaticBitmap( m_panelProgress, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer174->Add( m_bitmapGraphKeyItems, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapGraphKeyItems = new wxStaticBitmap( m_panelProgress, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer174->Add( m_bitmapGraphKeyItems, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - wxStaticText* m_staticText100; - m_staticText100 = new wxStaticText( m_panelProgress, wxID_ANY, _("Items"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText100->Wrap( -1 ); - bSizer174->Add( m_staticText100, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxStaticText* m_staticText100; + m_staticText100 = new wxStaticText( m_panelProgress, wxID_ANY, _("Items"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText100->Wrap( -1 ); + bSizer174->Add( m_staticText100, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer233->Add( bSizer174, 0, wxALL, 5 ); + bSizer233->Add( bSizer174, 0, wxALL, 5 ); - bSizer232->Add( bSizer233, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + bSizer232->Add( bSizer233, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - ffgSizer11 = new wxFlexGridSizer( 2, 0, 5, 5 ); - ffgSizer11->SetFlexibleDirection( wxBOTH ); - ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer11 = new wxFlexGridSizer( 2, 0, 5, 5 ); + ffgSizer11->SetFlexibleDirection( wxBOTH ); + ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticTextProcessed = new wxStaticText( m_panelProgress, wxID_ANY, _("Processed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextProcessed->Wrap( -1 ); - ffgSizer11->Add( m_staticTextProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT, 5 ); + m_staticTextProcessed = new wxStaticText( m_panelProgress, wxID_ANY, _("Processed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextProcessed->Wrap( -1 ); + ffgSizer11->Add( m_staticTextProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT, 5 ); - m_staticTextRemaining = new wxStaticText( m_panelProgress, wxID_ANY, _("Remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextRemaining->Wrap( -1 ); - ffgSizer11->Add( m_staticTextRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_staticTextRemaining = new wxStaticText( m_panelProgress, wxID_ANY, _("Remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextRemaining->Wrap( -1 ); + ffgSizer11->Add( m_staticTextRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer232->Add( ffgSizer11, 0, wxTOP|wxBOTTOM|wxALIGN_CENTER_VERTICAL, 10 ); + bSizer232->Add( ffgSizer11, 0, wxTOP|wxBOTTOM|wxALIGN_CENTER_VERTICAL, 10 ); - m_panelItemStats = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelItemStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_panelItemStats = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panelItemStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer291; - bSizer291 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer291; + bSizer291 = new wxBoxSizer( wxVERTICAL ); - ffgSizer111 = new wxFlexGridSizer( 2, 0, 5, 5 ); - ffgSizer111->SetFlexibleDirection( wxBOTH ); - ffgSizer111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer111 = new wxFlexGridSizer( 2, 0, 5, 5 ); + ffgSizer111->SetFlexibleDirection( wxBOTH ); + ffgSizer111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - wxBoxSizer* bSizer293; - bSizer293 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer293; + bSizer293 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapItemStat = new wxStaticBitmap( m_panelItemStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer293->Add( m_bitmapItemStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapItemStat = new wxStaticBitmap( m_panelItemStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer293->Add( m_bitmapItemStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer293->Add( 0, 0, 1, 0, 5 ); + bSizer293->Add( 0, 0, 1, 0, 5 ); - m_staticTextItemsProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextItemsProcessed->Wrap( -1 ); - m_staticTextItemsProcessed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextItemsProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticTextItemsProcessed->Wrap( -1 ); + m_staticTextItemsProcessed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer293->Add( m_staticTextItemsProcessed, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer293->Add( m_staticTextItemsProcessed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - ffgSizer111->Add( bSizer293, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + ffgSizer111->Add( bSizer293, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticTextBytesProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextBytesProcessed->Wrap( -1 ); - ffgSizer111->Add( m_staticTextBytesProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + m_staticTextBytesProcessed = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextBytesProcessed->Wrap( -1 ); + ffgSizer111->Add( m_staticTextBytesProcessed, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); - m_staticTextItemsRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextItemsRemaining->Wrap( -1 ); - m_staticTextItemsRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextItemsRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticTextItemsRemaining->Wrap( -1 ); + m_staticTextItemsRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - ffgSizer111->Add( m_staticTextItemsRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer111->Add( m_staticTextItemsRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextBytesRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextBytesRemaining->Wrap( -1 ); - ffgSizer111->Add( m_staticTextBytesRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextBytesRemaining = new wxStaticText( m_panelItemStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextBytesRemaining->Wrap( -1 ); + ffgSizer111->Add( m_staticTextBytesRemaining, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer291->Add( ffgSizer111, 0, wxALL, 5 ); + bSizer291->Add( ffgSizer111, 0, wxALL, 5 ); - m_panelItemStats->SetSizer( bSizer291 ); - m_panelItemStats->Layout(); - bSizer291->Fit( m_panelItemStats ); - bSizer232->Add( m_panelItemStats, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 10 ); + m_panelItemStats->SetSizer( bSizer291 ); + m_panelItemStats->Layout(); + bSizer291->Fit( m_panelItemStats ); + bSizer232->Add( m_panelItemStats, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 10 ); - m_panelTimeStats = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelTimeStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_panelTimeStats = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panelTimeStats->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer292; - bSizer292 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer292; + bSizer292 = new wxBoxSizer( wxVERTICAL ); - ffgSizer112 = new wxFlexGridSizer( 2, 0, 5, 5 ); - ffgSizer112->SetFlexibleDirection( wxBOTH ); - ffgSizer112->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer112 = new wxFlexGridSizer( 2, 0, 5, 5 ); + ffgSizer112->SetFlexibleDirection( wxBOTH ); + ffgSizer112->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - wxBoxSizer* bSizer294; - bSizer294 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer294; + bSizer294 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapTimeStat = new wxStaticBitmap( m_panelTimeStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer294->Add( m_bitmapTimeStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapTimeStat = new wxStaticBitmap( m_panelTimeStats, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer294->Add( m_bitmapTimeStat, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizer294->Add( 0, 0, 1, 0, 5 ); + bSizer294->Add( 0, 0, 1, 0, 5 ); - m_staticTextTimeElapsed = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeElapsed->Wrap( -1 ); - m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextTimeElapsed = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeElapsed->Wrap( -1 ); + m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer294->Add( m_staticTextTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer294->Add( m_staticTextTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - ffgSizer112->Add( bSizer294, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + ffgSizer112->Add( bSizer294, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticTextTimeRemaining = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeRemaining->Wrap( -1 ); - m_staticTextTimeRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticTextTimeRemaining = new wxStaticText( m_panelTimeStats, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeRemaining->Wrap( -1 ); + m_staticTextTimeRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - ffgSizer112->Add( m_staticTextTimeRemaining, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + ffgSizer112->Add( m_staticTextTimeRemaining, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); - bSizer292->Add( ffgSizer112, 0, wxALL, 5 ); + bSizer292->Add( ffgSizer112, 0, wxALL, 5 ); - m_panelTimeStats->SetSizer( bSizer292 ); - m_panelTimeStats->Layout(); - bSizer292->Fit( m_panelTimeStats ); - bSizer232->Add( m_panelTimeStats, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 10 ); + m_panelTimeStats->SetSizer( bSizer292 ); + m_panelTimeStats->Layout(); + bSizer292->Fit( m_panelTimeStats ); + bSizer232->Add( m_panelTimeStats, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 10 ); - bSizer232->Add( 0, 0, 1, 0, 5 ); + bSizer232->Add( 0, 0, 1, 0, 5 ); - bSizerDynSpace = new wxBoxSizer( wxVERTICAL ); + bSizerDynSpace = new wxBoxSizer( wxVERTICAL ); - bSizerDynSpace->Add( 0, 0, 0, 0, 5 ); + bSizerDynSpace->Add( 0, 0, 0, 0, 5 ); - bSizer232->Add( bSizerDynSpace, 0, 0, 5 ); + bSizer232->Add( bSizerDynSpace, 0, 0, 5 ); - bSizer161->Add( bSizer232, 0, wxEXPAND, 5 ); + bSizer161->Add( bSizer232, 0, wxEXPAND, 5 ); - m_panelGraphItems = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_panelGraphItems->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelGraphItems = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_panelGraphItems->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizer161->Add( m_panelGraphItems, 1, wxEXPAND|wxLEFT, 10 ); + bSizer161->Add( m_panelGraphItems, 1, wxEXPAND|wxLEFT, 10 ); - bSizerProgressFooter = new wxBoxSizer( wxHORIZONTAL ); + bSizerProgressFooter = new wxBoxSizer( wxHORIZONTAL ); - bSizerErrorsRetry = new wxBoxSizer( wxHORIZONTAL ); + bSizerErrorsRetry = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapRetryErrors = new wxStaticBitmap( m_panelProgress, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerErrorsRetry->Add( m_bitmapRetryErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapRetryErrors = new wxStaticBitmap( m_panelProgress, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerErrorsRetry->Add( m_bitmapRetryErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText1461 = new wxStaticText( m_panelProgress, wxID_ANY, _("Automatic retry"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1461->Wrap( -1 ); - bSizerErrorsRetry->Add( m_staticText1461, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + m_staticText1461 = new wxStaticText( m_panelProgress, wxID_ANY, _("Automatic retry"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1461->Wrap( -1 ); + bSizerErrorsRetry->Add( m_staticText1461, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - m_staticTextRetryCount = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextRetryCount->Wrap( -1 ); - bSizerErrorsRetry->Add( m_staticTextRetryCount, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_staticTextRetryCount = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextRetryCount->Wrap( -1 ); + bSizerErrorsRetry->Add( m_staticTextRetryCount, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizerProgressFooter->Add( bSizerErrorsRetry, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizerProgressFooter->Add( bSizerErrorsRetry, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizerErrorsIgnore = new wxBoxSizer( wxHORIZONTAL ); + bSizerErrorsIgnore = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapIgnoreErrors = new wxStaticBitmap( m_panelProgress, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerErrorsIgnore->Add( m_bitmapIgnoreErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapIgnoreErrors = new wxStaticBitmap( m_panelProgress, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerErrorsIgnore->Add( m_bitmapIgnoreErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText146 = new wxStaticText( m_panelProgress, wxID_ANY, _("Ignore errors"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText146->Wrap( -1 ); - bSizerErrorsIgnore->Add( m_staticText146, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + m_staticText146 = new wxStaticText( m_panelProgress, wxID_ANY, _("Ignore errors"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText146->Wrap( -1 ); + bSizerErrorsIgnore->Add( m_staticText146, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - bSizerProgressFooter->Add( bSizerErrorsIgnore, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizerProgressFooter->Add( bSizerErrorsIgnore, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizerProgressFooter->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizerProgressFooter->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticText137 = new wxStaticText( m_panelProgress, wxID_ANY, _("When finished:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText137->Wrap( -1 ); - bSizerProgressFooter->Add( m_staticText137, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_staticText137 = new wxStaticText( m_panelProgress, wxID_ANY, _("When finished:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText137->Wrap( -1 ); + bSizerProgressFooter->Add( m_staticText137, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - wxArrayString m_choicePostSyncActionChoices; - m_choicePostSyncAction = new wxChoice( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choicePostSyncActionChoices, 0 ); - m_choicePostSyncAction->SetSelection( 0 ); - bSizerProgressFooter->Add( m_choicePostSyncAction, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxArrayString m_choicePostSyncActionChoices; + m_choicePostSyncAction = new wxChoice( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choicePostSyncActionChoices, 0 ); + m_choicePostSyncAction->SetSelection( 0 ); + bSizerProgressFooter->Add( m_choicePostSyncAction, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer161->Add( bSizerProgressFooter, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); + bSizer161->Add( bSizerProgressFooter, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); - bSizer173->Add( bSizer161, 1, wxEXPAND|wxLEFT, 5 ); + bSizer173->Add( bSizer161, 1, wxEXPAND|wxLEFT, 5 ); - m_panelProgress->SetSizer( bSizer173 ); - m_panelProgress->Layout(); - bSizer173->Fit( m_panelProgress ); - bSizerRoot->Add( m_panelProgress, 1, wxEXPAND, 5 ); + m_panelProgress->SetSizer( bSizer173 ); + m_panelProgress->Layout(); + bSizer173->Fit( m_panelProgress ); + bSizerRoot->Add( m_panelProgress, 1, wxEXPAND, 5 ); - m_notebookResult = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_FIXEDWIDTH ); - m_notebookResult->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_notebookResult = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_FIXEDWIDTH ); + m_notebookResult->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizerRoot->Add( m_notebookResult, 1, wxEXPAND, 5 ); + bSizerRoot->Add( m_notebookResult, 1, wxEXPAND, 5 ); - m_staticlineFooter = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerRoot->Add( m_staticlineFooter, 0, wxEXPAND, 5 ); + m_staticlineFooter = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerRoot->Add( m_staticlineFooter, 0, wxEXPAND, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 ); - m_checkBoxAutoClose = new wxCheckBox( this, wxID_ANY, _("Auto-close"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStdButtons->Add( m_checkBoxAutoClose, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + m_checkBoxAutoClose = new wxCheckBox( this, wxID_ANY, _("Auto-close"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerStdButtons->Add( m_checkBoxAutoClose, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonClose->SetDefault(); - m_buttonClose->Enable( false ); + m_buttonClose->SetDefault(); + m_buttonClose->Enable( false ); - bSizerStdButtons->Add( m_buttonClose, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizerStdButtons->Add( m_buttonClose, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - m_buttonPause = new wxButton( this, wxID_ANY, _("&Pause"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonPause, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_buttonPause = new wxButton( this, wxID_ANY, _("&Pause"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonPause, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - m_buttonStop = new wxButton( this, wxID_CANCEL, _("Stop"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonStop, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_buttonStop = new wxButton( this, wxID_CANCEL, _("Stop"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonStop, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizerRoot->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); + bSizerRoot->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); - this->SetSizer( bSizerRoot ); - this->Layout(); - bSizerRoot->Fit( this ); + this->SetSizer( bSizerRoot ); + this->Layout(); + bSizerRoot->Fit( this ); } SyncProgressPanelGenerated::~SyncProgressPanelGenerated() @@ -3947,42 +3953,42 @@ SyncProgressPanelGenerated::~SyncProgressPanelGenerated() LogPanelGenerated::LogPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name ) { - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer153; - bSizer153 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer153; + bSizer153 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer154; - bSizer154 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer154; + bSizer154 = new wxBoxSizer( wxVERTICAL ); - m_bpButtonErrors = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizer154->Add( m_bpButtonErrors, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + m_bpButtonErrors = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizer154->Add( m_bpButtonErrors, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - m_bpButtonWarnings = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizer154->Add( m_bpButtonWarnings, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + m_bpButtonWarnings = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizer154->Add( m_bpButtonWarnings, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - m_bpButtonInfo = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizer154->Add( m_bpButtonInfo, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + m_bpButtonInfo = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizer154->Add( m_bpButtonInfo, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer153->Add( bSizer154, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + bSizer153->Add( bSizer154, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - m_staticline13 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer153->Add( m_staticline13, 0, wxEXPAND, 5 ); + m_staticline13 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer153->Add( m_staticline13, 0, wxEXPAND, 5 ); - m_gridMessages = new zen::Grid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridMessages->SetScrollRate( 5, 5 ); - bSizer153->Add( m_gridMessages, 1, wxEXPAND, 5 ); + m_gridMessages = new zen::Grid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_gridMessages->SetScrollRate( 5, 5 ); + bSizer153->Add( m_gridMessages, 1, wxEXPAND, 5 ); - this->SetSizer( bSizer153 ); - this->Layout(); - bSizer153->Fit( this ); + this->SetSizer( bSizer153 ); + this->Layout(); + bSizer153->Fit( this ); - // Connect Events - m_bpButtonErrors->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LogPanelGenerated::onErrors ), NULL, this ); - m_bpButtonWarnings->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LogPanelGenerated::onWarnings ), NULL, this ); - m_bpButtonInfo->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LogPanelGenerated::onInfo ), NULL, this ); + // Connect Events + m_bpButtonErrors->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LogPanelGenerated::onErrors ), NULL, this ); + m_bpButtonWarnings->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LogPanelGenerated::onWarnings ), NULL, this ); + m_bpButtonInfo->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LogPanelGenerated::onInfo ), NULL, this ); } LogPanelGenerated::~LogPanelGenerated() @@ -3991,173 +3997,173 @@ LogPanelGenerated::~LogPanelGenerated() BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer54; - bSizer54 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer54; + bSizer54 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapBatchJob = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer72->Add( m_bitmapBatchJob, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); + m_bitmapBatchJob = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer72->Add( m_bitmapBatchJob, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextHeader->Wrap( -1 ); - bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextHeader->Wrap( -1 ); + bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - bSizer54->Add( bSizer72, 0, 0, 5 ); + bSizer54->Add( bSizer72, 0, 0, 5 ); - m_staticline18 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer54->Add( m_staticline18, 0, wxEXPAND, 5 ); + m_staticline18 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer54->Add( m_staticline18, 0, wxEXPAND, 5 ); - m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer172; - bSizer172 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer172; + bSizer172 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer180; - bSizer180 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer180; + bSizer180 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer2361; - bSizer2361 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer2361; + bSizer2361 = new wxBoxSizer( wxVERTICAL ); - m_staticText146 = new wxStaticText( m_panel35, wxID_ANY, _("Progress dialog:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText146->Wrap( -1 ); - bSizer2361->Add( m_staticText146, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + m_staticText146 = new wxStaticText( m_panel35, wxID_ANY, _("Progress dialog:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText146->Wrap( -1 ); + bSizer2361->Add( m_staticText146, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - ffgSizer11 = new wxFlexGridSizer( 0, 2, 5, 5 ); - ffgSizer11->SetFlexibleDirection( wxBOTH ); - ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer11 = new wxFlexGridSizer( 0, 2, 5, 5 ); + ffgSizer11->SetFlexibleDirection( wxBOTH ); + ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_bitmapMinimizeToTray = new wxStaticBitmap( m_panel35, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - ffgSizer11->Add( m_bitmapMinimizeToTray, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapMinimizeToTray = new wxStaticBitmap( m_panel35, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + ffgSizer11->Add( m_bitmapMinimizeToTray, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_checkBoxRunMinimized = new wxCheckBox( m_panel35, wxID_ANY, _("Run minimized"), wxDefaultPosition, wxDefaultSize, 0 ); - ffgSizer11->Add( m_checkBoxRunMinimized, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + m_checkBoxRunMinimized = new wxCheckBox( m_panel35, wxID_ANY, _("Run minimized"), wxDefaultPosition, wxDefaultSize, 0 ); + ffgSizer11->Add( m_checkBoxRunMinimized, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - ffgSizer11->Add( 0, 0, 1, wxEXPAND, 5 ); + ffgSizer11->Add( 0, 0, 1, wxEXPAND, 5 ); - m_checkBoxAutoClose = new wxCheckBox( m_panel35, wxID_ANY, _("Auto-close"), wxDefaultPosition, wxDefaultSize, 0 ); - ffgSizer11->Add( m_checkBoxAutoClose, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + m_checkBoxAutoClose = new wxCheckBox( m_panel35, wxID_ANY, _("Auto-close"), wxDefaultPosition, wxDefaultSize, 0 ); + ffgSizer11->Add( m_checkBoxAutoClose, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - bSizer2361->Add( ffgSizer11, 0, wxEXPAND|wxALL, 5 ); + bSizer2361->Add( ffgSizer11, 0, wxEXPAND|wxALL, 5 ); - bSizer180->Add( bSizer2361, 0, wxALL, 5 ); + bSizer180->Add( bSizer2361, 0, wxALL, 5 ); - m_staticline26 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer180->Add( m_staticline26, 0, wxEXPAND, 5 ); + m_staticline26 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer180->Add( m_staticline26, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer242; - bSizer242 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer242; + bSizer242 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer243; - bSizer243 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer243; + bSizer243 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapIgnoreErrors = new wxStaticBitmap( m_panel35, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer243->Add( m_bitmapIgnoreErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapIgnoreErrors = new wxStaticBitmap( m_panel35, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer243->Add( m_bitmapIgnoreErrors, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_checkBoxIgnoreErrors = new wxCheckBox( m_panel35, wxID_ANY, _("Ignore errors"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer243->Add( m_checkBoxIgnoreErrors, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + m_checkBoxIgnoreErrors = new wxCheckBox( m_panel35, wxID_ANY, _("Ignore errors"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer243->Add( m_checkBoxIgnoreErrors, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - bSizer242->Add( bSizer243, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + bSizer242->Add( bSizer243, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - wxBoxSizer* bSizer246; - bSizer246 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer246; + bSizer246 = new wxBoxSizer( wxVERTICAL ); - m_radioBtnErrorDialogShow = new wxRadioButton( m_panel35, wxID_ANY, _("&Show error message"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); - m_radioBtnErrorDialogShow->SetValue( true ); - m_radioBtnErrorDialogShow->SetToolTip( _("Show pop-up on errors or warnings") ); + m_radioBtnErrorDialogShow = new wxRadioButton( m_panel35, wxID_ANY, _("&Show error message"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); + m_radioBtnErrorDialogShow->SetValue( true ); + m_radioBtnErrorDialogShow->SetToolTip( _("Show pop-up on errors or warnings") ); - bSizer246->Add( m_radioBtnErrorDialogShow, 0, wxALL|wxEXPAND, 5 ); + bSizer246->Add( m_radioBtnErrorDialogShow, 0, wxALL|wxEXPAND, 5 ); - m_radioBtnErrorDialogCancel = new wxRadioButton( m_panel35, wxID_ANY, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); - m_radioBtnErrorDialogCancel->SetToolTip( _("Stop synchronization at first error") ); + m_radioBtnErrorDialogCancel = new wxRadioButton( m_panel35, wxID_ANY, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnErrorDialogCancel->SetToolTip( _("Stop synchronization at first error") ); - bSizer246->Add( m_radioBtnErrorDialogCancel, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + bSizer246->Add( m_radioBtnErrorDialogCancel, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - bSizer242->Add( bSizer246, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT, 15 ); + bSizer242->Add( bSizer246, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT, 15 ); - bSizer180->Add( bSizer242, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer180->Add( bSizer242, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticline261 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer180->Add( m_staticline261, 0, wxEXPAND, 5 ); + m_staticline261 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer180->Add( m_staticline261, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer247; - bSizer247 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer247; + bSizer247 = new wxBoxSizer( wxVERTICAL ); - m_staticText137 = new wxStaticText( m_panel35, wxID_ANY, _("When finished:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText137->Wrap( -1 ); - bSizer247->Add( m_staticText137, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + m_staticText137 = new wxStaticText( m_panel35, wxID_ANY, _("When finished:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText137->Wrap( -1 ); + bSizer247->Add( m_staticText137, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - wxArrayString m_choicePostSyncActionChoices; - m_choicePostSyncAction = new wxChoice( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choicePostSyncActionChoices, 0 ); - m_choicePostSyncAction->SetSelection( 0 ); - bSizer247->Add( m_choicePostSyncAction, 0, wxALL, 5 ); + wxArrayString m_choicePostSyncActionChoices; + m_choicePostSyncAction = new wxChoice( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choicePostSyncActionChoices, 0 ); + m_choicePostSyncAction->SetSelection( 0 ); + bSizer247->Add( m_choicePostSyncAction, 0, wxALL, 5 ); - bSizer180->Add( bSizer247, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer180->Add( bSizer247, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticline262 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer180->Add( m_staticline262, 0, wxEXPAND, 5 ); + m_staticline262 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer180->Add( m_staticline262, 0, wxEXPAND, 5 ); - bSizer172->Add( bSizer180, 0, 0, 5 ); + bSizer172->Add( bSizer180, 0, 0, 5 ); - m_staticline25 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer172->Add( m_staticline25, 0, wxEXPAND, 5 ); + m_staticline25 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer172->Add( m_staticline25, 0, wxEXPAND, 5 ); - m_hyperlink17 = new wxHyperlinkCtrl( m_panel35, wxID_ANY, _("How can I schedule a batch job?"), wxT("https://freefilesync.org/manual.php?topic=schedule-a-batch-job"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink17->SetToolTip( _("https://freefilesync.org/manual.php?topic=schedule-a-batch-job") ); + m_hyperlink17 = new wxHyperlinkCtrl( m_panel35, wxID_ANY, _("How can I schedule a batch job?"), wxT("https://freefilesync.org/manual.php?topic=schedule-a-batch-job"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink17->SetToolTip( _("https://freefilesync.org/manual.php?topic=schedule-a-batch-job") ); - bSizer172->Add( m_hyperlink17, 0, wxALL, 10 ); + bSizer172->Add( m_hyperlink17, 0, wxALL, 10 ); - m_panel35->SetSizer( bSizer172 ); - m_panel35->Layout(); - bSizer172->Fit( m_panel35 ); - bSizer54->Add( m_panel35, 1, wxEXPAND, 5 ); + m_panel35->SetSizer( bSizer172 ); + m_panel35->Layout(); + bSizer172->Fit( m_panel35 ); + bSizer54->Add( m_panel35, 1, wxEXPAND, 5 ); - m_staticline13 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer54->Add( m_staticline13, 0, wxEXPAND, 5 ); + m_staticline13 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer54->Add( m_staticline13, 0, wxEXPAND, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_buttonSaveAs = new wxButton( this, wxID_SAVE, _("Save &as..."), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonSaveAs = new wxButton( this, wxID_SAVE, _("Save &as..."), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonSaveAs->SetDefault(); - m_buttonSaveAs->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonSaveAs->SetDefault(); + m_buttonSaveAs->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizerStdButtons->Add( m_buttonSaveAs, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizerStdButtons->Add( m_buttonSaveAs, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer54->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + bSizer54->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - this->SetSizer( bSizer54 ); - this->Layout(); - bSizer54->Fit( this ); + this->SetSizer( bSizer54 ); + this->Layout(); + bSizer54->Fit( this ); - this->Centre( wxBOTH ); + this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( BatchDlgGenerated::onClose ) ); - m_checkBoxRunMinimized->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::onToggleRunMinimized ), NULL, this ); - m_checkBoxIgnoreErrors->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::onToggleIgnoreErrors ), NULL, this ); - m_buttonSaveAs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::onSaveBatchJob ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::onCancel ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( BatchDlgGenerated::onClose ) ); + m_checkBoxRunMinimized->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::onToggleRunMinimized ), NULL, this ); + m_checkBoxIgnoreErrors->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::onToggleIgnoreErrors ), NULL, this ); + m_buttonSaveAs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::onSaveBatchJob ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::onCancel ), NULL, this ); } BatchDlgGenerated::~BatchDlgGenerated() @@ -4166,85 +4172,85 @@ BatchDlgGenerated::~BatchDlgGenerated() DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer24; - bSizer24 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapDeleteType = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer72->Add( m_bitmapDeleteType, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); + m_bitmapDeleteType = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer72->Add( m_bitmapDeleteType, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextHeader->Wrap( -1 ); - bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextHeader->Wrap( -1 ); + bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - bSizer24->Add( bSizer72, 0, 0, 5 ); + bSizer24->Add( bSizer72, 0, 0, 5 ); - m_staticline91 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer24->Add( m_staticline91, 0, wxEXPAND, 5 ); + m_staticline91 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer24->Add( m_staticline91, 0, wxEXPAND, 5 ); - m_panel31 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel31->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel31 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel31->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer185; - bSizer185 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer185; + bSizer185 = new wxBoxSizer( wxHORIZONTAL ); - bSizer185->Add( 60, 0, 0, 0, 5 ); + bSizer185->Add( 60, 0, 0, 0, 5 ); - m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 ); + m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 ); - m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE ); - bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 ); + m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE ); + bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 ); - m_panel31->SetSizer( bSizer185 ); - m_panel31->Layout(); - bSizer185->Fit( m_panel31 ); - bSizer24->Add( m_panel31, 1, wxEXPAND, 5 ); + m_panel31->SetSizer( bSizer185 ); + m_panel31->Layout(); + bSizer185->Fit( m_panel31 ); + bSizer24->Add( m_panel31, 1, wxEXPAND, 5 ); - m_staticline9 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer24->Add( m_staticline9, 0, wxEXPAND, 5 ); + m_staticline9 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer24->Add( m_staticline9, 0, wxEXPAND, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_checkBoxUseRecycler = new wxCheckBox( this, wxID_ANY, _("&Recycle bin"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStdButtons->Add( m_checkBoxUseRecycler, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_checkBoxUseRecycler = new wxCheckBox( this, wxID_ANY, _("&Recycle bin"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerStdButtons->Add( m_checkBoxUseRecycler, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 ); - m_buttonOK = new wxButton( this, wxID_OK, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonOK = new wxButton( this, wxID_OK, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonOK->SetDefault(); - m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonOK->SetDefault(); + m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizerStdButtons->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizerStdButtons->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer24->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); + bSizer24->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); - this->SetSizer( bSizer24 ); - this->Layout(); - bSizer24->Fit( this ); + this->SetSizer( bSizer24 ); + this->Layout(); + bSizer24->Fit( this ); - this->Centre( wxBOTH ); + this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DeleteDlgGenerated::onClose ) ); - m_checkBoxUseRecycler->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::onUseRecycler ), NULL, this ); - m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::onOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::onCancel ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DeleteDlgGenerated::onClose ) ); + m_checkBoxUseRecycler->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::onUseRecycler ), NULL, this ); + m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::onOkay ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::onCancel ), NULL, this ); } DeleteDlgGenerated::~DeleteDlgGenerated() @@ -4253,120 +4259,120 @@ DeleteDlgGenerated::~DeleteDlgGenerated() CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer24; - bSizer24 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapCopyTo = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer72->Add( m_bitmapCopyTo, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); + m_bitmapCopyTo = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer72->Add( m_bitmapCopyTo, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextHeader->Wrap( -1 ); - bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextHeader->Wrap( -1 ); + bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - bSizer24->Add( bSizer72, 0, 0, 5 ); + bSizer24->Add( bSizer72, 0, 0, 5 ); - m_staticline91 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer24->Add( m_staticline91, 0, wxEXPAND, 5 ); + m_staticline91 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer24->Add( m_staticline91, 0, wxEXPAND, 5 ); - m_panel31 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel31->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel31 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel31->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer242; - bSizer242 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer242; + bSizer242 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer185; - bSizer185 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer185; + bSizer185 = new wxBoxSizer( wxHORIZONTAL ); - bSizer185->Add( 60, 0, 0, 0, 5 ); + bSizer185->Add( 60, 0, 0, 0, 5 ); - m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 ); + m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 ); - m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE ); - bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 ); + m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE ); + bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 ); - bSizer242->Add( bSizer185, 1, wxEXPAND, 5 ); + bSizer242->Add( bSizer185, 1, wxEXPAND, 5 ); - wxBoxSizer* bSizer182; - bSizer182 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer182; + bSizer182 = new wxBoxSizer( wxHORIZONTAL ); - m_targetFolderPath = new fff::FolderHistoryBox( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer182->Add( m_targetFolderPath, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_targetFolderPath = new fff::FolderHistoryBox( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer182->Add( m_targetFolderPath, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectTargetFolder = new wxButton( m_panel31, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectTargetFolder->SetToolTip( _("Select a folder") ); + m_buttonSelectTargetFolder = new wxButton( m_panel31, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectTargetFolder->SetToolTip( _("Select a folder") ); - bSizer182->Add( m_buttonSelectTargetFolder, 0, wxEXPAND, 5 ); + bSizer182->Add( m_buttonSelectTargetFolder, 0, wxEXPAND, 5 ); - m_bpButtonSelectAltTargetFolder = new wxBitmapButton( m_panel31, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSelectAltTargetFolder->SetToolTip( _("Access online storage") ); + m_bpButtonSelectAltTargetFolder = new wxBitmapButton( m_panel31, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSelectAltTargetFolder->SetToolTip( _("Access online storage") ); - bSizer182->Add( m_bpButtonSelectAltTargetFolder, 0, wxEXPAND, 5 ); + bSizer182->Add( m_bpButtonSelectAltTargetFolder, 0, wxEXPAND, 5 ); - bSizer242->Add( bSizer182, 0, wxALL|wxEXPAND, 10 ); + bSizer242->Add( bSizer182, 0, wxALL|wxEXPAND, 10 ); - m_panel31->SetSizer( bSizer242 ); - m_panel31->Layout(); - bSizer242->Fit( m_panel31 ); - bSizer24->Add( m_panel31, 1, wxEXPAND, 5 ); + m_panel31->SetSizer( bSizer242 ); + m_panel31->Layout(); + bSizer242->Fit( m_panel31 ); + bSizer24->Add( m_panel31, 1, wxEXPAND, 5 ); - m_staticline9 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer24->Add( m_staticline9, 0, wxEXPAND, 5 ); + m_staticline9 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer24->Add( m_staticline9, 0, wxEXPAND, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer189; - bSizer189 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer189; + bSizer189 = new wxBoxSizer( wxVERTICAL ); - m_checkBoxKeepRelPath = new wxCheckBox( this, wxID_ANY, _("&Keep relative paths"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxKeepRelPath->SetValue(true); - bSizer189->Add( m_checkBoxKeepRelPath, 0, wxALL|wxEXPAND, 5 ); + m_checkBoxKeepRelPath = new wxCheckBox( this, wxID_ANY, _("&Keep relative paths"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxKeepRelPath->SetValue(true); + bSizer189->Add( m_checkBoxKeepRelPath, 0, wxALL|wxEXPAND, 5 ); - m_checkBoxOverwriteIfExists = new wxCheckBox( this, wxID_ANY, _("&Overwrite existing files"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxOverwriteIfExists->SetValue(true); - bSizer189->Add( m_checkBoxOverwriteIfExists, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + m_checkBoxOverwriteIfExists = new wxCheckBox( this, wxID_ANY, _("&Overwrite existing files"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxOverwriteIfExists->SetValue(true); + bSizer189->Add( m_checkBoxOverwriteIfExists, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - bSizerStdButtons->Add( bSizer189, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizerStdButtons->Add( bSizer189, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 ); - m_buttonOK = new wxButton( this, wxID_OK, _("Copy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonOK = new wxButton( this, wxID_OK, _("Copy"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonOK->SetDefault(); - m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonOK->SetDefault(); + m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizerStdButtons->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizerStdButtons->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer24->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); + bSizer24->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); - this->SetSizer( bSizer24 ); - this->Layout(); - bSizer24->Fit( this ); + this->SetSizer( bSizer24 ); + this->Layout(); + bSizer24->Fit( this ); - this->Centre( wxBOTH ); + this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CopyToDlgGenerated::onClose ) ); - m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CopyToDlgGenerated::onOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CopyToDlgGenerated::onCancel ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CopyToDlgGenerated::onClose ) ); + m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CopyToDlgGenerated::onOkay ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CopyToDlgGenerated::onCancel ), NULL, this ); } CopyToDlgGenerated::~CopyToDlgGenerated() @@ -4375,1301 +4381,1376 @@ CopyToDlgGenerated::~CopyToDlgGenerated() OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer95; - bSizer95 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer95; + bSizer95 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapSettings = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer72->Add( m_bitmapSettings, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); + m_bitmapSettings = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer72->Add( m_bitmapSettings, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - m_staticText44 = new wxStaticText( this, wxID_ANY, _("The following settings are used for all synchronization jobs."), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticText44->Wrap( -1 ); - bSizer72->Add( m_staticText44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + m_staticText44 = new wxStaticText( this, wxID_ANY, _("The following settings are used for all synchronization jobs."), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticText44->Wrap( -1 ); + bSizer72->Add( m_staticText44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - bSizer95->Add( bSizer72, 0, 0, 5 ); + bSizer95->Add( bSizer72, 0, 0, 5 ); - m_staticline20 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer95->Add( m_staticline20, 0, wxEXPAND, 5 ); + m_staticline20 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer95->Add( m_staticline20, 0, wxEXPAND, 5 ); - m_panel39 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel39->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel39 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel39->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer166; - bSizer166 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer166; + bSizer166 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer186; - bSizer186 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer186; + bSizer186 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer160; - bSizer160 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer160; + bSizer160 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer176; - bSizer176 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer176; + bSizer176 = new wxBoxSizer( wxHORIZONTAL ); - m_checkBoxFailSafe = new wxCheckBox( m_panel39, wxID_ANY, _("Fail-safe file copy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxFailSafe->SetValue(true); - m_checkBoxFailSafe->SetToolTip( _("Copy to a temporary file (*.ffs_tmp) before overwriting target.\nThis guarantees a consistent state even in case of a serious error.") ); + m_checkBoxFailSafe = new wxCheckBox( m_panel39, wxID_ANY, _("Fail-safe file copy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxFailSafe->SetValue(true); + m_checkBoxFailSafe->SetToolTip( _("Copy to a temporary file (*.ffs_tmp) before overwriting target.\nThis guarantees a consistent state even in case of a serious error.") ); - bSizer176->Add( m_checkBoxFailSafe, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer176->Add( m_checkBoxFailSafe, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText911 = new wxStaticText( m_panel39, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText911->Wrap( -1 ); - m_staticText911->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText911 = new wxStaticText( m_panel39, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText911->Wrap( -1 ); + m_staticText911->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer176->Add( m_staticText911, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); + bSizer176->Add( m_staticText911, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); - m_staticText91 = new wxStaticText( m_panel39, wxID_ANY, _("recommended"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText91->Wrap( -1 ); - m_staticText91->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText91 = new wxStaticText( m_panel39, wxID_ANY, _("recommended"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText91->Wrap( -1 ); + m_staticText91->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer176->Add( m_staticText91, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); + bSizer176->Add( m_staticText91, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); - m_staticText9111 = new wxStaticText( m_panel39, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText9111->Wrap( -1 ); - m_staticText9111->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText9111 = new wxStaticText( m_panel39, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText9111->Wrap( -1 ); + m_staticText9111->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer176->Add( m_staticText9111, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer176->Add( m_staticText9111, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer160->Add( bSizer176, 0, wxEXPAND, 5 ); + bSizer160->Add( bSizer176, 0, wxEXPAND, 5 ); - bSizerLockedFiles = new wxBoxSizer( wxHORIZONTAL ); + bSizerLockedFiles = new wxBoxSizer( wxHORIZONTAL ); - m_checkBoxCopyLocked = new wxCheckBox( m_panel39, wxID_ANY, _("Copy locked files"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxCopyLocked->SetValue(true); - m_checkBoxCopyLocked->SetToolTip( _("Copy shared or locked files using the Volume Shadow Copy Service.") ); + m_checkBoxCopyLocked = new wxCheckBox( m_panel39, wxID_ANY, _("Copy locked files"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxCopyLocked->SetValue(true); + m_checkBoxCopyLocked->SetToolTip( _("Copy shared or locked files using the Volume Shadow Copy Service.") ); - bSizerLockedFiles->Add( m_checkBoxCopyLocked, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerLockedFiles->Add( m_checkBoxCopyLocked, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText921 = new wxStaticText( m_panel39, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText921->Wrap( -1 ); - m_staticText921->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText921 = new wxStaticText( m_panel39, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText921->Wrap( -1 ); + m_staticText921->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizerLockedFiles->Add( m_staticText921, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); + bSizerLockedFiles->Add( m_staticText921, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); - m_staticText92 = new wxStaticText( m_panel39, wxID_ANY, _("requires administrator rights"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText92->Wrap( -1 ); - m_staticText92->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText92 = new wxStaticText( m_panel39, wxID_ANY, _("requires administrator rights"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText92->Wrap( -1 ); + m_staticText92->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizerLockedFiles->Add( m_staticText92, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); + bSizerLockedFiles->Add( m_staticText92, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); - m_staticText922 = new wxStaticText( m_panel39, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText922->Wrap( -1 ); - m_staticText922->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText922 = new wxStaticText( m_panel39, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText922->Wrap( -1 ); + m_staticText922->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizerLockedFiles->Add( m_staticText922, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerLockedFiles->Add( m_staticText922, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer160->Add( bSizerLockedFiles, 0, wxEXPAND, 5 ); + bSizer160->Add( bSizerLockedFiles, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer178; - bSizer178 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer178; + bSizer178 = new wxBoxSizer( wxHORIZONTAL ); - m_checkBoxCopyPermissions = new wxCheckBox( m_panel39, wxID_ANY, _("Copy file access permissions"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxCopyPermissions->SetValue(true); - m_checkBoxCopyPermissions->SetToolTip( _("Transfer file and folder permissions.") ); + m_checkBoxCopyPermissions = new wxCheckBox( m_panel39, wxID_ANY, _("Copy file access permissions"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxCopyPermissions->SetValue(true); + m_checkBoxCopyPermissions->SetToolTip( _("Transfer file and folder permissions.") ); - bSizer178->Add( m_checkBoxCopyPermissions, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer178->Add( m_checkBoxCopyPermissions, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_staticText931 = new wxStaticText( m_panel39, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText931->Wrap( -1 ); - m_staticText931->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText931 = new wxStaticText( m_panel39, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText931->Wrap( -1 ); + m_staticText931->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer178->Add( m_staticText931, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); + bSizer178->Add( m_staticText931, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); - m_staticText93 = new wxStaticText( m_panel39, wxID_ANY, _("requires administrator rights"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText93->Wrap( -1 ); - m_staticText93->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText93 = new wxStaticText( m_panel39, wxID_ANY, _("requires administrator rights"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText93->Wrap( -1 ); + m_staticText93->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer178->Add( m_staticText93, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); + bSizer178->Add( m_staticText93, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); - m_staticText932 = new wxStaticText( m_panel39, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText932->Wrap( -1 ); - m_staticText932->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText932 = new wxStaticText( m_panel39, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText932->Wrap( -1 ); + m_staticText932->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer178->Add( m_staticText932, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer178->Add( m_staticText932, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer160->Add( bSizer178, 0, wxEXPAND, 5 ); + bSizer160->Add( bSizer178, 0, wxEXPAND, 5 ); - bSizer186->Add( bSizer160, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer186->Add( bSizer160, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_staticline39 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer186->Add( m_staticline39, 0, wxEXPAND, 5 ); + m_staticline39 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer186->Add( m_staticline39, 0, wxEXPAND, 5 ); - bSizer166->Add( bSizer186, 0, wxEXPAND, 5 ); + bSizer166->Add( bSizer186, 0, wxEXPAND, 5 ); - m_staticline191 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer166->Add( m_staticline191, 0, wxEXPAND, 5 ); + m_staticline191 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer166->Add( m_staticline191, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer292; - bSizer292 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer292; + bSizer292 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapWarnings = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer292->Add( m_bitmapWarnings, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_bitmapWarnings = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer292->Add( m_bitmapWarnings, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_staticText182 = new wxStaticText( m_panel39, wxID_ANY, _("Show hidden dialogs and warning messages again:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText182->Wrap( -1 ); - bSizer292->Add( m_staticText182, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText182 = new wxStaticText( m_panel39, wxID_ANY, _("Show hidden dialogs and warning messages again:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText182->Wrap( -1 ); + bSizer292->Add( m_staticText182, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextHiddenDialogsCount = new wxStaticText( m_panel39, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextHiddenDialogsCount->Wrap( -1 ); - m_staticTextHiddenDialogsCount->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticTextHiddenDialogsCount = new wxStaticText( m_panel39, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextHiddenDialogsCount->Wrap( -1 ); + m_staticTextHiddenDialogsCount->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer292->Add( m_staticTextHiddenDialogsCount, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer292->Add( m_staticTextHiddenDialogsCount, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonShowHiddenDialogs = new wxButton( m_panel39, wxID_ANY, _("&Show details"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer292->Add( m_buttonShowHiddenDialogs, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + m_buttonShowHiddenDialogs = new wxButton( m_panel39, wxID_ANY, _("&Show details"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer292->Add( m_buttonShowHiddenDialogs, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - bSizer166->Add( bSizer292, 0, wxALL, 10 ); + bSizer166->Add( bSizer292, 0, wxALL, 10 ); - wxArrayString m_checkListHiddenDialogsChoices; - m_checkListHiddenDialogs = new wxCheckListBox( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_checkListHiddenDialogsChoices, wxLB_EXTENDED ); - bSizer166->Add( m_checkListHiddenDialogs, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); + wxArrayString m_checkListHiddenDialogsChoices; + m_checkListHiddenDialogs = new wxCheckListBox( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_checkListHiddenDialogsChoices, wxLB_EXTENDED ); + bSizer166->Add( m_checkListHiddenDialogs, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); - m_staticline1911 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer166->Add( m_staticline1911, 0, wxEXPAND, 5 ); + m_staticline1911 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer166->Add( m_staticline1911, 0, wxEXPAND, 5 ); - wxFlexGridSizer* fgSizer25111; - fgSizer25111 = new wxFlexGridSizer( 0, 2, 0, 0 ); - fgSizer25111->AddGrowableCol( 1 ); - fgSizer25111->AddGrowableRow( 0 ); - fgSizer25111->SetFlexibleDirection( wxBOTH ); - fgSizer25111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + wxFlexGridSizer* fgSizer25111; + fgSizer25111 = new wxFlexGridSizer( 0, 2, 0, 0 ); + fgSizer25111->AddGrowableCol( 1 ); + fgSizer25111->AddGrowableRow( 0 ); + fgSizer25111->SetFlexibleDirection( wxBOTH ); + fgSizer25111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_bitmapLogFile = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer25111->Add( m_bitmapLogFile, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapLogFile = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer25111->Add( m_bitmapLogFile, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* bSizer296; - bSizer296 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer296; + bSizer296 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText163 = new wxStaticText( m_panel39, wxID_ANY, _("Default log folder:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText163->Wrap( -1 ); - bSizer296->Add( m_staticText163, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText163 = new wxStaticText( m_panel39, wxID_ANY, _("Default log folder:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText163->Wrap( -1 ); + bSizer296->Add( m_staticText163, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonShowLogFolder = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonShowLogFolder->SetToolTip( _("dummy") ); + m_bpButtonShowLogFolder = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonShowLogFolder->SetToolTip( _("dummy") ); - bSizer296->Add( m_bpButtonShowLogFolder, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer296->Add( m_bpButtonShowLogFolder, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - fgSizer25111->Add( bSizer296, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + fgSizer25111->Add( bSizer296, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - fgSizer25111->Add( 0, 0, 0, 0, 5 ); + fgSizer25111->Add( 0, 0, 0, 0, 5 ); - m_panelLogfile = new wxPanel( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelLogfile->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panelLogfile = new wxPanel( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelLogfile->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer279; - bSizer279 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer279; + bSizer279 = new wxBoxSizer( wxHORIZONTAL ); - m_logFolderPath = new fff::FolderHistoryBox( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer279->Add( m_logFolderPath, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_logFolderPath = new fff::FolderHistoryBox( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer279->Add( m_logFolderPath, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectLogFolder = new wxButton( m_panelLogfile, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectLogFolder->SetToolTip( _("Select a folder") ); + m_buttonSelectLogFolder = new wxButton( m_panelLogfile, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectLogFolder->SetToolTip( _("Select a folder") ); - bSizer279->Add( m_buttonSelectLogFolder, 0, wxEXPAND, 5 ); + bSizer279->Add( m_buttonSelectLogFolder, 0, wxEXPAND, 5 ); - m_bpButtonSelectAltLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - m_bpButtonSelectAltLogFolder->SetToolTip( _("Access online storage") ); + m_bpButtonSelectAltLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + m_bpButtonSelectAltLogFolder->SetToolTip( _("Access online storage") ); - bSizer279->Add( m_bpButtonSelectAltLogFolder, 0, wxEXPAND, 5 ); + bSizer279->Add( m_bpButtonSelectAltLogFolder, 0, wxEXPAND, 5 ); - m_panelLogfile->SetSizer( bSizer279 ); - m_panelLogfile->Layout(); - bSizer279->Fit( m_panelLogfile ); - fgSizer25111->Add( m_panelLogfile, 0, wxEXPAND, 5 ); + m_panelLogfile->SetSizer( bSizer279 ); + m_panelLogfile->Layout(); + bSizer279->Fit( m_panelLogfile ); + fgSizer25111->Add( m_panelLogfile, 0, wxEXPAND, 5 ); - fgSizer25111->Add( 0, 0, 0, 0, 5 ); + fgSizer25111->Add( 0, 0, 0, 0, 5 ); - wxBoxSizer* bSizer297; - bSizer297 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer297; + bSizer297 = new wxBoxSizer( wxHORIZONTAL ); - m_checkBoxLogFilesMaxAge = new wxCheckBox( m_panel39, wxID_ANY, _("&Delete logs after x days:"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer297->Add( m_checkBoxLogFilesMaxAge, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_checkBoxLogFilesMaxAge = new wxCheckBox( m_panel39, wxID_ANY, _("&Delete logs after x days:"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer297->Add( m_checkBoxLogFilesMaxAge, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_spinCtrlLogFilesMaxAge = new wxSpinCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); - bSizer297->Add( m_spinCtrlLogFilesMaxAge, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + m_spinCtrlLogFilesMaxAge = new wxSpinCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); + bSizer297->Add( m_spinCtrlLogFilesMaxAge, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - m_staticline81 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer297->Add( m_staticline81, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + m_staticline81 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer297->Add( m_staticline81, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - m_staticText184 = new wxStaticText( m_panel39, wxID_ANY, _("Log file format:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText184->Wrap( -1 ); - bSizer297->Add( m_staticText184, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + m_staticText184 = new wxStaticText( m_panel39, wxID_ANY, _("Log file format:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText184->Wrap( -1 ); + bSizer297->Add( m_staticText184, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - wxFlexGridSizer* fgSizer251; - fgSizer251 = new wxFlexGridSizer( 0, 1, 5, 0 ); - fgSizer251->SetFlexibleDirection( wxBOTH ); - fgSizer251->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + wxFlexGridSizer* fgSizer251; + fgSizer251 = new wxFlexGridSizer( 0, 1, 5, 0 ); + fgSizer251->SetFlexibleDirection( wxBOTH ); + fgSizer251->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_radioBtnLogHtml = new wxRadioButton( m_panel39, wxID_ANY, _("&HTML"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); - m_radioBtnLogHtml->SetValue( true ); - fgSizer251->Add( m_radioBtnLogHtml, 0, wxEXPAND, 5 ); + m_radioBtnLogHtml = new wxRadioButton( m_panel39, wxID_ANY, _("&HTML"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); + m_radioBtnLogHtml->SetValue( true ); + fgSizer251->Add( m_radioBtnLogHtml, 0, wxEXPAND, 5 ); - m_radioBtnLogText = new wxRadioButton( m_panel39, wxID_ANY, _("&Plain text"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer251->Add( m_radioBtnLogText, 0, wxEXPAND, 5 ); + m_radioBtnLogText = new wxRadioButton( m_panel39, wxID_ANY, _("&Plain text"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer251->Add( m_radioBtnLogText, 0, wxEXPAND, 5 ); - bSizer297->Add( fgSizer251, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer297->Add( fgSizer251, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - fgSizer25111->Add( bSizer297, 0, wxTOP, 5 ); + fgSizer25111->Add( bSizer297, 0, wxTOP, 5 ); - bSizer166->Add( fgSizer25111, 0, wxALL|wxEXPAND, 10 ); + bSizer166->Add( fgSizer25111, 0, wxALL|wxEXPAND, 10 ); - m_staticline361 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer166->Add( m_staticline361, 0, wxEXPAND, 5 ); + m_staticline361 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer166->Add( m_staticline361, 0, wxEXPAND, 5 ); - wxFlexGridSizer* fgSizer251111; - fgSizer251111 = new wxFlexGridSizer( 0, 2, 0, 0 ); - fgSizer251111->AddGrowableCol( 1 ); - fgSizer251111->AddGrowableRow( 0 ); - fgSizer251111->SetFlexibleDirection( wxBOTH ); - fgSizer251111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + wxFlexGridSizer* fgSizer251111; + fgSizer251111 = new wxFlexGridSizer( 0, 2, 0, 0 ); + fgSizer251111->AddGrowableCol( 1 ); + fgSizer251111->AddGrowableRow( 0 ); + fgSizer251111->SetFlexibleDirection( wxBOTH ); + fgSizer251111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_bitmapNotificationSounds = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer251111->Add( m_bitmapNotificationSounds, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapNotificationSounds = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer251111->Add( m_bitmapNotificationSounds, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText851 = new wxStaticText( m_panel39, wxID_ANY, _("Notification sounds:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText851->Wrap( -1 ); - fgSizer251111->Add( m_staticText851, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText851 = new wxStaticText( m_panel39, wxID_ANY, _("Notification sounds:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText851->Wrap( -1 ); + fgSizer251111->Add( m_staticText851, 0, wxALIGN_CENTER_VERTICAL, 5 ); - fgSizer251111->Add( 0, 0, 0, 0, 5 ); + fgSizer251111->Add( 0, 0, 0, 0, 5 ); - ffgSizer11 = new wxFlexGridSizer( 0, 3, 0, 10 ); - ffgSizer11->AddGrowableCol( 2 ); - ffgSizer11->SetFlexibleDirection( wxBOTH ); - ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer11 = new wxFlexGridSizer( 0, 3, 0, 10 ); + ffgSizer11->AddGrowableCol( 2 ); + ffgSizer11->SetFlexibleDirection( wxBOTH ); + ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticText171 = new wxStaticText( m_panel39, wxID_ANY, _("Comparison finished:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText171->Wrap( -1 ); - m_staticText171->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText171 = new wxStaticText( m_panel39, wxID_ANY, _("Comparison finished:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText171->Wrap( -1 ); + m_staticText171->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - ffgSizer11->Add( m_staticText171, 0, wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer11->Add( m_staticText171, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapCompareDone = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - ffgSizer11->Add( m_bitmapCompareDone, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapCompareDone = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + ffgSizer11->Add( m_bitmapCompareDone, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* bSizer290; - bSizer290 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer290; + bSizer290 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonPlayCompareDone = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizer290->Add( m_bpButtonPlayCompareDone, 0, wxEXPAND, 5 ); + m_bpButtonPlayCompareDone = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer290->Add( m_bpButtonPlayCompareDone, 0, wxEXPAND, 5 ); - m_textCtrlSoundPathCompareDone = new wxTextCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer290->Add( m_textCtrlSoundPathCompareDone, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_textCtrlSoundPathCompareDone = new wxTextCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer290->Add( m_textCtrlSoundPathCompareDone, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectSoundCompareDone = new wxButton( m_panel39, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectSoundCompareDone->SetToolTip( _("Select a folder") ); + m_buttonSelectSoundCompareDone = new wxButton( m_panel39, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectSoundCompareDone->SetToolTip( _("Select a folder") ); - bSizer290->Add( m_buttonSelectSoundCompareDone, 0, wxEXPAND, 5 ); + bSizer290->Add( m_buttonSelectSoundCompareDone, 0, wxEXPAND, 5 ); - ffgSizer11->Add( bSizer290, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + ffgSizer11->Add( bSizer290, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticText1711 = new wxStaticText( m_panel39, wxID_ANY, _("Synchronization finished:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1711->Wrap( -1 ); - m_staticText1711->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText1711 = new wxStaticText( m_panel39, wxID_ANY, _("Synchronization finished:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1711->Wrap( -1 ); + m_staticText1711->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - ffgSizer11->Add( m_staticText1711, 0, wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer11->Add( m_staticText1711, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapSyncDone = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - ffgSizer11->Add( m_bitmapSyncDone, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapSyncDone = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + ffgSizer11->Add( m_bitmapSyncDone, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* bSizer2901; - bSizer2901 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer2901; + bSizer2901 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonPlaySyncDone = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizer2901->Add( m_bpButtonPlaySyncDone, 0, wxEXPAND, 5 ); + m_bpButtonPlaySyncDone = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer2901->Add( m_bpButtonPlaySyncDone, 0, wxEXPAND, 5 ); - m_textCtrlSoundPathSyncDone = new wxTextCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer2901->Add( m_textCtrlSoundPathSyncDone, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_textCtrlSoundPathSyncDone = new wxTextCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2901->Add( m_textCtrlSoundPathSyncDone, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectSoundSyncDone = new wxButton( m_panel39, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectSoundSyncDone->SetToolTip( _("Select a folder") ); + m_buttonSelectSoundSyncDone = new wxButton( m_panel39, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectSoundSyncDone->SetToolTip( _("Select a folder") ); - bSizer2901->Add( m_buttonSelectSoundSyncDone, 0, wxEXPAND, 5 ); + bSizer2901->Add( m_buttonSelectSoundSyncDone, 0, wxEXPAND, 5 ); - ffgSizer11->Add( bSizer2901, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + ffgSizer11->Add( bSizer2901, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticText17111 = new wxStaticText( m_panel39, wxID_ANY, _("Unattended error message:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText17111->Wrap( -1 ); - m_staticText17111->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText17111 = new wxStaticText( m_panel39, wxID_ANY, _("Unattended error message:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText17111->Wrap( -1 ); + m_staticText17111->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - ffgSizer11->Add( m_staticText17111, 0, wxALIGN_CENTER_VERTICAL, 5 ); + ffgSizer11->Add( m_staticText17111, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_bitmapAlertPending = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - ffgSizer11->Add( m_bitmapAlertPending, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapAlertPending = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + ffgSizer11->Add( m_bitmapAlertPending, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* bSizer29011; - bSizer29011 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer29011; + bSizer29011 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonPlayAlertPending = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizer29011->Add( m_bpButtonPlayAlertPending, 0, wxEXPAND, 5 ); + m_bpButtonPlayAlertPending = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer29011->Add( m_bpButtonPlayAlertPending, 0, wxEXPAND, 5 ); - m_textCtrlSoundPathAlertPending = new wxTextCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer29011->Add( m_textCtrlSoundPathAlertPending, 1, wxALIGN_CENTER_VERTICAL, 5 ); + m_textCtrlSoundPathAlertPending = new wxTextCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer29011->Add( m_textCtrlSoundPathAlertPending, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonSelectSoundAlertPending = new wxButton( m_panel39, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectSoundAlertPending->SetToolTip( _("Select a folder") ); + m_buttonSelectSoundAlertPending = new wxButton( m_panel39, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectSoundAlertPending->SetToolTip( _("Select a folder") ); - bSizer29011->Add( m_buttonSelectSoundAlertPending, 0, wxEXPAND, 5 ); + bSizer29011->Add( m_buttonSelectSoundAlertPending, 0, wxEXPAND, 5 ); - ffgSizer11->Add( bSizer29011, 1, wxEXPAND, 5 ); + ffgSizer11->Add( bSizer29011, 1, wxEXPAND, 5 ); - fgSizer251111->Add( ffgSizer11, 0, wxEXPAND|wxTOP, 5 ); + fgSizer251111->Add( ffgSizer11, 0, wxEXPAND|wxTOP, 5 ); - bSizer166->Add( fgSizer251111, 0, wxALL|wxEXPAND, 10 ); + bSizer166->Add( fgSizer251111, 0, wxALL|wxEXPAND, 10 ); - m_staticline3611 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer166->Add( m_staticline3611, 0, wxEXPAND, 5 ); + m_staticline3611 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer166->Add( m_staticline3611, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer2971; - bSizer2971 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer2971; + bSizer2971 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapConsole = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer2971->Add( m_bitmapConsole, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapConsole = new wxStaticBitmap( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2971->Add( m_bitmapConsole, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText85 = new wxStaticText( m_panel39, wxID_ANY, _("Customize context menu:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText85->Wrap( -1 ); - bSizer2971->Add( m_staticText85, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + m_staticText85 = new wxStaticText( m_panel39, wxID_ANY, _("Customize context menu:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText85->Wrap( -1 ); + bSizer2971->Add( m_staticText85, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - m_buttonShowCtxCustomize = new wxButton( m_panel39, wxID_ANY, _("&Show details"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer2971->Add( m_buttonShowCtxCustomize, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + m_buttonShowCtxCustomize = new wxButton( m_panel39, wxID_ANY, _("&Show details"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer2971->Add( m_buttonShowCtxCustomize, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - bSizer166->Add( bSizer2971, 0, wxALL, 10 ); + bSizer166->Add( bSizer2971, 0, wxALL, 10 ); - bSizerContextCustomize = new wxBoxSizer( wxVERTICAL ); + bSizerContextCustomize = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer181; - bSizer181 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer181; + bSizer181 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer2991; - bSizer2991 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer2991; + bSizer2991 = new wxBoxSizer( wxVERTICAL ); - bSizer2991->Add( 0, 0, 1, 0, 5 ); + bSizer2991->Add( 0, 0, 1, 0, 5 ); - wxBoxSizer* bSizer193; - bSizer193 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer193; + bSizer193 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonAddRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizer193->Add( m_bpButtonAddRow, 0, wxALIGN_BOTTOM, 5 ); + m_bpButtonAddRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizer193->Add( m_bpButtonAddRow, 0, wxALIGN_BOTTOM, 5 ); - m_bpButtonRemoveRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - bSizer193->Add( m_bpButtonRemoveRow, 0, wxALIGN_BOTTOM, 5 ); + m_bpButtonRemoveRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 ); + bSizer193->Add( m_bpButtonRemoveRow, 0, wxALIGN_BOTTOM, 5 ); - bSizer2991->Add( bSizer193, 0, 0, 5 ); + bSizer2991->Add( bSizer193, 0, 0, 5 ); - bSizer181->Add( bSizer2991, 1, wxEXPAND, 5 ); + bSizer181->Add( bSizer2991, 1, wxEXPAND, 5 ); - wxFlexGridSizer* fgSizer37; - fgSizer37 = new wxFlexGridSizer( 0, 2, 0, 10 ); - fgSizer37->SetFlexibleDirection( wxBOTH ); - fgSizer37->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + wxFlexGridSizer* fgSizer37; + fgSizer37 = new wxFlexGridSizer( 0, 2, 0, 10 ); + fgSizer37->SetFlexibleDirection( wxBOTH ); + fgSizer37->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticText174 = new wxStaticText( m_panel39, wxID_ANY, _("%item_path%"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText174->Wrap( -1 ); - m_staticText174->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); - m_staticText174->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText174 = new wxStaticText( m_panel39, wxID_ANY, _("%item_path%"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText174->Wrap( -1 ); + m_staticText174->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); + m_staticText174->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - fgSizer37->Add( m_staticText174, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer37->Add( m_staticText174, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText175 = new wxStaticText( m_panel39, wxID_ANY, _("Full file or folder path"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText175->Wrap( -1 ); - m_staticText175->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText175 = new wxStaticText( m_panel39, wxID_ANY, _("Full file or folder path"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText175->Wrap( -1 ); + m_staticText175->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - fgSizer37->Add( m_staticText175, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer37->Add( m_staticText175, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText178 = new wxStaticText( m_panel39, wxID_ANY, _("%local_path%"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText178->Wrap( -1 ); - m_staticText178->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); - m_staticText178->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText178 = new wxStaticText( m_panel39, wxID_ANY, _("%local_path%"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText178->Wrap( -1 ); + m_staticText178->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); + m_staticText178->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - fgSizer37->Add( m_staticText178, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer37->Add( m_staticText178, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText179 = new wxStaticText( m_panel39, wxID_ANY, _("Temporary local copy for SFTP and MTP storage"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText179->Wrap( -1 ); - m_staticText179->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText179 = new wxStaticText( m_panel39, wxID_ANY, _("Temporary local copy for SFTP and MTP storage"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText179->Wrap( -1 ); + m_staticText179->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - fgSizer37->Add( m_staticText179, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer37->Add( m_staticText179, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText189 = new wxStaticText( m_panel39, wxID_ANY, _("%item_name%"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText189->Wrap( -1 ); - m_staticText189->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); - m_staticText189->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText189 = new wxStaticText( m_panel39, wxID_ANY, _("%item_name%"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText189->Wrap( -1 ); + m_staticText189->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); + m_staticText189->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - fgSizer37->Add( m_staticText189, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer37->Add( m_staticText189, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText190 = new wxStaticText( m_panel39, wxID_ANY, _("File or folder name"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText190->Wrap( -1 ); - m_staticText190->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText190 = new wxStaticText( m_panel39, wxID_ANY, _("File or folder name"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText190->Wrap( -1 ); + m_staticText190->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - fgSizer37->Add( m_staticText190, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer37->Add( m_staticText190, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText176 = new wxStaticText( m_panel39, wxID_ANY, _("%parent_path%"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText176->Wrap( -1 ); - m_staticText176->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); - m_staticText176->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText176 = new wxStaticText( m_panel39, wxID_ANY, _("%parent_path%"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText176->Wrap( -1 ); + m_staticText176->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); + m_staticText176->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - fgSizer37->Add( m_staticText176, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer37->Add( m_staticText176, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* bSizer298; - bSizer298 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer298; + bSizer298 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText177 = new wxStaticText( m_panel39, wxID_ANY, _("Parent folder path"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText177->Wrap( -1 ); - m_staticText177->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_staticText177 = new wxStaticText( m_panel39, wxID_ANY, _("Parent folder path"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText177->Wrap( -1 ); + m_staticText177->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer298->Add( m_staticText177, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer298->Add( m_staticText177, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer298->Add( 0, 0, 1, 0, 5 ); + bSizer298->Add( 0, 0, 1, 0, 5 ); - m_hyperlink17 = new wxHyperlinkCtrl( m_panel39, wxID_ANY, _("Show examples"), wxT("https://freefilesync.org/manual.php?topic=external-applications"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink17->SetToolTip( _("https://freefilesync.org/manual.php?topic=external-applications") ); + m_hyperlink17 = new wxHyperlinkCtrl( m_panel39, wxID_ANY, _("Show examples"), wxT("https://freefilesync.org/manual.php?topic=external-applications"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink17->SetToolTip( _("https://freefilesync.org/manual.php?topic=external-applications") ); - bSizer298->Add( m_hyperlink17, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + bSizer298->Add( m_hyperlink17, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - fgSizer37->Add( bSizer298, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + fgSizer37->Add( bSizer298, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - bSizer181->Add( fgSizer37, 0, wxBOTTOM|wxLEFT, 10 ); + bSizer181->Add( fgSizer37, 0, wxBOTTOM|wxLEFT, 10 ); - bSizerContextCustomize->Add( bSizer181, 0, wxEXPAND, 5 ); + bSizerContextCustomize->Add( bSizer181, 0, wxEXPAND, 5 ); - m_gridCustomCommand = new wxGrid( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_gridCustomCommand = new wxGrid( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - // Grid - m_gridCustomCommand->CreateGrid( 3, 2 ); - m_gridCustomCommand->EnableEditing( true ); - m_gridCustomCommand->EnableGridLines( true ); - m_gridCustomCommand->EnableDragGridSize( false ); - m_gridCustomCommand->SetMargins( 0, 0 ); + // Grid + m_gridCustomCommand->CreateGrid( 3, 2 ); + m_gridCustomCommand->EnableEditing( true ); + m_gridCustomCommand->EnableGridLines( true ); + m_gridCustomCommand->EnableDragGridSize( false ); + m_gridCustomCommand->SetMargins( 0, 0 ); - // Columns - m_gridCustomCommand->EnableDragColMove( false ); - m_gridCustomCommand->EnableDragColSize( false ); - m_gridCustomCommand->SetColLabelValue( 0, _("Description") ); - m_gridCustomCommand->SetColLabelValue( 1, _("Command line") ); - m_gridCustomCommand->SetColLabelSize( -1 ); - m_gridCustomCommand->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + // Columns + m_gridCustomCommand->EnableDragColMove( false ); + m_gridCustomCommand->EnableDragColSize( false ); + m_gridCustomCommand->SetColLabelValue( 0, _("Description") ); + m_gridCustomCommand->SetColLabelValue( 1, _("Command line") ); + m_gridCustomCommand->SetColLabelSize( -1 ); + m_gridCustomCommand->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); - // Rows - m_gridCustomCommand->EnableDragRowSize( false ); - m_gridCustomCommand->SetRowLabelSize( 1 ); - m_gridCustomCommand->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + // Rows + m_gridCustomCommand->EnableDragRowSize( false ); + m_gridCustomCommand->SetRowLabelSize( 1 ); + m_gridCustomCommand->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); - // Label Appearance + // Label Appearance - // Cell Defaults - m_gridCustomCommand->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); - bSizerContextCustomize->Add( m_gridCustomCommand, 1, wxEXPAND, 5 ); + // Cell Defaults + m_gridCustomCommand->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + bSizerContextCustomize->Add( m_gridCustomCommand, 1, wxEXPAND, 5 ); - bSizer166->Add( bSizerContextCustomize, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); + bSizer166->Add( bSizerContextCustomize, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); - m_panel39->SetSizer( bSizer166 ); - m_panel39->Layout(); - bSizer166->Fit( m_panel39 ); - bSizer95->Add( m_panel39, 1, wxEXPAND, 5 ); + m_panel39->SetSizer( bSizer166 ); + m_panel39->Layout(); + bSizer166->Fit( m_panel39 ); + bSizer95->Add( m_panel39, 1, wxEXPAND, 5 ); - m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer95->Add( m_staticline36, 0, wxEXPAND, 5 ); + m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer95->Add( m_staticline36, 0, wxEXPAND, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_buttonDefault = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonDefault, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_buttonDefault = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonDefault, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStdButtons->Add( 0, 0, 1, 0, 5 ); + bSizerStdButtons->Add( 0, 0, 1, 0, 5 ); - m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonOkay->SetDefault(); + m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer95->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); + bSizer95->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); - this->SetSizer( bSizer95 ); - this->Layout(); - bSizer95->Fit( this ); + this->SetSizer( bSizer95 ); + this->Layout(); + bSizer95->Fit( this ); - this->Centre( wxBOTH ); + this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( OptionsDlgGenerated::onClose ) ); - m_buttonShowHiddenDialogs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onShowHiddenDialogs ), NULL, this ); - m_checkListHiddenDialogs->Connect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( OptionsDlgGenerated::onToggleHiddenDialog ), NULL, this ); - m_bpButtonShowLogFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onShowLogFolder ), NULL, this ); - m_checkBoxLogFilesMaxAge->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onToggleLogfilesLimit ), NULL, this ); - m_bpButtonPlayCompareDone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onPlayCompareDone ), NULL, this ); - m_textCtrlSoundPathCompareDone->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( OptionsDlgGenerated::onChangeSoundFilePath ), NULL, this ); - m_buttonSelectSoundCompareDone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onSelectSoundCompareDone ), NULL, this ); - m_bpButtonPlaySyncDone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onPlaySyncDone ), NULL, this ); - m_textCtrlSoundPathSyncDone->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( OptionsDlgGenerated::onChangeSoundFilePath ), NULL, this ); - m_buttonSelectSoundSyncDone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onSelectSoundSyncDone ), NULL, this ); - m_bpButtonPlayAlertPending->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onPlayAlertPending ), NULL, this ); - m_textCtrlSoundPathAlertPending->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( OptionsDlgGenerated::onChangeSoundFilePath ), NULL, this ); - m_buttonSelectSoundAlertPending->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onSelectSoundAlertPending ), NULL, this ); - m_buttonShowCtxCustomize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onShowContextCustomize ), NULL, this ); - m_bpButtonAddRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onAddRow ), NULL, this ); - m_bpButtonRemoveRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onRemoveRow ), NULL, this ); - m_buttonDefault->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onDefault ), NULL, this ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onCancel ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( OptionsDlgGenerated::onClose ) ); + m_buttonShowHiddenDialogs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onShowHiddenDialogs ), NULL, this ); + m_checkListHiddenDialogs->Connect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( OptionsDlgGenerated::onToggleHiddenDialog ), NULL, this ); + m_bpButtonShowLogFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onShowLogFolder ), NULL, this ); + m_checkBoxLogFilesMaxAge->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onToggleLogfilesLimit ), NULL, this ); + m_bpButtonPlayCompareDone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onPlayCompareDone ), NULL, this ); + m_textCtrlSoundPathCompareDone->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( OptionsDlgGenerated::onChangeSoundFilePath ), NULL, this ); + m_buttonSelectSoundCompareDone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onSelectSoundCompareDone ), NULL, this ); + m_bpButtonPlaySyncDone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onPlaySyncDone ), NULL, this ); + m_textCtrlSoundPathSyncDone->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( OptionsDlgGenerated::onChangeSoundFilePath ), NULL, this ); + m_buttonSelectSoundSyncDone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onSelectSoundSyncDone ), NULL, this ); + m_bpButtonPlayAlertPending->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onPlayAlertPending ), NULL, this ); + m_textCtrlSoundPathAlertPending->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( OptionsDlgGenerated::onChangeSoundFilePath ), NULL, this ); + m_buttonSelectSoundAlertPending->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onSelectSoundAlertPending ), NULL, this ); + m_buttonShowCtxCustomize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onShowContextCustomize ), NULL, this ); + m_bpButtonAddRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onAddRow ), NULL, this ); + m_bpButtonRemoveRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onRemoveRow ), NULL, this ); + m_buttonDefault->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onDefault ), NULL, this ); + m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onOkay ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OptionsDlgGenerated::onCancel ), NULL, this ); } OptionsDlgGenerated::~OptionsDlgGenerated() { } -TooltipDlgGenerated::TooltipDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +SelectTimespanDlgGenerated::SelectTimespanDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + + wxBoxSizer* bSizer96; + bSizer96 = new wxBoxSizer( wxVERTICAL ); + + m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + + wxBoxSizer* bSizer98; + bSizer98 = new wxBoxSizer( wxHORIZONTAL ); + + m_calendarFrom = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxCAL_SHOW_SURROUNDING_WEEKS|wxBORDER_NONE ); + bSizer98->Add( m_calendarFrom, 0, wxTOP|wxBOTTOM|wxLEFT, 10 ); + + m_calendarTo = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxCAL_SHOW_SURROUNDING_WEEKS|wxBORDER_NONE ); + bSizer98->Add( m_calendarTo, 0, wxALL, 10 ); + + + m_panel35->SetSizer( bSizer98 ); + m_panel35->Layout(); + bSizer98->Fit( m_panel35 ); + bSizer96->Add( m_panel35, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer158; - bSizer158 = new wxBoxSizer( wxHORIZONTAL ); + m_staticline21 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer96->Add( m_staticline21, 0, wxEXPAND, 5 ); - m_bitmapLeft = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer158->Add( m_bitmapLeft, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_staticTextMain = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMain->Wrap( 600 ); - bSizer158->Add( m_staticTextMain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_buttonOkay->SetDefault(); + m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - this->SetSizer( bSizer158 ); - this->Layout(); - bSizer158->Fit( this ); + bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + + bSizer96->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + + + this->SetSizer( bSizer96 ); + this->Layout(); + bSizer96->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SelectTimespanDlgGenerated::onClose ) ); + m_calendarFrom->Connect( wxEVT_CALENDAR_SEL_CHANGED, wxCalendarEventHandler( SelectTimespanDlgGenerated::onChangeSelectionFrom ), NULL, this ); + m_calendarTo->Connect( wxEVT_CALENDAR_SEL_CHANGED, wxCalendarEventHandler( SelectTimespanDlgGenerated::onChangeSelectionTo ), NULL, this ); + m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectTimespanDlgGenerated::onOkay ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectTimespanDlgGenerated::onCancel ), NULL, this ); } -TooltipDlgGenerated::~TooltipDlgGenerated() +SelectTimespanDlgGenerated::~SelectTimespanDlgGenerated() { } -SelectTimespanDlgGenerated::SelectTimespanDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer96; - bSizer96 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer31; + bSizer31 = new wxBoxSizer( wxVERTICAL ); - m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel41 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel41->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer98; - bSizer98 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer174; + bSizer174 = new wxBoxSizer( wxHORIZONTAL ); - m_calendarFrom = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxCAL_SHOW_SURROUNDING_WEEKS|wxBORDER_NONE ); - bSizer98->Add( m_calendarFrom, 0, wxTOP|wxBOTTOM|wxLEFT, 10 ); + m_bitmapLogoLeft = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer174->Add( m_bitmapLogoLeft, 0, wxBOTTOM, 5 ); - m_calendarTo = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxCAL_SHOW_SURROUNDING_WEEKS|wxBORDER_NONE ); - bSizer98->Add( m_calendarTo, 0, wxALL, 10 ); + m_staticline81 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer174->Add( m_staticline81, 0, wxEXPAND, 5 ); + bSizerMainSection = new wxBoxSizer( wxVERTICAL ); - m_panel35->SetSizer( bSizer98 ); - m_panel35->Layout(); - bSizer98->Fit( m_panel35 ); - bSizer96->Add( m_panel35, 0, wxEXPAND, 5 ); + m_staticline82 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMainSection->Add( m_staticline82, 0, wxEXPAND, 5 ); - m_staticline21 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer96->Add( m_staticline21, 0, wxEXPAND, 5 ); + m_bitmapLogo = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerMainSection->Add( m_bitmapLogo, 0, 0, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + m_staticline341 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMainSection->Add( m_staticline341, 0, wxEXPAND, 5 ); - m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + wxBoxSizer* bSizer298; + bSizer298 = new wxBoxSizer( wxHORIZONTAL ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticFfsTextVersion = new wxStaticText( m_panel41, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticFfsTextVersion->Wrap( -1 ); + bSizer298->Add( m_staticFfsTextVersion, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_staticTextFfsVariant = new wxStaticText( m_panel41, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextFfsVariant->Wrap( -1 ); + m_staticTextFfsVariant->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer298->Add( m_staticTextFfsVariant, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 10 ); - bSizer96->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + bSizerMainSection->Add( bSizer298, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + m_staticline3411 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMainSection->Add( m_staticline3411, 0, wxEXPAND, 5 ); - this->SetSizer( bSizer96 ); - this->Layout(); - bSizer96->Fit( this ); + bSizerDonate = new wxBoxSizer( wxVERTICAL ); - this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SelectTimespanDlgGenerated::onClose ) ); - m_calendarFrom->Connect( wxEVT_CALENDAR_SEL_CHANGED, wxCalendarEventHandler( SelectTimespanDlgGenerated::onChangeSelectionFrom ), NULL, this ); - m_calendarTo->Connect( wxEVT_CALENDAR_SEL_CHANGED, wxCalendarEventHandler( SelectTimespanDlgGenerated::onChangeSelectionTo ), NULL, this ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectTimespanDlgGenerated::onOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectTimespanDlgGenerated::onCancel ), NULL, this ); -} + bSizerDonate->Add( 0, 0, 1, 0, 5 ); -SelectTimespanDlgGenerated::~SelectTimespanDlgGenerated() -{ -} + m_panelDonate = new wxPanel( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelDonate->SetBackgroundColour( wxColour( 153, 170, 187 ) ); -AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + wxBoxSizer* bSizer183; + bSizer183 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer31; - bSizer31 = new wxBoxSizer( wxVERTICAL ); + m_bitmapAnimalSmall = new wxStaticBitmap( m_panelDonate, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer183->Add( m_bitmapAnimalSmall, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_panel41 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel41->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel39 = new wxPanel( m_panelDonate, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel39->SetBackgroundColour( wxColour( 248, 248, 248 ) ); - wxBoxSizer* bSizer174; - bSizer174 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer184; + bSizer184 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapLogoLeft = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer174->Add( m_bitmapLogoLeft, 0, wxBOTTOM, 5 ); + m_staticTextDonate = new wxStaticText( m_panel39, wxID_ANY, _("Get the Donation Edition with bonus features and help keep FreeFileSync ad-free."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDonate->Wrap( -1 ); + m_staticTextDonate->SetForegroundColour( wxColour( 0, 0, 0 ) ); - m_staticline81 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer174->Add( m_staticline81, 0, wxEXPAND, 5 ); + bSizer184->Add( m_staticTextDonate, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxALIGN_CENTER_VERTICAL, 10 ); - bSizerMainSection = new wxBoxSizer( wxVERTICAL ); - m_staticline82 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerMainSection->Add( m_staticline82, 0, wxEXPAND, 5 ); + m_panel39->SetSizer( bSizer184 ); + m_panel39->Layout(); + bSizer184->Fit( m_panel39 ); + bSizer183->Add( m_panel39, 1, wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND, 5 ); - m_bitmapLogo = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerMainSection->Add( m_bitmapLogo, 0, 0, 5 ); - m_staticline341 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerMainSection->Add( m_staticline341, 0, wxEXPAND, 5 ); + m_panelDonate->SetSizer( bSizer183 ); + m_panelDonate->Layout(); + bSizer183->Fit( m_panelDonate ); + bSizerDonate->Add( m_panelDonate, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer298; - bSizer298 = new wxBoxSizer( wxHORIZONTAL ); + m_buttonDonate1 = new zen::BitmapTextButton( m_panel41, wxID_ANY, _("Support with a donation"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_buttonDonate1->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonDonate1->SetToolTip( _("https://freefilesync.org/donate") ); - m_staticFfsTextVersion = new wxStaticText( m_panel41, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticFfsTextVersion->Wrap( -1 ); - bSizer298->Add( m_staticFfsTextVersion, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizerDonate->Add( m_buttonDonate1, 0, wxEXPAND|wxALL, 10 ); - m_staticTextFfsVariant = new wxStaticText( m_panel41, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextFfsVariant->Wrap( -1 ); - m_staticTextFfsVariant->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer298->Add( m_staticTextFfsVariant, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 10 ); + bSizerDonate->Add( 0, 0, 1, 0, 5 ); - bSizerMainSection->Add( bSizer298, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + bSizerMainSection->Add( bSizerDonate, 1, wxEXPAND, 5 ); - m_staticline3411 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerMainSection->Add( m_staticline3411, 0, wxEXPAND, 5 ); + m_bitmapAnimalBig = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerMainSection->Add( m_bitmapAnimalBig, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizerDonate = new wxBoxSizer( wxVERTICAL ); + m_staticline3412 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMainSection->Add( m_staticline3412, 0, wxEXPAND, 5 ); + wxBoxSizer* bSizer186; + bSizer186 = new wxBoxSizer( wxVERTICAL ); - bSizerDonate->Add( 0, 0, 1, 0, 5 ); + m_staticText94 = new wxStaticText( m_panel41, wxID_ANY, _("Share your feedback and ideas:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText94->Wrap( -1 ); + bSizer186->Add( m_staticText94, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 ); - m_panelDonate = new wxPanel( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelDonate->SetBackgroundColour( wxColour( 153, 170, 187 ) ); + wxBoxSizer* bSizer289; + bSizer289 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer183; - bSizer183 = new wxBoxSizer( wxHORIZONTAL ); + m_bpButtonForum = new wxBitmapButton( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + m_bpButtonForum->SetToolTip( _("https://freefilesync.org/forum") ); - m_bitmapAnimalSmall = new wxStaticBitmap( m_panelDonate, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer183->Add( m_bitmapAnimalSmall, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer289->Add( m_bpButtonForum, 0, wxALL|wxEXPAND, 5 ); - m_panel39 = new wxPanel( m_panelDonate, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel39->SetBackgroundColour( wxColour( 248, 248, 248 ) ); + m_bpButtonEmail = new wxBitmapButton( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer289->Add( m_bpButtonEmail, 0, wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND, 5 ); - wxBoxSizer* bSizer184; - bSizer184 = new wxBoxSizer( wxHORIZONTAL ); - m_staticTextDonate = new wxStaticText( m_panel39, wxID_ANY, _("Get the Donation Edition with bonus features and help keep FreeFileSync ad-free."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDonate->Wrap( -1 ); - m_staticTextDonate->SetForegroundColour( wxColour( 0, 0, 0 ) ); + bSizer186->Add( bSizer289, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer184->Add( m_staticTextDonate, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxALIGN_CENTER_VERTICAL, 10 ); + bSizerMainSection->Add( bSizer186, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - m_panel39->SetSizer( bSizer184 ); - m_panel39->Layout(); - bSizer184->Fit( m_panel39 ); - bSizer183->Add( m_panel39, 1, wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND, 5 ); + bSizer174->Add( bSizerMainSection, 0, wxEXPAND, 5 ); - m_panelDonate->SetSizer( bSizer183 ); - m_panelDonate->Layout(); - bSizer183->Fit( m_panelDonate ); - bSizerDonate->Add( m_panelDonate, 0, wxEXPAND, 5 ); + m_staticline37 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer174->Add( m_staticline37, 0, wxEXPAND, 5 ); - m_buttonDonate1 = new zen::BitmapTextButton( m_panel41, wxID_ANY, _("Support with a donation"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonDonate1->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonDonate1->SetToolTip( _("https://freefilesync.org/donate") ); + wxBoxSizer* bSizer177; + bSizer177 = new wxBoxSizer( wxVERTICAL ); - bSizerDonate->Add( m_buttonDonate1, 0, wxEXPAND|wxALL, 10 ); + m_staticTextThanksForLoc = new wxStaticText( m_panel41, wxID_ANY, _("Many thanks for translation:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextThanksForLoc->Wrap( -1 ); + bSizer177->Add( m_staticTextThanksForLoc, 0, wxALL, 5 ); + m_scrolledWindowTranslators = new wxScrolledWindow( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxVSCROLL ); + m_scrolledWindowTranslators->SetScrollRate( 10, 10 ); + m_scrolledWindowTranslators->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizerDonate->Add( 0, 0, 1, 0, 5 ); + fgSizerTranslators = new wxFlexGridSizer( 0, 2, 2, 10 ); + fgSizerTranslators->SetFlexibleDirection( wxBOTH ); + fgSizerTranslators->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - bSizerMainSection->Add( bSizerDonate, 1, wxEXPAND, 5 ); + m_scrolledWindowTranslators->SetSizer( fgSizerTranslators ); + m_scrolledWindowTranslators->Layout(); + fgSizerTranslators->Fit( m_scrolledWindowTranslators ); + bSizer177->Add( m_scrolledWindowTranslators, 1, wxEXPAND|wxLEFT, 5 ); - m_bitmapAnimalBig = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerMainSection->Add( m_bitmapAnimalBig, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - m_staticline3412 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerMainSection->Add( m_staticline3412, 0, wxEXPAND, 5 ); + bSizer174->Add( bSizer177, 0, wxEXPAND|wxLEFT, 5 ); - wxBoxSizer* bSizer186; - bSizer186 = new wxBoxSizer( wxVERTICAL ); - m_staticText94 = new wxStaticText( m_panel41, wxID_ANY, _("Share your feedback and ideas:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText94->Wrap( -1 ); - bSizer186->Add( m_staticText94, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 ); + m_panel41->SetSizer( bSizer174 ); + m_panel41->Layout(); + bSizer174->Fit( m_panel41 ); + bSizer31->Add( m_panel41, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer289; - bSizer289 = new wxBoxSizer( wxHORIZONTAL ); + m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer31->Add( m_staticline36, 0, wxEXPAND, 5 ); - m_bpButtonForum = new wxBitmapButton( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - m_bpButtonForum->SetToolTip( _("https://freefilesync.org/forum") ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - bSizer289->Add( m_bpButtonForum, 0, wxALL|wxEXPAND, 5 ); + m_buttonShowDonationDetails = new wxButton( this, wxID_ANY, _("Thank you, %x, for your support!"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerStdButtons->Add( m_buttonShowDonationDetails, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - m_bpButtonEmail = new wxBitmapButton( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizer289->Add( m_bpButtonEmail, 0, wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND, 5 ); + bSizerStdButtons->Add( 0, 0, 1, 0, 5 ); - bSizer186->Add( bSizer289, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + m_buttonDonate2 = new zen::BitmapTextButton( this, wxID_ANY, _("&Donate"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_buttonDonate2->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_buttonDonate2->SetToolTip( _("https://freefilesync.org/donate") ); + bSizerStdButtons->Add( m_buttonDonate2, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - bSizerMainSection->Add( bSizer186, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_buttonClose->SetDefault(); + bSizerStdButtons->Add( m_buttonClose, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer174->Add( bSizerMainSection, 0, wxEXPAND, 5 ); - m_staticline37 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer174->Add( m_staticline37, 0, wxEXPAND, 5 ); + bSizer31->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); - wxBoxSizer* bSizer177; - bSizer177 = new wxBoxSizer( wxVERTICAL ); - m_staticTextThanksForLoc = new wxStaticText( m_panel41, wxID_ANY, _("Many thanks for localization:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextThanksForLoc->Wrap( -1 ); - bSizer177->Add( m_staticTextThanksForLoc, 0, wxALL, 5 ); + this->SetSizer( bSizer31 ); + this->Layout(); + bSizer31->Fit( this ); - m_scrolledWindowTranslators = new wxScrolledWindow( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxVSCROLL ); - m_scrolledWindowTranslators->SetScrollRate( 10, 10 ); - m_scrolledWindowTranslators->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + this->Centre( wxBOTH ); - fgSizerTranslators = new wxFlexGridSizer( 0, 2, 2, 10 ); - fgSizerTranslators->SetFlexibleDirection( wxBOTH ); - fgSizerTranslators->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::onClose ) ); + m_buttonDonate1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onDonate ), NULL, this ); + m_bpButtonForum->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onOpenForum ), NULL, this ); + m_bpButtonEmail->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onSendEmail ), NULL, this ); + m_buttonShowDonationDetails->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onShowDonationDetails ), NULL, this ); + m_buttonDonate2->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onDonate ), NULL, this ); + m_buttonClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onOkay ), NULL, this ); +} + +AboutDlgGenerated::~AboutDlgGenerated() +{ +} + +DownloadProgressDlgGenerated::DownloadProgressDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); - m_scrolledWindowTranslators->SetSizer( fgSizerTranslators ); - m_scrolledWindowTranslators->Layout(); - fgSizerTranslators->Fit( m_scrolledWindowTranslators ); - bSizer177->Add( m_scrolledWindowTranslators, 1, wxEXPAND|wxLEFT, 5 ); + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + m_bitmapDownloading = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer72->Add( m_bitmapDownloading, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - bSizer174->Add( bSizer177, 0, wxEXPAND|wxLEFT, 5 ); + m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextHeader->Wrap( -1 ); + bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - m_panel41->SetSizer( bSizer174 ); - m_panel41->Layout(); - bSizer174->Fit( m_panel41 ); - bSizer31->Add( m_panel41, 0, wxEXPAND, 5 ); + bSizer72->Add( 20, 0, 0, 0, 5 ); - m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer31->Add( m_staticline36, 0, wxEXPAND, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizer24->Add( bSizer72, 0, 0, 5 ); - m_buttonShowDonationDetails = new wxButton( this, wxID_ANY, _("Thank you, %x, for your support!"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStdButtons->Add( m_buttonShowDonationDetails, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + wxBoxSizer* bSizer212; + bSizer212 = new wxBoxSizer( wxVERTICAL ); + m_gaugeProgress = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL ); + m_gaugeProgress->SetValue( 0 ); + bSizer212->Add( m_gaugeProgress, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - bSizerStdButtons->Add( 0, 0, 1, 0, 5 ); + m_staticTextDetails = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDetails->Wrap( -1 ); + bSizer212->Add( m_staticTextDetails, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - m_buttonDonate2 = new zen::BitmapTextButton( this, wxID_ANY, _("&Donate"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonDonate2->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonDonate2->SetToolTip( _("https://freefilesync.org/donate") ); - bSizerStdButtons->Add( m_buttonDonate2, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + bSizer24->Add( bSizer212, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_staticline9 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer24->Add( m_staticline9, 0, wxEXPAND, 5 ); - m_buttonClose->SetDefault(); - bSizerStdButtons->Add( m_buttonClose, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - bSizer31->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); + m_buttonCancel->SetDefault(); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - this->SetSizer( bSizer31 ); - this->Layout(); - bSizer31->Fit( this ); + bSizer24->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::onClose ) ); - m_buttonDonate1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onDonate ), NULL, this ); - m_bpButtonForum->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onOpenForum ), NULL, this ); - m_bpButtonEmail->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onSendEmail ), NULL, this ); - m_buttonShowDonationDetails->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onShowDonationDetails ), NULL, this ); - m_buttonDonate2->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onDonate ), NULL, this ); - m_buttonClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::onOkay ), NULL, this ); + this->SetSizer( bSizer24 ); + this->Layout(); + bSizer24->Fit( this ); + + // Connect Events + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DownloadProgressDlgGenerated::onCancel ), NULL, this ); } -AboutDlgGenerated::~AboutDlgGenerated() +DownloadProgressDlgGenerated::~DownloadProgressDlgGenerated() { } -DownloadProgressDlgGenerated::DownloadProgressDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +CfgHighlightDlgGenerated::CfgHighlightDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer24; - bSizer24 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer96; + bSizer96 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_bitmapDownloading = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer72->Add( m_bitmapDownloading, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); + wxBoxSizer* bSizer98; + bSizer98 = new wxBoxSizer( wxHORIZONTAL ); - m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextHeader->Wrap( -1 ); - bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + wxBoxSizer* bSizer238; + bSizer238 = new wxBoxSizer( wxVERTICAL ); + m_staticTextHighlight = new wxStaticText( m_panel35, wxID_ANY, _("Highlight configurations that have not been run for more than the following number of days:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextHighlight->Wrap( -1 ); + bSizer238->Add( m_staticTextHighlight, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - bSizer72->Add( 20, 0, 0, 0, 5 ); + m_spinCtrlOverdueDays = new wxSpinCtrl( m_panel35, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxSP_ARROW_KEYS, 0, 2000000000, 0 ); + bSizer238->Add( m_spinCtrlOverdueDays, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer24->Add( bSizer72, 0, 0, 5 ); + bSizer98->Add( bSizer238, 1, wxALL|wxEXPAND, 5 ); - wxBoxSizer* bSizer212; - bSizer212 = new wxBoxSizer( wxVERTICAL ); - m_gaugeProgress = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL ); - m_gaugeProgress->SetValue( 0 ); - bSizer212->Add( m_gaugeProgress, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + m_panel35->SetSizer( bSizer98 ); + m_panel35->Layout(); + bSizer98->Fit( m_panel35 ); + bSizer96->Add( m_panel35, 0, 0, 5 ); - m_staticTextDetails = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDetails->Wrap( -1 ); - bSizer212->Add( m_staticTextDetails, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + m_staticline21 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer96->Add( m_staticline21, 0, wxEXPAND, 5 ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - bSizer24->Add( bSizer212, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_staticline9 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer24->Add( m_staticline9, 0, wxEXPAND, 5 ); + m_buttonOkay->SetDefault(); + m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - m_buttonCancel->SetDefault(); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer96->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - bSizer24->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + this->SetSizer( bSizer96 ); + this->Layout(); + bSizer96->Fit( this ); - this->SetSizer( bSizer24 ); - this->Layout(); - bSizer24->Fit( this ); + this->Centre( wxBOTH ); - // Connect Events - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DownloadProgressDlgGenerated::onCancel ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CfgHighlightDlgGenerated::onClose ) ); + m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CfgHighlightDlgGenerated::onOkay ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CfgHighlightDlgGenerated::onCancel ), NULL, this ); } -DownloadProgressDlgGenerated::~DownloadProgressDlgGenerated() +CfgHighlightDlgGenerated::~CfgHighlightDlgGenerated() { } -ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +PasswordPromptDlgGenerated::PasswordPromptDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer54; - bSizer54 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer96; + bSizer96 = new wxBoxSizer( wxVERTICAL ); - m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer172; - bSizer172 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer98; + bSizer98 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer165; - bSizer165 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer238; + bSizer238 = new wxBoxSizer( wxVERTICAL ); - m_bitmapActivation = new wxStaticBitmap( m_panel35, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer165->Add( m_bitmapActivation, 0, wxALL, 10 ); + m_staticTextMain = new wxStaticText( m_panel35, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextMain->Wrap( -1 ); + bSizer238->Add( m_staticTextMain, 1, wxALL, 5 ); - wxBoxSizer* bSizer16; - bSizer16 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer305; + bSizer305 = new wxBoxSizer( wxHORIZONTAL ); + m_staticTextPassword = new wxStaticText( m_panel35, wxID_ANY, _("Password:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextPassword->Wrap( -1 ); + bSizer305->Add( m_staticTextPassword, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - bSizer16->Add( 0, 10, 0, 0, 5 ); + m_textCtrlPasswordVisible = new wxTextCtrl( m_panel35, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer305->Add( m_textCtrlPasswordVisible, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - m_richTextLastError = new wxRichTextCtrl( m_panel35, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY|wxBORDER_NONE|wxVSCROLL|wxWANTS_CHARS ); - bSizer16->Add( m_richTextLastError, 1, wxEXPAND, 5 ); + m_textCtrlPasswordHidden = new wxTextCtrl( m_panel35, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD ); + bSizer305->Add( m_textCtrlPasswordHidden, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + m_checkBoxShowPassword = new wxCheckBox( m_panel35, wxID_ANY, _("&Show password"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer305->Add( m_checkBoxShowPassword, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizer165->Add( bSizer16, 1, wxEXPAND, 5 ); + bSizer238->Add( bSizer305, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - bSizer172->Add( bSizer165, 1, wxEXPAND, 5 ); + bSizerError = new wxBoxSizer( wxHORIZONTAL ); - m_staticline82 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer172->Add( m_staticline82, 0, wxEXPAND, 5 ); + m_bitmapError = new wxStaticBitmap( m_panel35, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerError->Add( m_bitmapError, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextMain = new wxStaticText( m_panel35, wxID_ANY, _("Activate the FreeFileSync Donation Edition by one of the following methods:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMain->Wrap( -1 ); - bSizer172->Add( m_staticTextMain, 0, wxALL, 10 ); + m_staticTextError = new wxStaticText( m_panel35, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextError->Wrap( -1 ); + bSizerError->Add( m_staticTextError, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_panel35->SetSizer( bSizer172 ); - m_panel35->Layout(); - bSizer172->Fit( m_panel35 ); - bSizer54->Add( m_panel35, 1, wxEXPAND, 5 ); + bSizer238->Add( bSizerError, 0, 0, 5 ); - m_staticline181 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer54->Add( m_staticline181, 0, wxEXPAND|wxBOTTOM, 5 ); - m_staticline18111 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer54->Add( m_staticline18111, 0, wxEXPAND|wxTOP, 5 ); + bSizer98->Add( bSizer238, 1, wxALL, 5 ); - m_panel3511 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel3511->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer263; - bSizer263 = new wxBoxSizer( wxVERTICAL ); + m_panel35->SetSizer( bSizer98 ); + m_panel35->Layout(); + bSizer98->Fit( m_panel35 ); + bSizer96->Add( m_panel35, 1, wxEXPAND, 5 ); - wxBoxSizer* bSizer234; - bSizer234 = new wxBoxSizer( wxHORIZONTAL ); + m_staticline21 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer96->Add( m_staticline21, 0, wxEXPAND, 5 ); - m_staticTextMain1 = new wxStaticText( m_panel3511, wxID_ANY, _("1."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMain1->Wrap( -1 ); - bSizer234->Add( m_staticTextMain1, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_staticText136 = new wxStaticText( m_panel3511, wxID_ANY, _("Activate via internet now:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText136->Wrap( -1 ); - bSizer234->Add( m_staticText136, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonActivateOnline = new wxButton( m_panel3511, wxID_ANY, _("Activate online"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonOkay->SetDefault(); + m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonActivateOnline->SetDefault(); - m_buttonActivateOnline->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizer234->Add( m_buttonActivateOnline, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer263->Add( bSizer234, 0, wxEXPAND|wxALL, 10 ); + bSizer96->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - m_panel3511->SetSizer( bSizer263 ); - m_panel3511->Layout(); - bSizer263->Fit( m_panel3511 ); - bSizer54->Add( m_panel3511, 0, wxEXPAND, 5 ); + this->SetSizer( bSizer96 ); + this->Layout(); + bSizer96->Fit( this ); - m_staticline181111 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer54->Add( m_staticline181111, 0, wxEXPAND|wxBOTTOM, 5 ); + this->Centre( wxBOTH ); - m_staticline181112 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer54->Add( m_staticline181112, 0, wxEXPAND|wxTOP, 5 ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PasswordPromptDlgGenerated::onClose ) ); + m_textCtrlPasswordVisible->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PasswordPromptDlgGenerated::onTypingPassword ), NULL, this ); + m_textCtrlPasswordHidden->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PasswordPromptDlgGenerated::onTypingPassword ), NULL, this ); + m_checkBoxShowPassword->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PasswordPromptDlgGenerated::onToggleShowPassword ), NULL, this ); + m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PasswordPromptDlgGenerated::onOkay ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PasswordPromptDlgGenerated::onCancel ), NULL, this ); +} - m_panel351 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel351->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); +PasswordPromptDlgGenerated::~PasswordPromptDlgGenerated() +{ +} - wxBoxSizer* bSizer266; - bSizer266 = new wxBoxSizer( wxVERTICAL ); +ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer237; - bSizer237 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer54; + bSizer54 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer236; - bSizer236 = new wxBoxSizer( wxHORIZONTAL ); + m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_staticText175 = new wxStaticText( m_panel351, wxID_ANY, _("2."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText175->Wrap( -1 ); - bSizer236->Add( m_staticText175, 0, wxRIGHT|wxALIGN_BOTTOM, 5 ); + wxBoxSizer* bSizer172; + bSizer172 = new wxBoxSizer( wxVERTICAL ); - m_staticText1361 = new wxStaticText( m_panel351, wxID_ANY, _("Retrieve an offline activation key from the following URL:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1361->Wrap( -1 ); - bSizer236->Add( m_staticText1361, 1, wxRIGHT|wxALIGN_BOTTOM, 5 ); + wxBoxSizer* bSizer165; + bSizer165 = new wxBoxSizer( wxHORIZONTAL ); - m_buttonCopyUrl = new wxButton( m_panel351, wxID_ANY, _("&Copy to clipboard"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer236->Add( m_buttonCopyUrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_bitmapActivation = new wxStaticBitmap( m_panel35, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer165->Add( m_bitmapActivation, 0, wxALL, 10 ); + wxBoxSizer* bSizer16; + bSizer16 = new wxBoxSizer( wxVERTICAL ); - bSizer237->Add( bSizer236, 0, wxEXPAND|wxBOTTOM, 5 ); - m_richTextManualActivationUrl = new wxRichTextCtrl( m_panel351, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY|wxBORDER_NONE|wxVSCROLL|wxWANTS_CHARS ); - bSizer237->Add( m_richTextManualActivationUrl, 0, wxEXPAND|wxBOTTOM, 5 ); + bSizer16->Add( 0, 10, 0, 0, 5 ); - wxBoxSizer* bSizer235; - bSizer235 = new wxBoxSizer( wxHORIZONTAL ); + m_richTextLastError = new wxRichTextCtrl( m_panel35, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY|wxBORDER_NONE|wxVSCROLL|wxWANTS_CHARS ); + bSizer16->Add( m_richTextLastError, 1, wxEXPAND, 5 ); - m_staticText13611 = new wxStaticText( m_panel351, wxID_ANY, _("Enter activation key:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText13611->Wrap( -1 ); - bSizer235->Add( m_staticText13611, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_textCtrlOfflineActivationKey = new wxTextCtrl( m_panel351, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_PROCESS_ENTER ); - bSizer235->Add( m_textCtrlOfflineActivationKey, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizer165->Add( bSizer16, 1, wxEXPAND, 5 ); - m_buttonActivateOffline = new wxButton( m_panel351, wxID_ANY, _("Activate offline"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonActivateOffline->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizer235->Add( m_buttonActivateOffline, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer172->Add( bSizer165, 1, wxEXPAND, 5 ); + m_staticline82 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer172->Add( m_staticline82, 0, wxEXPAND, 5 ); - bSizer237->Add( bSizer235, 0, wxEXPAND|wxTOP, 5 ); + m_staticTextMain = new wxStaticText( m_panel35, wxID_ANY, _("Activate the FreeFileSync Donation Edition by one of the following methods:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextMain->Wrap( -1 ); + bSizer172->Add( m_staticTextMain, 0, wxALL, 10 ); - bSizer266->Add( bSizer237, 0, wxALL|wxEXPAND, 10 ); + m_panel35->SetSizer( bSizer172 ); + m_panel35->Layout(); + bSizer172->Fit( m_panel35 ); + bSizer54->Add( m_panel35, 1, wxEXPAND, 5 ); + m_staticline181 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer54->Add( m_staticline181, 0, wxEXPAND|wxBOTTOM, 5 ); - m_panel351->SetSizer( bSizer266 ); - m_panel351->Layout(); - bSizer266->Fit( m_panel351 ); - bSizer54->Add( m_panel351, 0, wxEXPAND, 5 ); + m_staticline18111 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer54->Add( m_staticline18111, 0, wxEXPAND|wxTOP, 5 ); - m_staticline13 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer54->Add( m_staticline13, 0, wxEXPAND, 5 ); + m_panel3511 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel3511->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer263; + bSizer263 = new wxBoxSizer( wxVERTICAL ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + wxBoxSizer* bSizer234; + bSizer234 = new wxBoxSizer( wxHORIZONTAL ); + m_staticTextMain1 = new wxStaticText( m_panel3511, wxID_ANY, _("1."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextMain1->Wrap( -1 ); + bSizer234->Add( m_staticTextMain1, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer54->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + m_staticText136 = new wxStaticText( m_panel3511, wxID_ANY, _("Activate via internet now:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText136->Wrap( -1 ); + bSizer234->Add( m_staticText136, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_buttonActivateOnline = new wxButton( m_panel3511, wxID_ANY, _("Activate online"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - this->SetSizer( bSizer54 ); - this->Layout(); - bSizer54->Fit( this ); + m_buttonActivateOnline->SetDefault(); + m_buttonActivateOnline->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - this->Centre( wxBOTH ); + bSizer234->Add( m_buttonActivateOnline, 0, wxALIGN_CENTER_VERTICAL, 5 ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ActivationDlgGenerated::onClose ) ); - m_buttonActivateOnline->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActivationDlgGenerated::onActivateOnline ), NULL, this ); - m_buttonCopyUrl->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActivationDlgGenerated::onCopyUrl ), NULL, this ); - m_textCtrlOfflineActivationKey->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( ActivationDlgGenerated::onOfflineActivationEnter ), NULL, this ); - m_buttonActivateOffline->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActivationDlgGenerated::onActivateOffline ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActivationDlgGenerated::onCancel ), NULL, this ); -} -ActivationDlgGenerated::~ActivationDlgGenerated() -{ -} + bSizer263->Add( bSizer234, 0, wxEXPAND|wxALL, 10 ); -CfgHighlightDlgGenerated::CfgHighlightDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer96; - bSizer96 = new wxBoxSizer( wxVERTICAL ); + m_panel3511->SetSizer( bSizer263 ); + m_panel3511->Layout(); + bSizer263->Fit( m_panel3511 ); + bSizer54->Add( m_panel3511, 0, wxEXPAND, 5 ); + + m_staticline181111 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer54->Add( m_staticline181111, 0, wxEXPAND|wxBOTTOM, 5 ); + + m_staticline181112 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer54->Add( m_staticline181112, 0, wxEXPAND|wxTOP, 5 ); + + m_panel351 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel351->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + + wxBoxSizer* bSizer266; + bSizer266 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer237; + bSizer237 = new wxBoxSizer( wxVERTICAL ); - m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + wxBoxSizer* bSizer236; + bSizer236 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer98; - bSizer98 = new wxBoxSizer( wxHORIZONTAL ); + m_staticText175 = new wxStaticText( m_panel351, wxID_ANY, _("2."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText175->Wrap( -1 ); + bSizer236->Add( m_staticText175, 0, wxRIGHT|wxALIGN_BOTTOM, 5 ); - wxBoxSizer* bSizer238; - bSizer238 = new wxBoxSizer( wxVERTICAL ); + m_staticText1361 = new wxStaticText( m_panel351, wxID_ANY, _("Retrieve an offline activation key from the following URL:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1361->Wrap( -1 ); + bSizer236->Add( m_staticText1361, 1, wxRIGHT|wxALIGN_BOTTOM, 5 ); - m_staticTextHighlight = new wxStaticText( m_panel35, wxID_ANY, _("Highlight configurations that have not been run for more than the following number of days:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextHighlight->Wrap( -1 ); - bSizer238->Add( m_staticTextHighlight, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + m_buttonCopyUrl = new wxButton( m_panel351, wxID_ANY, _("&Copy to clipboard"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer236->Add( m_buttonCopyUrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_spinCtrlOverdueDays = new wxSpinCtrl( m_panel35, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - bSizer238->Add( m_spinCtrlOverdueDays, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer237->Add( bSizer236, 0, wxEXPAND|wxBOTTOM, 5 ); - bSizer98->Add( bSizer238, 1, wxALL|wxEXPAND, 5 ); + m_richTextManualActivationUrl = new wxRichTextCtrl( m_panel351, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY|wxBORDER_NONE|wxVSCROLL|wxWANTS_CHARS ); + bSizer237->Add( m_richTextManualActivationUrl, 0, wxEXPAND|wxBOTTOM, 5 ); + wxBoxSizer* bSizer235; + bSizer235 = new wxBoxSizer( wxHORIZONTAL ); - m_panel35->SetSizer( bSizer98 ); - m_panel35->Layout(); - bSizer98->Fit( m_panel35 ); - bSizer96->Add( m_panel35, 0, 0, 5 ); + m_staticText13611 = new wxStaticText( m_panel351, wxID_ANY, _("Enter activation key:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText13611->Wrap( -1 ); + bSizer235->Add( m_staticText13611, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_staticline21 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer96->Add( m_staticline21, 0, wxEXPAND, 5 ); + m_textCtrlOfflineActivationKey = new wxTextCtrl( m_panel351, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_PROCESS_ENTER ); + bSizer235->Add( m_textCtrlOfflineActivationKey, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + m_buttonActivateOffline = new wxButton( m_panel351, wxID_ANY, _("Activate offline"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_buttonActivateOffline->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizer235->Add( m_buttonActivateOffline, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); - bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer237->Add( bSizer235, 0, wxEXPAND|wxTOP, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer266->Add( bSizer237, 0, wxALL|wxEXPAND, 10 ); - bSizer96->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + m_panel351->SetSizer( bSizer266 ); + m_panel351->Layout(); + bSizer266->Fit( m_panel351 ); + bSizer54->Add( m_panel351, 0, wxEXPAND, 5 ); - this->SetSizer( bSizer96 ); - this->Layout(); - bSizer96->Fit( this ); + m_staticline13 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer54->Add( m_staticline13, 0, wxEXPAND, 5 ); - this->Centre( wxBOTH ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CfgHighlightDlgGenerated::onClose ) ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CfgHighlightDlgGenerated::onOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CfgHighlightDlgGenerated::onCancel ), NULL, this ); + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + + bSizer54->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + + + this->SetSizer( bSizer54 ); + this->Layout(); + bSizer54->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ActivationDlgGenerated::onClose ) ); + m_buttonActivateOnline->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActivationDlgGenerated::onActivateOnline ), NULL, this ); + m_buttonCopyUrl->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActivationDlgGenerated::onCopyUrl ), NULL, this ); + m_textCtrlOfflineActivationKey->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( ActivationDlgGenerated::onOfflineActivationEnter ), NULL, this ); + m_buttonActivateOffline->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActivationDlgGenerated::onActivateOffline ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActivationDlgGenerated::onCancel ), NULL, this ); } -CfgHighlightDlgGenerated::~CfgHighlightDlgGenerated() +ActivationDlgGenerated::~ActivationDlgGenerated() { } WarnAccessRightsMissingDlgGenerated::WarnAccessRightsMissingDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - wxBoxSizer* bSizer330; - bSizer330 = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer330; + bSizer330 = new wxBoxSizer( wxHORIZONTAL ); - m_bitmapGrantAccess = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer330->Add( m_bitmapGrantAccess, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); + m_bitmapGrantAccess = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer330->Add( m_bitmapGrantAccess, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - wxBoxSizer* bSizer95; - bSizer95 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer95; + bSizer95 = new wxBoxSizer( wxVERTICAL ); - m_staticTextDescr = new wxStaticText( this, wxID_ANY, _("FreeFileSync requires access rights to avoid \"Operation not permitted\" errors when synchronizing your data (e.g. Mail, Messages, Calendars)."), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextDescr->Wrap( -1 ); - bSizer95->Add( m_staticTextDescr, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + m_staticTextDescr = new wxStaticText( this, wxID_ANY, _("FreeFileSync requires access rights to avoid \"Operation not permitted\" errors when synchronizing your data (e.g. Mail, Messages, Calendars)."), wxDefaultPosition, wxSize( -1, -1 ), 0 ); + m_staticTextDescr->Wrap( -1 ); + bSizer95->Add( m_staticTextDescr, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - m_staticline20 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer95->Add( m_staticline20, 0, wxEXPAND, 5 ); + m_staticline20 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer95->Add( m_staticline20, 0, wxEXPAND, 5 ); - m_panel39 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel39->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_panel39 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel39->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - wxBoxSizer* bSizer166; - bSizer166 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer166; + bSizer166 = new wxBoxSizer( wxVERTICAL ); - ffgSizer11 = new wxFlexGridSizer( 0, 2, 5, 5 ); - ffgSizer11->SetFlexibleDirection( wxBOTH ); - ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + ffgSizer11 = new wxFlexGridSizer( 0, 2, 5, 5 ); + ffgSizer11->SetFlexibleDirection( wxBOTH ); + ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticTextStep1 = new wxStaticText( m_panel39, wxID_ANY, _("1."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStep1->Wrap( -1 ); - ffgSizer11->Add( m_staticTextStep1, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_staticTextStep1 = new wxStaticText( m_panel39, wxID_ANY, _("1."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStep1->Wrap( -1 ); + ffgSizer11->Add( m_staticTextStep1, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_buttonLocateBundle = new wxButton( m_panel39, wxID_ANY, _("Locate the FreeFileSync app"), wxDefaultPosition, wxDefaultSize, 0 ); - ffgSizer11->Add( m_buttonLocateBundle, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + m_buttonLocateBundle = new wxButton( m_panel39, wxID_ANY, _("Locate the FreeFileSync app"), wxDefaultPosition, wxDefaultSize, 0 ); + ffgSizer11->Add( m_buttonLocateBundle, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticTextStep2 = new wxStaticText( m_panel39, wxID_ANY, _("2."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStep2->Wrap( -1 ); - ffgSizer11->Add( m_staticTextStep2, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_staticTextStep2 = new wxStaticText( m_panel39, wxID_ANY, _("2."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStep2->Wrap( -1 ); + ffgSizer11->Add( m_staticTextStep2, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_buttonOpenSecurity = new wxButton( m_panel39, wxID_ANY, _("Open Security && Privacy"), wxDefaultPosition, wxDefaultSize, 0 ); - ffgSizer11->Add( m_buttonOpenSecurity, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + m_buttonOpenSecurity = new wxButton( m_panel39, wxID_ANY, _("Open Security && Privacy"), wxDefaultPosition, wxDefaultSize, 0 ); + ffgSizer11->Add( m_buttonOpenSecurity, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticTextStep3 = new wxStaticText( m_panel39, wxID_ANY, _("3."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStep3->Wrap( -1 ); - ffgSizer11->Add( m_staticTextStep3, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_staticTextStep3 = new wxStaticText( m_panel39, wxID_ANY, _("3."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStep3->Wrap( -1 ); + ffgSizer11->Add( m_staticTextStep3, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_staticTextAllowChanges = new wxStaticText( m_panel39, wxID_ANY, _("Click the lock to allow changes."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextAllowChanges->Wrap( -1 ); - ffgSizer11->Add( m_staticTextAllowChanges, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextAllowChanges = new wxStaticText( m_panel39, wxID_ANY, _("Click the lock to allow changes."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextAllowChanges->Wrap( -1 ); + ffgSizer11->Add( m_staticTextAllowChanges, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_staticTextStep4 = new wxStaticText( m_panel39, wxID_ANY, _("4."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStep4->Wrap( -1 ); - ffgSizer11->Add( m_staticTextStep4, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_staticTextStep4 = new wxStaticText( m_panel39, wxID_ANY, _("4."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStep4->Wrap( -1 ); + ffgSizer11->Add( m_staticTextStep4, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_staticTextGrantAccess = new wxStaticText( m_panel39, wxID_ANY, _("Drag FreeFileSync into the panel."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextGrantAccess->Wrap( -1 ); - ffgSizer11->Add( m_staticTextGrantAccess, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticTextGrantAccess = new wxStaticText( m_panel39, wxID_ANY, _("Drag FreeFileSync into the panel."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextGrantAccess->Wrap( -1 ); + ffgSizer11->Add( m_staticTextGrantAccess, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bSizer166->Add( ffgSizer11, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 10 ); + bSizer166->Add( ffgSizer11, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 10 ); - m_panel39->SetSizer( bSizer166 ); - m_panel39->Layout(); - bSizer166->Fit( m_panel39 ); - bSizer95->Add( m_panel39, 1, wxEXPAND, 5 ); + m_panel39->SetSizer( bSizer166 ); + m_panel39->Layout(); + bSizer166->Fit( m_panel39 ); + bSizer95->Add( m_panel39, 1, wxEXPAND, 5 ); - m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer95->Add( m_staticline36, 0, wxEXPAND, 5 ); + m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer95->Add( m_staticline36, 0, wxEXPAND, 5 ); - m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("&Don't show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer95->Add( m_checkBoxDontShowAgain, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("&Don't show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer95->Add( m_checkBoxDontShowAgain, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1, -1 ), 0 ); - m_buttonClose->SetDefault(); - bSizerStdButtons->Add( m_buttonClose, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_buttonClose->SetDefault(); + bSizerStdButtons->Add( m_buttonClose, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizer95->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + bSizer95->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - bSizer330->Add( bSizer95, 1, wxEXPAND, 5 ); + bSizer330->Add( bSizer95, 1, wxEXPAND, 5 ); - this->SetSizer( bSizer330 ); - this->Layout(); - bSizer330->Fit( this ); + this->SetSizer( bSizer330 ); + this->Layout(); + bSizer330->Fit( this ); - this->Centre( wxBOTH ); + this->Centre( wxBOTH ); - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WarnAccessRightsMissingDlgGenerated::onClose ) ); - m_buttonLocateBundle->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarnAccessRightsMissingDlgGenerated::onShowAppBundle ), NULL, this ); - m_buttonOpenSecurity->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarnAccessRightsMissingDlgGenerated::onOpenSecuritySettings ), NULL, this ); - m_checkBoxDontShowAgain->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( WarnAccessRightsMissingDlgGenerated::onCheckBoxClick ), NULL, this ); - m_buttonClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarnAccessRightsMissingDlgGenerated::onOkay ), NULL, this ); + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WarnAccessRightsMissingDlgGenerated::onClose ) ); + m_buttonLocateBundle->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarnAccessRightsMissingDlgGenerated::onShowAppBundle ), NULL, this ); + m_buttonOpenSecurity->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarnAccessRightsMissingDlgGenerated::onOpenSecuritySettings ), NULL, this ); + m_checkBoxDontShowAgain->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( WarnAccessRightsMissingDlgGenerated::onCheckBoxClick ), NULL, this ); + m_buttonClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarnAccessRightsMissingDlgGenerated::onOkay ), NULL, this ); } WarnAccessRightsMissingDlgGenerated::~WarnAccessRightsMissingDlgGenerated() diff --git a/FreeFileSync/Source/ui/gui_generated.h b/FreeFileSync/Source/ui/gui_generated.h index 62015c50..d44dc41d 100644 --- a/FreeFileSync/Source/ui/gui_generated.h +++ b/FreeFileSync/Source/ui/gui_generated.h @@ -10,7 +10,7 @@ #include <wx/artprov.h> #include <wx/xrc/xmlres.h> #include <wx/intl.h> -namespace zen{ class BitmapTextButton; } +namespace zen { class BitmapTextButton; } #include "wx+/bitmap_button.h" #include "folder_history_box.h" @@ -65,229 +65,229 @@ namespace zen{ class BitmapTextButton; } /////////////////////////////////////////////////////////////////////////////// class MainDialogGenerated : public wxFrame { - private: - - protected: - wxMenuBar* m_menubar; - wxMenu* m_menuFile; - wxMenuItem* m_menuItemNew; - wxMenuItem* m_menuItemLoad; - wxMenuItem* m_menuItemSave; - wxMenuItem* m_menuItemSaveAs; - wxMenuItem* m_menuItemSaveAsBatch; - wxMenuItem* m_menuItemQuit; - wxMenu* m_menuActions; - wxMenuItem* m_menuItemShowLog; - wxMenuItem* m_menuItemCompare; - wxMenuItem* m_menuItemCompSettings; - wxMenuItem* m_menuItemFilter; - wxMenuItem* m_menuItemSyncSettings; - wxMenuItem* m_menuItemSynchronize; - wxMenu* m_menuTools; - wxMenuItem* m_menuItemOptions; - wxMenu* m_menuLanguages; - wxMenuItem* m_menuItemFind; - wxMenuItem* m_menuItemExportList; - wxMenuItem* m_menuItemResetLayout; - wxMenuItem* m_menuItemShowMain; - wxMenuItem* m_menuItemShowFolders; - wxMenuItem* m_menuItemShowViewFilter; - wxMenuItem* m_menuItemShowConfig; - wxMenuItem* m_menuItemShowOverview; - wxMenu* m_menuHelp; - wxMenuItem* m_menuItemHelp; - wxMenuItem* m_menuItemCheckVersionNow; - wxMenuItem* m_menuItemCheckVersionAuto; - wxMenuItem* m_menuItemAbout; - wxBoxSizer* bSizerPanelHolder; - wxPanel* m_panelTopButtons; - wxBoxSizer* bSizerTopButtons; - wxButton* m_buttonCancel; - zen::BitmapTextButton* m_buttonCompare; - wxBitmapButton* m_bpButtonCmpConfig; - wxBitmapButton* m_bpButtonCmpContext; - wxBitmapButton* m_bpButtonFilter; - wxBitmapButton* m_bpButtonFilterContext; - wxBitmapButton* m_bpButtonSyncConfig; - wxBitmapButton* m_bpButtonSyncContext; - zen::BitmapTextButton* m_buttonSync; - wxPanel* m_panelDirectoryPairs; - wxStaticText* m_staticTextResolvedPathL; - wxBitmapButton* m_bpButtonAddPair; - wxButton* m_buttonSelectFolderLeft; - wxPanel* m_panelTopCenter; - wxBitmapButton* m_bpButtonSwapSides; - wxStaticText* m_staticTextResolvedPathR; - wxButton* m_buttonSelectFolderRight; - wxScrolledWindow* m_scrolledWindowFolderPairs; - wxBoxSizer* bSizerAddFolderPairs; - zen::Grid* m_gridOverview; - wxPanel* m_panelCenter; - fff::TripleSplitter* m_splitterMain; - zen::Grid* m_gridMainL; - zen::Grid* m_gridMainC; - zen::Grid* m_gridMainR; - wxPanel* m_panelStatusBar; - wxBoxSizer* bSizerFileStatus; - wxBoxSizer* bSizerStatusLeft; - wxBoxSizer* bSizerStatusLeftDirectories; - wxStaticBitmap* m_bitmapSmallDirectoryLeft; - wxStaticText* m_staticTextStatusLeftDirs; - wxBoxSizer* bSizerStatusLeftFiles; - wxStaticBitmap* m_bitmapSmallFileLeft; - wxStaticText* m_staticTextStatusLeftFiles; - wxStaticText* m_staticTextStatusLeftBytes; - wxStaticLine* m_staticline9; - wxStaticText* m_staticTextStatusCenter; - wxBoxSizer* bSizerStatusRight; - wxStaticLine* m_staticline10; - wxBoxSizer* bSizerStatusRightDirectories; - wxStaticBitmap* m_bitmapSmallDirectoryRight; - wxStaticText* m_staticTextStatusRightDirs; - wxBoxSizer* bSizerStatusRightFiles; - wxStaticBitmap* m_bitmapSmallFileRight; - wxStaticText* m_staticTextStatusRightFiles; - wxStaticText* m_staticTextStatusRightBytes; - wxStaticText* m_staticTextFullStatus; - wxPanel* m_panelSearch; - wxBitmapButton* m_bpButtonHideSearch; - wxStaticText* m_staticText101; - wxTextCtrl* m_textCtrlSearchTxt; - wxCheckBox* m_checkBoxMatchCase; - wxPanel* m_panelLog; - wxBoxSizer* bSizerLog; - wxBoxSizer* bSizer42; - wxFlexGridSizer* ffgSizer11; - wxFlexGridSizer* ffgSizer111; - wxFlexGridSizer* ffgSizer112; - wxStaticLine* m_staticline70; - wxPanel* m_panelConfig; - wxBoxSizer* bSizerConfig; - wxBoxSizer* bSizerCfgHistoryButtons; - wxBitmapButton* m_bpButtonNew; - wxStaticText* m_staticText951; - wxBitmapButton* m_bpButtonOpen; - wxStaticText* m_staticText95; - wxBitmapButton* m_bpButtonSave; - wxStaticText* m_staticText961; - wxBoxSizer* bSizerSaveAs; - wxBitmapButton* m_bpButtonSaveAs; - wxBitmapButton* m_bpButtonSaveAsBatch; - wxStaticText* m_staticText97; - wxStaticLine* m_staticline81; - zen::Grid* m_gridCfgHistory; - wxPanel* m_panelViewFilter; - wxBoxSizer* bSizerViewFilter; - wxBitmapButton* m_bpButtonToggleLog; - wxBoxSizer* bSizerViewButtons; - zen::ToggleButton* m_bpButtonViewType; - zen::ToggleButton* m_bpButtonShowExcluded; - zen::ToggleButton* m_bpButtonShowDeleteLeft; - zen::ToggleButton* m_bpButtonShowUpdateLeft; - zen::ToggleButton* m_bpButtonShowCreateLeft; - zen::ToggleButton* m_bpButtonShowLeftOnly; - zen::ToggleButton* m_bpButtonShowLeftNewer; - zen::ToggleButton* m_bpButtonShowEqual; - zen::ToggleButton* m_bpButtonShowDoNothing; - zen::ToggleButton* m_bpButtonShowDifferent; - zen::ToggleButton* m_bpButtonShowRightNewer; - zen::ToggleButton* m_bpButtonShowRightOnly; - zen::ToggleButton* m_bpButtonShowCreateRight; - zen::ToggleButton* m_bpButtonShowUpdateRight; - zen::ToggleButton* m_bpButtonShowDeleteRight; - zen::ToggleButton* m_bpButtonShowConflict; - wxBitmapButton* m_bpButtonViewFilterContext; - wxStaticText* m_staticText96; - wxPanel* m_panelStatistics; - wxBoxSizer* bSizer1801; - wxStaticBitmap* m_bitmapDeleteLeft; - wxStaticText* m_staticTextDeleteLeft; - wxStaticBitmap* m_bitmapUpdateLeft; - wxStaticText* m_staticTextUpdateLeft; - wxStaticBitmap* m_bitmapCreateLeft; - wxStaticText* m_staticTextCreateLeft; - wxStaticBitmap* m_bitmapData; - wxStaticText* m_staticTextData; - wxStaticBitmap* m_bitmapCreateRight; - wxStaticText* m_staticTextCreateRight; - wxStaticBitmap* m_bitmapUpdateRight; - wxStaticText* m_staticTextUpdateRight; - wxStaticBitmap* m_bitmapDeleteRight; - wxStaticText* m_staticTextDeleteRight; - - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onConfigNew( wxCommandEvent& event ) { event.Skip(); } - virtual void onConfigLoad( wxCommandEvent& event ) { event.Skip(); } - virtual void onConfigSave( wxCommandEvent& event ) { event.Skip(); } - virtual void onConfigSaveAs( wxCommandEvent& event ) { event.Skip(); } - virtual void onSaveAsBatchJob( wxCommandEvent& event ) { event.Skip(); } - virtual void onMenuQuit( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleLog( wxCommandEvent& event ) { event.Skip(); } - virtual void onCompare( wxCommandEvent& event ) { event.Skip(); } - virtual void onCmpSettings( wxCommandEvent& event ) { event.Skip(); } - virtual void onConfigureFilter( wxCommandEvent& event ) { event.Skip(); } - virtual void onSyncSettings( wxCommandEvent& event ) { event.Skip(); } - virtual void onStartSync( wxCommandEvent& event ) { event.Skip(); } - virtual void onMenuOptions( wxCommandEvent& event ) { event.Skip(); } - virtual void onMenuFindItem( wxCommandEvent& event ) { event.Skip(); } - virtual void onMenuExportFileList( wxCommandEvent& event ) { event.Skip(); } - virtual void onMenuResetLayout( wxCommandEvent& event ) { event.Skip(); } - virtual void onShowHelp( wxCommandEvent& event ) { event.Skip(); } - virtual void onMenuCheckVersion( wxCommandEvent& event ) { event.Skip(); } - virtual void onMenuCheckVersionAutomatically( wxCommandEvent& event ) { event.Skip(); } - virtual void onMenuAbout( wxCommandEvent& event ) { event.Skip(); } - virtual void onCompSettingsContextMouse( wxMouseEvent& event ) { event.Skip(); } - virtual void onCompSettingsContext( wxCommandEvent& event ) { event.Skip(); } - virtual void onGlobalFilterContextMouse( wxMouseEvent& event ) { event.Skip(); } - virtual void onGlobalFilterContext( wxCommandEvent& event ) { event.Skip(); } - virtual void onSyncSettingsContextMouse( wxMouseEvent& event ) { event.Skip(); } - virtual void onSyncSettingsContext( wxCommandEvent& event ) { event.Skip(); } - virtual void onTopFolderPairAdd( wxCommandEvent& event ) { event.Skip(); } - virtual void onTopFolderPairRemove( wxCommandEvent& event ) { event.Skip(); } - virtual void onSwapSides( wxCommandEvent& event ) { event.Skip(); } - virtual void onTopLocalCompCfg( wxCommandEvent& event ) { event.Skip(); } - virtual void onTopLocalFilterCfg( wxCommandEvent& event ) { event.Skip(); } - virtual void onTopLocalSyncCfg( wxCommandEvent& event ) { event.Skip(); } - virtual void onHideSearchPanel( wxCommandEvent& event ) { event.Skip(); } - virtual void onSearchGridEnter( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleViewType( wxCommandEvent& event ) { event.Skip(); } - virtual void onViewTypeContextMouse( wxMouseEvent& event ) { event.Skip(); } - virtual void onToggleViewButton( wxCommandEvent& event ) { event.Skip(); } - virtual void onViewFilterContextMouse( wxMouseEvent& event ) { event.Skip(); } - virtual void onViewFilterContext( wxCommandEvent& event ) { event.Skip(); } - - - public: - wxPanel* m_panelTopLeft; - wxBitmapButton* m_bpButtonRemovePair; - fff::FolderHistoryBox* m_folderPathLeft; - wxBitmapButton* m_bpButtonSelectAltFolderLeft; - wxBitmapButton* m_bpButtonLocalCompCfg; - wxBitmapButton* m_bpButtonLocalFilter; - wxBitmapButton* m_bpButtonLocalSyncCfg; - wxPanel* m_panelTopRight; - fff::FolderHistoryBox* m_folderPathRight; - wxBitmapButton* m_bpButtonSelectAltFolderRight; - wxStaticBitmap* m_bitmapSyncResult; - wxStaticText* m_staticTextSyncResult; - wxStaticText* m_staticTextProcessed; - wxStaticText* m_staticTextRemaining; - wxPanel* m_panelItemStats; - wxStaticBitmap* m_bitmapItemStat; - wxStaticText* m_staticTextItemsProcessed; - wxStaticText* m_staticTextBytesProcessed; - wxStaticText* m_staticTextItemsRemaining; - wxStaticText* m_staticTextBytesRemaining; - wxPanel* m_panelTimeStats; - wxStaticBitmap* m_bitmapTimeStat; - wxStaticText* m_staticTextTimeElapsed; - wxBoxSizer* bSizerStatistics; - wxBoxSizer* bSizerData; - - MainDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); - - ~MainDialogGenerated(); +private: + +protected: + wxMenuBar* m_menubar; + wxMenu* m_menuFile; + wxMenuItem* m_menuItemNew; + wxMenuItem* m_menuItemLoad; + wxMenuItem* m_menuItemSave; + wxMenuItem* m_menuItemSaveAs; + wxMenuItem* m_menuItemSaveAsBatch; + wxMenuItem* m_menuItemQuit; + wxMenu* m_menuActions; + wxMenuItem* m_menuItemShowLog; + wxMenuItem* m_menuItemCompare; + wxMenuItem* m_menuItemCompSettings; + wxMenuItem* m_menuItemFilter; + wxMenuItem* m_menuItemSyncSettings; + wxMenuItem* m_menuItemSynchronize; + wxMenu* m_menuTools; + wxMenuItem* m_menuItemOptions; + wxMenu* m_menuLanguages; + wxMenuItem* m_menuItemFind; + wxMenuItem* m_menuItemExportList; + wxMenuItem* m_menuItemResetLayout; + wxMenuItem* m_menuItemShowMain; + wxMenuItem* m_menuItemShowFolders; + wxMenuItem* m_menuItemShowViewFilter; + wxMenuItem* m_menuItemShowConfig; + wxMenuItem* m_menuItemShowOverview; + wxMenu* m_menuHelp; + wxMenuItem* m_menuItemHelp; + wxMenuItem* m_menuItemCheckVersionNow; + wxMenuItem* m_menuItemCheckVersionAuto; + wxMenuItem* m_menuItemAbout; + wxBoxSizer* bSizerPanelHolder; + wxPanel* m_panelTopButtons; + wxBoxSizer* bSizerTopButtons; + wxButton* m_buttonCancel; + zen::BitmapTextButton* m_buttonCompare; + wxBitmapButton* m_bpButtonCmpConfig; + wxBitmapButton* m_bpButtonCmpContext; + wxBitmapButton* m_bpButtonFilter; + wxBitmapButton* m_bpButtonFilterContext; + wxBitmapButton* m_bpButtonSyncConfig; + wxBitmapButton* m_bpButtonSyncContext; + zen::BitmapTextButton* m_buttonSync; + wxPanel* m_panelDirectoryPairs; + wxStaticText* m_staticTextResolvedPathL; + wxBitmapButton* m_bpButtonAddPair; + wxButton* m_buttonSelectFolderLeft; + wxPanel* m_panelTopCenter; + wxBitmapButton* m_bpButtonSwapSides; + wxStaticText* m_staticTextResolvedPathR; + wxButton* m_buttonSelectFolderRight; + wxScrolledWindow* m_scrolledWindowFolderPairs; + wxBoxSizer* bSizerAddFolderPairs; + zen::Grid* m_gridOverview; + wxPanel* m_panelCenter; + fff::TripleSplitter* m_splitterMain; + zen::Grid* m_gridMainL; + zen::Grid* m_gridMainC; + zen::Grid* m_gridMainR; + wxPanel* m_panelStatusBar; + wxBoxSizer* bSizerFileStatus; + wxBoxSizer* bSizerStatusLeft; + wxBoxSizer* bSizerStatusLeftDirectories; + wxStaticBitmap* m_bitmapSmallDirectoryLeft; + wxStaticText* m_staticTextStatusLeftDirs; + wxBoxSizer* bSizerStatusLeftFiles; + wxStaticBitmap* m_bitmapSmallFileLeft; + wxStaticText* m_staticTextStatusLeftFiles; + wxStaticText* m_staticTextStatusLeftBytes; + wxStaticLine* m_staticline9; + wxStaticText* m_staticTextStatusCenter; + wxBoxSizer* bSizerStatusRight; + wxStaticLine* m_staticline10; + wxBoxSizer* bSizerStatusRightDirectories; + wxStaticBitmap* m_bitmapSmallDirectoryRight; + wxStaticText* m_staticTextStatusRightDirs; + wxBoxSizer* bSizerStatusRightFiles; + wxStaticBitmap* m_bitmapSmallFileRight; + wxStaticText* m_staticTextStatusRightFiles; + wxStaticText* m_staticTextStatusRightBytes; + wxStaticText* m_staticTextFullStatus; + wxPanel* m_panelSearch; + wxBitmapButton* m_bpButtonHideSearch; + wxStaticText* m_staticText101; + wxTextCtrl* m_textCtrlSearchTxt; + wxCheckBox* m_checkBoxMatchCase; + wxPanel* m_panelLog; + wxBoxSizer* bSizerLog; + wxBoxSizer* bSizer42; + wxFlexGridSizer* ffgSizer11; + wxFlexGridSizer* ffgSizer111; + wxFlexGridSizer* ffgSizer112; + wxStaticLine* m_staticline70; + wxPanel* m_panelConfig; + wxBoxSizer* bSizerConfig; + wxBoxSizer* bSizerCfgHistoryButtons; + wxBitmapButton* m_bpButtonNew; + wxStaticText* m_staticText951; + wxBitmapButton* m_bpButtonOpen; + wxStaticText* m_staticText95; + wxBitmapButton* m_bpButtonSave; + wxStaticText* m_staticText961; + wxBoxSizer* bSizerSaveAs; + wxBitmapButton* m_bpButtonSaveAs; + wxBitmapButton* m_bpButtonSaveAsBatch; + wxStaticText* m_staticText97; + wxStaticLine* m_staticline81; + zen::Grid* m_gridCfgHistory; + wxPanel* m_panelViewFilter; + wxBoxSizer* bSizerViewFilter; + wxBitmapButton* m_bpButtonToggleLog; + wxBoxSizer* bSizerViewButtons; + zen::ToggleButton* m_bpButtonViewType; + zen::ToggleButton* m_bpButtonShowExcluded; + zen::ToggleButton* m_bpButtonShowDeleteLeft; + zen::ToggleButton* m_bpButtonShowUpdateLeft; + zen::ToggleButton* m_bpButtonShowCreateLeft; + zen::ToggleButton* m_bpButtonShowLeftOnly; + zen::ToggleButton* m_bpButtonShowLeftNewer; + zen::ToggleButton* m_bpButtonShowEqual; + zen::ToggleButton* m_bpButtonShowDoNothing; + zen::ToggleButton* m_bpButtonShowDifferent; + zen::ToggleButton* m_bpButtonShowRightNewer; + zen::ToggleButton* m_bpButtonShowRightOnly; + zen::ToggleButton* m_bpButtonShowCreateRight; + zen::ToggleButton* m_bpButtonShowUpdateRight; + zen::ToggleButton* m_bpButtonShowDeleteRight; + zen::ToggleButton* m_bpButtonShowConflict; + wxBitmapButton* m_bpButtonViewFilterContext; + wxStaticText* m_staticText96; + wxPanel* m_panelStatistics; + wxBoxSizer* bSizer1801; + wxStaticBitmap* m_bitmapDeleteLeft; + wxStaticText* m_staticTextDeleteLeft; + wxStaticBitmap* m_bitmapUpdateLeft; + wxStaticText* m_staticTextUpdateLeft; + wxStaticBitmap* m_bitmapCreateLeft; + wxStaticText* m_staticTextCreateLeft; + wxStaticBitmap* m_bitmapData; + wxStaticText* m_staticTextData; + wxStaticBitmap* m_bitmapCreateRight; + wxStaticText* m_staticTextCreateRight; + wxStaticBitmap* m_bitmapUpdateRight; + wxStaticText* m_staticTextUpdateRight; + wxStaticBitmap* m_bitmapDeleteRight; + wxStaticText* m_staticTextDeleteRight; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onConfigNew( wxCommandEvent& event ) { event.Skip(); } + virtual void onConfigLoad( wxCommandEvent& event ) { event.Skip(); } + virtual void onConfigSave( wxCommandEvent& event ) { event.Skip(); } + virtual void onConfigSaveAs( wxCommandEvent& event ) { event.Skip(); } + virtual void onSaveAsBatchJob( wxCommandEvent& event ) { event.Skip(); } + virtual void onMenuQuit( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleLog( wxCommandEvent& event ) { event.Skip(); } + virtual void onCompare( wxCommandEvent& event ) { event.Skip(); } + virtual void onCmpSettings( wxCommandEvent& event ) { event.Skip(); } + virtual void onConfigureFilter( wxCommandEvent& event ) { event.Skip(); } + virtual void onSyncSettings( wxCommandEvent& event ) { event.Skip(); } + virtual void onStartSync( wxCommandEvent& event ) { event.Skip(); } + virtual void onMenuOptions( wxCommandEvent& event ) { event.Skip(); } + virtual void onMenuFindItem( wxCommandEvent& event ) { event.Skip(); } + virtual void onMenuExportFileList( wxCommandEvent& event ) { event.Skip(); } + virtual void onMenuResetLayout( wxCommandEvent& event ) { event.Skip(); } + virtual void onShowHelp( wxCommandEvent& event ) { event.Skip(); } + virtual void onMenuCheckVersion( wxCommandEvent& event ) { event.Skip(); } + virtual void onMenuCheckVersionAutomatically( wxCommandEvent& event ) { event.Skip(); } + virtual void onMenuAbout( wxCommandEvent& event ) { event.Skip(); } + virtual void onCompSettingsContextMouse( wxMouseEvent& event ) { event.Skip(); } + virtual void onCompSettingsContext( wxCommandEvent& event ) { event.Skip(); } + virtual void onGlobalFilterContextMouse( wxMouseEvent& event ) { event.Skip(); } + virtual void onGlobalFilterContext( wxCommandEvent& event ) { event.Skip(); } + virtual void onSyncSettingsContextMouse( wxMouseEvent& event ) { event.Skip(); } + virtual void onSyncSettingsContext( wxCommandEvent& event ) { event.Skip(); } + virtual void onTopFolderPairAdd( wxCommandEvent& event ) { event.Skip(); } + virtual void onTopFolderPairRemove( wxCommandEvent& event ) { event.Skip(); } + virtual void onSwapSides( wxCommandEvent& event ) { event.Skip(); } + virtual void onTopLocalCompCfg( wxCommandEvent& event ) { event.Skip(); } + virtual void onTopLocalFilterCfg( wxCommandEvent& event ) { event.Skip(); } + virtual void onTopLocalSyncCfg( wxCommandEvent& event ) { event.Skip(); } + virtual void onHideSearchPanel( wxCommandEvent& event ) { event.Skip(); } + virtual void onSearchGridEnter( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleViewType( wxCommandEvent& event ) { event.Skip(); } + virtual void onViewTypeContextMouse( wxMouseEvent& event ) { event.Skip(); } + virtual void onToggleViewButton( wxCommandEvent& event ) { event.Skip(); } + virtual void onViewFilterContextMouse( wxMouseEvent& event ) { event.Skip(); } + virtual void onViewFilterContext( wxCommandEvent& event ) { event.Skip(); } + + +public: + wxPanel* m_panelTopLeft; + wxBitmapButton* m_bpButtonRemovePair; + fff::FolderHistoryBox* m_folderPathLeft; + wxBitmapButton* m_bpButtonSelectAltFolderLeft; + wxBitmapButton* m_bpButtonLocalCompCfg; + wxBitmapButton* m_bpButtonLocalFilter; + wxBitmapButton* m_bpButtonLocalSyncCfg; + wxPanel* m_panelTopRight; + fff::FolderHistoryBox* m_folderPathRight; + wxBitmapButton* m_bpButtonSelectAltFolderRight; + wxStaticBitmap* m_bitmapSyncResult; + wxStaticText* m_staticTextSyncResult; + wxStaticText* m_staticTextProcessed; + wxStaticText* m_staticTextRemaining; + wxPanel* m_panelItemStats; + wxStaticBitmap* m_bitmapItemStat; + wxStaticText* m_staticTextItemsProcessed; + wxStaticText* m_staticTextBytesProcessed; + wxStaticText* m_staticTextItemsRemaining; + wxStaticText* m_staticTextBytesRemaining; + wxPanel* m_panelTimeStats; + wxStaticBitmap* m_bitmapTimeStat; + wxStaticText* m_staticTextTimeElapsed; + wxBoxSizer* bSizerStatistics; + wxBoxSizer* bSizerData; + + MainDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); + + ~MainDialogGenerated(); }; @@ -296,29 +296,29 @@ class MainDialogGenerated : public wxFrame /////////////////////////////////////////////////////////////////////////////// class FolderPairPanelGenerated : public wxPanel { - private: - - protected: - wxButton* m_buttonSelectFolderLeft; - wxButton* m_buttonSelectFolderRight; - - public: - wxPanel* m_panelLeft; - wxBitmapButton* m_bpButtonFolderPairOptions; - wxBitmapButton* m_bpButtonRemovePair; - fff::FolderHistoryBox* m_folderPathLeft; - wxBitmapButton* m_bpButtonSelectAltFolderLeft; - wxPanel* m_panel20; - wxBitmapButton* m_bpButtonLocalCompCfg; - wxBitmapButton* m_bpButtonLocalFilter; - wxBitmapButton* m_bpButtonLocalSyncCfg; - wxPanel* m_panelRight; - fff::FolderHistoryBox* m_folderPathRight; - wxBitmapButton* m_bpButtonSelectAltFolderRight; - - FolderPairPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 698,67 ), long style = 0, const wxString& name = wxEmptyString ); - - ~FolderPairPanelGenerated(); +private: + +protected: + wxButton* m_buttonSelectFolderLeft; + wxButton* m_buttonSelectFolderRight; + +public: + wxPanel* m_panelLeft; + wxBitmapButton* m_bpButtonFolderPairOptions; + wxBitmapButton* m_bpButtonRemovePair; + fff::FolderHistoryBox* m_folderPathLeft; + wxBitmapButton* m_bpButtonSelectAltFolderLeft; + wxPanel* m_panel20; + wxBitmapButton* m_bpButtonLocalCompCfg; + wxBitmapButton* m_bpButtonLocalFilter; + wxBitmapButton* m_bpButtonLocalSyncCfg; + wxPanel* m_panelRight; + fff::FolderHistoryBox* m_folderPathRight; + wxBitmapButton* m_bpButtonSelectAltFolderRight; + + FolderPairPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 698, 67 ), long style = 0, const wxString& name = wxEmptyString ); + + ~FolderPairPanelGenerated(); }; @@ -327,235 +327,235 @@ class FolderPairPanelGenerated : public wxPanel /////////////////////////////////////////////////////////////////////////////// class ConfigDlgGenerated : public wxDialog { - private: - - protected: - wxStaticText* m_staticTextFolderPairLabel; - wxListBox* m_listBoxFolderPair; - wxNotebook* m_notebook; - wxPanel* m_panelCompSettingsTab; - wxBoxSizer* bSizerHeaderCompSettings; - wxStaticText* m_staticTextMainCompSettings; - wxCheckBox* m_checkBoxUseLocalCmpOptions; - wxStaticLine* m_staticlineCompHeader; - wxPanel* m_panelComparisonSettings; - wxStaticText* m_staticText91; - zen::ToggleButton* m_buttonByTimeSize; - zen::ToggleButton* m_buttonByContent; - zen::ToggleButton* m_buttonBySize; - wxStaticBitmap* m_bitmapCompVariant; - wxStaticText* m_staticTextCompVarDescription; - wxStaticLine* m_staticline33; - wxCheckBox* m_checkBoxSymlinksInclude; - wxRadioButton* m_radioBtnSymlinksFollow; - wxRadioButton* m_radioBtnSymlinksDirect; - wxHyperlinkCtrl* m_hyperlink24; - wxStaticLine* m_staticline44; - wxStaticText* m_staticText112; - wxTextCtrl* m_textCtrlTimeShift; - wxStaticText* m_staticText1381; - wxStaticText* m_staticText13811; - wxHyperlinkCtrl* m_hyperlink241; - wxStaticLine* m_staticline331; - wxBoxSizer* bSizerCompMisc; - wxStaticLine* m_staticline3311; - wxStaticBitmap* m_bitmapIgnoreErrors; - wxCheckBox* m_checkBoxIgnoreErrors; - wxCheckBox* m_checkBoxAutoRetry; - wxFlexGridSizer* fgSizerAutoRetry; - wxStaticText* m_staticText96; - wxStaticText* m_staticTextAutoRetryDelay; - wxSpinCtrl* m_spinCtrlAutoRetryCount; - wxSpinCtrl* m_spinCtrlAutoRetryDelay; - wxStaticLine* m_staticline751; - wxBoxSizer* bSizerPerformance; - wxPanel* m_panel57; - wxStaticBitmap* m_bitmapPerf; - wxStaticText* m_staticText13611; - wxHyperlinkCtrl* m_hyperlinkPerfDeRequired; - wxBoxSizer* bSizer260; - wxStaticText* m_staticTextPerfParallelOps; - wxScrolledWindow* m_scrolledWindowPerf; - wxFlexGridSizer* fgSizerPerf; - wxHyperlinkCtrl* m_hyperlink1711; - wxPanel* m_panelFilterSettingsTab; - wxBoxSizer* bSizerHeaderFilterSettings; - wxStaticText* m_staticTextMainFilterSettings; - wxStaticText* m_staticTextLocalFilterSettings; - wxStaticLine* m_staticlineFilterHeader; - wxStaticBitmap* m_bitmapInclude; - wxStaticText* m_staticText78; - wxTextCtrl* m_textCtrlInclude; - wxStaticBitmap* m_bitmapExclude; - wxStaticText* m_staticText77; - wxHyperlinkCtrl* m_hyperlink171; - wxTextCtrl* m_textCtrlExclude; - wxStaticLine* m_staticline24; - wxStaticBitmap* m_bitmapFilterSize; - wxStaticText* m_staticText80; - wxStaticText* m_staticText101; - wxSpinCtrl* m_spinCtrlMinSize; - wxChoice* m_choiceUnitMinSize; - wxStaticText* m_staticText102; - wxSpinCtrl* m_spinCtrlMaxSize; - wxChoice* m_choiceUnitMaxSize; - wxStaticLine* m_staticline23; - wxStaticBitmap* m_bitmapFilterDate; - wxStaticText* m_staticText79; - wxChoice* m_choiceUnitTimespan; - wxSpinCtrl* m_spinCtrlTimespan; - wxStaticLine* m_staticline231; - wxButton* m_buttonDefault; - wxBitmapButton* m_bpButtonDefaultContext; - wxButton* m_buttonClear; - wxPanel* m_panelSyncSettingsTab; - wxBoxSizer* bSizerHeaderSyncSettings; - wxStaticText* m_staticTextMainSyncSettings; - wxCheckBox* m_checkBoxUseLocalSyncOptions; - wxStaticLine* m_staticlineSyncHeader; - wxPanel* m_panelSyncSettings; - wxStaticText* m_staticText86; - zen::ToggleButton* m_buttonTwoWay; - zen::ToggleButton* m_buttonMirror; - zen::ToggleButton* m_buttonUpdate; - zen::ToggleButton* m_buttonCustom; - wxBoxSizer* bSizerSyncDirHolder; - wxBoxSizer* bSizerSyncDirections; - wxStaticText* m_staticText184; - wxFlexGridSizer* ffgSizer11; - wxStaticBitmap* m_bitmapLeftOnly; - wxStaticBitmap* m_bitmapLeftNewer; - wxStaticBitmap* m_bitmapDifferent; - wxStaticBitmap* m_bitmapConflict; - wxStaticBitmap* m_bitmapRightNewer; - wxStaticBitmap* m_bitmapRightOnly; - wxBitmapButton* m_bpButtonLeftOnly; - wxBitmapButton* m_bpButtonLeftNewer; - wxBitmapButton* m_bpButtonDifferent; - wxBitmapButton* m_bpButtonConflict; - wxBitmapButton* m_bpButtonRightNewer; - wxBitmapButton* m_bpButtonRightOnly; - wxStaticText* m_staticText120; - wxBoxSizer* bSizerDatabase; - wxStaticBitmap* m_bitmapDatabase; - wxStaticText* m_staticText145; - wxStaticText* m_staticTextSyncVarDescription; - wxStaticLine* m_staticline431; - wxStaticLine* m_staticline72; - wxCheckBox* m_checkBoxDetectMove; - wxHyperlinkCtrl* m_hyperlink242; - wxStaticLine* m_staticline54; - wxBoxSizer* bSizer2361; - wxStaticText* m_staticText87; - zen::ToggleButton* m_buttonRecycler; - zen::ToggleButton* m_buttonPermanent; - zen::ToggleButton* m_buttonVersioning; - wxBoxSizer* bSizerVersioningHolder; - wxStaticBitmap* m_bitmapDeletionType; - wxStaticText* m_staticTextDeletionTypeDescription; - wxPanel* m_panelVersioning; - wxStaticBitmap* m_bitmapVersioning; - wxStaticText* m_staticText155; - wxHyperlinkCtrl* m_hyperlink243; - fff::FolderHistoryBox* m_versioningFolderPath; - wxButton* m_buttonSelectVersioningFolder; - wxStaticText* m_staticText93; - wxChoice* m_choiceVersioningStyle; - wxStaticText* m_staticTextNamingCvtPart1; - wxStaticText* m_staticTextNamingCvtPart2Bold; - wxStaticText* m_staticTextNamingCvtPart3; - wxStaticLine* m_staticline69; - wxStaticText* m_staticTextLimitVersions; - wxFlexGridSizer* fgSizer15; - wxCheckBox* m_checkBoxVersionMaxDays; - wxCheckBox* m_checkBoxVersionCountMin; - wxCheckBox* m_checkBoxVersionCountMax; - wxSpinCtrl* m_spinCtrlVersionMaxDays; - wxSpinCtrl* m_spinCtrlVersionCountMin; - wxSpinCtrl* m_spinCtrlVersionCountMax; - wxStaticLine* m_staticline582; - wxBoxSizer* bSizerSyncMisc; - wxStaticBitmap* m_bitmapEmail; - wxCheckBox* m_checkBoxSendEmail; - fff::CommandBox* m_comboBoxEmail; - wxBitmapButton* m_bpButtonEmailAlways; - wxBitmapButton* m_bpButtonEmailErrorWarning; - wxBitmapButton* m_bpButtonEmailErrorOnly; - wxHyperlinkCtrl* m_hyperlinkPerfDeRequired2; - wxStaticLine* m_staticline57; - wxPanel* m_panelLogfile; - wxStaticBitmap* m_bitmapLogFile; - wxCheckBox* m_checkBoxOverrideLogPath; - wxButton* m_buttonSelectLogFolder; - wxStaticLine* m_staticline80; - wxStaticText* m_staticTextPostSync; - fff::CommandBox* m_comboBoxPostSyncCommand; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonOkay; - wxButton* m_buttonCancel; - - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onListBoxKeyEvent( wxKeyEvent& event ) { event.Skip(); } - virtual void onSelectFolderPair( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleLocalCompSettings( wxCommandEvent& event ) { event.Skip(); } - virtual void onCompByTimeSize( wxCommandEvent& event ) { event.Skip(); } - virtual void onCompByTimeSizeDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void onCompByContent( wxCommandEvent& event ) { event.Skip(); } - virtual void onCompByContentDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void onCompBySize( wxCommandEvent& event ) { event.Skip(); } - virtual void onCompBySizeDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void onChangeCompOption( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleIgnoreErrors( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleAutoRetry( wxCommandEvent& event ) { event.Skip(); } - virtual void onChangeFilterOption( wxCommandEvent& event ) { event.Skip(); } - virtual void onFilterDefault( wxCommandEvent& event ) { event.Skip(); } - virtual void onFilterDefaultContextMouse( wxMouseEvent& event ) { event.Skip(); } - virtual void onFilterDefaultContext( wxCommandEvent& event ) { event.Skip(); } - virtual void onFilterClear( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleLocalSyncSettings( wxCommandEvent& event ) { event.Skip(); } - virtual void onSyncTwoWay( wxCommandEvent& event ) { event.Skip(); } - virtual void onSyncTwoWayDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void onSyncMirror( wxCommandEvent& event ) { event.Skip(); } - virtual void onSyncMirrorDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void onSyncUpdate( wxCommandEvent& event ) { event.Skip(); } - virtual void onSyncUpdateDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void onSyncCustom( wxCommandEvent& event ) { event.Skip(); } - virtual void onSyncCustomDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void onExLeftSideOnly( wxCommandEvent& event ) { event.Skip(); } - virtual void onLeftNewer( wxCommandEvent& event ) { event.Skip(); } - virtual void onDifferent( wxCommandEvent& event ) { event.Skip(); } - virtual void onConflict( wxCommandEvent& event ) { event.Skip(); } - virtual void onRightNewer( wxCommandEvent& event ) { event.Skip(); } - virtual void onExRightSideOnly( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleDetectMovedFiles( wxCommandEvent& event ) { event.Skip(); } - virtual void onDeletionRecycler( wxCommandEvent& event ) { event.Skip(); } - virtual void onDeletionPermanent( wxCommandEvent& event ) { event.Skip(); } - virtual void onDeletionVersioning( wxCommandEvent& event ) { event.Skip(); } - virtual void onChanegVersioningStyle( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleVersioningLimit( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleMiscEmail( wxCommandEvent& event ) { event.Skip(); } - virtual void onEmailAlways( wxCommandEvent& event ) { event.Skip(); } - virtual void onEmailErrorWarning( wxCommandEvent& event ) { event.Skip(); } - virtual void onEmailErrorOnly( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleMiscOption( wxCommandEvent& event ) { event.Skip(); } - virtual void onShowLogFolder( wxCommandEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - - - public: - wxStaticBitmap* m_bitmapRetryErrors; - wxStaticText* m_staticTextFilterDescr; - wxBitmapButton* m_bpButtonSelectVersioningAltFolder; - wxBitmapButton* m_bpButtonShowLogFolder; - fff::FolderHistoryBox* m_logFolderPath; - wxBitmapButton* m_bpButtonSelectAltLogFolder; - wxChoice* m_choicePostSyncCondition; - - ConfigDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Synchronization Settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); - - ~ConfigDlgGenerated(); +private: + +protected: + wxStaticText* m_staticTextFolderPairLabel; + wxListBox* m_listBoxFolderPair; + wxNotebook* m_notebook; + wxPanel* m_panelCompSettingsTab; + wxBoxSizer* bSizerHeaderCompSettings; + wxStaticText* m_staticTextMainCompSettings; + wxCheckBox* m_checkBoxUseLocalCmpOptions; + wxStaticLine* m_staticlineCompHeader; + wxPanel* m_panelComparisonSettings; + wxStaticText* m_staticText91; + zen::ToggleButton* m_buttonByTimeSize; + zen::ToggleButton* m_buttonByContent; + zen::ToggleButton* m_buttonBySize; + wxStaticBitmap* m_bitmapCompVariant; + wxStaticText* m_staticTextCompVarDescription; + wxStaticLine* m_staticline33; + wxCheckBox* m_checkBoxSymlinksInclude; + wxRadioButton* m_radioBtnSymlinksFollow; + wxRadioButton* m_radioBtnSymlinksDirect; + wxHyperlinkCtrl* m_hyperlink24; + wxStaticLine* m_staticline44; + wxStaticText* m_staticText112; + wxTextCtrl* m_textCtrlTimeShift; + wxStaticText* m_staticText1381; + wxStaticText* m_staticText13811; + wxHyperlinkCtrl* m_hyperlink241; + wxStaticLine* m_staticline331; + wxBoxSizer* bSizerCompMisc; + wxStaticLine* m_staticline3311; + wxStaticBitmap* m_bitmapIgnoreErrors; + wxCheckBox* m_checkBoxIgnoreErrors; + wxCheckBox* m_checkBoxAutoRetry; + wxFlexGridSizer* fgSizerAutoRetry; + wxStaticText* m_staticText96; + wxStaticText* m_staticTextAutoRetryDelay; + wxSpinCtrl* m_spinCtrlAutoRetryCount; + wxSpinCtrl* m_spinCtrlAutoRetryDelay; + wxStaticLine* m_staticline751; + wxBoxSizer* bSizerPerformance; + wxPanel* m_panel57; + wxStaticBitmap* m_bitmapPerf; + wxStaticText* m_staticText13611; + wxHyperlinkCtrl* m_hyperlinkPerfDeRequired; + wxBoxSizer* bSizer260; + wxStaticText* m_staticTextPerfParallelOps; + wxScrolledWindow* m_scrolledWindowPerf; + wxFlexGridSizer* fgSizerPerf; + wxHyperlinkCtrl* m_hyperlink1711; + wxPanel* m_panelFilterSettingsTab; + wxBoxSizer* bSizerHeaderFilterSettings; + wxStaticText* m_staticTextMainFilterSettings; + wxStaticText* m_staticTextLocalFilterSettings; + wxStaticLine* m_staticlineFilterHeader; + wxStaticBitmap* m_bitmapInclude; + wxStaticText* m_staticText78; + wxTextCtrl* m_textCtrlInclude; + wxStaticBitmap* m_bitmapExclude; + wxStaticText* m_staticText77; + wxHyperlinkCtrl* m_hyperlink171; + wxTextCtrl* m_textCtrlExclude; + wxStaticLine* m_staticline24; + wxStaticBitmap* m_bitmapFilterSize; + wxStaticText* m_staticText80; + wxStaticText* m_staticText101; + wxSpinCtrl* m_spinCtrlMinSize; + wxChoice* m_choiceUnitMinSize; + wxStaticText* m_staticText102; + wxSpinCtrl* m_spinCtrlMaxSize; + wxChoice* m_choiceUnitMaxSize; + wxStaticLine* m_staticline23; + wxStaticBitmap* m_bitmapFilterDate; + wxStaticText* m_staticText79; + wxChoice* m_choiceUnitTimespan; + wxSpinCtrl* m_spinCtrlTimespan; + wxStaticLine* m_staticline231; + wxButton* m_buttonDefault; + wxBitmapButton* m_bpButtonDefaultContext; + wxButton* m_buttonClear; + wxPanel* m_panelSyncSettingsTab; + wxBoxSizer* bSizerHeaderSyncSettings; + wxStaticText* m_staticTextMainSyncSettings; + wxCheckBox* m_checkBoxUseLocalSyncOptions; + wxStaticLine* m_staticlineSyncHeader; + wxPanel* m_panelSyncSettings; + wxStaticText* m_staticText86; + zen::ToggleButton* m_buttonTwoWay; + zen::ToggleButton* m_buttonMirror; + zen::ToggleButton* m_buttonUpdate; + zen::ToggleButton* m_buttonCustom; + wxBoxSizer* bSizerSyncDirHolder; + wxBoxSizer* bSizerSyncDirections; + wxStaticText* m_staticText184; + wxFlexGridSizer* ffgSizer11; + wxStaticBitmap* m_bitmapLeftOnly; + wxStaticBitmap* m_bitmapLeftNewer; + wxStaticBitmap* m_bitmapDifferent; + wxStaticBitmap* m_bitmapConflict; + wxStaticBitmap* m_bitmapRightNewer; + wxStaticBitmap* m_bitmapRightOnly; + wxBitmapButton* m_bpButtonLeftOnly; + wxBitmapButton* m_bpButtonLeftNewer; + wxBitmapButton* m_bpButtonDifferent; + wxBitmapButton* m_bpButtonConflict; + wxBitmapButton* m_bpButtonRightNewer; + wxBitmapButton* m_bpButtonRightOnly; + wxStaticText* m_staticText120; + wxBoxSizer* bSizerDatabase; + wxStaticBitmap* m_bitmapDatabase; + wxStaticText* m_staticText145; + wxStaticText* m_staticTextSyncVarDescription; + wxStaticLine* m_staticline431; + wxStaticLine* m_staticline72; + wxCheckBox* m_checkBoxDetectMove; + wxHyperlinkCtrl* m_hyperlink242; + wxStaticLine* m_staticline54; + wxBoxSizer* bSizer2361; + wxStaticText* m_staticText87; + zen::ToggleButton* m_buttonRecycler; + zen::ToggleButton* m_buttonPermanent; + zen::ToggleButton* m_buttonVersioning; + wxBoxSizer* bSizerVersioningHolder; + wxStaticBitmap* m_bitmapDeletionType; + wxStaticText* m_staticTextDeletionTypeDescription; + wxPanel* m_panelVersioning; + wxStaticBitmap* m_bitmapVersioning; + wxStaticText* m_staticText155; + wxHyperlinkCtrl* m_hyperlink243; + fff::FolderHistoryBox* m_versioningFolderPath; + wxButton* m_buttonSelectVersioningFolder; + wxStaticText* m_staticText93; + wxChoice* m_choiceVersioningStyle; + wxStaticText* m_staticTextNamingCvtPart1; + wxStaticText* m_staticTextNamingCvtPart2Bold; + wxStaticText* m_staticTextNamingCvtPart3; + wxStaticLine* m_staticline69; + wxStaticText* m_staticTextLimitVersions; + wxFlexGridSizer* fgSizer15; + wxCheckBox* m_checkBoxVersionMaxDays; + wxCheckBox* m_checkBoxVersionCountMin; + wxCheckBox* m_checkBoxVersionCountMax; + wxSpinCtrl* m_spinCtrlVersionMaxDays; + wxSpinCtrl* m_spinCtrlVersionCountMin; + wxSpinCtrl* m_spinCtrlVersionCountMax; + wxStaticLine* m_staticline582; + wxBoxSizer* bSizerSyncMisc; + wxStaticBitmap* m_bitmapEmail; + wxCheckBox* m_checkBoxSendEmail; + fff::CommandBox* m_comboBoxEmail; + wxBitmapButton* m_bpButtonEmailAlways; + wxBitmapButton* m_bpButtonEmailErrorWarning; + wxBitmapButton* m_bpButtonEmailErrorOnly; + wxHyperlinkCtrl* m_hyperlinkPerfDeRequired2; + wxStaticLine* m_staticline57; + wxPanel* m_panelLogfile; + wxStaticBitmap* m_bitmapLogFile; + wxCheckBox* m_checkBoxOverrideLogPath; + wxButton* m_buttonSelectLogFolder; + wxStaticLine* m_staticline80; + wxStaticText* m_staticTextPostSync; + fff::CommandBox* m_comboBoxPostSyncCommand; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonOkay; + wxButton* m_buttonCancel; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onListBoxKeyEvent( wxKeyEvent& event ) { event.Skip(); } + virtual void onSelectFolderPair( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleLocalCompSettings( wxCommandEvent& event ) { event.Skip(); } + virtual void onCompByTimeSize( wxCommandEvent& event ) { event.Skip(); } + virtual void onCompByTimeSizeDouble( wxMouseEvent& event ) { event.Skip(); } + virtual void onCompByContent( wxCommandEvent& event ) { event.Skip(); } + virtual void onCompByContentDouble( wxMouseEvent& event ) { event.Skip(); } + virtual void onCompBySize( wxCommandEvent& event ) { event.Skip(); } + virtual void onCompBySizeDouble( wxMouseEvent& event ) { event.Skip(); } + virtual void onChangeCompOption( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleIgnoreErrors( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleAutoRetry( wxCommandEvent& event ) { event.Skip(); } + virtual void onChangeFilterOption( wxCommandEvent& event ) { event.Skip(); } + virtual void onFilterDefault( wxCommandEvent& event ) { event.Skip(); } + virtual void onFilterDefaultContextMouse( wxMouseEvent& event ) { event.Skip(); } + virtual void onFilterDefaultContext( wxCommandEvent& event ) { event.Skip(); } + virtual void onFilterClear( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleLocalSyncSettings( wxCommandEvent& event ) { event.Skip(); } + virtual void onSyncTwoWay( wxCommandEvent& event ) { event.Skip(); } + virtual void onSyncTwoWayDouble( wxMouseEvent& event ) { event.Skip(); } + virtual void onSyncMirror( wxCommandEvent& event ) { event.Skip(); } + virtual void onSyncMirrorDouble( wxMouseEvent& event ) { event.Skip(); } + virtual void onSyncUpdate( wxCommandEvent& event ) { event.Skip(); } + virtual void onSyncUpdateDouble( wxMouseEvent& event ) { event.Skip(); } + virtual void onSyncCustom( wxCommandEvent& event ) { event.Skip(); } + virtual void onSyncCustomDouble( wxMouseEvent& event ) { event.Skip(); } + virtual void onExLeftSideOnly( wxCommandEvent& event ) { event.Skip(); } + virtual void onLeftNewer( wxCommandEvent& event ) { event.Skip(); } + virtual void onDifferent( wxCommandEvent& event ) { event.Skip(); } + virtual void onConflict( wxCommandEvent& event ) { event.Skip(); } + virtual void onRightNewer( wxCommandEvent& event ) { event.Skip(); } + virtual void onExRightSideOnly( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleDetectMovedFiles( wxCommandEvent& event ) { event.Skip(); } + virtual void onDeletionRecycler( wxCommandEvent& event ) { event.Skip(); } + virtual void onDeletionPermanent( wxCommandEvent& event ) { event.Skip(); } + virtual void onDeletionVersioning( wxCommandEvent& event ) { event.Skip(); } + virtual void onChanegVersioningStyle( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleVersioningLimit( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleMiscEmail( wxCommandEvent& event ) { event.Skip(); } + virtual void onEmailAlways( wxCommandEvent& event ) { event.Skip(); } + virtual void onEmailErrorWarning( wxCommandEvent& event ) { event.Skip(); } + virtual void onEmailErrorOnly( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleMiscOption( wxCommandEvent& event ) { event.Skip(); } + virtual void onShowLogFolder( wxCommandEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + + +public: + wxStaticBitmap* m_bitmapRetryErrors; + wxStaticText* m_staticTextFilterDescr; + wxBitmapButton* m_bpButtonSelectVersioningAltFolder; + wxBitmapButton* m_bpButtonShowLogFolder; + fff::FolderHistoryBox* m_logFolderPath; + wxBitmapButton* m_bpButtonSelectAltLogFolder; + wxChoice* m_choicePostSyncCondition; + + ConfigDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Synchronization Settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); + + ~ConfigDlgGenerated(); }; @@ -564,114 +564,117 @@ class ConfigDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class CloudSetupDlgGenerated : public wxDialog { - private: - - protected: - wxStaticBitmap* m_bitmapCloud; - wxStaticText* m_staticText136; - wxToggleButton* m_toggleBtnGdrive; - wxToggleButton* m_toggleBtnSftp; - wxToggleButton* m_toggleBtnFtp; - wxStaticLine* m_staticline371; - wxPanel* m_panel41; - wxBoxSizer* bSizerGdrive; - wxStaticBitmap* m_bitmapGdriveUser; - wxStaticText* m_staticText166; - wxListBox* m_listBoxGdriveUsers; - zen::BitmapTextButton* m_buttonGdriveAddUser; - zen::BitmapTextButton* m_buttonGdriveRemoveUser; - wxStaticLine* m_staticline841; - wxStaticBitmap* m_bitmapGdriveDrive; - wxStaticText* m_staticText186; - wxListBox* m_listBoxGdriveDrives; - wxStaticLine* m_staticline73; - wxBoxSizer* bSizerServer; - wxStaticBitmap* m_bitmapServer; - wxStaticText* m_staticText12311; - wxTextCtrl* m_textCtrlServer; - wxStaticText* m_staticText1233; - wxTextCtrl* m_textCtrlPort; - wxStaticLine* m_staticline58; - wxBoxSizer* bSizerAuth; - wxBoxSizer* bSizerAuthInner; - wxBoxSizer* bSizerFtpEncrypt; - wxStaticText* m_staticText1251; - wxRadioButton* m_radioBtnEncryptNone; - wxRadioButton* m_radioBtnEncryptSsl; - wxStaticLine* m_staticline5721; - wxBoxSizer* bSizerSftpAuth; - wxStaticText* m_staticText125; - wxRadioButton* m_radioBtnPassword; - wxRadioButton* m_radioBtnKeyfile; - wxRadioButton* m_radioBtnAgent; - wxStaticLine* m_staticline572; - wxPanel* m_panelAuth; - wxStaticText* m_staticText123; - wxTextCtrl* m_textCtrlUserName; - wxStaticText* m_staticTextKeyfile; - wxBoxSizer* bSizerKeyFile; - wxTextCtrl* m_textCtrlKeyfilePath; - wxButton* m_buttonSelectKeyfile; - wxStaticText* m_staticTextPassword; - wxBoxSizer* bSizerPassword; - wxTextCtrl* m_textCtrlPasswordVisible; - wxTextCtrl* m_textCtrlPasswordHidden; - wxCheckBox* m_checkBoxShowPassword; - wxStaticLine* m_staticline581; - wxStaticBitmap* m_bitmapServerDir; - wxStaticText* m_staticText1232; - wxStaticLine* m_staticline83; - wxStaticText* m_staticTextTimeout; - wxSpinCtrl* m_spinCtrlTimeout; - wxStaticLine* m_staticline82; - wxTextCtrl* m_textCtrlServerPath; - wxButton* m_buttonSelectFolder; - wxStaticLine* m_staticline571; - wxStaticBitmap* m_bitmapPerf; - wxStaticText* m_staticText1361; - wxHyperlinkCtrl* m_hyperlink171; - wxStaticLine* m_staticline57; - wxPanel* m_panel411; - wxBoxSizer* bSizerConnectionsLabel; - wxStaticText* m_staticTextConnectionsLabel; - wxStaticText* m_staticTextConnectionsLabelSub; - wxSpinCtrl* m_spinCtrlConnectionCount; - wxStaticText* m_staticTextConnectionCountDescr; - wxHyperlinkCtrl* m_hyperlinkDeRequired; - wxStaticText* m_staticTextChannelCountSftp; - wxSpinCtrl* m_spinCtrlChannelCountSftp; - wxButton* m_buttonChannelCountSftp; - wxCheckBox* m_checkBoxAllowZlib; - wxStaticText* m_staticTextZlibDescr; - wxStaticLine* m_staticline12; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonOkay; - wxButton* m_buttonCancel; - - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onConnectionGdrive( wxCommandEvent& event ) { event.Skip(); } - virtual void onConnectionSftp( wxCommandEvent& event ) { event.Skip(); } - virtual void onConnectionFtp( wxCommandEvent& event ) { event.Skip(); } - virtual void onGdriveUserSelect( wxCommandEvent& event ) { event.Skip(); } - virtual void onGdriveUserAdd( wxCommandEvent& event ) { event.Skip(); } - virtual void onGdriveUserRemove( wxCommandEvent& event ) { event.Skip(); } - virtual void onAuthPassword( wxCommandEvent& event ) { event.Skip(); } - virtual void onAuthKeyfile( wxCommandEvent& event ) { event.Skip(); } - virtual void onAuthAgent( wxCommandEvent& event ) { event.Skip(); } - virtual void onSelectKeyfile( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleShowPassword( wxCommandEvent& event ) { event.Skip(); } - virtual void onBrowseCloudFolder( wxCommandEvent& event ) { event.Skip(); } - virtual void onDetectServerChannelLimit( wxCommandEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - - - public: - - CloudSetupDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Access Online Storage"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - - ~CloudSetupDlgGenerated(); +private: + +protected: + wxStaticBitmap* m_bitmapCloud; + wxStaticText* m_staticText136; + wxToggleButton* m_toggleBtnGdrive; + wxToggleButton* m_toggleBtnSftp; + wxToggleButton* m_toggleBtnFtp; + wxStaticLine* m_staticline371; + wxPanel* m_panel41; + wxBoxSizer* bSizerGdrive; + wxStaticBitmap* m_bitmapGdriveUser; + wxStaticText* m_staticText166; + wxListBox* m_listBoxGdriveUsers; + zen::BitmapTextButton* m_buttonGdriveAddUser; + zen::BitmapTextButton* m_buttonGdriveRemoveUser; + wxStaticLine* m_staticline841; + wxStaticBitmap* m_bitmapGdriveDrive; + wxStaticText* m_staticText186; + wxListBox* m_listBoxGdriveDrives; + wxStaticLine* m_staticline73; + wxBoxSizer* bSizerServer; + wxStaticBitmap* m_bitmapServer; + wxStaticText* m_staticText12311; + wxTextCtrl* m_textCtrlServer; + wxStaticText* m_staticText1233; + wxTextCtrl* m_textCtrlPort; + wxStaticLine* m_staticline58; + wxBoxSizer* bSizerAuth; + wxBoxSizer* bSizerAuthInner; + wxBoxSizer* bSizerFtpEncrypt; + wxStaticText* m_staticText1251; + wxRadioButton* m_radioBtnEncryptNone; + wxRadioButton* m_radioBtnEncryptSsl; + wxStaticLine* m_staticline5721; + wxBoxSizer* bSizerSftpAuth; + wxStaticText* m_staticText125; + wxRadioButton* m_radioBtnPassword; + wxRadioButton* m_radioBtnKeyfile; + wxRadioButton* m_radioBtnAgent; + wxStaticLine* m_staticline572; + wxPanel* m_panelAuth; + wxStaticText* m_staticText123; + wxTextCtrl* m_textCtrlUserName; + wxStaticText* m_staticTextKeyfile; + wxBoxSizer* bSizerKeyFile; + wxTextCtrl* m_textCtrlKeyfilePath; + wxButton* m_buttonSelectKeyfile; + wxStaticText* m_staticTextPassword; + wxBoxSizer* bSizerPassword; + wxTextCtrl* m_textCtrlPasswordVisible; + wxTextCtrl* m_textCtrlPasswordHidden; + wxCheckBox* m_checkBoxShowPassword; + wxCheckBox* m_checkBoxPasswordPrompt; + wxStaticLine* m_staticline581; + wxStaticBitmap* m_bitmapServerDir; + wxStaticText* m_staticText1232; + wxStaticLine* m_staticline83; + wxStaticText* m_staticTextTimeout; + wxSpinCtrl* m_spinCtrlTimeout; + wxStaticLine* m_staticline82; + wxTextCtrl* m_textCtrlServerPath; + wxButton* m_buttonSelectFolder; + wxStaticLine* m_staticline571; + wxStaticBitmap* m_bitmapPerf; + wxStaticText* m_staticText1361; + wxHyperlinkCtrl* m_hyperlink171; + wxStaticLine* m_staticline57; + wxPanel* m_panel411; + wxBoxSizer* bSizerConnectionsLabel; + wxStaticText* m_staticTextConnectionsLabel; + wxStaticText* m_staticTextConnectionsLabelSub; + wxSpinCtrl* m_spinCtrlConnectionCount; + wxStaticText* m_staticTextConnectionCountDescr; + wxHyperlinkCtrl* m_hyperlinkDeRequired; + wxStaticText* m_staticTextChannelCountSftp; + wxSpinCtrl* m_spinCtrlChannelCountSftp; + wxButton* m_buttonChannelCountSftp; + wxCheckBox* m_checkBoxAllowZlib; + wxStaticText* m_staticTextZlibDescr; + wxStaticLine* m_staticline12; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonOkay; + wxButton* m_buttonCancel; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onConnectionGdrive( wxCommandEvent& event ) { event.Skip(); } + virtual void onConnectionSftp( wxCommandEvent& event ) { event.Skip(); } + virtual void onConnectionFtp( wxCommandEvent& event ) { event.Skip(); } + virtual void onGdriveUserSelect( wxCommandEvent& event ) { event.Skip(); } + virtual void onGdriveUserAdd( wxCommandEvent& event ) { event.Skip(); } + virtual void onGdriveUserRemove( wxCommandEvent& event ) { event.Skip(); } + virtual void onAuthPassword( wxCommandEvent& event ) { event.Skip(); } + virtual void onAuthKeyfile( wxCommandEvent& event ) { event.Skip(); } + virtual void onAuthAgent( wxCommandEvent& event ) { event.Skip(); } + virtual void onSelectKeyfile( wxCommandEvent& event ) { event.Skip(); } + virtual void onTypingPassword( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleShowPassword( wxCommandEvent& event ) { event.Skip(); } + virtual void onTogglePasswordPrompt( wxCommandEvent& event ) { event.Skip(); } + virtual void onBrowseCloudFolder( wxCommandEvent& event ) { event.Skip(); } + virtual void onDetectServerChannelLimit( wxCommandEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + + +public: + + CloudSetupDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Access Online Storage"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + + ~CloudSetupDlgGenerated(); }; @@ -680,29 +683,29 @@ class CloudSetupDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class AbstractFolderPickerGenerated : public wxDialog { - private: +private: - protected: - wxPanel* m_panel41; - wxStaticText* m_staticTextStatus; - wxTreeCtrl* m_treeCtrlFileSystem; - wxStaticLine* m_staticline12; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonOkay; - wxButton* m_buttonCancel; +protected: + wxPanel* m_panel41; + wxStaticText* m_staticTextStatus; + wxTreeCtrl* m_treeCtrlFileSystem; + wxStaticLine* m_staticline12; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonOkay; + wxButton* m_buttonCancel; - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onExpandNode( wxTreeEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onExpandNode( wxTreeEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - public: +public: - AbstractFolderPickerGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select a folder"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); + AbstractFolderPickerGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select a folder"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); - ~AbstractFolderPickerGenerated(); + ~AbstractFolderPickerGenerated(); }; @@ -711,51 +714,51 @@ class AbstractFolderPickerGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class SyncConfirmationDlgGenerated : public wxDialog { - private: - - protected: - wxStaticBitmap* m_bitmapSync; - wxStaticText* m_staticTextCaption; - wxStaticLine* m_staticline371; - wxPanel* m_panelStatistics; - wxStaticLine* m_staticline38; - wxStaticText* m_staticText84; - wxStaticText* m_staticTextSyncVar; - wxStaticBitmap* m_bitmapSyncVar; - wxStaticLine* m_staticline14; - wxStaticText* m_staticText83; - wxStaticBitmap* m_bitmapDeleteLeft; - wxStaticBitmap* m_bitmapUpdateLeft; - wxStaticBitmap* m_bitmapCreateLeft; - wxStaticBitmap* m_bitmapData; - wxStaticBitmap* m_bitmapCreateRight; - wxStaticBitmap* m_bitmapUpdateRight; - wxStaticBitmap* m_bitmapDeleteRight; - wxStaticText* m_staticTextDeleteLeft; - wxStaticText* m_staticTextUpdateLeft; - wxStaticText* m_staticTextCreateLeft; - wxStaticText* m_staticTextData; - wxStaticText* m_staticTextCreateRight; - wxStaticText* m_staticTextUpdateRight; - wxStaticText* m_staticTextDeleteRight; - wxStaticLine* m_staticline381; - wxStaticLine* m_staticline12; - wxCheckBox* m_checkBoxDontShowAgain; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonStartSync; - wxButton* m_buttonCancel; - - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onStartSync( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - - - public: - - SyncConfirmationDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - - ~SyncConfirmationDlgGenerated(); +private: + +protected: + wxStaticBitmap* m_bitmapSync; + wxStaticText* m_staticTextCaption; + wxStaticLine* m_staticline371; + wxPanel* m_panelStatistics; + wxStaticLine* m_staticline38; + wxStaticText* m_staticText84; + wxStaticText* m_staticTextSyncVar; + wxStaticBitmap* m_bitmapSyncVar; + wxStaticLine* m_staticline14; + wxStaticText* m_staticText83; + wxStaticBitmap* m_bitmapDeleteLeft; + wxStaticBitmap* m_bitmapUpdateLeft; + wxStaticBitmap* m_bitmapCreateLeft; + wxStaticBitmap* m_bitmapData; + wxStaticBitmap* m_bitmapCreateRight; + wxStaticBitmap* m_bitmapUpdateRight; + wxStaticBitmap* m_bitmapDeleteRight; + wxStaticText* m_staticTextDeleteLeft; + wxStaticText* m_staticTextUpdateLeft; + wxStaticText* m_staticTextCreateLeft; + wxStaticText* m_staticTextData; + wxStaticText* m_staticTextCreateRight; + wxStaticText* m_staticTextUpdateRight; + wxStaticText* m_staticTextDeleteRight; + wxStaticLine* m_staticline381; + wxStaticLine* m_staticline12; + wxCheckBox* m_checkBoxDontShowAgain; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonStartSync; + wxButton* m_buttonCancel; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onStartSync( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + + +public: + + SyncConfirmationDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + + ~SyncConfirmationDlgGenerated(); }; @@ -764,41 +767,41 @@ class SyncConfirmationDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class CompareProgressDlgGenerated : public wxPanel { - private: - - protected: - wxStaticText* m_staticTextStatus; - wxFlexGridSizer* ffgSizer11; - wxFlexGridSizer* ffgSizer111; - wxFlexGridSizer* ffgSizer112; - wxStaticText* m_staticText1461; - wxStaticText* m_staticTextRetryCount; - wxStaticText* m_staticText146; - wxBoxSizer* bSizerProgressGraph; - wxFlexGridSizer* ffgSizer113; - zen::Graph2D* m_panelProgressGraph; - - public: - wxStaticText* m_staticTextProcessed; - wxStaticText* m_staticTextRemaining; - wxPanel* m_panelItemStats; - wxStaticBitmap* m_bitmapItemStat; - wxStaticText* m_staticTextItemsProcessed; - wxStaticText* m_staticTextBytesProcessed; - wxStaticText* m_staticTextItemsRemaining; - wxStaticText* m_staticTextBytesRemaining; - wxPanel* m_panelTimeStats; - wxStaticBitmap* m_bitmapTimeStat; - wxStaticText* m_staticTextTimeElapsed; - wxStaticText* m_staticTextTimeRemaining; - wxBoxSizer* bSizerErrorsRetry; - wxStaticBitmap* m_bitmapRetryErrors; - wxBoxSizer* bSizerErrorsIgnore; - wxStaticBitmap* m_bitmapIgnoreErrors; - - CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxBORDER_RAISED, const wxString& name = wxEmptyString ); - - ~CompareProgressDlgGenerated(); +private: + +protected: + wxStaticText* m_staticTextStatus; + wxFlexGridSizer* ffgSizer11; + wxFlexGridSizer* ffgSizer111; + wxFlexGridSizer* ffgSizer112; + wxStaticText* m_staticText1461; + wxStaticText* m_staticTextRetryCount; + wxStaticText* m_staticText146; + wxBoxSizer* bSizerProgressGraph; + wxFlexGridSizer* ffgSizer113; + zen::Graph2D* m_panelProgressGraph; + +public: + wxStaticText* m_staticTextProcessed; + wxStaticText* m_staticTextRemaining; + wxPanel* m_panelItemStats; + wxStaticBitmap* m_bitmapItemStat; + wxStaticText* m_staticTextItemsProcessed; + wxStaticText* m_staticTextBytesProcessed; + wxStaticText* m_staticTextItemsRemaining; + wxStaticText* m_staticTextBytesRemaining; + wxPanel* m_panelTimeStats; + wxStaticBitmap* m_bitmapTimeStat; + wxStaticText* m_staticTextTimeElapsed; + wxStaticText* m_staticTextTimeRemaining; + wxBoxSizer* bSizerErrorsRetry; + wxStaticBitmap* m_bitmapRetryErrors; + wxBoxSizer* bSizerErrorsIgnore; + wxStaticBitmap* m_bitmapIgnoreErrors; + + CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxBORDER_RAISED, const wxString& name = wxEmptyString ); + + ~CompareProgressDlgGenerated(); }; @@ -807,61 +810,61 @@ class CompareProgressDlgGenerated : public wxPanel /////////////////////////////////////////////////////////////////////////////// class SyncProgressPanelGenerated : public wxPanel { - private: - - protected: - wxPanel* m_panel53; - wxBoxSizer* bSizer42; - wxFlexGridSizer* ffgSizer11; - wxFlexGridSizer* ffgSizer111; - wxFlexGridSizer* ffgSizer112; - wxStaticText* m_staticText1461; - wxStaticText* m_staticText146; - wxStaticText* m_staticText137; - - public: - wxBoxSizer* bSizerRoot; - wxStaticBitmap* m_bitmapStatus; - wxStaticText* m_staticTextPhase; - wxBitmapButton* m_bpButtonMinimizeToTray; - wxBoxSizer* bSizerStatusText; - wxStaticText* m_staticTextStatus; - wxPanel* m_panelProgress; - zen::Graph2D* m_panelGraphBytes; - wxStaticBitmap* m_bitmapGraphKeyBytes; - wxStaticBitmap* m_bitmapGraphKeyItems; - wxStaticText* m_staticTextProcessed; - wxStaticText* m_staticTextRemaining; - wxPanel* m_panelItemStats; - wxStaticBitmap* m_bitmapItemStat; - wxStaticText* m_staticTextItemsProcessed; - wxStaticText* m_staticTextBytesProcessed; - wxStaticText* m_staticTextItemsRemaining; - wxStaticText* m_staticTextBytesRemaining; - wxPanel* m_panelTimeStats; - wxStaticBitmap* m_bitmapTimeStat; - wxStaticText* m_staticTextTimeElapsed; - wxStaticText* m_staticTextTimeRemaining; - wxBoxSizer* bSizerDynSpace; - zen::Graph2D* m_panelGraphItems; - wxBoxSizer* bSizerProgressFooter; - wxBoxSizer* bSizerErrorsRetry; - wxStaticBitmap* m_bitmapRetryErrors; - wxStaticText* m_staticTextRetryCount; - wxBoxSizer* bSizerErrorsIgnore; - wxStaticBitmap* m_bitmapIgnoreErrors; - wxChoice* m_choicePostSyncAction; - wxNotebook* m_notebookResult; - wxStaticLine* m_staticlineFooter; - wxBoxSizer* bSizerStdButtons; - wxCheckBox* m_checkBoxAutoClose; - wxButton* m_buttonClose; - wxButton* m_buttonPause; - wxButton* m_buttonStop; - - SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); - - ~SyncProgressPanelGenerated(); +private: + +protected: + wxPanel* m_panel53; + wxBoxSizer* bSizer42; + wxFlexGridSizer* ffgSizer11; + wxFlexGridSizer* ffgSizer111; + wxFlexGridSizer* ffgSizer112; + wxStaticText* m_staticText1461; + wxStaticText* m_staticText146; + wxStaticText* m_staticText137; + +public: + wxBoxSizer* bSizerRoot; + wxStaticBitmap* m_bitmapStatus; + wxStaticText* m_staticTextPhase; + wxBitmapButton* m_bpButtonMinimizeToTray; + wxBoxSizer* bSizerStatusText; + wxStaticText* m_staticTextStatus; + wxPanel* m_panelProgress; + zen::Graph2D* m_panelGraphBytes; + wxStaticBitmap* m_bitmapGraphKeyBytes; + wxStaticBitmap* m_bitmapGraphKeyItems; + wxStaticText* m_staticTextProcessed; + wxStaticText* m_staticTextRemaining; + wxPanel* m_panelItemStats; + wxStaticBitmap* m_bitmapItemStat; + wxStaticText* m_staticTextItemsProcessed; + wxStaticText* m_staticTextBytesProcessed; + wxStaticText* m_staticTextItemsRemaining; + wxStaticText* m_staticTextBytesRemaining; + wxPanel* m_panelTimeStats; + wxStaticBitmap* m_bitmapTimeStat; + wxStaticText* m_staticTextTimeElapsed; + wxStaticText* m_staticTextTimeRemaining; + wxBoxSizer* bSizerDynSpace; + zen::Graph2D* m_panelGraphItems; + wxBoxSizer* bSizerProgressFooter; + wxBoxSizer* bSizerErrorsRetry; + wxStaticBitmap* m_bitmapRetryErrors; + wxStaticText* m_staticTextRetryCount; + wxBoxSizer* bSizerErrorsIgnore; + wxStaticBitmap* m_bitmapIgnoreErrors; + wxChoice* m_choicePostSyncAction; + wxNotebook* m_notebookResult; + wxStaticLine* m_staticlineFooter; + wxBoxSizer* bSizerStdButtons; + wxCheckBox* m_checkBoxAutoClose; + wxButton* m_buttonClose; + wxButton* m_buttonPause; + wxButton* m_buttonStop; + + SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); + + ~SyncProgressPanelGenerated(); }; @@ -870,26 +873,26 @@ class SyncProgressPanelGenerated : public wxPanel /////////////////////////////////////////////////////////////////////////////// class LogPanelGenerated : public wxPanel { - private: +private: - protected: - zen::ToggleButton* m_bpButtonErrors; - zen::ToggleButton* m_bpButtonWarnings; - zen::ToggleButton* m_bpButtonInfo; - wxStaticLine* m_staticline13; +protected: + zen::ToggleButton* m_bpButtonErrors; + zen::ToggleButton* m_bpButtonWarnings; + zen::ToggleButton* m_bpButtonInfo; + wxStaticLine* m_staticline13; - // Virtual event handlers, override them in your derived class - virtual void onErrors( wxCommandEvent& event ) { event.Skip(); } - virtual void onWarnings( wxCommandEvent& event ) { event.Skip(); } - virtual void onInfo( wxCommandEvent& event ) { event.Skip(); } + // Virtual event handlers, override them in your derived class + virtual void onErrors( wxCommandEvent& event ) { event.Skip(); } + virtual void onWarnings( wxCommandEvent& event ) { event.Skip(); } + virtual void onInfo( wxCommandEvent& event ) { event.Skip(); } - public: - zen::Grid* m_gridMessages; +public: + zen::Grid* m_gridMessages; - LogPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); + LogPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); - ~LogPanelGenerated(); + ~LogPanelGenerated(); }; @@ -898,47 +901,47 @@ class LogPanelGenerated : public wxPanel /////////////////////////////////////////////////////////////////////////////// class BatchDlgGenerated : public wxDialog { - private: - - protected: - wxStaticBitmap* m_bitmapBatchJob; - wxStaticText* m_staticTextHeader; - wxStaticLine* m_staticline18; - wxPanel* m_panel35; - wxStaticText* m_staticText146; - wxFlexGridSizer* ffgSizer11; - wxStaticBitmap* m_bitmapMinimizeToTray; - wxCheckBox* m_checkBoxRunMinimized; - wxStaticLine* m_staticline26; - wxStaticBitmap* m_bitmapIgnoreErrors; - wxCheckBox* m_checkBoxIgnoreErrors; - wxRadioButton* m_radioBtnErrorDialogShow; - wxRadioButton* m_radioBtnErrorDialogCancel; - wxStaticLine* m_staticline261; - wxStaticText* m_staticText137; - wxStaticLine* m_staticline262; - wxStaticLine* m_staticline25; - wxHyperlinkCtrl* m_hyperlink17; - wxStaticLine* m_staticline13; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonSaveAs; - wxButton* m_buttonCancel; - - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onToggleRunMinimized( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleIgnoreErrors( wxCommandEvent& event ) { event.Skip(); } - virtual void onSaveBatchJob( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - - - public: - wxCheckBox* m_checkBoxAutoClose; - wxChoice* m_choicePostSyncAction; - - BatchDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Save as a Batch Job"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - - ~BatchDlgGenerated(); +private: + +protected: + wxStaticBitmap* m_bitmapBatchJob; + wxStaticText* m_staticTextHeader; + wxStaticLine* m_staticline18; + wxPanel* m_panel35; + wxStaticText* m_staticText146; + wxFlexGridSizer* ffgSizer11; + wxStaticBitmap* m_bitmapMinimizeToTray; + wxCheckBox* m_checkBoxRunMinimized; + wxStaticLine* m_staticline26; + wxStaticBitmap* m_bitmapIgnoreErrors; + wxCheckBox* m_checkBoxIgnoreErrors; + wxRadioButton* m_radioBtnErrorDialogShow; + wxRadioButton* m_radioBtnErrorDialogCancel; + wxStaticLine* m_staticline261; + wxStaticText* m_staticText137; + wxStaticLine* m_staticline262; + wxStaticLine* m_staticline25; + wxHyperlinkCtrl* m_hyperlink17; + wxStaticLine* m_staticline13; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonSaveAs; + wxButton* m_buttonCancel; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onToggleRunMinimized( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleIgnoreErrors( wxCommandEvent& event ) { event.Skip(); } + virtual void onSaveBatchJob( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + + +public: + wxCheckBox* m_checkBoxAutoClose; + wxChoice* m_choicePostSyncAction; + + BatchDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Save as a Batch Job"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + + ~BatchDlgGenerated(); }; @@ -947,33 +950,33 @@ class BatchDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class DeleteDlgGenerated : public wxDialog { - private: +private: - protected: - wxStaticBitmap* m_bitmapDeleteType; - wxStaticText* m_staticTextHeader; - wxStaticLine* m_staticline91; - wxPanel* m_panel31; - wxStaticLine* m_staticline42; - wxTextCtrl* m_textCtrlFileList; - wxStaticLine* m_staticline9; - wxBoxSizer* bSizerStdButtons; - wxCheckBox* m_checkBoxUseRecycler; - wxButton* m_buttonOK; - wxButton* m_buttonCancel; +protected: + wxStaticBitmap* m_bitmapDeleteType; + wxStaticText* m_staticTextHeader; + wxStaticLine* m_staticline91; + wxPanel* m_panel31; + wxStaticLine* m_staticline42; + wxTextCtrl* m_textCtrlFileList; + wxStaticLine* m_staticline9; + wxBoxSizer* bSizerStdButtons; + wxCheckBox* m_checkBoxUseRecycler; + wxButton* m_buttonOK; + wxButton* m_buttonCancel; - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onUseRecycler( wxCommandEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onUseRecycler( wxCommandEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - public: +public: - DeleteDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Delete Items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); + DeleteDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Delete Items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); - ~DeleteDlgGenerated(); + ~DeleteDlgGenerated(); }; @@ -982,36 +985,36 @@ class DeleteDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class CopyToDlgGenerated : public wxDialog { - private: +private: - protected: - wxStaticBitmap* m_bitmapCopyTo; - wxStaticText* m_staticTextHeader; - wxStaticLine* m_staticline91; - wxPanel* m_panel31; - wxStaticLine* m_staticline42; - wxTextCtrl* m_textCtrlFileList; - wxButton* m_buttonSelectTargetFolder; - wxStaticLine* m_staticline9; - wxBoxSizer* bSizerStdButtons; - wxCheckBox* m_checkBoxKeepRelPath; - wxCheckBox* m_checkBoxOverwriteIfExists; - wxButton* m_buttonOK; - wxButton* m_buttonCancel; +protected: + wxStaticBitmap* m_bitmapCopyTo; + wxStaticText* m_staticTextHeader; + wxStaticLine* m_staticline91; + wxPanel* m_panel31; + wxStaticLine* m_staticline42; + wxTextCtrl* m_textCtrlFileList; + wxButton* m_buttonSelectTargetFolder; + wxStaticLine* m_staticline9; + wxBoxSizer* bSizerStdButtons; + wxCheckBox* m_checkBoxKeepRelPath; + wxCheckBox* m_checkBoxOverwriteIfExists; + wxButton* m_buttonOK; + wxButton* m_buttonCancel; - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - public: - fff::FolderHistoryBox* m_targetFolderPath; - wxBitmapButton* m_bpButtonSelectAltTargetFolder; +public: + fff::FolderHistoryBox* m_targetFolderPath; + wxBitmapButton* m_bpButtonSelectAltTargetFolder; - CopyToDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Copy Items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); + CopyToDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Copy Items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); - ~CopyToDlgGenerated(); + ~CopyToDlgGenerated(); }; @@ -1020,134 +1023,115 @@ class CopyToDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class OptionsDlgGenerated : public wxDialog { - private: - - protected: - wxStaticBitmap* m_bitmapSettings; - wxStaticText* m_staticText44; - wxStaticLine* m_staticline20; - wxPanel* m_panel39; - wxCheckBox* m_checkBoxFailSafe; - wxStaticText* m_staticText911; - wxStaticText* m_staticText91; - wxStaticText* m_staticText9111; - wxBoxSizer* bSizerLockedFiles; - wxCheckBox* m_checkBoxCopyLocked; - wxStaticText* m_staticText921; - wxStaticText* m_staticText92; - wxStaticText* m_staticText922; - wxCheckBox* m_checkBoxCopyPermissions; - wxStaticText* m_staticText931; - wxStaticText* m_staticText93; - wxStaticText* m_staticText932; - wxStaticLine* m_staticline39; - wxStaticLine* m_staticline191; - wxStaticBitmap* m_bitmapWarnings; - wxStaticText* m_staticText182; - wxStaticText* m_staticTextHiddenDialogsCount; - wxButton* m_buttonShowHiddenDialogs; - wxCheckListBox* m_checkListHiddenDialogs; - wxStaticLine* m_staticline1911; - wxStaticBitmap* m_bitmapLogFile; - wxStaticText* m_staticText163; - wxPanel* m_panelLogfile; - wxButton* m_buttonSelectLogFolder; - wxCheckBox* m_checkBoxLogFilesMaxAge; - wxSpinCtrl* m_spinCtrlLogFilesMaxAge; - wxStaticLine* m_staticline81; - wxStaticText* m_staticText184; - wxRadioButton* m_radioBtnLogHtml; - wxRadioButton* m_radioBtnLogText; - wxStaticLine* m_staticline361; - wxStaticBitmap* m_bitmapNotificationSounds; - wxStaticText* m_staticText851; - wxFlexGridSizer* ffgSizer11; - wxStaticText* m_staticText171; - wxStaticBitmap* m_bitmapCompareDone; - wxBitmapButton* m_bpButtonPlayCompareDone; - wxTextCtrl* m_textCtrlSoundPathCompareDone; - wxButton* m_buttonSelectSoundCompareDone; - wxStaticText* m_staticText1711; - wxStaticBitmap* m_bitmapSyncDone; - wxBitmapButton* m_bpButtonPlaySyncDone; - wxTextCtrl* m_textCtrlSoundPathSyncDone; - wxButton* m_buttonSelectSoundSyncDone; - wxStaticText* m_staticText17111; - wxStaticBitmap* m_bitmapAlertPending; - wxBitmapButton* m_bpButtonPlayAlertPending; - wxTextCtrl* m_textCtrlSoundPathAlertPending; - wxButton* m_buttonSelectSoundAlertPending; - wxStaticLine* m_staticline3611; - wxStaticBitmap* m_bitmapConsole; - wxStaticText* m_staticText85; - wxButton* m_buttonShowCtxCustomize; - wxBoxSizer* bSizerContextCustomize; - wxBitmapButton* m_bpButtonAddRow; - wxBitmapButton* m_bpButtonRemoveRow; - wxStaticText* m_staticText174; - wxStaticText* m_staticText175; - wxStaticText* m_staticText178; - wxStaticText* m_staticText179; - wxStaticText* m_staticText189; - wxStaticText* m_staticText190; - wxStaticText* m_staticText176; - wxStaticText* m_staticText177; - wxHyperlinkCtrl* m_hyperlink17; - wxGrid* m_gridCustomCommand; - wxStaticLine* m_staticline36; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonDefault; - wxButton* m_buttonOkay; - wxButton* m_buttonCancel; - - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onShowHiddenDialogs( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleHiddenDialog( wxCommandEvent& event ) { event.Skip(); } - virtual void onShowLogFolder( wxCommandEvent& event ) { event.Skip(); } - virtual void onToggleLogfilesLimit( wxCommandEvent& event ) { event.Skip(); } - virtual void onPlayCompareDone( wxCommandEvent& event ) { event.Skip(); } - virtual void onChangeSoundFilePath( wxCommandEvent& event ) { event.Skip(); } - virtual void onSelectSoundCompareDone( wxCommandEvent& event ) { event.Skip(); } - virtual void onPlaySyncDone( wxCommandEvent& event ) { event.Skip(); } - virtual void onSelectSoundSyncDone( wxCommandEvent& event ) { event.Skip(); } - virtual void onPlayAlertPending( wxCommandEvent& event ) { event.Skip(); } - virtual void onSelectSoundAlertPending( wxCommandEvent& event ) { event.Skip(); } - virtual void onShowContextCustomize( wxCommandEvent& event ) { event.Skip(); } - virtual void onAddRow( wxCommandEvent& event ) { event.Skip(); } - virtual void onRemoveRow( wxCommandEvent& event ) { event.Skip(); } - virtual void onDefault( wxCommandEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - - - public: - wxBitmapButton* m_bpButtonShowLogFolder; - fff::FolderHistoryBox* m_logFolderPath; - wxBitmapButton* m_bpButtonSelectAltLogFolder; - - OptionsDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Options"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - - ~OptionsDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class TooltipDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class TooltipDlgGenerated : public wxDialog -{ - private: - - protected: - - public: - wxStaticBitmap* m_bitmapLeft; - wxStaticText* m_staticTextMain; - - TooltipDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - - ~TooltipDlgGenerated(); +private: + +protected: + wxStaticBitmap* m_bitmapSettings; + wxStaticText* m_staticText44; + wxStaticLine* m_staticline20; + wxPanel* m_panel39; + wxCheckBox* m_checkBoxFailSafe; + wxStaticText* m_staticText911; + wxStaticText* m_staticText91; + wxStaticText* m_staticText9111; + wxBoxSizer* bSizerLockedFiles; + wxCheckBox* m_checkBoxCopyLocked; + wxStaticText* m_staticText921; + wxStaticText* m_staticText92; + wxStaticText* m_staticText922; + wxCheckBox* m_checkBoxCopyPermissions; + wxStaticText* m_staticText931; + wxStaticText* m_staticText93; + wxStaticText* m_staticText932; + wxStaticLine* m_staticline39; + wxStaticLine* m_staticline191; + wxStaticBitmap* m_bitmapWarnings; + wxStaticText* m_staticText182; + wxStaticText* m_staticTextHiddenDialogsCount; + wxButton* m_buttonShowHiddenDialogs; + wxCheckListBox* m_checkListHiddenDialogs; + wxStaticLine* m_staticline1911; + wxStaticBitmap* m_bitmapLogFile; + wxStaticText* m_staticText163; + wxPanel* m_panelLogfile; + wxButton* m_buttonSelectLogFolder; + wxCheckBox* m_checkBoxLogFilesMaxAge; + wxSpinCtrl* m_spinCtrlLogFilesMaxAge; + wxStaticLine* m_staticline81; + wxStaticText* m_staticText184; + wxRadioButton* m_radioBtnLogHtml; + wxRadioButton* m_radioBtnLogText; + wxStaticLine* m_staticline361; + wxStaticBitmap* m_bitmapNotificationSounds; + wxStaticText* m_staticText851; + wxFlexGridSizer* ffgSizer11; + wxStaticText* m_staticText171; + wxStaticBitmap* m_bitmapCompareDone; + wxBitmapButton* m_bpButtonPlayCompareDone; + wxTextCtrl* m_textCtrlSoundPathCompareDone; + wxButton* m_buttonSelectSoundCompareDone; + wxStaticText* m_staticText1711; + wxStaticBitmap* m_bitmapSyncDone; + wxBitmapButton* m_bpButtonPlaySyncDone; + wxTextCtrl* m_textCtrlSoundPathSyncDone; + wxButton* m_buttonSelectSoundSyncDone; + wxStaticText* m_staticText17111; + wxStaticBitmap* m_bitmapAlertPending; + wxBitmapButton* m_bpButtonPlayAlertPending; + wxTextCtrl* m_textCtrlSoundPathAlertPending; + wxButton* m_buttonSelectSoundAlertPending; + wxStaticLine* m_staticline3611; + wxStaticBitmap* m_bitmapConsole; + wxStaticText* m_staticText85; + wxButton* m_buttonShowCtxCustomize; + wxBoxSizer* bSizerContextCustomize; + wxBitmapButton* m_bpButtonAddRow; + wxBitmapButton* m_bpButtonRemoveRow; + wxStaticText* m_staticText174; + wxStaticText* m_staticText175; + wxStaticText* m_staticText178; + wxStaticText* m_staticText179; + wxStaticText* m_staticText189; + wxStaticText* m_staticText190; + wxStaticText* m_staticText176; + wxStaticText* m_staticText177; + wxHyperlinkCtrl* m_hyperlink17; + wxGrid* m_gridCustomCommand; + wxStaticLine* m_staticline36; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonDefault; + wxButton* m_buttonOkay; + wxButton* m_buttonCancel; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onShowHiddenDialogs( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleHiddenDialog( wxCommandEvent& event ) { event.Skip(); } + virtual void onShowLogFolder( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleLogfilesLimit( wxCommandEvent& event ) { event.Skip(); } + virtual void onPlayCompareDone( wxCommandEvent& event ) { event.Skip(); } + virtual void onChangeSoundFilePath( wxCommandEvent& event ) { event.Skip(); } + virtual void onSelectSoundCompareDone( wxCommandEvent& event ) { event.Skip(); } + virtual void onPlaySyncDone( wxCommandEvent& event ) { event.Skip(); } + virtual void onSelectSoundSyncDone( wxCommandEvent& event ) { event.Skip(); } + virtual void onPlayAlertPending( wxCommandEvent& event ) { event.Skip(); } + virtual void onSelectSoundAlertPending( wxCommandEvent& event ) { event.Skip(); } + virtual void onShowContextCustomize( wxCommandEvent& event ) { event.Skip(); } + virtual void onAddRow( wxCommandEvent& event ) { event.Skip(); } + virtual void onRemoveRow( wxCommandEvent& event ) { event.Skip(); } + virtual void onDefault( wxCommandEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + + +public: + wxBitmapButton* m_bpButtonShowLogFolder; + fff::FolderHistoryBox* m_logFolderPath; + wxBitmapButton* m_bpButtonSelectAltLogFolder; + + OptionsDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Options"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + + ~OptionsDlgGenerated(); }; @@ -1156,30 +1140,30 @@ class TooltipDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class SelectTimespanDlgGenerated : public wxDialog { - private: +private: - protected: - wxPanel* m_panel35; - wxCalendarCtrl* m_calendarFrom; - wxCalendarCtrl* m_calendarTo; - wxStaticLine* m_staticline21; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonOkay; - wxButton* m_buttonCancel; +protected: + wxPanel* m_panel35; + wxCalendarCtrl* m_calendarFrom; + wxCalendarCtrl* m_calendarTo; + wxStaticLine* m_staticline21; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonOkay; + wxButton* m_buttonCancel; - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onChangeSelectionFrom( wxCalendarEvent& event ) { event.Skip(); } - virtual void onChangeSelectionTo( wxCalendarEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onChangeSelectionFrom( wxCalendarEvent& event ) { event.Skip(); } + virtual void onChangeSelectionTo( wxCalendarEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - public: +public: - SelectTimespanDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Time Span"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + SelectTimespanDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Time Span"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~SelectTimespanDlgGenerated(); + ~SelectTimespanDlgGenerated(); }; @@ -1188,54 +1172,54 @@ class SelectTimespanDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class AboutDlgGenerated : public wxDialog { - private: - - protected: - wxPanel* m_panel41; - wxStaticBitmap* m_bitmapLogoLeft; - wxStaticLine* m_staticline81; - wxBoxSizer* bSizerMainSection; - wxStaticLine* m_staticline82; - wxStaticBitmap* m_bitmapLogo; - wxStaticLine* m_staticline341; - wxStaticText* m_staticFfsTextVersion; - wxStaticText* m_staticTextFfsVariant; - wxStaticLine* m_staticline3411; - wxBoxSizer* bSizerDonate; - wxPanel* m_panelDonate; - wxStaticBitmap* m_bitmapAnimalSmall; - wxPanel* m_panel39; - wxStaticText* m_staticTextDonate; - zen::BitmapTextButton* m_buttonDonate1; - wxStaticBitmap* m_bitmapAnimalBig; - wxStaticLine* m_staticline3412; - wxStaticText* m_staticText94; - wxBitmapButton* m_bpButtonForum; - wxBitmapButton* m_bpButtonEmail; - wxStaticLine* m_staticline37; - wxStaticText* m_staticTextThanksForLoc; - wxScrolledWindow* m_scrolledWindowTranslators; - wxFlexGridSizer* fgSizerTranslators; - wxStaticLine* m_staticline36; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonShowDonationDetails; - zen::BitmapTextButton* m_buttonDonate2; - wxButton* m_buttonClose; - - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onDonate( wxCommandEvent& event ) { event.Skip(); } - virtual void onOpenForum( wxCommandEvent& event ) { event.Skip(); } - virtual void onSendEmail( wxCommandEvent& event ) { event.Skip(); } - virtual void onShowDonationDetails( wxCommandEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - - - public: - - AboutDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("About"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - - ~AboutDlgGenerated(); +private: + +protected: + wxPanel* m_panel41; + wxStaticBitmap* m_bitmapLogoLeft; + wxStaticLine* m_staticline81; + wxBoxSizer* bSizerMainSection; + wxStaticLine* m_staticline82; + wxStaticBitmap* m_bitmapLogo; + wxStaticLine* m_staticline341; + wxStaticText* m_staticFfsTextVersion; + wxStaticText* m_staticTextFfsVariant; + wxStaticLine* m_staticline3411; + wxBoxSizer* bSizerDonate; + wxPanel* m_panelDonate; + wxStaticBitmap* m_bitmapAnimalSmall; + wxPanel* m_panel39; + wxStaticText* m_staticTextDonate; + zen::BitmapTextButton* m_buttonDonate1; + wxStaticBitmap* m_bitmapAnimalBig; + wxStaticLine* m_staticline3412; + wxStaticText* m_staticText94; + wxBitmapButton* m_bpButtonForum; + wxBitmapButton* m_bpButtonEmail; + wxStaticLine* m_staticline37; + wxStaticText* m_staticTextThanksForLoc; + wxScrolledWindow* m_scrolledWindowTranslators; + wxFlexGridSizer* fgSizerTranslators; + wxStaticLine* m_staticline36; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonShowDonationDetails; + zen::BitmapTextButton* m_buttonDonate2; + wxButton* m_buttonClose; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onDonate( wxCommandEvent& event ) { event.Skip(); } + virtual void onOpenForum( wxCommandEvent& event ) { event.Skip(); } + virtual void onSendEmail( wxCommandEvent& event ) { event.Skip(); } + virtual void onShowDonationDetails( wxCommandEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + + +public: + + AboutDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("About"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + + ~AboutDlgGenerated(); }; @@ -1244,106 +1228,144 @@ class AboutDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class DownloadProgressDlgGenerated : public wxDialog { - private: +private: - protected: - wxStaticBitmap* m_bitmapDownloading; - wxStaticText* m_staticTextHeader; - wxGauge* m_gaugeProgress; - wxStaticText* m_staticTextDetails; - wxStaticLine* m_staticline9; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonCancel; +protected: + wxStaticBitmap* m_bitmapDownloading; + wxStaticText* m_staticTextHeader; + wxGauge* m_gaugeProgress; + wxStaticText* m_staticTextDetails; + wxStaticLine* m_staticline9; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonCancel; - // Virtual event handlers, override them in your derived class - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + // Virtual event handlers, override them in your derived class + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - public: +public: - DownloadProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0 ); + DownloadProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0 ); - ~DownloadProgressDlgGenerated(); + ~DownloadProgressDlgGenerated(); }; /////////////////////////////////////////////////////////////////////////////// -/// Class ActivationDlgGenerated +/// Class CfgHighlightDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class ActivationDlgGenerated : public wxDialog +class CfgHighlightDlgGenerated : public wxDialog { - private: - - protected: - wxPanel* m_panel35; - wxStaticBitmap* m_bitmapActivation; - wxRichTextCtrl* m_richTextLastError; - wxStaticLine* m_staticline82; - wxStaticText* m_staticTextMain; - wxStaticLine* m_staticline181; - wxStaticLine* m_staticline18111; - wxPanel* m_panel3511; - wxStaticText* m_staticTextMain1; - wxStaticText* m_staticText136; - wxButton* m_buttonActivateOnline; - wxStaticLine* m_staticline181111; - wxStaticLine* m_staticline181112; - wxPanel* m_panel351; - wxStaticText* m_staticText175; - wxStaticText* m_staticText1361; - wxButton* m_buttonCopyUrl; - wxRichTextCtrl* m_richTextManualActivationUrl; - wxStaticText* m_staticText13611; - wxTextCtrl* m_textCtrlOfflineActivationKey; - wxButton* m_buttonActivateOffline; - wxStaticLine* m_staticline13; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonCancel; - - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onActivateOnline( wxCommandEvent& event ) { event.Skip(); } - virtual void onCopyUrl( wxCommandEvent& event ) { event.Skip(); } - virtual void onOfflineActivationEnter( wxCommandEvent& event ) { event.Skip(); } - virtual void onActivateOffline( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - - - public: - - ActivationDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - - ~ActivationDlgGenerated(); +private: + +protected: + wxPanel* m_panel35; + wxStaticText* m_staticTextHighlight; + wxSpinCtrl* m_spinCtrlOverdueDays; + wxStaticLine* m_staticline21; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonOkay; + wxButton* m_buttonCancel; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + + +public: + + CfgHighlightDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Highlight Configurations"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + + ~CfgHighlightDlgGenerated(); }; /////////////////////////////////////////////////////////////////////////////// -/// Class CfgHighlightDlgGenerated +/// Class PasswordPromptDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class CfgHighlightDlgGenerated : public wxDialog +class PasswordPromptDlgGenerated : public wxDialog { - private: +private: + +protected: + wxPanel* m_panel35; + wxStaticText* m_staticTextMain; + wxStaticText* m_staticTextPassword; + wxTextCtrl* m_textCtrlPasswordVisible; + wxTextCtrl* m_textCtrlPasswordHidden; + wxCheckBox* m_checkBoxShowPassword; + wxBoxSizer* bSizerError; + wxStaticBitmap* m_bitmapError; + wxStaticText* m_staticTextError; + wxStaticLine* m_staticline21; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonOkay; + wxButton* m_buttonCancel; - protected: - wxPanel* m_panel35; - wxStaticText* m_staticTextHighlight; - wxSpinCtrl* m_spinCtrlOverdueDays; - wxStaticLine* m_staticline21; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonOkay; - wxButton* m_buttonCancel; + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onTypingPassword( wxCommandEvent& event ) { event.Skip(); } + virtual void onToggleShowPassword( wxCommandEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } +public: - public: + PasswordPromptDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - CfgHighlightDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Highlight Configurations"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~PasswordPromptDlgGenerated(); - ~CfgHighlightDlgGenerated(); +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class ActivationDlgGenerated +/////////////////////////////////////////////////////////////////////////////// +class ActivationDlgGenerated : public wxDialog +{ +private: + +protected: + wxPanel* m_panel35; + wxStaticBitmap* m_bitmapActivation; + wxRichTextCtrl* m_richTextLastError; + wxStaticLine* m_staticline82; + wxStaticText* m_staticTextMain; + wxStaticLine* m_staticline181; + wxStaticLine* m_staticline18111; + wxPanel* m_panel3511; + wxStaticText* m_staticTextMain1; + wxStaticText* m_staticText136; + wxButton* m_buttonActivateOnline; + wxStaticLine* m_staticline181111; + wxStaticLine* m_staticline181112; + wxPanel* m_panel351; + wxStaticText* m_staticText175; + wxStaticText* m_staticText1361; + wxButton* m_buttonCopyUrl; + wxRichTextCtrl* m_richTextManualActivationUrl; + wxStaticText* m_staticText13611; + wxTextCtrl* m_textCtrlOfflineActivationKey; + wxButton* m_buttonActivateOffline; + wxStaticLine* m_staticline13; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonCancel; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onActivateOnline( wxCommandEvent& event ) { event.Skip(); } + virtual void onCopyUrl( wxCommandEvent& event ) { event.Skip(); } + virtual void onOfflineActivationEnter( wxCommandEvent& event ) { event.Skip(); } + virtual void onActivateOffline( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + + +public: + + ActivationDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + + ~ActivationDlgGenerated(); }; @@ -1352,40 +1374,40 @@ class CfgHighlightDlgGenerated : public wxDialog /////////////////////////////////////////////////////////////////////////////// class WarnAccessRightsMissingDlgGenerated : public wxDialog { - private: - - protected: - wxStaticBitmap* m_bitmapGrantAccess; - wxStaticText* m_staticTextDescr; - wxStaticLine* m_staticline20; - wxPanel* m_panel39; - wxFlexGridSizer* ffgSizer11; - wxStaticText* m_staticTextStep1; - wxButton* m_buttonLocateBundle; - wxStaticText* m_staticTextStep2; - wxButton* m_buttonOpenSecurity; - wxStaticText* m_staticTextStep3; - wxStaticText* m_staticTextAllowChanges; - wxStaticText* m_staticTextStep4; - wxStaticText* m_staticTextGrantAccess; - wxStaticLine* m_staticline36; - wxCheckBox* m_checkBoxDontShowAgain; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonClose; - - // Virtual event handlers, override them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onShowAppBundle( wxCommandEvent& event ) { event.Skip(); } - virtual void onOpenSecuritySettings( wxCommandEvent& event ) { event.Skip(); } - virtual void onCheckBoxClick( wxCommandEvent& event ) { event.Skip(); } - virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } - - - public: - - WarnAccessRightsMissingDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Grant Full Disk Access"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - - ~WarnAccessRightsMissingDlgGenerated(); +private: + +protected: + wxStaticBitmap* m_bitmapGrantAccess; + wxStaticText* m_staticTextDescr; + wxStaticLine* m_staticline20; + wxPanel* m_panel39; + wxFlexGridSizer* ffgSizer11; + wxStaticText* m_staticTextStep1; + wxButton* m_buttonLocateBundle; + wxStaticText* m_staticTextStep2; + wxButton* m_buttonOpenSecurity; + wxStaticText* m_staticTextStep3; + wxStaticText* m_staticTextAllowChanges; + wxStaticText* m_staticTextStep4; + wxStaticText* m_staticTextGrantAccess; + wxStaticLine* m_staticline36; + wxCheckBox* m_checkBoxDontShowAgain; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonClose; + + // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onShowAppBundle( wxCommandEvent& event ) { event.Skip(); } + virtual void onOpenSecuritySettings( wxCommandEvent& event ) { event.Skip(); } + virtual void onCheckBoxClick( wxCommandEvent& event ) { event.Skip(); } + virtual void onOkay( wxCommandEvent& event ) { event.Skip(); } + + +public: + + WarnAccessRightsMissingDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Grant Full Disk Access"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + + ~WarnAccessRightsMissingDlgGenerated(); }; diff --git a/FreeFileSync/Source/ui/log_panel.cpp b/FreeFileSync/Source/ui/log_panel.cpp index 7b3d6c2c..9e839d4b 100644 --- a/FreeFileSync/Source/ui/log_panel.cpp +++ b/FreeFileSync/Source/ui/log_panel.cpp @@ -508,15 +508,14 @@ void LogPanel::onLocalKeyEvent(wxKeyEvent& event) //process key events without e case WXK_NUMPAD_END: if (!isComponentOf(wxWindow::FindFocus(), m_gridMessages) && //don't propagate keyboard commands if grid is already in focus m_gridMessages->IsEnabled()) - if (wxEvtHandler* evtHandler = m_gridMessages->getMainWin().GetEventHandler()) - { - m_gridMessages->SetFocus(); + { + m_gridMessages->SetFocus(); - event.SetEventType(wxEVT_KEY_DOWN); //the grid event handler doesn't expect wxEVT_CHAR_HOOK! - evtHandler->ProcessEvent(event); //propagating event catched at wxTheApp to child leads to recursion, but we prevented it... - event.Skip(false); //definitively handled now! - return; - } + event.SetEventType(wxEVT_KEY_DOWN); //the grid event handler doesn't expect wxEVT_CHAR_HOOK! + m_gridMessages->getMainWin().GetEventHandler()->ProcessEvent(event); //propagating event catched at wxTheApp to child leads to recursion, but we prevented it... + event.Skip(false); //definitively handled now! + return; + } break; } } diff --git a/FreeFileSync/Source/ui/main_dlg.cpp b/FreeFileSync/Source/ui/main_dlg.cpp index 0442bfbf..341cfec7 100644 --- a/FreeFileSync/Source/ui/main_dlg.cpp +++ b/FreeFileSync/Source/ui/main_dlg.cpp @@ -335,7 +335,7 @@ XmlGlobalSettings tryLoadGlobalConfig(const Zstring& globalConfigFilePath) //blo { try { - if (itemStillExists(globalConfigFilePath)) //throw FileError + if (itemExists(globalConfigFilePath)) //throw FileError throw; } catch (const FileError& e2) @@ -361,10 +361,13 @@ void MainDialog::create(const Zstring& globalConfigFilePath) for (const Zstring& filePath : cfgFilePaths) firstUnavailableFile.addJob([filePath]() -> std::optional<std::false_type> { - assert(!filePath.empty()); - if (!fileAvailable(filePath)) - return std::false_type(); - return {}; + try + { + assert(!filePath.empty()); + getItemType(filePath); //throw FileError + return {}; + } + catch (FileError&) { return std::false_type(); } }); //potentially slow network access: give all checks 500ms to finish @@ -375,12 +378,15 @@ void MainDialog::create(const Zstring& globalConfigFilePath) //------------------------------------------------------------------------------------------ if (cfgFilePaths.empty()) - { - const Zstring lastRunConfigFilePath = getLastRunConfigPath(); - if (fileAvailable(lastRunConfigFilePath)) //3. try to load auto-save config (should not block) + try //3. ...to load auto-save config (should not block) + { + const Zstring lastRunConfigFilePath = getLastRunConfigPath(); + + getItemType(lastRunConfigFilePath); //throw FileError cfgFilePaths.push_back(lastRunConfigFilePath); - //else: not-existing/access error? => user may click on [Last session] later - } + } + catch (FileError&) {} //not-existing/access error? => user may click on [Last session] later + XmlGuiConfig guiCfg = getDefaultGuiConfig(globalSettings.defaultFilter); @@ -2245,15 +2251,14 @@ void MainDialog::onLocalKeyEvent(wxKeyEvent& event) //process key events without !isComponentOf(focus, m_panelLog ) && !isComponentOf(focus, m_panelDirectoryPairs) && //don't propagate if changing directory fields m_gridMainL->IsEnabled()) - if (wxEvtHandler* evtHandler = m_gridMainL->getMainWin().GetEventHandler()) - { - m_gridMainL->SetFocus(); + { + m_gridMainL->SetFocus(); - event.SetEventType(wxEVT_KEY_DOWN); //the grid event handler doesn't expect wxEVT_CHAR_HOOK! - evtHandler->ProcessEvent(event); //propagating event to child lead to recursion with old key_event.h handling => still an issue? - event.Skip(false); //definitively handled now! - return; - } + event.SetEventType(wxEVT_KEY_DOWN); //the grid event handler doesn't expect wxEVT_CHAR_HOOK! + m_gridMainL->getMainWin().GetEventHandler()->ProcessEvent(event); //propagating event to child lead to recursion with old key_event.h handling => still an issue? + event.Skip(false); //definitively handled now! + return; + } } break; @@ -2298,8 +2303,8 @@ void MainDialog::onTreeGridSelection(GridSelectEvent& event) { leadRow = std::max<ptrdiff_t>(0, leadRow - 1); //scroll one more row - m_gridMainL->scrollTo(leadRow); //scroll all of them (including "scroll master") - m_gridMainC->scrollTo(leadRow); // + m_gridMainL->scrollTo(leadRow); // + m_gridMainC->scrollTo(leadRow); //scroll all of them (including "scroll master") m_gridMainR->scrollTo(leadRow); // m_gridOverview->getMainWin().Update(); //draw cursor immediately rather than on next idle event (required for slow CPUs, netbook) @@ -2307,7 +2312,7 @@ void MainDialog::onTreeGridSelection(GridSelectEvent& event) //get selection on overview panel and set corresponding markers on main grid std::unordered_set<const FileSystemObject*> markedFilesAndLinks; //mark files/symlinks directly - std::unordered_set<const ContainerObject*> markedContainer; //mark full container including child-objects + std::unordered_set<const ContainerObject*> markedContainer; //mark full container including child-objects for (size_t row : m_gridOverview->getSelectedRows()) if (std::unique_ptr<TreeView::Node> node = treegrid::getDataView(*m_gridOverview).getLine(row)) @@ -2323,6 +2328,11 @@ void MainDialog::onTreeGridSelection(GridSelectEvent& event) filegrid::setNavigationMarker(*m_gridMainL, *m_gridMainR, std::move(markedFilesAndLinks), std::move(markedContainer)); + //selecting overview should clear main grid selection (if any) but not the other way around: + m_gridMainL->clearSelection(GridEventPolicy::deny); + m_gridMainC->clearSelection(GridEventPolicy::deny); + m_gridMainR->clearSelection(GridEventPolicy::deny); + event.Skip(); } @@ -2977,16 +2987,24 @@ void MainDialog::cfgHistoryRemoveObsolete(const std::vector<Zstring>& filePaths) std::vector<std::future<bool>> availableFiles; //check existence of all config files in parallel! for (const Zstring& filePath : filePaths) - availableFiles.push_back(runAsync([=] { return fileAvailable(filePath); })); + availableFiles.push_back(runAsync([=] + { + try + { + getItemType(filePath); //throw FileError + return true; + } + catch (FileError&) { return false; } //not-existing/access error? + })); //potentially slow network access => limit maximum wait time! - waitForAllTimed(availableFiles.begin(), availableFiles.end(), std::chrono::seconds(1)); + waitForAllTimed(availableFiles.begin(), availableFiles.end(), std::chrono::seconds(2)); std::vector<Zstring> pathsToRemove; auto itFut = availableFiles.begin(); for (auto it = filePaths.begin(); it != filePaths.end(); ++it, ++itFut) - if (isReady(*itFut) && !itFut->get()) //remove only files that are confirmed to be non-existent + if (isReady(*itFut) && !itFut->get()) //no ready? maybe on HDD that is just spinning up => better keep it pathsToRemove.push_back(*it); //file access error? probably not accessible network share or usb stick => remove cfg return pathsToRemove; @@ -3090,7 +3108,8 @@ void MainDialog::onConfigSave(wxCommandEvent& event) else showNotificationDialog(this, DialogInfoType::error, PopupDialogCfg().setDetailInstructions(replaceCpy(_("Cannot open file %x."), L"%x", fmtPath(activeCfgFilePath)) + - L"\n\n" + _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(activeCfgFilePath)))); + L"\n\n" + _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(activeCfgFilePath)) + L'\n' + + _("Expected:") + L" ffs_gui, ffs_batch")); } } @@ -3113,7 +3132,7 @@ bool MainDialog::trySaveConfig(const Zstring* guiCfgPath) //"false": error/cance getParentFolderPath(globalCfg_.mainDlg.config.lastSelectedFile); Zstring defaultFileName = !activeCfgFilePath.empty() ? - afterLast(activeCfgFilePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all) : + getItemName(activeCfgFilePath) : Zstr("SyncSettings.ffs_gui"); //attention: activeConfigFiles_ may be an imported ffs_batch file! We don't want to overwrite it with a GUI config! @@ -3196,7 +3215,7 @@ bool MainDialog::trySaveBatchConfig(const Zstring* batchCfgPath) //"false": erro getParentFolderPath(globalCfg_.mainDlg.config.lastSelectedFile); Zstring defaultFileName = !activeCfgFilePath.empty() ? - afterLast(activeCfgFilePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all) : + getItemName(activeCfgFilePath) : Zstr("BatchRun.ffs_batch"); //attention: activeConfigFiles_ may be an ffs_gui file! We don't want to overwrite it with a BATCH config! @@ -3250,8 +3269,7 @@ bool MainDialog::saveOldConfig() //"false": error/cancel bool neverSaveChanges = false; switch (showQuestionDialog(this, DialogInfoType::info, PopupDialogCfg(). setTitle(utfTo<wxString>(activeCfgFilePath)). - setMainInstructions(replaceCpy(_("Do you want to save changes to %x?"), L"%x", - fmtPath(afterLast(activeCfgFilePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all)))). + setMainInstructions(replaceCpy(_("Do you want to save changes to %x?"), L"%x", fmtPath(getItemName(activeCfgFilePath)))). setCheckBox(neverSaveChanges, _("Never save &changes"), static_cast<ConfirmationButton3>(QuestionButton2::yes)), _("&Save"), _("Do&n't save"))) { @@ -3264,7 +3282,8 @@ bool MainDialog::saveOldConfig() //"false": error/cancel { showNotificationDialog(this, DialogInfoType::error, PopupDialogCfg().setDetailInstructions(replaceCpy(_("Cannot open file %x."), L"%x", fmtPath(activeCfgFilePath)) + - L"\n\n" + _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(activeCfgFilePath)) )); + L"\n\n" + _("Unexpected file extension:") + L' ' + fmtPath(getFileExtension(activeCfgFilePath)) + L'\n' + + _("Expected:") + L" ffs_gui, ffs_batch")); return false; } break; @@ -3483,7 +3502,7 @@ void MainDialog::renameSelectedCfgHistoryItem() if (!loadConfiguration({cfgPathOld})) //=> error/cancel return; - const Zstring fileName = afterLast(cfgPathOld, FILE_NAME_SEPARATOR, IfNotFoundReturn::all); + const Zstring fileName = getItemName(cfgPathOld); /**/ Zstring folderPathPf = beforeLast(cfgPathOld, FILE_NAME_SEPARATOR, IfNotFoundReturn::none); if (!folderPathPf.empty()) folderPathPf += FILE_NAME_SEPARATOR; @@ -3641,7 +3660,7 @@ void MainDialog::onCfgGridContext(GridContextMenuEvent& event) dc.DrawText(L"?", wxPoint() + (bmpColorPicker.GetSize() - dc.GetTextExtent(L"?")) / 2); } - submenu.addItem(_("Select different color..."), [&] + submenu.addItem(_("Different color..."), [&] { wxColourData colCfg; colCfg.SetChooseFull(true); @@ -4088,6 +4107,13 @@ void MainDialog::onToggleViewButton(wxCommandEvent& event) { button->toggle(); updateGui(); + + //consistency: toggling view buttons should *always* clear selections, not only implicitly when row count changes: + // + //m_gridMainL->clearSelection(GridEventPolicy::deny); + //m_gridMainC->clearSelection(GridEventPolicy::deny); -> implicitly called by onTreeGridSelection() + //m_gridMainR->clearSelection(GridEventPolicy::deny); + m_gridOverview->clearSelection(GridEventPolicy::allow); } else assert(false); @@ -4215,15 +4241,24 @@ void MainDialog::onCompare(wxCommandEvent& event) guiCfg.mainCfg.autoRetryCount, guiCfg.mainCfg.autoRetryDelay, globalCfg_.soundFileAlertPending); + + auto requestPassword = [&, password = Zstring()](const std::wstring& msg, const std::wstring& lastErrorMsg) mutable //throw AbortProcess + { + assert(runningOnMainThread()); + if (showPasswordPrompt(this, msg, lastErrorMsg, password) != ConfirmationButton::accept) + statusHandler.abortProcessNow(AbortTrigger::user); //throw AbortProcess + + return password; + }; try { //GUI mode: place directory locks on directories isolated(!) during both comparison and synchronization - std::unique_ptr<LockHolder> dirLocks; //COMPARE DIRECTORIES + std::unique_ptr<LockHolder> dirLocks; folderCmp_ = compare(globalCfg_.warnDlgs, globalCfg_.fileTimeTolerance, - true, //allowUserInteraction + requestPassword, globalCfg_.runWithBackgroundPriority, globalCfg_.createLockFile, dirLocks, @@ -4242,15 +4277,9 @@ void MainDialog::onCompare(wxCommandEvent& event) return updateGui(); //refresh grid in ANY case! (also on abort) - filegrid::setData(*m_gridMainC, folderCmp_); //update view on data - treegrid::setData(*m_gridOverview, folderCmp_); // - updateGui(); - - m_gridMainL->clearSelection(GridEventPolicy::allow); - m_gridMainC->clearSelection(GridEventPolicy::allow); - m_gridMainR->clearSelection(GridEventPolicy::allow); - - m_gridOverview->clearSelection(GridEventPolicy::allow); + filegrid::setData(*m_gridMainC, folderCmp_); // + treegrid::setData(*m_gridOverview, folderCmp_); //update view on data + updateGui(); // //play (optional) sound notification if (!globalCfg_.soundFileCompareFinished.empty()) @@ -4301,8 +4330,8 @@ void MainDialog::updateGui() updateUnsavedCfgStatus(); const auto& mainCfg = getConfig().mainCfg; - const std::optional<CompareVariant> cmpVar = getCompVariant(mainCfg); - const std::optional<SyncVariant> syncVar = getSyncVariant(mainCfg); + const std::optional<CompareVariant> cmpVar = getCompVariant(mainCfg); + const std::optional<SyncVariant> syncVar = getSyncVariant(mainCfg); const char* cmpVarIconName = nullptr; if (cmpVar) @@ -4870,12 +4899,11 @@ void MainDialog::onGridLabelLeftClickRim(GridLabelClickEvent& event, bool leftSi const ItemPathFormat itemPathFormat = leftSide ? globalCfg_.mainDlg.itemPathFormatLeftGrid : globalCfg_.mainDlg.itemPathFormatRightGrid; filegrid::getDataView(*m_gridMainC).sortView(colType, itemPathFormat, leftSide, sortAscending); - - m_gridMainL->clearSelection(GridEventPolicy::allow); - m_gridMainC->clearSelection(GridEventPolicy::allow); - m_gridMainR->clearSelection(GridEventPolicy::allow); - updateGui(); //refresh gridDataView + + m_gridMainL->clearSelection(GridEventPolicy::deny); //call *after* updateGui/updateGridViewData() has restored FileView::viewRef_ + m_gridMainC->clearSelection(GridEventPolicy::deny); + m_gridMainR->clearSelection(GridEventPolicy::deny); } @@ -4892,12 +4920,11 @@ void MainDialog::onGridLabelLeftClickC(GridLabelClickEvent& event) sortAscending = !sortInfo->ascending; filegrid::getDataView(*m_gridMainC).sortView(colType, sortAscending); - - m_gridMainL->clearSelection(GridEventPolicy::allow); - m_gridMainC->clearSelection(GridEventPolicy::allow); - m_gridMainR->clearSelection(GridEventPolicy::allow); - updateGui(); //refresh gridDataView + + m_gridMainL->clearSelection(GridEventPolicy::deny); + m_gridMainC->clearSelection(GridEventPolicy::deny); + m_gridMainR->clearSelection(GridEventPolicy::deny); } } @@ -5919,7 +5946,7 @@ void MainDialog::switchProgramLanguage(wxLanguage langId) //show new dialog, then delete old one MainDialog::create(globalConfigFilePath_, &newGlobalCfg, getConfig(), activeConfigFiles_, false); - //we don't use Close(): + //don't use Close(): //1. we don't want to show the prompt to save current config in onClose() //2. after getGlobalCfgBeforeExit() the old main dialog is invalid so we want to force deletion Destroy(); //alternative: Close(true /*force*/) diff --git a/FreeFileSync/Source/ui/small_dlgs.cpp b/FreeFileSync/Source/ui/small_dlgs.cpp index ba75c4c3..50713faa 100644 --- a/FreeFileSync/Source/ui/small_dlgs.cpp +++ b/FreeFileSync/Source/ui/small_dlgs.cpp @@ -198,7 +198,9 @@ private: void gdriveUpdateDrivesAndSelect(const std::string& accountEmail, const Zstring& locationToSelect); void onDetectServerChannelLimit(wxCommandEvent& event) override; + void onTypingPassword(wxCommandEvent& event) override; void onToggleShowPassword(wxCommandEvent& event) override; + void onTogglePasswordPrompt(wxCommandEvent& event) override { updateGui(); } void onBrowseCloudFolder (wxCommandEvent& event) override; void onConnectionGdrive(wxCommandEvent& event) override { type_ = CloudType::gdrive; updateGui(); } @@ -219,6 +221,7 @@ private: static bool acceptFileDrop(const std::vector<Zstring>& shellItemPaths); void onKeyFileDropped(FileDropEvent& event); + bool validateParameters(); AbstractPath getFolderPath() const; enum class CloudType @@ -269,7 +272,8 @@ CloudSetupDlg::CloudSetupDlg(wxWindow* parent, Zstring& folderPathPhrase, Zstrin setImage(*m_bitmapCloud, loadImage("cloud")); setImage(*m_bitmapPerf, loadImage("speed")); setImage(*m_bitmapServerDir, IconBuffer::genericDirIcon(IconBuffer::IconSize::small)); - m_checkBoxShowPassword->SetValue(false); + m_checkBoxShowPassword ->SetValue(false); + m_checkBoxPasswordPrompt->SetValue(false); m_textCtrlServer->SetHint(_("Example:") + L" website.com 66.198.240.22"); m_textCtrlServer->SetMinSize({fastFromDIP(260), -1}); @@ -339,12 +343,15 @@ CloudSetupDlg::CloudSetupDlg(wxWindow* parent, Zstring& folderPathPhrase, Zstrin const AbstractPath folderPath = createItemPathSftp(folderPathPhrase); const SftpLogin login = extractSftpLogin(folderPath.afsDevice); //noexcept - if (login.port > 0) - m_textCtrlPort->ChangeValue(numberTo<wxString>(login.port)); + if (login.portCfg > 0) + m_textCtrlPort->ChangeValue(numberTo<wxString>(login.portCfg)); m_textCtrlServer ->ChangeValue(utfTo<wxString>(login.server)); m_textCtrlUserName ->ChangeValue(utfTo<wxString>(login.username)); sftpAuthType_ = login.authType; - m_textCtrlPasswordHidden->ChangeValue(utfTo<wxString>(login.password)); + if (login.password) + m_textCtrlPasswordHidden->ChangeValue(utfTo<wxString>(*login.password)); + else + m_checkBoxPasswordPrompt->SetValue(true); m_textCtrlKeyfilePath ->ChangeValue(utfTo<wxString>(login.privateKeyFilePath)); m_textCtrlServerPath ->ChangeValue(utfTo<wxString>(FILE_NAME_SEPARATOR + folderPath.afsPath.value)); m_checkBoxAllowZlib ->SetValue(login.allowZlib); @@ -357,11 +364,14 @@ CloudSetupDlg::CloudSetupDlg(wxWindow* parent, Zstring& folderPathPhrase, Zstrin const AbstractPath folderPath = createItemPathFtp(folderPathPhrase); const FtpLogin login = extractFtpLogin(folderPath.afsDevice); //noexcept - if (login.port > 0) - m_textCtrlPort->ChangeValue(numberTo<wxString>(login.port)); + if (login.portCfg > 0) + m_textCtrlPort->ChangeValue(numberTo<wxString>(login.portCfg)); m_textCtrlServer ->ChangeValue(utfTo<wxString>(login.server)); m_textCtrlUserName ->ChangeValue(utfTo<wxString>(login.username)); - m_textCtrlPasswordHidden ->ChangeValue(utfTo<wxString>(login.password)); + if (login.password) + m_textCtrlPasswordHidden ->ChangeValue(utfTo<wxString>(*login.password)); + else + m_checkBoxPasswordPrompt->SetValue(true); m_textCtrlServerPath ->ChangeValue(utfTo<wxString>(FILE_NAME_SEPARATOR + folderPath.afsPath.value)); (login.useTls ? m_radioBtnEncryptSsl : m_radioBtnEncryptNone)->SetValue(true); m_spinCtrlTimeout ->SetValue(login.timeoutSec); @@ -379,7 +389,8 @@ CloudSetupDlg::CloudSetupDlg(wxWindow* parent, Zstring& folderPathPhrase, Zstrin //set up default view for dialog size calculation bSizerGdrive->Show(false); bSizerFtpEncrypt->Show(false); - m_textCtrlPasswordHidden->Hide(); + m_textCtrlPasswordVisible->Hide(); + m_checkBoxPasswordPrompt->Hide(); GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! @@ -516,13 +527,26 @@ void CloudSetupDlg::onDetectServerChannelLimit(wxCommandEvent& event) m_spinCtrlChannelCountSftp->SetSelection(0, 0); //some visual feedback: clear selection m_spinCtrlChannelCountSftp->Refresh(); //both needed for wxGTK: meh! m_spinCtrlChannelCountSftp->Update(); // - - const int channelCountMax = getServerMaxChannelsPerConnection(extractSftpLogin(getFolderPath().afsDevice)); //throw FileError + + AbstractPath folderPath = getFolderPath(); //noexcept + //------------------------------------------------------------------- + auto requestPassword = [&, password = Zstring()](const std::wstring& msg, const std::wstring& lastErrorMsg) mutable + { + assert(runningOnMainThread()); + if (showPasswordPrompt(this, msg, lastErrorMsg, password) != ConfirmationButton::accept) + throw AbortProcess(); + return password; + }; + AFS::authenticateAccess(folderPath.afsDevice, requestPassword); //throw FileError, AbortProcess + //------------------------------------------------------------------- + + const int channelCountMax = getServerMaxChannelsPerConnection(extractSftpLogin(folderPath.afsDevice)); //throw FileError m_spinCtrlChannelCountSftp->SetValue(channelCountMax); m_spinCtrlChannelCountSftp->SetFocus(); //[!] otherwise selection is lost m_spinCtrlChannelCountSftp->SetSelection(-1, -1); //some visual feedback: select all } + catch (AbortProcess&) { return; } catch (const FileError& e) { showNotificationDialog(this, DialogInfoType::error, PopupDialogCfg().setDetailInstructions(e.toString())); @@ -537,7 +561,22 @@ void CloudSetupDlg::onToggleShowPassword(wxCommandEvent& event) m_textCtrlPasswordVisible->ChangeValue(m_textCtrlPasswordHidden->GetValue()); else m_textCtrlPasswordHidden->ChangeValue(m_textCtrlPasswordVisible->GetValue()); + updateGui(); + + wxTextCtrl& textCtrl = *(m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden); + textCtrl.SetFocus(); //macOS: selects text as unwanted side effect => *before* SetInsertionPointEnd() + textCtrl.SetInsertionPointEnd(); +} + + +void CloudSetupDlg::onTypingPassword(wxCommandEvent& event) +{ + assert(m_staticTextPassword->IsShown()); + const wxString password = (m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden)->GetValue(); + if (m_checkBoxShowPassword ->IsShown() != !password.empty() || //let's avoid some minor flicker + m_checkBoxPasswordPrompt->IsShown() != password.empty()) //in updateGui() Layout() + updateGui(); } @@ -606,6 +645,13 @@ void CloudSetupDlg::updateGui() { m_textCtrlPasswordVisible->Show( m_checkBoxShowPassword->GetValue()); m_textCtrlPasswordHidden ->Show(!m_checkBoxShowPassword->GetValue()); + + m_textCtrlPasswordVisible->Enable(!m_checkBoxPasswordPrompt->GetValue()); + m_textCtrlPasswordHidden ->Enable(!m_checkBoxPasswordPrompt->GetValue()); + + const wxString password = (m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden)->GetValue(); + m_checkBoxShowPassword ->Show(!password.empty()); + m_checkBoxPasswordPrompt->Show( password.empty()); } switch (type_) @@ -654,6 +700,55 @@ void CloudSetupDlg::updateGui() } +bool CloudSetupDlg::validateParameters() +{ + if (type_ == CloudType::sftp || + type_ == CloudType::ftp) + { + if (trimCpy(m_textCtrlServer->GetValue()).empty()) + { + showNotificationDialog(this, DialogInfoType::info, PopupDialogCfg().setMainInstructions(_("Server name must not be empty."))); + m_textCtrlServer->SetFocus(); + return false; + } + } + + switch (type_) + { + case CloudType::gdrive: + if (m_listBoxGdriveUsers->GetSelection() == wxNOT_FOUND) + { + showNotificationDialog(this, DialogInfoType::info, PopupDialogCfg().setMainInstructions(_("Please select a user account first."))); + return false; + } + break; + + case CloudType::sftp: + //username *required* for SFTP, but optional for FTP: libcurl will use "anonymous" + if (trimCpy(m_textCtrlUserName->GetValue()).empty()) + { + showNotificationDialog(this, DialogInfoType::info, PopupDialogCfg().setMainInstructions(_("Please enter a username."))); + m_textCtrlUserName->SetFocus(); + return false; + } + + if (sftpAuthType_ == SftpAuthType::keyFile) + if (trimCpy(m_textCtrlKeyfilePath->GetValue()).empty()) + { + showNotificationDialog(this, DialogInfoType::info, PopupDialogCfg().setMainInstructions(_("Please enter a file path."))); + //don't show error icon to follow "Windows' encouraging tone" + m_textCtrlKeyfilePath->SetFocus(); + return false; + } + break; + + case CloudType::ftp: + break; + } + return true; +} + + AbstractPath CloudSetupDlg::getFolderPath() const { //clean up (messy) user input, but no trim: support folders with trailing blanks! @@ -686,11 +781,14 @@ AbstractPath CloudSetupDlg::getFolderPath() const { SftpLogin login; login.server = utfTo<Zstring>(m_textCtrlServer ->GetValue()); - login.port = stringTo<int> (m_textCtrlPort ->GetValue()); //0 if empty + login.portCfg = stringTo<int> (m_textCtrlPort ->GetValue()); //0 if empty login.username = utfTo<Zstring>(m_textCtrlUserName->GetValue()); login.authType = sftpAuthType_; login.privateKeyFilePath = utfTo<Zstring>(m_textCtrlKeyfilePath->GetValue()); - login.password = utfTo<Zstring>((m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden)->GetValue()); + if (m_checkBoxPasswordPrompt->GetValue()) + login.password = std::nullopt; + else + login.password = utfTo<Zstring>((m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden)->GetValue()); login.allowZlib = m_checkBoxAllowZlib->GetValue(); login.timeoutSec = m_spinCtrlTimeout->GetValue(); login.traverserChannelsPerConnection = m_spinCtrlChannelCountSftp->GetValue(); @@ -701,9 +799,12 @@ AbstractPath CloudSetupDlg::getFolderPath() const { FtpLogin login; login.server = utfTo<Zstring>(m_textCtrlServer ->GetValue()); - login.port = stringTo<int> (m_textCtrlPort ->GetValue()); //0 if empty + login.portCfg = stringTo<int> (m_textCtrlPort ->GetValue()); //0 if empty login.username = utfTo<Zstring>(m_textCtrlUserName->GetValue()); - login.password = utfTo<Zstring>((m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden)->GetValue()); + if (m_checkBoxPasswordPrompt->GetValue()) + login.password = std::nullopt; + else + login.password = utfTo<Zstring>((m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden)->GetValue()); login.useTls = m_radioBtnEncryptSsl->GetValue(); login.timeoutSec = m_spinCtrlTimeout->GetValue(); return AbstractPath(condenseToFtpDevice(login), serverRelPath); //noexcept @@ -716,10 +817,26 @@ AbstractPath CloudSetupDlg::getFolderPath() const void CloudSetupDlg::onBrowseCloudFolder(wxCommandEvent& event) { - AbstractPath folderPath = getFolderPath(); //noexcept + if (!validateParameters()) + return; - if (!AFS::getParentPath(folderPath)) - try //for (S)FTP it makes more sense to start with the home directory rather than root (which often denies access!) + AbstractPath folderPath = getFolderPath(); //noexcept + try + { + //------------------------------------------------------------------- + auto requestPassword = [&, password = Zstring()](const std::wstring& msg, const std::wstring& lastErrorMsg) mutable + { + assert(runningOnMainThread()); + if (showPasswordPrompt(this, msg, lastErrorMsg, password) != ConfirmationButton::accept) + throw AbortProcess(); + return password; + }; + AFS::authenticateAccess(folderPath.afsDevice, requestPassword); //throw FileError, AbortProcess + //caveat: this could block *indefinitely* for Google Drive, but luckily already authenticated in this context + //------------------------------------------------------------------- + // + //for (S)FTP it makes more sense to start with the home directory rather than root (which often denies access!) + if (!AFS::getParentPath(folderPath)) { if (type_ == CloudType::sftp) folderPath.afsPath = getSftpHomePath(extractSftpLogin(folderPath.afsDevice)); //throw FileError @@ -727,11 +844,13 @@ void CloudSetupDlg::onBrowseCloudFolder(wxCommandEvent& event) if (type_ == CloudType::ftp) folderPath.afsPath = getFtpHomePath(extractFtpLogin(folderPath.afsDevice)); //throw FileError } - catch (const FileError& e) - { - showNotificationDialog(this, DialogInfoType::error, PopupDialogCfg().setDetailInstructions(e.toString())); - return; - } + } + catch (AbortProcess&) { return; } + catch (const FileError& e) + { + showNotificationDialog(this, DialogInfoType::error, PopupDialogCfg().setDetailInstructions(e.toString())); + return; + } if (showAbstractFolderPicker(this, folderPath) == ConfirmationButton::accept) m_textCtrlServerPath->ChangeValue(utfTo<wxString>(FILE_NAME_SEPARATOR + folderPath.afsPath.value)); @@ -741,14 +860,8 @@ void CloudSetupDlg::onBrowseCloudFolder(wxCommandEvent& event) void CloudSetupDlg::onOkay(wxCommandEvent& event) { //------- parameter validation (BEFORE writing output!) ------- - if (type_ == CloudType::sftp && sftpAuthType_ == SftpAuthType::keyFile) - if (trimCpy(m_textCtrlKeyfilePath->GetValue()).empty()) - { - showNotificationDialog(this, DialogInfoType::info, PopupDialogCfg().setMainInstructions(_("Please enter a file path."))); - //don't show error icon to follow "Windows' encouraging tone" - m_textCtrlKeyfilePath->SetFocus(); - return; - } + if (!validateParameters()) + return; //------------------------------------------------------------- folderPathPhraseOut_ = AFS::getInitPathPhrase(getFolderPath()); @@ -1212,9 +1325,9 @@ private: {[](const XmlGlobalSettings& gs){ return gs.warnDlgs.warnFoldersDifferInCase; }, []( XmlGlobalSettings& gs, bool show){ gs.warnDlgs.warnFoldersDifferInCase = show; }, _("The following folder paths differ in case. Please use a single form in order to avoid duplicate accesses.")}, {[](const XmlGlobalSettings& gs){ return gs.warnDlgs.warnDependentFolderPair; }, - []( XmlGlobalSettings& gs, bool show){ gs.warnDlgs.warnDependentFolderPair = show; }, _("One base folder of a folder pair is contained in the other one.") + L' ' + _("The folder should be excluded from synchronization via filter.")}, + []( XmlGlobalSettings& gs, bool show){ gs.warnDlgs.warnDependentFolderPair = show; }, _("One folder of the folder pair is a subfolder of the other.") + L' ' + _("The folder should be excluded via filter.")}, {[](const XmlGlobalSettings& gs){ return gs.warnDlgs.warnDependentBaseFolders; }, - []( XmlGlobalSettings& gs, bool show){ gs.warnDlgs.warnDependentBaseFolders = show; }, _("Some files will be synchronized as part of multiple base folders.") + L' ' + _("To avoid conflicts, set up exclude filters so that each updated file is included by only one base folder.")}, + []( XmlGlobalSettings& gs, bool show){ gs.warnDlgs.warnDependentBaseFolders = show; }, _("Some files will be synchronized as part of multiple folder pairs.") + L' ' + _("To avoid conflicts, set up exclude filters so that each updated file is included by only one folder pair.")}, {[](const XmlGlobalSettings& gs){ return gs.warnDlgs.warnSignificantDifference; }, []( XmlGlobalSettings& gs, bool show){ gs.warnDlgs.warnSignificantDifference = show; }, _("The following folders are significantly different. Please check that the correct folders are selected for synchronization.")}, {[](const XmlGlobalSettings& gs){ return gs.warnDlgs.warnNotEnoughDiskSpace; }, @@ -1228,7 +1341,7 @@ private: {[](const XmlGlobalSettings& gs){ return gs.warnDlgs.warnDirectoryLockFailed; }, []( XmlGlobalSettings& gs, bool show){ gs.warnDlgs.warnDirectoryLockFailed = show; }, _("Cannot set directory locks for the following folders:")}, {[](const XmlGlobalSettings& gs){ return gs.warnDlgs.warnVersioningFolderPartOfSync; }, - []( XmlGlobalSettings& gs, bool show){ gs.warnDlgs.warnVersioningFolderPartOfSync = show; }, _("The versioning folder is contained in a base folder.") + L' ' + _("The folder should be excluded from synchronization via filter.")}, + []( XmlGlobalSettings& gs, bool show){ gs.warnDlgs.warnVersioningFolderPartOfSync = show; }, _("The versioning folder is part of the synchronization.") + L' ' + _("The folder should be excluded via filter.")}, //*INDENT-ON* }; @@ -1306,8 +1419,7 @@ OptionsDlg::OptionsDlg(wxWindow* parent, XmlGlobalSettings& globalCfg) : wxCommandEvent chkEvent(wxEVT_CHECKLISTBOX); chkEvent.SetInt(selection[0]); - if (wxEvtHandler* evtHandler = checklist.GetEventHandler()) - evtHandler->ProcessEvent(chkEvent); + checklist.GetEventHandler()->ProcessEvent(chkEvent); } return; } @@ -1729,6 +1841,113 @@ ConfirmationButton fff::showSelectTimespanDlg(wxWindow* parent, time_t& timeFrom namespace { +class PasswordPromptDlg : public PasswordPromptDlgGenerated +{ +public: + PasswordPromptDlg(wxWindow* parent, const std::wstring& msg, const std::wstring& lastErrorMsg /*optional*/, Zstring& password); + +private: + void onOkay (wxCommandEvent& event) override; + void onCancel(wxCommandEvent& event) override { EndModal(static_cast<int>(ConfirmationButton::cancel)); } + void onClose (wxCloseEvent& event) override { EndModal(static_cast<int>(ConfirmationButton::cancel)); } + + void onToggleShowPassword(wxCommandEvent& event) override; + + void updateGui(); + + //work around defunct keyboard focus on macOS (or is it wxMac?) => not needed for this dialog! + //void onLocalKeyEvent(wxKeyEvent& event); + + //output-only parameters: + Zstring& passwordOut_; +}; + + +PasswordPromptDlg::PasswordPromptDlg(wxWindow* parent, const std::wstring& msg, const std::wstring& lastErrorMsg /*optional*/, Zstring& password) : + PasswordPromptDlgGenerated(parent), + passwordOut_(password) +{ + setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOkay).setCancel(m_buttonCancel)); + + wxString titleTmp; + if (!parent || !parent->IsShownOnScreen()) + titleTmp = wxTheApp->GetAppDisplayName(); + SetTitle(titleTmp); + + const int maxWidthDip = 600; + + m_staticTextMain->SetLabelText(msg); + m_staticTextMain->Wrap(fastFromDIP(maxWidthDip)); + + m_checkBoxShowPassword->SetValue(false); + + m_textCtrlPasswordHidden->ChangeValue(utfTo<wxString>(password)); + + bSizerError->Show(!lastErrorMsg.empty()); + if (!lastErrorMsg.empty()) + { + setImage(*m_bitmapError, loadImage("msg_error", fastFromDIP(32))); + + m_staticTextError->SetLabelText(lastErrorMsg); + m_staticTextError->Wrap(fastFromDIP(maxWidthDip) - m_bitmapError->GetSize().x - 10 /*border in non-DIP pixel*/); + } + + //set up default view for dialog size calculation + m_textCtrlPasswordVisible->Hide(); + + GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() + //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! + Center(); //needs to be re-applied after a dialog size change! + + updateGui(); //*after* SetSizeHints when standard dialog height has been calculated + + //m_textCtrlPasswordHidden->SelectAll(); -> apparantly implicitly caused by SetFocus!? + m_textCtrlPasswordHidden->SetFocus(); +} + + +void PasswordPromptDlg::onToggleShowPassword(wxCommandEvent& event) +{ + if (m_checkBoxShowPassword->GetValue()) + m_textCtrlPasswordVisible->ChangeValue(m_textCtrlPasswordHidden->GetValue()); + else + m_textCtrlPasswordHidden->ChangeValue(m_textCtrlPasswordVisible->GetValue()); + + updateGui(); + + wxTextCtrl& textCtrl = *(m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden); + textCtrl.SetFocus(); //macOS: selects text as unwanted side effect => *before* SetInsertionPointEnd() + textCtrl.SetInsertionPointEnd(); +} + + +void PasswordPromptDlg::updateGui() +{ + m_textCtrlPasswordVisible->Show( m_checkBoxShowPassword->GetValue()); + m_textCtrlPasswordHidden ->Show(!m_checkBoxShowPassword->GetValue()); + + Layout(); + Refresh(); +} + + +void PasswordPromptDlg::onOkay(wxCommandEvent& event) +{ + passwordOut_ = utfTo<Zstring>((m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden)->GetValue()); + EndModal(static_cast<int>(ConfirmationButton::accept)); +} +} + +ConfirmationButton fff::showPasswordPrompt(wxWindow* parent, const std::wstring& msg, const std::wstring& lastErrorMsg /*optional*/, Zstring& password) +{ + PasswordPromptDlg dlg(parent, msg, lastErrorMsg, password); + return static_cast<ConfirmationButton>(dlg.ShowModal()); +} + +//######################################################################################## + +namespace +{ class CfgHighlightDlg : public CfgHighlightDlgGenerated { public: @@ -1751,13 +1970,12 @@ CfgHighlightDlg::CfgHighlightDlg(wxWindow* parent, int& cfgHistSyncOverdueDays) CfgHighlightDlgGenerated(parent), cfgHistSyncOverdueDaysOut_(cfgHistSyncOverdueDays) { + setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOkay).setCancel(m_buttonCancel)); m_staticTextHighlight->Wrap(fastFromDIP(300)); m_spinCtrlOverdueDays->SetMinSize({fastFromDIP(70), -1}); //Hack: set size (why does wxWindow::Size() not work?) - setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOkay).setCancel(m_buttonCancel)); - m_spinCtrlOverdueDays->SetValue(cfgHistSyncOverdueDays); GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() @@ -1838,8 +2056,8 @@ void ActivationDlg::onCopyUrl(wxCommandEvent& event) { setClipboardText(m_richTextManualActivationUrl->GetValue()); - m_richTextManualActivationUrl->SetFocus(); //[!] otherwise selection is lost - m_richTextManualActivationUrl->SelectAll(); //some visual feedback + m_richTextManualActivationUrl->SetFocus(); //[!] otherwise selection is lost + m_richTextManualActivationUrl->SelectAll(); //some visual feedback } diff --git a/FreeFileSync/Source/ui/small_dlgs.h b/FreeFileSync/Source/ui/small_dlgs.h index 9f4b896c..eec1eca2 100644 --- a/FreeFileSync/Source/ui/small_dlgs.h +++ b/FreeFileSync/Source/ui/small_dlgs.h @@ -43,6 +43,8 @@ zen::ConfirmationButton showOptionsDlg(wxWindow* parent, XmlGlobalSettings& glob zen::ConfirmationButton showSelectTimespanDlg(wxWindow* parent, time_t& timeFrom, time_t& timeTo); +zen::ConfirmationButton showPasswordPrompt(wxWindow* parent, const std::wstring& msg, const std::wstring& lastErrorMsg /*optional*/, Zstring& password); + zen::ConfirmationButton showCfgHighlightDlg(wxWindow* parent, int& cfgHistSyncOverdueDays); zen::ConfirmationButton showCloudSetupDialog(wxWindow* parent, Zstring& folderPathPhrase, Zstring& sftpKeyFileLastSelected, diff --git a/FreeFileSync/Source/ui/sync_cfg.cpp b/FreeFileSync/Source/ui/sync_cfg.cpp index 69833505..66acc204 100644 --- a/FreeFileSync/Source/ui/sync_cfg.cpp +++ b/FreeFileSync/Source/ui/sync_cfg.cpp @@ -185,7 +185,7 @@ bool sanitizeFilter(FilterConfig& filterCfg, const std::vector<AbstractPath>& ba detailsMsg.pop_back(); switch (showConfirmationDialog(parent, DialogInfoType::info, PopupDialogCfg(). - setMainInstructions(_("Each filter item must be a path relative to the base folders. The following changes are suggested:")). + setMainInstructions(_("Each filter item must be a path relative to the selected folder pairs. The following changes are suggested:")). setDetailInstructions(detailsMsg), _("&Change"))) { case ConfirmationButton::accept: //change @@ -913,7 +913,7 @@ void ConfigDialog::onFilterKeyEvent(wxKeyEvent& event) { case 'A': //CTRL + A if (auto textCtrl = dynamic_cast<wxTextCtrl*>(event.GetEventObject())) - textCtrl->SetSelection(-1, -1); //select all + textCtrl->SelectAll(); return; } @@ -1654,7 +1654,7 @@ bool ConfigDialog::unselectFolderPairConfig(bool validateParams) if (AFS::isNullPath(createAbstractPath(syncCfg->versioningFolderPhrase))) { m_notebook->ChangeSelection(static_cast<size_t>(SyncConfigPanel::sync)); - showNotificationDialog(this, DialogInfoType::info, PopupDialogCfg().setMainInstructions(_("Please enter a target folder for versioning."))); + showNotificationDialog(this, DialogInfoType::info, PopupDialogCfg().setMainInstructions(_("Please enter a target folder."))); //don't show error icon to follow "Windows' encouraging tone" m_versioningFolderPath->SetFocus(); return false; diff --git a/FreeFileSync/Source/ui/tray_icon.h b/FreeFileSync/Source/ui/tray_icon.h index 18058e46..da11ac55 100644 --- a/FreeFileSync/Source/ui/tray_icon.h +++ b/FreeFileSync/Source/ui/tray_icon.h @@ -26,7 +26,7 @@ namespace fff class FfsTrayIcon { public: - FfsTrayIcon(const std::function<void()>& requestResume); //callback only held during lifetime of this instance + explicit FfsTrayIcon(const std::function<void()>& requestResume); //callback only held during lifetime of this instance ~FfsTrayIcon(); void setToolTip(const wxString& toolTip); diff --git a/FreeFileSync/Source/ui/tree_grid.cpp b/FreeFileSync/Source/ui/tree_grid.cpp index 313b5097..f53b212f 100644 --- a/FreeFileSync/Source/ui/tree_grid.cpp +++ b/FreeFileSync/Source/ui/tree_grid.cpp @@ -1146,8 +1146,8 @@ private: sortAscending = !ascending; getDataView().setSortDirection(colTypeTree, sortAscending); + grid_.Refresh(); //just in case, but setSortDirection() should not change grid size grid_.clearSelection(GridEventPolicy::allow); - grid_.Refresh(); } void expandNode(size_t row) diff --git a/FreeFileSync/Source/ui/version_check.cpp b/FreeFileSync/Source/ui/version_check.cpp index 6499818e..543c9510 100644 --- a/FreeFileSync/Source/ui/version_check.cpp +++ b/FreeFileSync/Source/ui/version_check.cpp @@ -259,7 +259,7 @@ void fff::checkForUpdateNow(wxWindow& parent, std::string& lastOnlineVersion) showNotificationDialog(&parent, DialogInfoType::info, PopupDialogCfg(). setIcon(loadImage("update_check")). setTitle(_("Check for Program Updates")). - setMainInstructions(_("FreeFileSync is up to date."))); + setMainInstructions(_("FreeFileSync is up-to-date."))); } catch (const SysError& e) { diff --git a/FreeFileSync/Source/version/version.h b/FreeFileSync/Source/version/version.h index 30acb43a..4e3f0c59 100644 --- a/FreeFileSync/Source/version/version.h +++ b/FreeFileSync/Source/version/version.h @@ -3,7 +3,7 @@ namespace fff { -const char ffsVersion[] = "11.29"; //internal linkage! +const char ffsVersion[] = "12.0"; //internal linkage! const char FFS_VERSION_SEPARATOR = '.'; } diff --git a/License.txt b/License.txt index 2cd32bd9..4d8169cb 100644 --- a/License.txt +++ b/License.txt @@ -2,6 +2,7 @@ A. GNU GENERAL PUBLIC LICENSE B. OpenSSL License C. curl License D. libssh2 License +E. PuTTY License ================================================================== @@ -878,4 +879,37 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - END OF TERMS AND CONDITIONS +================================================================== + +E. PuTTY License + +PuTTY is copyright 1997-2022 Simon Tatham. + +Portions copyright Robert de Bath, Joris van Rantwijk, Delian +Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, +Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus +Kuhn, Colin Watson, Christopher Staite, Lorenz Diener, Christian +Brabandt, Jeff Smith, Pavel Kryukov, Maxim Kuznetsov, Svyatoslav +Kuzmich, Nico Williams, Viktor Dukhovni, Josh Dersch, Lars Brinkhoff, +and CORE SDI S.A. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + END OF TERMS AND CONDITIONS diff --git a/libssh2/libssh2_wrap.h b/libssh2/libssh2_wrap.h index d4365538..5a3782bc 100644 --- a/libssh2/libssh2_wrap.h +++ b/libssh2/libssh2_wrap.h @@ -116,7 +116,6 @@ inline int libssh2_sftp_rename(LIBSSH2_SFTP* sftp, const std::string& pathFrom, } - namespace zen { namespace @@ -183,33 +182,33 @@ std::wstring formatSshStatusCode(int sc) std::wstring formatSftpStatusCode(unsigned long sc) { + //libssh2 only defines LIBSSH2_FX_OK(0) to LIBSSH2_FX_LINK_LOOP(21) + //=> all SFTP codes: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.1 switch (sc) { - //*INDENT-OFF* - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_OK); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_EOF); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_NO_SUCH_FILE); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_PERMISSION_DENIED); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_FAILURE); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_BAD_MESSAGE); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_NO_CONNECTION); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_CONNECTION_LOST); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_OP_UNSUPPORTED); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_INVALID_HANDLE); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_NO_SUCH_PATH); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_FILE_ALREADY_EXISTS); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_WRITE_PROTECT); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_NO_MEDIA); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_QUOTA_EXCEEDED); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_UNKNOWN_PRINCIPAL); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_LOCK_CONFLICT); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_DIR_NOT_EMPTY); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_NOT_A_DIRECTORY); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_INVALID_FILENAME); - ZEN_CHECK_CASE_FOR_CONSTANT(LIBSSH2_FX_LINK_LOOP); - - //SFTP error codes missing from libssh2: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.1 + //*INDENT-OFF* + case 0: return L"SSH_FX_OK"; + case 1: return L"SSH_FX_EOF"; + case 2: return L"SSH_FX_NO_SUCH_FILE"; + case 3: return L"SSH_FX_PERMISSION_DENIED"; + case 4: return L"SSH_FX_FAILURE"; + case 5: return L"SSH_FX_BAD_MESSAGE"; + case 6: return L"SSH_FX_NO_CONNECTION"; + case 7: return L"SSH_FX_CONNECTION_LOST"; + case 8: return L"SSH_FX_OP_UNSUPPORTED"; + case 9: return L"SSH_FX_INVALID_HANDLE"; + case 10: return L"SSH_FX_NO_SUCH_PATH"; + case 11: return L"SSH_FX_FILE_ALREADY_EXISTS"; + case 12: return L"SSH_FX_WRITE_PROTECT"; + case 13: return L"SSH_FX_NO_MEDIA"; + case 14: return L"SSH_FX_NO_SPACE_ON_FILESYSTEM"; + case 15: return L"SSH_FX_QUOTA_EXCEEDED"; + case 16: return L"SSH_FX_UNKNOWN_PRINCIPAL"; + case 17: return L"SSH_FX_LOCK_CONFLICT"; + case 18: return L"SSH_FX_DIR_NOT_EMPTY"; + case 19: return L"SSH_FX_NOT_A_DIRECTORY"; + case 20: return L"SSH_FX_INVALID_FILENAME"; + case 21: return L"SSH_FX_LINK_LOOP"; case 22: return L"SSH_FX_CANNOT_DELETE"; case 23: return L"SSH_FX_INVALID_PARAMETER"; case 24: return L"SSH_FX_FILE_IS_A_DIRECTORY"; diff --git a/wx+/context_menu.h b/wx+/context_menu.h index d1d2bd9f..92d8504c 100644 --- a/wx+/context_menu.h +++ b/wx+/context_menu.h @@ -126,6 +126,9 @@ void fixMenuIcons(wxMenu& menu) } +//better call wxClipboard::Get()->Flush() *once* during app exit instead of after each setClipboardText()? +// => OleFlushClipboard: "Carries out the clipboard shutdown sequence" +// => maybe this helps with clipboard randomly "forgetting" content after app exit? inline void setClipboardText(const wxString& txt) { @@ -133,9 +136,8 @@ void setClipboardText(const wxString& txt) if (clip.Open()) { ZEN_ON_SCOPE_EXIT(clip.Close()); - [[maybe_unused]] const bool rv1 = clip.SetData(new wxTextDataObject(txt)); //ownership passed - [[maybe_unused]] const bool rv2 = clip.Flush(); - assert(rv1 && rv2); + [[maybe_unused]] const bool rv = clip.SetData(new wxTextDataObject(txt)); //ownership passed + assert(rv); } else assert(false); } @@ -147,6 +147,14 @@ void setScaleFactor(wxDC& dc, double scale) } +//add some sanity to moronic const/non-const wxRect::Intersect() +inline +wxRect getIntersection(const wxRect& rect1, const wxRect& rect2) +{ + return rect1.Intersect(rect2); +} + + //---------------------- implementation ------------------------ class RecursiveDcClipper { @@ -158,8 +166,7 @@ public: { oldRect_ = it->second; - wxRect tmp = r; - tmp.Intersect(*oldRect_); //better safe than sorry + const wxRect tmp = getIntersection(r, *oldRect_); //better safe than sorry assert(!tmp.IsEmpty()); //"setting an empty clipping region is equivalent to DestroyClippingRegion()" diff --git a/wx+/file_drop.cpp b/wx+/file_drop.cpp index 86db57c1..cd233c56 100644 --- a/wx+/file_drop.cpp +++ b/wx+/file_drop.cpp @@ -60,8 +60,7 @@ private: filePaths.push_back(utfTo<Zstring>(file)); //create a custom event on drop window: execute event after file dropping is completed! (after mouse is released) - if (wxEvtHandler* handler = dropWindow_.GetEventHandler()) - handler->AddPendingEvent(FileDropEvent(filePaths)); + dropWindow_.GetEventHandler()->AddPendingEvent(FileDropEvent(filePaths)); return true; } diff --git a/wx+/graph.cpp b/wx+/graph.cpp index ce65d299..07268f34 100644 --- a/wx+/graph.cpp +++ b/wx+/graph.cpp @@ -247,7 +247,7 @@ void cutPoints(std::vector<CurvePoint>& curvePoints, std::vector<unsigned char>& auto savePoint = [&](const CurvePoint& pt, bool markedOob) { curvePointsTmp.push_back(pt); oobMarkerTmp.push_back(markedOob); }; - bool pointInside = isInside(curvePoints[0]); + bool pointInside = isInside(curvePoints[0]); if (pointInside) savePoint(curvePoints[0], isMarkedOob(0)); @@ -283,7 +283,7 @@ void cutPoints(std::vector<CurvePoint>& curvePoints, std::vector<unsigned char>& struct GetIntersectionX { explicit GetIntersectionX(double x) : x_(x) {} - + CurvePoint operator()(const CurvePoint& from, const CurvePoint& to) const { const double deltaX = to.x - from.x; @@ -493,9 +493,7 @@ void Graph2D::onMouseLeftUp(wxMouseEvent& event) { if (activeSel_->getStartPos() != activeSel_->refCurrentPos()) //if it's just a single mouse click: discard selection { - GraphSelectEvent selEvent(activeSel_->refSelection()); //fire off GraphSelectEvent - if (wxEvtHandler* handler = GetEventHandler()) - handler->AddPendingEvent(selEvent); + GetEventHandler()->AddPendingEvent(GraphSelectEvent(activeSel_->refSelection())); oldSel_.push_back(activeSel_->refSelection()); //commit selection } diff --git a/wx+/grid.cpp b/wx+/grid.cpp index 0ffee3a7..f997d72c 100644 --- a/wx+/grid.cpp +++ b/wx+/grid.cpp @@ -295,9 +295,7 @@ public: template <class T> bool sendEventToParent(T&& event) //take both "rvalue + lvalues", return "true" if a suitable event handler function was found and executed, and the function did not call wxEvent::Skip. { - if (wxEvtHandler* evtHandler = parent_.GetEventHandler()) - return evtHandler->ProcessEvent(event); - return false; + return parent_.GetEventHandler()->ProcessEvent(event); } protected: @@ -1412,8 +1410,7 @@ private: if (!gridUpdatePending_) //without guarding, the number of outstanding async events can become very high during scrolling!! test case: Ubuntu: 170; Windows: 20 { gridUpdatePending_ = true; - wxCommandEvent scrollEvent(EVENT_GRID_HAS_SCROLLED); - AddPendingEvent(scrollEvent); //asynchronously call updateAfterScroll() + GetEventHandler()->AddPendingEvent(wxCommandEvent(EVENT_GRID_HAS_SCROLLED)); //asynchronously call updateAfterScroll() } } @@ -1776,8 +1773,7 @@ void Grid::onKeyDown(wxKeyEvent& event) const wxPoint mousePos = mainWin_->GetPosition() + wxPoint(0, clientPosMainWinY); //mainWin_-relative to Grid-relative GridContextMenuEvent contextEvent(mousePos); - if (wxEvtHandler* evtHandler = GetEventHandler()) - evtHandler->ProcessEvent(contextEvent); + GetEventHandler()->ProcessEvent(contextEvent); } return; @@ -1907,19 +1903,21 @@ void Grid::selectRange(size_t rowFirst, size_t rowLast, bool positive, GridEvent void Grid::selectRange2(size_t rowFirst, size_t rowLast, bool positive, const GridClickEvent* mouseClick, GridEventPolicy rangeEventPolicy) { assert(rowFirst <= rowLast); + assert(getRowCount() == selection_.gridSize()); + rowFirst = std::clamp<size_t>(rowFirst, 0, selection_.gridSize()); + rowLast = std::clamp<size_t>(rowLast, 0, selection_.gridSize()); - const size_t rowCount = getRowCount(); - rowFirst = std::clamp<size_t>(rowFirst, 0, rowCount); - rowLast = std::clamp<size_t>(rowLast, 0, rowCount); - - selection_.selectRange(rowFirst, rowLast, positive); - mainWin_->Refresh(); + if (rowFirst < rowLast && !selection_.matchesRange(rowFirst, rowLast, positive)) + { + selection_.selectRange(rowFirst, rowLast, positive); + mainWin_->Refresh(); + } + //issue event even for unchanged selection! e.g. MainWin::onMouseDown() temporarily clears range with GridEventPolicy::deny! if (rangeEventPolicy == GridEventPolicy::allow) { GridSelectEvent selEvent(rowFirst, rowLast, positive, mouseClick); - if (wxEvtHandler* evtHandler = GetEventHandler()) - [[maybe_unused]] const bool processed = evtHandler->ProcessEvent(selEvent); + [[maybe_unused]] const bool processed = GetEventHandler()->ProcessEvent(selEvent); } } @@ -1962,8 +1960,19 @@ void Grid::Refresh(bool eraseBackground, const wxRect* rect) updateWindowSizes(); } - if (selection_.gridSize() != rowCountNew) //clear selection only when needed (consider setSelectedRows()) - selection_.init(rowCountNew); + if (selection_.gridSize() != rowCountNew) + { + const bool priorSelection = !selection_.matchesRange(0, selection_.gridSize(), false /*positive*/); + + selection_.resize(rowCountNew); + + if (priorSelection) //clear selection only when needed + { + //clearSelection(GridEventPolicy::allow); -> no, we need async event to make filegrid::refresh(*m_gridMainL, *m_gridMainC, *m_gridMainR) work + selection_.clear(); + GetEventHandler()->AddPendingEvent(GridSelectEvent(0, rowCountNew, false /*positive*/, nullptr /*mouseClick*/)); + } + } wxScrolledWindow::Refresh(eraseBackground, rect); } @@ -2306,13 +2315,10 @@ void Grid::setColumnWidth(int width, size_t col, GridEventPolicy columnResizeEve if (columnResizeEventPolicy == GridEventPolicy::allow) { GridColumnResizeEvent sizeEvent(vcRs.offset, vcRs.type); - if (wxEvtHandler* evtHandler = GetEventHandler()) - { - if (notifyAsync) - evtHandler->AddPendingEvent(sizeEvent); - else - evtHandler->ProcessEvent(sizeEvent); - } + if (notifyAsync) + GetEventHandler()->AddPendingEvent(sizeEvent); + else + GetEventHandler()->ProcessEvent(sizeEvent); } } else @@ -97,9 +97,6 @@ struct GridContextMenuEvent : public wxEvent }; //------------------------------------------------------------------------------------------------------------ -class Grid; - - class GridData { public: @@ -113,21 +110,21 @@ public: virtual void renderCell (wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected, HoverArea rowHover); virtual int getBestSize (wxDC& dc, size_t row, ColumnType colType); //must correspond to renderCell()! virtual HoverArea getMouseHover (wxDC& dc, size_t row, ColumnType colType, int cellRelativePosX, int cellWidth) { return HoverArea::none; } - virtual std::wstring getToolTip (size_t row, ColumnType colType, HoverArea rowHover) { return std::wstring(); } + virtual std::wstring getToolTip ( size_t row, ColumnType colType, HoverArea rowHover) { return std::wstring(); } //label area: virtual std::wstring getColumnLabel(ColumnType colType) const = 0; virtual void renderColumnLabel(wxDC& dc, const wxRect& rect, ColumnType colType, bool enabled, bool highlighted); //default implementation virtual std::wstring getToolTip(ColumnType colType) const { return std::wstring(); } + //optional helper routines: static int getColumnGapLeft(); //for left-aligned text static wxColor getColorSelectionGradientFrom(); static wxColor getColorSelectionGradientTo(); - //optional helper routines: static void drawCellText(wxDC& dc, const wxRect& rect, const std::wstring& text, - int alignment = wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, const wxSize* textExtentHint = nullptr); //returns text extent - static wxRect drawCellBorder (wxDC& dc, const wxRect& rect); //returns inner rectangle + int alignment = wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, const wxSize* textExtentHint = nullptr); + static wxRect drawCellBorder(wxDC& dc, const wxRect& rect); //returns inner rectangle static wxRect drawColumnLabelBackground(wxDC& dc, const wxRect& rect, bool highlighted); //returns inner rectangle static void drawColumnLabelText (wxDC& dc, const wxRect& rect, const std::wstring& text, bool enabled); @@ -253,7 +250,7 @@ private: class Selection { public: - void init(size_t rowCount) { selected_.resize(rowCount); clear(); } + void resize(size_t rowCount) { selected_.resize(rowCount, false); } size_t gridSize() const { return selected_.size(); } @@ -266,20 +263,30 @@ private: return result; } - void clear() { selectRange(0, selected_.size(), false); } - bool isSelected(size_t row) const { return row < selected_.size() ? selected_[row] != 0 : false; } - void selectRange(size_t rowFirst, size_t rowLast, bool positive = true) //select [rowFirst, rowLast), trims if required! + bool matchesRange(size_t rowFirst, size_t rowLast, bool positive) { - if (rowFirst <= rowLast) + if (rowFirst <= rowLast && rowLast <= selected_.size()) { - rowFirst = std::clamp<size_t>(rowFirst, 0, selected_.size()); - rowLast = std::clamp<size_t>(rowLast, 0, selected_.size()); - - std::fill(selected_.begin() + rowFirst, selected_.begin() + rowLast, positive); + const auto rangeEnd = selected_.begin() + rowLast; + return std::find(selected_.begin() + rowFirst, rangeEnd, static_cast<unsigned char>(!positive)) == rangeEnd; } - else assert(false); + else + { + assert(false); + return false; + } + } + + void clear() { selectRange(0, selected_.size(), false); } + + void selectRange(size_t rowFirst, size_t rowLast, bool positive = true) //select [rowFirst, rowLast), trims if required! + { + assert(rowFirst <= rowLast && rowLast <= selected_.size()); + if (rowFirst < rowLast) + std::fill(selected_.begin() + std::min(rowFirst, selected_.size()), + selected_.begin() + std::min(rowLast, selected_.size()), positive); } private: diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp index 667b5912..823e867e 100644 --- a/wx+/image_resources.cpp +++ b/wx+/image_resources.cpp @@ -70,7 +70,7 @@ ImageHolder xbrzScale(int width, int height, const unsigned char* imageRgb, cons } -auto createScalerTask(const std::string& imageName, const wxImage& img, int hqScale, Protected<std::vector<std::pair<std::string, ImageHolder>>>& result) +auto createScalerTask(const std::string& imageName, const wxImage& img, int hqScale, Protected<std::vector<std::pair<std::string, ImageHolder>>>& protResult) { assert(runningOnMainThread()); return [imageName, @@ -78,10 +78,10 @@ auto createScalerTask(const std::string& imageName, const wxImage& img, int hqSc height = img.GetHeight(), //don't call wxWidgets functions from worker thread rgb = img.GetData(), // alpha = img.GetAlpha(), // - hqScale, &result] + hqScale, &protResult] { ImageHolder ih = xbrzScale(width, height, rgb, alpha, hqScale); - result.access([&](std::vector<std::pair<std::string, ImageHolder>>& r) { r.emplace_back(imageName, std::move(ih)); }); + protResult.access([&](std::vector<std::pair<std::string, ImageHolder>>& result) { result.emplace_back(imageName, std::move(ih)); }); }; } @@ -97,7 +97,7 @@ public: { assert(runningOnMainThread()); imgKeeper_.push_back(img); //retain (ref-counted) wxImage so that the rgb/alpha pointers remain valid after passed to threads - threadGroup_->run(createScalerTask(imageName, img, hqScale_, result_)); + threadGroup_->run(createScalerTask(imageName, img, hqScale_, protResult_)); } std::unordered_map<std::string, wxImage> waitAndGetResult() @@ -107,9 +107,9 @@ public: std::unordered_map<std::string, wxImage> output; - result_.access([&](std::vector<std::pair<std::string, ImageHolder>>& r) + protResult_.access([&](std::vector<std::pair<std::string, ImageHolder>>& result) { - for (auto& [imageName, ih] : r) + for (auto& [imageName, ih] : result) { wxImage img(ih.getWidth(), ih.getHeight(), ih.releaseRgb(), false /*static_data*/); //pass ownership img.SetAlpha(ih.releaseAlpha(), false /*static_data*/); @@ -123,7 +123,7 @@ public: private: const int hqScale_; std::vector<wxImage> imgKeeper_; - Protected<std::vector<std::pair<std::string, ImageHolder>>> result_; + Protected<std::vector<std::pair<std::string, ImageHolder>>> protResult_; using TaskType = FunctionReturnTypeT<decltype(&createScalerTask)>; std::optional<ThreadGroup<TaskType>> threadGroup_{ThreadGroup<TaskType>(std::max<int>(std::thread::hardware_concurrency(), 1), Zstr("xBRZ Scaler"))}; @@ -195,7 +195,7 @@ ImageBuffer::ImageBuffer(const Zstring& zipPath) //throw FileError catch (FileError&) //fall back to folder: dev build (only!?) { const Zstring fallbackFolder = beforeLast(zipPath, Zstr(".zip"), IfNotFoundReturn::none); - if (!itemStillExists(fallbackFolder)) //throw FileError + if (!itemExists(fallbackFolder)) //throw FileError throw; traverseFolder(fallbackFolder, [&](const FileInfo& fi) @@ -205,7 +205,7 @@ ImageBuffer::ImageBuffer(const Zstring& zipPath) //throw FileError std::string stream = getFileContent(fi.fullPath, nullptr /*notifyUnbufferedIO*/); //throw FileError streams.emplace_back(fi.itemName, std::move(stream)); } - }, nullptr, nullptr, [](const std::wstring& errorMsg) { throw FileError(errorMsg); }); + }, nullptr, nullptr); //throw FileError } //-------------------------------------------------------------------- diff --git a/wx+/no_flicker.h b/wx+/no_flicker.h index 185ee052..1c91bd48 100644 --- a/wx+/no_flicker.h +++ b/wx+/no_flicker.h @@ -123,7 +123,7 @@ void setTextWithUrls(wxRichTextCtrl& richCtrl, const wxString& newText) using KeyEventsFun = void(*)(wxKeyEvent& event); static const KeyEventsFun onKeyEvents = [](wxKeyEvent& event) { - wxRichTextCtrl& richCtrl = dynamic_cast<UserData*>(event.GetEventUserData())->richCtrl; //unclear if we can rely on event.GetEventObject() == richCtrl + wxRichTextCtrl& richCtrl2 = dynamic_cast<UserData*>(event.GetEventUserData())->richCtrl; //unclear if we can rely on event.GetEventObject() == richCtrl //CTRL/SHIFT + INS is broken for wxRichTextCtrl on Windows/Linux (apparently never was a thing on macOS) if (event.ControlDown()) @@ -131,8 +131,8 @@ void setTextWithUrls(wxRichTextCtrl& richCtrl, const wxString& newText) { case WXK_INSERT: case WXK_NUMPAD_INSERT: - assert(richCtrl.CanCopy()); //except when no selection - richCtrl.Copy(); + assert(richCtrl2.CanCopy()); //except when no selection + richCtrl2.Copy(); return; } @@ -141,8 +141,8 @@ void setTextWithUrls(wxRichTextCtrl& richCtrl, const wxString& newText) { case WXK_INSERT: case WXK_NUMPAD_INSERT: - assert(richCtrl.CanPaste()); //except wxTE_READONLY - richCtrl.Paste(); + assert(richCtrl2.CanPaste()); //except wxTE_READONLY + richCtrl2.Paste(); return; } event.Skip(); diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp index dfa5494f..c30426cb 100644 --- a/wx+/popup_dlg.cpp +++ b/wx+/popup_dlg.cpp @@ -150,15 +150,9 @@ public: if (iconTmp.IsOk()) setImage(*m_bitmapMsgType, iconTmp); - if (titleTmp.empty()) - SetTitle(wxTheApp->GetAppDisplayName()); - else - { - if (parent && parent->IsShownOnScreen()) - SetTitle(titleTmp); - else - SetTitle(wxTheApp->GetAppDisplayName() + SPACED_DASH + titleTmp); - } + if (!parent || !parent->IsShownOnScreen()) + titleTmp = wxTheApp->GetAppDisplayName() + (!titleTmp.empty() ? SPACED_DASH + titleTmp : wxString()); + SetTitle(titleTmp); int maxWidth = fastFromDIP(500); int maxHeight = fastFromDIP(400); //try to determine better value based on actual display resolution: diff --git a/wx+/popup_dlg_generated.cpp b/wx+/popup_dlg_generated.cpp index fb449d13..b7e3d94d 100644 --- a/wx+/popup_dlg_generated.cpp +++ b/wx+/popup_dlg_generated.cpp @@ -98,3 +98,27 @@ PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, con PopupDialogGenerated::~PopupDialogGenerated() { } + +TooltipDlgGenerated::TooltipDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer158; + bSizer158 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapLeft = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer158->Add( m_bitmapLeft, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextMain = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextMain->Wrap( 600 ); + bSizer158->Add( m_staticTextMain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + this->SetSizer( bSizer158 ); + this->Layout(); + bSizer158->Fit( this ); +} + +TooltipDlgGenerated::~TooltipDlgGenerated() +{ +} diff --git a/wx+/popup_dlg_generated.h b/wx+/popup_dlg_generated.h index 6218c6d8..ce4e2ac8 100644 --- a/wx+/popup_dlg_generated.h +++ b/wx+/popup_dlg_generated.h @@ -70,3 +70,22 @@ public: }; +/////////////////////////////////////////////////////////////////////////////// +/// Class TooltipDlgGenerated +/////////////////////////////////////////////////////////////////////////////// +class TooltipDlgGenerated : public wxDialog +{ +private: + +protected: + +public: + wxStaticBitmap* m_bitmapLeft; + wxStaticText* m_staticTextMain; + + TooltipDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + + ~TooltipDlgGenerated(); + +}; + diff --git a/wx+/tooltip.cpp b/wx+/tooltip.cpp index a3fa770d..c56d80a1 100644 --- a/wx+/tooltip.cpp +++ b/wx+/tooltip.cpp @@ -27,10 +27,9 @@ const int TIP_WINDOW_OFFSET_DIP = 30; class Tooltip::TooltipDlgGenerated : public wxDialog { public: - TooltipDlgGenerated(wxWindow* parent) : wxDialog(parent, wxID_ANY, L"" /*title*/, wxDefaultPosition, wxDefaultSize, 0 /*style*/) + TooltipDlgGenerated(wxWindow* parent) : //Suse Linux/X11: needs parent window, else there are z-order issues + wxDialog(parent, wxID_ANY, L"" /*title*/, wxDefaultPosition, wxDefaultSize, 0 /*style*/) { - //Suse Linux/X11: needs parent window, else there are z-order issues - SetSizeHints(wxDefaultSize, wxDefaultSize); SetExtraStyle(this->GetExtraStyle() | wxWS_EX_TRANSIENT); SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK)); //both required: on Ubuntu background is black, foreground white! @@ -44,11 +43,11 @@ public: bSizer158->Add(staticTextMain_, 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5); SetSizer(bSizer158); - Layout(); - bSizer158->Fit(this); } + bool AcceptsFocus() const override { return false; } //any benefit? + wxStaticText* staticTextMain_ = nullptr; wxStaticBitmap* bitmapLeft_ = nullptr; }; @@ -61,21 +60,28 @@ void Tooltip::show(const wxString& text, wxPoint mousePos, const wxImage* img) const wxImage& newImg = img ? *img : wxNullImage; - if (!lastUsedImg_.IsSameAs(newImg)) + const bool imgChanged = !newImg.IsSameAs(lastUsedImg_); + const bool txtChanged = text != tipWindow_->staticTextMain_->GetLabelText(); + + if (imgChanged) { lastUsedImg_ = newImg; setImage(*tipWindow_->bitmapLeft_, newImg); - tipWindow_->Refresh(); //needed if bitmap size changed! + // tipWindow_->Refresh(); //needed if bitmap size changed! ->??? } - if (text != tipWindow_->staticTextMain_->GetLabelText()) + if (txtChanged) { tipWindow_->staticTextMain_->SetLabelText(text); tipWindow_->staticTextMain_->Wrap(fastFromDIP(600)); } - tipWindow_->GetSizer()->SetSizeHints(tipWindow_); //~=Fit() + SetMinSize() - //Linux: Fit() seems to be broken => this needs to be called EVERY time inside show, not only if text or bmp change + if (imgChanged || txtChanged) + { + //tipWindow_->Layout(); -> apparently not needed!? + tipWindow_->GetSizer()->SetSizeHints(tipWindow_); //~=Fit() + SetMinSize() + //Linux: Fit() seems to be broken => call EVERY time inside show, not only if text or bmp change -> still true?!? + } const wxPoint newPos = wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft ? mousePos - wxPoint(fastFromDIP(TIP_WINDOW_OFFSET_DIP) + tipWindow_->GetSize().GetWidth(), 0) : @@ -98,6 +104,7 @@ void Tooltip::hide() #if GTK_MAJOR_VERSION == 2 //the tooltip sometimes turns blank or is not shown again after it was hidden: e.g. drag-selection on middle grid tipWindow_->Destroy(); //apply brute force: tipWindow_ = nullptr; // + lastUsedImg_ = wxNullImage; #elif GTK_MAJOR_VERSION == 3 tipWindow_->Hide(); diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp index e0b4a338..235c466c 100644 --- a/zen/dir_watcher.cpp +++ b/zen/dir_watcher.cpp @@ -37,15 +37,18 @@ DirWatcher::DirWatcher(const Zstring& dirPath) : //throw FileError { std::function<void(const Zstring& path)> traverse; - traverse = [&traverse, &fullFolderList](const Zstring& path) + traverse = [&traverse, &fullFolderList](const Zstring& path) //throw FileError { traverseFolder(path, nullptr, - [&](const FolderInfo& fi ) { fullFolderList.push_back(fi.fullPath); traverse(fi.fullPath); }, - nullptr, //don't traverse into symlinks (analog to windows build) - [&](const std::wstring& errorMsg) { throw FileError(errorMsg); }); + [&](const FolderInfo& fi ) + { + fullFolderList.push_back(fi.fullPath); + traverse(fi.fullPath); //throw FileError + }, + nullptr /*don't traverse into symlinks (analog to Windows)*/); //throw FileError }; - traverse(baseDirPath_); + traverse(baseDirPath_); //throw FileError } //init diff --git a/zen/file_access.cpp b/zen/file_access.cpp index 0c28f325..d06202ba 100644 --- a/zen/file_access.cpp +++ b/zen/file_access.cpp @@ -31,51 +31,19 @@ namespace { -std::pair<Zstring, ItemType> getExistingPath(const Zstring& itemPath) //throw FileError +struct SysErrorCode : public zen::SysError { - try - { - return {itemPath, getItemType(itemPath)}; //throw FileError - } - catch (const FileError& e) //not existing or access error - { - const std::optional<Zstring> parentPath = getParentFolderPath(itemPath); - if (!parentPath) //device root - throw; - //else: let's dig deeper... don't bother checking Win32 codes; e.g. not existing item may have the codes: - // ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, ERROR_INVALID_NAME, ERROR_INVALID_DRIVE, - // ERROR_NOT_READY, ERROR_INVALID_PARAMETER, ERROR_BAD_PATHNAME, ERROR_BAD_NETPATH => not reliable - - auto [existingPath, existingType] = getExistingPath(*parentPath); //throw FileError - - if (existingPath == *parentPath && existingType != ItemType::file /*obscure, but possible (and not an error)*/) - try - { - const Zstring itemName = afterLast(itemPath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all); - assert(!itemName.empty()); - - traverseFolder(*parentPath, - [&](const FileInfo& fi) { if (fi.itemName == itemName) throw ItemType::file; }, //case-sensitive! itemPath must be normalized! - [&](const FolderInfo& fi) { if (fi.itemName == itemName) throw ItemType::folder; }, - [&](const SymlinkInfo& si) { if (si.itemName == itemName) throw ItemType::symlink; }, - [](const std::wstring& errorMsg) { throw FileError(errorMsg); }); - } - catch (const ItemType&) //finding the item after getItemType() previously failed is exceptional - { - throw FileError(_("Temporary access error:") + L' ' + e.toString()); - } + SysErrorCode(const std::string& functionName, ErrorCode ec) : SysError(formatSystemError(functionName, ec)), errorCode(ec) {} - return {std::move(existingPath), existingType}; - } -} -} + const ErrorCode errorCode; +}; -ItemType zen::getItemType(const Zstring& itemPath) //throw FileError +ItemType getItemTypeImpl(const Zstring& itemPath) //throw SysErrorCode { struct stat itemInfo = {}; if (::lstat(itemPath.c_str(), &itemInfo) != 0) - THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), "lstat"); + throw SysErrorCode("lstat", errno); if (S_ISLNK(itemInfo.st_mode)) return ItemType::symlink; @@ -83,35 +51,72 @@ ItemType zen::getItemType(const Zstring& itemPath) //throw FileError return ItemType::folder; return ItemType::file; //S_ISREG || S_ISCHR || S_ISBLK || S_ISFIFO || S_ISSOCK } +} -std::optional<ItemType> zen::itemStillExists(const Zstring& itemPath) //throw FileError +ItemType zen::getItemType(const Zstring& itemPath) //throw FileError { - const auto& [existingPath, existingType] = getExistingPath(itemPath); //throw FileError - if (existingPath == itemPath) - return existingType; - else - return {}; + try + { + return getItemTypeImpl(itemPath); //throw SysErrorCode + } + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), e.toString()); } } -bool zen::fileAvailable(const Zstring& filePath) //noexcept +std::variant<ItemType, Zstring /*last existing parent path*/> zen::getItemTypeIfExists(const Zstring& itemPath) //throw FileError { - //symbolic links (broken or not) are also treated as existing files! - struct stat fileInfo = {}; - if (::stat(filePath.c_str(), &fileInfo) == 0) //follow symlinks! - return S_ISREG(fileInfo.st_mode); - return false; + try + { + try + { + //fast check: 1. perf 2. expected by getFolderStatusNonBlocking() + return getItemTypeImpl(itemPath); //throw SysErrorCode + } + catch (const SysErrorCode& e) //let's dig deeper, but *only* if error code sounds like "not existing" + { + const std::optional<Zstring> parentPath = getParentFolderPath(itemPath); + if (!parentPath) //device root => quick access test + throw; + if (e.errorCode == ENOENT) + { + const std::variant<ItemType, Zstring /*last existing parent path*/> parentTypeOrPath = getItemTypeIfExists(*parentPath); //throw FileError + + if (const ItemType* parentType = std::get_if<ItemType>(&parentTypeOrPath)) + { + if (*parentType == ItemType::file /*obscure, but possible*/) + throw SysError(replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(getItemName(*parentPath)))); + + const Zstring itemName = getItemName(itemPath); + assert(!itemName.empty()); + + traverseFolder(*parentPath, //throw FileError + [&](const FileInfo& fi) { if (fi.itemName == itemName) throw SysError(_("Temporary access error:") + L' ' + e.toString()); }, + [&](const FolderInfo& fi) { if (fi.itemName == itemName) throw SysError(_("Temporary access error:") + L' ' + e.toString()); }, + [&](const SymlinkInfo& si) { if (si.itemName == itemName) throw SysError(_("Temporary access error:") + L' ' + e.toString()); }); + //- case-sensitive comparison! itemPath must be normalized! + //- finding the item after getItemType() previously failed is exceptional + + return *parentPath; + } + else + return parentTypeOrPath; + } + else + throw; + } + } + catch (const SysError& e) + { + throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), e.toString()); + } } -bool zen::dirAvailable(const Zstring& dirPath) //noexcept +bool zen::itemExists(const Zstring& itemPath) //throw FileError { - //symbolic links (broken or not) are also treated as existing directories! - struct stat dirInfo = {}; - if (::stat(dirPath.c_str(), &dirInfo) == 0) //follow symlinks! - return S_ISDIR(dirInfo.st_mode); - return false; + const std::variant<ItemType, Zstring /*last existing parent path*/> typeOrPath = getItemTypeIfExists(itemPath); //throw FileError + return std::get_if<ItemType>(&typeOrPath); } @@ -125,7 +130,14 @@ namespace //- folderPath does not need to exist (yet) int64_t zen::getFreeDiskSpace(const Zstring& folderPath) //throw FileError { - const auto& [existingPath, existingType] = getExistingPath(folderPath); //throw FileError + const Zstring existingPath = [&] + { + const std::variant<ItemType, Zstring /*last existing parent path*/> typeOrPath = getItemTypeIfExists(folderPath); //throw FileError + if (std::get_if<ItemType>(&typeOrPath)) + return folderPath; + else + return std::get<Zstring>(typeOrPath); + }(); try { struct statfs info = {}; @@ -165,52 +177,42 @@ Zstring zen::getTempFolderPath() //throw FileError -void zen::removeFilePlain(const Zstring& filePath) //throw FileError +namespace { - const char* functionName = "unlink"; - if (::unlink(filePath.c_str()) != 0) - { - ErrorCode ec = getLastError(); //copy before directly/indirectly making other system calls! - //begin of "regular" error reporting - std::wstring errorDescr = formatSystemError(functionName, ec); - - throw FileError(replaceCpy(_("Cannot delete file %x."), L"%x", fmtPath(filePath)), errorDescr); - } } -void zen::removeSymlinkPlain(const Zstring& linkPath) //throw FileError +void zen::removeFilePlain(const Zstring& filePath) //throw FileError { - removeFilePlain(linkPath); //throw FileError + try + { + if (::unlink(filePath.c_str()) != 0) + THROW_LAST_SYS_ERROR("unlink"); + } + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot delete file %x."), L"%x", fmtPath(filePath)), e.toString()); } } + void zen::removeDirectoryPlain(const Zstring& dirPath) //throw FileError { - const char* functionName = "rmdir"; - if (::rmdir(dirPath.c_str()) != 0) + try { - ErrorCode ec = getLastError(); //copy before making other system calls! - bool symlinkExists = false; - try { symlinkExists = getItemType(dirPath) == ItemType::symlink; } /*throw FileError*/ catch (FileError&) {} //previous exception is more relevant + if (::rmdir(dirPath.c_str()) != 0) + THROW_LAST_SYS_ERROR("rmdir"); + } + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot delete directory %x."), L"%x", fmtPath(dirPath)), e.toString()); } +} - if (symlinkExists) - { - if (::unlink(dirPath.c_str()) != 0) - THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot delete directory %x."), L"%x", fmtPath(dirPath)), "unlink"); - return; - } - //if (ec == ERROR_SHARING_VIOLATION) => getLockingProcesses() can't handle directory paths! :( RmGetList() fails with ERROR_ACCESS_DENIED - //https://blog.yaakov.online/failed-experiment-what-processes-have-a-lock-on-this-folder/ - throw FileError(replaceCpy(_("Cannot delete directory %x."), L"%x", fmtPath(dirPath)), formatSystemError(functionName, ec)); +void zen::removeSymlinkPlain(const Zstring& linkPath) //throw FileError +{ + try + { + if (::unlink(linkPath.c_str()) != 0) + THROW_LAST_SYS_ERROR("unlink"); } - /* Windows: may spuriously fail with ERROR_DIR_NOT_EMPTY(145) even though all child items have - successfully been *marked* for deletion, but some application still has a handle open! - e.g. Open "C:\Test\Dir1\Dir2" (filled with lots of files) in Explorer, then delete "C:\Test\Dir1" via ::RemoveDirectory() => Error 145 - Sample code: http://us.generation-nt.com/answer/createfile-directory-handles-removing-parent-help-29126332.html - Alternatives: 1. move file/empty folder to some other location, then DeleteFile()/RemoveDirectory() - 2. use CreateFile/FILE_FLAG_DELETE_ON_CLOSE *without* FILE_SHARE_DELETE instead of DeleteFile() => early failure */ + catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot delete symbolic link %x."), L"%x", fmtPath(linkPath)), e.toString()); } } @@ -218,22 +220,23 @@ namespace { void removeDirectoryImpl(const Zstring& folderPath) //throw FileError { - std::vector<Zstring> filePaths; - std::vector<Zstring> symlinkPaths; std::vector<Zstring> folderPaths; + { + std::vector<Zstring> filePaths; + std::vector<Zstring> symlinkPaths; - //get all files and directories from current directory (WITHOUT subdirectories!) - traverseFolder(folderPath, - [&](const FileInfo& fi) { filePaths.push_back(fi.fullPath); }, - [&](const FolderInfo& fi) { folderPaths.push_back(fi.fullPath); }, //defer recursion => save stack space and allow deletion of extremely deep hierarchies! - [&](const SymlinkInfo& si) { symlinkPaths.push_back(si.fullPath); }, - [](const std::wstring& errorMsg) { throw FileError(errorMsg); }); + //get all files and directories from current directory (WITHOUT subdirectories!) + traverseFolder(folderPath, + [&](const FileInfo& fi) { filePaths.push_back(fi.fullPath); }, + [&](const FolderInfo& fi) { folderPaths.push_back(fi.fullPath); }, + [&](const SymlinkInfo& si) { symlinkPaths.push_back(si.fullPath); }); //throw FileError - for (const Zstring& filePath : filePaths) - removeFilePlain(filePath); //throw FileError + for (const Zstring& filePath : filePaths) + removeFilePlain(filePath); //throw FileError - for (const Zstring& symlinkPath : symlinkPaths) - removeSymlinkPlain(symlinkPath); //throw FileError + for (const Zstring& symlinkPath : symlinkPaths) + removeSymlinkPlain(symlinkPath); //throw FileError + } //=> save stack space and allow deletion of extremely deep hierarchies! //delete directories recursively for (const Zstring& subFolderPath : folderPaths) @@ -486,7 +489,7 @@ void zen::createDirectory(const Zstring& dirPath) //throw FileError, ErrorTarget try { //don't allow creating irregular folders! - const Zstring dirName = afterLast(dirPath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all); + const Zstring dirName = getItemName(dirPath); //e.g. "...." https://social.technet.microsoft.com/Forums/windows/en-US/ffee2322-bb6b-4fdf-86f9-8f93cf1fa6cb/ if (std::all_of(dirName.begin(), dirName.end(), [](Zchar c) { return c == Zstr('.'); })) @@ -505,8 +508,6 @@ void zen::createDirectory(const Zstring& dirPath) //throw FileError, ErrorTarget const int ec = errno; //copy before directly or indirectly making other system calls! if (ec == EEXIST) throw ErrorTargetExisting(replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(dirPath)), formatSystemError("mkdir", ec)); - //else if (ec == ENOENT) - // throw ErrorTargetPathMissing(errorMsg, errorDescr); THROW_LAST_SYS_ERROR("mkdir"); } } @@ -516,34 +517,43 @@ void zen::createDirectory(const Zstring& dirPath) //throw FileError, ErrorTarget void zen::createDirectoryIfMissingRecursion(const Zstring& dirPath) //throw FileError { - const std::optional<Zstring> parentPath = getParentFolderPath(dirPath); - if (!parentPath) //device root - return; + //expect that path already exists (see: versioning, base folder, log file path) => check first + const std::variant<ItemType, Zstring /*last existing parent path*/> typeOrPath = getItemTypeIfExists(dirPath); //throw FileError - try //generally expect folder already exists (see: ffs_paths.cpp) => check first + if (const ItemType* type = std::get_if<ItemType>(&typeOrPath)) { - if (getItemType(dirPath) != ItemType::file) //throw FileError - return; + if (*type == ItemType::file /*obscure, but possible*/) + throw FileError(replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(dirPath)), + replaceCpy(_("The name %x is already used by another item."), L"%x", fmtPath(getItemName(dirPath)))); } - catch (FileError&) {} //not yet existing or access error? let's find out... + else + { + const Zstring existingDirPath = std::get<Zstring>(typeOrPath); + assert(startsWith(dirPath, existingDirPath)); - createDirectoryIfMissingRecursion(*parentPath); //throw FileError + const ZstringView relPath = makeStringView(dirPath.begin() + existingDirPath.size(), dirPath.end()); + const std::vector<ZstringView> namesMissing = splitCpy(relPath, FILE_NAME_SEPARATOR, SplitOnEmpty::skip); + assert(!namesMissing.empty()); - try - { - createDirectory(dirPath); //throw FileError, ErrorTargetExisting - return; - } - catch (FileError&) - { - try - { - if (getItemType(dirPath) != ItemType::file) //throw FileError - return; //already existing => possible, if createDirectoryIfMissingRecursion() is run in parallel - } - catch (FileError&) {} //not yet existing or access error + Zstring dirPathNew = existingDirPath; + for (const ZstringView folderName : namesMissing) + try + { + dirPathNew = appendPath(dirPathNew, Zstring(folderName)); - throw; + createDirectory(dirPathNew); //throw FileError + } + catch (FileError&) + { + try + { + if (getItemType(dirPathNew) != ItemType::file /*obscure, but possible*/) //throw FileError + continue; //already existing => possible, if createFolderIfMissingRecursion() is run in parallel + } + catch (FileError&) {} //not yet existing or access error + + throw; + } } } diff --git a/zen/file_access.h b/zen/file_access.h index d87fcd0d..5af8b879 100644 --- a/zen/file_access.h +++ b/zen/file_access.h @@ -8,6 +8,7 @@ #define FILE_ACCESS_H_8017341345614857 #include <functional> +#include <variant> #include "file_path.h" #include "file_error.h" #include "serialize.h" //IoCallback @@ -17,10 +18,6 @@ namespace zen { //note: certain functions require COM initialization! (vista_file_op.h) -//POSITIVE existence checks; if false: 1. item not existing 2. different type 3.device access error or similar -bool fileAvailable(const Zstring& filePath); //noexcept -bool dirAvailable (const Zstring& dirPath ); // - //FAT/FAT32: "Why does the timestamp of a file *increase* by up to 2 seconds when I copy it to a USB thumb drive?" const int FAT_FILE_TIME_PRECISION_SEC = 2; //https://devblogs.microsoft.com/oldnewthing/?p=83 //https://web.archive.org/web/20141127143832/http://support.microsoft.com/kb/127830 @@ -42,7 +39,9 @@ ItemType getItemType(const Zstring& itemPath); //throw FileError //execute potentially SLOW folder traversal but distinguish error/not existing: // - all child item path parts must correspond to folder traversal // => we can conclude whether an item is *not* existing anymore by doing a *case-sensitive* name search => potentially SLOW! -std::optional<ItemType> itemStillExists(const Zstring& itemPath); //throw FileError +std::variant<ItemType, Zstring /*last existing parent path*/> getItemTypeIfExists(const Zstring& itemPath); //throw FileError + +bool itemExists(const Zstring& itemPath); //throw FileError enum class ProcSymlink { diff --git a/zen/file_io.cpp b/zen/file_io.cpp index 7dd11a1d..910b75e7 100644 --- a/zen/file_io.cpp +++ b/zen/file_io.cpp @@ -199,7 +199,6 @@ FileBase::FileHandle openHandleForWrite(const Zstring& filePath) //throw FileErr const int ec = errno; //copy before making other system calls! if (ec == EEXIST) throw ErrorTargetExisting(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(filePath)), formatSystemError("open", ec)); - //if (ec == ENOENT) throw ErrorTargetPathMissing(errorMsg, errorDescr); THROW_LAST_SYS_ERROR("open"); } diff --git a/zen/file_path.cpp b/zen/file_path.cpp index 73a3e923..d06ab6bd 100644 --- a/zen/file_path.cpp +++ b/zen/file_path.cpp @@ -75,6 +75,13 @@ std::optional<Zstring> zen::getParentFolderPath(const Zstring& itemPath) } +Zstring zen::getFileExtension(const ZstringView filePath) +{ + const ZstringView fileName = afterLast(filePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all); + return Zstring(afterLast(fileName, Zstr('.'), IfNotFoundReturn::none)); +} + + Zstring zen::appendSeparator(Zstring path) //support rvalue references! { assert(!endsWith(path, FILE_NAME_SEPARATOR == Zstr('/') ? Zstr('\\' ) : Zstr('/' ))); @@ -116,25 +123,6 @@ Zstring zen::appendPath(const Zstring& basePath, const Zstring& relPath) } -Zstring zen::getFileExtension(const Zstring& filePath) -{ - //const Zstring fileName = afterLast(filePath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all); - //return afterLast(fileName, Zstr('.'), IfNotFoundReturn::none); - - auto it = zen::findLast(filePath.begin(), filePath.end(), FILE_NAME_SEPARATOR); - if (it == filePath.end()) - it = filePath.begin(); - else - ++it; - - auto it2 = zen::findLast(it, filePath.end(), Zstr('.')); - if (it2 != filePath.end()) - ++it2; - - return Zstring(it2, filePath.end()); -} - - /* https://docs.microsoft.com/de-de/windows/desktop/Intl/handling-sorting-in-your-applications Perf test: compare strings 10 mio times; 64 bit build diff --git a/zen/file_path.h b/zen/file_path.h index 85af251d..d67a49d0 100644 --- a/zen/file_path.h +++ b/zen/file_path.h @@ -22,6 +22,9 @@ struct PathComponents std::optional<PathComponents> parsePathComponents(const Zstring& itemPath); //no value on failure std::optional<Zstring> getParentFolderPath(const Zstring& itemPath); +inline Zstring getItemName(const Zstring& itemPath) { return afterLast(itemPath, FILE_NAME_SEPARATOR, IfNotFoundReturn::all); } + +Zstring getFileExtension(const ZstringView filePath); Zstring appendSeparator(Zstring path); //support rvalue references! @@ -29,8 +32,6 @@ bool isValidRelPath(const Zstring& relPath); Zstring appendPath(const Zstring& basePath, const Zstring& relPath); -Zstring getFileExtension(const Zstring& filePath); - //------------------------------------------------------------------------------------------ /* Compare *local* file paths: Windows: igore case (but distinguish Unicode normalization forms!) diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp index 3a6099d9..4b33d3e6 100644 --- a/zen/file_traverser.cpp +++ b/zen/file_traverser.cpp @@ -17,11 +17,8 @@ using namespace zen; void zen::traverseFolder(const Zstring& dirPath, const std::function<void(const FileInfo& fi)>& onFile, const std::function<void(const FolderInfo& fi)>& onFolder, - const std::function<void(const SymlinkInfo& si)>& onSymlink, - const std::function<void(const std::wstring& errorMsg)>& onError) + const std::function<void(const SymlinkInfo& si)>& onSymlink) //throw FileError { - try - { DIR* folder = ::opendir(dirPath.c_str()); //directory must NOT end with path separator, except "/" if (!folder) THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot open directory %x."), L"%x", fmtPath(dirPath)), "opendir"); @@ -54,17 +51,8 @@ void zen::traverseFolder(const Zstring& dirPath, const Zstring& itemPath = appendPath(dirPath, itemName); struct stat statData = {}; - try - { if (::lstat(itemPath.c_str(), &statData) != 0) //lstat() does not resolve symlinks THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), "lstat"); - } - catch (const FileError& e) - { - if (onError) - onError(e.toString()); - continue; //ignore error: skip file - } if (S_ISLNK(statData.st_mode)) //on Linux there is no distinction between file and directory symlinks! { @@ -76,22 +64,15 @@ void zen::traverseFolder(const Zstring& dirPath, if (onFolder) onFolder({itemName, itemPath}); } - else //a file or named pipe, etc. + else //a file or named pipe, etc. S_ISREG, S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK { if (onFile) onFile({itemName, itemPath, makeUnsigned(statData.st_size), statData.st_mtime}); - } - /* It may be a good idea to not check "S_ISREG(statData.st_mode)" explicitly and to not issue an error message on other types to support these scenarios: - RTS setup watch (essentially wants to read directories only) - removeDirectory (wants to delete everything; pipes can be deleted just like files via "unlink") - However an "open" on a pipe will block (https://sourceforge.net/p/freefilesync/bugs/221/), so the copy routines need to be smarter!! */ + However an "open" on a pipe will block (https://sourceforge.net/p/freefilesync/bugs/221/), so the copy routines better be smart! */ + } } - } - catch (const FileError& e) - { - if (onError) - onError(e.toString()); - } } diff --git a/zen/file_traverser.h b/zen/file_traverser.h index 8bd32f2c..8903548d 100644 --- a/zen/file_traverser.h +++ b/zen/file_traverser.h @@ -8,6 +8,7 @@ #define FILER_TRAVERSER_H_127463214871234 #include <functional> +#include "file_error.h" #include "file_path.h" namespace zen @@ -34,12 +35,10 @@ struct SymlinkInfo }; //- non-recursive -//- directory path may end with PATH_SEPARATOR -void traverseFolder(const Zstring& dirPath, //noexcept - const std::function<void(const FileInfo& fi)>& onFile, // - const std::function<void(const FolderInfo& fi)>& onFolder, //optional - const std::function<void(const SymlinkInfo& si)>& onSymlink, // - const std::function<void(const std::wstring& errorMsg)>& onError); // +void traverseFolder(const Zstring& dirPath, + const std::function<void(const FileInfo& fi)>& onFile, /*optional*/ + const std::function<void(const FolderInfo& fi)>& onFolder,/*optional*/ + const std::function<void(const SymlinkInfo& si)>& onSymlink/*optional*/); //throw FileError } #endif //FILER_TRAVERSER_H_127463214871234 diff --git a/zen/http.cpp b/zen/http.cpp index 540b4ef6..7eb3fb76 100644 --- a/zen/http.cpp +++ b/zen/http.cpp @@ -12,7 +12,7 @@ using namespace zen; -const int HTTP_ACCESS_TIME_OUT_SEC = 20; +const int HTTP_ACCESS_TIMEOUT_SEC = 20; const size_t HTTP_BLOCK_SIZE_DOWNLOAD = 64 * 1024; //libcurl returns blocks of only 16 kB as returned by recv() even if we request larger blocks via CURLOPT_BUFFERSIZE //- InternetReadFile() is buffered + prefetching @@ -62,12 +62,12 @@ public: //caveat: INTERNET_FLAG_RELOAD issues "Pragma: no-cache" instead if "request is going through a proxy" - auto promiseHeader = std::make_shared<std::promise<std::string>>(); - std::future<std::string> futHeader = promiseHeader->get_future(); + auto promHeader = std::make_shared<std::promise<std::string>>(); + std::future<std::string> futHeader = promHeader->get_future(); auto postBytesSent = std::make_shared<std::atomic<int64_t>>(0); - worker_ = InterruptibleThread([asyncStreamOut = this->asyncStreamIn_, promiseHeader, headers = std::move(headers), postBytesSent, + worker_ = InterruptibleThread([asyncStreamOut = this->asyncStreamIn_, promHeader, headers = std::move(headers), postBytesSent, server, useTls, caCertFilePath, userAgent = utfTo<std::string>(userAgent), postBuf = postBuf ? std::optional<std::string>(*postBuf) : std::nullopt, //[!] life-time! serverRelPath = utfTo<std::string>(page)] @@ -112,7 +112,7 @@ public: if (headerLine == "\r\n") { headerReceived = true; - promiseHeader->set_value(std::move(headerBuf)); + promHeader->set_value(std::move(headerBuf)); } }; @@ -131,7 +131,7 @@ public: writeResponse /*throw ThreadStopRequest*/, readRequest, onHeaderData /*throw SysError*/, - HTTP_ACCESS_TIME_OUT_SEC); //throw SysError, ThreadStopRequest + HTTP_ACCESS_TIMEOUT_SEC); //throw SysError, ThreadStopRequest if (!headerReceived) throw SysError(L"HTTP response is missing header."); @@ -141,7 +141,7 @@ public: catch (SysError&) //let ThreadStopRequest pass through! { if (!headerReceived) - promiseHeader->set_exception(std::current_exception()); + promHeader->set_exception(std::current_exception()); asyncStreamOut->setWriteError(std::current_exception()); } diff --git a/zen/open_ssl.cpp b/zen/open_ssl.cpp index 9278b6dd..af4306b2 100644 --- a/zen/open_ssl.cpp +++ b/zen/open_ssl.cpp @@ -8,15 +8,15 @@ #include <bit> //std::endian (needed for macOS) #include "base64.h" #include "thread.h" +#include "argon2.h" +#include "serialize.h" #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/ssl.h> -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - #include <openssl/core_names.h> - #include <openssl/encoder.h> - #include <openssl/decoder.h> - #include <openssl/param_build.h> -#endif +#include <openssl/core_names.h> +#include <openssl/encoder.h> +#include <openssl/decoder.h> +#include <openssl/param_build.h> using namespace zen; @@ -26,7 +26,7 @@ using namespace zen; #error FFS, we are royally screwed! #endif -static_assert(OPENSSL_VERSION_NUMBER >= 0x10100000L, "OpenSSL version too old"); +static_assert(OPENSSL_VERSION_NUMBER >= 0x30000000L, "OpenSSL version too old"); void zen::openSslInit() @@ -79,7 +79,7 @@ std::wstring formatOpenSSLError(const char* functionName, unsigned long ec) std::wstring formatLastOpenSSLError(const char* functionName) { - const auto ec = ::ERR_peek_last_error(); + const auto ec = ::ERR_peek_last_error(); //"returns latest error code from the thread's error queue without modifying it" - unlike ERR_get_error() ::ERR_clear_error(); //clean up for next OpenSSL operation on this thread return formatOpenSSLError(functionName, ec); } @@ -110,13 +110,13 @@ std::shared_ptr<EVP_PKEY> generateRsaKeyPair(int bits) //throw SysError //================================================================================ -std::shared_ptr<EVP_PKEY> streamToKey(const std::string& keyStream, RsaStreamType streamType, bool publicKey) //throw SysError +std::shared_ptr<EVP_PKEY> streamToKey(const std::string_view keyStream, RsaStreamType streamType, bool publicKey) //throw SysError { switch (streamType) { case RsaStreamType::pkix: { - BIO* bio = ::BIO_new_mem_buf(keyStream.c_str(), static_cast<int>(keyStream.size())); + BIO* bio = ::BIO_new_mem_buf(keyStream.data(), static_cast<int>(keyStream.size())); if (!bio) throw SysError(formatLastOpenSSLError("BIO_new_mem_buf")); ZEN_ON_SCOPE_EXIT(::BIO_free_all(bio)); @@ -134,7 +134,6 @@ std::shared_ptr<EVP_PKEY> streamToKey(const std::string& keyStream, RsaStreamTyp case RsaStreamType::pkcs1: { -#if OPENSSL_VERSION_NUMBER >= 0x30000000L EVP_PKEY* evp = nullptr; auto guardEvp = makeGuard<ScopeGuardRunMode::onExit>([&] { if (evp) ::EVP_PKEY_free(evp); }); @@ -159,46 +158,20 @@ std::shared_ptr<EVP_PKEY> streamToKey(const std::string& keyStream, RsaStreamTyp throw SysError(formatLastOpenSSLError("OSSL_DECODER_CTX_set_passphrase")); #endif - const unsigned char* keyBuf = reinterpret_cast<const unsigned char*>(keyStream.c_str()); + const unsigned char* keyBuf = reinterpret_cast<const unsigned char*>(keyStream.data()); size_t keyLen = keyStream.size(); if (::OSSL_DECODER_from_data(decCtx, &keyBuf, &keyLen) != 1) throw SysError(formatLastOpenSSLError("OSSL_DECODER_from_data")); guardEvp.dismiss(); //pass ownership return std::shared_ptr<EVP_PKEY>(evp, ::EVP_PKEY_free); // -#else - BIO* bio = ::BIO_new_mem_buf(keyStream.c_str(), static_cast<int>(keyStream.size())); - if (!bio) - throw SysError(formatLastOpenSSLError("BIO_new_mem_buf")); - ZEN_ON_SCOPE_EXIT(::BIO_free_all(bio)); - - RSA* rsa = (publicKey ? - ::PEM_read_bio_RSAPublicKey : - ::PEM_read_bio_RSAPrivateKey)(bio, //BIO* bp - nullptr, //RSA** x - nullptr, //pem_password_cb* cb - nullptr); //void* u - if (!rsa) - throw SysError(formatLastOpenSSLError(publicKey ? "PEM_read_bio_RSAPublicKey" : "PEM_read_bio_RSAPrivateKey")); - ZEN_ON_SCOPE_EXIT(::RSA_free(rsa)); - - EVP_PKEY* evp = ::EVP_PKEY_new(); - if (!evp) - throw SysError(formatLastOpenSSLError("EVP_PKEY_new")); - std::shared_ptr<EVP_PKEY> sharedKey(evp, ::EVP_PKEY_free); - - if (::EVP_PKEY_set1_RSA(evp, rsa) != 1) //no ownership transfer (internally ref-counted) - throw SysError(formatLastOpenSSLError("EVP_PKEY_set1_RSA")); - - return sharedKey; -#endif } case RsaStreamType::raw: break; } - auto tmp = reinterpret_cast<const unsigned char*>(keyStream.c_str()); + auto tmp = reinterpret_cast<const unsigned char*>(keyStream.data()); EVP_PKEY* evp = (publicKey ? ::d2i_PublicKey : ::d2i_PrivateKey)(EVP_PKEY_RSA, //int type nullptr, //EVP_PKEY** a &tmp, /*changes tmp pointer itself!*/ //const unsigned char** pp @@ -255,7 +228,6 @@ std::string keyToStream(const EVP_PKEY* evp, RsaStreamType streamType, bool publ case RsaStreamType::pkcs1: { -#if OPENSSL_VERSION_NUMBER >= 0x30000000L const int selection = publicKey ? OSSL_KEYMGMT_SELECT_PUBLIC_KEY : OSSL_KEYMGMT_SELECT_PRIVATE_KEY; OSSL_ENCODER_CTX* encCtx = ::OSSL_ENCODER_CTX_new_for_pkey(evp, //const EVP_PKEY* pkey @@ -276,46 +248,6 @@ std::string keyToStream(const EVP_PKEY* evp, RsaStreamType streamType, bool publ ZEN_ON_SCOPE_EXIT(::OPENSSL_free(keyBuf)); return {reinterpret_cast<const char*>(keyBuf), keyLen}; -#else - //fix OpenSSL API inconsistencies: - auto PEM_write_bio_RSAPrivateKey2 = [](BIO* bio, const RSA* rsa) - { - return ::PEM_write_bio_RSAPrivateKey(bio, //BIO* bp - rsa, //const RSA* x - nullptr, //const EVP_CIPHER* enc - nullptr, //const unsigned char* kstr - 0, //int klen - nullptr, //pem_password_cb* cb - nullptr); //void* u - }; - auto PEM_write_bio_RSAPublicKey2 = [](BIO* bio, const RSA* rsa) { return ::PEM_write_bio_RSAPublicKey(bio, rsa); }; - - BIO* bio = ::BIO_new(BIO_s_mem()); - if (!bio) - throw SysError(formatLastOpenSSLError("BIO_new")); - ZEN_ON_SCOPE_EXIT(::BIO_free_all(bio)); - - const RSA* rsa = ::EVP_PKEY_get0_RSA(evp); //unowned reference! - if (!rsa) - throw SysError(formatLastOpenSSLError("EVP_PKEY_get0_RSA")); - - if ((publicKey ? - PEM_write_bio_RSAPublicKey2 : - PEM_write_bio_RSAPrivateKey2)(bio, rsa) != 1) - throw SysError(formatLastOpenSSLError(publicKey ? "PEM_write_bio_RSAPublicKey" : "PEM_write_bio_RSAPrivateKey")); - //--------------------------------------------- - const int keyLen = BIO_pending(bio); - if (keyLen < 0) - throw SysError(formatLastOpenSSLError("BIO_pending")); - if (keyLen == 0) - throw SysError(formatSystemError("BIO_pending", L"", L"Unexpected failure.")); //no more error details - - std::string keyStream(keyLen, '\0'); - - if (::BIO_read(bio, keyStream.data(), keyLen) != keyLen) - throw SysError(formatLastOpenSSLError("BIO_read")); - return keyStream; -#endif } case RsaStreamType::raw: @@ -333,13 +265,51 @@ std::string keyToStream(const EVP_PKEY* evp, RsaStreamType streamType, bool publ //================================================================================ -std::string createSignature(const std::string& message, EVP_PKEY* privateKey) //throw SysError +std::string createHash(const std::string_view str, const EVP_MD* type) //throw SysError +{ + std::string output(EVP_MAX_MD_SIZE, '\0'); + unsigned int bytesWritten = 0; +#if 1 + //https://www.openssl.org/docs/manmaster/man3/EVP_Digest.html + if (::EVP_Digest(str.data(), //const void* data + str.size(), //size_t count + reinterpret_cast<unsigned char*>(output.data()), //unsigned char* md + &bytesWritten, //unsigned int* size + type, //const EVP_MD* type + nullptr) != 1) //ENGINE* impl + throw SysError(formatLastOpenSSLError("EVP_Digest")); +#else //streaming version + EVP_MD_CTX* mdctx = ::EVP_MD_CTX_new(); + if (!mdctx) + throw SysError(formatSystemError("EVP_MD_CTX_new", L"", L"Unexpected failure.")); //no more error details + ZEN_ON_SCOPE_EXIT(::EVP_MD_CTX_free(mdctx)); + + if (::EVP_DigestInit(mdctx, //EVP_MD_CTX* ctx + type) != 1) //const EVP_MD* type + throw SysError(formatLastOpenSSLError("EVP_DigestInit")); + + if (::EVP_DigestUpdate(mdctx, //EVP_MD_CTX* ctx + str.data(), //const void* + str.size()) != 1) //size_t cnt); + throw SysError(formatLastOpenSSLError("EVP_DigestUpdate")); + + if (::EVP_DigestFinal_ex(mdctx, //EVP_MD_CTX* ctx + reinterpret_cast<unsigned char*>(output.data()), //unsigned char* md + &bytesWritten) != 1) //unsigned int* s + throw SysError(formatLastOpenSSLError("EVP_DigestFinal_ex")); +#endif + output.resize(bytesWritten); + return output; +} + + +std::string createSignature(const std::string_view message, EVP_PKEY* privateKey) //throw SysError { //https://www.openssl.org/docs/manmaster/man3/EVP_DigestSign.html - EVP_MD_CTX* mdctx = ::EVP_MD_CTX_create(); + EVP_MD_CTX* mdctx = ::EVP_MD_CTX_new(); if (!mdctx) - throw SysError(formatSystemError("EVP_MD_CTX_create", L"", L"Unexpected failure.")); //no more error details - ZEN_ON_SCOPE_EXIT(::EVP_MD_CTX_destroy(mdctx)); + throw SysError(formatSystemError("EVP_MD_CTX_new", L"", L"Unexpected failure.")); //no more error details + ZEN_ON_SCOPE_EXIT(::EVP_MD_CTX_free(mdctx)); if (::EVP_DigestSignInit(mdctx, //EVP_MD_CTX* ctx nullptr, //EVP_PKEY_CTX** pctx @@ -349,7 +319,7 @@ std::string createSignature(const std::string& message, EVP_PKEY* privateKey) // throw SysError(formatLastOpenSSLError("EVP_DigestSignInit")); if (::EVP_DigestSignUpdate(mdctx, //EVP_MD_CTX* ctx - message.c_str(), //const void* d + message.data(), //const void* d message.size()) != 1) //size_t cnt throw SysError(formatLastOpenSSLError("EVP_DigestSignUpdate")); @@ -372,13 +342,13 @@ std::string createSignature(const std::string& message, EVP_PKEY* privateKey) // } -void verifySignature(const std::string& message, const std::string& signature, EVP_PKEY* publicKey) //throw SysError +void verifySignature(const std::string_view message, const std::string_view signature, EVP_PKEY* publicKey) //throw SysError { //https://www.openssl.org/docs/manmaster/man3/EVP_DigestVerify.html - EVP_MD_CTX* mdctx = ::EVP_MD_CTX_create(); + EVP_MD_CTX* mdctx = ::EVP_MD_CTX_new(); if (!mdctx) - throw SysError(formatSystemError("EVP_MD_CTX_create", L"", L"Unexpected failure.")); //no more error details - ZEN_ON_SCOPE_EXIT(::EVP_MD_CTX_destroy(mdctx)); + throw SysError(formatSystemError("EVP_MD_CTX_new", L"", L"Unexpected failure.")); //no more error details + ZEN_ON_SCOPE_EXIT(::EVP_MD_CTX_free(mdctx)); if (::EVP_DigestVerifyInit(mdctx, //EVP_MD_CTX* ctx nullptr, //EVP_PKEY_CTX** pctx @@ -388,19 +358,19 @@ void verifySignature(const std::string& message, const std::string& signature, E throw SysError(formatLastOpenSSLError("EVP_DigestVerifyInit")); if (::EVP_DigestVerifyUpdate(mdctx, //EVP_MD_CTX* ctx - message.c_str(), //const void* d + message.data(), //const void* d message.size()) != 1) //size_t cnt throw SysError(formatLastOpenSSLError("EVP_DigestVerifyUpdate")); - if (::EVP_DigestVerifyFinal(mdctx, //EVP_MD_CTX* ctx - reinterpret_cast<const unsigned char*>(signature.c_str()), //const unsigned char* sig - signature.size()) != 1) //size_t siglen + if (::EVP_DigestVerifyFinal(mdctx, //EVP_MD_CTX* ctx + reinterpret_cast<const unsigned char*>(signature.data()), //const unsigned char* sig + signature.size()) != 1) //size_t siglen throw SysError(formatLastOpenSSLError("EVP_DigestVerifyFinal")); } } -std::string zen::convertRsaKey(const std::string& keyStream, RsaStreamType typeFrom, RsaStreamType typeTo, bool publicKey) //throw SysError +std::string zen::convertRsaKey(const std::string_view keyStream, RsaStreamType typeFrom, RsaStreamType typeTo, bool publicKey) //throw SysError { assert(typeFrom != typeTo); std::shared_ptr<EVP_PKEY> evp = streamToKey(keyStream, typeFrom, publicKey); //throw SysError @@ -408,7 +378,7 @@ std::string zen::convertRsaKey(const std::string& keyStream, RsaStreamType typeF } -void zen::verifySignature(const std::string& message, const std::string& signature, const std::string& publicKeyStream, RsaStreamType streamType) //throw SysError +void zen::verifySignature(const std::string_view message, const std::string_view signature, const std::string_view publicKeyStream, RsaStreamType streamType) //throw SysError { std::shared_ptr<EVP_PKEY> publicKey = streamToKey(publicKeyStream, streamType, true /*publicKey*/); //throw SysError ::verifySignature(message, signature, publicKey.get()); //throw SysError @@ -417,11 +387,11 @@ void zen::verifySignature(const std::string& message, const std::string& signatu bool zen::isPuttyKeyStream(const std::string_view keyStream) { - return startsWith(trimCpy(keyStream, true, false), "PuTTY-User-Key-File-"); + return startsWith(trimCpy(keyStream, true, false), "PuTTY-User-Key-File-"); } -std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std::string& passphrase) //throw SysError +std::string zen::convertPuttyKeyToPkix(const std::string_view keyStream, const std::string_view passphrase) //throw SysError { std::vector<std::string_view> lines; @@ -433,25 +403,39 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: //----------- parse PuTTY ppk structure ---------------------------------- auto itLine = lines.begin(); - if (itLine == lines.end() || !startsWith(*itLine, "PuTTY-User-Key-File-2: ")) - throw SysError(L"Unknown key file format"); - const std::string_view algorithm = afterFirst(*itLine, ' ', IfNotFoundReturn::none); - ++itLine; - if (itLine == lines.end() || !startsWith(*itLine, "Encryption: ")) + auto lineStartsWith = [&](const char* str) + { + return itLine != lines.end() && startsWith(*itLine, str); + }; + + const int ppkFormat = [&] + { + if (lineStartsWith("PuTTY-User-Key-File-2: ")) + return 2; + else if (lineStartsWith("PuTTY-User-Key-File-3: ")) + return 3; + else + throw SysError(L"Unknown key file format"); + }(); + + const std::string_view algorithm = afterFirst(*itLine++, ' ', IfNotFoundReturn::none); + + if (!lineStartsWith("Encryption: ")) + throw SysError(L"Missing key encryption"); + const std::string_view keyEncryption = afterFirst(*itLine++, ' ', IfNotFoundReturn::none); + + const bool keyEncrypted = keyEncryption == "aes256-cbc"; + if (!keyEncrypted && keyEncryption != "none") throw SysError(L"Unknown key encryption"); - const std::string_view keyEncryption = afterFirst(*itLine, ' ', IfNotFoundReturn::none); - ++itLine; - if (itLine == lines.end() || !startsWith(*itLine, "Comment: ")) - throw SysError(L"Invalid key comment"); - const std::string_view comment = afterFirst(*itLine, ' ', IfNotFoundReturn::none); - ++itLine; + if (!lineStartsWith("Comment: ")) + throw SysError(L"Missing comment"); + const std::string_view comment = afterFirst(*itLine++, ' ', IfNotFoundReturn::none); - if (itLine == lines.end() || !startsWith(*itLine, "Public-Lines: ")) - throw SysError(L"Invalid key: invalid public lines"); - size_t pubLineCount = stringTo<size_t>(afterFirst(*itLine, ' ', IfNotFoundReturn::none)); - ++itLine; + if (!lineStartsWith("Public-Lines: ")) + throw SysError(L"Missing public lines"); + size_t pubLineCount = stringTo<size_t>(afterFirst(*itLine++, ' ', IfNotFoundReturn::none)); std::string publicBlob64; while (pubLineCount-- != 0) @@ -460,10 +444,55 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: else throw SysError(L"Invalid key: incomplete public lines"); - if (itLine == lines.end() || !startsWith(*itLine, "Private-Lines: ")) - throw SysError(L"Invalid key: invalid private lines"); - size_t privLineCount = stringTo<size_t>(afterFirst(*itLine, ' ', IfNotFoundReturn::none)); - ++itLine; + Argon2Flavor argonFlavor = Argon2Flavor::d; + uint32_t argonMemory = 0; + uint32_t argonPasses = 0; + uint32_t argonParallelism = 0; + std::string argonSalt; + if (ppkFormat >= 3 && keyEncrypted) + { + if (!lineStartsWith("Key-Derivation: ")) + throw SysError(L"Missing Argon2 parameter: Key-Derivation"); + const std::string_view keyDerivation = afterFirst(*itLine++, ' ', IfNotFoundReturn::none); + + argonFlavor = [&] + { + if (keyDerivation == "Argon2d") + return Argon2Flavor::d; + else if (keyDerivation == "Argon2i") + return Argon2Flavor::i; + else if (keyDerivation == "Argon2id") + return Argon2Flavor::id; + else + throw SysError(L"Unexpected Argon2 parameter for Key-Derivation"); + }(); + + if (!lineStartsWith("Argon2-Memory: ")) + throw SysError(L"Missing Argon2 parameter: Argon2-Memory"); + argonMemory = stringTo<uint32_t>(afterFirst(*itLine++, ' ', IfNotFoundReturn::none)); + + if (!lineStartsWith("Argon2-Passes: ")) + throw SysError(L"Missing Argon2 parameter: Argon2-Passes"); + argonPasses = stringTo<uint32_t>(afterFirst(*itLine++, ' ', IfNotFoundReturn::none)); + + if (!lineStartsWith("Argon2-Parallelism: ")) + throw SysError(L"Missing Argon2 parameter: Argon2-Parallelism"); + argonParallelism = stringTo<uint32_t>(afterFirst(*itLine++, ' ', IfNotFoundReturn::none)); + + if (!lineStartsWith("Argon2-Salt: ")) + throw SysError(L"Missing Argon2 parameter: Argon2-Salt"); + const std::string_view argonSaltHex = afterFirst(*itLine++, ' ', IfNotFoundReturn::none); + + if (argonSaltHex.size() % 2 != 0 || !std::all_of(argonSaltHex.begin(), argonSaltHex.end(), isHexDigit<char>)) + throw SysError(L"Invalid Argon2 parameter: Argon2-Salt"); + + for (size_t i = 0; i < argonSaltHex.size(); i += 2) + argonSalt += unhexify(argonSaltHex[i], argonSaltHex[i + 1]); + } + + if (!lineStartsWith("Private-Lines: ")) + throw SysError(L"Missing private lines"); + size_t privLineCount = stringTo<size_t>(afterFirst(*itLine++, ' ', IfNotFoundReturn::none)); std::string privateBlob64; while (privLineCount-- != 0) @@ -472,16 +501,11 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: else throw SysError(L"Invalid key: incomplete private lines"); - if (itLine == lines.end() || !startsWith(*itLine, "Private-MAC: ")) - throw SysError(L"Invalid key: MAC missing"); - const std::string_view macHex = afterFirst(*itLine, ' ', IfNotFoundReturn::none); - ++itLine; + if (!lineStartsWith("Private-MAC: ")) + throw SysError(L"MAC missing"); //apparently "Private-Hash" is/was possible here: maybe with ppk version 1!? + const std::string_view macHex = afterFirst(*itLine++, ' ', IfNotFoundReturn::none); //----------- unpack key file elements --------------------- - const bool keyEncrypted = keyEncryption == "aes256-cbc"; - if (!keyEncrypted && keyEncryption != "none") - throw SysError(L"Unknown key encryption"); - if (macHex.size() % 2 != 0 || !std::all_of(macHex.begin(), macHex.end(), isHexDigit<char>)) throw SysError(L"Invalid key: invalid MAC"); @@ -493,6 +517,8 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: const std::string privateBlobEnc = stringDecodeBase64(privateBlob64); std::string privateBlob; + std::string macKeyFmt3; + if (!keyEncrypted) privateBlob = privateBlobEnc; else @@ -500,23 +526,40 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: if (passphrase.empty()) throw SysError(L"Passphrase required to access private key"); - const auto block1 = std::string("\0\0\0\0", 4) + passphrase; - const auto block2 = std::string("\0\0\0\1", 4) + passphrase; + const EVP_CIPHER* const cipher = EVP_aes_256_cbc(); + std::string decryptKey; + std::string iv; + if (ppkFormat >= 3) + { + decryptKey.resize(::EVP_CIPHER_get_key_length(cipher)); + iv .resize(::EVP_CIPHER_get_iv_length (cipher)); + macKeyFmt3.resize(32); + + const std::string argonBlob = zargon2(argonFlavor, argonMemory, argonPasses, argonParallelism, + static_cast<uint32_t>(decryptKey.size() + iv.size() + macKeyFmt3.size()), passphrase, argonSalt); + MemoryStreamIn streamIn(argonBlob); + readArray(streamIn, decryptKey.data(), decryptKey.size()); // + readArray(streamIn, iv .data(), iv .size()); //throw SysErrorUnexpectedEos + readArray(streamIn, macKeyFmt3.data(), macKeyFmt3.size()); // + } + else + { + decryptKey = createHash(std::string("\0\0\0\0", 4) + passphrase, EVP_sha1()) + //throw SysError + createHash(std::string("\0\0\0\1", 4) + passphrase, EVP_sha1()); // + decryptKey.resize(::EVP_CIPHER_get_key_length(cipher)); //PuTTYgen only uses first 32 bytes as key (== key length of EVP_aes_256_cbc) - unsigned char key[2 * SHA_DIGEST_LENGTH] = {}; - ::SHA1(reinterpret_cast<const unsigned char*>(block1.c_str()), block1.size(), key); //no-fail - ::SHA1(reinterpret_cast<const unsigned char*>(block2.c_str()), block2.size(), key + SHA_DIGEST_LENGTH); // + iv.assign(::EVP_CIPHER_get_iv_length(cipher), 0); //initialization vector is 16-byte-range of zeros (== default for EVP_aes_256_cbc) + } EVP_CIPHER_CTX* cipCtx = ::EVP_CIPHER_CTX_new(); if (!cipCtx) throw SysError(formatSystemError("EVP_CIPHER_CTX_new", L"", L"Unexpected failure.")); //no more error details ZEN_ON_SCOPE_EXIT(::EVP_CIPHER_CTX_free(cipCtx)); - if (::EVP_DecryptInit_ex(cipCtx, //EVP_CIPHER_CTX* ctx - EVP_aes_256_cbc(), //const EVP_CIPHER* type - nullptr, //ENGINE* impl - key, //const unsigned char* key => implied length of 256 bit! - nullptr) != 1) //const unsigned char* iv + if (::EVP_DecryptInit(cipCtx, //EVP_CIPHER_CTX* ctx + cipher, //const EVP_CIPHER* type + reinterpret_cast<const unsigned char*>(decryptKey.c_str()), //const unsigned char* key + reinterpret_cast<const unsigned char*>(iv.c_str())) != 1) //const unsigned char* iv => nullptr = 16-byte zeros for EVP_aes_256_cbc throw SysError(formatLastOpenSSLError("EVP_DecryptInit_ex")); if (::EVP_CIPHER_CTX_set_padding(cipCtx, 0 /*padding*/) != 1) @@ -527,28 +570,27 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: int decLen1 = 0; if (::EVP_DecryptUpdate(cipCtx, //EVP_CIPHER_CTX* ctx - reinterpret_cast<unsigned char*>(privateBlob.data()), //unsigned char* out + reinterpret_cast<unsigned char*>(privateBlob.data()), //unsigned char* out &decLen1, //int* outl reinterpret_cast<const unsigned char*>(privateBlobEnc.c_str()), //const unsigned char* in static_cast<int>(privateBlobEnc.size())) != 1) //int inl throw SysError(formatLastOpenSSLError("EVP_DecryptUpdate")); int decLen2 = 0; - if (::EVP_DecryptFinal_ex(cipCtx, //EVP_CIPHER_CTX* ctx - reinterpret_cast<unsigned char*>(&privateBlob[decLen1]), //unsigned char* outm - &decLen2) != 1) //int* outl + if (::EVP_DecryptFinal(cipCtx, //EVP_CIPHER_CTX* ctx + reinterpret_cast<unsigned char*>(&privateBlob[decLen1]), //unsigned char* outm + &decLen2) != 1) //int* outl throw SysError(formatLastOpenSSLError("EVP_DecryptFinal_ex")); privateBlob.resize(decLen1 + decLen2); } //----------- verify key consistency --------------------- - std::string macKeyBlob = "putty-private-key-file-mac-key"; - if (keyEncrypted) - macKeyBlob += passphrase; - - unsigned char macKey[SHA_DIGEST_LENGTH] = {}; - ::SHA1(reinterpret_cast<const unsigned char*>(macKeyBlob.c_str()), macKeyBlob.size(), macKey); //no-fail + std::string macKey; + if (ppkFormat >= 3) + macKey = macKeyFmt3; + else + macKey = createHash(std::string("putty-private-key-file-mac-key") + (keyEncrypted ? passphrase : ""), EVP_sha1()); //throw SysError auto numToBeString = [](size_t n) -> std::string { @@ -564,18 +606,17 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: numToBeString(privateBlob .size()) + privateBlob; char md[EVP_MAX_MD_SIZE] = {}; unsigned int mdLen = 0; - if (!::HMAC(EVP_sha1(), //const EVP_MD* evp_md - macKey, //const void* key - sizeof(macKey), //int key_len + if (!::HMAC(ppkFormat <= 2 ? EVP_sha1() : EVP_sha256(), //const EVP_MD* evp_md + macKey.c_str(), //const void* key + static_cast<int>(macKey.size()), //int key_len reinterpret_cast<const unsigned char*>(macData.c_str()), //const unsigned char* d - static_cast<int>(macData.size()), //int n - reinterpret_cast<unsigned char*>(md), //unsigned char* md - &mdLen)) //unsigned int* md_len + static_cast<int>(macData.size()), //int n + reinterpret_cast<unsigned char*>(md), //unsigned char* md + &mdLen)) //unsigned int* md_len throw SysError(formatSystemError("HMAC", L"", L"Unexpected failure.")); //no more error details - const bool hashValid = mac == std::string_view(md, mdLen); - if (!hashValid) - throw SysError(formatSystemError("HMAC", L"", keyEncrypted ? L"Validation failed: wrong passphrase or corrupted key" : L"Validation failed: corrupted key")); + if (mac != std::string_view(md, mdLen)) + throw SysError(keyEncrypted ? L"Wrong passphrase (or corrupted key)" : L"Validation failed: corrupted key"); //---------------------------------------------------------- auto extractString = [](auto& it, auto itEnd) @@ -663,17 +704,16 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: throw SysError(formatLastOpenSSLError("BN_mod")); //---------------------------------------------------------- -#if OPENSSL_VERSION_NUMBER >= 0x30000000L OSSL_PARAM_BLD* paramBld = ::OSSL_PARAM_BLD_new(); if (!paramBld) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_new")); ZEN_ON_SCOPE_EXIT(::OSSL_PARAM_BLD_free(paramBld)); - if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_N, n.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(n)")); - if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_E, e.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(e)")); - if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_D, d.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(d)")); - if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_FACTOR1, p.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(p)")); - if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_FACTOR2, q.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(q)")); + if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_N, n.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(n)")); + if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_E, e.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(e)")); + if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_D, d.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(d)")); + if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_FACTOR1, p.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(p)")); + if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_FACTOR2, q.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(q)")); if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_EXPONENT1, dmp1.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(dmp1)")); if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_EXPONENT2, dmq1.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(dmq1)")); if (::OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, iqmp.get()) != 1) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_push_BN(iqmp)")); @@ -696,29 +736,7 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: if (::EVP_PKEY_fromdata(evpCtx, &evp, EVP_PKEY_KEYPAIR, sslParams) != 1) throw SysError(formatLastOpenSSLError("EVP_PKEY_fromdata")); ZEN_ON_SCOPE_EXIT(::EVP_PKEY_free(evp)); -#else - RSA* rsa = ::RSA_new(); - if (!rsa) - throw SysError(formatLastOpenSSLError("RSA_new")); - ZEN_ON_SCOPE_EXIT(::RSA_free(rsa)); - - if (::RSA_set0_key(rsa, n.release(), e.release(), d.release()) != 1) //pass BIGNUM ownership - throw SysError(formatLastOpenSSLError("RSA_set0_key")); - - if (::RSA_set0_factors(rsa, p.release(), q.release()) != 1) - throw SysError(formatLastOpenSSLError("RSA_set0_factors")); - - if (::RSA_set0_crt_params(rsa, dmp1.release(), dmq1.release(), iqmp.release()) != 1) - throw SysError(formatLastOpenSSLError("RSA_set0_crt_params")); - - EVP_PKEY* evp = ::EVP_PKEY_new(); - if (!evp) - throw SysError(formatLastOpenSSLError("EVP_PKEY_new")); - ZEN_ON_SCOPE_EXIT(::EVP_PKEY_free(evp)); - if (::EVP_PKEY_set1_RSA(evp, rsa) != 1) //no ownership transfer (internally ref-counted) - throw SysError(formatLastOpenSSLError("EVP_PKEY_set1_RSA")); -#endif return keyToStream(evp, RsaStreamType::pkix, false /*publicKey*/); //throw SysError } //---------------------------------------------------------- @@ -730,7 +748,6 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: std::unique_ptr<BIGNUM, BnFree> pub = extractBigNumPub (); // std::unique_ptr<BIGNUM, BnFree> pri = extractBigNumPriv(); // //---------------------------------------------------------- -#if OPENSSL_VERSION_NUMBER >= 0x30000000L OSSL_PARAM_BLD* paramBld = ::OSSL_PARAM_BLD_new(); if (!paramBld) throw SysError(formatLastOpenSSLError("OSSL_PARAM_BLD_new")); @@ -760,26 +777,7 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: if (::EVP_PKEY_fromdata(evpCtx, &evp, EVP_PKEY_KEYPAIR, sslParams) != 1) throw SysError(formatLastOpenSSLError("EVP_PKEY_fromdata")); ZEN_ON_SCOPE_EXIT(::EVP_PKEY_free(evp)); -#else - DSA* dsa = ::DSA_new(); - if (!dsa) - throw SysError(formatLastOpenSSLError("DSA_new")); - ZEN_ON_SCOPE_EXIT(::DSA_free(dsa)); - - if (::DSA_set0_pqg(dsa, p.release(), q.release(), g.release()) != 1) //pass BIGNUM ownership - throw SysError(formatLastOpenSSLError("DSA_set0_pqg")); - - if (::DSA_set0_key(dsa, pub.release(), pri.release()) != 1) - throw SysError(formatLastOpenSSLError("DSA_set0_key")); - - EVP_PKEY* evp = ::EVP_PKEY_new(); - if (!evp) - throw SysError(formatLastOpenSSLError("EVP_PKEY_new")); - ZEN_ON_SCOPE_EXIT(::EVP_PKEY_free(evp)); - if (::EVP_PKEY_set1_DSA(evp, dsa) != 1) //no ownership transfer (internally ref-counted) - throw SysError(formatLastOpenSSLError("EVP_PKEY_set1_DSA")); -#endif return keyToStream(evp, RsaStreamType::pkix, false /*publicKey*/); //throw SysError } //---------------------------------------------------------- @@ -794,7 +792,6 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: const std::string pointStream = extractStringPub(); std::unique_ptr<BIGNUM, BnFree> pri = extractBigNumPriv(); //throw SysError //---------------------------------------------------------- -#if OPENSSL_VERSION_NUMBER >= 0x30000000L const char* groupName = [&] { if (algoShort == "nistp256") @@ -838,53 +835,7 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: if (::EVP_PKEY_fromdata(evpCtx, &evp, EVP_PKEY_KEYPAIR, sslParams) != 1) throw SysError(formatLastOpenSSLError("EVP_PKEY_fromdata")); ZEN_ON_SCOPE_EXIT(::EVP_PKEY_free(evp)); -#else - const int curveNid = [&] - { - if (algoShort == "nistp256") - return NID_X9_62_prime256v1; //same as SECG secp256r1 - if (algoShort == "nistp384") - return NID_secp384r1; - if (algoShort == "nistp521") - return NID_secp521r1; - throw SysError(L"Unknown elliptic curve: " + utfTo<std::wstring>(algorithm)); - }(); - - EC_KEY* ecKey = ::EC_KEY_new_by_curve_name(curveNid); - if (!ecKey) - throw SysError(formatLastOpenSSLError("EC_KEY_new_by_curve_name")); - ZEN_ON_SCOPE_EXIT(::EC_KEY_free(ecKey)); - - const EC_GROUP* ecGroup = ::EC_KEY_get0_group(ecKey); - if (!ecGroup) - throw SysError(formatLastOpenSSLError("EC_KEY_get0_group")); - - EC_POINT* ecPoint = ::EC_POINT_new(ecGroup); - if (!ecPoint) - throw SysError(formatLastOpenSSLError("EC_POINT_new")); - ZEN_ON_SCOPE_EXIT(::EC_POINT_free(ecPoint)); - - if (::EC_POINT_oct2point(ecGroup, //const EC_GROUP* group - ecPoint, //EC_POINT* p - reinterpret_cast<const unsigned char*>(pointStream.c_str()), //const unsigned char* buf - pointStream.size(), //size_t len - nullptr) != 1) //BN_CTX* ctx - throw SysError(formatLastOpenSSLError("EC_POINT_oct2point")); - - if (::EC_KEY_set_public_key(ecKey, ecPoint) != 1) //no ownership transfer (internally ref-counted) - throw SysError(formatLastOpenSSLError("EC_KEY_set_public_key")); - - if (::EC_KEY_set_private_key(ecKey, pri.get()) != 1) //no ownership transfer (internally ref-counted) - throw SysError(formatLastOpenSSLError("EC_KEY_set_private_key")); - - EVP_PKEY* evp = ::EVP_PKEY_new(); - if (!evp) - throw SysError(formatLastOpenSSLError("EVP_PKEY_new")); - ZEN_ON_SCOPE_EXIT(::EVP_PKEY_free(evp)); - if (::EVP_PKEY_set1_EC_KEY(evp, ecKey) != 1) //no ownership transfer (internally ref-counted) - throw SysError(formatLastOpenSSLError("EVP_PKEY_set1_EC_KEY")); -#endif return keyToStream(evp, RsaStreamType::pkix, false /*publicKey*/); //throw SysError } //---------------------------------------------------------- @@ -904,5 +855,17 @@ std::string zen::convertPuttyKeyToPkix(const std::string& keyStream, const std:: return keyToStream(evpPriv, RsaStreamType::pkix, false /*publicKey*/); //throw SysError } else - throw SysError(L"Unknown key algorithm: " + utfTo<std::wstring>(algorithm)); + throw SysError(L"Unsupported key algorithm: " + utfTo<std::wstring>(algorithm)); + /* PuTTYgen supports many more (which are not yet supported by libssh2): + - rsa-sha2-256 + - rsa-sha2-512 + - ssh-ed448 + - ssh-dss-cert-v01@openssh.com + - ssh-rsa-cert-v01@openssh.com + - rsa-sha2-256-cert-v01@openssh.com + - rsa-sha2-512-cert-v01@openssh.com + - ssh-ed25519-cert-v01@openssh.com + - ecdsa-sha2-nistp256-cert-v01@openssh.com + - ecdsa-sha2-nistp384-cert-v01@openssh.com + - ecdsa-sha2-nistp521-cert-v01@openssh.com */ } diff --git a/zen/open_ssl.h b/zen/open_ssl.h index 1a28f068..96e25ffc 100644 --- a/zen/open_ssl.h +++ b/zen/open_ssl.h @@ -25,16 +25,16 @@ enum class RsaStreamType }; //verify signatures produced with: "openssl dgst -sha256 -sign private.pem -out file.sig file.txt" -void verifySignature(const std::string& message, - const std::string& signature, - const std::string& publicKeyStream, +void verifySignature(const std::string_view message, + const std::string_view signature, + const std::string_view publicKeyStream, RsaStreamType streamType); //throw SysError -std::string convertRsaKey(const std::string& keyStream, RsaStreamType typeFrom, RsaStreamType typeTo, bool publicKey); //throw SysError +std::string convertRsaKey(const std::string_view keyStream, RsaStreamType typeFrom, RsaStreamType typeTo, bool publicKey); //throw SysError bool isPuttyKeyStream(const std::string_view keyStream); -std::string convertPuttyKeyToPkix(const std::string& keyStream, const std::string& passphrase); //throw SysError +std::string convertPuttyKeyToPkix(const std::string_view keyStream, const std::string_view passphrase); //throw SysError } #endif //OPEN_SSL_H_801974580936508934568792347506 diff --git a/zen/process_exec.cpp b/zen/process_exec.cpp index ffc90b4f..89df9f8b 100644 --- a/zen/process_exec.cpp +++ b/zen/process_exec.cpp @@ -154,7 +154,7 @@ std::pair<int /*exit code*/, std::string> processExecuteImpl(const Zstring& file THROW_LAST_SYS_ERROR("fcntl(F_SETFL, O_NONBLOCK)"); - const auto endTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(*timeoutMs); + const auto stopTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(*timeoutMs); for (;;) //EINTR handling? => allow interruption!? { //read until EAGAIN @@ -172,18 +172,18 @@ std::pair<int /*exit code*/, std::string> processExecuteImpl(const Zstring& file //wait for stream input const auto now = std::chrono::steady_clock::now(); - if (now > endTime) + if (now > stopTime) throw SysErrorTimeOut(_P("Operation timed out after 1 second.", "Operation timed out after %x seconds.", *timeoutMs / 1000)); - const auto waitTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - now).count(); + const auto waitTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(stopTime - now).count(); timeval tv{.tv_sec = static_cast<long>(waitTimeMs / 1000)}; tv.tv_usec = static_cast<long>(waitTimeMs - tv.tv_sec * 1000) * 1000; - fd_set rfd = {}; //includes FD_ZERO + fd_set rfd{}; //includes FD_ZERO FD_SET(fdLifeSignR, &rfd); - if (const int rv = ::select(fdLifeSignR + 1, //int nfds + if (const int rv = ::select(fdLifeSignR + 1, //int nfds = "highest-numbered file descriptor in any of the three sets, plus 1" &rfd, //fd_set* readfds nullptr, //fd_set* writefds nullptr, //fd_set* exceptfds diff --git a/zen/socket.h b/zen/socket.h index 8e92b616..df8b768b 100644 --- a/zen/socket.h +++ b/zen/socket.h @@ -13,7 +13,6 @@ #include <netdb.h> //getaddrinfo - namespace zen { #define THROW_LAST_SYS_ERROR_WSA(functionName) \ @@ -26,14 +25,23 @@ const SocketType invalidSocket = -1; inline void closeSocket(SocketType s) { ::close(s); } warn_static("log on error!") +void setNonBlocking(SocketType socket, bool value); //throw SysError + //Winsock needs to be initialized before calling any of these functions! (WSAStartup/WSACleanup) + + class Socket //throw SysError { public: - Socket(const Zstring& server, const Zstring& serviceName) //throw SysError + Socket(const Zstring& server, const Zstring& serviceName, int timeoutSec) //throw SysError { + //GetAddrInfo(): "If the pNodeName parameter contains an empty string, all registered addresses on the local computer are returned." + // "If the pNodeName parameter points to a string equal to "localhost", all loopback addresses on the local computer are returned." + if (trimCpy(server).empty()) + throw SysError(_("Server name must not be empty.")); + const addrinfo hints { .ai_flags = AI_ADDRCONFIG, //save a AAAA lookup on machines that can't use the returned data anyhow @@ -49,23 +57,62 @@ public: if (!servinfo) throw SysError(formatSystemError("getaddrinfo", L"", L"Empty server info.")); - const auto getConnectedSocket = [](const auto& /*::addrinfo*/ ai) + const auto getConnectedSocket = [timeoutSec](const auto& /*addrinfo*/ ai) { SocketType testSocket = ::socket(ai.ai_family, //int socket_family - SOCK_CLOEXEC | + SOCK_CLOEXEC | SOCK_NONBLOCK | ai.ai_socktype, //int socket_type ai.ai_protocol); //int protocol if (testSocket == invalidSocket) THROW_LAST_SYS_ERROR_WSA("socket"); ZEN_ON_SCOPE_FAIL(closeSocket(testSocket)); - warn_static("support timeout! https://stackoverflow.com/questions/2597608/c-socket-connection-timeout") - if (::connect(testSocket, ai.ai_addr, static_cast<int>(ai.ai_addrlen)) != 0) - THROW_LAST_SYS_ERROR_WSA("connect"); + + if (::connect(testSocket, ai.ai_addr, static_cast<int>(ai.ai_addrlen)) != 0) //0 or SOCKET_ERROR(-1) + { + if (errno != EINPROGRESS) + THROW_LAST_SYS_ERROR_WSA("connect"); + + fd_set writefds{}; + fd_set exceptfds{}; //mostly only relevant for connect() + FD_SET(testSocket, &writefds); + FD_SET(testSocket, &exceptfds); + + /*const*/ timeval tv{.tv_sec = timeoutSec}; + + const int rv = ::select( + testSocket + 1, //int nfds = "highest-numbered file descriptor in any of the three sets, plus 1" + nullptr, //fd_set* readfds + &writefds, //fd_set* writefds + &exceptfds, //fd_set* exceptfds + &tv); //const timeval* timeout + if (rv < 0) + THROW_LAST_SYS_ERROR_WSA("select"); + + if (rv == 0) //time-out! + throw SysError(formatSystemError("select, " + utfTo<std::string>(_P("1 sec", "%x sec", timeoutSec)), ETIMEDOUT)); + int error = 0; + socklen_t optLen = sizeof(error); + if (::getsockopt(testSocket, //[in] SOCKET s + SOL_SOCKET, //[in] int level + SO_ERROR, //[in] int optname + reinterpret_cast<char*>(&error), //[out] char* optval + &optLen) //[in, out] socklen_t* optlen + != 0) + THROW_LAST_SYS_ERROR_WSA("getsockopt(SO_ERROR)"); + + if (error != 0) + throw SysError(formatSystemError("connect, SO_ERROR", static_cast<ErrorCode>(error))/*== system error code, apparently!?*/); + } + + setNonBlocking(testSocket, false); //throw SysError return testSocket; }; + /* getAddrInfo() often returns only one ai_family == AF_INET address, but more items are possible: + facebook.com: 1 x AF_INET6, 3 x AF_INET + microsoft.com: 5 x AF_INET => server not allowing connection: hanging for 5x timeoutSec :( */ std::optional<SysError> firstError; for (const auto* /*::addrinfo*/ si = servinfo; si; si = si->ai_next) try @@ -152,6 +199,23 @@ void shutdownSocketSend(SocketType socket) //throw SysError if (::shutdown(socket, SHUT_WR) != 0) THROW_LAST_SYS_ERROR_WSA("shutdown"); } + + +inline +void setNonBlocking(SocketType socket, bool nonBlocking) //throw SysError +{ + int flags = ::fcntl(socket, F_GETFL); + if (flags == -1) + THROW_LAST_SYS_ERROR("fcntl(F_GETFL)"); + + if (nonBlocking) + flags |= O_NONBLOCK; + else + flags &= ~O_NONBLOCK; + + if (::fcntl(socket, F_SETFL, flags) != 0) + THROW_LAST_SYS_ERROR(nonBlocking ? "fcntl(F_SETFL, O_NONBLOCK)" : "fcntl(F_SETFL, ~O_NONBLOCK)"); +} } #endif //SOCKET_H_23498325972583947678456437 diff --git a/zen/stl_tools.h b/zen/stl_tools.h index bb005e34..03e7901a 100644 --- a/zen/stl_tools.h +++ b/zen/stl_tools.h @@ -251,7 +251,7 @@ RandomAccessIterator1 searchFirst(const RandomAccessIterator1 first, const const RandomAccessIterator2 needleFirst, const RandomAccessIterator2 needleLast, IsEq isEqual) { if (needleLast - needleFirst == 1) //don't use expensive std::search unless required! - return std::find_if(first, last, [needleFirst, isEqual](const auto c){ return isEqual(*needleFirst, c); }); + return std::find_if(first, last, [needleFirst, isEqual](const auto c) { return isEqual(*needleFirst, c); }); return std::search(first, last, needleFirst, needleLast, isEqual); @@ -335,7 +335,7 @@ class FNV1aHash //FNV-1a: https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%8 { public: FNV1aHash() {} - explicit FNV1aHash(Num startVal) : hashVal_(startVal) {} + explicit FNV1aHash(Num startVal) : hashVal_(startVal) { assert(startVal != 0); /*(yes, might be a real hash, but) most likely bad init value*/} void add(Num n) { diff --git a/zen/string_base.h b/zen/string_base.h index 676d7f7f..98544ab3 100644 --- a/zen/string_base.h +++ b/zen/string_base.h @@ -586,7 +586,7 @@ void Zbase<Char, SP>::reserve(size_t minCapacity) //make unshared and check capa //allocate a new string const size_t len = size(); Char* newStr = this->create(len, std::max(len, minCapacity)); //reserve() must NEVER shrink the string: logical const! - *std::copy(rawStr_, rawStr_ + len , newStr) = 0; + *std::copy(rawStr_, rawStr_ + len, newStr) = 0; this->destroy(rawStr_); rawStr_ = newStr; diff --git a/zen/string_tools.h b/zen/string_tools.h index 3975cc92..ca086efd 100644 --- a/zen/string_tools.h +++ b/zen/string_tools.h @@ -53,7 +53,6 @@ struct StringHashAsciiNoCase; struct StringEqualAsciiNoCase; template <class Num, class S> Num hashString(const S& str); -template <class Num, class S> Num appendHashString(Num hashVal, const S& str); enum class IfNotFoundReturn { @@ -315,7 +314,7 @@ bool contains(const S& str, const T& term) const auto* const strFirst = strBegin(str); const auto* const strLast = strFirst + strLen; const auto* const termFirst = strBegin(term); - + return searchFirst(strFirst, strLast, termFirst, termFirst + termLen) != strLast; } @@ -331,7 +330,7 @@ S afterLast(const S& str, const T& term, IfNotFoundReturn infr) const auto* const strFirst = strBegin(str); const auto* const strLast = strFirst + strLength(str); const auto* const termFirst = strBegin(term); - + const auto* it = searchLast(strFirst, strLast, termFirst, termFirst + termLen); if (it == strLast) @@ -348,7 +347,7 @@ S beforeLast(const S& str, const T& term, IfNotFoundReturn infr) static_assert(std::is_same_v<GetCharTypeT<S>, GetCharTypeT<T>>); const size_t termLen = strLength(term); assert(termLen > 0); - + const auto* const strFirst = strBegin(str); const auto* const strLast = strFirst + strLength(str); const auto* const termFirst = strBegin(term); @@ -372,7 +371,7 @@ S afterFirst(const S& str, const T& term, IfNotFoundReturn infr) const auto* const strFirst = strBegin(str); const auto* const strLast = strFirst + strLength(str); const auto* const termFirst = strBegin(term); - + const auto* it = searchFirst(strFirst, strLast, termFirst, termFirst + termLen); if (it == strLast) @@ -393,7 +392,7 @@ S beforeFirst(const S& str, const T& term, IfNotFoundReturn infr) const auto* const strFirst = strBegin(str); const auto* const strLast = strFirst + strLength(str); const auto* const termFirst = strBegin(term); - + auto it = searchFirst(strFirst, strLast, termFirst, termFirst + termLen); if (it == strLast) @@ -642,7 +641,7 @@ S printNumber(const T& format, const Num& number) //format a single number using #error refactor? #endif static_assert(std::is_same_v<GetCharTypeT<S>, GetCharTypeT<T>>); - assert(strBegin(format)[strLength(format)] == 0); //format must be null-terminated! + assert(strBegin(format)[strLength(format)] == 0); //format must be null-terminated! S buf(128, static_cast<GetCharTypeT<S>>('0')); const int charsWritten = impl::saferPrintf(buf.data(), buf.size(), strBegin(format), number); diff --git a/zen/sys_info.cpp b/zen/sys_info.cpp index df0e4612..244343f2 100644 --- a/zen/sys_info.cpp +++ b/zen/sys_info.cpp @@ -48,7 +48,7 @@ Zstring zen::getLoginUser() //throw FileError &pwEntry); //struct passwd** result rv != 0 || !pwEntry) { - //"If an error occurs, errno is set appropriately" => why the fuck, then also return errno as return value!? + //"If an error occurs, errno is set appropriately" => why the fuck, then, also return errno as return value!? errno = rv != 0 ? rv : ENOENT; THROW_LAST_FILE_ERROR(_("Cannot get process information."), "getpwuid_r(" + numberTo<std::string>(userIdNo) + ')'); } @@ -65,9 +65,9 @@ Zstring zen::getLoginUser() //throw FileError //BUT: getlogin() can fail with ENOENT on Linux Mint: https://freefilesync.org/forum/viewtopic.php?t=8181 //getting a little desperate: variables used by installer.sh - if (const char* userName = tryGetNonRootUser("USER")) return userName; - if (const char* userName = tryGetNonRootUser("SUDO_USER")) return userName; - if (const char* userName = tryGetNonRootUser("LOGNAME")) return userName; + if (const char* username = tryGetNonRootUser("USER")) return username; + if (const char* username = tryGetNonRootUser("SUDO_USER")) return username; + if (const char* username = tryGetNonRootUser("LOGNAME")) return username; //apparently the current user really IS root: https://freefilesync.org/forum/viewtopic.php?t=8405 @@ -78,7 +78,7 @@ Zstring zen::getLoginUser() //throw FileError Zstring zen::getUserDescription() //throw FileError { - const Zstring userName = getLoginUser(); //throw FileError + const Zstring username = getLoginUser(); //throw FileError const Zstring computerName = []() -> Zstring //throw FileError { std::vector<char> buf(10000); @@ -92,10 +92,10 @@ Zstring zen::getUserDescription() //throw FileError return hostName; }(); - if (contains(getUpperCase(computerName), getUpperCase(userName))) - return userName; //no need for text duplication! e.g. "Zenju (Zenju-PC)" + if (contains(getUpperCase(computerName), getUpperCase(username))) + return username; //no need for text duplication! e.g. "Zenju (Zenju-PC)" - return userName + Zstr(" (") + computerName + Zstr(')'); //e.g. "Admin (Zenju-PC)" + return username + Zstr(" (") + computerName + Zstr(')'); //e.g. "Admin (Zenju-PC)" } @@ -118,7 +118,7 @@ ComputerModel zen::getComputerModel() //throw FileError } catch (FileError&) { - if (!itemStillExists(filePath)) //throw FileError + if (!itemExists(filePath)) //throw FileError return std::wstring(); throw; diff --git a/zen/thread.h b/zen/thread.h index 1823eefc..25a6463a 100644 --- a/zen/thread.h +++ b/zen/thread.h @@ -161,7 +161,7 @@ public: ~ThreadGroup() { for (InterruptibleThread& w : worker_) - w.requestStop(); //stop *all* at the same time before join! + w.requestStop(); //similar, but not the same as ~InterruptibleThread: stop *all* at the same time before join! if (detach_) //detach() without requestStop() doesn't make sense for (InterruptibleThread& w : worker_) @@ -190,13 +190,13 @@ public: void wait() { //perf: no difference in xBRZ test case compared to std::condition_variable-based implementation - auto promiseDone = std::make_shared<std::promise<void>>(); // - std::future<void> allDone = promiseDone->get_future(); + auto promDone = std::make_shared<std::promise<void>>(); // + std::future<void> futDone = promDone->get_future(); - notifyWhenDone([promiseDone] { promiseDone->set_value(); }); //std::function doesn't support construction involving move-only types! + notifyWhenDone([promDone] { promDone->set_value(); }); //std::function doesn't support construction involving move-only types! //use reference? => potential lifetime issue, e.g. promise object theoretically might be accessed inside set_value() after future gets signalled - allDone.get(); + futDone.get(); } //non-blocking wait()-alternative: context of controlling thread: diff --git a/zen/zstring.cpp b/zen/zstring.cpp index 59e90956..019973e9 100644 --- a/zen/zstring.cpp +++ b/zen/zstring.cpp @@ -22,11 +22,17 @@ Zstring getUnicodeNormalForm_NonAsciiValidUtf(const Zstring& str, UnicodeNormalF try { - gchar* outStr = ::g_utf8_normalize(str.c_str(), str.length(), form == UnicodeNormalForm::nfc ? G_NORMALIZE_NFC : G_NORMALIZE_NFD); - if (!outStr) + gchar* strNorm = ::g_utf8_normalize(str.c_str(), str.length(), form == UnicodeNormalForm::nfc ? G_NORMALIZE_NFC : G_NORMALIZE_NFD); + if (!strNorm) throw SysError(formatSystemError("g_utf8_normalize", L"", L"Conversion failed.")); - ZEN_ON_SCOPE_EXIT(::g_free(outStr)); - return outStr; + ZEN_ON_SCOPE_EXIT(::g_free(strNorm)); + + const std::string_view strNormView(strNorm, strLength(strNorm)); + + if (equalString(str, strNormView)) //avoid extra memory allocation + return str; + + return Zstring(strNormView); } catch (const SysError& e) @@ -37,7 +43,7 @@ Zstring getUnicodeNormalForm_NonAsciiValidUtf(const Zstring& str, UnicodeNormalF } -Zstring getUnicodeNormalFormNonAscii(const Zstring& str, UnicodeNormalForm form) +Zstring getValidUtf(const Zstring& str) { /* 1. do NOT fail on broken UTF encoding, instead normalize using REPLACEMENT_CHAR! 2. NormalizeString() haateeez them Unicode non-characters: ERROR_NO_UNICODE_TRANSLATION! http://www.unicode.org/faq/private_use.html#nonchar1 @@ -68,10 +74,10 @@ Zstring getUnicodeNormalFormNonAscii(const Zstring& str, UnicodeNormalForm form) codePointToUtf<Zchar>(*cp, [&](Zchar ch) { validStr += ch; }); } - return getUnicodeNormalForm_NonAsciiValidUtf(validStr, form); + return validStr; } else - return getUnicodeNormalForm_NonAsciiValidUtf(str, form); + return str; } @@ -88,9 +94,11 @@ Zstring getUpperCaseAscii(const Zstring& str) Zstring getUpperCaseNonAscii(const Zstring& str) { - Zstring strNorm = getUnicodeNormalFormNonAscii(str, UnicodeNormalForm::native); + const Zstring& strValidUtf = getValidUtf(str); try { + const Zstring strNorm = getUnicodeNormalForm_NonAsciiValidUtf(strValidUtf, UnicodeNormalForm::native); + Zstring output; output.reserve(strNorm.size()); @@ -118,7 +126,7 @@ Zstring getUnicodeNormalForm(const Zstring& str, UnicodeNormalForm form) if (isAsciiString(str)) //fast path: in the range of 3.5ns return str; - return getUnicodeNormalFormNonAscii(str, form); //slow path + return getUnicodeNormalForm_NonAsciiValidUtf(getValidUtf(str), form); //slow path } diff --git a/zenXml/zenxml/dom.h b/zenXml/zenxml/dom.h index ff409eb1..cba12cfb 100644 --- a/zenXml/zenxml/dom.h +++ b/zenXml/zenxml/dom.h @@ -317,8 +317,7 @@ private: XmlDoc (const XmlDoc&) = delete; //not implemented, thanks to XmlElement::parent_ XmlDoc& operator=(const XmlDoc&) = delete; - //std::string version_ {"1.0"}; -> who cares!? - std::string version_; + std::string version_ {"1.0"}; //non-optional for valid XML std::string encoding_{"utf-8"}; std::string standalone_; |