diff options
46 files changed, 941 insertions, 250 deletions
diff --git a/.qmake.conf b/.qmake.conf index 29a1f22..eea2453 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,6 +1,9 @@ load(qt_build_config) CONFIG += qt_example_installs -MODULE_VERSION = 5.13.1 +DEFINES += QT_NO_JAVA_STYLE_ITERATORS +DEFINES += QT_NO_FOREACH + +MODULE_VERSION = 5.14.0 QTRO_SOURCE_TREE = $$PWD diff --git a/examples/remoteobjects/remoteobjects.pro b/examples/remoteobjects/remoteobjects.pro index e4dd62a..9b22d21 100644 --- a/examples/remoteobjects/remoteobjects.pro +++ b/examples/remoteobjects/remoteobjects.pro @@ -3,7 +3,8 @@ CONFIG += debug_and_release ordered SUBDIRS = \ server \ cppclient \ - simpleswitch + simpleswitch \ + websockets qtHaveModule(widgets) { SUBDIRS += \ diff --git a/examples/remoteobjects/websockets/common/cert/cert.qrc b/examples/remoteobjects/websockets/common/cert/cert.qrc new file mode 100644 index 0000000..65f92e2 --- /dev/null +++ b/examples/remoteobjects/websockets/common/cert/cert.qrc @@ -0,0 +1,11 @@ +<RCC> + <qresource prefix="/sslcert"> + <file>client.crt</file> + <file>client.key</file> + <file>rootCA.key</file> + <file>rootCA.pem</file> + <file>rootCA.srl</file> + <file>server.crt</file> + <file>server.key</file> + </qresource> +</RCC> diff --git a/examples/remoteobjects/websockets/common/cert/client.crt b/examples/remoteobjects/websockets/common/cert/client.crt new file mode 100644 index 0000000..e8c8c14 --- /dev/null +++ b/examples/remoteobjects/websockets/common/cert/client.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC8jCCAdoCCQDPkkFD8ish3zANBgkqhkiG9w0BAQsFADAxMQswCQYDVQQGEwJV +UzEPMA0GA1UECAwGT3JlZ29uMREwDwYDVQQHDAhQb3J0bGFuZDAeFw0xODA3MDMw +OTMyNTFaFw0yMzA3MDIwOTMyNTFaMEUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIDAZP +cmVnb24xETAPBgNVBAcMCFBvcnRsYW5kMRIwEAYDVQQDDAkxMjcuMC4wLjEwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDexH8hCVisI6sHb7o2nK3kMuwT +DEBoQesEqZsfypiwOYkB2OqzW3HmFfDeUVKBGBJk07QPYM1v9ocaEbYFkAOpj1hH +Gl02DihWqMqbFdwugV/z6dwo8r7ZOsCYhDeAhtXKbAX2ASGdlHusY9lIHRqGrlm3 +veHJrdXUAQAYHyI7XrinLV8RNCMDI3CVhcNEOc3C3AyufcXUZ1cEGAYDPXGtwPEd +RFQQBbyYSQ4RgR2BlPkPE1VQiE01cDFMF8RNaQL89uhJkMruano+7eTawax1h8q4 +D2LK9sRPRtz7Zivx3Z2Vk9I7suX9C2RhuSgzHiXWuP7VBVcJiAL/GICoq9bJAgMB +AAEwDQYJKoZIhvcNAQELBQADggEBABy/ofQyVtXNZ6thyU+M41m3nb2DFayFimjm +wPcbgXR/EPyZrP2I1O8FZh7KlICg97kqPsN4CvVU6n9KVmM3EVzwNcPuwr0ufXHF +nq/lrVvy0osNh8KzN8jpHZ8Dsl4XXnXAKh4oxCRVB+R4FVirBTAQiu7OUFk+s7I5 +hoXI47whP7sOmxB+2YbVFPSTj26pupssMHCDoxAXC36ARH/68itdX2LQ5iLoqzEI +PNxuLY3fFEGnu0ymZUMuevIbD4tAZiIlw17gr683pwNCuEvKAyNoehLnknXIILs5 +pVx3XcS6vw5+IbQb+HdxT/RPm6U4fIZVFdoC2o/x1G8wzPJvW/0= +-----END CERTIFICATE----- diff --git a/examples/remoteobjects/websockets/common/cert/client.key b/examples/remoteobjects/websockets/common/cert/client.key new file mode 100644 index 0000000..75e1f43 --- /dev/null +++ b/examples/remoteobjects/websockets/common/cert/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA3sR/IQlYrCOrB2+6Npyt5DLsEwxAaEHrBKmbH8qYsDmJAdjq +s1tx5hXw3lFSgRgSZNO0D2DNb/aHGhG2BZADqY9YRxpdNg4oVqjKmxXcLoFf8+nc +KPK+2TrAmIQ3gIbVymwF9gEhnZR7rGPZSB0ahq5Zt73hya3V1AEAGB8iO164py1f +ETQjAyNwlYXDRDnNwtwMrn3F1GdXBBgGAz1xrcDxHURUEAW8mEkOEYEdgZT5DxNV +UIhNNXAxTBfETWkC/PboSZDK7mp6Pu3k2sGsdYfKuA9iyvbET0bc+2Yr8d2dlZPS +O7Ll/QtkYbkoMx4l1rj+1QVXCYgC/xiAqKvWyQIDAQABAoIBAQCDTQYxjrS5IXzZ +MT1smwTTkEAdKgd8a/3+DYnlPyCoHgFnGVecx7VmjGAgaYZbmLievTlQJxpvd7tB +3laPCMdf1aGOpzdxeP7FtU9WAZh5wL+xoJGngQyENWD3hFbCZrb0TJ9m1Fvf6XjL +rz6Ohrjv0SwIZN8EZHW4M66+iPtASgabi2mgMl6tiF2p+Cl7CDSvd70u4WNEdhN5 +9rtLqReSYQmRHJvXddh6A1uSYujnYdV5tmg6tx1BkbFf9W6R5HllkOXLsT2c9uGD +qO/8hZxzf8bJICJe/2aoKC6WEXdMkkasMgtEMlPXIPITxspZvjDeGwy2/A6CnloX +sCoHlaABAoGBAPaj/LZxyyRT2rELATtZbLs/G8hXQKnywihSSnaeLpf2p/VyBpOx +cJtTMvKcPACEfnX3n40cMVbC3XOx/prbYxs5PFhzTkhPk5v5joGymRtmNajpm2/a +G2tbYBC/lCHLDj6Jw0i1VFIB620WtnTm9agf7zRCholSBbeRl21CyMUBAoGBAOc4 +l8WgXU/Nv+mmGgv94GZCdLYTHo5WEKbBN3uaXZaLU6YA00Hkroa4xh5Ic+7tRTBw +T+byoKicn7XuCNeJRy0FDxPgLj+d70sZ6Fzxq9xP8uwQ8gD/G2jO5v3e4O3F70sf +DjpTrFRZXC/isNooE1HCerjS9fPs619m98ylfCnJAoGAWgMzQap6BwILeD2Z730N +b7DyhMVDNkMAlRKjVnMYciF03uEEgXZqsGVG3MAkLdQtCwSaWDeH0jA//e9iCkYy +/0Z+PZGnakCQkIYdejwiIJvGzaSkM8gX5bBteO9SMpsW0cAZYzm6UkudDi0R3cxE +r10oQZxd2VPz/jDGYPvUpgECgYEAvT1+SksT0+rrdUly6/mfHVKqvxIq4gfinPhq +dolCq6Hglm76eGW3yZ+U1tgpupULGbfyTWyqvRVjSb1GE1HRpTEMxBGpCHw0i1zq +5pcNN8VfZoH/73zbbA5a09EEetaTIQKL3IT6+BYi8zYv1H0UQshPNNHEZx2zDmPx +z9ZpJrECgYEAmxsv/6LNyV5+h8WOdyHtNFF04jo1s9CfRc0fMkKVQNZVaOu3sgLZ +B4r2XrK75S19iJj4AVxf7dP3EbblDXvnQhlLV8IcYuULDovdXvYJrkv2a0KQ5nqO +mt8brk85kb/GW8MrYHwLeFYSytZk267osPlwzIW1Zr9pDpARSVXer98= +-----END RSA PRIVATE KEY----- diff --git a/examples/remoteobjects/websockets/common/cert/rootCA.key b/examples/remoteobjects/websockets/common/cert/rootCA.key new file mode 100644 index 0000000..4603898 --- /dev/null +++ b/examples/remoteobjects/websockets/common/cert/rootCA.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAnFgYQwg4xeA2yYnWZ0TqZCEBlzg2zbi0ToeO3msOYI7m6urI +/gUp3uezK/5bO9xVudRYq9qbK/1XmAhD+oILxVFY8VHO9p7xGVav2T8cPtFUkj05 +9WT7TDlOwEIOyb7WbEjLE1a0u9Iyl6Ju7VwCf0xijtD8TomB41PojNe49G1JN5CK +AdkCYyrgjCBj13iZo9VFp/xWWTfk6iPa928AavYYUWHizAc3Kvr46DGW9pIjPthH +EC6dmiX0oHfLF8HcTvgL/pHzF2bT5grYoARwIectD996z8smrsN7clfjMHwDHH8a +OCgIvNNOs4jWSu6oXqEwvGyRxmsHFi1jbhHNkwIDAQABAoIBADmSQxTkASv0fZhH +VpleikVm1hQeUif9HQBR8K08lOW/mY7l+C96LUn03kiT+HqZj0PHywM1k7BmMQw9 +9vJXUwhNBUiPzHuKWdPv1P9Vuwvyv4a+XwpbLiKKc9JeQN3PlVv4jjdH1XPYWmL2 +IIztNco0kZJvqIkvH5JbgqXihiwTQuyw6SnvF/kxZmTFnX9uzakNW/fYhE1rHig8 +Z/l4Ojhh9rvE//aCS0FMGd5GFNzoWyOSSExvZePupWgYsQluBQFgZK9Mh2EmObnY +o8yy7DZ93JKSwFxVouj4Oqm9jX3Xq/v2Oz9ZN8ZoOeS4IvgWHoPCNDbFllrTWLDi +r8aG5EECgYEAyD+Gq74db6C6Of4C8L29SLdPglsLlkR2ZVZN3d8DcysEiGlLHbRB +STNYvFw3T4zmkOJQhcCmfrUAZ1D7ybvCxifyLR0xkjz50ALwzNTyg0VgBPVJWfLx +nNzuF47Vtmu33P0xCiMUg7PDhIV22zaaBhgNqaNZFCGhyGrLisQwdKECgYEAx99b +ErYq9P7/GP27J3SIL2TY9dWWBQBMpXx+GaHE0gOixrL6ZYrS0hVik60K/trgDGUx +RTu4K8JLSo7NQqDcuRXVfMguNNrrAZ3DxqMJ8D2vS9ObDRa0hl2ctKAoIfno8xII +PVGcSShrJvpw/P9AdkEYUUYZHJPDfWbqOZB3obMCgYAspNUOZwVDBM9f7HyVVYfk +tVGZm1i6+Kp4r0QO6hBn1bhd/TOM/MntWvA2lkyShLRGqt4O48N6zjm3zvtDn4Ou +D+vTGQYbN1LuiClNUVB76bSdhl4DGsG5GhxOzj5hPCSytRQA0Y9aSXKWkfbMqqCu +KSCqqEtMzK638u9MEa9H4QKBgFOQRntkPkF/+xdvvbeZOPbXqv3c9oPQxDrL+cyt +naRQcNWyLo4VpF7BIh2r01UKHXIRPLA9b5qb+O6LFbYtmxqmzkMFTow6mtZqJ1f9 +AkK3B3skVUb7ny4uJT4/V4gc/A/kEh3Q6Q6NH3+EZYjhDwph3NDeBdG01Z6wUG0Q +wXORAoGAQwdTtwI1mXtCF/AXYdgdpLxwP1mtevfxt7j65CPQYOQK4ceu54Ka48+8 +2TkmC/WjyWtM1YJZtArJsFBGYcX4WoVtGCU1Mbl19+1vKQMb1dlOC0HqU0c9UCcu +fD6y4coCLXemKOJ32sHMdy8qyFxOz2CrznZa4uYBT4Lid8SY+yY= +-----END RSA PRIVATE KEY----- diff --git a/examples/remoteobjects/websockets/common/cert/rootCA.pem b/examples/remoteobjects/websockets/common/cert/rootCA.pem new file mode 100644 index 0000000..6f3f886 --- /dev/null +++ b/examples/remoteobjects/websockets/common/cert/rootCA.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIJAJDf3heNbfP6MA0GCSqGSIb3DQEBCwUAMDExCzAJBgNV +BAYTAlVTMQ8wDQYDVQQIDAZPcmVnb24xETAPBgNVBAcMCFBvcnRsYW5kMB4XDTE4 +MDcwMzA5MzI1MFoXDTIzMDcwMjA5MzI1MFowMTELMAkGA1UEBhMCVVMxDzANBgNV +BAgMBk9yZWdvbjERMA8GA1UEBwwIUG9ydGxhbmQwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCcWBhDCDjF4DbJidZnROpkIQGXODbNuLROh47eaw5gjubq +6sj+BSne57Mr/ls73FW51Fir2psr/VeYCEP6ggvFUVjxUc72nvEZVq/ZPxw+0VSS +PTn1ZPtMOU7AQg7JvtZsSMsTVrS70jKXom7tXAJ/TGKO0PxOiYHjU+iM17j0bUk3 +kIoB2QJjKuCMIGPXeJmj1UWn/FZZN+TqI9r3bwBq9hhRYeLMBzcq+vjoMZb2kiM+ +2EcQLp2aJfSgd8sXwdxO+Av+kfMXZtPmCtigBHAh5y0P33rPyyauw3tyV+MwfAMc +fxo4KAi8006ziNZK7qheoTC8bJHGawcWLWNuEc2TAgMBAAGjUzBRMB0GA1UdDgQW +BBRFDBFImjfGGcuUO2yGvXFtkj+tATAfBgNVHSMEGDAWgBRFDBFImjfGGcuUO2yG +vXFtkj+tATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCbBnbX +ms5mFTaPJislt+8A7c/HKz5S5U2jg4+5Nh7b7szbG3s/AGDuSwEQDRAU5J8gqb1r +IkmrkZA3C8mEY/NLzDjbbW+T0z7zlXFXWKZmzhx+ROONys1HGKwNRe/oa9cAJnbv +KeMfruIXeSTf6U9tehUdoEk87eTAONm4PtVgE4aenSxaIdT7dXlzYBzhCFzsXH/y +VyNQD0wd7u+L6av+zRod7Sz7WU/Lnhi1fQXcFmmAmmmCHyctI0xgwdRB9O80ls8s +Ea+0J9Mkt07YTKcG1ZpmJHU915M/aDDpV/2RGcYGLOHOrD1IT8Cl3ZwHGlERI3y6 ++GFPhQzo4mXu3pdb +-----END CERTIFICATE----- diff --git a/examples/remoteobjects/websockets/common/cert/rootCA.srl b/examples/remoteobjects/websockets/common/cert/rootCA.srl new file mode 100644 index 0000000..8888354 --- /dev/null +++ b/examples/remoteobjects/websockets/common/cert/rootCA.srl @@ -0,0 +1 @@ +CF924143F22B21E0 diff --git a/examples/remoteobjects/websockets/common/cert/server.crt b/examples/remoteobjects/websockets/common/cert/server.crt new file mode 100644 index 0000000..0587867 --- /dev/null +++ b/examples/remoteobjects/websockets/common/cert/server.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC7zCCAdcCCQDPkkFD8ish4DANBgkqhkiG9w0BAQsFADAxMQswCQYDVQQGEwJV +UzEPMA0GA1UECAwGT3JlZ29uMREwDwYDVQQHDAhQb3J0bGFuZDAeFw0xODA3MDMw +OTMyNTFaFw0yMzA3MDIwOTMyNTFaMEIxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIDAZP +cmVnb24xDjAMBgNVBAcMBVNhbGVtMRIwEAYDVQQDDAkxMjcuMC4wLjEwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1zm/3QDUh1FhAczb7zDzme2Ncgs3x +26RNMCS+DKQS8mf4tuyBT/62Ba8pMgOi46hS2/7BKbCFlU3F4rZiz/2y50fs5m0z +Puf9sB6xGrya4hzLS7gML7QbP3gXvmWSYRGLT4kpK7Cf58nK9P8NWbgzcX95bjlV +QDyUdLNy9wnH5xuumdIk7Il4EmSjWyL7N5PtEpfgvG79DAh8AiWvVWKgddVbkAUy +s4kI+2LJ3NKfLGqh0ijY00a6KD7wuAAyws5EqQQ3/BYDf6/dSRXRMED/0gg1XPF5 +7VtTDltwneelfVI1SBhgHTE5ynN0WiTP5LaVPs6jQPJXNslvbWWbyngNAgMBAAEw +DQYJKoZIhvcNAQELBQADggEBAEGGolgL7wv4NwuAfFA0fPu6VZOfqgqw3g5M2gpw +7+XcUSWdum/8yUxkeaI5fLSA3sq6PefLaMpZ7+2JQYKJZZ4zl3fJ5D1M/VMQOQ1Q +PAMzGjHNZ7T0vs5F5TdpbXpEbvcBvLz/k2FRMs2Z/WBQZQITEiQ1wf91jxc4dQr5 +nM6CN0TUW8wCKOi+8QXruUnHnaPreRh68A2FfnGSBJlkImhkFjAMtIdpkAHTiNs+ +PE/Dx58wsrnY6DiZfYPrKj54TkdnoKpWCLarxuMzeGUEvQcaXhksnRfDBc5k4ev4 +g7RhsGXyIJvFFvKVeH9GbGfgSXn7rc6Tesnzyh+mvHT3vMU= +-----END CERTIFICATE----- diff --git a/examples/remoteobjects/websockets/common/cert/server.key b/examples/remoteobjects/websockets/common/cert/server.key new file mode 100644 index 0000000..e9bc3a1 --- /dev/null +++ b/examples/remoteobjects/websockets/common/cert/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAtc5v90A1IdRYQHM2+8w85ntjXILN8dukTTAkvgykEvJn+Lbs +gU/+tgWvKTIDouOoUtv+wSmwhZVNxeK2Ys/9sudH7OZtMz7n/bAesRq8muIcy0u4 +DC+0Gz94F75lkmERi0+JKSuwn+fJyvT/DVm4M3F/eW45VUA8lHSzcvcJx+cbrpnS +JOyJeBJko1si+zeT7RKX4Lxu/QwIfAIlr1VioHXVW5AFMrOJCPtiydzSnyxqodIo +2NNGuig+8LgAMsLORKkEN/wWA3+v3UkV0TBA/9IINVzxee1bUw5bcJ3npX1SNUgY +YB0xOcpzdFokz+S2lT7Oo0DyVzbJb21lm8p4DQIDAQABAoIBAFbJrk9Uekik6mAR +3/yBecz4t+zwkElVdXBXfCKxPB3DU/i5sdrlCg1wVzaOJog6rx6m4EzrjtWl+VNu +r2wqJ8ygdYhUU2q0K+DBk1UuEzzIlcBCbCB9ITgkqzqCbFBdQBfFpw9dSNp8tqrJ +G3wPCUydcKHSCVJ18LVZpFRMM4IWNWeIr2P3GvlXHTZodYkVRgb/A0Wr8BS+tlVx +lGSOETgihNgyzG8tB3TZDrhlc2So6zrU0E+Akk8jXNARqBGUPwjeIORkX6RB913G +mXqKpXRjdD8xzK/0a665wHv/3yFEuMjK/raiX/UrA/i01J++A0/PMyD8XoNLVcFk +WG3mE20CgYEA6HYwnCb1lulMOJA/2QDDNSp/yeTlCo/5Oem0D/kzCuyiYlYZPMJY +x33MoozY/4tdmajuYDiB71hj2pZLE3FYdpU4pmaR8G8T6Yf3KesvXoe9+89VUsS3 +bv2a6kfD1RHX+4DxRDIBbIKg11RBV2cOKsf1i0pn+VqkuJQcnVi+KKcCgYEAyDcs +tSf6vJSAWgiJfNi5+wq0bxLZi+DL+9y6hmu1HrUUgMVUcU7qaKFHvq4NHR95Ww0q +nxAjHB/KqRPLrDlIfkhmOttQThzEQClUUSS9f8BEndW/6BPBFVyAQS+GsDv55lEy +n7LM9GaNu+CGq6zZPOFBnNVBW2E4fwIRkkLpvCsCgYAq9URwZua1l7FlNosGABUS +6yKoXatR8188K4sB9KxRFX/AqmaJiuS7IO1DEMI9HzUR410B3Q9t+qihSWrgUe7m +IxdP8N6BTxWf72dmkLa1QmKCeUMsQ3wef7E0IET5SA3gxWhQkOkgc1dj04crrri4 +gTFIJ1zlgLG2BnDvRuoFOwKBgCueiaj2CtRm7gevcHS4qtwcmu7QBoFI+mfm0ORU +NuN3w/3CAAGnlb4x1PWf6c98ee3yUmTRGTUZYAex/l+JI1gP4eXUvgwmjEMGPg5n +mLlqZAiW9vZSx3Al9PM+rXNbvbgF3KeaRrjAVwSlh/GC+NkgojDO7SxBZBOXmchp +t459AoGABXvsiqC8TxAyGTlnVUTNlWnWzo7Qy+DHsJUgLvEdW47oairtdvGjCWFU +dBk7qmxDNpEZ/0LrUtcgLwN/45PXOrKn0ojA86Csoij5HbsUx0c/g8bMES0ilghx +tbEtOBkXNIPgmaXdyXW203i3/oLSY1nedePIbJU22nJzQHmw0mk= +-----END RSA PRIVATE KEY----- diff --git a/examples/remoteobjects/websockets/common/common.pri b/examples/remoteobjects/websockets/common/common.pri new file mode 100644 index 0000000..4ee7eef --- /dev/null +++ b/examples/remoteobjects/websockets/common/common.pri @@ -0,0 +1,11 @@ +CONFIG -= app_bundle + +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/websocketiodevice.h + +SOURCES += \ + $$PWD/websocketiodevice.cpp + +RESOURCES += $$PWD/cert/cert.qrc diff --git a/examples/remoteobjects/websockets/common/websocketiodevice.cpp b/examples/remoteobjects/websockets/common/websocketiodevice.cpp new file mode 100644 index 0000000..4c3e917 --- /dev/null +++ b/examples/remoteobjects/websockets/common/websocketiodevice.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Ford Motor Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtRemoteObjects module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "websocketiodevice.h" + +#include <QWebSocket> + +WebSocketIoDevice::WebSocketIoDevice(QWebSocket *webSocket, QObject *parent) + : QIODevice(parent) + , m_socket(webSocket) +{ + open(QIODevice::ReadWrite); + connect(webSocket, &QWebSocket::disconnected, this, &WebSocketIoDevice::disconnected); + connect(webSocket, &QWebSocket::binaryMessageReceived, this, [this](const QByteArray &message){ + m_buffer.append(message); + emit readyRead(); + }); + connect(webSocket, &QWebSocket::bytesWritten, this, &WebSocketIoDevice::bytesWritten); +} + +qint64 WebSocketIoDevice::bytesAvailable() const +{ + return QIODevice::bytesAvailable() + m_buffer.size(); +} + +bool WebSocketIoDevice::isSequential() const +{ + return true; +} + +void WebSocketIoDevice::close() +{ + if (m_socket) + m_socket->close(); +} + +qint64 WebSocketIoDevice::readData(char *data, qint64 maxlen) +{ + auto sz = std::min(int(maxlen), m_buffer.size()); + if (sz <= 0) + return sz; + memcpy(data, m_buffer.constData(), size_t(sz)); + m_buffer.remove(0, sz); + return sz; +} + +qint64 WebSocketIoDevice::writeData(const char *data, qint64 len) +{ + if (m_socket) + return m_socket->sendBinaryMessage(QByteArray{data, int(len)}); + return -1; +} diff --git a/examples/remoteobjects/websockets/common/websocketiodevice.h b/examples/remoteobjects/websockets/common/websocketiodevice.h new file mode 100644 index 0000000..0e5609c --- /dev/null +++ b/examples/remoteobjects/websockets/common/websocketiodevice.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Ford Motor Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtRemoteObjects module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WEBSOCKETIODEVICE_H +#define WEBSOCKETIODEVICE_H + +#include <QBuffer> +#include <QIODevice> +#include <QPointer> + +class QWebSocket; + +class WebSocketIoDevice : public QIODevice +{ + Q_OBJECT +public: + WebSocketIoDevice(QWebSocket *webSocket, QObject *parent = nullptr); + +signals: + void disconnected(); + + // QIODevice interface +public: + qint64 bytesAvailable() const override; + bool isSequential() const override; + void close() override; + +protected: + qint64 readData(char *data, qint64 maxlen) override; + qint64 writeData(const char *data, qint64 len) override; + +private: + QPointer<QWebSocket> m_socket; + QByteArray m_buffer; +}; + +#endif // WEBSOCKETIODEVICE_H diff --git a/examples/remoteobjects/websockets/websockets.pro b/examples/remoteobjects/websockets/websockets.pro new file mode 100644 index 0000000..bb2685a --- /dev/null +++ b/examples/remoteobjects/websockets/websockets.pro @@ -0,0 +1,7 @@ +TEMPLATE = subdirs + +qtHaveModule(widgets): qtHaveModule(websockets) { + SUBDIRS += \ + wsclient \ + wsserver +} diff --git a/examples/remoteobjects/websockets/wsclient/main.cpp b/examples/remoteobjects/websockets/wsclient/main.cpp new file mode 100644 index 0000000..19b7672 --- /dev/null +++ b/examples/remoteobjects/websockets/wsclient/main.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Ford Motor Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtRemoteObjects module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QTreeView> +#include <QApplication> +#include <QRemoteObjectNode> +#include <QAbstractItemModelReplica> +#include <QWebSocket> + +#ifndef QT_NO_SSL +# include <QFile> +# include <QSslConfiguration> +# include <QSslKey> +#endif +#include "websocketiodevice.h" + +int main(int argc, char **argv) +{ + + QLoggingCategory::setFilterRules("qt.remoteobjects.debug=false\n" + "qt.remoteobjects.warning=false\n" + "qt.remoteobjects.models.debug=false\n" + "qt.remoteobjects.models.debug=false"); + + QApplication app(argc, argv); + + + + QScopedPointer<QWebSocket> webSocket{new QWebSocket}; + WebSocketIoDevice socket(webSocket.data()); +#ifndef QT_NO_SSL + // Always use secure connections when available + QSslConfiguration sslConf; + QFile certFile(QStringLiteral(":/sslcert/client.crt")); + if (!certFile.open(QIODevice::ReadOnly)) + qFatal("Can't open client.crt file"); + sslConf.setLocalCertificate(QSslCertificate{certFile.readAll()}); + + QFile keyFile(QStringLiteral(":/sslcert/client.key")); + if (!keyFile.open(QIODevice::ReadOnly)) + qFatal("Can't open client.key file"); + sslConf.setPrivateKey(QSslKey{keyFile.readAll(), QSsl::Rsa}); + + sslConf.setPeerVerifyMode(QSslSocket::VerifyPeer); + webSocket->setSslConfiguration(sslConf); +#endif + QRemoteObjectNode node; + node.addClientSideConnection(&socket); + node.setHeartbeatInterval(1000); + webSocket->open(QStringLiteral("ws://localhost:8088")); + + QTreeView view; + view.setWindowTitle(QStringLiteral("RemoteView")); + view.resize(640,480); + QScopedPointer<QAbstractItemModelReplica> model(node.acquireModel(QStringLiteral("RemoteModel"))); + view.setModel(model.data()); + view.show(); + + return app.exec(); +} diff --git a/examples/remoteobjects/websockets/wsclient/wsclient.pro b/examples/remoteobjects/websockets/wsclient/wsclient.pro new file mode 100644 index 0000000..f329e4a --- /dev/null +++ b/examples/remoteobjects/websockets/wsclient/wsclient.pro @@ -0,0 +1,9 @@ +QT += widgets remoteobjects websockets +requires(qtConfig(treeview)) + +SOURCES += main.cpp + +include(../common/common.pri) + +target.path = $$[QT_INSTALL_EXAMPLES]/remoteobjects/websockets/wsclient +INSTALLS += target diff --git a/examples/remoteobjects/websockets/wsserver/main.cpp b/examples/remoteobjects/websockets/wsserver/main.cpp new file mode 100644 index 0000000..26bbc02 --- /dev/null +++ b/examples/remoteobjects/websockets/wsserver/main.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Ford Motor Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtRemoteObjects module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QTreeView> +#include <QApplication> +#include <QRemoteObjectNode> +#include <QTimer> +#include <QStandardItemModel> +#include <QStandardItem> +#include <QWebSocket> +#include <QWebSocketServer> + +#ifndef QT_NO_SSL +# include <QFile> +# include <QSslConfiguration> +# include <QSslKey> +#endif + +#include "websocketiodevice.h" + +struct TimerHandler : public QObject +{ + Q_OBJECT +public: + QStandardItemModel *model; +public Q_SLOTS: + void changeData() { + Q_ASSERT(model); + Q_ASSERT(model->rowCount() > 50); + Q_ASSERT(model->columnCount() > 1); + for (int i = 10; i < 50; ++i) + model->setData(model->index(i, 1), QColor(Qt::blue), Qt::BackgroundRole); + } + void insertData() { + Q_ASSERT(model); + Q_ASSERT(model->rowCount() > 50); + Q_ASSERT(model->columnCount() > 1); + model->insertRows(2, 9); + for (int i = 2; i < 11; ++i) { + model->setData(model->index(i, 1), QColor(Qt::green), Qt::BackgroundRole); + model->setData(model->index(i, 1), QLatin1String("InsertedRow"), Qt::DisplayRole); + } + } + void removeData() { + model->removeRows(2, 4); + } + + void changeFlags() { + QStandardItem *item = model->item(0, 0); + item->setEnabled(false); + item = item->child(0, 0); + item->setFlags(item->flags() & Qt::ItemIsSelectable); + } + + void moveData() { + model->moveRows(QModelIndex(), 2, 4, QModelIndex(), 10); + } +}; + +QList<QStandardItem*> addChild(int numChildren, int nestingLevel) +{ + QList<QStandardItem*> result; + if (nestingLevel == 0) + return result; + for (int i = 0; i < numChildren; ++i) { + QStandardItem *child = new QStandardItem(QStringLiteral("Child num %1, nesting Level %2").arg(i+1).arg(nestingLevel)); + if (i == 0) + child->appendRow(addChild(numChildren, nestingLevel -1)); + result.push_back(child); + } + return result; +} + +int main(int argc, char *argv[]) +{ + QLoggingCategory::setFilterRules("qt.remoteobjects.debug=false\n" + "qt.remoteobjects.warning=false"); + QApplication app(argc, argv); + + const int modelSize = 100000; + QStringList list; + QStandardItemModel sourceModel; + QStringList hHeaderList; + hHeaderList << QStringLiteral("First Column with spacing") << QStringLiteral("Second Column with spacing"); + sourceModel.setHorizontalHeaderLabels(hHeaderList); + list.reserve(modelSize); + for (int i = 0; i < modelSize; ++i) { + QStandardItem *firstItem = new QStandardItem(QStringLiteral("FancyTextNumber %1").arg(i)); + if (i == 0) + firstItem->appendRow(addChild(2, 2)); + QStandardItem *secondItem = new QStandardItem(QStringLiteral("FancyRow2TextNumber %1").arg(i)); + if (i % 2 == 0) + firstItem->setBackground(Qt::red); + QList<QStandardItem*> row; + row << firstItem << secondItem; + sourceModel.invisibleRootItem()->appendRow(row); + //sourceModel.appendRow(row); + list << QStringLiteral("FancyTextNumber %1").arg(i); + } + + // Needed by QMLModelViewClient + QHash<int,QByteArray> roleNames = { + {Qt::DisplayRole, "_text"}, + {Qt::BackgroundRole, "_color"} + }; + sourceModel.setItemRoleNames(roleNames); + + QVector<int> roles; + roles << Qt::DisplayRole << Qt::BackgroundRole; + + QWebSocketServer webSockServer{QStringLiteral("WS QtRO"), QWebSocketServer::NonSecureMode}; + webSockServer.listen(QHostAddress::Any, 8088); + + QRemoteObjectHost hostNode; + hostNode.setHostUrl(webSockServer.serverAddress().toString(), QRemoteObjectHost::AllowExternalRegistration); + + hostNode.enableRemoting(&sourceModel, QStringLiteral("RemoteModel"), roles); + + QObject::connect(&webSockServer, &QWebSocketServer::newConnection, &hostNode, [&hostNode, &webSockServer]{ + while (auto conn = webSockServer.nextPendingConnection()) { +#ifndef QT_NO_SSL + // Always use secure connections when available + QSslConfiguration sslConf; + QFile certFile(QStringLiteral(":/sslcert/server.crt")); + if (!certFile.open(QIODevice::ReadOnly)) + qFatal("Can't open client.crt file"); + sslConf.setLocalCertificate(QSslCertificate{certFile.readAll()}); + + QFile keyFile(QStringLiteral(":/sslcert/server.key")); + if (!keyFile.open(QIODevice::ReadOnly)) + qFatal("Can't open client.key file"); + sslConf.setPrivateKey(QSslKey{keyFile.readAll(), QSsl::Rsa}); + + sslConf.setPeerVerifyMode(QSslSocket::VerifyPeer); + conn->setSslConfiguration(sslConf); + QObject::connect(conn, &QWebSocket::sslErrors, conn, &QWebSocket::deleteLater); +#endif + QObject::connect(conn, &QWebSocket::disconnected, conn, &QWebSocket::deleteLater); + QObject::connect(conn, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), conn, &QWebSocket::deleteLater); + auto ioDevice = new WebSocketIoDevice(conn); + QObject::connect(conn, &QWebSocket::destroyed, ioDevice, &WebSocketIoDevice::deleteLater); + hostNode.addHostSideConnection(ioDevice); + } + }); + + QTreeView view; + view.setWindowTitle(QStringLiteral("SourceView")); + view.setModel(&sourceModel); + view.show(); + TimerHandler handler; + handler.model = &sourceModel; + QTimer::singleShot(5000, &handler, SLOT(changeData())); + QTimer::singleShot(10000, &handler, SLOT(insertData())); + QTimer::singleShot(11000, &handler, SLOT(changeFlags())); + QTimer::singleShot(12000, &handler, SLOT(removeData())); + QTimer::singleShot(13000, &handler, SLOT(moveData())); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/remoteobjects/websockets/wsserver/wsserver.pro b/examples/remoteobjects/websockets/wsserver/wsserver.pro new file mode 100644 index 0000000..e892091 --- /dev/null +++ b/examples/remoteobjects/websockets/wsserver/wsserver.pro @@ -0,0 +1,9 @@ +QT += widgets remoteobjects websockets +requires(qtConfig(treeview)) + +SOURCES += main.cpp + +include(../common/common.pri) + +target.path = $$[QT_INSTALL_EXAMPLES]/remoteobjects/websockets/wsserver +INSTALLS += target diff --git a/src/remoteobjects/doc/src/remoteobjects-external-schemas.qdoc b/src/remoteobjects/doc/src/remoteobjects-external-schemas.qdoc index 18a19a8..b18f890 100644 --- a/src/remoteobjects/doc/src/remoteobjects-external-schemas.qdoc +++ b/src/remoteobjects/doc/src/remoteobjects-external-schemas.qdoc @@ -46,11 +46,11 @@ use an SSL connection, which would require configuration of certificates, etc. \code // Create the server and listen outside of QtRO QTcpServer tcpServer; - tcpServer.listen(QHostAddress(127.0.0.1), 65213); + tcpServer.listen(QHostAddress(QStringLiteral("127.0.0.1")), 65213); // Create the host node. We don't need a hostUrl unless we want to take // advantage of external schemas (see next example). - QRemoteObjectHost srcNode(); + QRemoteObjectHost srcNode; // Make sure any connections are handed to QtRO QObject::connect(&tcpServer, &QTcpServer::newConnection, &srcNode, @@ -61,14 +61,13 @@ use an SSL connection, which would require configuration of certificates, etc. The Replica side code needs to manually connect to the Host \code - QRemoteObjectNode repNode(); + QRemoteObjectNode repNode; QTcpSocket *socket = new QTcpSocket(&repNode); - connect(socket, &QTcpSocket::connected, &repNode, + QObject::connect(socket, &QTcpSocket::connected, &repNode, [socket, &repNode]() { repNode.addClientSideConnection(socket); }); - socket->connectToHost(QHostAddress(127.0.0.1), 65213); - }; + socket->connectToHost(QHostAddress(QStringLiteral("127.0.0.1")), 65213); \endcode \section1 External Schemas diff --git a/src/remoteobjects/qconnection_qnx_server.cpp b/src/remoteobjects/qconnection_qnx_server.cpp index 361a554..f1606e5 100644 --- a/src/remoteobjects/qconnection_qnx_server.cpp +++ b/src/remoteobjects/qconnection_qnx_server.cpp @@ -175,8 +175,8 @@ void QQnxNativeServerPrivate::thread_func() * our client, and if so, clean up our saved state */ const int scoid = recv_buf.pulse.scoid; - QSet<int> coids = connections.take(scoid); - Q_FOREACH (int coid, coids) + const QSet<int> coids = connections.take(scoid); + for (int coid : coids) { const uint64_t uid = static_cast<uint64_t>(scoid) << 32 | static_cast<uint32_t>(coid); QSharedPointer<QIOQnxSource> io; @@ -415,12 +415,12 @@ void QQnxNativeServerPrivate::cleanupIOSource(QIOQnxSource *conn) { QSharedPointer<QIOQnxSource> io; mutex.lock(); - QHashIterator<uint64_t, QSharedPointer<QIOQnxSource>> i(sources); - while (i.hasNext()) { - i.next(); - if (i.value().data() == conn) - io = sources.take(i.key()); - break; + for (auto i = sources.begin(), end = sources.end(); i != end; ++i) { + if (i.value().data() == conn) { + io = std::move(i.value()); + sources.erase(i); + break; + } } mutex.unlock(); if (!io.isNull()) { diff --git a/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp b/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp index 861a9aa..83bf02e 100644 --- a/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp +++ b/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp @@ -45,7 +45,8 @@ inline QVariantList collectData(const QModelIndex &index, const QAbstractItemModel *model, const QVector<int> &roles) { QVariantList result; - Q_FOREACH (int role, roles) + result.reserve(roles.size()); + for (int role : roles) result << model->data(index, role); return result; } @@ -56,8 +57,8 @@ inline QVector<int> filterRoles(const QVector<int> &roles, const QVector<int> &a return availableRoles; QVector<int> neededRoles; - foreach (int inRole, roles) { - foreach (int availableRole, availableRoles) + for (int inRole : roles) { + for (int availableRole : availableRoles) if (inRole == availableRole) { neededRoles << inRole; continue; diff --git a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp index 6e643e2..0b84975 100644 --- a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp +++ b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp @@ -151,9 +151,8 @@ inline void removeIndexFromRow(const QModelIndex &index, const QVector<int> &rol if (roles.isEmpty()) { entry.data.clear(); } else { - Q_FOREACH (int role, roles) { + for (int role : roles) entry.data.remove(role); - } } } } @@ -403,7 +402,7 @@ void QAbstractItemModelReplicaImplementation::handleSizeDone(QRemoteObjectPendin if (size.width() != parentItem->columnCount) { const int columnCount = std::max(0, parentItem->columnCount); - Q_ASSERT_X(size.width() >= parentItem->columnCount, __FUNCTION__, qPrintable(QStringLiteral("The column count should only shrink in columnsRemoved!!"))); + Q_ASSERT_X(size.width() >= parentItem->columnCount, __FUNCTION__, "The column count should only shrink in columnsRemoved!!"); parentItem->columnCount = size.width(); if (size.width() > columnCount) { Q_ASSERT(size.width() > 0); @@ -414,7 +413,7 @@ void QAbstractItemModelReplicaImplementation::handleSizeDone(QRemoteObjectPendin } } - Q_ASSERT_X(size.height() >= parentItem->rowCount, __FUNCTION__, qPrintable(QStringLiteral("The new size and the current size should match!!"))); + Q_ASSERT_X(size.height() >= parentItem->rowCount, __FUNCTION__, "The new size and the current size should match!!"); if (!parentItem->rowCount) { if (size.height() > 0) { q->beginInsertRows(parent, 0, size.height() - 1); @@ -571,7 +570,7 @@ void QAbstractItemModelReplicaImplementation::fetchPendingData() std::vector<RequestedData> finalRequests; RequestedData curData; - Q_FOREACH (const RequestedData &data, m_requestedData) { + for (const RequestedData &data : qExchange(m_requestedData, {})) { qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "REQUESTED start=" << data.start << "end=" << data.end << "roles=" << data.roles; Q_ASSERT(!data.start.isEmpty()); @@ -601,7 +600,7 @@ void QAbstractItemModelReplicaImplementation::fetchPendingData() const ModelIndex resEnd(std::max(curIndEnd.row, dataIndEnd.row), std::max(curIndEnd.column, dataIndEnd.column)); QVector<int> roles = curData.roles; if (!curData.roles.isEmpty()) { - Q_FOREACH (int role, data.roles) { + for (int role : data.roles) { if (!curData.roles.contains(role)) roles.append(role); } @@ -645,7 +644,6 @@ void QAbstractItemModelReplicaImplementation::fetchPendingData() m_pendingRequests.push_back(watcher); connect(watcher, &RowWatcher::finished, this, &QAbstractItemModelReplicaImplementation::requestedData); } - m_requestedData.clear(); } void QAbstractItemModelReplicaImplementation::onModelReset() @@ -673,7 +671,7 @@ void QAbstractItemModelReplicaImplementation::fetchPendingHeaderData() QVector<int> roles; QVector<int> sections; QVector<Qt::Orientation> orientations; - Q_FOREACH (const RequestedHeaderData &data, m_requestedHeaderData) { + for (const RequestedHeaderData &data : qAsConst(m_requestedHeaderData)) { roles.push_back(data.role); sections.push_back(data.section); orientations.push_back(data.orientation); diff --git a/src/remoteobjects/qremoteobjectnode.cpp b/src/remoteobjects/qremoteobjectnode.cpp index 482de0f..8cbaa71 100644 --- a/src/remoteobjects/qremoteobjectnode.cpp +++ b/src/remoteobjects/qremoteobjectnode.cpp @@ -233,11 +233,15 @@ QRemoteObjectSourceLocations QRemoteObjectRegistryHostPrivate::remoteObjectAddre void QRemoteObjectNode::timerEvent(QTimerEvent*) { Q_D(QRemoteObjectNode); - Q_FOREACH (ClientIoDevice *conn, d->pendingReconnect) { - if (conn->isOpen()) - d->pendingReconnect.remove(conn); - else + + for (auto it = d->pendingReconnect.begin(), end = d->pendingReconnect.end(); it != end; /*erasing*/) { + const auto &conn = *it; + if (conn->isOpen()) { + it = d->pendingReconnect.erase(it); + } else { conn->connectToServer(); + ++it; + } } if (d->pendingReconnect.isEmpty()) @@ -976,7 +980,7 @@ void QRemoteObjectMetaObjectManager::addFromMetaObject(const QMetaObject *metaOb QString className = QLatin1String(metaObject->className()); if (!className.endsWith(QLatin1String("Replica"))) return; - if (className == QStringLiteral("QRemoteObjectDynamicReplica") || staticTypes.contains(className)) + if (className == QLatin1String("QRemoteObjectDynamicReplica") || staticTypes.contains(className)) return; className.chop(7); //Remove 'Replica' from name staticTypes.insert(className, metaObject); @@ -1110,9 +1114,8 @@ void QRemoteObjectNodePrivate::onRegistryInitialized() { qROPrivDebug() << "Registry Initialized" << remoteObjectAddresses(); - QHashIterator<QString, QRemoteObjectSourceLocationInfo> i(remoteObjectAddresses()); - while (i.hasNext()) { - i.next(); + const auto remotes = remoteObjectAddresses(); + for (auto i = remotes.cbegin(), end = remotes.cend(); i != end; ++i) { if (replicas.contains(i.key())) //We have a replica waiting on this remoteObject { QSharedPointer<QReplicaImplementationInterface> rep = replicas.value(i.key()).toStrongRef(); @@ -1130,7 +1133,8 @@ void QRemoteObjectNodePrivate::onShouldReconnect(ClientIoDevice *ioDevice) { Q_Q(QRemoteObjectNode); - Q_FOREACH (const QString &remoteObject, ioDevice->remoteObjects()) { + const auto remoteObjects = ioDevice->remoteObjects(); + for (const QString &remoteObject : remoteObjects) { connectedSources.remove(remoteObject); ioDevice->removeSource(remoteObject); if (replicas.contains(remoteObject)) { //We have a replica waiting on this remoteObject @@ -1265,17 +1269,17 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj) // We need to make sure all of the source objects are in connectedSources before we add connections, // otherwise nested QObjects could fail (we want to acquire children before parents, and the object // list is unordered) - Q_FOREACH (const auto &remoteObject, rxObjects) { + for (const auto &remoteObject : qAsConst(rxObjects)) { qROPrivDebug() << " connectedSources.contains(" << remoteObject << ")" << connectedSources.contains(remoteObject.name) << replicas.contains(remoteObject.name); if (!connectedSources.contains(remoteObject.name)) { connectedSources[remoteObject.name] = SourceInfo{connection, remoteObject.typeName, remoteObject.signature}; connection->addSource(remoteObject.name); // Make sure we handle Registry first if it is available - if (remoteObject.name == QStringLiteral("Registry") && replicas.contains(remoteObject.name)) + if (remoteObject.name == QLatin1String("Registry") && replicas.contains(remoteObject.name)) handleReplicaConnection(remoteObject.name); } } - Q_FOREACH (const auto &remoteObject, rxObjects) { + for (const auto &remoteObject : qAsConst(rxObjects)) { if (replicas.contains(remoteObject.name)) //We have a replica waiting on this remoteObject handleReplicaConnection(remoteObject.name); } @@ -2226,7 +2230,7 @@ bool QRemoteObjectHostBase::enableRemoting(QAbstractItemModel *model, const QStr QAbstractItemAdapterSourceAPI<QAbstractItemModel, QAbstractItemModelSourceAdapter> *api = new QAbstractItemAdapterSourceAPI<QAbstractItemModel, QAbstractItemModelSourceAdapter>(name); if (!this->objectName().isEmpty()) - adapter->setObjectName(this->objectName().append(QStringLiteral("Adapter"))); + adapter->setObjectName(this->objectName().append(QLatin1String("Adapter"))); return enableRemoting(model, api, adapter); } diff --git a/src/remoteobjects/qremoteobjectpacket.cpp b/src/remoteobjects/qremoteobjectpacket.cpp index 4b8f77c..d517794 100644 --- a/src/remoteobjects/qremoteobjectpacket.cpp +++ b/src/remoteobjects/qremoteobjectpacket.cpp @@ -588,7 +588,7 @@ void serializeInvokePacket(DataStreamPacket &ds, const QString &name, int call, ds << index; ds << (quint32)args.size(); - foreach (const auto &arg, args) + for (const auto &arg : args) ds << encodeVariant(arg); ds << serialId; diff --git a/src/remoteobjects/qremoteobjectpendingcall_p.h b/src/remoteobjects/qremoteobjectpendingcall_p.h index 97b37fd..59eb77c 100644 --- a/src/remoteobjects/qremoteobjectpendingcall_p.h +++ b/src/remoteobjects/qremoteobjectpendingcall_p.h @@ -76,7 +76,7 @@ public: mutable QMutex mutex; - QScopedPointer<QRemoteObjectPendingCallWatcherHelper> watcherHelper; + mutable QScopedPointer<QRemoteObjectPendingCallWatcherHelper> watcherHelper; }; class QRemoteObjectPendingCallWatcherHelper: public QObject diff --git a/src/remoteobjects/qremoteobjectregistry.cpp b/src/remoteobjects/qremoteobjectregistry.cpp index 71856a2..5d72dcc 100644 --- a/src/remoteobjects/qremoteobjectregistry.cpp +++ b/src/remoteobjects/qremoteobjectregistry.cpp @@ -204,23 +204,23 @@ void QRemoteObjectRegistry::pushToRegistryIfNeeded() if (state() != QRemoteObjectReplica::State::Valid) return; - const QSet<QString> myLocs = QSet<QString>::fromList(d->hostedSources.keys()); - if (myLocs.empty()) + if (d->hostedSources.isEmpty()) return; - const QSet<QString> registryLocs = QSet<QString>::fromList(sourceLocations().keys()); - foreach (const QString &loc, myLocs & registryLocs) { - qCWarning(QT_REMOTEOBJECT) << "Node warning: Ignoring Source" << loc << "as another source (" - << sourceLocations().value(loc) << ") has already registered that name."; - d->hostedSources.remove(loc); - return; - } - //Sources that need to be pushed to the registry... - foreach (const QString &loc, myLocs - registryLocs) { - static int index = QRemoteObjectRegistry::staticMetaObject.indexOfMethod("addSource(QRemoteObjectSourceLocation)"); - QVariantList args; - args << QVariant::fromValue(QRemoteObjectSourceLocation(loc, d->hostedSources[loc])); - send(QMetaObject::InvokeMetaMethod, index, args); + const auto &sourceLocs = sourceLocations(); + for (auto it = d->hostedSources.begin(); it != d->hostedSources.end(); ) { + const QString &loc = it.key(); + const auto sourceLocsIt = sourceLocs.constFind(loc); + if (sourceLocsIt != sourceLocs.cend()) { + qCWarning(QT_REMOTEOBJECT) << "Node warning: Ignoring Source" << loc << "as another source (" + << sourceLocsIt.value() << ") has already registered that name."; + it = d->hostedSources.erase(it); + } else { + static const int index = QRemoteObjectRegistry::staticMetaObject.indexOfMethod("addSource(QRemoteObjectSourceLocation)"); + QVariantList args{QVariant::fromValue(QRemoteObjectSourceLocation(loc, it.value()))}; + send(QMetaObject::InvokeMetaMethod, index, args); + ++it; + } } } diff --git a/src/remoteobjects/qremoteobjectregistrysource.cpp b/src/remoteobjects/qremoteobjectregistrysource.cpp index 1e1a2f4..ddd7026 100644 --- a/src/remoteobjects/qremoteobjectregistrysource.cpp +++ b/src/remoteobjects/qremoteobjectregistrysource.cpp @@ -61,14 +61,12 @@ QRemoteObjectSourceLocations QRegistrySource::sourceLocations() const void QRegistrySource::removeServer(const QUrl &url) { - QVector<QString> results; - typedef QRemoteObjectSourceLocations::const_iterator CustomIterator; - const CustomIterator end = m_sourceLocations.constEnd(); - for (CustomIterator it = m_sourceLocations.constBegin(); it != end; ++it) + for (auto it = m_sourceLocations.begin(), end = m_sourceLocations.end(); it != end; /* erasing */) { if (it.value().hostUrl == url) - results.push_back(it.key()); - Q_FOREACH (const QString &res, results) - m_sourceLocations.remove(res); + it = m_sourceLocations.erase(it); + else + ++it; + } } void QRegistrySource::addSource(const QRemoteObjectSourceLocation &entry) diff --git a/src/remoteobjects/qremoteobjectreplica.cpp b/src/remoteobjects/qremoteobjectreplica.cpp index 6536dc8..3c2c84b 100644 --- a/src/remoteobjects/qremoteobjectreplica.cpp +++ b/src/remoteobjects/qremoteobjectreplica.cpp @@ -158,15 +158,15 @@ bool QRemoteObjectReplicaImplementation::needsDynamicInitialization() const void QRemoteObjectReplicaImplementation::setState(QRemoteObjectReplica::State state) { - if (m_state != QRemoteObjectReplica::Suspect && m_state >= state) + if (m_state.loadAcquire() != QRemoteObjectReplica::Suspect && m_state.loadAcquire() >= state) return; - int oldState = m_state; - m_state = state; + int oldState = m_state.loadAcquire(); + m_state.storeRelease(state); // We should emit initialized before emitting any changed signals in case connections are made in a // Slot responding to initialized/validChanged. - if (m_state == QRemoteObjectReplica::Valid) { + if (m_state.loadAcquire() == QRemoteObjectReplica::Valid) { // we're initialized now, emit signal emitInitialized(); } @@ -213,7 +213,7 @@ void QConnectedReplicaImplementation::initialize(QVariantList &values) qCDebug(QT_REMOTEOBJECT) << "SETPROPERTY" << i << m_metaObject->property(i+offset).name() << values.at(i).typeName() << values.at(i).toString(); } - Q_ASSERT(m_state < QRemoteObjectReplica::Valid || m_state == QRemoteObjectReplica::Suspect); + Q_ASSERT(m_state.loadAcquire() < QRemoteObjectReplica::Valid || m_state.loadAcquire() == QRemoteObjectReplica::Suspect); setState(QRemoteObjectReplica::Valid); void *args[] = {nullptr, nullptr}; @@ -292,11 +292,10 @@ void QRemoteObjectReplicaImplementation::setDynamicProperties(const QVariantList void QConnectedReplicaImplementation::setDynamicProperties(const QVariantList &values) { QRemoteObjectReplicaImplementation::setDynamicProperties(values); - foreach (QRemoteObjectReplica *obj, m_parentsNeedingConnect) + for (QRemoteObjectReplica *obj : qExchange(m_parentsNeedingConnect, {})) configurePrivate(obj); - m_parentsNeedingConnect.clear(); - Q_ASSERT(m_state < QRemoteObjectReplica::Valid); + Q_ASSERT(m_state.loadAcquire() < QRemoteObjectReplica::Valid); setState(QRemoteObjectReplica::Valid); void *args[] = {nullptr, nullptr}; @@ -314,7 +313,7 @@ void QConnectedReplicaImplementation::setDynamicProperties(const QVariantList &v bool QConnectedReplicaImplementation::isInitialized() const { - return m_state > QRemoteObjectReplica::Default && m_state != QRemoteObjectReplica::SignatureMismatch; + return m_state.loadAcquire() > QRemoteObjectReplica::Default && m_state.loadAcquire() != QRemoteObjectReplica::SignatureMismatch; } bool QConnectedReplicaImplementation::waitForSource(int timeout) diff --git a/src/remoteobjects/qremoteobjectsource.cpp b/src/remoteobjects/qremoteobjectsource.cpp index 3ddec27..d497edd 100644 --- a/src/remoteobjects/qremoteobjectsource.cpp +++ b/src/remoteobjects/qremoteobjectsource.cpp @@ -252,7 +252,10 @@ QRemoteObjectRootSource::~QRemoteObjectRootSource() delete it; } d->m_sourceIo->unregisterSource(this); - Q_FOREACH (IoDeviceBase *io, d->m_listeners) { + // removeListener tries to modify d->m_listeners, this is O(N²), + // so clear d->m_listeners prior to calling unregister (consume loop). + // We can do this, because we don't care about the return value of removeListener() here. + for (IoDeviceBase *io : qExchange(d->m_listeners, {})) { removeListener(io, true); } delete d; @@ -372,7 +375,7 @@ void QRemoteObjectSourceBase::handleMetaCall(int index, QMetaObject::Call call, serializeInvokePacket(d->m_packet, name(), call, index, *marshalArgs(index, a), -1, propertyIndex); d->m_packet.baseAddress = 0; - Q_FOREACH (IoDeviceBase *io, d->m_listeners) + for (IoDeviceBase *io : qAsConst(d->m_listeners)) io->write(d->m_packet.array, d->m_packet.size); } @@ -451,7 +454,7 @@ DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, con if (typeName.isNull()) { typeName = QString::fromLatin1(propertyMeta->className()); // TODO better way to ensure we have consistent typenames between source/replicas? - if (typeName.endsWith(QStringLiteral("Source"))) + if (typeName.endsWith(QLatin1String("Source"))) typeName.chop(6); } diff --git a/src/remoteobjects/qremoteobjectsourceio.cpp b/src/remoteobjects/qremoteobjectsourceio.cpp index 189e5f4..a6cdd11 100644 --- a/src/remoteobjects/qremoteobjectsourceio.cpp +++ b/src/remoteobjects/qremoteobjectsourceio.cpp @@ -161,7 +161,7 @@ void QRemoteObjectSourceIo::onServerDisconnect(QObject *conn) qRODebug(this) << "OnServerDisconnect"; - Q_FOREACH (QRemoteObjectRootSource *root, m_sourceRoots) + for (QRemoteObjectRootSource *root : qAsConst(m_sourceRoots)) root->removeListener(connection); const QUrl location = m_registryMapping.value(connection); @@ -220,7 +220,7 @@ void QRemoteObjectSourceIo::onServerRead(QObject *conn) { int call, index, serialId, propertyId; deserializeInvokePacket(connection->stream(), call, index, m_rxArgs, serialId, propertyId); - if (m_rxName == QStringLiteral("Registry") && !m_registryMapping.contains(connection)) { + if (m_rxName == QLatin1String("Registry") && !m_registryMapping.contains(connection)) { const QRemoteObjectSourceLocation loc = m_rxArgs.first().value<QRemoteObjectSourceLocation>(); m_registryMapping[connection] = loc.second.hostUrl; } @@ -313,7 +313,8 @@ void QRemoteObjectSourceIo::newConnection(IoDeviceBase *conn) conn->write(m_packet.array, m_packet.size); QRemoteObjectPackets::ObjectInfoList infos; - foreach (auto remoteObject, m_sourceRoots) { + infos.reserve(m_sourceRoots.size()); + for (auto remoteObject : qAsConst(m_sourceRoots)) { infos << QRemoteObjectPackets::ObjectInfo{remoteObject->m_api->name(), remoteObject->m_api->typeName(), remoteObject->m_api->objectSignature()}; } serializeObjectListPacket(m_packet, infos); diff --git a/src/remoteobjects/qtremoteobjectglobal.h b/src/remoteobjects/qtremoteobjectglobal.h index 998139b..f4a0b35 100644 --- a/src/remoteobjects/qtremoteobjectglobal.h +++ b/src/remoteobjects/qtremoteobjectglobal.h @@ -49,17 +49,10 @@ QT_BEGIN_NAMESPACE struct QRemoteObjectSourceLocationInfo { - QRemoteObjectSourceLocationInfo() {} + QRemoteObjectSourceLocationInfo() = default; QRemoteObjectSourceLocationInfo(const QString &typeName_, const QUrl &hostUrl_) : typeName(typeName_), hostUrl(hostUrl_) {} - QRemoteObjectSourceLocationInfo &operator=(const QRemoteObjectSourceLocationInfo &other) - { - typeName = other.typeName; - hostUrl = other.hostUrl; - return *this; - } - inline bool operator==(const QRemoteObjectSourceLocationInfo &other) const Q_DECL_NOTHROW { return other.typeName == typeName && other.hostUrl == hostUrl; diff --git a/src/repparser/parser.g b/src/repparser/parser.g index 34c8ddf..2930de3 100644 --- a/src/repparser/parser.g +++ b/src/repparser/parser.g @@ -352,13 +352,13 @@ ASTFunction::ASTFunction(const QString &name, const QString &returnType) QString ASTFunction::paramsAsString(ParamsAsStringFormat format) const { QString str; - foreach (const ASTDeclaration ¶m, params) { + for (const ASTDeclaration ¶m : params) { QString paramStr = param.asString(format != Normalized); if (format == Normalized) { paramStr = QString::fromLatin1(::normalizeType(paramStr.toLatin1().constData())); str += paramStr + QLatin1Char(','); } else { - str += paramStr + QStringLiteral(", "); + str += paramStr + QLatin1String(", "); } } @@ -370,9 +370,9 @@ QString ASTFunction::paramsAsString(ParamsAsStringFormat format) const QStringList ASTFunction::paramNames() const { QStringList names; - foreach (const ASTDeclaration ¶m, params) { + names.reserve(params.size()); + for (const ASTDeclaration ¶m : params) names << param.name; - } return names; } @@ -426,23 +426,23 @@ bool RepParser::parseModifierFlag(const QString &flag, ASTProperty::Modifier &mo modifier = ASTProperty::Constant; return true; } else { - setErrorString(QStringLiteral("Invalid property declaration: combination not allowed (%1)").arg(flag)); + setErrorString(QLatin1String("Invalid property declaration: combination not allowed (%1)").arg(flag)); return false; } } const QString &f = flags.at(0); - if (f == QStringLiteral("READONLY")) + if (f == QLatin1String("READONLY")) modifier = ASTProperty::ReadOnly; - else if (f == QStringLiteral("CONSTANT")) + else if (f == QLatin1String("CONSTANT")) modifier = ASTProperty::Constant; - else if (f == QStringLiteral("READPUSH")) + else if (f == QLatin1String("READPUSH")) modifier = ASTProperty::ReadPush; - else if (f == QStringLiteral("READWRITE")) + else if (f == QLatin1String("READWRITE")) modifier = ASTProperty::ReadWrite; - else if (f == QStringLiteral("SOURCEONLYSETTER")) + else if (f == QLatin1String("SOURCEONLYSETTER")) modifier = ASTProperty::SourceOnlySetter; else { - setErrorString(QStringLiteral("Invalid property declaration: flag %1 is unknown").arg(flag)); + setErrorString(QLatin1String("Invalid property declaration: flag %1 is unknown").arg(flag)); return false; } @@ -500,7 +500,7 @@ bool RepParser::parseProperty(ASTClass &astClass, const QString &propertyDeclara } if (nameIndex == -1) { - setErrorString(QStringLiteral("PROP: Invalid property declaration: %1").arg(propertyDeclaration)); + setErrorString(QLatin1String("PROP: Invalid property declaration: %1").arg(propertyDeclaration)); return false; } @@ -628,14 +628,13 @@ void RepParser::TypeParser::generateFunctionParameter(QString variableName, cons void RepParser::TypeParser::appendParams(ASTFunction &slot) { - Q_FOREACH (const ASTDeclaration &arg, arguments) { + for (const ASTDeclaration &arg : qAsConst(arguments)) slot.params << arg; - } } void RepParser::TypeParser::appendPods(POD &pods) { - Q_FOREACH (const ASTDeclaration &arg, arguments) { + for (const ASTDeclaration &arg : qAsConst(arguments)) { PODAttribute attr; attr.type = arg.type; attr.name = arg.name; @@ -773,7 +772,7 @@ EnumParam: enum_param; value = value.trimmed(); if (value.isEmpty()) param.value = ++m_astEnumValue; - else if (value.startsWith(QStringLiteral("0x"), Qt::CaseInsensitive)) + else if (value.startsWith(QLatin1String("0x"), Qt::CaseInsensitive)) param.value = m_astEnumValue = value.toInt(0,16); else param.value = m_astEnumValue = value.toInt(); @@ -823,13 +822,13 @@ Slot: slot; const QString argString = captured().value(QLatin1String("args")).trimmed(); // compat code with old SLOT declaration: "SLOT(func(...))" - const bool hasWhitespace = returnTypeAndName.indexOf(QStringLiteral(" ")) != -1; + const bool hasWhitespace = returnTypeAndName.indexOf(u' ') != -1; if (!hasWhitespace) { qWarning() << "[repc] - Adding 'void' for unspecified return type on" << qPrintable(returnTypeAndName); - returnTypeAndName.prepend(QStringLiteral("void ")); + returnTypeAndName.prepend(QLatin1String("void ")); } - const int startOfFunctionName = returnTypeAndName.lastIndexOf(QStringLiteral(" ")) + 1; + const int startOfFunctionName = returnTypeAndName.lastIndexOf(u' ') + 1; ASTFunction slot; slot.returnType = returnTypeAndName.mid(0, startOfFunctionName-1); diff --git a/src/repparser/qregexparser.h b/src/repparser/qregexparser.h index c09bb91..cfaf59e 100644 --- a/src/repparser/qregexparser.h +++ b/src/repparser/qregexparser.h @@ -139,7 +139,7 @@ private: inline QString escapeString(QString s) { - return s.replace(QLatin1Char('\n'), QStringLiteral("\\n")).replace(QLatin1Char('\t'), QStringLiteral("\\t")); + return s.replace(QLatin1Char('\n'), QLatin1String("\\n")).replace(QLatin1Char('\t'), QLatin1String("\\t")); } QSharedDataPointer<Data> d; @@ -283,7 +283,8 @@ QRegexParser<_Parser, _Table>::QRegexParser(int maxMatchLen) : d(new Data()), m_ #ifndef QT_BOOTSTRAPPED pat.optimize(); int counter = 0; - Q_FOREACH (const QString &name, pat.namedCaptureGroups()) { + const auto namedCaptureGroups = pat.namedCaptureGroups(); + for (const QString &name : namedCaptureGroups) { if (!name.isEmpty()) names.insert(counter, name); ++counter; @@ -399,7 +400,7 @@ int QRegexParser<_Parser, _Table>::nextToken() # endif int i = 0; regexCandidates[nextChar] = QList<int>(); - Q_FOREACH (const QRegularExpression &re, m_regexes) + for (const QRegularExpression &re : qAsConst(m_regexes)) { QRegularExpressionMatch match = re.match(tmp, 0, QRegularExpression::PartialPreferFirstMatch, QRegularExpression::DontCheckSubjectStringMatchOption); //qDebug() << nextChar << tmp << match.hasMatch() << match.hasPartialMatch() << re.pattern(); @@ -408,7 +409,8 @@ int QRegexParser<_Parser, _Table>::nextToken() i++; } } - Q_FOREACH (int i, regexCandidates.value(nextChar)) + const auto indices = regexCandidates.value(nextChar); + for (int i : indices) { //Seems like I should be able to run the regex on the entire string, but performance is horrible //unless I use a substring. @@ -432,7 +434,7 @@ int QRegexParser<_Parser, _Table>::nextToken() #else { int i = 0; - Q_FOREACH (const QRegExp &r, m_regexes) + for (const QRegExp &r : qAsConst(m_regexes)) { if (r.indexIn(m_buffer, m_loc, QRegExp::CaretAtOffset) == m_loc) { if (m_debug) @@ -447,14 +449,13 @@ int QRegexParser<_Parser, _Table>::nextToken() } #endif if (best < 0) { - setErrorString(QStringLiteral("Error generating tokens from file, next characters >%1<").arg(m_buffer.mid(m_loc, 15))); + setErrorString(QLatin1String("Error generating tokens from file, next characters >%1<").arg(m_buffer.midRef(m_loc, 15))); return -1; } else { - QMapIterator<int, QString> iter(m_names.at(best)); - if (iter.hasNext()) + const QMap<int, QString> &map = m_names.at(best); + if (!map.isEmpty()) m_captured.clear(); - while (iter.hasNext()) { - iter.next(); + for (auto iter = map.cbegin(), end = map.cend(); iter != end; ++iter) { #ifdef QT_BOOTSTRAPPED m_captured.insert(iter.value(), m_regexes.at(best).cap(iter.key())); #else @@ -463,7 +464,7 @@ int QRegexParser<_Parser, _Table>::nextToken() } if (m_debug) { qDebug() << "Match candidates:"; - Q_FOREACH (const MatchCandidate &m, candidates) { + for (const MatchCandidate &m : qAsConst(candidates)) { QLatin1String result = m.index == best ? QLatin1String(" * ") : QLatin1String(" "); qDebug() << qPrintable(result) << qPrintable(m.name) << qPrintable(escapeString(m.matchText)); } diff --git a/tests/auto/benchmarks/tst_benchmarkstest.cpp b/tests/auto/benchmarks/tst_benchmarkstest.cpp index 9c6a1dd..851f392 100644 --- a/tests/auto/benchmarks/tst_benchmarkstest.cpp +++ b/tests/auto/benchmarks/tst_benchmarkstest.cpp @@ -262,7 +262,7 @@ void BenchmarksTest::benchModelLinearAccess() QThread::usleep(10); continue; } - foreach (int role, roles) { + for (int role : roles) { QVariant data = model->data(model->index(row, 0), role); switch (role) { case Qt::DisplayRole: @@ -334,7 +334,7 @@ void BenchmarksTest::benchModelRandomAccess() QThread::yieldCurrentThread(); // instead to wait continue; } - foreach (int role, roles) { + for (int role : roles) { QVariant data = model->data(model->index(row, 0), role); switch (role) { case Qt::DisplayRole: diff --git a/tests/auto/integration_external/client/main.cpp b/tests/auto/integration_external/client/main.cpp index bc53333..1a918c8 100644 --- a/tests/auto/integration_external/client/main.cpp +++ b/tests/auto/integration_external/client/main.cpp @@ -31,6 +31,7 @@ #include <QCoreApplication> #include <QtRemoteObjects/qremoteobjectnode.h> #include <QtTest/QtTest> +#include <QTcpSocket> const QUrl registryUrl = QUrl(QStringLiteral("tcp://127.0.0.1:65212")); @@ -48,7 +49,7 @@ private Q_SLOTS: [socket, this]() { this->m_repNode.addClientSideConnection(socket); }); - connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QSslSocket::error), + connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), [socket](QAbstractSocket::SocketError error) { qDebug() << "SocketError" << error; delete socket; diff --git a/tests/auto/integration_external/server/main.cpp b/tests/auto/integration_external/server/main.cpp index e97408b..23d708f 100644 --- a/tests/auto/integration_external/server/main.cpp +++ b/tests/auto/integration_external/server/main.cpp @@ -31,6 +31,7 @@ #include <QCoreApplication> #include <QTcpServer> #include <QtTest/QtTest> +#include <QTcpSocket> const QUrl registryUrl = QUrl(QStringLiteral("tcp://127.0.0.1:65212")); const QUrl extUrl = QUrl(QStringLiteral("exttcp://127.0.0.1:65213")); diff --git a/tests/auto/modelview/tst_modelview.cpp b/tests/auto/modelview/tst_modelview.cpp index 52c2419..da42763 100644 --- a/tests/auto/modelview/tst_modelview.cpp +++ b/tests/auto/modelview/tst_modelview.cpp @@ -54,7 +54,7 @@ bool waitForSignal(QVector<Storage> *storage, QSignalSpy *spy) ++runs; if (spy->wait() && !spy->isEmpty()){ - foreach (const Storage &row, *storage) { + for (const Storage &row : qAsConst(*storage)) { for (int i = 0; i < spy->size(); ++i) { const QList<QVariant> &signal = spy->at(i); if (row.match(signal)) { @@ -63,7 +63,7 @@ bool waitForSignal(QVector<Storage> *storage, QSignalSpy *spy) } } } - foreach (const Storage &row, rowsToRemove) + for (const Storage &row : qAsConst(rowsToRemove)) storage->removeAll(row); if (storage->isEmpty()) break; @@ -141,12 +141,12 @@ inline void dumpModel(const QAbstractItemModel *model, const QModelIndex &parent s.fill(QChar(' '), level*2); cout << qPrintable(s); cout << QString(QLatin1String("%1:%2")).arg(i).arg(j); - foreach (int role, roles.keys()) { - const QVariant v = model->data(index, role); + for (auto it = roles.cbegin(), end = roles.cend(); it != end; ++it) { + const QVariant v = model->data(index, it.key()); if (!v.isValid()) continue; QString t; QDebug(&t) << v; - cout << " " << QString::fromUtf8(roles[role]) << "=" << t.trimmed(); + cout << " " << QString::fromUtf8(it.value()) << "=" << t.trimmed(); } { @@ -174,7 +174,8 @@ void compareData(const QAbstractItemModel *sourceModel, const QAbstractItemModel for (int i = 0; i < sourceModel->rowCount(); ++i) { for (int j = 0; j < sourceModel->columnCount(); ++j) { - foreach (int role, replica->availableRoles()) { + const auto roles = replica->availableRoles(); + for (int role : roles) { QCOMPARE(replica->index(i, j).data(role), sourceModel->index(i, j).data(role)); } } @@ -186,7 +187,7 @@ void compareIndex(const QModelIndex &sourceIndex, const QModelIndex &replicaInde { QVERIFY(sourceIndex.isValid()); QVERIFY(replicaIndex.isValid()); - foreach (int role, roles) { + for (int role : roles) { QCOMPARE(replicaIndex.data(role), sourceIndex.data(role)); } const QAbstractItemModel *sourceModel = sourceIndex.model(); @@ -203,7 +204,10 @@ void compareIndex(const QModelIndex &sourceIndex, const QModelIndex &replicaInde QCOMPARE(replicaColumnCount, sourceColumnCount); for (int i = 0; i < sourceRowCount; ++i) { for (int j = 0; j < sourceColumnCount; ++j) { - compareIndex(sourceIndex.child(i, j), replicaIndex.child(i, j), roles); + auto sourceChild = sourceModel->index(i, j, sourceIndex); + auto replicaChild = replicaModel->index(i, j, replicaIndex); + compareIndex(sourceChild, replicaChild, roles); + } } } @@ -334,7 +338,7 @@ public: void addData(const QModelIndex &index, const QVector<int> &roles) { - foreach (int role, roles) { + for (int role : roles) { const bool cached = m_replica->hasData(index, role); if (cached) continue; @@ -376,7 +380,7 @@ public: pending.detach(); QHash<QPersistentModelIndex, QVector<int> >::ConstIterator it(pending.constBegin()), end(pending.constEnd()); for (; it != end; ++it) { - foreach (int role, it.value()) { + for (int role : it.value()) { QVariant v = m_replica->data(it.key(), role); Q_UNUSED(v); } @@ -455,7 +459,7 @@ private: if (roles.isEmpty()) { itroles.clear(); } else { - foreach (int r, roles) { + for (int r : roles) { itroles.removeAll(r); } } @@ -788,7 +792,7 @@ void TestModelView::testDataInsertion() ++runs; if (rowSpy.wait() && !rowSpy.isEmpty()){ - foreach (const InsertedRow &irow, insertedRows) { + for (const InsertedRow &irow : qAsConst(insertedRows)) { for (int i = 0; i < rowSpy.size(); ++i) { const QList<QVariant> &signal = rowSpy.at(i); if (irow.match(signal)) { @@ -808,7 +812,7 @@ void TestModelView::testDataInsertion() } } } - foreach (const InsertedRow &irow, rowsToRemove) + for (const InsertedRow &irow : qAsConst(rowsToRemove)) insertedRows.removeAll(irow); if (insertedRows.isEmpty()) break; @@ -875,7 +879,7 @@ void TestModelView::testDataInsertionTree() ++runs; if (rowSpy.wait() && !rowSpy.isEmpty()){ - foreach (const InsertedRow &irow, insertedRows) { + for (const InsertedRow &irow : qAsConst(insertedRows)) { for (int i = 0; i < rowSpy.size(); ++i) { const QList<QVariant> &signal = rowSpy.at(i); if (irow.match(signal)) { @@ -895,7 +899,7 @@ void TestModelView::testDataInsertionTree() } } } - foreach (const InsertedRow &irow, rowsToRemove) + for (const InsertedRow &irow : qAsConst(rowsToRemove)) insertedRows.removeAll(irow); if (insertedRows.isEmpty()) break; diff --git a/tests/auto/proxy/tst_proxy.cpp b/tests/auto/proxy/tst_proxy.cpp index 8022063..79e1adf 100644 --- a/tests/auto/proxy/tst_proxy.cpp +++ b/tests/auto/proxy/tst_proxy.cpp @@ -221,8 +221,15 @@ void ProxyTest::testProxy() if (!useProxy) QCOMPARE(rep->tracks()->availableRoles(), QVector<int>{Qt::DisplayRole}); else { - QCOMPARE(QSet<int>::fromList(rep->tracks()->availableRoles().toList()), - QSet<int>::fromList(model.roleNames().keys())); + const auto &availableRolesVec = rep->tracks()->availableRoles(); + QSet<int> availableRoles; + for (int r : availableRolesVec) + availableRoles.insert(r); + const auto &rolesHash = model.roleNames(); + QSet<int> roles; + for (auto it = rolesHash.cbegin(), end = rolesHash.cend(); it != end; ++it) + roles.insert(it.key()); + QCOMPARE(availableRoles, roles); } QSignalSpy dataSpy(rep->tracks(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>))); QVector<QModelIndex> pending; @@ -290,8 +297,15 @@ void ProxyTest::testProxy() if (!useProxy) QCOMPARE(tracksReplica->availableRoles(), QVector<int>{Qt::DisplayRole}); else { - QCOMPARE(QSet<int>::fromList(tracksReplica->availableRoles().toList()), - QSet<int>::fromList(model.roleNames().keys())); + const auto &availableRolesVec = tracksReplica->availableRoles(); + QSet<int> availableRoles; + for (int r : availableRolesVec) + availableRoles.insert(r); + const auto &rolesHash = model.roleNames(); + QSet<int> roles; + for (auto it = rolesHash.cbegin(), end = rolesHash.cend(); it != end; ++it) + roles.insert(it.key()); + QCOMPARE(availableRoles, roles); } QTRY_COMPARE(tracksReplica->isInitialized(), true); QSignalSpy dataSpy(tracksReplica, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>))); diff --git a/tests/auto/proxy_multiprocess/client/main.cpp b/tests/auto/proxy_multiprocess/client/main.cpp index 19ba46f..f28c65a 100644 --- a/tests/auto/proxy_multiprocess/client/main.cpp +++ b/tests/auto/proxy_multiprocess/client/main.cpp @@ -53,7 +53,7 @@ private Q_SLOTS: const auto objectMode = qEnvironmentVariable("ObjectMode"); qDebug() << "Starting test" << objectMode; - if (objectMode == QLatin1Literal("ObjectPointer")) { + if (objectMode == QLatin1String("ObjectPointer")) { QSignalSpy tracksSpy(m_rep->tracks(), &QAbstractItemModelReplica::initialized); QVERIFY(m_rep->subClass() != nullptr); QCOMPARE(m_rep->subClass()->myPOD(), initialValue); diff --git a/tests/auto/proxy_multiprocess/server/main.cpp b/tests/auto/proxy_multiprocess/server/main.cpp index 1cd005d..1e8f107 100644 --- a/tests/auto/proxy_multiprocess/server/main.cpp +++ b/tests/auto/proxy_multiprocess/server/main.cpp @@ -52,7 +52,7 @@ private Q_SLOTS: subclass.setI(initialI); QStringListModel model; model.setStringList(QStringList() << "Track1" << "Track2" << "Track3"); - if (objectMode == QLatin1Literal("ObjectPointer")) { + if (objectMode == QLatin1String("ObjectPointer")) { parent.setSubClass(&subclass); parent.setTracks(&model); parent.setMyEnum(ParentClassSource::bar); @@ -82,7 +82,7 @@ private Q_SLOTS: updatedSubclass.setMyPOD(updatedValue); updatedSubclass.setI(updatedI); parent.setSubClass(&updatedSubclass); - if (objectMode == QLatin1Literal("NullPointer")) + if (objectMode == QLatin1String("NullPointer")) parent.setTracks(&model); parent.setMyEnum(ParentClassSource::foobar); parent.setDate(Qt::SystemLocaleLongDate); diff --git a/tests/auto/repc/signature/signatureTests/tst_signature.cpp b/tests/auto/repc/signature/signatureTests/tst_signature.cpp index 371b0ec..0907df1 100644 --- a/tests/auto/repc/signature/signatureTests/tst_signature.cpp +++ b/tests/auto/repc/signature/signatureTests/tst_signature.cpp @@ -63,25 +63,26 @@ private slots: // wait for server start QTest::qWait(200); - QStringList tests; - tests << _("differentGlobalEnum") - << _("differentClassEnum") - << _("differentPropertyCount") - << _("differentPropertyType") - << _("scrambledProperties") - << _("differentSlotCount") - << _("differentSlotType") - << _("differentSlotParamCount") - << _("differentSlotParamType") - << _("scrambledSlots") - << _("differentSignalCount") - << _("differentSignalParamCount") - << _("differentSignalParamType") - << _("scrambledSignals") - << _("state") - << _("matchAndQuit"); // matchAndQuit should be the last one + const QLatin1String tests[] = { + _("differentGlobalEnum"), + _("differentClassEnum"), + _("differentPropertyCount"), + _("differentPropertyType"), + _("scrambledProperties"), + _("differentSlotCount"), + _("differentSlotType"), + _("differentSlotParamCount"), + _("differentSlotParamType"), + _("scrambledSlots"), + _("differentSignalCount"), + _("differentSignalParamCount"), + _("differentSignalParamType"), + _("scrambledSignals"), + _("state"), + _("matchAndQuit"), // matchAndQuit should be the last one + }; - foreach (auto test, tests) { + for (const auto &test : tests) { qDebug() << "Starting" << test << "process"; QProcess testProc; testProc.setProcessChannelMode(QProcess::ForwardedChannels); diff --git a/tests/auto/restart/client/main.cpp b/tests/auto/restart/client/main.cpp index aa2cdd9..c520131 100644 --- a/tests/auto/restart/client/main.cpp +++ b/tests/auto/restart/client/main.cpp @@ -64,7 +64,7 @@ private Q_SLOTS: qWarning() << "From client"; const MyPOD initialValue(42, 3.14f, QStringLiteral("SubClass")); - if (objectMode == QLatin1Literal("ObjectPointer")) { + if (objectMode == QLatin1String("ObjectPointer")) { QSignalSpy tracksSpy(m_rep->tracks(), &QAbstractItemModelReplica::initialized); QVERIFY(m_rep->subClass() != nullptr); QCOMPARE(m_rep->subClass()->myPOD(), initialValue); @@ -79,7 +79,7 @@ private Q_SLOTS: QSignalSpy advanceSpy(m_rep.data(), SIGNAL(advance())); QVERIFY(advanceSpy.wait()); - if (objectMode == QLatin1Literal("ObjectPointer")) { + if (objectMode == QLatin1String("ObjectPointer")) { QVERIFY(m_rep->subClass() != nullptr); QCOMPARE(m_rep->subClass()->myPOD(), initialValue); QVERIFY(m_rep->tracks() != nullptr); diff --git a/tests/auto/restart/server/main.cpp b/tests/auto/restart/server/main.cpp index b65dc17..f4e83a5 100644 --- a/tests/auto/restart/server/main.cpp +++ b/tests/auto/restart/server/main.cpp @@ -47,7 +47,7 @@ private Q_SLOTS: SubClassSimpleSource subclass; QStringListModel model; const MyPOD initialValue(42, 3.14f, QStringLiteral("SubClass")); - if (objectMode == QLatin1Literal("ObjectPointer")) { + if (objectMode == QLatin1String("ObjectPointer")) { subclass.setMyPOD(initialValue); model.setStringList(QStringList() << "Track1" << "Track2" << "Track3"); myTestServer.setSubClass(&subclass); @@ -66,9 +66,9 @@ private Q_SLOTS: QTest::qWait(200); qDebug() << "Client connected"; - if (runMode != QLatin1Literal("Baseline")) { + if (runMode != QLatin1String("Baseline")) { qDebug() << "Server quitting" << runMode; - if (runMode == QLatin1Literal("ServerRestartFatal")) + if (runMode == QLatin1String("ServerRestartFatal")) qFatal("Fatal"); QCoreApplication::exit(); return; diff --git a/tests/auto/shared/model_utilities.h b/tests/auto/shared/model_utilities.h index 0d77499..60bb7b2 100644 --- a/tests/auto/shared/model_utilities.h +++ b/tests/auto/shared/model_utilities.h @@ -96,22 +96,19 @@ struct WaitForDataChanged void checkAndRemoveRange(const QModelIndex &topLeft, const QModelIndex &bottomRight) { QVERIFY(topLeft.parent() == bottomRight.parent()); - QVector<QModelIndex> toRemove; - for (int i = 0; i < m_pending.size(); ++i) { - const QModelIndex &pending = m_pending.at(i); + const auto isInRange = [topLeft, bottomRight] (const QModelIndex &pending) noexcept -> bool { if (pending.isValid() && compareIndices(pending.parent(), topLeft.parent())) { const bool fitLeft = topLeft.column() <= pending.column(); const bool fitRight = bottomRight.column() >= pending.column(); const bool fitTop = topLeft.row() <= pending.row(); const bool fitBottom = bottomRight.row() >= pending.row(); if (fitLeft && fitRight && fitTop && fitBottom) - toRemove.append(pending); + return true; } - } - foreach (const QModelIndex &index, toRemove) { - const int ind = m_pending.indexOf(index); - m_pending.remove(ind); - } + return false; + }; + m_pending.erase(std::remove_if(m_pending.begin(), m_pending.end(), isInRange), + m_pending.end()); } QVector<QModelIndex> m_pending; diff --git a/tools/repc/main.cpp b/tools/repc/main.cpp index 41adee2..92747c0 100644 --- a/tools/repc/main.cpp +++ b/tools/repc/main.cpp @@ -150,7 +150,7 @@ int main(int argc, char **argv) outputFile = files.last(); if (!(mode & (OutRep | OutSource | OutReplica))) { // try to figure out the Out mode from file extension - if (outputFile.endsWith(QLatin1Literal(".rep"))) + if (outputFile.endsWith(QLatin1String(".rep"))) mode |= OutRep; } Q_FALLTHROUGH(); @@ -158,7 +158,7 @@ int main(int argc, char **argv) inputFile = files.first(); if (!(mode & (InRep | InSrc))) { // try to figure out the In mode from file extension - if (inputFile.endsWith(QLatin1Literal(".rep"))) + if (inputFile.endsWith(QLatin1String(".rep"))) mode |= InRep; else mode |= InSrc; @@ -212,7 +212,8 @@ int main(int argc, char **argv) const QFileInfo includePath(QLatin1String(RO_INSTALL_HEADERS)); pp.includes += Preprocessor::IncludePath(QFile::encodeName(includePath.canonicalFilePath())); pp.includes += Preprocessor::IncludePath(QFile::encodeName(includePath.canonicalPath())); - foreach (const QString &path, parser.values(includePathOption)) + const auto paths = parser.values(includePathOption); + for (const QString &path : paths) pp.includes += Preprocessor::IncludePath(QFile::encodeName(path)); pp.macros["Q_MOC_RUN"]; diff --git a/tools/repc/repcodegenerator.cpp b/tools/repc/repcodegenerator.cpp index fd208c0..fdb27d7 100644 --- a/tools/repc/repcodegenerator.cpp +++ b/tools/repc/repcodegenerator.cpp @@ -42,7 +42,7 @@ template <typename C> static int accumulatedSizeOfNames(const C &c) { int result = 0; - Q_FOREACH (const typename C::value_type &e, c) + for (const auto &e : c) result += e.name.size(); return result; } @@ -51,7 +51,7 @@ template <typename C> static int accumulatedSizeOfTypes(const C &c) { int result = 0; - Q_FOREACH (const typename C::value_type &e, c) + for (const auto &e : c) result += e.type.size(); return result; } @@ -65,7 +65,7 @@ static QString cap(QString name) static bool isClassEnum(const ASTClass &classContext, const QString &typeName) { - Q_FOREACH (const ASTEnum &astEnum, classContext.enums) { + for (const ASTEnum &astEnum : classContext.enums) { if (astEnum.name == typeName) { return true; } @@ -119,7 +119,7 @@ static QByteArray enumSignature(const ASTEnum &e) { QByteArray ret; ret += e.name.toLatin1(); - Q_FOREACH (const ASTEnumParam ¶m, e.params) + for (const ASTEnumParam ¶m : e.params) ret += param.name.toLatin1() + QByteArray::number(param.value); return ret; } @@ -138,9 +138,9 @@ static QByteArray typeData(const QString &type, const QHash<QString, QByteArray> static QByteArray functionsData(const QVector<ASTFunction> &functions, const QHash<QString, QByteArray> &specialTypes) { QByteArray ret; - Q_FOREACH (const ASTFunction &func, functions) { + for (const ASTFunction &func : functions) { ret += func.name.toLatin1(); - Q_FOREACH (const ASTDeclaration ¶m, func.params) { + for (const ASTDeclaration ¶m : func.params) { ret += param.name.toLatin1(); ret += typeData(param.type, specialTypes); ret += QByteArray(reinterpret_cast<const char *>(¶m.variableType), sizeof(param.variableType)); @@ -154,13 +154,13 @@ QByteArray RepCodeGenerator::classSignature(const ASTClass &ac) { QCryptographicHash checksum(QCryptographicHash::Sha1); QHash<QString, QByteArray> localTypes = m_globalEnumsPODs; - Q_FOREACH (const ASTEnum &e, ac.enums) // add local enums + for (const ASTEnum &e : ac.enums) // add local enums localTypes[e.name] = enumSignature(e); checksum.addData(ac.name.toLatin1()); // Checksum properties - Q_FOREACH (const ASTProperty &p, ac.properties) { + for (const ASTProperty &p : ac.properties) { checksum.addData(p.name.toLatin1()); checksum.addData(typeData(p.type, localTypes)); checksum.addData(reinterpret_cast<const char *>(&p.modifier), sizeof(p.modifier)); @@ -189,33 +189,37 @@ void RepCodeGenerator::generate(const AST &ast, Mode mode, QString fileName) } generateHeader(mode, stream, ast); - Q_FOREACH (const ASTEnum &en, ast.enums) + for (const ASTEnum &en : ast.enums) generateENUM(stream, en); - Q_FOREACH (const POD &pod, ast.pods) + for (const POD &pod : ast.pods) generatePOD(stream, pod); QSet<QString> metaTypes; - Q_FOREACH (const POD &pod, ast.pods) { + for (const POD &pod : ast.pods) { metaTypes << pod.name; - Q_FOREACH (const PODAttribute &attribute, pod.attributes) + for (const PODAttribute &attribute : pod.attributes) metaTypes << attribute.type; } const QString metaTypeRegistrationCode = generateMetaTypeRegistration(metaTypes) + generateMetaTypeRegistrationForEnums(ast.enumUses); - Q_FOREACH (const ASTClass &astClass, ast.classes) { + for (const ASTClass &astClass : ast.classes) { QSet<QString> classMetaTypes; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.isPointer) continue; classMetaTypes << property.type; } - Q_FOREACH (const ASTFunction &function, astClass.signalsList + astClass.slotsList) { + const auto extractClassMetaTypes = [&](const ASTFunction &function) { classMetaTypes << function.returnType; - Q_FOREACH (const ASTDeclaration &decl, function.params) { + for (const ASTDeclaration &decl : function.params) { classMetaTypes << decl.type; } - } + }; + for (const ASTFunction &function : astClass.signalsList) + extractClassMetaTypes(function); + for (const ASTFunction &function : astClass.slotsList) + extractClassMetaTypes(function); QString classMetaTypeRegistrationCode = metaTypeRegistrationCode + generateMetaTypeRegistration(classMetaTypes); if (mode == MERGED) { @@ -292,7 +296,7 @@ static QString formatTemplateStringArgTypeNameCapitalizedName(int numberOfTypeOc + numberOfTypeOccurrences * accumulatedSizeOfTypes(pod.attributes) + pod.attributes.size() * (templateString.size() - (numberOfNameOccurrences + numberOfTypeOccurrences) * LengthOfPlaceholderText); out.reserve(expectedOutSize); - Q_FOREACH (const PODAttribute &a, pod.attributes) + for (const PODAttribute &a : pod.attributes) out += templateString.arg(a.type, a.name, cap(a.name)); return out; } @@ -307,7 +311,7 @@ QString RepCodeGenerator::formatConstructors(const POD &pod) QString initializerString = QStringLiteral(": "); QString defaultInitializerString = initializerString; QString argString; - Q_FOREACH (const PODAttribute &a, pod.attributes) { + for (const PODAttribute &a : pod.attributes) { initializerString += QString::fromLatin1("m_%1(%1), ").arg(a.name); defaultInitializerString += QString::fromLatin1("m_%1(), ").arg(a.name); argString += QString::fromLatin1("%1 %2, ").arg(a.type, a.name); @@ -340,7 +344,7 @@ QString RepCodeGenerator::formatDataMembers(const POD &pod) + accumulatedSizeOfTypes(pod.attributes) + pod.attributes.size() * (prefix.size() + infix.size() + suffix.size()); out.reserve(expectedOutSize); - Q_FOREACH (const PODAttribute &a, pod.attributes) { + for (const PODAttribute &a : pod.attributes) { out += prefix; out += a.type; out += infix; @@ -386,7 +390,11 @@ QString RepCodeGenerator::typeForMode(const ASTProperty &property, RepCodeGenera void RepCodeGenerator::generateSimpleSetter(QTextStream &out, const ASTProperty &property, bool generateOverride) { - out << " virtual void set" << cap(property.name) << "(" << typeForMode(property, SIMPLE_SOURCE) << " " << property.name << ")"; + if (!generateOverride) + out << " virtual "; + else + out << " "; + out << "void set" << cap(property.name) << "(" << typeForMode(property, SIMPLE_SOURCE) << " " << property.name << ")"; if (generateOverride) out << " override"; out << endl; @@ -402,7 +410,7 @@ void RepCodeGenerator::generatePOD(QTextStream &out, const POD &pod) { QByteArray podData = pod.name.toLatin1(); QStringList equalityCheck; - Q_FOREACH (const PODAttribute &attr, pod.attributes) { + for (const PODAttribute &attr : pod.attributes) { equalityCheck << QStringLiteral("left.%1() == right.%1()").arg(attr.name); podData += attr.name.toLatin1() + typeData(attr.type, m_globalEnumsPODs); } @@ -456,21 +464,16 @@ void RepCodeGenerator::generateDeclarationsForEnums(QTextStream &out, const QVec out << " // QObject class in order to use .rep enums over QtRO for" << endl; out << " // non-repc generated QObjects." << endl; } - Q_FOREACH (const ASTEnum &en, enums) { + for (const ASTEnum &en : enums) { m_globalEnumsPODs[en.name] = enumSignature(en); out << " enum " << en.name << " {" << endl; - Q_FOREACH (const ASTEnumParam &p, en.params) + for (const ASTEnumParam &p : en.params) out << " " << p.name << " = " << p.value << "," << endl; out << " };" << endl; - if (generateQENUM) { - out << "#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))" << endl; + if (generateQENUM) out << " Q_ENUM(" << en.name << ")" << endl; - out << "#else" << endl; - out << " Q_ENUMS(" << en.name << ")" << endl; - out << "#endif" << endl; - } } } @@ -488,27 +491,20 @@ void RepCodeGenerator::generateENUMs(QTextStream &out, const QVector<ASTEnum> &e out << "};\n\n"; - if (!enums.isEmpty()) { - out << "#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))\n"; - Q_FOREACH (const ASTEnum &en, enums) - out << " Q_DECLARE_METATYPE(" << className <<"::" << en.name << ")\n"; - out << "#endif\n\n"; - } - generateStreamOperatorsForEnums(out, enums, className); } void RepCodeGenerator::generateConversionFunctionsForEnums(QTextStream &out, const QVector<ASTEnum> &enums) { - Q_FOREACH (const ASTEnum &en, enums) + for (const ASTEnum &en : enums) { const QString type = getEnumType(en); - out << " static inline " << en.name << " to" << en.name << "(" << type << " i, bool *ok = 0)\n" + out << " static inline " << en.name << " to" << en.name << "(" << type << " i, bool *ok = nullptr)\n" " {\n" " if (ok)\n" " *ok = true;\n" " switch (i) {\n"; - Q_FOREACH (const ASTEnumParam &p, en.params) + for (const ASTEnumParam &p : en.params) out << " case " << p.value << ": return " << p.name << ";\n"; out << " default:\n" " if (ok)\n" @@ -521,7 +517,7 @@ void RepCodeGenerator::generateConversionFunctionsForEnums(QTextStream &out, con void RepCodeGenerator::generateStreamOperatorsForEnums(QTextStream &out, const QVector<ASTEnum> &enums, const QString &className) { - Q_FOREACH (const ASTEnum &en, enums) + for (const ASTEnum &en : enums) { const QString type = getEnumType(en); out << "inline QDataStream &operator<<(QDataStream &ds, const " << className << "::" << en.name << " &obj)\n" @@ -553,7 +549,7 @@ QString RepCodeGenerator::generateMetaTypeRegistration(const QSet<QString> &meta const QString qRegisterMetaType = QStringLiteral(" qRegisterMetaType<"); const QString qRegisterMetaTypeStreamOperators = QStringLiteral(" qRegisterMetaTypeStreamOperators<"); const QString lineEnding = QStringLiteral(">();\n"); - Q_FOREACH (const QString &metaType, metaTypes) { + for (const QString &metaType : metaTypes) { if (isBuiltinType(metaType)) continue; @@ -572,7 +568,7 @@ QString RepCodeGenerator::generateMetaTypeRegistrationForEnums(const QVector<QSt { QString out; - Q_FOREACH (const QString &enumName, enumUses) { + for (const QString &enumName : enumUses) { out += QLatin1String(" qRegisterMetaTypeStreamOperators<") + enumName + QLatin1String(">(\"") + enumName + QLatin1String("\");\n"); } @@ -582,7 +578,7 @@ QString RepCodeGenerator::generateMetaTypeRegistrationForEnums(const QVector<QSt void RepCodeGenerator::generateStreamOperatorsForEnums(QTextStream &out, const QVector<QString> &enumUses) { out << "QT_BEGIN_NAMESPACE" << endl; - Q_FOREACH (const QString &enumName, enumUses) { + for (const QString &enumName : enumUses) { out << "inline QDataStream &operator<<(QDataStream &out, " << enumName << " value)" << endl; out << "{" << endl; out << " out << static_cast<qint32>(value);" << endl; @@ -629,7 +625,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass //First output properties - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { out << " Q_PROPERTY(" << typeForMode(property, mode) << " " << property.name << " READ " << property.name; if (property.modifier == ASTProperty::Constant) { if (mode == REPLICA) // We still need to notify when we get the initial value @@ -719,7 +715,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass out << " " << className << "::registerMetatypes();" << endl; out << " QVariantList properties;" << endl; out << " properties.reserve(" << astClass.properties.size() << ");" << endl; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.isPointer) out << " properties << QVariant::fromValue((" << typeForMode(property, mode) << ")" << property.defaultValue << ");" << endl; else @@ -763,7 +759,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass parameters.append(QStringLiteral("QObject *parent = nullptr")); out << " explicit " << className << "(" << parameters.join(QStringLiteral(", ")) << ") : " << astClass.name << "Source(parent)" << endl; } - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.modifier == ASTProperty::Constant) out << " , m_" << property.name << "(" << property.name << ")" << endl; else @@ -777,7 +773,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass out << "public:" << endl; if (mode == REPLICA && astClass.hasPersisted) { - out << " virtual ~" << className << "() {" << endl; + out << " ~" << className << "() override {" << endl; out << " QVariantList persisted;" << endl; for (int i = 0; i < astClass.properties.size(); i++) { if (astClass.properties.at(i).persisted) { @@ -787,7 +783,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass out << " persistProperties(\"" << astClass.name << "\", \"" << classSignature(astClass) << "\", persisted);" << endl; out << " }" << endl; } else { - out << " virtual ~" << className << "() {}" << endl; + out << " ~" << className << "() override = default;" << endl; } out << "" << endl; @@ -797,7 +793,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass //Next output getter/setter if (mode == REPLICA) { int i = 0; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { auto type = typeForMode(property, mode); if (type == QLatin1String("QVariant")) { out << " " << type << " " << property.name << "() const" << endl; @@ -828,19 +824,19 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass out << "" << endl; } } else if (mode == SOURCE) { - Q_FOREACH (const ASTProperty &property, astClass.properties) + for (const ASTProperty &property : astClass.properties) out << " virtual " << typeForMode(property, mode) << " " << property.name << "() const = 0;" << endl; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.modifier == ASTProperty::ReadWrite || property.modifier == ASTProperty::ReadPush || property.modifier == ASTProperty::SourceOnlySetter) out << " virtual void set" << cap(property.name) << "(" << typeForMode(property, mode) << " " << property.name << ") = 0;" << endl; } } else { - Q_FOREACH (const ASTProperty &property, astClass.properties) + for (const ASTProperty &property : astClass.properties) out << " " << typeForMode(property, mode) << " " << property.name << "() const override { return m_" << property.name << "; }" << endl; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.modifier == ASTProperty::ReadWrite || property.modifier == ASTProperty::ReadPush || property.modifier == ASTProperty::SourceOnlySetter) { @@ -854,25 +850,25 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass if (!astClass.properties.isEmpty() || !astClass.signalsList.isEmpty()) { out << "" << endl; out << "Q_SIGNALS:" << endl; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.modifier != ASTProperty::Constant) out << " void " << property.name << "Changed(" << fullyQualifiedTypeName(astClass, className, typeForMode(property, mode)) << " " << property.name << ");" << endl; } const QVector<ASTFunction> signalsList = transformEnumParams(astClass, astClass.signalsList, className); - Q_FOREACH (const ASTFunction &signal, signalsList) + for (const ASTFunction &signal : signalsList) out << " void " << signal.name << "(" << signal.paramsAsString() << ");" << endl; // CONSTANT source properties still need an onChanged signal on the Replica side to // update (once) when the value is initialized. Put these last, so they don't mess // up the signal index order - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (mode == REPLICA && property.modifier == ASTProperty::Constant) out << " void " << property.name << "Changed(" << fullyQualifiedTypeName(astClass, className, typeForMode(property, mode)) << " " << property.name << ");" << endl; } } bool hasWriteSlots = false; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.modifier == ASTProperty::ReadPush) { hasWriteSlots = true; break; @@ -881,7 +877,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass if (hasWriteSlots || !astClass.slotsList.isEmpty()) { out << "" << endl; out << "public Q_SLOTS:" << endl; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.modifier == ASTProperty::ReadPush) { const auto type = fullyQualifiedTypeName(astClass, className, property.type); if (mode != REPLICA) { @@ -901,7 +897,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass } } const QVector<ASTFunction> slotsList = transformEnumParams(astClass, astClass.slotsList, className); - Q_FOREACH (const ASTFunction &slot, slotsList) { + for (const ASTFunction &slot : slotsList) { const auto returnType = fullyQualifiedTypeName(astClass, className, slot.returnType); if (mode != REPLICA) { out << " virtual " << returnType << " " << slot.name << "(" << slot.paramsAsString() << ") = 0;" << endl; @@ -916,9 +912,10 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass out << " {" << endl; out << " static int __repc_index = " << className << "::staticMetaObject.indexOfSlot(\"" << slot.name << "(" << slot.paramsAsString(ASTFunction::Normalized) << ")\");" << endl; out << " QVariantList __repc_args;" << endl; - if (!slot.paramNames().isEmpty()) { + const auto ¶mNames = slot.paramNames(); + if (!paramNames.isEmpty()) { out << " __repc_args" << endl; - Q_FOREACH (const QString &name, slot.paramNames()) + for (const QString &name : paramNames) out << " << " << "QVariant::fromValue(" << name << ")" << endl; out << " ;" << endl; } @@ -933,7 +930,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass } else { if (!astClass.properties.isEmpty()) { bool addProtected = true; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.modifier == ASTProperty::ReadOnly) { if (addProtected) { out << "" << endl; @@ -951,7 +948,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass //Next output data members if (mode == SIMPLE_SOURCE) { - Q_FOREACH (const ASTProperty &property, astClass.properties) + for (const ASTProperty &property : astClass.properties) out << " " << typeForMode(property, SOURCE) << " " << "m_" << property.name << ";" << endl; } @@ -961,15 +958,8 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass out << "};" << endl; out << "" << endl; - if (mode != SIMPLE_SOURCE) { - out << "#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))" << endl; - Q_FOREACH (const ASTEnum &en, astClass.enums) - out << " Q_DECLARE_METATYPE(" << className << "::" << en.name << ")" << endl; - out << "#endif" << endl; - out << "" << endl; - + if (mode != SIMPLE_SOURCE) generateStreamOperatorsForEnums(out, astClass.enums, className); - } out << "" << endl; } @@ -1041,7 +1031,7 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl } const int slotCount = astClass.slotsList.count(); QVector<ASTProperty> pushProps; - Q_FOREACH (const ASTProperty &property, astClass.properties) { + for (const ASTProperty &property : astClass.properties) { if (property.modifier == ASTProperty::ReadPush) pushProps << property; } |