This service tests the validity of an RSS 2.0 feed, checking to see that it follows the rules of the RSS specification. For advice from the RSS Advisory Board on how to implement RSS and handle issues such as enclosures and HTML encoding, read the RSS Best Practices Profile. This checker is also a validator of Atom and RSS 1.0 feeds.

Use this tester regularly to ensure that your RSS feed continues to work well in the wide audience of RSS readers, podcast clients and other software that supports the format.

 

Congratulations!

[Valid RSS] This is a valid RSS feed.

Recommendations

This feed is valid, but interoperability with the widest range of feed readers could be improved by implementing the following recommendations.

  • line 104, column 0: style attribute contains potentially dangerous content: background-position (8 occurrences) [help]

    <table align="center" border="0" cellpadding="0" cellspacing="0" class="r ...
  • line 2530, column 0: Non-html tag: connectionevaluator (8 occurrences) [help]

    auto evaluator = std::make_shared<ConnectionEvaluator>(); // Shared ow ...
  • line 3507, column 0: description should not contain html tag [help]

    <html>
  • line 3508, column 0: description should not contain head tag [help]

    <head>
  • line 3509, column 0: description should not contain meta tag [help]

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  • line 3510, column 0: description should not contain style tag [help]

    <style>
  • line 3522, column 0: description should not contain body tag [help]

    <body>
  • line 3525, column 0: description should not contain script tag (3 occurrences) [help]

    <script src="jquery.min.js"></script>
  • line 5183, column 100: title should not contain HTML: – [help]

    ... &amp;#8211; First Steps with Qt for MCUs</title>
                                                 ^

Source: http://planet.qt-project.org/rss20.xml

  1. <?xml version="1.0"?>
  2. <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
  3.  <channel>
  4.    <title>Planet Qt</title>
  5.    <link>http://planet.qt.io</link>
  6.    <language>en</language>
  7.    <description>"Planet Qt - http://planet.qt.io/"</description>
  8.    <atom:link href="http://planet.qt.io/rss20.xml" rel="self" type="application/rss+xml"/>
  9.    <item>
  10.      <guid isPermaLink="false">https://www.qt.io/blog/moving-to-msvc-2022-in-qt-68</guid>
  11.      <title>The Qt Company Blog: Moving to Microsoft Visual C/C++ (MSVC) compiler 2022 in Qt 6.8 packages. Please test this on Qt 6.7</title>
  12.      <pubDate>Wed, 08 May 2024 15:40:26 GMT</pubDate>
  13.      <link>https://www.qt.io/blog/moving-to-msvc-2022-in-qt-68</link>
  14.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://www.qt.io/blog/moving-to-msvc-2022-in-qt-68" title=""&gt;&lt;img alt="Qt on Windows" class="hs-featured-image" src="https://www.qt.io/hubfs/Qt%20on%20Windows.png" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  15. &lt;p&gt;When you install Qt from the Qt Installer, you have a selection of target platforms. On Windows, at the time of writing, this is MinGW, MSVC as regular choices, and LLVM-MinGW as a Technology Preview. This basically specifies the environment which is used to build Qt code for that packages. Most importanly, this also de-facto specifies a version of the of the compiler which you should use for your development work, if you use pre-built Qt.&lt;br&gt;
  16. &lt;br&gt;
  17. In Qt 6.7.0, for example, we support MSVC 2022, MSVC 2019, MinGW 11.2 as compilers (see &lt;a href="https://doc.qt.io/qt-6/windows.html"&gt;this page&lt;/a&gt; in the Qt documentation), but we do not provide binary Qt packages built with MSVC 2022 which is the current version of MSVC. For future releases of Qt 6, we need to move faster towards more modern MSVC 2022 and start to phase out MSVC 2019 as an older version.&lt;br&gt;
  18. &lt;br&gt;
  19. This will be a change not only for the Qt's release team, but also for Qt's users who use these binary packages. We want to make it as smooth as possible and got a plan which we want to share here. BTW, the below changes are only related to MSVC and do not concern MinGW packages for Windows.&lt;br&gt;
  20. &lt;br&gt;
  21. In one of the next bug-fix releases of Qt 6.7, possibly in Qt 6.7.2, we will add packages built with MSVC 2022 &lt;span style="text-decoration: underline;"&gt;&lt;span style="font-style: italic;"&gt;in addition&lt;/span&gt;&lt;/span&gt; to the MSVC 2019 ones as we have now. The upcoming Qt 6.8 will have packages for Windows built with MSVC 2022 &lt;span style="text-decoration: underline;"&gt;&lt;span style="font-style: italic;"&gt;only&lt;/span&gt;&lt;/span&gt;, and MSVC 2019 ones will be discontinued in packages. MSVC 2019 will still stay in the packages of future Qt 6.7 bug-fix releases as long as Qt 6.7 is supported.&lt;br&gt;
  22. &lt;br&gt;
  23. We see this as a migration path which gives MSVC users a possibility to test Qt 6.7.x binary packages with both versions of MSVC in their projects.&lt;/p&gt;
  24. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fmoving-to-msvc-2022-in-qt-68&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  25.    </item>
  26.    <item>
  27.      <guid isPermaLink="false">https://www.qt.io/blog/qt-creator-13.0.1-released</guid>
  28.      <title>The Qt Company Blog: Qt Creator 13.0.1 released</title>
  29.      <pubDate>Tue, 07 May 2024 10:59:42 GMT</pubDate>
  30.      <link>https://www.qt.io/blog/qt-creator-13.0.1-released</link>
  31.      <description>&lt;p&gt;We are happy to announce the release of Qt Creator 13.0.1!&lt;/p&gt;
  32. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fqt-creator-13.0.1-released&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  33.    </item>
  34.    <item>
  35.      <guid isPermaLink="false">https://blog.felgo.com/qt-on-ios-itms-91053-nsprivacyaccessedapitypes</guid>
  36.      <title>Felgo: Qt on iOS and ITMS-91053 NSPrivacyAccessedAPITypes Error</title>
  37.      <pubDate>Tue, 07 May 2024 08:47:00 GMT</pubDate>
  38.      <link>https://blog.felgo.com/qt-on-ios-itms-91053-nsprivacyaccessedapitypes</link>
  39.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://blog.felgo.com/qt-on-ios-itms-91053-nsprivacyaccessedapitypes" title=""&gt;&lt;img alt="Qt on iOS and the ITMS-91053 NSPrivacyAccessedAPITypes Error" class="hs-featured-image" src="https://blog.felgo.com/hubfs/feature-itms-91053.jpg" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  40. &lt;p&gt;If you develop a Felgo or Qt app for iOS and upload it to the app store via AppStore Connect, you may face a new Apple warning e-mail these days:&lt;/p&gt;
  41. &lt;blockquote&gt;
  42. &lt;p&gt;&lt;em&gt;We noticed one or more issues with a recent submission for App Store review for the following app.&lt;/em&gt;&lt;/p&gt;
  43. &lt;p&gt;&lt;em&gt;Although submission for App Store review was successful, you may want to correct the following issues in your next submission for App Store review. Once you've corrected the issues, upload a new binary to App Store Connect.&lt;/em&gt;&lt;/p&gt;
  44. &lt;p&gt;&lt;em&gt;ITMS-91053: Missing API declaration - Your app&#x2019;s code in the &#x201C;iosproject&#x201D; file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategorySystemBootTime. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app&#x2019;s privacy manifest to provide approved reasons for these APIs used by your app&#x2019;s code.&lt;/em&gt;&lt;/p&gt;
  45. &lt;p&gt;&lt;em&gt;ITMS-91053: Missing API declaration - Your app&#x2019;s code in the &#x201C;iosproject&#x201D; file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryDiskSpace. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app&#x2019;s privacy manifest to provide approved reasons for these APIs used by your app&#x2019;s code.&lt;/em&gt;&lt;/p&gt;
  46. &lt;p&gt;&lt;em&gt;ITMS-91053: Missing API declaration - Your app&#x2019;s code in the &#x201C;iosproject&#x201D; file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryUserDefaults. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app&#x2019;s privacy manifest to provide approved reasons for these APIs used by your app&#x2019;s code.&lt;/em&gt;&lt;/p&gt;
  47. &lt;p&gt;&lt;em&gt;ITMS-91053: Missing API declaration - Your app&#x2019;s code in the &#x201C;iosproject&#x201D; file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryFileTimestamp. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app&#x2019;s privacy manifest to provide approved reasons for these APIs used by your app&#x2019;s code.&lt;/em&gt;&lt;/p&gt;
  48. &lt;p&gt;&lt;em&gt;Apple Developer Relations&lt;/em&gt;&lt;/p&gt;
  49. &lt;/blockquote&gt;
  50. &lt;p&gt;Without a proper fix, Apple has rejected app submissions to App Store Connect since May 1&lt;sup&gt;st&lt;/sup&gt;.&lt;/p&gt;
  51. &lt;h2&gt;Why is ITMS-91053 happening?&lt;/h2&gt;
  52. &lt;p&gt;In an attempt to prevent fingerprinting, Apple recently added a new policy that requires you to provide a specific reason if you are using one of the APIs that Apple identified as a possible backdoor for fingerprinting. Fingerprinting refers to using specific APIs or device signals to uniquely identify a device or user for the purpose of tracking, even though users might not be aware of that.&lt;/p&gt;
  53. &lt;p&gt;While you may not use those APIs directly, Qt or any third-party framework integrated into your app may. Read on to learn how to fix the issue.&lt;/p&gt;
  54. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=6147417&amp;k=14&amp;r=https%3A%2F%2Fblog.felgo.com%2Fqt-on-ios-itms-91053-nsprivacyaccessedapitypes&amp;bu=https%253A%252F%252Fblog.felgo.com&amp;bvt=rss" width="1"&gt;</description>
  55.    </item>
  56.    <item>
  57.      <guid isPermaLink="false">https://www.basyskom.de/?p=9100</guid>
  58.      <title>Qt &#x2013; basysKom GmbH: About QML Efficiency: Compilers, Language Server, and Type Annotations</title>
  59.      <pubDate>Mon, 06 May 2024 13:22:26 GMT</pubDate>
  60.      <link>https://www.basyskom.de/2024/about-qml-efficiency-compilers-language-server-and-type-annotations/</link>
  61.      <description>&lt;p&gt;&lt;a href="https://www.basyskom.de/2024/about-qml-efficiency-compilers-language-server-and-type-annotations/"&gt;&lt;img align="left" alt="About QML Efficiency: Compilers, Language Server, and Type Annotations" height="150" src="https://www.basyskom.de/wp-content/uploads/2020/07/Qt_logo_space-01-01-300x150.png" style="margin: 0 20px 20px 0;" width="300"&gt;&lt;/a&gt;&lt;/p&gt;
  62. &lt;p&gt;In our last post we had a look at how to set up QML Modules and how we can benefit from the QML Linter. Today we&#x2019;re going to set up the QML Language Server to get an IDE-like experience in an editor of our choice. We&#x2019;ll also help the the QML Compiler generate more efficient code.&lt;/p&gt;
  63. &lt;p&gt;&lt;a href="https://www.basyskom.de/2024/about-qml-efficiency-compilers-language-server-and-type-annotations/" rel="nofollow"&gt;Continue reading About QML Efficiency: Compilers, Language Server, and Type Annotations at basysKom GmbH.&lt;/a&gt;&lt;/p&gt;</description>
  64.    </item>
  65.    <item>
  66.      <guid isPermaLink="false">https://www.qt.io/blog/enhancing-productivity-in-distributed-software-development-teams</guid>
  67.      <title>The Qt Company Blog: Enhancing Productivity in Distributed Software Development Teams</title>
  68.      <pubDate>Fri, 03 May 2024 10:10:36 GMT</pubDate>
  69.      <link>https://www.qt.io/blog/enhancing-productivity-in-distributed-software-development-teams</link>
  70.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://www.qt.io/blog/enhancing-productivity-in-distributed-software-development-teams" title=""&gt;&lt;img alt="Enhancing Productivity in Distributed Software Development Teams" class="hs-featured-image" src="https://www.qt.io/hubfs/shutterstock_1434361487%20copy%202.png" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  71. &lt;p&gt;&#xA0;&lt;/p&gt;
  72. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fenhancing-productivity-in-distributed-software-development-teams&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  73.    </item>
  74.    <item>
  75.      <guid isPermaLink="false">https://www.qt.io/blog/qt-quick-in-android-as-a-view</guid>
  76.      <title>The Qt Company Blog: Qt Quick in Android as a View</title>
  77.      <pubDate>Thu, 02 May 2024 11:54:41 GMT</pubDate>
  78.      <link>https://www.qt.io/blog/qt-quick-in-android-as-a-view</link>
  79.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://www.qt.io/blog/qt-quick-in-android-as-a-view" title=""&gt;&lt;img alt="Qt Quick in Android as a View" class="hs-featured-image" src="https://www.qt.io/hubfs/_Website_Blog/Upload_Here/morphing-example-landscape-3.png" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  80. &lt;p&gt;&lt;span&gt;&lt;span&gt;This blog post is the first one in a series where we are going to have a look at one exciting feature coming as a Technology Preview in 6.7.0: the ability to use QML and Qt Quick in your otherwise non-Qt Android apps as an Android View! We've also created an Android Studio plugin to help you keep the workflow simple. In this first post, we'll have an overview of the feature, what it entails, why we are adding it, and where you could benefit from it. In the following posts, we will show how to use it along with some code examples and take a closer look at the tooling, testing, and some possible use cases, such as 3D.&#xA0;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
  81. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fqt-quick-in-android-as-a-view&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  82.    </item>
  83.    <item>
  84.      <guid isPermaLink="false">https://www.qt.io/blog/security-advisory-qstringconverter</guid>
  85.      <title>The Qt Company Blog: Security advisory: QStringConverter</title>
  86.      <pubDate>Thu, 02 May 2024 11:45:00 GMT</pubDate>
  87.      <link>https://www.qt.io/blog/security-advisory-qstringconverter</link>
  88.      <description>&lt;p&gt;QStringConverter has an invalid pointer being passed as a callback which can allow modification of the stack and has been assigned the CVE id CVE-2024-33861.&lt;/p&gt;
  89. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fsecurity-advisory-qstringconverter&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  90.    </item>
  91.    <item>
  92.      <guid isPermaLink="false">https://www.kdab.com/?p=34951</guid>
  93.      <title>KDAB on Qt: C++ &amp; Rust, Servo Web &amp; Qt, Qt Quick &amp; JSON, Embedded &#x2013; blogs &amp; videos, Hotspot 1.5, Qt 6.7, GCompris in India, Events</title>
  94.      <pubDate>Mon, 29 Apr 2024 09:21:56 GMT</pubDate>
  95.      <link>https://www.kdab.com/2024-april-newsletter/</link>
  96.      <description>&lt;p&gt;&#xA0;&lt;/p&gt;
  97. &amp;
  98. &lt;p&gt;96&lt;/p&gt;
  99. &lt;p&gt;&#xA0;&lt;/p&gt;
  100. &lt;table border="0" cellpadding="0" cellspacing="0" class="nl2go-body-table" style="width: 100%;" width="100%"&gt;
  101. &lt;tbody&gt;
  102. &lt;tr&gt;
  103. &lt;td&gt;
  104. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r0-o" style="background-color: #eff2f7; background-position: top; font-size: 0; width: 100%;" width="100%"&gt;
  105. &lt;tbody&gt;
  106. &lt;tr&gt;
  107. &lt;td valign="top"&gt;
  108. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r2-o" style="width: 600px;" width="600"&gt;
  109. &lt;tbody&gt;
  110. &lt;tr&gt;
  111. &lt;td class="r3-i" style="padding-top: 25px;"&gt;
  112. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  113. &lt;tbody&gt;
  114. &lt;tr&gt;
  115. &lt;th class="r4-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  116. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  117. &lt;tbody&gt;
  118. &lt;tr&gt;
  119. &lt;td class="r6-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  120. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  121. &lt;tbody&gt;
  122. &lt;tr&gt;
  123. &lt;td align="center" class="r7-c"&gt;
  124. &lt;table border="0" cellpadding="0" cellspacing="0" class="r8-o" style="width: 524px;" width="524"&gt;
  125. &lt;tbody&gt;
  126. &lt;tr&gt;
  127. &lt;td class="r9-i" style="font-size: 0px; line-height: 0px; padding-top: 5px;"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/7e24fd0c93b897ddc07cdc954ef9c7185f185ec3b23574d30556343e28787391.png?e=JQwvmPyLRA4bC7MWqyL3xQgHa9_YSAtyNoNDvYiSghSXK_LUjc7sP7ajdz_wOEFQF202u-sdxQKHJ5PRm0eC72VfbG-LydQ1AsopXBMkyTIxMsjVmGsxZkdxN2jYYUTIoh0NcTEQElhmWxsNheAO1TLraew9CZYsVXZRQ6JIQu15ozDYjXUPfRDvvsvPHdETjV_eCC5dnfgdrRfdG0SFxMZRwON7yR62s07Pc-QY1gEEhUE" style="display: block; width: 100%;" width="524"&gt;&lt;/td&gt;
  128. &lt;/tr&gt;
  129. &lt;/tbody&gt;
  130. &lt;/table&gt;
  131. &lt;/td&gt;
  132. &lt;/tr&gt;
  133. &lt;/tbody&gt;
  134. &lt;/table&gt;
  135. &lt;/td&gt;
  136. &lt;/tr&gt;
  137. &lt;/tbody&gt;
  138. &lt;/table&gt;
  139. &lt;/th&gt;
  140. &lt;/tr&gt;
  141. &lt;/tbody&gt;
  142. &lt;/table&gt;
  143. &lt;/td&gt;
  144. &lt;/tr&gt;
  145. &lt;/tbody&gt;
  146. &lt;/table&gt;
  147. &lt;/td&gt;
  148. &lt;/tr&gt;
  149. &lt;/tbody&gt;
  150. &lt;/table&gt;
  151. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r2-o" style="width: 600px;" width="600"&gt;
  152. &lt;tbody&gt;
  153. &lt;tr&gt;
  154. &lt;td valign="top"&gt;
  155. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  156. &lt;tbody&gt;
  157. &lt;tr&gt;
  158. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  159. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  160. &lt;tbody&gt;
  161. &lt;tr&gt;
  162. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  163. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  164. &lt;tbody&gt;
  165. &lt;tr&gt;
  166. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  167. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  168. &lt;tbody&gt;
  169. &lt;tr&gt;
  170. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-top: 15px; text-align: left;"&gt;
  171. &lt;div&gt;
  172. &lt;h2 class="default-heading2" style="margin: 0; color: #222222; direction: ltr; font-family: Open Sans; font-size: 28px;"&gt;Welcome to April&#x2019;s Newsletter from KDAB&lt;/h2&gt;
  173. &lt;/div&gt;
  174. &lt;/td&gt;
  175. &lt;/tr&gt;
  176. &lt;tr&gt;
  177. &lt;td align="left" class="r15-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; text-align: left;"&gt;
  178. &lt;div&gt;
  179. &lt;p style="margin: 0; direction: ltr;"&gt;It must be spring! Blogs are sprouting out all over &lt;img alt="&#x1F331;" class="wp-smiley" src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f331.png" style="height: 1em;"&gt; &lt;img alt="&#x1F60A;" class="wp-smiley" src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f60a.png" style="height: 1em;"&gt;&lt;/p&gt;
  180. &lt;p&gt;&#xA0;&lt;/p&gt;
  181. &lt;p style="margin: 0; direction: ltr;"&gt;We kick off with Part 3 of &lt;strong&gt;Mixing C++ and Rust for Fun and Profit,&lt;/strong&gt; followed by &lt;strong&gt;Embedding the Servo Web Engine in Qt&lt;/strong&gt; and &lt;strong&gt;Recursive Instantiation with Qt Quick and JSON.&lt;/strong&gt;&lt;/p&gt;
  182. &lt;p&gt;&#xA0;&lt;/p&gt;
  183. &lt;p style="margin: 0; direction: ltr;"&gt;Then we offer two new blogs in our &lt;strong&gt;Embedded Development series,&lt;/strong&gt; and, still on the embedded theme, some videos on &lt;strong&gt;Reducing Your Qt Embedded Development Cycle Time&lt;/strong&gt; plus a report (with demos) from &lt;strong&gt;Embedded World 2024&lt;/strong&gt;.&lt;/p&gt;
  184. &lt;p&gt;&#xA0;&lt;/p&gt;
  185. &lt;p style="margin: 0; direction: ltr;"&gt;After that, there&#x2019;s &lt;strong&gt;Hotspot 1.5&lt;/strong&gt; and the &lt;strong&gt;Qt 6.7 releases&lt;/strong&gt;, and a different kind of glimpse into the open source contributor world, with &lt;strong&gt;GCompris in India.&lt;/strong&gt;&lt;/p&gt;
  186. &lt;p&gt;&#xA0;&lt;/p&gt;
  187. &lt;p style="margin: 0; direction: ltr;"&gt;Lastly, you will find important updates on coming &lt;strong&gt;events in 2024,&lt;/strong&gt; including next month&#x2019;s &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/jbx5n6YDyJ64K8THeECjMoOcxdp7U5p1WnTcue_HXb-ZMWcoAyjcvaupZh5-iauZyNAGbVeqLPBGhufGfXHaCGRAvZz7DV5MHs5lQdikWZgP6IQIjTlnd6Vjj2TRmhzm0ySgecuMwpWtMRZFkncmplxaH8N9fEbRn9MRMK1XsyjchT-6sU1Pu1dahMuR" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Oxidize&lt;/a&gt; conference in Berlin, where the focus is on &lt;strong&gt;Industrial Rust Use&lt;/strong&gt;. Enjoy!&lt;/p&gt;
  188. &lt;/div&gt;
  189. &lt;/td&gt;
  190. &lt;/tr&gt;
  191. &lt;tr&gt;
  192. &lt;td align="center" class="r16-c" style="padding-bottom: 30px; padding-top: 30px;"&gt;
  193. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  194. &lt;tbody&gt;
  195. &lt;tr&gt;
  196. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  197. &lt;/tr&gt;
  198. &lt;/tbody&gt;
  199. &lt;/table&gt;
  200. &lt;/td&gt;
  201. &lt;/tr&gt;
  202. &lt;/tbody&gt;
  203. &lt;/table&gt;
  204. &lt;/td&gt;
  205. &lt;/tr&gt;
  206. &lt;/tbody&gt;
  207. &lt;/table&gt;
  208. &lt;/th&gt;
  209. &lt;/tr&gt;
  210. &lt;/tbody&gt;
  211. &lt;/table&gt;
  212. &lt;/td&gt;
  213. &lt;/tr&gt;
  214. &lt;/tbody&gt;
  215. &lt;/table&gt;
  216. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  217. &lt;tbody&gt;
  218. &lt;tr&gt;
  219. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  220. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  221. &lt;tbody&gt;
  222. &lt;tr&gt;
  223. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  224. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  225. &lt;tbody&gt;
  226. &lt;tr&gt;
  227. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  228. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  229. &lt;tbody&gt;
  230. &lt;tr&gt;
  231. &lt;td align="left" class="r17-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  232. &lt;div&gt;
  233. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;Mixing C++ and Rust for Fun and Profit&lt;/p&gt;
  234. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;&lt;span style="font-size: 22px;"&gt;Part 3: How not to invent the wheel&lt;/span&gt;&lt;/p&gt;
  235. &lt;/div&gt;
  236. &lt;/td&gt;
  237. &lt;/tr&gt;
  238. &lt;/tbody&gt;
  239. &lt;/table&gt;
  240. &lt;/td&gt;
  241. &lt;/tr&gt;
  242. &lt;/tbody&gt;
  243. &lt;/table&gt;
  244. &lt;/th&gt;
  245. &lt;/tr&gt;
  246. &lt;/tbody&gt;
  247. &lt;/table&gt;
  248. &lt;/td&gt;
  249. &lt;/tr&gt;
  250. &lt;/tbody&gt;
  251. &lt;/table&gt;
  252. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  253. &lt;tbody&gt;
  254. &lt;tr&gt;
  255. &lt;td class="r18-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  256. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  257. &lt;tbody&gt;
  258. &lt;tr&gt;
  259. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  260. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  261. &lt;tbody&gt;
  262. &lt;tr&gt;
  263. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  264. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  265. &lt;tbody&gt;
  266. &lt;tr&gt;
  267. &lt;td align="left" class="r20-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 2; padding-top: 15px; text-align: left;"&gt;
  268. &lt;div&gt;
  269. &lt;h3 class="default-heading3" style="margin: 0; color: #222; font-family: Open Sans,Arial; direction: ltr; font-size: 22px;"&gt;by Loren Burkholder&lt;/h3&gt;
  270. &lt;/div&gt;
  271. &lt;/td&gt;
  272. &lt;/tr&gt;
  273. &lt;tr&gt;
  274. &lt;td align="left" class="r21-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 2; padding-bottom: 15px; padding-top: 15px; text-align: left;"&gt;
  275. &lt;div&gt;
  276. &lt;p style="margin: 0; direction: ltr;"&gt;In the two previous posts (&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/xtqRKDBs2toZplY465kjBdSCbXzKgtDRAmrMA4QJ89IDjKrKPlhsJjEnq0ang_qfxNOcpMWsJvGt0Y8LJIJyUJUUItPdMcTTrsG0rrxuyzaKFsEKdaCIRRiEaEYCjsU2EV4cyFfq5zwovGCIrckniw02u-wTAG83kQAiS9Z87miFss6RX6tfKCa7E9CsoZKLxGErj0HMg4P52HW7ZA3XLWB3W8cjlNYCK3rCbWuO_nORY52DF8TblQ" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Part 1&lt;/a&gt; and &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/rvuSPtmenT0IY39bgAHv8h4EYcpDnM14fChYj81OAnAADNyu3XsxagpFH4QisaoTqM0vymsFGaUs8qcueaQrmuPEqM5PvcEhXxYy8C3W8iZZdErlpMo5s-cp-0bVv0S0iCEwaehQwMxNZFWkGhvk7V0wGA1GW1j3leRK7GRcfNJT0MeCy7C5IQ75ks3AYeHxIobRYevaQS0nTylFLJ_1ctkexrA-V2nPtxQvS4HVPwFQ7sfheEBZ-Q" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Part 2&lt;/a&gt;), we looked at how to build bindings between C++ and Rust from scratch.&lt;/p&gt;
  277. &lt;p&gt;&#xA0;&lt;/p&gt;
  278. &lt;p style="margin: 0; direction: ltr;"&gt;However, while building a binding generator from scratch is fun, it&#x2019;s not necessarily an efficient way to integrate Rust into your C++ project.&lt;/p&gt;
  279. &lt;p&gt;&#xA0;&lt;/p&gt;
  280. &lt;p style="margin: 0; direction: ltr;"&gt;Let&#x2019;s look at some existing technologies for mixing C++ and Rust that you can easily deploy today.&lt;/p&gt;
  281. &lt;p&gt;&#xA0;&lt;/p&gt;
  282. &lt;p style="margin: 0; direction: ltr;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/A6iRSlLeArxRuw44JGZQdsG7Ujbj0ePkn9X37zogEBRE6NoinBAQ6eyOvdCz-HHWg8IIyc5p08PHmaeRj8NH20OBbwAQB7uGE1yCvufnafHi_i2lfg_SwBCv6r0B-hnG49O3KagscVpNZeX2-xGhZqImPCo1ktjyAI4hCEyb62xOHd1d1N728qKwa8pmhuxFQFoXTfdxQXdsiNG5Q51honCjMIV0fGs49eoGAv85pd5AFLCnbnBxtQ" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Read on&lt;/a&gt;.&lt;/p&gt;
  283. &lt;/div&gt;
  284. &lt;/td&gt;
  285. &lt;/tr&gt;
  286. &lt;/tbody&gt;
  287. &lt;/table&gt;
  288. &lt;/td&gt;
  289. &lt;/tr&gt;
  290. &lt;/tbody&gt;
  291. &lt;/table&gt;
  292. &lt;/th&gt;
  293. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  294. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  295. &lt;tbody&gt;
  296. &lt;tr&gt;
  297. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  298. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  299. &lt;tbody&gt;
  300. &lt;tr&gt;
  301. &lt;td align="center" class="r22-c" style="font-size: 0px; line-height: 0px; padding-bottom: 15px; padding-top: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/tfz51YjUI095e4x2LzMnUUOg9uZXc93bTzK9-jntmxHqM3nY5afQ2De6gJz4tcPPjnIsTqXzYS11VDG0BjG3UDgGVADEzlhWCUwI4LhZor0pV4JSjM7DTcVubo0hw9gxzAtPTymoOQf0JEd1FFrgRYhSZ7e9olxO9COKUQHtUmMBoNagzS18fcwgDm9OfN4YwyEKqzKyu53F4iQX909F6oa485mA8nbaxlXC912H1EEq4b727hukiw" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/120388115e4294b29eda2d39fa4dad2528e6b5e5c779794e453a4693e2a57fd0.png?e=5jHCtsBLHi0Xtap0ycj0GY9hjxFg-CARmgE2VnDeAoDie6bYg_CWzV7vJytMP1VjlGqM2u63h6LfcwcqAHaD3f3N4mYAEr-iR8J4DSkHd9LBkR1jdrVv6sURmR4TahsT0AYCPVoPfOTDVvCW4ss-A1ZXk8iybkbIZnysLuJX3Y9fJ_wHfq-ivOmJb8QLrSEdjlMWgtVE2wIon07LyavLYzo5vtaQK2nBnAl-YmhzEcNtgUI" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  302. &lt;/tr&gt;
  303. &lt;/tbody&gt;
  304. &lt;/table&gt;
  305. &lt;/td&gt;
  306. &lt;/tr&gt;
  307. &lt;/tbody&gt;
  308. &lt;/table&gt;
  309. &lt;/th&gt;
  310. &lt;/tr&gt;
  311. &lt;/tbody&gt;
  312. &lt;/table&gt;
  313. &lt;/td&gt;
  314. &lt;/tr&gt;
  315. &lt;/tbody&gt;
  316. &lt;/table&gt;
  317. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  318. &lt;tbody&gt;
  319. &lt;tr&gt;
  320. &lt;td class="r18-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  321. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  322. &lt;tbody&gt;
  323. &lt;tr&gt;
  324. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  325. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  326. &lt;tbody&gt;
  327. &lt;tr&gt;
  328. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  329. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  330. &lt;tbody&gt;
  331. &lt;tr&gt;
  332. &lt;td align="center" class="r16-c" style="padding-bottom: 30px; padding-top: 30px;"&gt;
  333. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  334. &lt;tbody&gt;
  335. &lt;tr&gt;
  336. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  337. &lt;/tr&gt;
  338. &lt;/tbody&gt;
  339. &lt;/table&gt;
  340. &lt;/td&gt;
  341. &lt;/tr&gt;
  342. &lt;/tbody&gt;
  343. &lt;/table&gt;
  344. &lt;/td&gt;
  345. &lt;/tr&gt;
  346. &lt;/tbody&gt;
  347. &lt;/table&gt;
  348. &lt;/th&gt;
  349. &lt;/tr&gt;
  350. &lt;/tbody&gt;
  351. &lt;/table&gt;
  352. &lt;/td&gt;
  353. &lt;/tr&gt;
  354. &lt;/tbody&gt;
  355. &lt;/table&gt;
  356. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  357. &lt;tbody&gt;
  358. &lt;tr&gt;
  359. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  360. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  361. &lt;tbody&gt;
  362. &lt;tr&gt;
  363. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  364. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  365. &lt;tbody&gt;
  366. &lt;tr&gt;
  367. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  368. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  369. &lt;tbody&gt;
  370. &lt;tr&gt;
  371. &lt;td align="left" class="r17-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  372. &lt;div&gt;
  373. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;Embedding the Servo Web Engine in Qt&lt;/p&gt;
  374. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;&lt;span style="font-size: 22px;"&gt;Using CXX-Qt to integrate a web rendering engine written in Rust&lt;/span&gt;&lt;/p&gt;
  375. &lt;/div&gt;
  376. &lt;/td&gt;
  377. &lt;/tr&gt;
  378. &lt;/tbody&gt;
  379. &lt;/table&gt;
  380. &lt;/td&gt;
  381. &lt;/tr&gt;
  382. &lt;/tbody&gt;
  383. &lt;/table&gt;
  384. &lt;/th&gt;
  385. &lt;/tr&gt;
  386. &lt;/tbody&gt;
  387. &lt;/table&gt;
  388. &lt;/td&gt;
  389. &lt;/tr&gt;
  390. &lt;/tbody&gt;
  391. &lt;/table&gt;
  392. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  393. &lt;tbody&gt;
  394. &lt;tr&gt;
  395. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  396. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  397. &lt;tbody&gt;
  398. &lt;tr&gt;
  399. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  400. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  401. &lt;tbody&gt;
  402. &lt;tr&gt;
  403. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  404. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  405. &lt;tbody&gt;
  406. &lt;tr&gt;
  407. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  408. &lt;div&gt;
  409. &lt;p style="margin: 0; color: #222222; direction: ltr; font-family: Open Sans; font-size: 22px;"&gt;by Andrew Hayzen and Magnus Gro&#xDF;&lt;/p&gt;
  410. &lt;/div&gt;
  411. &lt;/td&gt;
  412. &lt;/tr&gt;
  413. &lt;tr&gt;
  414. &lt;td align="left" class="r23-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; padding-top: 15px; text-align: left;"&gt;
  415. &lt;div&gt;
  416. &lt;p style="margin: 0; direction: ltr;"&gt;The Rust ecosystem has been brewing up a new web rendering engine called Servo&#x2026;. , now under the stewardship of the Linux Foundation&#x2026;.&lt;/p&gt;
  417. &lt;p&gt;&#xA0;&lt;/p&gt;
  418. &lt;p style="margin: 0;"&gt;At KDAB we managed to embed the Servo web engine inside Qt, by using our &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/-RBYhCzSkojCjdV4QaQYwJC_RJoG2dlky4ck97ccArQPwZzh3nhUiqGSa6poLY4Bfr5ciASmOQv8qwUAEl_IoWmoFn2Qm4wvZ4dnIcWCwn1Z_2y3PHSzqwcu0e3Ql7R-pofuYNU7CaWS_J2DNfP9F03WNGLKxXXfNFTyIf4vd3s0D_QO2e-v_6txEzxJLghAhex2ugE" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;CXX-Qt&lt;/a&gt; library as a bridge between Rust and C++.&lt;/p&gt;
  419. &lt;p style="margin: 0;"&gt;This means that we can now use Servo as an alternative to Chromium for webviews in Qt applications.&lt;/p&gt;
  420. &lt;p&gt;&#xA0;&lt;/p&gt;
  421. &lt;p style="margin: 0;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/lsFBw970dONEq7RAoXp7RsqfLREOGl2d0bmTii7EgNSoOHBGKXmGqsvL1H_0XC5M3vW1ksew3SJdD676uu1zixKCpwGxFLUp0WWhtTKfK-xf7LfIVrnAjlsW1rvLIBfOciFDI9VF2hUBP6uYQB3RjN2pbC0IfF4MVeXrAssqcUkiO8cdYZ0Cd5rEAzr1hBTiyQjC5_uBbxQxrmX7w7768mSC" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Read the blog&lt;/a&gt;.&lt;/p&gt;
  422. &lt;p style="margin: 0;"&gt;More &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/fM_kK32DR7wZt_ZexB_ECw_XbB-zU8LtK0ewvcsLNIQLiBq-0dAFJychbCgY8jI557qZo9rhn7OndUFsWCcAQ5MM14ivEK_-wF-7C89mQniF9u-VkUVnufURAUQBu1T5gjo9sbdYQvdeWZHdihRz-LlmlLJfbfX4FCD3_Jl0-ISM0clY14XjA7TmvaLN8vVeHTg-" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;about CXX-Qt.&lt;/a&gt; &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/O75wVrcUxAoqt3qfizxdTlNvIk2c0Ctu1axPhPxO_f9FWyA3KulUf7tevZmsP_mZxC6rhaZgAAi5KCugV7pHSdmUahL7Fwxr6nC3nBwy2gmcFXlnmuSalfNh2QkgDyVfLjWandrLCjf6gtVfh9To-SfI5xhUeR3rC2_GoKzWTGpLunaDmFvSqhY5yrmvzV4" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;About Servo&lt;/a&gt;&lt;a rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;.&lt;/a&gt;&lt;/p&gt;
  423. &lt;/div&gt;
  424. &lt;/td&gt;
  425. &lt;/tr&gt;
  426. &lt;/tbody&gt;
  427. &lt;/table&gt;
  428. &lt;/td&gt;
  429. &lt;/tr&gt;
  430. &lt;/tbody&gt;
  431. &lt;/table&gt;
  432. &lt;/th&gt;
  433. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  434. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  435. &lt;tbody&gt;
  436. &lt;tr&gt;
  437. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  438. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  439. &lt;tbody&gt;
  440. &lt;tr&gt;
  441. &lt;td align="center" class="r24-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 15px; padding-top: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/8QvWxWvxxxLcycSICvUeiK4os7A33dHNgX3uqd5OYA_9usk-fgW1q8o9KJI3YKzVwBNbrjkekJLiFwuyi4SYktW4ti6TaQBSo_5dDDx2reQEoYQaxIhhHF3-PE8Fr9iIoBeIO_cEE_P7E5-K-6rUZd9wTgp1Yx-7e-Kg3NV1p-NufbLIDb77lV0AWxwqFqnj22ZvqHMS7gpw0vDLFg_b4xYC" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/d5d4662c80f26009988acb8be64041be8066c1dc219412109756f6cdfbaf5c85.png?e=YrQ75mGjpmF2rsOcA1Po6nQCgZRXVqbFPraU3b99th2btDoz8fPMkEuNTIObXpiTTRr17XpzMI8e1b0ZIYrBNEvaGvbulPDPVM9j8bBbPeOojhJJ2Ncdk2elqCN6hxDxyXm0-NAWOtjQxOcEXrB8zDHTr1RQWeRud4E_Dm1BaLe2G72obXJvc85yYM4s055v0xgf6pflDeFyO5WHonxYEt6NwklSid-4YcYnjSIiYS6NPZo" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  442. &lt;/tr&gt;
  443. &lt;/tbody&gt;
  444. &lt;/table&gt;
  445. &lt;/td&gt;
  446. &lt;/tr&gt;
  447. &lt;/tbody&gt;
  448. &lt;/table&gt;
  449. &lt;/th&gt;
  450. &lt;/tr&gt;
  451. &lt;/tbody&gt;
  452. &lt;/table&gt;
  453. &lt;/td&gt;
  454. &lt;/tr&gt;
  455. &lt;/tbody&gt;
  456. &lt;/table&gt;
  457. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  458. &lt;tbody&gt;
  459. &lt;tr&gt;
  460. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  461. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  462. &lt;tbody&gt;
  463. &lt;tr&gt;
  464. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  465. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  466. &lt;tbody&gt;
  467. &lt;tr&gt;
  468. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  469. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  470. &lt;tbody&gt;
  471. &lt;tr&gt;
  472. &lt;td align="center" class="r25-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 30px; padding-top: 30px;"&gt;
  473. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  474. &lt;tbody&gt;
  475. &lt;tr&gt;
  476. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  477. &lt;/tr&gt;
  478. &lt;/tbody&gt;
  479. &lt;/table&gt;
  480. &lt;/td&gt;
  481. &lt;/tr&gt;
  482. &lt;tr&gt;
  483. &lt;td align="left" class="r17-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  484. &lt;div&gt;
  485. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;Recursive Instantiation with Qt Quick and JSON &#x2013; Factory Design Techniques, Part 1&lt;/p&gt;
  486. &lt;/div&gt;
  487. &lt;/td&gt;
  488. &lt;/tr&gt;
  489. &lt;/tbody&gt;
  490. &lt;/table&gt;
  491. &lt;/td&gt;
  492. &lt;/tr&gt;
  493. &lt;/tbody&gt;
  494. &lt;/table&gt;
  495. &lt;/th&gt;
  496. &lt;/tr&gt;
  497. &lt;/tbody&gt;
  498. &lt;/table&gt;
  499. &lt;/td&gt;
  500. &lt;/tr&gt;
  501. &lt;/tbody&gt;
  502. &lt;/table&gt;
  503. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  504. &lt;tbody&gt;
  505. &lt;tr&gt;
  506. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  507. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  508. &lt;tbody&gt;
  509. &lt;tr&gt;
  510. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  511. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  512. &lt;tbody&gt;
  513. &lt;tr&gt;
  514. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  515. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  516. &lt;tbody&gt;
  517. &lt;tr&gt;
  518. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  519. &lt;div&gt;
  520. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;by Javier O. Cordero P&#xE9;rez&lt;/p&gt;
  521. &lt;/div&gt;
  522. &lt;/td&gt;
  523. &lt;/tr&gt;
  524. &lt;tr&gt;
  525. &lt;td align="left" class="r23-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; padding-top: 15px; text-align: left;"&gt;
  526. &lt;div&gt;
  527. &lt;p style="margin: 0;"&gt;This is the first in a series of blogs Javier has written, in response to a request for an architecture for remote real time instantiation and updating of arbitrary QML components.&lt;/p&gt;
  528. &lt;p&gt;&#xA0;&lt;/p&gt;
  529. &lt;p style="margin: 0;"&gt;This entry shows how you can use a simple variation of the factory method pattern in QML for instantiating arbitrary components.&lt;/p&gt;
  530. &lt;p&gt;&#xA0;&lt;/p&gt;
  531. &lt;p style="margin: 0;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/CQnH1Rs_11VC-or5nlnbVSAhUxZtWoiczSLOfdwTNrtK3sogozTiSpj8WHaQ85xi1BQxW5v65FRohI6wIiRUqXbZVVMholzvbTWvx0UOJ23_uAjNqa2Wh3HK9SOKflN0UhB8vUV0aJZMfXxVMvxe4Yz4hCffJm4lQZIKZ8UibHO9rMycYNkVHm635X0TIp6YMV0wBH7CrDeXju5vH52QW-cGBXHgzbj6uX_--xy2u-F6bhILcF31TTteCDw" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Read the blog&lt;/a&gt;.&lt;/p&gt;
  532. &lt;/div&gt;
  533. &lt;/td&gt;
  534. &lt;/tr&gt;
  535. &lt;/tbody&gt;
  536. &lt;/table&gt;
  537. &lt;/td&gt;
  538. &lt;/tr&gt;
  539. &lt;/tbody&gt;
  540. &lt;/table&gt;
  541. &lt;/th&gt;
  542. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  543. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  544. &lt;tbody&gt;
  545. &lt;tr&gt;
  546. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  547. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  548. &lt;tbody&gt;
  549. &lt;tr&gt;
  550. &lt;td align="center" class="r7-c"&gt;
  551. &lt;table border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 189px;" width="189"&gt;
  552. &lt;tbody&gt;
  553. &lt;tr&gt;
  554. &lt;td class="r26-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 15px; padding-top: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/KQXop50xvFQWQ8rrb333EnziWATXgPiWTxohlE8DAXXIIeElPRof_iqWSAJCKTI-E-yf7qMfp4R2eCCOt5ftTcRF7pSbXggu7LvNEbfCltCtY7sQR-j1TGh37SvDwNuorJm6T394vQTp2hsxWjBK8H_RAPvHJSTxqQrgjETXZx9OhrzfNDzvllwup41nJGT0vmKtFKhWWbofVFcqDafjYy8tlMa8REbZXtpiVa8kdcgj50F7lFCAvlEu_6E" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/1525e612d8a54bd753d6b978bf185ea266ad501288253b40a1d0410d88c60aa2.png?e=mgT6CDSWKOpWj8r7jAFmPOeMMJO84MT57KEMU5rh2vz2djG_c45wQwWqdMGjDoGhB2_fMegajJTpzJ38oo8Fj9oXY2az2Rcy3AW0R9tyoiz8dNzTFT_SlLROFRn-FBAKfoUAgSJAMkIJOMMZoaruNNTex7rNapzu9FyBQI3TcNwYyVe025qKIPbtpUkLTt6_CLuftEwNcOlYx6OJgBbtULQIPgUEsSx_tzXCncmwunpbJ-g" style="display: block; width: 100%;" width="189"&gt;&lt;/a&gt;&lt;/td&gt;
  555. &lt;/tr&gt;
  556. &lt;/tbody&gt;
  557. &lt;/table&gt;
  558. &lt;/td&gt;
  559. &lt;/tr&gt;
  560. &lt;/tbody&gt;
  561. &lt;/table&gt;
  562. &lt;/td&gt;
  563. &lt;/tr&gt;
  564. &lt;/tbody&gt;
  565. &lt;/table&gt;
  566. &lt;/th&gt;
  567. &lt;/tr&gt;
  568. &lt;/tbody&gt;
  569. &lt;/table&gt;
  570. &lt;/td&gt;
  571. &lt;/tr&gt;
  572. &lt;/tbody&gt;
  573. &lt;/table&gt;
  574. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  575. &lt;tbody&gt;
  576. &lt;tr&gt;
  577. &lt;td class="r18-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  578. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  579. &lt;tbody&gt;
  580. &lt;tr&gt;
  581. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  582. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  583. &lt;tbody&gt;
  584. &lt;tr&gt;
  585. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  586. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  587. &lt;tbody&gt;
  588. &lt;tr&gt;
  589. &lt;td align="center" class="r25-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 30px; padding-top: 30px;"&gt;
  590. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  591. &lt;tbody&gt;
  592. &lt;tr&gt;
  593. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  594. &lt;/tr&gt;
  595. &lt;/tbody&gt;
  596. &lt;/table&gt;
  597. &lt;/td&gt;
  598. &lt;/tr&gt;
  599. &lt;/tbody&gt;
  600. &lt;/table&gt;
  601. &lt;/td&gt;
  602. &lt;/tr&gt;
  603. &lt;/tbody&gt;
  604. &lt;/table&gt;
  605. &lt;/th&gt;
  606. &lt;/tr&gt;
  607. &lt;/tbody&gt;
  608. &lt;/table&gt;
  609. &lt;/td&gt;
  610. &lt;/tr&gt;
  611. &lt;/tbody&gt;
  612. &lt;/table&gt;
  613. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  614. &lt;tbody&gt;
  615. &lt;tr&gt;
  616. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  617. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  618. &lt;tbody&gt;
  619. &lt;tr&gt;
  620. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  621. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  622. &lt;tbody&gt;
  623. &lt;tr&gt;
  624. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  625. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  626. &lt;tbody&gt;
  627. &lt;tr&gt;
  628. &lt;td align="left" class="r17-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  629. &lt;div&gt;
  630. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;Mastering the Embedded Update Process&lt;/p&gt;
  631. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;&lt;span style="font-size: 22px;"&gt;&#x2013; the first of our two new blogs on Embedded&lt;/span&gt;&lt;/p&gt;
  632. &lt;/div&gt;
  633. &lt;/td&gt;
  634. &lt;/tr&gt;
  635. &lt;/tbody&gt;
  636. &lt;/table&gt;
  637. &lt;/td&gt;
  638. &lt;/tr&gt;
  639. &lt;/tbody&gt;
  640. &lt;/table&gt;
  641. &lt;/th&gt;
  642. &lt;/tr&gt;
  643. &lt;/tbody&gt;
  644. &lt;/table&gt;
  645. &lt;/td&gt;
  646. &lt;/tr&gt;
  647. &lt;/tbody&gt;
  648. &lt;/table&gt;
  649. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  650. &lt;tbody&gt;
  651. &lt;tr&gt;
  652. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  653. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  654. &lt;tbody&gt;
  655. &lt;tr&gt;
  656. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  657. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  658. &lt;tbody&gt;
  659. &lt;tr&gt;
  660. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  661. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  662. &lt;tbody&gt;
  663. &lt;tr&gt;
  664. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  665. &lt;div&gt;
  666. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;by Andreas Holzammer&lt;/p&gt;
  667. &lt;/div&gt;
  668. &lt;/td&gt;
  669. &lt;/tr&gt;
  670. &lt;tr&gt;
  671. &lt;td align="left" class="r23-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; padding-top: 15px; text-align: left;"&gt;
  672. &lt;div&gt;
  673. &lt;p style="margin: 0;"&gt;The importance of updating your product after it&#x2019;s in the field cannot be overstated. Not only is it essential for customer satisfaction with feature updates and bug fixes, but also for addressing security vulnerabilities.&lt;/p&gt;
  674. &lt;p&gt;&#xA0;&lt;/p&gt;
  675. &lt;p style="margin: 0;"&gt;In this post, we&#x2019;ll look at some key considerations and methodologies for updating embedded systems.&lt;/p&gt;
  676. &lt;p&gt;&#xA0;&lt;/p&gt;
  677. &lt;p style="margin: 0;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/gl84u_qbv6ZxQCINTnoOC-zjSdS92FfBeLxP2gKZ2tUCJr31vn00XGAVy3vWbxXCKBJMhSEorpM03Xs7R55Yl2Pcxn43aOPwOcCWuZ1w8tUCE3puswoyOBG2xrklfVInp_bP3MtchUzi_JcDLsm2aBsZ7ZpggcxtoP69PW14Gm7Y3YRr2gSDMplR7X7rZTOGhy1H87yTcvGSsG4_ZplPwF2fPtzPUrsQTM8eIcqdZKajEjQ" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Read on&lt;/a&gt;.&lt;/p&gt;
  678. &lt;/div&gt;
  679. &lt;/td&gt;
  680. &lt;/tr&gt;
  681. &lt;/tbody&gt;
  682. &lt;/table&gt;
  683. &lt;/td&gt;
  684. &lt;/tr&gt;
  685. &lt;/tbody&gt;
  686. &lt;/table&gt;
  687. &lt;/th&gt;
  688. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  689. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  690. &lt;tbody&gt;
  691. &lt;tr&gt;
  692. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  693. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  694. &lt;tbody&gt;
  695. &lt;tr&gt;
  696. &lt;td align="center" class="r24-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 15px; padding-top: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/EvlP_qc1fsJgyCUMPM2P_s-saL3LzV-qHt5p9T5tinCHE70mH-VS9tyNgnbRuWZ_5_X4mCI4uFJAYfxm0fK1Lw0WRVdnSG_ph1B4w6OFExfpqypvymHdm4sgYWrWMtRmEI1hpAccLFhc9sgAWeUkJW27K5YUAqbsaC34LPDXK_0-ZjM_aPc5BkqFNuaXd-S5bLYe-JCiYMRQwbZVPFg36AnVWsDFrjcV1Hal7PDPVoSo6RU" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/930810f65dccc987ebb61f99e2f20f0d5c49de89125b17473fd5c6b61e078087.jpg?e=JdhzdYpJzLb8tWPMCCKF-TioiWILWcYrLOwwJcZmBcz3tYgJm45IwzNHfSU9NuI6C6gNugF9UC50akZO10QD-cCp2ojqu4OI82j6Q9fCFZZQzwtHKox2O6MIoDhfPiM1mE0qbNw4rV57sdnkgF5Hh5znaJqVjBO1psmhLUVEsgg0zHPOwDAXJsbHvUp92S0Fy854TWFBDjUhmNxbj5KlgY_nLfmfG4hDnin9K_L09Gprq38" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  697. &lt;/tr&gt;
  698. &lt;/tbody&gt;
  699. &lt;/table&gt;
  700. &lt;/td&gt;
  701. &lt;/tr&gt;
  702. &lt;/tbody&gt;
  703. &lt;/table&gt;
  704. &lt;/th&gt;
  705. &lt;/tr&gt;
  706. &lt;/tbody&gt;
  707. &lt;/table&gt;
  708. &lt;/td&gt;
  709. &lt;/tr&gt;
  710. &lt;/tbody&gt;
  711. &lt;/table&gt;
  712. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  713. &lt;tbody&gt;
  714. &lt;tr&gt;
  715. &lt;td class="r18-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  716. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  717. &lt;tbody&gt;
  718. &lt;tr&gt;
  719. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  720. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  721. &lt;tbody&gt;
  722. &lt;tr&gt;
  723. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  724. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  725. &lt;tbody&gt;
  726. &lt;tr&gt;
  727. &lt;td align="center" class="r25-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 30px; padding-top: 30px;"&gt;
  728. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  729. &lt;tbody&gt;
  730. &lt;tr&gt;
  731. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  732. &lt;/tr&gt;
  733. &lt;/tbody&gt;
  734. &lt;/table&gt;
  735. &lt;/td&gt;
  736. &lt;/tr&gt;
  737. &lt;/tbody&gt;
  738. &lt;/table&gt;
  739. &lt;/td&gt;
  740. &lt;/tr&gt;
  741. &lt;/tbody&gt;
  742. &lt;/table&gt;
  743. &lt;/th&gt;
  744. &lt;/tr&gt;
  745. &lt;/tbody&gt;
  746. &lt;/table&gt;
  747. &lt;/td&gt;
  748. &lt;/tr&gt;
  749. &lt;/tbody&gt;
  750. &lt;/table&gt;
  751. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  752. &lt;tbody&gt;
  753. &lt;tr&gt;
  754. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  755. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  756. &lt;tbody&gt;
  757. &lt;tr&gt;
  758. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  759. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  760. &lt;tbody&gt;
  761. &lt;tr&gt;
  762. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  763. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  764. &lt;tbody&gt;
  765. &lt;tr&gt;
  766. &lt;td align="left" class="r17-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  767. &lt;div&gt;
  768. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;&lt;strong&gt;Streamlining Strategies for Embedded Software Development&lt;/strong&gt;&lt;/p&gt;
  769. &lt;/div&gt;
  770. &lt;/td&gt;
  771. &lt;/tr&gt;
  772. &lt;/tbody&gt;
  773. &lt;/table&gt;
  774. &lt;/td&gt;
  775. &lt;/tr&gt;
  776. &lt;/tbody&gt;
  777. &lt;/table&gt;
  778. &lt;/th&gt;
  779. &lt;/tr&gt;
  780. &lt;/tbody&gt;
  781. &lt;/table&gt;
  782. &lt;/td&gt;
  783. &lt;/tr&gt;
  784. &lt;/tbody&gt;
  785. &lt;/table&gt;
  786. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  787. &lt;tbody&gt;
  788. &lt;tr&gt;
  789. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-right: 8px;"&gt;
  790. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  791. &lt;tbody&gt;
  792. &lt;tr&gt;
  793. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  794. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  795. &lt;tbody&gt;
  796. &lt;tr&gt;
  797. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  798. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  799. &lt;tbody&gt;
  800. &lt;tr&gt;
  801. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  802. &lt;div&gt;
  803. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;by Nathan Collins&lt;/p&gt;
  804. &lt;/div&gt;
  805. &lt;/td&gt;
  806. &lt;/tr&gt;
  807. &lt;tr&gt;
  808. &lt;td align="left" class="r23-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; padding-top: 15px; text-align: left;"&gt;
  809. &lt;div&gt;
  810. &lt;p style="margin: 0;"&gt;Developing embedded software is notoriously difficult &#x2013; how can we simplify the process? Fortunately, there are lots of techniques you can use daily . . .&lt;/p&gt;
  811. &lt;p&gt;&#xA0;&lt;/p&gt;
  812. &lt;p style="margin: 0;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/IF9WB4SmbqkgHXBJyT4MMmMAUwoz3Nnec7n4gFyRIt-j0I5TmHcVHf-Gi2KR-GjgVdEfqstOa2VouLjotFl7SI-n1LDCAgd76T1QAR9hFDCSjdEW4ThpiL-WfDGbYvaKSptlsFDBrQQwAo6MDND28OuDMXkxsia4v6zvxRkPYQi9CKs9Dv8bWpNX4331qU1-88W108fU38vHE5wNvDgCWaWiaQDyMYEYX6_lw5bzGWDtmS9NaojU3PwAgwu8mSIMQcceC4AJsg" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Read on&lt;/a&gt;.&lt;/p&gt;
  813. &lt;/div&gt;
  814. &lt;/td&gt;
  815. &lt;/tr&gt;
  816. &lt;/tbody&gt;
  817. &lt;/table&gt;
  818. &lt;/td&gt;
  819. &lt;/tr&gt;
  820. &lt;/tbody&gt;
  821. &lt;/table&gt;
  822. &lt;/th&gt;
  823. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  824. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  825. &lt;tbody&gt;
  826. &lt;tr&gt;
  827. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  828. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  829. &lt;tbody&gt;
  830. &lt;tr&gt;
  831. &lt;td align="center" class="r7-c"&gt;
  832. &lt;table border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 172px;" width="172"&gt;
  833. &lt;tbody&gt;
  834. &lt;tr&gt;
  835. &lt;td class="r26-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 15px; padding-top: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/V8OIFs3rCpcYODKFm8jCUgUBNo8EAzH9GjAjLuR0rGr1isJ_SSD1LD27Pisyeky2Sp24_KJevtP1mkxSkXWn3Cr35XQu7N88Z7b_fCkxha0giKtqfDG_1Zo8jBeWe_3tLCxV3aPCVVn__6VO3UHAxN2Lmp-0G6y0kzNLloTw8W2hLz_frAtSDeiyJJ3DD7CNflXu9JM4I6ZDLB4bQQxgH6qyc0fzhHWnaq53eeka5zOPeLZRrUCCOzt-w3Yik9Ja8DR4YVTs4w" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/6825d75a45e2af7e631fc8571c5f9023dc6f984b7e01daa7f4a956353a3c21a9.png?e=DWrmvgI5_x6_TIPhMyfTP3ZT0sI5EDim_NokyP5vgwbvrAxvv1VcXEXurIQex_00E67-uptb-3b7E8PQOD_nCgBmkQl3KEMJypTZJU2J5c9NClHgmbsDt2T3KV_zPgHM5ik56iBsj9e4mMGDuyrxdBxSqRvmfweyGyYhR5G-DvQ8hDsVU9yoAJO_uwB5bxzyEjbzqmzMp4FZ-4YEidQADufEH8wWxffT_VKQdt0aJp0sO78" style="display: block; width: 100%;" width="172"&gt;&lt;/a&gt;&lt;/td&gt;
  836. &lt;/tr&gt;
  837. &lt;/tbody&gt;
  838. &lt;/table&gt;
  839. &lt;/td&gt;
  840. &lt;/tr&gt;
  841. &lt;/tbody&gt;
  842. &lt;/table&gt;
  843. &lt;/td&gt;
  844. &lt;/tr&gt;
  845. &lt;/tbody&gt;
  846. &lt;/table&gt;
  847. &lt;/th&gt;
  848. &lt;/tr&gt;
  849. &lt;/tbody&gt;
  850. &lt;/table&gt;
  851. &lt;/td&gt;
  852. &lt;/tr&gt;
  853. &lt;/tbody&gt;
  854. &lt;/table&gt;
  855. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  856. &lt;tbody&gt;
  857. &lt;tr&gt;
  858. &lt;td class="r18-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  859. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  860. &lt;tbody&gt;
  861. &lt;tr&gt;
  862. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  863. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  864. &lt;tbody&gt;
  865. &lt;tr&gt;
  866. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  867. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  868. &lt;tbody&gt;
  869. &lt;tr&gt;
  870. &lt;td align="center" class="r16-c" style="padding-bottom: 30px; padding-top: 30px;"&gt;
  871. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  872. &lt;tbody&gt;
  873. &lt;tr&gt;
  874. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  875. &lt;/tr&gt;
  876. &lt;/tbody&gt;
  877. &lt;/table&gt;
  878. &lt;/td&gt;
  879. &lt;/tr&gt;
  880. &lt;/tbody&gt;
  881. &lt;/table&gt;
  882. &lt;/td&gt;
  883. &lt;/tr&gt;
  884. &lt;/tbody&gt;
  885. &lt;/table&gt;
  886. &lt;/th&gt;
  887. &lt;/tr&gt;
  888. &lt;/tbody&gt;
  889. &lt;/table&gt;
  890. &lt;/td&gt;
  891. &lt;/tr&gt;
  892. &lt;/tbody&gt;
  893. &lt;/table&gt;
  894. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  895. &lt;tbody&gt;
  896. &lt;tr&gt;
  897. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  898. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  899. &lt;tbody&gt;
  900. &lt;tr&gt;
  901. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  902. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  903. &lt;tbody&gt;
  904. &lt;tr&gt;
  905. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  906. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  907. &lt;tbody&gt;
  908. &lt;tr&gt;
  909. &lt;td align="left" class="r17-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  910. &lt;div&gt;
  911. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;Reducing Qt Devpt. Embedded Cycle Time&lt;/p&gt;
  912. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;&lt;span style="font-size: 22px;"&gt;Video series from Christoph Sterz&lt;/span&gt;&lt;/p&gt;
  913. &lt;/div&gt;
  914. &lt;/td&gt;
  915. &lt;/tr&gt;
  916. &lt;/tbody&gt;
  917. &lt;/table&gt;
  918. &lt;/td&gt;
  919. &lt;/tr&gt;
  920. &lt;/tbody&gt;
  921. &lt;/table&gt;
  922. &lt;/th&gt;
  923. &lt;/tr&gt;
  924. &lt;/tbody&gt;
  925. &lt;/table&gt;
  926. &lt;/td&gt;
  927. &lt;/tr&gt;
  928. &lt;/tbody&gt;
  929. &lt;/table&gt;
  930. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  931. &lt;tbody&gt;
  932. &lt;tr&gt;
  933. &lt;td class="r18-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  934. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  935. &lt;tbody&gt;
  936. &lt;tr&gt;
  937. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  938. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  939. &lt;tbody&gt;
  940. &lt;tr&gt;
  941. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  942. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  943. &lt;tbody&gt;
  944. &lt;tr&gt;
  945. &lt;td align="left" class="r15-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; text-align: left;"&gt;
  946. &lt;div&gt;
  947. &lt;p style="margin: 0;"&gt;Christoph Sterz is known for his ability to make the impossible possible, producing top-class results, often on limited hardware. This month he added three more videos to &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/wV0uSXc0E6-55t2r2C6jaIBgiFhnHIx-UsLLpLS61FofEin-UBiSFaz6Gk0zMLJuV7_fnYHSYyD3EkjXv5kjLR4hniHxu6D24vCypyktULk8oGCaDydh62hl3hBAOZnYSKuWByLrhqUzfFR7qFc43KLjlB8n1jGUgcCKDT0MqZtzi4FkGaKfUI8w3AL0WtO5Cl4xFrwijXLXjgcNerz5w9pSuWztx064J7RWarIvOQFw_SdZO8bArVCcbh_IZi_7nf8" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;this series&lt;/a&gt;, where he reveals some of the tricks he&#x2019;s learnt over the years that save time on embedded. Check them out.&lt;/p&gt;
  948. &lt;/div&gt;
  949. &lt;/td&gt;
  950. &lt;/tr&gt;
  951. &lt;/tbody&gt;
  952. &lt;/table&gt;
  953. &lt;/td&gt;
  954. &lt;/tr&gt;
  955. &lt;/tbody&gt;
  956. &lt;/table&gt;
  957. &lt;/th&gt;
  958. &lt;/tr&gt;
  959. &lt;/tbody&gt;
  960. &lt;/table&gt;
  961. &lt;/td&gt;
  962. &lt;/tr&gt;
  963. &lt;/tbody&gt;
  964. &lt;/table&gt;
  965. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r28-o" style="width: 100%;" width="100%"&gt;
  966. &lt;tbody&gt;
  967. &lt;tr&gt;
  968. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  969. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  970. &lt;tbody&gt;
  971. &lt;tr&gt;
  972. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="33.33%"&gt;
  973. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  974. &lt;tbody&gt;
  975. &lt;tr&gt;
  976. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  977. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  978. &lt;tbody&gt;
  979. &lt;tr&gt;
  980. &lt;td align="center" class="r7-c"&gt;
  981. &lt;table border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 161px;" width="161"&gt;
  982. &lt;tbody&gt;
  983. &lt;tr&gt;
  984. &lt;td class="r29-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-top: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/VAcJWlbbTZDIWOBBOtm6qn_EJIRUoKrnqreWCGj3EBtCyL620mk6k8M868Zbk681eyVzYs38XHcH495oOiPegtyHPwXowB79f6w_TuoGKaZm0YHR-wGB5CQ29JPENzPA9LlzrtPV4uETNmYFMoIE6EdGIMr5mGgVG3jLDqJ0vj6PHTKSmDdNPBHPlnGoewP_WMYXq1aknvl4ssWnbf4CJGg1qL-J" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/27b77d5e73f2dea7aba9a00758e560c92645b2540a021561f19f4c4a3177dc6f.png?e=7OrFBNitKWOH-TxdWpIPbb3veOxlQQoruPcR4RU5ZWQtM4eya3e0TqrhIdkVHXsuDNlZlwIpwyuF2YFCoV5WvJbOkjzUUaNx6MR259WFI-p3AwmI1sQkYTSjGIp4zkgxi1-4cVmU3K97LqwS4iCymIJlIOOd9zxsGxVAnejh2UhKpEgR4Tc5fcgZ4zAfezoNMNzr-TarVtO2YOqxNWmLCpHqeY59p1AF_1_IgtV_H4IgUyI" style="display: block; width: 100%;" width="161"&gt;&lt;/a&gt;&lt;/td&gt;
  985. &lt;/tr&gt;
  986. &lt;/tbody&gt;
  987. &lt;/table&gt;
  988. &lt;/td&gt;
  989. &lt;/tr&gt;
  990. &lt;tr&gt;
  991. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  992. &lt;div&gt;
  993. &lt;p style="margin: 0; color: #677876; font-size: 18px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/HwI4CJVg47mDY2tkhy5VKasYqn4AbPetThlZ3j5FOGP1ovTfxQ1LAylIBi87XDvIivXOhNsx5C-YVf1jdx-n0P7-sr1VJ4Cl2XTuY-mFqupvA6R85ILt0auYPz6rXpSs3yd1sQlHEJxIejZI_J7laJo1VUQxQtcELJj8UNLghP_c0i70BmscEotJQ2VPVrNAur2htpvrBXRpg2LjqZFTN7FfZUs0" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Installing GammaRay on your Embedded Target&lt;/a&gt;&lt;/p&gt;
  994. &lt;/div&gt;
  995. &lt;/td&gt;
  996. &lt;/tr&gt;
  997. &lt;tr&gt;
  998. &lt;td align="left" class="r30-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 2; padding-bottom: 15px; padding-top: 5px; text-align: left;"&gt;
  999. &lt;div&gt;
  1000. &lt;p style="margin: 0;"&gt;A 7 minute tutorial on Christoph&#x2019;s favorite debugging tool for Qt apps.&lt;/p&gt;
  1001. &lt;/div&gt;
  1002. &lt;/td&gt;
  1003. &lt;/tr&gt;
  1004. &lt;/tbody&gt;
  1005. &lt;/table&gt;
  1006. &lt;/td&gt;
  1007. &lt;/tr&gt;
  1008. &lt;/tbody&gt;
  1009. &lt;/table&gt;
  1010. &lt;/th&gt;
  1011. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="33.33%"&gt;
  1012. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1013. &lt;tbody&gt;
  1014. &lt;tr&gt;
  1015. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1016. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1017. &lt;tbody&gt;
  1018. &lt;tr&gt;
  1019. &lt;td align="center" class="r24-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 15px; padding-top: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/5hh6DyxuXAEBl92fu-XWbEZWDTYzT0SJnbYnoVmN48tERUC3sIlZZtBL7k6LmBjMMxcBwEcqNUVFIjG0QmPuiNaEwgU8vf_IWbth0QGMNFLcylIUjJvMZY2WBZXRJe9VjUekAbdv5QP0Akqo18HLyHlgacenySnAq5YXc6ap1d9fB5tHcCv0WxsXtiFF8TshcBSx_yyT_fopeoB4A4_IH4A8CZdVmGHlO-ZeKWpG" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/00250732a9e735cd2161b41f7680e00f2b9bf443ca2d1954baa366439b645f20.png?e=a29bNiCzQqg4RVFzifrxQAq5qzJE6mV_W9t2-8diBJ8LZuW-u8deC01455pFkZbUHtbgufccTvrce2GanXPFVHkLMV3ln95xLIiF8gz7Tp_faLxlvZjHc3OVpfDcqK_S5MS1K1z1JUL_ALYypYopsffD25Wri5GNgWtBXYcG4ODVVWuFnupb-kwFlrINubgm6rYh8lbxwytyj8UN7apvzHgFv6qTH2StgLa_pj9uFn5jJCg" style="display: block; width: 100%;" width="169"&gt;&lt;/a&gt;&lt;/td&gt;
  1020. &lt;/tr&gt;
  1021. &lt;tr&gt;
  1022. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1023. &lt;div&gt;
  1024. &lt;p style="margin: 0; color: #677876; font-size: 18px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/pEoXFH85hGAtZkMGY3gU9keQHf7-nodI2DZEaNlhAW3Wq11Vk2aoYo_mtmwtSmPqhBLxXFh6UnG6SjMv5abWRZKOCv6v6tiJ419DufBJLjn7H9xNYtGX2i7T18tmxFc6bf2xRpeC864nIAtqQqqAqS60mANGCS15oktTaIEmqIwM2TD-Lpkh4E1QQDLdyTJAgWvDdsMs08qGeCM5se6dcH3u1g3-b3jlijpQ3qYt" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Embedded GammaRay in Action&lt;/a&gt;&lt;/p&gt;
  1025. &lt;/div&gt;
  1026. &lt;/td&gt;
  1027. &lt;/tr&gt;
  1028. &lt;tr&gt;
  1029. &lt;td align="left" class="r30-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; padding-top: 5px; text-align: left;"&gt;
  1030. &lt;div&gt;
  1031. &lt;p style="margin: 0;"&gt;Some surprising and useful ways you didn&#x2019;t know GammaRay can help.&lt;/p&gt;
  1032. &lt;p style="margin: 0;"&gt;Find more &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/HaBbjZf9-b206l1KND2VTSapeMWWc9INq-dGGdVT4OL9Q67dDDKknGMBDrw1iELVG944EiZx1GVODieFCNv0jNN3aX-_V1qHDxEhMppF92rgEfWpiH_OXCOKKUkC7zeRuH0bobAN-eFl0dcMyUynhi3SUHJeoCQO3mgV4_yOKw0FSZG7SGgn4Zs_29AZkXnUmKnNzN4mCnQ9BmsQti2y-DsWva_TMzZv2E2hOB2TJSNzBAwrQWgfKHaxQ43QlAb-xPw" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;tutorials for GammaRay&lt;/a&gt; here.&lt;/p&gt;
  1033. &lt;/div&gt;
  1034. &lt;/td&gt;
  1035. &lt;/tr&gt;
  1036. &lt;/tbody&gt;
  1037. &lt;/table&gt;
  1038. &lt;/td&gt;
  1039. &lt;/tr&gt;
  1040. &lt;/tbody&gt;
  1041. &lt;/table&gt;
  1042. &lt;/th&gt;
  1043. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="33.33%"&gt;
  1044. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1045. &lt;tbody&gt;
  1046. &lt;tr&gt;
  1047. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1048. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1049. &lt;tbody&gt;
  1050. &lt;tr&gt;
  1051. &lt;td align="center" class="r31-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 12px; padding-top: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/G03eNPB2twQUaxvDVkmQwL7urGjbjwoBmWJZm9DJH-cNyY68vhLqLZQeV9qY_ZNtaVF0JrEkOMxYN9oiHksjymtY6Z0ERIIM4l2WUjbeXd6XIJqr2-aBdg9XW7BHzUs9F_A_Gb8Hoho1jsgBSJSnw_TsThOusKDWg8LnL7k_znB9zGp-hjU1Xs7zk-Vu81NgaqLnQSITYImREOd8E_l5wBFrQDqJ" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/76f22c80ebbce103b7e3578feb71f2bb163278fbcc6265ea344994704eb1584c.png?e=Q1FNvBdyO6NSI2Pc4f48sSbEbK3kmFr52W7C18sRf2ebrcq8ySlIO-WSbGrtmBT0J5Dqfg3tUIS_MXXnCPeIew4dP2G6cYMEsMBBxte14P2Yj6LlTq1gLce1nNa9KIvQpazMYZN6XE-jdOhns9XCEzWGV6sdmAKNIw9p8XBHpN0GeM2l46p1rKNyMqDnMXcVKFX0LNWfic-eYisYGRzb8ZlvnHnr7F0pd7pY3_VwU6O07_I" style="display: block; width: 100%;" width="169"&gt;&lt;/a&gt;&lt;/td&gt;
  1052. &lt;/tr&gt;
  1053. &lt;tr&gt;
  1054. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-top: 15px; text-align: left;"&gt;
  1055. &lt;div&gt;
  1056. &lt;p style="margin: 0; color: #677876; font-size: 18px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/g8h4k8ZG37rCbzlfYykoeRRPXCAEIhipyVeM0NA683x9vyapq1X5vCik_tRB5YVUfh9xLKj-OX89CAIhRGu6Usw9QqvYLme1hO9u4ij2UVp69KT4axXIKmDfA_iAZNFjTkav6pnrB9UcMtwdU3MpoAGb_AtzNe6bze8oT_K9MctED6w9w8Bc6V9Jk3AAPnoZC2yHhVsMD65vfcbpqOQuKXNpIGhx" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Deploy Faster!&lt;/a&gt;&lt;/p&gt;
  1057. &lt;/div&gt;
  1058. &lt;/td&gt;
  1059. &lt;/tr&gt;
  1060. &lt;tr&gt;
  1061. &lt;td align="left" class="r30-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; padding-top: 5px; text-align: left;"&gt;
  1062. &lt;div&gt;
  1063. &lt;p style="margin: 0;"&gt;Learn how to bundle your executables and much more, in this 17 minute master class from Christoph.&lt;/p&gt;
  1064. &lt;p style="margin: 0;"&gt;&lt;/p&gt;
  1065. &lt;/div&gt;
  1066. &lt;/td&gt;
  1067. &lt;/tr&gt;
  1068. &lt;/tbody&gt;
  1069. &lt;/table&gt;
  1070. &lt;/td&gt;
  1071. &lt;/tr&gt;
  1072. &lt;/tbody&gt;
  1073. &lt;/table&gt;
  1074. &lt;/th&gt;
  1075. &lt;/tr&gt;
  1076. &lt;/tbody&gt;
  1077. &lt;/table&gt;
  1078. &lt;/td&gt;
  1079. &lt;/tr&gt;
  1080. &lt;/tbody&gt;
  1081. &lt;/table&gt;
  1082. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1083. &lt;tbody&gt;
  1084. &lt;tr&gt;
  1085. &lt;td class="r18-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  1086. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1087. &lt;tbody&gt;
  1088. &lt;tr&gt;
  1089. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  1090. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1091. &lt;tbody&gt;
  1092. &lt;tr&gt;
  1093. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1094. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1095. &lt;tbody&gt;
  1096. &lt;tr&gt;
  1097. &lt;td align="center" class="r25-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 30px; padding-top: 30px;"&gt;
  1098. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  1099. &lt;tbody&gt;
  1100. &lt;tr&gt;
  1101. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  1102. &lt;/tr&gt;
  1103. &lt;/tbody&gt;
  1104. &lt;/table&gt;
  1105. &lt;/td&gt;
  1106. &lt;/tr&gt;
  1107. &lt;/tbody&gt;
  1108. &lt;/table&gt;
  1109. &lt;/td&gt;
  1110. &lt;/tr&gt;
  1111. &lt;/tbody&gt;
  1112. &lt;/table&gt;
  1113. &lt;/th&gt;
  1114. &lt;/tr&gt;
  1115. &lt;/tbody&gt;
  1116. &lt;/table&gt;
  1117. &lt;/td&gt;
  1118. &lt;/tr&gt;
  1119. &lt;/tbody&gt;
  1120. &lt;/table&gt;
  1121. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1122. &lt;tbody&gt;
  1123. &lt;tr&gt;
  1124. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  1125. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1126. &lt;tbody&gt;
  1127. &lt;tr&gt;
  1128. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  1129. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1130. &lt;tbody&gt;
  1131. &lt;tr&gt;
  1132. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1133. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1134. &lt;tbody&gt;
  1135. &lt;tr&gt;
  1136. &lt;td align="left" class="r17-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1137. &lt;div&gt;
  1138. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;Hotspot v1.5.0 released&lt;/p&gt;
  1139. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;&lt;span style="font-size: 22px;"&gt;The Linux perf GUI for Performance Analysis&lt;/span&gt;&lt;/p&gt;
  1140. &lt;/div&gt;
  1141. &lt;/td&gt;
  1142. &lt;/tr&gt;
  1143. &lt;/tbody&gt;
  1144. &lt;/table&gt;
  1145. &lt;/td&gt;
  1146. &lt;/tr&gt;
  1147. &lt;/tbody&gt;
  1148. &lt;/table&gt;
  1149. &lt;/th&gt;
  1150. &lt;/tr&gt;
  1151. &lt;/tbody&gt;
  1152. &lt;/table&gt;
  1153. &lt;/td&gt;
  1154. &lt;/tr&gt;
  1155. &lt;/tbody&gt;
  1156. &lt;/table&gt;
  1157. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1158. &lt;tbody&gt;
  1159. &lt;tr&gt;
  1160. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-right: 8px;"&gt;
  1161. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1162. &lt;tbody&gt;
  1163. &lt;tr&gt;
  1164. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1165. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1166. &lt;tbody&gt;
  1167. &lt;tr&gt;
  1168. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1169. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1170. &lt;tbody&gt;
  1171. &lt;tr&gt;
  1172. &lt;td align="left" class="r23-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; padding-top: 15px; text-align: left;"&gt;
  1173. &lt;div&gt;
  1174. &lt;p style="margin: 0;"&gt;One of KDAB&#x2019;s most successful R&amp;D projects gets a major update.&lt;/p&gt;
  1175. &lt;p&gt;&#xA0;&lt;/p&gt;
  1176. &lt;p style="margin: 0;"&gt;Hotspot v1.5.0 comes packed with a wealth of code cleanups, bug fixes and new functionality. Most notably, the disassembly view has been further improved with better searching, highlighting and faster performance.&lt;/p&gt;
  1177. &lt;p&gt;&#xA0;&lt;/p&gt;
  1178. &lt;p style="margin: 0;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/VrbIGzKtcTjVjFvBgWlP7YqUrcrD4W-8A-NknFYobo4NG_a4c6O8ca7dtoB3dSHuYbMUnk3Oy8RhfiqT3855HCGpkAJbPfVkLKBuLmQkiMPuuuEwtZgPdKB5u1Gbiy7---A3fw09VwXkKW5a9p1T0Q5GG76auBZX94JTw1THfwZ9MVG6cpnXgM6yxgp87wVn43amTUuBrQsWopPRsp9OWOO3YV0-" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Find out more&lt;/a&gt;.&lt;/p&gt;
  1179. &lt;p style="margin: 0;"&gt;Check out the &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/T33XSqE_aaje7VTn8WeR1KhR4hDvqrG-Zv11tqvCyiz0n-wWwWK87YduncWEVmETjutCH0Cm3k_RJYllrzv_nQl0gLohWC7Bfmg8QP_Pp5kKJs3NqGS2Xn7qmc5Olckj3htACPKxv3KXVAGpT9PLY2wburmE6UXLeO-278VOwXPvRBNqGf0TBt326jkhnj-22bHMyvgQ0C0V-MO_D5M93O6V0mmbEGC_gOJN7JtITh3y" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;changelog&lt;/a&gt;.&lt;/p&gt;
  1180. &lt;p style="margin: 0;"&gt;&lt;/p&gt;
  1181. &lt;/div&gt;
  1182. &lt;/td&gt;
  1183. &lt;/tr&gt;
  1184. &lt;/tbody&gt;
  1185. &lt;/table&gt;
  1186. &lt;/td&gt;
  1187. &lt;/tr&gt;
  1188. &lt;/tbody&gt;
  1189. &lt;/table&gt;
  1190. &lt;/th&gt;
  1191. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1192. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1193. &lt;tbody&gt;
  1194. &lt;tr&gt;
  1195. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1196. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1197. &lt;tbody&gt;
  1198. &lt;tr&gt;
  1199. &lt;td align="center" class="r24-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 15px; padding-top: 15px;"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/17c56a817a721136dd6f5be0ee97c2da417a068d5a06ab2650533965c33087d4.png?e=VEgritmiJ-UaJp_3gMRt81G4TmeqhrpypDXBCHijo7cVCAjPS7iTa-JcFOyCfPI4OTF-YVvkYVN7927lWYviG7JJEJKh72pSTrLdBr4T_dgifvfj9fgtFLcCbTNYCqWyOU6t6UnJsOHcDc8JsFxzT7lMPRtkE4EX_Eyn3I8pSSq8KtkK1tTreB8W133bLMju1Q476emXG5KrSXheWEHNoz52ncxaFgzeRjlc9mwjdg7nSpg" style="display: block; width: 100%;" width="266"&gt;&lt;/td&gt;
  1200. &lt;/tr&gt;
  1201. &lt;/tbody&gt;
  1202. &lt;/table&gt;
  1203. &lt;/td&gt;
  1204. &lt;/tr&gt;
  1205. &lt;/tbody&gt;
  1206. &lt;/table&gt;
  1207. &lt;/th&gt;
  1208. &lt;/tr&gt;
  1209. &lt;/tbody&gt;
  1210. &lt;/table&gt;
  1211. &lt;/td&gt;
  1212. &lt;/tr&gt;
  1213. &lt;/tbody&gt;
  1214. &lt;/table&gt;
  1215. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1216. &lt;tbody&gt;
  1217. &lt;tr&gt;
  1218. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  1219. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1220. &lt;tbody&gt;
  1221. &lt;tr&gt;
  1222. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  1223. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1224. &lt;tbody&gt;
  1225. &lt;tr&gt;
  1226. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1227. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1228. &lt;tbody&gt;
  1229. &lt;tr&gt;
  1230. &lt;td align="center" class="r25-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 30px; padding-top: 30px;"&gt;
  1231. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  1232. &lt;tbody&gt;
  1233. &lt;tr&gt;
  1234. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  1235. &lt;/tr&gt;
  1236. &lt;/tbody&gt;
  1237. &lt;/table&gt;
  1238. &lt;/td&gt;
  1239. &lt;/tr&gt;
  1240. &lt;tr&gt;
  1241. &lt;td align="left" class="r17-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1242. &lt;div&gt;
  1243. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;Qt 6.7 is released&lt;/p&gt;
  1244. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;&lt;span style="font-size: 22px;"&gt;with support from C++ 20&lt;/span&gt;&lt;/p&gt;
  1245. &lt;/div&gt;
  1246. &lt;/td&gt;
  1247. &lt;/tr&gt;
  1248. &lt;/tbody&gt;
  1249. &lt;/table&gt;
  1250. &lt;/td&gt;
  1251. &lt;/tr&gt;
  1252. &lt;/tbody&gt;
  1253. &lt;/table&gt;
  1254. &lt;/th&gt;
  1255. &lt;/tr&gt;
  1256. &lt;/tbody&gt;
  1257. &lt;/table&gt;
  1258. &lt;/td&gt;
  1259. &lt;/tr&gt;
  1260. &lt;/tbody&gt;
  1261. &lt;/table&gt;
  1262. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1263. &lt;tbody&gt;
  1264. &lt;tr&gt;
  1265. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  1266. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1267. &lt;tbody&gt;
  1268. &lt;tr&gt;
  1269. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1270. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1271. &lt;tbody&gt;
  1272. &lt;tr&gt;
  1273. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1274. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1275. &lt;tbody&gt;
  1276. &lt;tr&gt;
  1277. &lt;td align="left" class="r23-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; padding-top: 15px; text-align: left;"&gt;
  1278. &lt;div&gt;
  1279. &lt;p style="margin: 0;"&gt;Just in case you hadn&#x2019;t noticed, earlier this month Qt released its latest version, with lots of updates, big and small. Check out the details &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/mEkKeFDkbSGAV0DsedUIFhUbf1bCAbGpV9t7nsERHNWMPTbphzBYIUUwHx1ksRpjIRa_TOdiT3Qk_iOe-jpO70wXE3NHLkGySkPvtf_8l9Bk7Ylr3ZtYM4hyMhxnElqc6Vp9XQ0u1adaL2R-40r8Q-14MRtTE4aT155SD7LKwAmN4Ss_y-rKy93-ZabL1YFIATj8kqSeVgenTH0D6Xg" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;here&lt;/a&gt; or, if you want to go deeper, in the &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/HopasATe-CodVdwJi-vNawkcXuLB9NExnRx1WTNi9gxVEwccixCwdh8gcsJtNBPUBQMTKyrbQvXOXUDN25qFq0t_U4dMexpvRYCo3b2W8yAuckzgt2NGZ_3VlhV74Qo0FvuPTj0Sdg3pYdFca5VI2SE1WqeK8j8EiQecXPR06DHlxUzK0n4YHyPcWB-b9HarXaf0cLr2MYmj3bCJiMw2LI3mLKo4Hm8-tHtMHX9ltvU0GB-MUDB7evHyPdLFcJskkhNSxhziJwPAladOZ_A" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;release notes&lt;/a&gt;.&lt;/p&gt;
  1280. &lt;p&gt;&#xA0;&lt;/p&gt;
  1281. &lt;p style="margin: 0;"&gt;Way down at the bottom of that page the many folk who made this release possible are listed, including around fifteen or so from KDAB. Hats off to all of them, and thanks!&lt;/p&gt;
  1282. &lt;/div&gt;
  1283. &lt;/td&gt;
  1284. &lt;/tr&gt;
  1285. &lt;/tbody&gt;
  1286. &lt;/table&gt;
  1287. &lt;/td&gt;
  1288. &lt;/tr&gt;
  1289. &lt;/tbody&gt;
  1290. &lt;/table&gt;
  1291. &lt;/th&gt;
  1292. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1293. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1294. &lt;tbody&gt;
  1295. &lt;tr&gt;
  1296. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1297. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1298. &lt;tbody&gt;
  1299. &lt;tr&gt;
  1300. &lt;td align="center" class="r7-c"&gt;
  1301. &lt;table border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 202px;" width="202"&gt;
  1302. &lt;tbody&gt;
  1303. &lt;tr&gt;
  1304. &lt;td class="r32-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/n9naTQ_qr-GGyXlsavL4yPP6ZErCgcZ6eyV9nclA_myUQVzhLW2Rcwv2u_YDXOcOjJsVY69wSV_5vk-6GFxYBk4_ZekEKWV612045lBMi1q1OUeiN889XMKq0fmY3sohS-8RIE-Ep0yGGjeDpnewezye4oQWT1nOWDloAC8oEOtk7oU6efD1VxiitKCaAum6TKCJ_RuTTV-VJ6RghGs" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/3ac36aadc6d869e9ff8f3572574a058d822f6c775895e083f2a2eb65babb3254.png?e=s7TbV4LZuCYk3FfpCg5eXmX1XMXYiZ_LlZlfuCWiLFxZiWzHukhBejnWitoypKFILgHhoC48UxvfLAeASMhfjXw-ggWNwE3wXpRDZFS4Y_-QFJdy9KktNffZwsJQdQFJ0IL1kUoDrxw8CB1wdhBEAcHp-U01JrFBWrZjrt61AAuITfKyKyXbHjZ2nu4dNgKt1JUZ_pkXpS1kNYsU9YhIa9I9yLYIqwqIzdY-RsiYkkQJ4yc" style="display: block; width: 100%;" width="202"&gt;&lt;/a&gt;&lt;/td&gt;
  1305. &lt;/tr&gt;
  1306. &lt;/tbody&gt;
  1307. &lt;/table&gt;
  1308. &lt;/td&gt;
  1309. &lt;/tr&gt;
  1310. &lt;/tbody&gt;
  1311. &lt;/table&gt;
  1312. &lt;/td&gt;
  1313. &lt;/tr&gt;
  1314. &lt;/tbody&gt;
  1315. &lt;/table&gt;
  1316. &lt;/th&gt;
  1317. &lt;/tr&gt;
  1318. &lt;/tbody&gt;
  1319. &lt;/table&gt;
  1320. &lt;/td&gt;
  1321. &lt;/tr&gt;
  1322. &lt;/tbody&gt;
  1323. &lt;/table&gt;
  1324. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1325. &lt;tbody&gt;
  1326. &lt;tr&gt;
  1327. &lt;td class="r18-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  1328. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1329. &lt;tbody&gt;
  1330. &lt;tr&gt;
  1331. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  1332. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1333. &lt;tbody&gt;
  1334. &lt;tr&gt;
  1335. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1336. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1337. &lt;tbody&gt;
  1338. &lt;tr&gt;
  1339. &lt;td align="center" class="r25-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 30px; padding-top: 30px;"&gt;
  1340. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  1341. &lt;tbody&gt;
  1342. &lt;tr&gt;
  1343. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  1344. &lt;/tr&gt;
  1345. &lt;/tbody&gt;
  1346. &lt;/table&gt;
  1347. &lt;/td&gt;
  1348. &lt;/tr&gt;
  1349. &lt;/tbody&gt;
  1350. &lt;/table&gt;
  1351. &lt;/td&gt;
  1352. &lt;/tr&gt;
  1353. &lt;/tbody&gt;
  1354. &lt;/table&gt;
  1355. &lt;/th&gt;
  1356. &lt;/tr&gt;
  1357. &lt;/tbody&gt;
  1358. &lt;/table&gt;
  1359. &lt;/td&gt;
  1360. &lt;/tr&gt;
  1361. &lt;/tbody&gt;
  1362. &lt;/table&gt;
  1363. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1364. &lt;tbody&gt;
  1365. &lt;tr&gt;
  1366. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  1367. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1368. &lt;tbody&gt;
  1369. &lt;tr&gt;
  1370. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  1371. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1372. &lt;tbody&gt;
  1373. &lt;tr&gt;
  1374. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1375. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1376. &lt;tbody&gt;
  1377. &lt;tr&gt;
  1378. &lt;td align="left" class="r17-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1379. &lt;div&gt;
  1380. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;GCompris in India&lt;/p&gt;
  1381. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 28px;"&gt;&lt;span style="font-size: 22px;"&gt;An example of its global spread, from a contributor&#x2019;s perspective&lt;/span&gt;&lt;/p&gt;
  1382. &lt;/div&gt;
  1383. &lt;/td&gt;
  1384. &lt;/tr&gt;
  1385. &lt;/tbody&gt;
  1386. &lt;/table&gt;
  1387. &lt;/td&gt;
  1388. &lt;/tr&gt;
  1389. &lt;/tbody&gt;
  1390. &lt;/table&gt;
  1391. &lt;/th&gt;
  1392. &lt;/tr&gt;
  1393. &lt;/tbody&gt;
  1394. &lt;/table&gt;
  1395. &lt;/td&gt;
  1396. &lt;/tr&gt;
  1397. &lt;/tbody&gt;
  1398. &lt;/table&gt;
  1399. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1400. &lt;tbody&gt;
  1401. &lt;tr&gt;
  1402. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-right: 8px;"&gt;
  1403. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1404. &lt;tbody&gt;
  1405. &lt;tr&gt;
  1406. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1407. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1408. &lt;tbody&gt;
  1409. &lt;tr&gt;
  1410. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1411. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1412. &lt;tbody&gt;
  1413. &lt;tr&gt;
  1414. &lt;td align="left" class="r23-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; padding-top: 15px; text-align: left;"&gt;
  1415. &lt;div&gt;
  1416. &lt;p style="margin: 0;"&gt;The final episode in our series about this open source teaching aid, supported by &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/zdfVYIef4J0sJs2hYPGC9vlNpZELStP8JHkqv8r3uQSaLXQ4AB0BrEFXFYNAYlXBdVxB-bM1SYXTg4WXSSSUY1fJ0pO5AsWfCnCA8q-_xtJ7V9Sl1ZwIbiqoAfcznPrkaBJLc1bt6A3ToXXmVxLC1VftM2FSPO2bX1SNwCsttv8pf5HH4gg" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;KDE&lt;/a&gt;.&lt;/p&gt;
  1417. &lt;p&gt;&#xA0;&lt;/p&gt;
  1418. &lt;p style="margin: 0;"&gt;It&#x2019;s amazing how, the things these folk get up to (mostly in their spare time), can cheer you up, even on a bad hair day &lt;img alt="&#x1F609;" class="wp-smiley" src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" style="height: 1em;"&gt;&lt;/p&gt;
  1419. &lt;p&gt;&#xA0;&lt;/p&gt;
  1420. &lt;p style="margin: 0;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/F974Xv-cpUgLd92t95cdrJO_u9CsjAOTWSwHQLeUaipVujlo6Re-qC3lJotHtPmODoRQUffJc8dnAmiwgJV4-hp8Vg17QvUBjTeM6_gxq8WDV4KugdE4sRZQTQepHDyJRzcZN5MXNHALBzzDSm1YdnZRtoyxRD6w2Hz5mrnugkZ0-i1VwZf1NxEP42Yf2p7myjf-HKioRWuHtxaoEQK3q03IIoRl" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Watch the video&lt;/a&gt;.&lt;/p&gt;
  1421. &lt;/div&gt;
  1422. &lt;/td&gt;
  1423. &lt;/tr&gt;
  1424. &lt;/tbody&gt;
  1425. &lt;/table&gt;
  1426. &lt;/td&gt;
  1427. &lt;/tr&gt;
  1428. &lt;/tbody&gt;
  1429. &lt;/table&gt;
  1430. &lt;/th&gt;
  1431. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1432. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1433. &lt;tbody&gt;
  1434. &lt;tr&gt;
  1435. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1436. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1437. &lt;tbody&gt;
  1438. &lt;tr&gt;
  1439. &lt;td align="center" class="r24-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 15px; padding-top: 15px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/eC4KpYdc91ucMVqP8yXiwj6byuZTfUcrbemQo6ZTXLDyfd9nKeVPAKRXN4NmXwv5ShI7upwVhrSfQ-NBumL0gTGVRXOKMUjGwBuWG6FjEjq6mikQAtAjB-xAHvWqsCwhnsbi1NXxx5ftvED_HOfIkxVQsjf8CYdGw1ftqX1lMNoaGGtWiDOhNPdO5sTnAEn62IQ5-eO5OFoWSpJgRULlK9tppvDH" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/75bdb3d83660930e90362b6a14ae2b7402f9ffd7df85ee87981263efcf96f57d.png?e=IsH4H2hk1upZk3i0_HubRKz2R2ZLgsgUpkmw_18zJO_wIFr92p0e_6kmFFZTa7VEenU7h1xE2QnMl0llo8PvJAZaCoQ6yVJ1fnFoaRRq5LJlK2f6o6T4qjs3eODHkiqCmmGxc0hH2_796thfklhurhlrELoGBvWNPqwHk6FnlN13JS7g9rVoXw16txraNPlGXz5pQ0On1Tsja-Oh2QtIKXjjLOYD-hkq2sALmLWlvKvOtaw" style="display: block; width: 100%;" width="266"&gt;&lt;/a&gt;&lt;/td&gt;
  1440. &lt;/tr&gt;
  1441. &lt;/tbody&gt;
  1442. &lt;/table&gt;
  1443. &lt;/td&gt;
  1444. &lt;/tr&gt;
  1445. &lt;/tbody&gt;
  1446. &lt;/table&gt;
  1447. &lt;/th&gt;
  1448. &lt;/tr&gt;
  1449. &lt;/tbody&gt;
  1450. &lt;/table&gt;
  1451. &lt;/td&gt;
  1452. &lt;/tr&gt;
  1453. &lt;/tbody&gt;
  1454. &lt;/table&gt;
  1455. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1456. &lt;tbody&gt;
  1457. &lt;tr&gt;
  1458. &lt;td class="r33-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  1459. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1460. &lt;tbody&gt;
  1461. &lt;tr&gt;
  1462. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  1463. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1464. &lt;tbody&gt;
  1465. &lt;tr&gt;
  1466. &lt;td class="r19-i" style="padding-left: 10px; padding-right: 10px;" valign="top"&gt;
  1467. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1468. &lt;tbody&gt;
  1469. &lt;tr&gt;
  1470. &lt;td align="center" class="r25-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 30px; padding-top: 30px;"&gt;
  1471. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  1472. &lt;tbody&gt;
  1473. &lt;tr&gt;
  1474. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  1475. &lt;/tr&gt;
  1476. &lt;/tbody&gt;
  1477. &lt;/table&gt;
  1478. &lt;/td&gt;
  1479. &lt;/tr&gt;
  1480. &lt;tr&gt;
  1481. &lt;td align="left" class="r34-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 2; padding-top: 15px; text-align: left;"&gt;
  1482. &lt;div&gt;
  1483. &lt;h2 class="default-heading2" style="margin: 0; color: #222; font-family: Open Sans,Arial; font-size: 28px; direction: ltr;"&gt;Events&lt;/h2&gt;
  1484. &lt;/div&gt;
  1485. &lt;/td&gt;
  1486. &lt;/tr&gt;
  1487. &lt;tr&gt;
  1488. &lt;td align="left" class="r20-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 2; padding-top: 15px; text-align: left;"&gt;
  1489. &lt;div&gt;
  1490. &lt;p style="margin: 0; direction: ltr;"&gt;Last month&#x2019;s &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/OtlJ3zE3VPbphlTafvpByylsvN_c0f_JgMBq6gITwnyhxvH3bx8ZUYZXeuI6SA8SNbVDsnNj6VJKWVFhw5N2-Fvb2Z2a0eIKz0Rt_Q2JjfljIwUqrY1nc3bDwCEwX75L605ykw1Ma9uSj6bpE2lfbpWqB4jbG_br_3-pqirvg0Hz1_8tS3l2A23Q7uN90WC92R8n5TzW" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Embedded World 2024&lt;/a&gt; in Nuremberg, Germany, went amazingly well, with attendee numbers up to pre-pandemic level and lots of visitors to KDAB&#x2019;s booth.&lt;/p&gt;
  1491. &lt;/div&gt;
  1492. &lt;/td&gt;
  1493. &lt;/tr&gt;
  1494. &lt;/tbody&gt;
  1495. &lt;/table&gt;
  1496. &lt;/td&gt;
  1497. &lt;/tr&gt;
  1498. &lt;/tbody&gt;
  1499. &lt;/table&gt;
  1500. &lt;/th&gt;
  1501. &lt;/tr&gt;
  1502. &lt;/tbody&gt;
  1503. &lt;/table&gt;
  1504. &lt;/td&gt;
  1505. &lt;/tr&gt;
  1506. &lt;/tbody&gt;
  1507. &lt;/table&gt;
  1508. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1509. &lt;tbody&gt;
  1510. &lt;tr&gt;
  1511. &lt;td class="r11-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px; padding-top: 20px;"&gt;
  1512. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1513. &lt;tbody&gt;
  1514. &lt;tr&gt;
  1515. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1516. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1517. &lt;tbody&gt;
  1518. &lt;tr&gt;
  1519. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1520. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1521. &lt;tbody&gt;
  1522. &lt;tr&gt;
  1523. &lt;td align="left" class="r15-c nl2go-default-textstyle" style="line-height: 2; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 15px; text-align: left;"&gt;
  1524. &lt;div&gt;
  1525. &lt;p style="margin: 0;"&gt;Check out the 5 on-site videos about &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/QxdqiKO9kEOdCOZhi7h-RvU0d3BKnHMMW66xvDl2V7EQs1lzOwK9msF71kGs7zn7oMj1YODRYc8JL11AG0g33c4Jk9uKMREcyoh_7eQJh5XEMuAc_C3IHYc_d0HUU0yGJmZz6c2SX-j7ky_QGeJMch_OBD7NpwKCquZKtNuQYh9cWZkWoW5a-0IWo4AM2cQsgmA-wNMzLAZ3-8rkqjTXzZCsI7B8-0tekj-b_TsYTjc60CZCd8oA8hYDNMoBcInVdLs" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;some of the demos&lt;/a&gt; we had on display &#x2013;&gt;.&lt;/p&gt;
  1526. &lt;p&gt;&#xA0;&lt;/p&gt;
  1527. &lt;p style="margin: 0;"&gt;More about &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/jKNYfdXY0pnb1cSBn9OKdVCY-Zy1sqKJSsBUONb_rJ7Q3hoIron00Tj1HXLgxjeSxFktFohdoRQufD-Hpyo1f5Dcvse3KNrzTkasmBPoPSC0svWYffBilHh8OaB5Avhk9DV230HLM3bXrHDUX6y1kAXu6dRrKYI6_wzha2Rin38OwO-2qnLRSn72TwNtz2Mv4zfq7mQKI15DEGaqegGNMPxqpTfKKyxXeQ" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;our presence at Embedded World&lt;/a&gt;. We&#x2019;ll be back next year!&lt;/p&gt;
  1528. &lt;p&gt;&#xA0;&lt;/p&gt;
  1529. &lt;p style="margin: 0;"&gt;A selection of events to come in 2024 follows.&lt;/p&gt;
  1530. &lt;/div&gt;
  1531. &lt;/td&gt;
  1532. &lt;/tr&gt;
  1533. &lt;/tbody&gt;
  1534. &lt;/table&gt;
  1535. &lt;/td&gt;
  1536. &lt;/tr&gt;
  1537. &lt;/tbody&gt;
  1538. &lt;/table&gt;
  1539. &lt;/th&gt;
  1540. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1541. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1542. &lt;tbody&gt;
  1543. &lt;tr&gt;
  1544. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1545. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1546. &lt;tbody&gt;
  1547. &lt;tr&gt;
  1548. &lt;td align="center" class="r7-c"&gt;
  1549. &lt;table border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 229px;" width="229"&gt;
  1550. &lt;tbody&gt;
  1551. &lt;tr&gt;
  1552. &lt;td class="r35-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-bottom: 15px; padding-top: 10px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/2xdq2h3aovHLYqeCmVj8CKI1dJJjGpJZNMiyfrvRRiI75CfLajwp082MSl8mghwUZlJaxCv-zCOKhU2bxbqkW2uSQQB8DOVtYs9qPT_giSC1m0L0V0XG1Yd6ACxvnzQygwIglzYdq8SWZF_Jc2IX69M5__jLEXicAQzoMB29Gx3PiIyu-6-9JS1tz8HKGoJqPhBFOFHa6ab6EKEV_qucYl997Bj3ndpBz5--nQL5FN-IZjzCXy9ZIZJAqS3Vjqike9g" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/e062def20432e2cb609878c4d21418aa924df79b91f32068c05f5b5305f1f643.png?e=6ippS7ZEl6KtBTllxe3uNlwVJ2IdFo9Wl8B0o01BqB9WXpjTewQqFG6Mr31h27RlH6s2Nz4m-pcNrLnRcXkXsJWJXX0Dul_oNXLbS_0XbSxkQhR7K9t3lC0kHqKeTUkt0j0V7Psa49XS_44Jh3r8OThdOp_ulTZdBa5OTxp8ER25cqsEEfl1Q28m1ufYKqlGdl4DBRpckFdMpw7GZ_JvmREtVLazfm44e_ZNsmhuILg2oXI" style="display: block; width: 100%;" width="229"&gt;&lt;/a&gt;&lt;/td&gt;
  1553. &lt;/tr&gt;
  1554. &lt;/tbody&gt;
  1555. &lt;/table&gt;
  1556. &lt;/td&gt;
  1557. &lt;/tr&gt;
  1558. &lt;/tbody&gt;
  1559. &lt;/table&gt;
  1560. &lt;/td&gt;
  1561. &lt;/tr&gt;
  1562. &lt;/tbody&gt;
  1563. &lt;/table&gt;
  1564. &lt;/th&gt;
  1565. &lt;/tr&gt;
  1566. &lt;/tbody&gt;
  1567. &lt;/table&gt;
  1568. &lt;/td&gt;
  1569. &lt;/tr&gt;
  1570. &lt;/tbody&gt;
  1571. &lt;/table&gt;
  1572. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r36-o" style="width: 100%;" width="100%"&gt;
  1573. &lt;tbody&gt;
  1574. &lt;tr&gt;
  1575. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px;"&gt;
  1576. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1577. &lt;tbody&gt;
  1578. &lt;tr&gt;
  1579. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1580. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1581. &lt;tbody&gt;
  1582. &lt;tr&gt;
  1583. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1584. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1585. &lt;tbody&gt;
  1586. &lt;tr&gt;
  1587. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1588. &lt;div&gt;
  1589. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/edztUVyvbtveNOCDhqdPw1f8F7ktB5fNyDWJhtlczey8UvR-Lb672YVBcdBd3THdhfWaDuBqKma3sCFsGOmfeASMIvw8EmE6xlLgpCkkBRywUMcJUvbshadl07ZpWFiBGAxndt2mPeXCPTzWTBETDT1d2KzvK1RGvCwyJPQZK7yF07warr_s_ZP3CUTZYA" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;span style="font-size: 18px;"&gt;Oxidize&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 18px;"&gt;, 05/28-30&lt;/span&gt;&lt;/p&gt;
  1590. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;span style="font-size: 16px;"&gt;Berlin, Germany&lt;/span&gt;&lt;/p&gt;
  1591. &lt;/div&gt;
  1592. &lt;/td&gt;
  1593. &lt;/tr&gt;
  1594. &lt;tr&gt;
  1595. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1596. &lt;div&gt;
  1597. &lt;p style="margin: 0;"&gt;&#x201C;&lt;strong&gt;Two day of applied insights from Rust innovators&lt;/strong&gt;&#x201C;&lt;/p&gt;
  1598. &lt;p style="margin: 0;"&gt;We&#x2019;re co-hosting, with Ferrous Systems and Slint. Come and talk to us about C++ and Rust.&lt;/p&gt;
  1599. &lt;p&gt;&#xA0;&lt;/p&gt;
  1600. &lt;p style="margin: 0;"&gt;With workshops on May 28th, and a talks program on May 29th-30th that includes &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/fcBgZUn3TyPpvTgzgDopcUvzU-HMNr6mQoZs4nxbDe9wc3mihvotmNzlHIcqJed0Vqq5eM52VIKi9E81dBPiC4SJkEwfr5bCGWUbYIrad7ZMBelnhVFWcU4Cj5XrS7muXbafbuSuiYMTPTahHoHWA67-r90I4VqAmbknyFAXGfUIy4-nfzvZ5z83Sdmb8gKHRbRIctl1NncFIKIUSDtX-Lc45OvP1wjVh-itvak" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Building an LLM pre-training data pipeline in Rust at Aleph Alpha&lt;/a&gt;, you don&#x2019;t want to miss this one.&lt;/p&gt;
  1601. &lt;p&gt;&#xA0;&lt;/p&gt;
  1602. &lt;p style="margin: 0;"&gt;Check out &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/mILu84V3Ujgd76ZmgXi8CVJWjMG2pixS7DVnIYTXP2Ft5WN3hzAmJbTCc8YQBkzlxk9v1HLUixi9wPCY2dBeTSlTYwnwqlIYsfarD5xmjSA0eHq8Iq4E9wVaFM5hloxXqLnvXVASF3BIH_zfdWoLM-3192AGkCs5z5yxsjJQpje4XYtFQa-Sg1n0Nz6Kbw" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;the program&lt;/a&gt; and &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/v-H9nlOMPYtOlkfc0qOanN2E8tQduDIciI43HTHcZ4KNWYAozPuBatO3OpSK2-JxDYJoAfxP6uGvLPRoSPjcgwODsbS7N3B2EOoJu8LzN8Mh-iXwJVno-eA-phtfzkai-dXvuaFHlVr83DL5XnXKw8D0s5HQyESTQ1SQrv67xSRiCK6kn5jB_oI1i7asBA" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;sign up&lt;/a&gt;!&lt;/p&gt;
  1603. &lt;/div&gt;
  1604. &lt;/td&gt;
  1605. &lt;/tr&gt;
  1606. &lt;/tbody&gt;
  1607. &lt;/table&gt;
  1608. &lt;/td&gt;
  1609. &lt;/tr&gt;
  1610. &lt;/tbody&gt;
  1611. &lt;/table&gt;
  1612. &lt;/th&gt;
  1613. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1614. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1615. &lt;tbody&gt;
  1616. &lt;tr&gt;
  1617. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1618. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1619. &lt;tbody&gt;
  1620. &lt;tr&gt;
  1621. &lt;td align="center" class="r37-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-top: 28px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/cBx72RvXEZ4QwbbF4yvg9dkhHrFd6CCUQyWifZSPsuANgsdRYCUUrncB1JpPWcEvjtRJzH0Z5yUU5C-sRZyMNTm9GJJ48B48FWTmT7Acf71sQ2eSoHsIRylZW5Q5uULTql7xyBhDbwt-RnGyg1_iJ-TDO0vngfSIud5YOlddY6JXOwWSCUPVr65nl1yobQ" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/7fb61a083b014b01981c7bb721ec4e127bb5dcbf1eb29c5ee098da1a611a5fc5.png?e=7W4XJ5RSU0wf74mbasoxZ31Y-kjWSiIeiTXPna88lJKKuvIWIwi6diHbjKxWv_zhtWdtwSghSaAZC98x1S89cOHIidAyneBkzFJ4wcDa4HkmOBUVHBKe-lMy5ZniWcugMeVgEgZ5NMVu1atGmtgVeVouUCShzXA9rOqgjD1Q7Z-uIGfWGAaT_16rBqjjbRjAnZAewvT9Mrx2ymK5NYNpsO1HPccNOIYZu5rRVwRKjT0jGA0" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  1622. &lt;/tr&gt;
  1623. &lt;/tbody&gt;
  1624. &lt;/table&gt;
  1625. &lt;/td&gt;
  1626. &lt;/tr&gt;
  1627. &lt;/tbody&gt;
  1628. &lt;/table&gt;
  1629. &lt;/th&gt;
  1630. &lt;/tr&gt;
  1631. &lt;/tbody&gt;
  1632. &lt;/table&gt;
  1633. &lt;/td&gt;
  1634. &lt;/tr&gt;
  1635. &lt;/tbody&gt;
  1636. &lt;/table&gt;
  1637. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r36-o" style="width: 100%;" width="100%"&gt;
  1638. &lt;tbody&gt;
  1639. &lt;tr&gt;
  1640. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px;"&gt;
  1641. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1642. &lt;tbody&gt;
  1643. &lt;tr&gt;
  1644. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1645. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1646. &lt;tbody&gt;
  1647. &lt;tr&gt;
  1648. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1649. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1650. &lt;tbody&gt;
  1651. &lt;tr&gt;
  1652. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1653. &lt;div&gt;
  1654. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/OumDmSd2GWF5p12NxrXyXpejwl1hGKrGMC6j32DXzm0tq8RhfSxC2_HHJf3dv5uGU7_IrOHmRuy9SrH80gMTIc1srETfeuc-WMAp2sI0PaNdR7fyss8F-btuYwMjooqWJuAh68fmy_JzqwWQPw-53vC5O745WB-uLw5P7uxS0Ynx6n7t3RtknMXARizp" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;span style="font-size: 18px;"&gt;FlutterCon&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 18px;"&gt;, 07/3-5&lt;/span&gt;&lt;/p&gt;
  1655. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;span style="font-size: 16px;"&gt;Berlin, Germany&lt;/span&gt;&lt;/p&gt;
  1656. &lt;/div&gt;
  1657. &lt;/td&gt;
  1658. &lt;/tr&gt;
  1659. &lt;tr&gt;
  1660. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1661. &lt;div&gt;
  1662. &lt;p style="margin: 0;"&gt;We&#x2019;re silver sponsors and will be exhibiting and running a workshop. Speakers TBA after May 1st. Save the dates!&lt;/p&gt;
  1663. &lt;/div&gt;
  1664. &lt;/td&gt;
  1665. &lt;/tr&gt;
  1666. &lt;/tbody&gt;
  1667. &lt;/table&gt;
  1668. &lt;/td&gt;
  1669. &lt;/tr&gt;
  1670. &lt;/tbody&gt;
  1671. &lt;/table&gt;
  1672. &lt;/th&gt;
  1673. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1674. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1675. &lt;tbody&gt;
  1676. &lt;tr&gt;
  1677. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1678. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1679. &lt;tbody&gt;
  1680. &lt;tr&gt;
  1681. &lt;td align="center" class="r37-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-top: 28px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/G8VXdbT5sdC4LmgC0-0k81_c4UqmOqtHpeniaQu1x077qgMrkpFxsrJlxv7iMv_s9rIuRmwIHIaacvNi55mtifNHyi4gbPNWInERM355ygs-6qEGYEA8AKJ8TSqz8POGCQ-PpUvm-AXyYUK3x95RqzRVz6kXtoSlqQz49auBNr2Rzw29v3nCT2c86VXk" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/6e5f8482bf9577f3c3dbfdf20383cd38c5b2e18f76eb2b5a374ae77cfb6f9236.png?e=FFwuiTZZNEhXbR0hNq_CzlVptxuJm08pZ_j3vX0Z6GT-Bo8Ab9tYv-UxdboIaBGymt85WH4znx9_DaO3XcbgsNipqoBLxykoTLc_uWJNKfm3uZBUXzgCdpP4MKzSxfPH4-glRzxYRNilFIyEVtbXBH6ve5MpQujLvVsTs1RCPzz5exDRyPPrirJCdVyjSQUhP0vKic2knjfAk0Tzs2IYBrCJOWsgDi_eawj2XaFothwUfYI" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  1682. &lt;/tr&gt;
  1683. &lt;/tbody&gt;
  1684. &lt;/table&gt;
  1685. &lt;/td&gt;
  1686. &lt;/tr&gt;
  1687. &lt;/tbody&gt;
  1688. &lt;/table&gt;
  1689. &lt;/th&gt;
  1690. &lt;/tr&gt;
  1691. &lt;/tbody&gt;
  1692. &lt;/table&gt;
  1693. &lt;/td&gt;
  1694. &lt;/tr&gt;
  1695. &lt;/tbody&gt;
  1696. &lt;/table&gt;
  1697. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1698. &lt;tbody&gt;
  1699. &lt;tr&gt;
  1700. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px;"&gt;
  1701. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1702. &lt;tbody&gt;
  1703. &lt;tr&gt;
  1704. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1705. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1706. &lt;tbody&gt;
  1707. &lt;tr&gt;
  1708. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1709. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1710. &lt;tbody&gt;
  1711. &lt;tr&gt;
  1712. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1713. &lt;div&gt;
  1714. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/o_ujTuUPSYKce7rEn0JSQ7c8AeSzxgf7JNNx1nB412YdOfTIMV_om_kpMll10G_BW_k20CxgKVIrRZ8norF7J_N7pzckzadJKSlWU1C7Oel4O4lHk-pG32tJdWJTYd9_n339OHepsxirv2keGRrJ_Dv6Lt0tmKc4x7jTb-Ta-ph1NWjjLGu3vZ0ZTOwc260NSg" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;span style="font-size: 18px;"&gt;SIGGRAPH&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 18px;"&gt;, 07/28-08/01&lt;/span&gt;&lt;/p&gt;
  1715. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;span style="font-size: 16px;"&gt;Denver, USA&lt;/span&gt;&lt;/p&gt;
  1716. &lt;/div&gt;
  1717. &lt;/td&gt;
  1718. &lt;/tr&gt;
  1719. &lt;tr&gt;
  1720. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1721. &lt;div&gt;
  1722. &lt;p style="margin: 0;"&gt;Registration is now open! &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/X7b81d30GrzbNrI5C8KRrW2gU8oD74etE5x3EvOB2cs1CqpsqPazSFQLqUU35O5OoefmvEvrW8lGBH-MZCka2vGX8JD0qn4QRjW4KbjCh4GbKAV60hxoDzEGPqztnljn8bLd2ZnHLvcp_UV-tFa-ovoG2RXbo-Ukd9pCnZPZTmAd5VX568ogbu1Cfym1wjM3-lYOaOkC2nk4npcLW237tknv8VRrgTq1pdfHcZSEPNw-2-c" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Check out the options and register&lt;/a&gt;&lt;a rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;.&lt;/a&gt; Best rates if you register by Friday, 17th May.&lt;/p&gt;
  1723. &lt;/div&gt;
  1724. &lt;/td&gt;
  1725. &lt;/tr&gt;
  1726. &lt;/tbody&gt;
  1727. &lt;/table&gt;
  1728. &lt;/td&gt;
  1729. &lt;/tr&gt;
  1730. &lt;/tbody&gt;
  1731. &lt;/table&gt;
  1732. &lt;/th&gt;
  1733. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1734. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1735. &lt;tbody&gt;
  1736. &lt;tr&gt;
  1737. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1738. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1739. &lt;tbody&gt;
  1740. &lt;tr&gt;
  1741. &lt;td align="center" class="r37-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-top: 28px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/F0lonb9bD5T20OsNd-9ZUMaI2RP2bX2NLRt-JgrubMiHW-0zVtc0jhVH9ErN8jrOCqny-cC69kBpmop9X26AJGdP-oZY_qjtL58qrrRBynM-b_sVa3ygtjZmD_zPR3_7-tYyE0vPTizJQAm_WKy1IqAUu91KzjzRuzQgSlfkzOmI9nEBMFWJbI8HQQN3k3dkig" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/424625e6e0b5e0401c625e02e3f8eedf807eba5cfd9799b6ce85fd7722d80cca.png?e=9hIutHbKq9oXDlZ1afONMEe8Qb2iqn55XtEcx2es72URltpa8seUD25Zgx5YYRKebMmfJys8jn1qmPTjfGPYuUgro5HDpB9BJQsF4p57hlRHgG1j-pAj4ywgOcbH8F_X5Cajjf-OyFtPg9EleXH-jJcFN48tiaMPxuWe85NmsELD0ilLCmv22oaEGJFqPtEY1uIGKn9MOUGQBZ6o6JlDkbhCNx_dCxDEOJOfjwyo1_C3Cp0" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  1742. &lt;/tr&gt;
  1743. &lt;/tbody&gt;
  1744. &lt;/table&gt;
  1745. &lt;/td&gt;
  1746. &lt;/tr&gt;
  1747. &lt;/tbody&gt;
  1748. &lt;/table&gt;
  1749. &lt;/th&gt;
  1750. &lt;/tr&gt;
  1751. &lt;/tbody&gt;
  1752. &lt;/table&gt;
  1753. &lt;/td&gt;
  1754. &lt;/tr&gt;
  1755. &lt;/tbody&gt;
  1756. &lt;/table&gt;
  1757. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1758. &lt;tbody&gt;
  1759. &lt;tr&gt;
  1760. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px;"&gt;
  1761. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1762. &lt;tbody&gt;
  1763. &lt;tr&gt;
  1764. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1765. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1766. &lt;tbody&gt;
  1767. &lt;tr&gt;
  1768. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1769. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1770. &lt;tbody&gt;
  1771. &lt;tr&gt;
  1772. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1773. &lt;div&gt;
  1774. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/0XzKP1VODORyABZkxsPDmRtaCTIhL7mRoujB8mEC1Wh2_FglA78dnTNJhevdV0df7P-BrIOnkYYUfWjD4a80u34URX20_fkMOSATMbyuwOgsoL1hJvIi_y49bDsu0uN2DjIPt-_v3W2_X53EeVb4lnItrp-1OCXM5dbnpX8ctTxSWx7Ygd7PModJmNRPok3PEoyGGIIjSCLCkGbfawrPO-DbkfGiyywBjDbN" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;span style="font-size: 18px;"&gt;Qt Contributor Summit&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 18px;"&gt;, 09/5-6&lt;/span&gt;&lt;/p&gt;
  1775. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;span style="font-size: 16px;"&gt;W&#xFC;rzburg, Germany&lt;/span&gt;&lt;/p&gt;
  1776. &lt;/div&gt;
  1777. &lt;/td&gt;
  1778. &lt;/tr&gt;
  1779. &lt;tr&gt;
  1780. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1781. &lt;div&gt;
  1782. &lt;p style="margin: 0;"&gt;&lt;span style="color: #27f00a;"&gt;&lt;strong&gt;Attention Qt Developers!&lt;/strong&gt;&lt;/span&gt; This event is now back-to-back with KDE Akademy in the same town. Save the dates!!&lt;/p&gt;
  1783. &lt;/div&gt;
  1784. &lt;/td&gt;
  1785. &lt;/tr&gt;
  1786. &lt;/tbody&gt;
  1787. &lt;/table&gt;
  1788. &lt;/td&gt;
  1789. &lt;/tr&gt;
  1790. &lt;/tbody&gt;
  1791. &lt;/table&gt;
  1792. &lt;/th&gt;
  1793. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1794. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1795. &lt;tbody&gt;
  1796. &lt;tr&gt;
  1797. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1798. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1799. &lt;tbody&gt;
  1800. &lt;tr&gt;
  1801. &lt;td align="center" class="r37-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-top: 28px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/o3erbI9Uas0nC3qndUkKJOWEuA-7JQBtJ-V4BP5SQ-QS8gSgx0ElJGn5wJa3RhsnM2fWOPCzlAoX0u5zY1woeFhMyGdNio0ecAJdw3OgKKZJDmgTdUpwR4928fg4ifwhrVy_nS3rJy-svYtt2QaFVTQRn1h1I832OKgYGxZsD4MXd6J16TMVgSwMC03Q9kJYMFROzQ4Zglwi_7ivBi9YK7LuhrPCcEd2I7hx" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/d922ae83011ca0af2b7abeca9c763c0db04bb8861fe8a0796934f8f7e9dde5f0.png?e=I8_OQoDYVu-MbgWYLoKigv6VfkJHc-T6nAh5Mxdy4yikvOdlzScd3ytJKwuNWZ5ytSq5kv_BeHIAEB1Lyc2LY_wniIz-W1Gn-nUuZb0ip7pfiajL3SxqOlHHFRGH1kpt2WzhTF4W9QgNa2cruwhHFPw4pSw_SU93k2h9klAEDalWNWPnZFiUMzJlXC4THA4pcnHsFX4-u9Dql8DsVjES_qqV58L1x3guHnxwP0e4akcsvrM" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  1802. &lt;/tr&gt;
  1803. &lt;/tbody&gt;
  1804. &lt;/table&gt;
  1805. &lt;/td&gt;
  1806. &lt;/tr&gt;
  1807. &lt;/tbody&gt;
  1808. &lt;/table&gt;
  1809. &lt;/th&gt;
  1810. &lt;/tr&gt;
  1811. &lt;/tbody&gt;
  1812. &lt;/table&gt;
  1813. &lt;/td&gt;
  1814. &lt;/tr&gt;
  1815. &lt;/tbody&gt;
  1816. &lt;/table&gt;
  1817. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1818. &lt;tbody&gt;
  1819. &lt;tr&gt;
  1820. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px;"&gt;
  1821. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1822. &lt;tbody&gt;
  1823. &lt;tr&gt;
  1824. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1825. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1826. &lt;tbody&gt;
  1827. &lt;tr&gt;
  1828. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1829. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1830. &lt;tbody&gt;
  1831. &lt;tr&gt;
  1832. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1833. &lt;div&gt;
  1834. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/5xdbeIHRIoapSqkZG1mX_AEAQOQdRHoccgU8NAjGAFj5yiTilpAbQaEHhwsOa_o9EQmDnAQUkku5XBuNyfJq6Wun4o9zIz8fSVfA2RjBavo1shzUBsuVClulKUnqb3layvITKlN-ShjKnfnWz_D6SMI035JfY9epSMH6Xz5Y94vzzwOPz9YynCUMHH7LLkAwD5sRDGU" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;span style="font-size: 18px;"&gt;KDE Akademy&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 18px;"&gt;, 09/7-12&lt;/span&gt;&lt;/p&gt;
  1835. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;span style="font-size: 16px;"&gt;W&#xFC;rzburg, Germany&lt;/span&gt;&lt;/p&gt;
  1836. &lt;/div&gt;
  1837. &lt;/td&gt;
  1838. &lt;/tr&gt;
  1839. &lt;tr&gt;
  1840. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1841. &lt;div&gt;
  1842. &lt;p style="margin: 0;"&gt;The call for proposals is out for talks on Sept 7th and 8th. &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/lF5VzLRnPCd49JSq6C050ntctlFKUgFbReQs571Vq_IpkvF4LTJJoRHw97f7ifloSkiHQpBjgefGQmDukMbc2XSqvh4endL_e-sxhonDlyLUD529FGFUSWXVpPt-HqEyggr3fxr-ioc32t5I9Y43PuPxPhz-1KOWL89cSFU3KAS2LNtz11QoGq53IHS57fqq5JSfHyr_cFH3r5E" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;Submit a talk&lt;/a&gt;!&lt;/p&gt;
  1843. &lt;/div&gt;
  1844. &lt;/td&gt;
  1845. &lt;/tr&gt;
  1846. &lt;/tbody&gt;
  1847. &lt;/table&gt;
  1848. &lt;/td&gt;
  1849. &lt;/tr&gt;
  1850. &lt;/tbody&gt;
  1851. &lt;/table&gt;
  1852. &lt;/th&gt;
  1853. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1854. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1855. &lt;tbody&gt;
  1856. &lt;tr&gt;
  1857. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1858. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1859. &lt;tbody&gt;
  1860. &lt;tr&gt;
  1861. &lt;td align="center" class="r37-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-top: 28px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/ja06ng4_vVBmuk21k6iQjHNb5Jh_7LwM83SaPPO4apajk9PRwHZu-ZQ0p-3GfB7Wthy7t1Kq4ZdXazTa6J5mS9LIV2FHX3zpEMhW5ZjBLQ1DPpLLSKifo-8BCmLoP30f10fZ28u2hMyIuw-MDQFtjVu22KzOeYs63lMobyav0seHx1oiQhrhG_uRwKcEfZlWrQ7gdD8" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/be552a158203cd963add24b791bcd3e301bd340d797be74165e1f827ef661413.png?e=3qI9ddJQlYxYEj0cIOxK7COFFEsArB0wTZzjbRtKpUsdGIQck2pROhh3WEooXNVMlPt4EZs_31EzmNG8FrXroShSdT4LxwmRjLCZYS-lTtt2IIiUVmEbtfCQJR2QjtAhO2Uz4QUVjHnr76evUn5C6jIlq6Qll-dmzyiPs6olQjJplOJbn737LkZefLXYSR9f83bivPmvnDthJ0cGYkqQijP6P0V6YHzbOER46OUOr2hxxQ8" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  1862. &lt;/tr&gt;
  1863. &lt;/tbody&gt;
  1864. &lt;/table&gt;
  1865. &lt;/td&gt;
  1866. &lt;/tr&gt;
  1867. &lt;/tbody&gt;
  1868. &lt;/table&gt;
  1869. &lt;/th&gt;
  1870. &lt;/tr&gt;
  1871. &lt;/tbody&gt;
  1872. &lt;/table&gt;
  1873. &lt;/td&gt;
  1874. &lt;/tr&gt;
  1875. &lt;/tbody&gt;
  1876. &lt;/table&gt;
  1877. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1878. &lt;tbody&gt;
  1879. &lt;tr&gt;
  1880. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px;"&gt;
  1881. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1882. &lt;tbody&gt;
  1883. &lt;tr&gt;
  1884. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1885. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1886. &lt;tbody&gt;
  1887. &lt;tr&gt;
  1888. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1889. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1890. &lt;tbody&gt;
  1891. &lt;tr&gt;
  1892. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1893. &lt;div&gt;
  1894. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/REn_e7IraZf-6parayETvD6W0y_VDosqk2mhi0-Bb46_HEve7HW1qLXQDVEhOMGNEcOa7sAGLH44NMUvD1G2XLRdjIdr_EeiwNP6bNwjRwZwRrtZNGWYKGAp794Mr-xzz6Iq3dJ42dhiEu2mYfSIofO11Y9WBMCJhjyoRytT0hS-QSwozcAWcXrL3Zv7PKVP5w" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;span style="font-size: 18px;"&gt;CppCon&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 18px;"&gt;, 09/15-20&lt;/span&gt;&lt;/p&gt;
  1895. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;span style="font-size: 16px;"&gt;Aurora, Colorado, USA&lt;/span&gt;&lt;/p&gt;
  1896. &lt;/div&gt;
  1897. &lt;/td&gt;
  1898. &lt;/tr&gt;
  1899. &lt;tr&gt;
  1900. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1901. &lt;div&gt;
  1902. &lt;p style="margin: 0;"&gt;Get ready for the biggest and best C++ conference in the world. Save the dates!&lt;/p&gt;
  1903. &lt;/div&gt;
  1904. &lt;/td&gt;
  1905. &lt;/tr&gt;
  1906. &lt;/tbody&gt;
  1907. &lt;/table&gt;
  1908. &lt;/td&gt;
  1909. &lt;/tr&gt;
  1910. &lt;/tbody&gt;
  1911. &lt;/table&gt;
  1912. &lt;/th&gt;
  1913. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1914. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1915. &lt;tbody&gt;
  1916. &lt;tr&gt;
  1917. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1918. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1919. &lt;tbody&gt;
  1920. &lt;tr&gt;
  1921. &lt;td align="center" class="r37-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-top: 28px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/YASxnsgColejLBua4ExNrQjF11vdCRvS6KPXFuvDJ5SjgKIJcbHSF3nJtD8hluWd-JRmEPlaYsIAXn2emDlHVDIpaHi2hpp6tHR9zrL8fVU9m-yPeGXBMH_LU2iy1q8C5LuzQaaYFviacRHpYFsc4hLnfKOjgNyH5hI_KmyY1b0QAXZ3E3Dpzy6WdDqjXKGRQQ" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/63b32b583a77d80860d4a2611d0822a2d3e3394c43fa69c616ab503f5152fa6c.png?e=ns7AM4UIQYnMJAFWMLZcENewoZdzMcqGOP8uS_lSTfRdf2OYcgad-uvRNu2eZStFCTsqytaqqIyZiK3scX-Yuh9Ro33SIJC5906LnTzzfTUO1OCHAPs1o0HMljqCuN9w6YnxyZqpzSroeHf5XsR8l3XMUmZ2P7e9fnWAGqMQWkfkcgrA7ztEtZlIk9YMabbL5jdJU_kgScJbkq6a4ywFrjtqsi4E41778GfK52qpFUvRXwc" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  1922. &lt;/tr&gt;
  1923. &lt;/tbody&gt;
  1924. &lt;/table&gt;
  1925. &lt;/td&gt;
  1926. &lt;/tr&gt;
  1927. &lt;/tbody&gt;
  1928. &lt;/table&gt;
  1929. &lt;/th&gt;
  1930. &lt;/tr&gt;
  1931. &lt;/tbody&gt;
  1932. &lt;/table&gt;
  1933. &lt;/td&gt;
  1934. &lt;/tr&gt;
  1935. &lt;/tbody&gt;
  1936. &lt;/table&gt;
  1937. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1938. &lt;tbody&gt;
  1939. &lt;tr&gt;
  1940. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px;"&gt;
  1941. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1942. &lt;tbody&gt;
  1943. &lt;tr&gt;
  1944. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1945. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1946. &lt;tbody&gt;
  1947. &lt;tr&gt;
  1948. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1949. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1950. &lt;tbody&gt;
  1951. &lt;tr&gt;
  1952. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1953. &lt;div&gt;
  1954. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/HUkYumzWHUNkZpQlrcbGgLov8Dw8I9A6HsVppIuYCExNxoNMSR6jij6xIk6qD5Jv6GEEMH2cNR3NrFXhLEUgt8AqDzZokOx4TAx6cOVyvLm-R6TvRrQ3ye1TY1jAp8XtR4kweeZfH9V9oVYfjVgNJ93pCkrIwgDEEAaSeQxcFCe722ra646Z0xI" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;span style="font-size: 18px;"&gt;RustLab&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 18px;"&gt;, 11/9-11&lt;/span&gt;&lt;/p&gt;
  1955. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;span style="font-size: 16px;"&gt;Florence, Italy&lt;/span&gt;&lt;/p&gt;
  1956. &lt;/div&gt;
  1957. &lt;/td&gt;
  1958. &lt;/tr&gt;
  1959. &lt;tr&gt;
  1960. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  1961. &lt;div&gt;
  1962. &lt;p style="margin: 0;"&gt;The &lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/6TbbT1LYegtRoQv0JPwz89N27V0xNavB634F57M_uQMC0jvT1qQz_YR1LdBkZjmdCEcNZ4KmoD1uQl63kSXDCMcSL7_2_TtDWvsryaCPKNv-wyUuhM1zZO2KUrd8WT3t2OoBylYm9leHeHOL2-cAbJJenfSJEJxyJ7yBtOv0TN43V_zxO3UybCj-_jk3Fy_wxoDypXeSjjjWsBI" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;call for proposals&lt;/a&gt; is open. There&#x2019;ll be two kinds of talks: 25-min &#x2018;inspirational&#x2019; and 40-min &#x2018;deep-dives&#x2019;, all in English and it happens in Florence. What&#x2019;s not to love?!&lt;/p&gt;
  1963. &lt;/div&gt;
  1964. &lt;/td&gt;
  1965. &lt;/tr&gt;
  1966. &lt;/tbody&gt;
  1967. &lt;/table&gt;
  1968. &lt;/td&gt;
  1969. &lt;/tr&gt;
  1970. &lt;/tbody&gt;
  1971. &lt;/table&gt;
  1972. &lt;/th&gt;
  1973. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  1974. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  1975. &lt;tbody&gt;
  1976. &lt;tr&gt;
  1977. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  1978. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  1979. &lt;tbody&gt;
  1980. &lt;tr&gt;
  1981. &lt;td align="center" class="r37-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-top: 28px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/TvnccsW2W3FTj54gk8fEdsJMuGfNBMx8Sq87n7kMiR-hIjqojhhPtY122T6TDPKU_3nQZIPj7R_i8fGTck9euGYkyfAfI6drQy_Qcy1-YTtBBzgYiDbqppIC8-mepUc_50Zip59oBt_EhiGgIawqjDCHE9ZOzW3cXsNlsS9dmw76CmoIyOkh0tw" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/d627f4f33f2be7f9875f781399065adf6167869724f3788585c6c8c0982d17f5.png?e=xrPFXyl4RVWGFZLUgWvv_6O4WDpyLH49W8iAr3npEYWJvoctUtugGOj2wLzMnOM9KdfckhU64RIgro0K-B9eBZ8W363vOIhlGWL56s0LYh_wbCdsSW5R-2R-dHfQ_pmIf-prVSH8NHuJzJ3FBsAFJswgmtrzzggu2bzAB2kZ_C0loxAAlySypKQIHX0auPW77QS4nZomfQ1xh7kafJcodHncG8AmqZ53Nb44XBcMdrN_2UM" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  1982. &lt;/tr&gt;
  1983. &lt;/tbody&gt;
  1984. &lt;/table&gt;
  1985. &lt;/td&gt;
  1986. &lt;/tr&gt;
  1987. &lt;/tbody&gt;
  1988. &lt;/table&gt;
  1989. &lt;/th&gt;
  1990. &lt;/tr&gt;
  1991. &lt;/tbody&gt;
  1992. &lt;/table&gt;
  1993. &lt;/td&gt;
  1994. &lt;/tr&gt;
  1995. &lt;/tbody&gt;
  1996. &lt;/table&gt;
  1997. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  1998. &lt;tbody&gt;
  1999. &lt;tr&gt;
  2000. &lt;td class="r27-i" style="background-color: #ffffff; color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-bottom: 20px;"&gt;
  2001. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  2002. &lt;tbody&gt;
  2003. &lt;tr&gt;
  2004. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  2005. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  2006. &lt;tbody&gt;
  2007. &lt;tr&gt;
  2008. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  2009. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  2010. &lt;tbody&gt;
  2011. &lt;tr&gt;
  2012. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  2013. &lt;div&gt;
  2014. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/ApsO8AIHE1R70f1sj8DW6wWupcd4obvNsP728kSM_lvQ7ZLmpv8BrtinoKzv3W9aFKuIdoHQLjZKV0LVRuFcJptwggSez8PV28ybNkb-l9-OT4ZJkOA_l-NQFqsAcal2lLpCXN7aGknf875NNnsD9q0ZegqBiT1ms0cVjhdkd_no7pr3LzMnYd6gqJypz4U2XTJ_-jj_DtVKt9-LbhK0sNyMq5E5bDIx4o1d5p0RB6tOLHeVtrbc7RxVLoCgxIZzLsY7rYaiLLcy" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;span style="font-size: 18px;"&gt;Meeting C++ 2024&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 18px;"&gt;, 11/14-16&lt;/span&gt;&lt;/p&gt;
  2015. &lt;p style="margin: 0; color: #222222; font-family: Open Sans; font-size: 22px;"&gt;&lt;span style="font-size: 16px;"&gt;Berlin, Germany &amp; online&lt;/span&gt;&lt;/p&gt;
  2016. &lt;/div&gt;
  2017. &lt;/td&gt;
  2018. &lt;/tr&gt;
  2019. &lt;tr&gt;
  2020. &lt;td align="left" class="r14-c nl2go-default-textstyle" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; line-height: 1.5; padding-top: 15px; text-align: left;"&gt;
  2021. &lt;div&gt;
  2022. &lt;p style="margin: 0;"&gt;With C++ committee members likely to be passing through (and giving talks) en route to the ISO C++ meeting in Poland a week later, it&#x2019;s not to be missed. Save the dates!&lt;/p&gt;
  2023. &lt;/div&gt;
  2024. &lt;/td&gt;
  2025. &lt;/tr&gt;
  2026. &lt;/tbody&gt;
  2027. &lt;/table&gt;
  2028. &lt;/td&gt;
  2029. &lt;/tr&gt;
  2030. &lt;/tbody&gt;
  2031. &lt;/table&gt;
  2032. &lt;/th&gt;
  2033. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="50%"&gt;
  2034. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  2035. &lt;tbody&gt;
  2036. &lt;tr&gt;
  2037. &lt;td class="r13-i" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 12px; padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  2038. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  2039. &lt;tbody&gt;
  2040. &lt;tr&gt;
  2041. &lt;td align="center" class="r37-c" style="color: #808080; font-family: verdana,geneva,sans-serif; font-size: 0px; line-height: 0px; padding-top: 28px;"&gt;&lt;a href="https://6hcgu.r.sp1-brevo.net/mk/cl/f/8oJ_-m-SeX7InAl5DUHh2cyvX4ah4EsEop4TTg2aie7VkOIx9rk7hhHu1EhrfBO0FzxZ5rvbm104i8XQe9GDyv7iik7QR6dBzsW7jXCqIF6Wt5tFiQySfuj8vSoq-TA3igzm0Ro-EDbxuML5AAbjiD5JgqChwBXvkeQdMHYgIERH9rponi-7IUgjsgVgXPGbWjlVcAKRZcY--9PcHCb4iHwdnmREegDZUSIrU9WAH1eZ9aDiLLndK64gA_GH0_q4jhluZ_CPqomu" rel="noopener" style="color: #4caad8; text-decoration: none;" target="_blank"&gt;&lt;img border="0" src="https://img-cache.net/im/3790426/cb39b2b508f5403c7cc0e02706b81a1fa6c10484d24f9e7e901508bb8139708c.png?e=bO9e-uXcZ1d67MrcB6l0aceACTNGE125738jJ2zZ-0sCkBr-CdkMalOjqQBv2dNSdCcJsCdCle_m65e2d0ia6_iG1ukeJYEFKmE00jeeLyem8YqEyADZpwq_QNPn9W_PHiQGo4Q9XdGVqsAQodigDhS3nb1BUTCDlNfF4gxAi6bmllPmmAifOY0O_i0-j0jztlcfvUW--gwLYoFFayGP81k0MiPX2KfXJXnsSz6c6gtNiMY" style="display: block; width: 100%;" width="270"&gt;&lt;/a&gt;&lt;/td&gt;
  2042. &lt;/tr&gt;
  2043. &lt;/tbody&gt;
  2044. &lt;/table&gt;
  2045. &lt;/td&gt;
  2046. &lt;/tr&gt;
  2047. &lt;/tbody&gt;
  2048. &lt;/table&gt;
  2049. &lt;/th&gt;
  2050. &lt;/tr&gt;
  2051. &lt;/tbody&gt;
  2052. &lt;/table&gt;
  2053. &lt;/td&gt;
  2054. &lt;/tr&gt;
  2055. &lt;/tbody&gt;
  2056. &lt;/table&gt;
  2057. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 100%;" width="100%"&gt;
  2058. &lt;tbody&gt;
  2059. &lt;tr&gt;
  2060. &lt;td class="r18-i" style="background-color: #ffffff; padding-bottom: 20px; padding-top: 20px;"&gt;
  2061. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  2062. &lt;tbody&gt;
  2063. &lt;tr&gt;
  2064. &lt;th class="r12-c" style="font-weight: normal;" valign="top" width="100%"&gt;
  2065. &lt;table border="0" cellpadding="0" cellspacing="0" class="r5-o" style="width: 100%;" width="100%"&gt;
  2066. &lt;tbody&gt;
  2067. &lt;tr&gt;
  2068. &lt;td class="r19-i" style="padding-left: 15px; padding-right: 15px;" valign="top"&gt;
  2069. &lt;table border="0" cellpadding="0" cellspacing="0" width="100%"&gt;
  2070. &lt;tbody&gt;
  2071. &lt;tr&gt;
  2072. &lt;td align="center" class="r16-c" style="padding-bottom: 30px; padding-top: 30px;"&gt;
  2073. &lt;table border="0" cellpadding="0" cellspacing="0" style="border-top-style: solid; border-top-color: #4caad8; border-top-width: 1px; font-size: 1px; line-height: 1px;" width="100%"&gt;
  2074. &lt;tbody&gt;
  2075. &lt;tr&gt;
  2076. &lt;td height="0" style="font-size: 0px; line-height: 0px;"&gt;&#xAD;&lt;/td&gt;
  2077. &lt;/tr&gt;
  2078. &lt;/tbody&gt;
  2079. &lt;/table&gt;
  2080. &lt;/td&gt;
  2081. &lt;/tr&gt;
  2082. &lt;tr&gt;
  2083. &lt;td align="center" class="r43-c"&gt;
  2084. &lt;table align="center" border="0" cellpadding="0" cellspacing="0" class="r10-o" style="width: 570px;" width="570"&gt;
  2085. &lt;tbody&gt;
  2086. &lt;tr&gt;
  2087. &lt;td valign="top"&gt;&lt;/td&gt;
  2088. &lt;/tr&gt;
  2089. &lt;/tbody&gt;
  2090. &lt;/table&gt;
  2091. &lt;/td&gt;
  2092. &lt;/tr&gt;
  2093. &lt;/tbody&gt;
  2094. &lt;/table&gt;
  2095. &lt;/td&gt;
  2096. &lt;/tr&gt;
  2097. &lt;/tbody&gt;
  2098. &lt;/table&gt;
  2099. &lt;/th&gt;
  2100. &lt;/tr&gt;
  2101. &lt;/tbody&gt;
  2102. &lt;/table&gt;
  2103. &lt;/td&gt;
  2104. &lt;/tr&gt;
  2105. &lt;/tbody&gt;
  2106. &lt;/table&gt;
  2107. &lt;/td&gt;
  2108. &lt;/tr&gt;
  2109. &lt;/tbody&gt;
  2110. &lt;/table&gt;
  2111. &lt;/td&gt;
  2112. &lt;/tr&gt;
  2113. &lt;/tbody&gt;
  2114. &lt;/table&gt;
  2115. &lt;div style="color: #727272; font-size: 10px;"&gt;&lt;/div&gt;
  2116. &lt;p&gt;The post &lt;a href="https://www.kdab.com/2024-april-newsletter/"&gt;C++ &amp; Rust, Servo Web &amp; Qt, Qt Quick &amp; JSON, Embedded &#x2013; blogs &amp; videos, Hotspot 1.5, Qt 6.7, GCompris in India, Events&lt;/a&gt; appeared first on &lt;a href="https://www.kdab.com"&gt;KDAB&lt;/a&gt;.&lt;/p&gt;</description>
  2117.    </item>
  2118.    <item>
  2119.      <guid isPermaLink="false">https://www.qt.io/blog/qt-visual-studio-tools-3.2.0-released</guid>
  2120.      <title>The Qt Company Blog: Qt Visual Studio Tools 3.2.0 Released</title>
  2121.      <pubDate>Mon, 29 Apr 2024 08:53:55 GMT</pubDate>
  2122.      <link>https://www.qt.io/blog/qt-visual-studio-tools-3.2.0-released</link>
  2123.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://www.qt.io/blog/qt-visual-studio-tools-3.2.0-released" title=""&gt;&lt;img alt="Qt Visual Studio Tools 3.2.0 Released" class="hs-featured-image" src="https://www.qt.io/hubfs/Settings.png" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  2124. &lt;p&gt;We are happy to announce the release of the Qt Visual Studio Tools version 3.2.0. Installation packages are now available at the &lt;a href="https://marketplace.visualstudio.com/publishers/TheQtCompany"&gt;Visual Studio Marketplace&lt;/a&gt; and &lt;a href="https://download.qt.io/official_releases/vsaddin/"&gt;download.qt.io&lt;/a&gt;.&lt;br&gt;
  2125. &lt;br&gt;
  2126. This update of the Qt VS Tools extension adds experimental support for QML LSP server, as well as full support of the Qt VS Tools for Visual Studio 2022 on ARM64.&lt;br&gt;
  2127. &lt;br&gt;
  2128. &lt;br&gt;
  2129. &lt;br&gt;
  2130. Qt MSBuild file support:&lt;br&gt;
  2131. &lt;br&gt;
  2132. Alongside providing Qt-related MSBuild files within the Qt VS Tools package, we now offer them as a separate .zip download for your convenience. Starting from version 3.2.0, access the standalone Qt MSBuild files by visiting our public server download location: &lt;a href="https://download.qt.io/official_releases/vsaddin/"&gt;Official releases&lt;/a&gt;.&#xA0;&lt;br&gt;
  2133. &lt;br&gt;
  2134. Please refer to the project's &lt;a href="https://code.qt.io/cgit/qt-labs/vstools.git/tree/Changelog"&gt;Changelog&lt;/a&gt; for a list of all changes included in this release. Feel free to report any problems, or make any suggestions or comments, in the &lt;a href="https://bugreports.qt.io/projects/QTVSADDINBUG/issues"&gt;Qt Visual Studio Tools bug tracker&lt;/a&gt;.&lt;/p&gt;
  2135. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fqt-visual-studio-tools-3.2.0-released&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  2136.    </item>
  2137.    <item>
  2138.      <guid isPermaLink="false">https://www.basyskom.de/?p=9069</guid>
  2139.      <title>Qt &#x2013; basysKom GmbH: How To Use Modern QML Tooling in Practice</title>
  2140.      <pubDate>Fri, 26 Apr 2024 07:37:58 GMT</pubDate>
  2141.      <link>https://www.basyskom.de/2024/how-to-use-modern-qml-tooling-in-practice/</link>
  2142.      <description>&lt;p&gt;&lt;a href="https://www.basyskom.de/2024/how-to-use-modern-qml-tooling-in-practice/"&gt;&lt;img align="left" alt="How To Use Modern QML Tooling in Practice" height="150" src="https://www.basyskom.de/wp-content/uploads/2020/07/Qt_logo_space-01-01-300x150.png" style="margin: 0 20px 20px 0;" width="300"&gt;&lt;/a&gt;&lt;/p&gt;
  2143. &lt;p&gt;Qt 5.15 introduced &#x201C;Automatic Type Registration&#x201D;. With it, a C++ class can be marked as &#x201C;QML_ELEMENT&#x201D; to be automatically registered to the QML engine. Qt 6 takes this to the next level and builds all of its tooling around the so-called QML Modules. Let&#x2019;s talk about what this new infrastructure means to your application in practice and how to benefit from it in an existing project.&lt;/p&gt;
  2144. &lt;p&gt;&lt;a href="https://www.basyskom.de/2024/how-to-use-modern-qml-tooling-in-practice/" rel="nofollow"&gt;Continue reading How To Use Modern QML Tooling in Practice at basysKom GmbH.&lt;/a&gt;&lt;/p&gt;</description>
  2145.    </item>
  2146.    <item>
  2147.      <guid isPermaLink="false">https://www.qt.io/blog/qt-meetup-community-events-in-toronto-and-detroit</guid>
  2148.      <title>The Qt Company Blog: Qt Meetup: Community Events in Toronto and Detroit!</title>
  2149.      <pubDate>Thu, 25 Apr 2024 15:21:53 GMT</pubDate>
  2150.      <link>https://www.qt.io/blog/qt-meetup-community-events-in-toronto-and-detroit</link>
  2151.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://www.qt.io/blog/qt-meetup-community-events-in-toronto-and-detroit" title=""&gt;&lt;img alt="Qt Meetup: Community Events in Toronto and Detroit!" class="hs-featured-image" src="https://www.qt.io/hubfs/Qt%20Toronto%20%2B%20Detroit%20May%202024.jpg" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  2152. &lt;p&gt;Hey Qt,&lt;/p&gt;
  2153. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fqt-meetup-community-events-in-toronto-and-detroit&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  2154.    </item>
  2155.    <item>
  2156.      <guid isPermaLink="false">https://blog.felgo.com/updates/felgohotreload-1.2.0-load-from-cache-auto-connect-qt-6-7</guid>
  2157.      <title>Felgo: Felgo Hot Reload 1.2.0: Load from Cache, Auto-Connect from Command Line, Improved QML Reload and Qt 6.7 Support</title>
  2158.      <pubDate>Wed, 24 Apr 2024 12:47:04 GMT</pubDate>
  2159.      <link>https://blog.felgo.com/updates/felgohotreload-1.2.0-load-from-cache-auto-connect-qt-6-7</link>
  2160.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://blog.felgo.com/updates/felgohotreload-1.2.0-load-from-cache-auto-connect-qt-6-7" title=""&gt;&lt;img alt="Felgo Hot Reload 1.2.0: Load from Cache, Auto-Connect from Command Line, Improved QML Reload and Qt 6.7 Support" class="hs-featured-image" src="https://blog.felgo.com/hubfs/felgo-hot-reload-product-release.png" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  2161. &lt;p&gt;The Felgo QML Hot Reload release 1.2.0 brings additional options on the connection screen, command line arguments, several QML Hot Reload improvements, and an overhauled user interface. Read on to check out all of the updates below:&lt;/p&gt;
  2162. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=6147417&amp;k=14&amp;r=https%3A%2F%2Fblog.felgo.com%2Fupdates%2Ffelgohotreload-1.2.0-load-from-cache-auto-connect-qt-6-7&amp;bu=https%253A%252F%252Fblog.felgo.com&amp;bvt=rss" width="1"&gt;</description>
  2163.    </item>
  2164.    <item>
  2165.      <guid isPermaLink="false">https://www.qt.io/blog/qt-safe-renderer-2.1.0-beta-3-released</guid>
  2166.      <title>The Qt Company Blog: Qt Safe Renderer 2.1.0 Beta 3 Released</title>
  2167.      <pubDate>Fri, 19 Apr 2024 16:15:29 GMT</pubDate>
  2168.      <link>https://www.qt.io/blog/qt-safe-renderer-2.1.0-beta-3-released</link>
  2169.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://www.qt.io/blog/qt-safe-renderer-2.1.0-beta-3-released" title=""&gt;&lt;img alt="Qt Safe Renderer 2.1.0 Beta 3 Released" class="hs-featured-image" src="https://www.qt.io/hubfs/qtsr-qtcluster-telltales-eventsender-1-1.png" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  2170. &lt;p&gt;&lt;span&gt;We have released Qt Safe Renderer 2.1.0 Beta 3 for commercial license holders today. It provides a snapshot of upcoming Qt Safe Renderer features and the following improvements for &lt;span&gt;Qt Safe Layout Tool QML and JavaScript parsing&lt;/span&gt;:&lt;br&gt;&lt;/span&gt;&lt;/p&gt;
  2171. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fqt-safe-renderer-2.1.0-beta-3-released&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  2172.    </item>
  2173.    <item>
  2174.      <guid isPermaLink="false">https://www.qt.io/blog/qt-for-android-automotive-6.7-is-released</guid>
  2175.      <title>The Qt Company Blog: Qt Android Automotive 6.7 is released</title>
  2176.      <pubDate>Fri, 19 Apr 2024 12:24:29 GMT</pubDate>
  2177.      <link>https://www.qt.io/blog/qt-for-android-automotive-6.7-is-released</link>
  2178.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://www.qt.io/blog/qt-for-android-automotive-6.7-is-released" title=""&gt;&lt;img alt="Qt Android Automotive 6.7 is released" class="hs-featured-image" src="https://doc.qt.io/qt-6/images/select_example_project.png" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  2179. &lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;The latest release of&lt;/span&gt; &lt;span&gt;Qt for Android Automotive (&lt;/span&gt;&lt;span&gt;QtAA&lt;/span&gt;&lt;span&gt;) is out, based on &lt;a href="https://www.qt.io/blog/qt-6.7-released"&gt;Qt 6.7.&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;
  2180. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fqt-for-android-automotive-6.7-is-released&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  2181.    </item>
  2182.    <item>
  2183.      <guid isPermaLink="false">https://www.qt.io/blog/security-advisory-potential-use-after-free-issue-in-qt-for-webassemblys-implementation-of-qnetworkreply</guid>
  2184.      <title>The Qt Company Blog: Security advisory: Potential Use-After-Free issue in Qt for WebAssembly&#x2019;s implementation of QNetworkReply</title>
  2185.      <pubDate>Thu, 18 Apr 2024 09:00:00 GMT</pubDate>
  2186.      <link>https://www.qt.io/blog/security-advisory-potential-use-after-free-issue-in-qt-for-webassemblys-implementation-of-qnetworkreply</link>
  2187.      <description>&lt;p&gt;A recently reported potential Use-After-Free issue in Qt&#x2019;s wasm implementation of QNetworkReply has been assigned the CVE id CVE-2024-30161.&lt;/p&gt;
  2188. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=149513&amp;k=14&amp;r=https%3A%2F%2Fwww.qt.io%2Fblog%2Fsecurity-advisory-potential-use-after-free-issue-in-qt-for-webassemblys-implementation-of-qnetworkreply&amp;bu=https%253A%252F%252Fwww.qt.io%252Fblog&amp;bvt=rss" width="1"&gt;</description>
  2189.    </item>
  2190.    <item>
  2191.      <guid isPermaLink="false">https://www.ics.com/4827 at https://www.ics.com</guid>
  2192.      <title>ICS Insights: Qt and QML: Key Takeaways from 2024 Embedded World</title>
  2193.      <pubDate>Tue, 16 Apr 2024 15:43:15 GMT</pubDate>
  2194.      <link>https://www.ics.com/blog/key-takeaways-2024-embedded-world</link>
  2195.      <description>&lt;p&gt;With the 2024 Embedded World Exhibition &amp; Conference in the rear view, here are some key impressions from the ICS team around the future of embedded development.&lt;/p&gt;</description>
  2196.    </item>
  2197.    <item>
  2198.      <guid isPermaLink="false">https://www.kdab.com/?p=33391</guid>
  2199.      <title>KDAB on Qt: Recursive Instantiation with Qt Quick and JSON</title>
  2200.      <pubDate>Thu, 11 Apr 2024 07:00:37 GMT</pubDate>
  2201.      <link>https://www.kdab.com/recursive-instantiation-with-qt-quick-and-json/</link>
  2202.      <description>&lt;p&gt;Recently I was tasked to come up with an architecture for remote real time instantiation and updating of arbitrary QML components.&lt;/p&gt;
  2203. &lt;p&gt;This entry shows how you can use a simple variation of the factory method pattern in QML for instantiating arbitrary components. I&#x2019;ve split my findings into 3 blog entries, each one covering a slightly different topic. Part 1 focuses on the software design pattern used to dynamically instantiate components. Part 2 shows how to layout these dynamic components by incorporating QML&#x2019; s positioning and layout APIs. The last entry, consisting of Parts 3 and 4, addresses the anchors API and important safety aspects.&lt;/p&gt;
  2204. &lt;p&gt;This is Part 1: Recursive Instantiation with Qt Quick and JSON.&lt;/p&gt;
  2205. &lt;p&gt;The original factory method pattern made use of static methods to programmatically instantiate objects of different classes, instead of having to call their constructors. It achieved that by having the classes share a common ancestor. Our variation of the popular pattern uses a Loader to choose which component to load, and a Repeater to dynamically instantiate arbitrary instances of this loader using a model.&lt;/p&gt;
  2206. &lt;p&gt;Here we specify which components with a JSON array and use a Repeater to load them.&lt;/p&gt;
  2207. &lt;pre class="language-js" tabindex="0"&gt;
  2208. &lt;code class="language-js"&gt;&lt;span class="token comment"&gt;    &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;root&lt;/span&gt;
  2209.    // A JSON representation of a QML layout:&lt;/span&gt;
  2210.    property &lt;span class="token keyword"&gt;var&lt;/span&gt; &lt;span class="token literal-property property"&gt;factoryModel&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
  2211.        &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2212.            &lt;span class="token string-property property"&gt;"component"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;"Button"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
  2213.        &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
  2214.        &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2215.            &lt;span class="token string-property property"&gt;"component"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;"Button"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
  2216.        &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2217.    &lt;span class="token punctuation"&gt;]&lt;/span&gt;
  2218. &lt;span class="token comment"&gt;    // Root of our component factory&lt;/span&gt;
  2219.    Repeater &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2220.        &lt;span class="token literal-property property"&gt;model&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; root.factoryModel
  2221.        &lt;span class="token literal-property property"&gt;delegate&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; loaderComp
  2222. &lt;span class="token punctuation"&gt;    }&lt;/span&gt;&lt;/code&gt;
  2223. &lt;/pre&gt;
  2224. &lt;p&gt;To be able to instantiate any kind of item, you can use a Component with a Loader inside, as the Repeater&#x2019;s delegate. This allows you to load a different component based on the Repeater&#x2019;s model data.&lt;/p&gt;
  2225. &lt;pre class="language-javascript" tabindex="0"&gt;
  2226. &lt;code class="language-javascript"&gt;    &lt;span class="token comment"&gt;// Root component of the factory and nodes&lt;/span&gt;
  2227.    Component &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2228.        &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; loaderComp
  2229.        Loader &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2230.            &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; instantiator
  2231.            required property var modelData
  2232.            &lt;span class="token literal-property property"&gt;sourceComponent&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token keyword"&gt;switch&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;component&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2233.                &lt;span class="token keyword"&gt;case&lt;/span&gt; &lt;span class="token string"&gt;"Button"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt;
  2234.                &lt;span class="token keyword"&gt;return&lt;/span&gt; buttonComp&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2235.                &lt;span class="token keyword"&gt;case&lt;/span&gt; &lt;span class="token string"&gt;"RowLayout"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt;
  2236.                &lt;span class="token keyword"&gt;return&lt;/span&gt; rowLayoutComp&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2237.                &lt;span class="token keyword"&gt;case&lt;/span&gt; &lt;span class="token string"&gt;"Item"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt;
  2238.                &lt;span class="token keyword"&gt;default&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token keyword"&gt;return&lt;/span&gt; itemComp&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2239.            &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2240.        &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2241.    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/code&gt;
  2242. &lt;/pre&gt;
  2243. &lt;p&gt;To assign values from the model to the component, add a method that gets called when the Loader&#x2019;s onItemChanged event is triggered. I use this method to take care of anything that involves the component&#x2019;s properties:&lt;/p&gt;
  2244. &lt;pre class="language-javascript" tabindex="0"&gt;
  2245. &lt;code class="language-javascript"&gt;    &lt;span class="token comment"&gt;// Root component of the factory and nodes&lt;/span&gt;
  2246.    Component &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2247.        &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; loaderComp
  2248.        Loader &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2249.            &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; instantiator
  2250.            required property var modelData
  2251.            &lt;span class="token literal-property property"&gt;sourceComponent&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token keyword"&gt;switch&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;component&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2252.                &lt;span class="token keyword"&gt;case&lt;/span&gt; &lt;span class="token string"&gt;"Button"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt;
  2253.                &lt;span class="token keyword"&gt;return&lt;/span&gt; buttonComp&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2254.                &lt;span class="token keyword"&gt;case&lt;/span&gt; &lt;span class="token string"&gt;"RowLayout"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt;
  2255.                &lt;span class="token keyword"&gt;return&lt;/span&gt; rowLayoutComp&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2256.                &lt;span class="token keyword"&gt;case&lt;/span&gt; &lt;span class="token string"&gt;"Item"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt;
  2257.                &lt;span class="token keyword"&gt;default&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token keyword"&gt;return&lt;/span&gt; itemComp&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2258.            &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2259.            &lt;span class="token literal-property property"&gt;onItemChanged&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2260.                &lt;span class="token comment"&gt;// Pass children (see explanation below)&lt;/span&gt;
  2261.                &lt;span class="token keyword"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;typeof&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;children&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;===&lt;/span&gt; &lt;span class="token string"&gt;"object"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;
  2262.                    item&lt;span class="token punctuation"&gt;.&lt;/span&gt;model &lt;span class="token operator"&gt;=&lt;/span&gt; modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;children&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2263.  
  2264.                &lt;span class="token comment"&gt;// Button properties&lt;/span&gt;
  2265.                &lt;span class="token keyword"&gt;switch&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;component&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2266.                    &lt;span class="token keyword"&gt;case&lt;/span&gt; &lt;span class="token string"&gt;"Button"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt;
  2267.                    &lt;span class="token comment"&gt;// If the model contains certain value, we may assign it:&lt;/span&gt;
  2268.                    &lt;span class="token keyword"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;typeof&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;text&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;!==&lt;/span&gt; &lt;span class="token string"&gt;"undefined"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;
  2269.                        item&lt;span class="token punctuation"&gt;.&lt;/span&gt;text &lt;span class="token operator"&gt;=&lt;/span&gt; modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;text&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2270.                    &lt;span class="token keyword"&gt;break&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2271.                &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2272.  
  2273.                &lt;span class="token comment"&gt;// Item properties&lt;/span&gt;
  2274.                &lt;span class="token comment"&gt;// Since Item is the parent of all repeatable, we don't need to check&lt;/span&gt;
  2275.                &lt;span class="token comment"&gt;// if the component supports Item properties before we assign them:&lt;/span&gt;
  2276.                &lt;span class="token keyword"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;typeof&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;x&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;!==&lt;/span&gt; &lt;span class="token string"&gt;"undefined"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;
  2277.                    loaderComp&lt;span class="token punctuation"&gt;.&lt;/span&gt;x &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;Number&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;x&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2278.                &lt;span class="token keyword"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;typeof&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;y&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;!==&lt;/span&gt; &lt;span class="token string"&gt;"undefined"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;
  2279.                    loaderComp&lt;span class="token punctuation"&gt;.&lt;/span&gt;y &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;Number&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;modelData&lt;span class="token punctuation"&gt;.&lt;/span&gt;y&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
  2280.                &lt;span class="token comment"&gt;// ...&lt;/span&gt;
  2281.            &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2282.        &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2283.    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/code&gt;
  2284. &lt;/pre&gt;
  2285. &lt;p&gt;Examples of components that loaderComp could load are defined below. To enable recursion, these components must contain a Repeater that instantiates children components, with loaderComp set as the delegate:&lt;/p&gt;
  2286. &lt;pre class="language-javascript" tabindex="0"&gt;
  2287. &lt;code class="language-javascript"&gt;    Component &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2288.        &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; itemComp
  2289.        Item &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2290.            property alias children&lt;span class="token operator"&gt;:&lt;/span&gt; itemRepeater&lt;span class="token punctuation"&gt;.&lt;/span&gt;model
  2291.            &lt;span class="token literal-property property"&gt;children&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; Repeater &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2292.                &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; itemRepeater
  2293.                &lt;span class="token literal-property property"&gt;delegate&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; loaderComp
  2294.            &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2295.        &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2296.    &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2297.    Component &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2298.        &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; buttonComp
  2299.        Button &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2300.            property alias children&lt;span class="token operator"&gt;:&lt;/span&gt; itemRepeater&lt;span class="token punctuation"&gt;.&lt;/span&gt;model
  2301.            &lt;span class="token literal-property property"&gt;children&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; Repeater &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2302.                &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; itemRepeater
  2303.                &lt;span class="token literal-property property"&gt;delegate&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; loaderComp
  2304.            &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2305.        &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2306.    &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2307.    Component &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2308.        &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; rowLayoutComp
  2309.        RowLayout &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2310.            property alias children&lt;span class="token operator"&gt;:&lt;/span&gt; itemRepeater&lt;span class="token punctuation"&gt;.&lt;/span&gt;model
  2311.            &lt;span class="token literal-property property"&gt;children&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; Repeater &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2312.                &lt;span class="token literal-property property"&gt;id&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; itemRepeater
  2313.                &lt;span class="token literal-property property"&gt;delegate&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; loaderComp
  2314.            &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2315.        &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2316.    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/code&gt;
  2317. &lt;/pre&gt;
  2318. &lt;p&gt;The Repeater inside of the components allows us to instantiate components recursively, by having a branch or more of children components in the model, like so:&lt;/p&gt;
  2319. &lt;pre class="language-javascript" tabindex="0"&gt;
  2320. &lt;code class="language-javascript"&gt;    &lt;span class="token comment"&gt;// This model lays out buttons vertically&lt;/span&gt;
  2321.    property &lt;span class="token keyword"&gt;var&lt;/span&gt; &lt;span class="token literal-property property"&gt;factoryModel&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
  2322.        &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2323.            &lt;span class="token string-property property"&gt;"component"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;"RowLayout"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
  2324.            &lt;span class="token string-property property"&gt;"children"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
  2325.                &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2326.                    &lt;span class="token string-property property"&gt;"component"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;"Button",&lt;/span&gt;
  2327.                    &lt;span class="token string-property property"&gt;"text"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;"Button 1"&lt;/span&gt;
  2328.                &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
  2329.                &lt;span class="token punctuation"&gt;{&lt;/span&gt;
  2330.                    &lt;span class="token string-property property"&gt;"component"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;"Button",&lt;/span&gt;
  2331.                    &lt;span class="token string-property property"&gt;"text"&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;"Button 2"&lt;/span&gt;
  2332.                &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2333.            &lt;span class="token punctuation"&gt;]&lt;/span&gt;
  2334.        &lt;span class="token punctuation"&gt;}&lt;/span&gt;
  2335.    &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;/code&gt;
  2336. &lt;/pre&gt;
  2337. &lt;p&gt;Here we&#x2019;ve seen how we can use a Repeater, a JSON model, a Loader delegate, and simple recursive definition to instantiate arbitrary QML objects from a JSON description. In my next entry I will focus on how you can lay out these arbitrarily instantiated objects on your screen.&lt;/p&gt;
  2338. &lt;p&gt;Thanks to &lt;a href="https://www.kdab.com/trainer/kevin-krammer/"&gt;Kevin Krammer&lt;/a&gt; and &lt;a href="https://www.kdab.com/trainer/jan-marker/"&gt;Jan Marker&lt;/a&gt; whose insights helped improve the code you&#x2019;ve seen here.&lt;/p&gt;
  2339. &lt;p&gt;I hope you&#x2019;ve found this useful! Part 2 may be found already or later by following &lt;a href="https://wp.me/p2b2Fz-8Sr"&gt;this link&lt;/a&gt;.&lt;/p&gt;
  2340. &lt;h5&gt;Reference&lt;/h5&gt;
  2341. &lt;ul&gt;
  2342. &lt;li&gt;To see a real world application of this factory design pattern in action, watch &#x201C;QML for building beautiful desktop apps | Dev/Des 2021&#x201D;, by Prashanth N. Udupa &lt;a href="https://youtu.be/l2nC-onPGQs?si=Q-xawseUUzsNADk9&amp;t=1720" rel="noopener noreferrer" target="_blank"&gt;https://www.youtube.com/watch?v=l2nC-onPGQs&lt;/a&gt;&lt;/li&gt;
  2343. &lt;/ul&gt;
  2344. &lt;div class="panel panel-info"&gt;
  2345. &lt;div class="panel-heading"&gt;About KDAB&lt;/div&gt;
  2346. &lt;div class="panel-body"&gt;
  2347. &lt;p&gt;If you like this article and want to read similar material, consider subscribing via &lt;a href="https://www.kdab.com/category/blogs/feed/"&gt;our RSS feed&lt;/a&gt;.&lt;/p&gt;
  2348. &lt;p&gt;Subscribe to &lt;a href="https://www.youtube.com/kdabtv"&gt;KDAB TV&lt;/a&gt; for similar informative short video content.&lt;/p&gt;
  2349. &lt;p&gt;KDAB provides market leading software consulting and development &lt;a href="https://www.kdab.com/software-services/"&gt;services&lt;/a&gt; and &lt;a href="https://training.kdab.com/"&gt;training&lt;/a&gt; in Qt, C++ and 3D/OpenGL. &lt;a href="https://www.kdab.com/about/contact/"&gt;Contact us&lt;/a&gt;.&lt;/p&gt;
  2350. &lt;/div&gt;
  2351. &lt;/div&gt;
  2352. &lt;p&gt;The post &lt;a href="https://www.kdab.com/recursive-instantiation-with-qt-quick-and-json/"&gt;Recursive Instantiation with Qt Quick and JSON&lt;/a&gt; appeared first on &lt;a href="https://www.kdab.com"&gt;KDAB&lt;/a&gt;.&lt;/p&gt;</description>
  2353.    </item>
  2354.    <item>
  2355.      <guid isPermaLink="false">https://www.kdab.com/?p=34100</guid>
  2356.      <title>KDAB on Qt: Embedding the Servo Web Engine in Qt</title>
  2357.      <pubDate>Fri, 05 Apr 2024 08:00:03 GMT</pubDate>
  2358.      <link>https://www.kdab.com/embedding-servo-in-qt/</link>
  2359.      <description>&lt;p&gt;With the Qt WebEngine module, Qt makes it possible to embed a webview component inside an otherwise native application. Under the hood, Qt WebEngine uses the Chromium browser engine, currently the de facto standard engine for such use cases.&lt;/p&gt;
  2360. &lt;p&gt;While the task of writing a brand new standard-compliant browser engine is infamous as being almost unachievable nowadays (and certainly so with Chromium coming in at 31 million lines of code), the Rust ecosystem has been brewing up a new web rendering engine called &lt;a href="https://servo.org/"&gt;Servo&lt;/a&gt;. Initially created by Mozilla in 2012, Servo is still being developed today, now under the stewardship of the Linux Foundation.&lt;/p&gt;
  2361. &lt;p&gt;With the browser inherently being exposed to the internet, it is usually the biggest attack vector on a system. Naturally this makes Servo very attractive as an alternative browser engine, given that it is written in a memory-safe language.&lt;/p&gt;
  2362. &lt;h2&gt;A Servo WebView&lt;/h2&gt;
  2363. &lt;p&gt;At KDAB we managed to embed the Servo web engine inside Qt, by using our &lt;a href="https://github.com/KDAB/cxx-qt"&gt;CXX-Qt&lt;/a&gt; library as a bridge between Rust and C++. This means that we can now use Servo as an alternative to Chromium for webviews in Qt applications.&lt;/p&gt;
  2364. &lt;p&gt;From a QML perspective this component is similar to the Chromium &lt;a href="https://doc.qt.io/qt-6/qml-qtwebview-webview.html"&gt;WebView&lt;/a&gt;, such as providing &lt;code&gt;canGoBack&lt;/code&gt;, &lt;code&gt;canGoForward&lt;/code&gt;, &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt; properties and &lt;code&gt;goBack&lt;/code&gt;, &lt;code&gt;goForward&lt;/code&gt; methods. The QML item itself acts in the same way with the contents being rendered to match its size.&lt;/p&gt;
  2365. &lt;pre class="brush: plain; title: ; notranslate"&gt;
  2366. import QtQuick
  2367. import QtQuick.Window
  2368.  
  2369. import com.kdab.servo
  2370.  
  2371. Window {
  2372.  height: 720
  2373.  width: 1280
  2374.  title: webView.title
  2375.  visible: true
  2376.  
  2377.  ServoWebView {
  2378.    id: webView
  2379.    anchors.fill: parent
  2380.    url: "https://servo.org/"
  2381.  }
  2382. }
  2383. &lt;/pre&gt;
  2384. &lt;p&gt;The screenshot below shows a basic QML application with a toolbar containing back, forward, go buttons and an address bar. We use CXX-Qt to define Qt properties, invokables, and event handlers (e.g. touch events) in Rust and trigger events in the Servo engine. Then any update requests from Servo can trigger an update of the Qt side via the Qt event loop.&lt;/p&gt;
  2385. &lt;p&gt;&lt;img alt="" class="aligncenter wp-image-34507 size-full" height="833" src="https://www.kdab.com/wp-content/uploads/stories/cxx-qt-servo-webview.png" width="1286"&gt;&lt;/p&gt;
  2386. &lt;p&gt;As we move towards stabilising &lt;a href="https://github.com/KDAB/cxx-qt/"&gt;CXX-Qt&lt;/a&gt; at KDAB, investigating real world use cases, such as exposing Servo to Qt, allows us to identify potential missing functionality and explore what is possible when joining the Rust and Qt ecosystems together.&lt;/p&gt;
  2387. &lt;h2&gt;Technical details&lt;/h2&gt;
  2388. &lt;p&gt;Under the hood most of the heavy lifting is done by our &lt;a href="https://github.com/KDAB/cxx-qt/"&gt;CXX-Qt&lt;/a&gt; bindings, which already bridges the obvious gap between the Rust and Qt/C++ worlds. However, some further glue is needed to connect the rendering contexts of Servo to being able to render the surfaces into the actual Qt application. Internally, Servo uses &lt;a href="https://github.com/servo/surfman"&gt;surfman&lt;/a&gt;, a Rust library to manage rendering surfaces. At the time of writing, surfman supports OpenGL and Metal, with support for Vulkan being planned.&lt;/p&gt;
  2389. &lt;p&gt;We use surfman to &lt;a href="https://github.com/KDABLabs/cxx-qt-servo-webview/blob/157b65bb44c7bb2ef5d84542f03dccc0de18c002/src/windowheadless.rs#L29"&gt;create a new OpenGL context&lt;/a&gt;, that &lt;a href="https://github.com/KDABLabs/cxx-qt-servo-webview/blob/157b65bb44c7bb2ef5d84542f03dccc0de18c002/src/servothread.rs#L76-L81"&gt;Servo then uses for rendering&lt;/a&gt;. To render the result into the QtQuick scene, we &lt;a href="https://github.com/KDABLabs/cxx-qt-servo-webview/blob/157b65bb44c7bb2ef5d84542f03dccc0de18c002/src/servothread.rs#L145-L161"&gt;borrow the surface&lt;/a&gt; from Servo, &lt;a href="https://github.com/KDABLabs/cxx-qt-servo-webview/blob/157b65bb44c7bb2ef5d84542f03dccc0de18c002/src/renderer.rs#L130"&gt;create a new framebuffer object&lt;/a&gt; and &lt;a href="https://github.com/KDABLabs/cxx-qt-servo-webview/blob/157b65bb44c7bb2ef5d84542f03dccc0de18c002/src/renderer.rs#L133"&gt;blit the framebuffer&lt;/a&gt; into a &lt;a href="https://doc.qt.io/qt-6/qquickframebufferobject.html"&gt;QQuickFrameBufferObject&lt;/a&gt; on the Qt side.&lt;/p&gt;
  2390. &lt;h2&gt;Future possibilities&lt;/h2&gt;
  2391. &lt;p&gt;Servo development is &lt;a href="https://servo.org/blog/2023/12/18/this-year-in-servo/"&gt;active&lt;/a&gt; again after a period of less activity, therefore the API is evolving and there is work to improve the API for &lt;a href="https://servo.org/blog/2024/01/19/embedding-update/"&gt;embedders&lt;/a&gt;. This could result in a simpler and documented process for integrating Servo into apps. Also as part of the &lt;a href="https://tauri.app/"&gt;Tauri&lt;/a&gt; and Servo &lt;a href="https://nlnet.nl/project/Tauri-Servo/"&gt;collaboration&lt;/a&gt;, a backend for &lt;a href="https://github.com/tauri-apps/wry"&gt;WRY&lt;/a&gt; could become available. All of these result in many possible changes for the bridge to Qt, as currently this demo directly constructs Servo components (similar to servoshell) but could instead use a shared library or WRY instead.&lt;/p&gt;
  2392. &lt;p&gt;On the Qt side, there are areas that could be improved or investigated further. For example, currently we are using a framebuffer object which forces use of the OpenGL backend, but with RHI, developers might want to use other backends. A way to solve this for QML would be to change the implementation to instead use a custom Qt Scene Graph node, which can then have implementations for Vulkan, OpenGL etc and read from the Servo engine.&lt;/p&gt;
  2393. &lt;p&gt;Alternatively &lt;a href="https://www.qt.io/blog/qt-6.7-released#hybrid-applications-with-native-ui-elements-and-rendering"&gt;Qt 6.7 has introduced a new QQuickRhiItem element&lt;/a&gt;, which is currently a technical preview, but can be used as a &lt;a href="https://doc-snapshots.qt.io/qt6-6.7/qquickrhiitem.html"&gt;rendering API-agnostic alternative to QQuickFrameBufferObject&lt;/a&gt;.&lt;/p&gt;
  2394. &lt;p&gt;If this sounds interesting to your use case or you would like to collaborate with us, the code for this tech demo is available on GitHub under &lt;a href="https://github.com/KDABLabs/cxx-qt-servo-webview"&gt;KDABLabs/cxx-qt-servo-webview&lt;/a&gt; or &lt;a href="https://www.kdab.com/about/contact/"&gt;contact KDAB directly&lt;/a&gt;. We also have a &lt;a href="https://cxx-qt.zulipchat.com"&gt;Zulip chat&lt;/a&gt; if you want to discuss any parts of bridging Servo or CXX-Qt with us.&lt;/p&gt;
  2395. &lt;p&gt;Come and see us at &lt;a href="https://www.embedded-world.de/en"&gt;Embedded World 2024&lt;/a&gt; where we will have the Servo demo and &lt;a href="https://www.kdab.com/kdab-at-embedded-world-2024/"&gt;others&lt;/a&gt; on display!&lt;/p&gt;
  2396. &lt;p&gt;&#xA0;&lt;/p&gt;
  2397. &lt;p&gt;The post &lt;a href="https://www.kdab.com/embedding-servo-in-qt/"&gt;Embedding the Servo Web Engine in Qt&lt;/a&gt; appeared first on &lt;a href="https://www.kdab.com"&gt;KDAB&lt;/a&gt;.&lt;/p&gt;</description>
  2398.    </item>
  2399.    <item>
  2400.      <guid isPermaLink="false">https://www.basyskom.de/?p=8828</guid>
  2401.      <title>Qt &#x2013; basysKom GmbH: Use Compute Shader in Qt Quick</title>
  2402.      <pubDate>Tue, 02 Apr 2024 09:14:23 GMT</pubDate>
  2403.      <link>https://www.basyskom.de/2024/use-compute-shader-in-qt-quick/</link>
  2404.      <description>&lt;p&gt;&lt;a href="https://www.basyskom.de/2024/use-compute-shader-in-qt-quick/"&gt;&lt;img align="left" alt="Use Compute Shader in Qt Quick" height="150" src="https://www.basyskom.de/wp-content/uploads/2020/07/Qt_logo_space-01-01-300x150.png" style="margin: 0 20px 20px 0;" width="300"&gt;&lt;/a&gt;&lt;/p&gt;
  2405. &lt;p&gt;With this blog post, we introduce the&#xA0;QtQuickComputeItem&#xA0;- a Qt Quick item that allows you to easily integrate compute shader into your Qt Quick Code.&lt;br&gt;
  2406. Compute&lt;br&gt;
  2407. Shader are used to perform arbitrary computations on the GPU. For&lt;br&gt;
  2408. example, the screenshot below shows a Qt Quick application that&lt;br&gt;
  2409. generates Gray Scott Reaction Diffusion patterns.&#xA0; The simulation is executed by a compute shader that is configured directly in QML.&lt;/p&gt;
  2410. &lt;p&gt;&lt;a href="https://www.basyskom.de/2024/use-compute-shader-in-qt-quick/" rel="nofollow"&gt;Continue reading Use Compute Shader in Qt Quick at basysKom GmbH.&lt;/a&gt;&lt;/p&gt;</description>
  2411.    </item>
  2412.    <item>
  2413.      <guid isPermaLink="false">tag:www.pythonguis.com,2024-03-27:/faq/adding-images-to-pyside6-applications/</guid>
  2414.      <title>Python GUIs - qt: Q&amp;A: How Do I Display Images in PySide6? &#x2014; Using QLabel to easily add images to your applications</title>
  2415.      <pubDate>Wed, 27 Mar 2024 06:00:00 GMT</pubDate>
  2416.      <link>https://www.pythonguis.com/faq/adding-images-to-pyside6-applications/</link>
  2417.      <description>&lt;p&gt;Adding images to your application is a common requirement, whether you're building an image/photo viewer, or just want to add some decoration to your GUI. Unfortunately, because of how this is done in Qt, it can be a little bit tricky to work out at first.&lt;/p&gt;
  2418. &lt;p&gt;In this short tutorial, we will look at how you can insert an external image into your PySide6 application layout, using both code and Qt Designer.&lt;/p&gt;
  2419. &lt;div class="toc"&gt;&lt;span class="toctitle"&gt;Table of Contents&lt;/span&gt;
  2420. &lt;ul&gt;
  2421. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#which-widget-to-use"&gt;Which widget to use?&lt;/a&gt;&lt;/li&gt;
  2422. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#using-qt-designer"&gt;Using Qt Designer&lt;/a&gt;&lt;/li&gt;
  2423. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#using-code"&gt;Using Code&lt;/a&gt;&lt;/li&gt;
  2424. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  2425. &lt;/ul&gt;
  2426. &lt;/div&gt;
  2427. &lt;h3 id="which-widget-to-use"&gt;Which widget to use?&lt;/h3&gt;
  2428. &lt;p&gt;Since you're wanting to insert an image you might be expecting to use a widget named &lt;code&gt;QImage&lt;/code&gt; or similar, but that would make a bit too much sense! &lt;code&gt;QImage&lt;/code&gt; is actually Qt's image &lt;em&gt;object&lt;/em&gt; type, which is used to store the actual image data for use within your application. The &lt;em&gt;widget&lt;/em&gt; you use to display an image is &lt;code&gt;QLabel&lt;/code&gt;.&lt;/p&gt;
  2429. &lt;p&gt;The primary use of &lt;code&gt;QLabel&lt;/code&gt; is of course to add labels to a UI, but it also has the ability to display an image &#x2014; or &lt;em&gt;pixmap&lt;/em&gt; &#x2014; instead, covering the entire area of the widget. Below we'll look at how to use &lt;code&gt;QLabel&lt;/code&gt; to display a widget in your applications.&lt;/p&gt;
  2430. &lt;h3 id="using-qt-designer"&gt;Using Qt Designer&lt;/h3&gt;
  2431. &lt;p&gt;First, create a &lt;em&gt;MainWindow&lt;/em&gt; object in Qt Designer and add a "Label" to it. You can find Label at in &lt;em&gt;Display Widgets&lt;/em&gt; in the bottom of the left hand panel. Drag this onto the &lt;code&gt;QMainWindow&lt;/code&gt; to add it.&lt;/p&gt;
  2432. &lt;p&gt;&lt;img alt="MainWindow with a single QLabel added" height="1027" src="https://www.pythonguis.com/static/faq/adding-images-to-applications/1.png" width="1917"&gt; &lt;em&gt;MainWindow with a single QLabel added&lt;/em&gt;&lt;/p&gt;
  2433. &lt;p&gt;Next, with the Label selected, look in the right hand &lt;code&gt;QLabel&lt;/code&gt; properties panel for the &lt;code&gt;pixmap&lt;/code&gt; property (scroll down to the blue region). From the property editor dropdown select "Choose File&#x2026;" and select an image file to insert.&lt;/p&gt;
  2434. &lt;div style="padding: 79.5% 0 0 0;"&gt;&lt;/div&gt;
  2435. &lt;p&gt;As you can see, the image is inserted, but the image is kept at its original size, cropped to the boundaries of the&lt;code&gt;QLabel&lt;/code&gt; box. You need to resize the &lt;code&gt;QLabel&lt;/code&gt; to be able to see the entire image.&lt;/p&gt;
  2436. &lt;p&gt;In the same controls panel, click to enable &lt;code&gt;scaledContents&lt;/code&gt;.&lt;/p&gt;
  2437. &lt;div style="padding: 79.5% 0 0 0;"&gt;&lt;/div&gt;
  2438. &lt;p&gt;When &lt;code&gt;scaledContents&lt;/code&gt; is enabled the image is resized to the fit the bounding box of the &lt;code&gt;QLabel&lt;/code&gt; widget. This shows the entire image at all times, although it does not respect the aspect ratio of the image if you resize the widget.&lt;/p&gt;
  2439. &lt;p&gt;You can now save your UI to file (e.g. as &lt;code&gt;mainwindow.ui&lt;/code&gt;).&lt;/p&gt;
  2440. &lt;p&gt;To view the resulting UI, we can use the standard application template below. This loads the &lt;code&gt;.ui&lt;/code&gt; file we've created (&lt;code&gt;mainwindow.ui&lt;/code&gt;) creates the window and starts up the application.&lt;/p&gt;
  2441. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-PySide6"&gt;PySide6&lt;/span&gt;
  2442. &lt;pre&gt;
  2443. &lt;code class="PySide6"&gt;import sys
  2444. from PySide6 import QtWidgets
  2445. from PySide6.QtUiTools import QUiLoader
  2446.  
  2447. loader = QUiLoader()
  2448. app = QtWidgets.QApplication(sys.argv)
  2449. window = loader.load("mainwindow.ui", None)
  2450. window.show()
  2451. app.exec()
  2452. &lt;/code&gt;
  2453. &lt;/pre&gt;&lt;/div&gt;
  2454. &lt;p&gt;Running the above code will create a window, with the image displayed in the middle.&lt;/p&gt;
  2455. &lt;p&gt;&lt;img alt="QtDesigner application showing a Cat" height="639" src="https://www.pythonguis.com/static/faq/adding-images-to-applications/5.png" width="802"&gt; &lt;em&gt;QtDesigner application showing a Cat&lt;/em&gt;&lt;/p&gt;
  2456. &lt;h3 id="using-code"&gt;Using Code&lt;/h3&gt;
  2457. &lt;p&gt;Instead of using Qt Designer, you might also want to show an image in your application through code. As before we use a &lt;code&gt;QLabel&lt;/code&gt; widget and add a &lt;em&gt;pixmap&lt;/em&gt; image to it. This is done using the &lt;code&gt;QLabel&lt;/code&gt; method &lt;code&gt;.setPixmap()&lt;/code&gt;. The full code is shown below.&lt;/p&gt;
  2458. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-PySide6"&gt;PySide6&lt;/span&gt;
  2459. &lt;pre&gt;
  2460. &lt;code class="PySide6"&gt;import sys
  2461. from PySide6.QtGui import QPixmap
  2462. from PySide6.QtWidgets import QMainWindow, QApplication, QLabel
  2463.  
  2464. class MainWindow(QMainWindow):
  2465.  
  2466.    def __init__(self):
  2467.        super(MainWindow, self).__init__()
  2468.        self.title = "Image Viewer"
  2469.        self.setWindowTitle(self.title)
  2470.  
  2471.        label = QLabel(self)
  2472.        pixmap = QPixmap('cat.jpg')
  2473.        label.setPixmap(pixmap)
  2474.        self.setCentralWidget(label)
  2475.        self.resize(pixmap.width(), pixmap.height())
  2476.  
  2477.  
  2478. app = QApplication(sys.argv)
  2479. w = MainWindow()
  2480. w.show()
  2481. sys.exit(app.exec())
  2482. &lt;/code&gt;
  2483. &lt;/pre&gt;&lt;/div&gt;
  2484. &lt;p&gt;The block of code below shows the process of creating the &lt;code&gt;QLabel&lt;/code&gt;, creating a &lt;code&gt;QPixmap&lt;/code&gt; object from our file &lt;code&gt;cat.jpg&lt;/code&gt; (passed as a file path), setting this &lt;code&gt;QPixmap&lt;/code&gt; onto the &lt;code&gt;QLabel&lt;/code&gt; with &lt;code&gt;.setPixmap()&lt;/code&gt; and then finally resizing the window to fit the image.&lt;/p&gt;
  2485. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2486. &lt;pre&gt;
  2487. &lt;code class="python"&gt;label = QLabel(self)
  2488. pixmap = QPixmap('cat.jpg')
  2489. label.setPixmap(pixmap)
  2490. self.setCentralWidget(label)
  2491. self.resize(pixmap.width(), pixmap.height())
  2492. &lt;/code&gt;
  2493. &lt;/pre&gt;&lt;/div&gt;
  2494. &lt;p&gt;Launching this code will show a window with the cat photo displayed and the window sized to the size of the image.&lt;/p&gt;
  2495. &lt;p&gt;&lt;img alt="QMainWindow with Cat image displayed" height="439" src="https://www.pythonguis.com/static/faq/adding-images-to-applications/4.png" width="602"&gt; &lt;em&gt;QMainWindow with Cat image displayed&lt;/em&gt;&lt;/p&gt;
  2496. &lt;p&gt;Just as in Qt designer, you can call &lt;code&gt;.setScaledContents(True)&lt;/code&gt; on your &lt;code&gt;QLabel&lt;/code&gt; image to enable scaled mode, which resizes the image to fit the available space.&lt;/p&gt;
  2497. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2498. &lt;pre&gt;
  2499. &lt;code class="python"&gt;label = QLabel(self)
  2500. pixmap = QPixmap('cat.jpg')
  2501. label.setPixmap(pixmap)
  2502. label.setScaledContents(True)
  2503. self.setCentralWidget(label)
  2504. self.resize(pixmap.width(), pixmap.height())
  2505. &lt;/code&gt;
  2506. &lt;/pre&gt;&lt;/div&gt;
  2507. &lt;p class="admonition admonition-note"&gt;Notice that you set the scaled state on the &lt;code&gt;QLabel&lt;/code&gt; widget and not the image pixmap itself.&lt;/p&gt;
  2508. &lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;
  2509. &lt;p&gt;In this quick tutorial we've covered how to insert images into your Qt UIs using &lt;code&gt;QLabel&lt;/code&gt; both from Qt Designer and directly from PySide6 code.&lt;/p&gt;</description>
  2510.    </item>
  2511.    <item>
  2512.      <guid isPermaLink="false">https://www.kdab.com/?p=33552</guid>
  2513.      <title>KDAB on Qt: Introducing the ConnectionEvaluator in KDBindings</title>
  2514.      <pubDate>Thu, 21 Mar 2024 08:00:17 GMT</pubDate>
  2515.      <link>https://www.kdab.com/introducing-the-connectionevaluator-in-kdbindings/</link>
  2516.      <description>&lt;p&gt;Managing the timing and context of signals and slots in multithreaded applications, especially those with a GUI, can be a complex task. The concept of deferred connection evaluation offers a nice and easy API, allowing for controlled and efficient signal-slot connections. This approach is particularly useful when dealing with worker threads and GUI threads.&lt;/p&gt;
  2517. &lt;p&gt;A classic example &lt;span class="hljs-keyword"&gt;where&lt;/span&gt; &lt;span class="hljs-keyword"&gt;cross&lt;/span&gt;-thread signal-slot connections are useful &lt;span class="hljs-keyword"&gt;is&lt;/span&gt; &lt;span class="hljs-keyword"&gt;when&lt;/span&gt; we have a worker thread performing &lt;span class="hljs-keyword"&gt;some&lt;/span&gt; computations &lt;span class="hljs-keyword"&gt;or&lt;/span&gt; data collection &lt;span class="hljs-keyword"&gt;and&lt;/span&gt; periodically emits signals. The GUI thread can &lt;span class="hljs-keyword"&gt;connect&lt;/span&gt; &lt;span class="hljs-keyword"&gt;to&lt;/span&gt; these signals &lt;span class="hljs-keyword"&gt;and&lt;/span&gt; &lt;span class="hljs-keyword"&gt;then&lt;/span&gt; display the data however it wishes. Graphical display usually must happen &lt;span class="hljs-keyword"&gt;on&lt;/span&gt; the main thread &lt;span class="hljs-keyword"&gt;and&lt;/span&gt; at specific times. Therefore, controlling exactly &lt;span class="hljs-keyword"&gt;when&lt;/span&gt; the receiving slots &lt;span class="hljs-keyword"&gt;get&lt;/span&gt; executed &lt;span class="hljs-keyword"&gt;is&lt;/span&gt; &lt;span class="hljs-keyword"&gt;of&lt;/span&gt; critical importance &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; correctness &lt;span class="hljs-keyword"&gt;and&lt;/span&gt; performance.&lt;/p&gt;
  2518. &lt;h2&gt;&lt;em&gt;A Quick Recap on Signals &amp; Slots and KDBindings&lt;/em&gt;&lt;/h2&gt;
  2519. &lt;p&gt;Signals and slots are integral to event handling in C++ applications. Signals, emitted upon certain events or conditions, trigger connected slots (functions or methods) to respond accordingly. This framework is highly effective, but there are cases where immediate slot invocation is not ideal, such as in multithreaded applications where you might want to emit a signal in one thread and handle it in another, like a GUI event loop.&lt;/p&gt;
  2520. &lt;p&gt;&lt;a href="https://github.com/KDAB/KDBindings"&gt;KDBindings&lt;/a&gt; &lt;span class="hljs-keyword"&gt;is&lt;/span&gt; a &lt;span class="hljs-keyword"&gt;header&lt;/span&gt;&#x2013;&lt;span class="hljs-keyword"&gt;only&lt;/span&gt; C++&lt;span class="hljs-number"&gt;17&lt;/span&gt; library that implements the signals &lt;span class="hljs-keyword"&gt;and&lt;/span&gt; slots design pattern. &lt;span class="hljs-keyword"&gt;In&lt;/span&gt; addition, KDBindings &lt;span class="hljs-keyword"&gt;also&lt;/span&gt; provides an easy &lt;span class="hljs-keyword"&gt;to&lt;/span&gt; use property &lt;span class="hljs-keyword"&gt;and&lt;/span&gt; bindings &lt;span class="hljs-keyword"&gt;system&lt;/span&gt; &lt;span class="hljs-keyword"&gt;to&lt;/span&gt; &lt;span class="hljs-keyword"&gt;enable&lt;/span&gt; reactive programming &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; C++. For more information, read &lt;a href="https://www.kdab.com/signals-slots-properties-bindings/"&gt;this introduction blog&lt;/a&gt;.&lt;/p&gt;
  2521. &lt;h2&gt;&lt;em&gt;Understanding Deferred Connection Evaluation&lt;/em&gt;&lt;/h2&gt;
  2522. &lt;p&gt;In Qt, a signal that should be evaluated on a different thread will be executed by the event loop of that thread. As &lt;a href="https://www.kdab.com/signals-slots-properties-bindings/"&gt;KDBindings&lt;/a&gt; doesn&#x2019;t have its own event loop and needs to be able to integrate into any framework, we&#x2019;re introducing the &lt;strong&gt;ConnectionEvaluator&lt;/strong&gt; as our solution to those nuanced requirements. It allows for a deferred evaluation of connections, providing a much-needed flexibility in handling signal emissions.&lt;/p&gt;
  2523. &lt;p&gt;In multithreaded environments, the immediate execution of slots in response to signals can lead to complications. Deferred connection evaluation addresses this by delaying the execution of a slot until a developer-determined point. This is achieved through a &lt;strong&gt;ConnectionEvaluator&lt;/strong&gt;, akin to a &lt;strong&gt;BindingEvaluator&lt;/strong&gt;, which governs when a slot is called.&lt;/p&gt;
  2524. &lt;h2&gt;&lt;em&gt;Implementing and Utilizing Deferred Connections&lt;/em&gt;&lt;/h2&gt;
  2525. &lt;p&gt;We have introduced &lt;strong&gt;connectDeferred.&lt;/strong&gt; This function, mirroring the standard connect method, takes a &lt;strong&gt;ConnectionEvaluator&lt;/strong&gt; as its first argument, followed by the standard signal and slot parameters.&lt;/p&gt;
  2526. &lt;p&gt;Signals emitted are queued in the &lt;strong&gt;ConnectionEvaluator&lt;/strong&gt; instead of immediately triggering the slot. Developers can then execute these queued slots at an appropriate time, akin to the &lt;strong&gt;evaluateAll&lt;/strong&gt; method in the &lt;strong&gt;BindingEvaluator&lt;/strong&gt;.&lt;/p&gt;
  2527. &lt;h4&gt;&lt;em&gt;How It Works&lt;/em&gt;&lt;/h4&gt;
  2528. &lt;p&gt;&lt;strong&gt;1. Create a ConnectionEvaluator:&lt;/strong&gt;&lt;/p&gt;
  2529. &lt;pre class="brush: cpp; title: ; notranslate"&gt;
  2530. auto evaluator = std::make_shared&lt;ConnectionEvaluator&gt;(); // Shared ownership for proper lifetime management
  2531. &lt;/pre&gt;
  2532. &lt;p&gt;&lt;strong&gt;2. Connect with Deferred Evaluation:&lt;/strong&gt;&lt;/p&gt;
  2533. &lt;pre class="brush: cpp; title: ; notranslate"&gt;
  2534. Signal&lt;int&gt; signal;
  2535. int value = 0;
  2536.  
  2537. auto connection = signal.connectDeferred(evaluator, [&amp;value](int increment) {
  2538. value += increment;
  2539. });
  2540. &lt;/pre&gt;
  2541. &lt;div class="line number6 index5 alt1"&gt;&lt;/div&gt;
  2542. &lt;p&gt;&lt;strong&gt;3. Queue Deferred Connections&lt;/strong&gt;&lt;/p&gt;
  2543. &lt;p&gt;When the signal emits, connected slots aren&#x2019;t executed immediately but are queued:&lt;/p&gt;
  2544. &lt;pre class="brush: cpp; title: ; notranslate"&gt;
  2545. signal.emit(5);  // The slot is queued, not executed.
  2546. &lt;/pre&gt;
  2547. &lt;p&gt;&lt;strong&gt;4. Evaluate Deferred Connections&lt;/strong&gt;&lt;/p&gt;
  2548. &lt;p&gt;Execute the queued connections at the desired time:&lt;/p&gt;
  2549. &lt;pre class="brush: cpp; title: ; notranslate"&gt;
  2550. evaluator.evaluateDeferredConnections();  // Executes the queued slot.
  2551. &lt;/pre&gt;
  2552. &lt;h4&gt;&lt;em&gt;Usage Example&lt;/em&gt;&lt;/h4&gt;
  2553. &lt;p&gt;To illustrate how this enhanced signal/slot system works in a multithreaded scenario, let&#x2019;s have a look at a usage example. Consider a scenario where a worker thread emits signals, but we want the connected slots to be executed in an event loop on the GUI thread:&lt;/p&gt;
  2554. &lt;pre class="brush: cpp; title: ; notranslate"&gt;
  2555. Signal&lt;int&gt; workerSignal;
  2556. int guiValue = 0;
  2557. auto evaluator = std::make_shared&lt;ConnectionEvaluator&gt;();
  2558.  
  2559. // Connect a slot to the workerSignal with deferred evaluation
  2560. workerSignal.connectDeferred(evaluator, [&amp;guiValue](int value) {
  2561. // This slot will be executed later in the GUI thread's event loop
  2562. guiValue += value;
  2563. });
  2564.  
  2565. // ... Worker thread emits signals ...
  2566.  
  2567. // In the GUI thread's event loop or at the right time
  2568. evaluator-&gt;evaluateDeferredConnections();
  2569.  
  2570. // The connected slot is now executed, and guiValue is updated
  2571. &lt;/pre&gt;
  2572. &lt;p&gt;In this example, the connectDeferred function allows us to queue the connection for deferred execution, and the ConnectionEvaluator determines when it should be invoked. This level of control enables more sophisticated and responsive applications.&lt;/p&gt;
  2573. &lt;h2&gt;&lt;em&gt;Conclusion&lt;/em&gt;&lt;/h2&gt;
  2574. &lt;p&gt;In simple terms, the ConnectionEvaluator is a valuable tool we&#x2019;ve added to KDBindings. It lets you decide when exactly your connections should &#x2018;wake up&#x2019; and do their jobs. This is especially helpful in complex applications where you want to make sure that certain tasks are performed at the right time and in the right order (preferably in multithreading applications). Think of it like having a remote control for your connections, allowing you to press &#x2018;play&#x2019; whenever you&#x2019;re ready.&lt;/p&gt;
  2575. &lt;p&gt;It may also be worthwhile mentioning that we will be integrating this feature into the KDFoundation library and event loop in the &lt;a href="https://github.com/KDAB/KDUtils"&gt;KDUtils GitHub repo&lt;/a&gt;. Additionally, it&#x2019;s important to note that it could easily be integrated into any application or framework, regardless of whether it utilizes an event loop.&lt;/p&gt;
  2576. &lt;div class="panel panel-info"&gt;
  2577. &lt;div class="panel-heading"&gt;About KDAB&lt;/div&gt;
  2578. &lt;div class="panel-body"&gt;
  2579. &lt;p&gt;If you like this article and want to read similar material, consider subscribing via &lt;a href="https://www.kdab.com/category/blogs/feed/"&gt;our RSS feed&lt;/a&gt;.&lt;/p&gt;
  2580. &lt;p&gt;Subscribe to &lt;a href="https://www.youtube.com/kdabtv"&gt;KDAB TV&lt;/a&gt; for similar informative short video content.&lt;/p&gt;
  2581. &lt;p&gt;KDAB provides market leading software consulting and development &lt;a href="https://www.kdab.com/software-services/"&gt;services&lt;/a&gt; and &lt;a href="https://training.kdab.com/"&gt;training&lt;/a&gt; in Qt, C++ and 3D/OpenGL. &lt;a href="https://www.kdab.com/about/contact/"&gt;Contact us&lt;/a&gt;.&lt;/p&gt;
  2582. &lt;/div&gt;
  2583. &lt;/div&gt;
  2584. &lt;p&gt;The post &lt;a href="https://www.kdab.com/introducing-the-connectionevaluator-in-kdbindings/"&gt;Introducing the ConnectionEvaluator in KDBindings&lt;/a&gt; appeared first on &lt;a href="https://www.kdab.com"&gt;KDAB&lt;/a&gt;.&lt;/p&gt;</description>
  2585.    </item>
  2586.    <item>
  2587.      <guid isPermaLink="false">tag:www.pythonguis.com,2024-03-06:/faq/pyside6-drag-drop-widgets/</guid>
  2588.      <title>Python GUIs - qt: Drag &amp; Drop Widgets with PySide6 &#x2014; Sort widgets visually with drag and drop in a container</title>
  2589.      <pubDate>Wed, 06 Mar 2024 13:00:00 GMT</pubDate>
  2590.      <link>https://www.pythonguis.com/faq/pyside6-drag-drop-widgets/</link>
  2591.      <description>&lt;p&gt;I had an interesting question from a reader of my &lt;a href="https://www.pythonguis.com/pyside6-book/"&gt;PySide6 book&lt;/a&gt;, about how to handle dragging and dropping of widgets in a container showing the dragged widget as it is moved.&lt;/p&gt;
  2592. &lt;blockquote&gt;
  2593. &lt;p&gt;I'm interested in managing movement of a QWidget with mouse in a container. I've implemented the application with drag &amp; drop, exchanging the position of buttons, but I want to show the motion of &lt;code&gt;QPushButton&lt;/code&gt;, like what you see in Qt Designer. Dragging a widget should show the widget itself, not just the mouse pointer.&lt;/p&gt;
  2594. &lt;/blockquote&gt;
  2595. &lt;p&gt;First, we'll implement the simple case which drags widgets without showing anything extra. Then we can extend it to answer the question. By the end of this quick tutorial we'll have a generic drag drop implementation which looks like the following.&lt;/p&gt;
  2596. &lt;div style="padding: 79.5% 0 0 0;"&gt;&lt;/div&gt;
  2597. &lt;div class="toc"&gt;&lt;span class="toctitle"&gt;Table of Contents&lt;/span&gt;
  2598. &lt;ul&gt;
  2599. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#drag-drop-widgets"&gt;Drag &amp; Drop Widgets&lt;/a&gt;&lt;/li&gt;
  2600. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#visual-drag-drop"&gt;Visual Drag &amp; Drop&lt;/a&gt;&lt;/li&gt;
  2601. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#generic-drag-drop-container"&gt;Generic Drag &amp; Drop Container&lt;/a&gt;&lt;/li&gt;
  2602. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#adding-a-visual-drop-target"&gt;Adding a Visual Drop Target&lt;/a&gt;&lt;/li&gt;
  2603. &lt;/ul&gt;
  2604. &lt;/div&gt;
  2605. &lt;h2 id="drag-drop-widgets"&gt;Drag &amp; Drop Widgets&lt;/h2&gt;
  2606. &lt;p&gt;We'll start with a simple application which creates a window using &lt;code&gt;QWidget&lt;/code&gt; and places a series of &lt;code&gt;QPushButton&lt;/code&gt; widgets into it.&lt;/p&gt;
  2607. &lt;p class="admonition admonition-tip"&gt;You can substitute &lt;code&gt;QPushButton&lt;/code&gt; for any other widget you like, e.g. &lt;code&gt;QLabel&lt;/code&gt;. Any widget can have drag behavior implemented on it, although some input widgets will not work well as we capture the mouse events for the drag.&lt;/p&gt;
  2608. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2609. &lt;pre&gt;
  2610. &lt;code class="python"&gt;from PySide6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QWidget
  2611.  
  2612.  
  2613. class Window(QWidget):
  2614.    def __init__(self):
  2615.        super().__init__()
  2616.  
  2617.        self.blayout = QHBoxLayout()
  2618.        for l in ["A", "B", "C", "D"]:
  2619.            btn = QPushButton(l)
  2620.            self.blayout.addWidget(btn)
  2621.  
  2622.        self.setLayout(self.blayout)
  2623.  
  2624.  
  2625. app = QApplication([])
  2626. w = Window()
  2627. w.show()
  2628.  
  2629. app.exec()
  2630.  
  2631. &lt;/code&gt;
  2632. &lt;/pre&gt;&lt;/div&gt;
  2633. &lt;p&gt;If you run this you should see something like this.&lt;/p&gt;
  2634. &lt;p&gt;&lt;img alt="Widgets in a layout" height="93" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/windows-in-layout.png" width="421"&gt; &lt;em&gt;The series of &lt;code&gt;QPushButton widgets&lt;/code&gt; in a horizontal layout.&lt;/em&gt;&lt;/p&gt;
  2635. &lt;p class="admonition admonition-note"&gt;Here we're creating a window, but the &lt;code&gt;Window&lt;/code&gt; widget is subclassed from &lt;code&gt;QWidget&lt;/code&gt;, meaning you can add this widget to any other layout. See later for an example of a generic object sorting widget.&lt;/p&gt;
  2636. &lt;p&gt;&lt;code&gt;QPushButton&lt;/code&gt; objects aren't usually draggable, so to handle the mouse movements and initiate a drag we need to implement a subclass. We can add the following to the top of the file.&lt;/p&gt;
  2637. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2638. &lt;pre&gt;
  2639. &lt;code class="python"&gt;from PySide6.QtCore import QMimeData, Qt
  2640. from PySide6.QtGui import QDrag
  2641. from PySide6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QWidget
  2642.  
  2643.  
  2644. class DragButton(QPushButton):
  2645.    def mouseMoveEvent(self, e):
  2646.        if e.buttons() == Qt.MouseButton.LeftButton:
  2647.            drag = QDrag(self)
  2648.            mime = QMimeData()
  2649.            drag.setMimeData(mime)
  2650.            drag.exec(Qt.DropAction.MoveAction)
  2651.  
  2652. &lt;/code&gt;
  2653. &lt;/pre&gt;&lt;/div&gt;
  2654. &lt;p&gt;We implement a &lt;code&gt;mouseMoveEvent&lt;/code&gt; which accepts the single &lt;code&gt;e&lt;/code&gt; parameter of the event. We check to see if the &lt;em&gt;left&lt;/em&gt; mouse button is pressed on this event -- as it would be when dragging -- and then initiate a drag. To start a drag, we create a &lt;code&gt;QDrag&lt;/code&gt; object, passing in &lt;code&gt;self&lt;/code&gt; to give us access later to the widget that was dragged. We also &lt;em&gt;must&lt;/em&gt; pass in mime data. This is used for including information about what is dragged, particularly for passing data between applications. However, as here, it is fine to leave this empty.&lt;/p&gt;
  2655. &lt;p&gt;Finally, we initiate a drag by calling &lt;code&gt;drag.exec_(Qt.MoveAction)&lt;/code&gt;. As with dialogs &lt;code&gt;exec_()&lt;/code&gt; starts a new event loop, blocking the main loop until the drag is complete. The parameter &lt;code&gt;Qt.MoveAction&lt;/code&gt; tells the drag handler what type of operation is happening, so it can show the appropriate icon tip to the user.&lt;/p&gt;
  2656. &lt;p&gt;You can update the main window code to use our new &lt;code&gt;DragButton&lt;/code&gt; class as follows.&lt;/p&gt;
  2657. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2658. &lt;pre&gt;
  2659. &lt;code class="python"&gt;class Window(QWidget):
  2660.    def __init__(self):
  2661.        super().__init__()
  2662.        self.setAcceptDrops(True)
  2663.  
  2664.        self.blayout = QHBoxLayout()
  2665.        for l in ["A", "B", "C", "D"]:
  2666.            btn = DragButton(l)
  2667.            self.blayout.addWidget(btn)
  2668.  
  2669.        self.setLayout(self.blayout)
  2670.  
  2671.    def dragEnterEvent(self, e):
  2672.        e.accept()
  2673. &lt;/code&gt;
  2674. &lt;/pre&gt;&lt;/div&gt;
  2675. &lt;p&gt;If you run the code now, you &lt;em&gt;can&lt;/em&gt; drag the buttons, but you'll notice the drag is forbidden.&lt;/p&gt;
  2676. &lt;p&gt;&lt;img alt="Drag forbidden" height="93" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-forbidden.png" width="421"&gt; &lt;em&gt;Dragging of the widget starts but is forbidden.&lt;/em&gt;&lt;/p&gt;
  2677. &lt;p&gt;What's happening? The mouse movement is being detected by our &lt;code&gt;DragButton&lt;/code&gt; object and the drag started, but the main window does not accept drag &amp; drop.&lt;/p&gt;
  2678. &lt;p&gt;To fix this we need to enable drops on the window and implement &lt;code&gt;dragEnterEvent&lt;/code&gt; to actually accept them.&lt;/p&gt;
  2679. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2680. &lt;pre&gt;
  2681. &lt;code class="python"&gt;class Window(QWidget):
  2682.    def __init__(self):
  2683.        super().__init__()
  2684.        self.setAcceptDrops(True)
  2685.  
  2686.        self.blayout = QHBoxLayout()
  2687.        for l in ["A", "B", "C", "D"]:
  2688.            btn = DragButton(l)
  2689.            self.blayout.addWidget(btn)
  2690.  
  2691.        self.setLayout(self.blayout)
  2692.  
  2693.    def dragEnterEvent(self, e):
  2694.        e.accept()
  2695.  
  2696. &lt;/code&gt;
  2697. &lt;/pre&gt;&lt;/div&gt;
  2698. &lt;p&gt;If you run this now, you'll see the drag is now accepted and you see the move icon. This indicates that the drag has started and been accepted by the window we're dragging onto. The icon shown is determined by the action we pass when calling &lt;code&gt;drag.exec_()&lt;/code&gt;.&lt;/p&gt;
  2699. &lt;p&gt;&lt;img alt="Drag accepted" height="93" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-accepted.png" width="421"&gt; &lt;em&gt;Dragging of the widget starts and is accepted, showing a move icon.&lt;/em&gt;&lt;/p&gt;
  2700. &lt;p&gt;Releasing the mouse button during a drag drop operation triggers a &lt;code&gt;dropEvent&lt;/code&gt; on the widget you're currently hovering the mouse over (if it is configured to accept drops). In our case that's the window. To handle the move we need to implement the code to do this in our &lt;code&gt;dropEvent&lt;/code&gt; method.&lt;/p&gt;
  2701. &lt;p&gt;The drop event contains the position the mouse was at when the button was released &amp; the drop triggered. We can use this to determine where to move the widget to.&lt;/p&gt;
  2702. &lt;p&gt;To determine where to place the widget, we iterate over all the widgets in the layout, &lt;em&gt;until&lt;/em&gt; we find one who's &lt;code&gt;x&lt;/code&gt; position is &lt;em&gt;greater&lt;/em&gt; than that of the mouse pointer. If so then when insert the widget directly to the left of this widget and exit the loop.&lt;/p&gt;
  2703. &lt;p&gt;If we get to the end of the loop without finding a match, we must be dropping past the end of the existing items, so we increment &lt;code&gt;n&lt;/code&gt; one further (in the &lt;code&gt;else:&lt;/code&gt; block below).&lt;/p&gt;
  2704. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2705. &lt;pre&gt;
  2706. &lt;code class="python"&gt;    def dropEvent(self, e):
  2707.        pos = e.position()
  2708.        widget = e.source()
  2709.        self.blayout.removeWidget(widget)
  2710.  
  2711.        for n in range(self.blayout.count()):
  2712.            # Get the widget at each index in turn.
  2713.            w = self.blayout.itemAt(n).widget()
  2714.            if pos.x() &lt; w.x():
  2715.                # We didn't drag past this widget.
  2716.                # insert to the left of it.
  2717.                break
  2718.        else:
  2719.            # We aren't on the left hand side of any widget,
  2720.            # so we're at the end. Increment 1 to insert after.
  2721.            n += 1
  2722.  
  2723.        self.blayout.insertWidget(n, widget)
  2724.  
  2725.        e.accept()
  2726. &lt;/code&gt;
  2727. &lt;/pre&gt;&lt;/div&gt;
  2728. &lt;p&gt;The effect of this is that if you drag 1 pixel past the start of another widget the drop will happen to the right of it, which is a bit confusing. To fix this we can adjust the cut off to use the middle of the widget using &lt;code&gt;if pos.x() &lt; w.x() + w.size().width() // 2:&lt;/code&gt; -- that is x + half of the width.&lt;/p&gt;
  2729. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2730. &lt;pre&gt;
  2731. &lt;code class="python"&gt;    def dropEvent(self, e):
  2732.        pos = e.position()
  2733.        widget = e.source()
  2734.        self.blayout.removeWidget(widget)
  2735.  
  2736.        for n in range(self.blayout.count()):
  2737.            # Get the widget at each index in turn.
  2738.            w = self.blayout.itemAt(n).widget()
  2739.            if pos.x() &lt; w.x() + w.size().width() // 2:
  2740.                # We didn't drag past this widget.
  2741.                # insert to the left of it.
  2742.                break
  2743.        else:
  2744.            # We aren't on the left hand side of any widget,
  2745.            # so we're at the end. Increment 1 to insert after.
  2746.            n += 1
  2747.  
  2748.        self.blayout.insertWidget(n, widget)
  2749.  
  2750.        e.accept()
  2751.  
  2752. &lt;/code&gt;
  2753. &lt;/pre&gt;&lt;/div&gt;
  2754. &lt;p&gt;The complete working drag-drop code is shown below.&lt;/p&gt;
  2755. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2756. &lt;pre&gt;
  2757. &lt;code class="python"&gt;from PySide6.QtCore import QMimeData, Qt
  2758. from PySide6.QtGui import QDrag
  2759. from PySide6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QWidget
  2760.  
  2761.  
  2762. class DragButton(QPushButton):
  2763.    def mouseMoveEvent(self, e):
  2764.        if e.buttons() == Qt.MouseButton.LeftButton:
  2765.            drag = QDrag(self)
  2766.            mime = QMimeData()
  2767.            drag.setMimeData(mime)
  2768.            drag.exec(Qt.DropAction.MoveAction)
  2769.  
  2770.  
  2771. class Window(QWidget):
  2772.    def __init__(self):
  2773.        super().__init__()
  2774.        self.setAcceptDrops(True)
  2775.  
  2776.        self.blayout = QHBoxLayout()
  2777.        for l in ["A", "B", "C", "D"]:
  2778.            btn = DragButton(l)
  2779.            self.blayout.addWidget(btn)
  2780.  
  2781.        self.setLayout(self.blayout)
  2782.  
  2783.    def dragEnterEvent(self, e):
  2784.        e.accept()
  2785.  
  2786.    def dropEvent(self, e):
  2787.        pos = e.position()
  2788.        widget = e.source()
  2789.        self.blayout.removeWidget(widget)
  2790.  
  2791.        for n in range(self.blayout.count()):
  2792.            # Get the widget at each index in turn.
  2793.            w = self.blayout.itemAt(n).widget()
  2794.            if pos.x() &lt; w.x() + w.size().width() // 2:
  2795.                # We didn't drag past this widget.
  2796.                # insert to the left of it.
  2797.                break
  2798.        else:
  2799.            # We aren't on the left hand side of any widget,
  2800.            # so we're at the end. Increment 1 to insert after.
  2801.            n += 1
  2802.  
  2803.        self.blayout.insertWidget(n, widget)
  2804.  
  2805.        e.accept()
  2806.  
  2807.  
  2808. app = QApplication([])
  2809. w = Window()
  2810. w.show()
  2811.  
  2812. app.exec()
  2813.  
  2814. &lt;/code&gt;
  2815. &lt;/pre&gt;&lt;/div&gt;
  2816. &lt;h2 id="visual-drag-drop"&gt;Visual Drag &amp; Drop&lt;/h2&gt;
  2817. &lt;p&gt;We now have a working drag &amp; drop implementation. Next we'll move onto improving the UX by showing the drag visually. First we'll add support for showing the button being dragged next to the mouse point as it is dragged. That way the user knows exactly what it is they are dragging.&lt;/p&gt;
  2818. &lt;p&gt;Qt's &lt;code&gt;QDrag&lt;/code&gt; handler natively provides a mechanism for showing dragged objects which we can use. We can update our &lt;code&gt;DragButton&lt;/code&gt; class to pass a &lt;em&gt;pixmap&lt;/em&gt; image to &lt;code&gt;QDrag&lt;/code&gt; and this will be displayed under the mouse pointer as the drag occurs. To show the widget, we just need to get a &lt;code&gt;QPixmap&lt;/code&gt; of the widget we're dragging.&lt;/p&gt;
  2819. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2820. &lt;pre&gt;
  2821. &lt;code class="python"&gt;from PySide6.QtCore import QMimeData, Qt
  2822. from PySide6.QtGui import QDrag
  2823. from PySide6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QWidget
  2824.  
  2825.  
  2826. class DragButton(QPushButton):
  2827.    def mouseMoveEvent(self, e):
  2828.        if e.buttons() == Qt.MouseButton.LeftButton:
  2829.            drag = QDrag(self)
  2830.            mime = QMimeData()
  2831.            drag.setMimeData(mime)
  2832.            drag.exec(Qt.DropAction.MoveAction)
  2833.  
  2834. &lt;/code&gt;
  2835. &lt;/pre&gt;&lt;/div&gt;
  2836. &lt;p&gt;To create the pixmap we create a &lt;code&gt;QPixmap&lt;/code&gt; object passing in the size of the widget this event is fired on with &lt;code&gt;self.size()&lt;/code&gt;. This creates an empty &lt;em&gt;pixmap&lt;/em&gt; which we can then pass into &lt;code&gt;self.render&lt;/code&gt; to &lt;em&gt;render&lt;/em&gt; -- or draw -- the current widget onto it. That's it. Then we set the resulting pixmap on the &lt;code&gt;drag&lt;/code&gt; object.&lt;/p&gt;
  2837. &lt;p&gt;If you run the code with this modification you'll see something like the following --&lt;/p&gt;
  2838. &lt;p&gt;&lt;img alt="Drag visual" height="93" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-visual.png" width="421"&gt; &lt;em&gt;Dragging of the widget showing the dragged widget.&lt;/em&gt;&lt;/p&gt;
  2839. &lt;h2 id="generic-drag-drop-container"&gt;Generic Drag &amp; Drop Container&lt;/h2&gt;
  2840. &lt;p&gt;We now have a working drag and drop behavior implemented on our window. We can take this a step further and implement a &lt;em&gt;generic&lt;/em&gt; drag drop widget which allows us to sort arbitrary objects. In the code below we've created a new widget &lt;code&gt;DragWidget&lt;/code&gt; which can be added to any window.&lt;/p&gt;
  2841. &lt;p&gt;You can add &lt;em&gt;items&lt;/em&gt; -- instances of &lt;code&gt;DragItem&lt;/code&gt; -- which you want to be sorted, as well as setting data on them. When items are re-ordered the new order is emitted as a signal &lt;code&gt;orderChanged&lt;/code&gt;.&lt;/p&gt;
  2842. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2843. &lt;pre&gt;
  2844. &lt;code class="python"&gt;from PySide6.QtCore import QMimeData, Qt, Signal
  2845. from PySide6.QtGui import QDrag, QPixmap
  2846. from PySide6.QtWidgets import (
  2847.    QApplication,
  2848.    QHBoxLayout,
  2849.    QLabel,
  2850.    QMainWindow,
  2851.    QVBoxLayout,
  2852.    QWidget,
  2853. )
  2854.  
  2855.  
  2856. class DragItem(QLabel):
  2857.    def __init__(self, *args, **kwargs):
  2858.        super().__init__(*args, **kwargs)
  2859.        self.setContentsMargins(25, 5, 25, 5)
  2860.        self.setAlignment(Qt.AlignmentFlag.AlignCenter)
  2861.        self.setStyleSheet("border: 1px solid black;")
  2862.        # Store data separately from display label, but use label for default.
  2863.        self.data = self.text()
  2864.  
  2865.    def set_data(self, data):
  2866.        self.data = data
  2867.  
  2868.    def mouseMoveEvent(self, e):
  2869.        if e.buttons() == Qt.MouseButton.LeftButton:
  2870.            drag = QDrag(self)
  2871.            mime = QMimeData()
  2872.            drag.setMimeData(mime)
  2873.  
  2874.            pixmap = QPixmap(self.size())
  2875.            self.render(pixmap)
  2876.            drag.setPixmap(pixmap)
  2877.  
  2878.            drag.exec(Qt.DropAction.MoveAction)
  2879.  
  2880.  
  2881. class DragWidget(QWidget):
  2882.    """
  2883.    Generic list sorting handler.
  2884.    """
  2885.  
  2886.    orderChanged = Signal(list)
  2887.  
  2888.    def __init__(self, *args, orientation=Qt.Orientation.Vertical, **kwargs):
  2889.        super().__init__()
  2890.        self.setAcceptDrops(True)
  2891.  
  2892.        # Store the orientation for drag checks later.
  2893.        self.orientation = orientation
  2894.  
  2895.        if self.orientation == Qt.Orientation.Vertical:
  2896.            self.blayout = QVBoxLayout()
  2897.        else:
  2898.            self.blayout = QHBoxLayout()
  2899.  
  2900.        self.setLayout(self.blayout)
  2901.  
  2902.    def dragEnterEvent(self, e):
  2903.        e.accept()
  2904.  
  2905.    def dropEvent(self, e):
  2906.        pos = e.position()
  2907.        widget = e.source()
  2908.        self.blayout.removeWidget(widget)
  2909.  
  2910.        for n in range(self.blayout.count()):
  2911.            # Get the widget at each index in turn.
  2912.            w = self.blayout.itemAt(n).widget()
  2913.            if self.orientation == Qt.Orientation.Vertical:
  2914.                # Drag drop vertically.
  2915.                drop_here = pos.y() &lt; w.y() + w.size().height() // 2
  2916.            else:
  2917.                # Drag drop horizontally.
  2918.                drop_here = pos.x() &lt; w.x() + w.size().width() // 2
  2919.  
  2920.            if drop_here:
  2921.                break
  2922.  
  2923.        else:
  2924.            # We aren't on the left hand/upper side of any widget,
  2925.            # so we're at the end. Increment 1 to insert after.
  2926.            n += 1
  2927.  
  2928.        self.blayout.insertWidget(n, widget)
  2929.        self.orderChanged.emit(self.get_item_data())
  2930.  
  2931.        e.accept()
  2932.  
  2933.    def add_item(self, item):
  2934.        self.blayout.addWidget(item)
  2935.  
  2936.    def get_item_data(self):
  2937.        data = []
  2938.        for n in range(self.blayout.count()):
  2939.            # Get the widget at each index in turn.
  2940.            w = self.blayout.itemAt(n).widget()
  2941.            data.append(w.data)
  2942.        return data
  2943.  
  2944.  
  2945. class MainWindow(QMainWindow):
  2946.    def __init__(self):
  2947.        super().__init__()
  2948.        self.drag = DragWidget(orientation=Qt.Orientation.Vertical)
  2949.        for n, l in enumerate(["A", "B", "C", "D"]):
  2950.            item = DragItem(l)
  2951.            item.set_data(n)  # Store the data.
  2952.            self.drag.add_item(item)
  2953.  
  2954.        # Print out the changed order.
  2955.        self.drag.orderChanged.connect(print)
  2956.  
  2957.        container = QWidget()
  2958.        layout = QVBoxLayout()
  2959.        layout.addStretch(1)
  2960.        layout.addWidget(self.drag)
  2961.        layout.addStretch(1)
  2962.        container.setLayout(layout)
  2963.  
  2964.        self.setCentralWidget(container)
  2965.  
  2966.  
  2967. app = QApplication([])
  2968. w = MainWindow()
  2969. w.show()
  2970.  
  2971. app.exec()
  2972.  
  2973. &lt;/code&gt;
  2974. &lt;/pre&gt;&lt;/div&gt;
  2975. &lt;p&gt;&lt;img alt="Generic drag drop horizontal" height="139" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-generic-horizontal.png" width="306"&gt; &lt;em&gt;Generic drag-drop sorting in horizontal orientation.&lt;/em&gt;&lt;/p&gt;
  2976. &lt;p&gt;You'll notice that when creating the item, you can set the label by passing it in as a parameter (just like for a normal &lt;code&gt;QLabel&lt;/code&gt; which we've subclassed from). But you can also set a data value, which is the internal value of this item -- this is what will be emitted when the order changes, or if you call &lt;code&gt;get_item_data&lt;/code&gt; yourself. This separates the visual representation from what is actually being sorted, meaning you can use this to sort &lt;em&gt;anything&lt;/em&gt; not just strings.&lt;/p&gt;
  2977. &lt;p&gt;In the example above we're passing in the enumerated index as the data, so dragging will output (via the &lt;code&gt;print&lt;/code&gt; connected to &lt;code&gt;orderChanged&lt;/code&gt;) something like:&lt;/p&gt;
  2978. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2979. &lt;pre&gt;
  2980. &lt;code class="python"&gt;[1, 0, 2, 3]
  2981. [1, 2, 0, 3]
  2982. [1, 0, 2, 3]
  2983. [1, 2, 0, 3]
  2984. &lt;/code&gt;
  2985. &lt;/pre&gt;&lt;/div&gt;
  2986. &lt;p&gt;If you remove the &lt;code&gt;item.set_data(n)&lt;/code&gt; you'll see the labels emitted on changes.&lt;/p&gt;
  2987. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  2988. &lt;pre&gt;
  2989. &lt;code class="python"&gt;['B', 'A', 'C', 'D']
  2990. ['B', 'C', 'A', 'D']
  2991. &lt;/code&gt;
  2992. &lt;/pre&gt;&lt;/div&gt;
  2993. &lt;p&gt;We've also implemented &lt;em&gt;orientation&lt;/em&gt; onto the &lt;code&gt;DragWidget&lt;/code&gt; using the Qt built in flags &lt;code&gt;Qt.Orientation.Vertical&lt;/code&gt; or &lt;code&gt;Qt.Orientation.Horizontal&lt;/code&gt;. This setting this allows you sort items either vertically or horizontally -- the calculations are handled for both directions.&lt;/p&gt;
  2994. &lt;p&gt;&lt;img alt="Generic drag drop vertical" height="216" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-generic-vertical.png" width="202"&gt; &lt;em&gt;Generic drag-drop sorting in vertical orientation.&lt;/em&gt;&lt;/p&gt;
  2995. &lt;h2 id="adding-a-visual-drop-target"&gt;Adding a Visual Drop Target&lt;/h2&gt;
  2996. &lt;p&gt;If you experiment with the drag-drop tool above you'll notice that it doesn't feel completely intuitive. When dragging you don't know where an item will be inserted until you drop it. If it ends up in the wrong place, you'll then need to pick it up and re-drop it again, using &lt;em&gt;guesswork&lt;/em&gt; to get it right.&lt;/p&gt;
  2997. &lt;p&gt;With a bit of practice you can get the hang of it, but it would be nicer to make the behavior immediately obvious for users. Many drag-drop interfaces solve this problem by showing a preview of where the item will be dropped while dragging -- either by showing the item in the place where it will be dropped, or showing some kind of placeholder.&lt;/p&gt;
  2998. &lt;p&gt;In this final section we'll implement this type of drag and drop preview indicator.&lt;/p&gt;
  2999. &lt;p&gt;The first step is to define our target indicator. This is just another label, which in our example is empty, with custom styles applied to make it have a solid "shadow" like background. This makes it obviously different to the items in the list, so it stands out as something distinct.&lt;/p&gt;
  3000. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3001. &lt;pre&gt;
  3002. &lt;code class="python"&gt;from PySide6.QtCore import QMimeData, Qt, Signal
  3003. from PySide6.QtGui import QDrag, QPixmap
  3004. from PySide6.QtWidgets import (
  3005.    QApplication,
  3006.    QHBoxLayout,
  3007.    QLabel,
  3008.    QMainWindow,
  3009.    QVBoxLayout,
  3010.    QWidget,
  3011. )
  3012.  
  3013.  
  3014. class DragTargetIndicator(QLabel):
  3015.    def __init__(self, parent=None):
  3016.        super().__init__(parent)
  3017.        self.setContentsMargins(25, 5, 25, 5)
  3018.        self.setStyleSheet(
  3019.            "QLabel { background-color: #ccc; border: 1px solid black; }"
  3020.        )
  3021.  
  3022.  
  3023. &lt;/code&gt;
  3024. &lt;/pre&gt;&lt;/div&gt;
  3025. &lt;p class="admonition admonition-tip"&gt;We've copied the contents margins from the items in the list. If you change your list items, remember to also update the indicator dimensions to match.&lt;/p&gt;
  3026. &lt;p&gt;The drag item is unchanged, but we need to implement some additional behavior on our &lt;code&gt;DragWidget&lt;/code&gt; to add the target, control showing and moving it.&lt;/p&gt;
  3027. &lt;p&gt;First we'll add the drag target indicator to the layout on our &lt;code&gt;DragWidget&lt;/code&gt;. This is hidden to begin with, but will be shown during the drag.&lt;/p&gt;
  3028. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3029. &lt;pre&gt;
  3030. &lt;code class="python"&gt;class DragWidget(QWidget):
  3031.    """
  3032.    Generic list sorting handler.
  3033.    """
  3034.  
  3035.    orderChanged = Signal(list)
  3036.  
  3037.    def __init__(self, *args, orientation=Qt.Orientation.Vertical, **kwargs):
  3038.        super().__init__()
  3039.        self.setAcceptDrops(True)
  3040.  
  3041.        # Store the orientation for drag checks later.
  3042.        self.orientation = orientation
  3043.  
  3044.        if self.orientation == Qt.Orientation.Vertical:
  3045.            self.blayout = QVBoxLayout()
  3046.        else:
  3047.            self.blayout = QHBoxLayout()
  3048.  
  3049.        # Add the drag target indicator. This is invisible by default,
  3050.        # we show it and move it around while the drag is active.
  3051.        self._drag_target_indicator = DragTargetIndicator()
  3052.        self.blayout.addWidget(self._drag_target_indicator)
  3053.        self._drag_target_indicator.hide()
  3054.  
  3055.        self.setLayout(self.blayout)
  3056. &lt;/code&gt;
  3057. &lt;/pre&gt;&lt;/div&gt;
  3058. &lt;p&gt;Next we modify the &lt;code&gt;DragWidget.dragMoveEvent&lt;/code&gt; to show the drag target indicator. We show it by &lt;em&gt;inserting&lt;/em&gt; it into the layout and then calling &lt;code&gt;.show&lt;/code&gt; -- inserting a widget which is already in a layout will move it. We also hide the original item which is being dragged.&lt;/p&gt;
  3059. &lt;p&gt;In the earlier examples we determined the position on drop by removing the widget being dragged, and then iterating over what is left. Because we now need to calculate the drop location before the drop, we take a different approach.&lt;/p&gt;
  3060. &lt;p class="admonition admonition-tip"&gt;If we wanted to do it the same way, we'd need to remove the item on drag start, hold onto it and implement re-inserting at it's old position on drag fail. That's a lot of work.&lt;/p&gt;
  3061. &lt;p&gt;Instead, the dragged item is left in place and hidden during move.&lt;/p&gt;
  3062. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3063. &lt;pre&gt;
  3064. &lt;code class="python"&gt;    def dragMoveEvent(self, e):
  3065.        # Find the correct location of the drop target, so we can move it there.
  3066.        index = self._find_drop_location(e)
  3067.        if index is not None:
  3068.            # Inserting moves the item if its alreaady in the layout.
  3069.            self.blayout.insertWidget(index, self._drag_target_indicator)
  3070.            # Hide the item being dragged.
  3071.            e.source().hide()
  3072.            # Show the target.
  3073.            self._drag_target_indicator.show()
  3074.        e.accept()
  3075.  
  3076. &lt;/code&gt;
  3077. &lt;/pre&gt;&lt;/div&gt;
  3078. &lt;p&gt;The method &lt;code&gt;self._find_drop_location&lt;/code&gt; finds the index where the drag target will be shown (or the item dropped when the mouse released). We'll implement that next.&lt;/p&gt;
  3079. &lt;p&gt;The calculation of the drop location follows the same pattern as before. We iterate over the items in the layout and calculate whether our mouse drop location is to the left of each widget. If it isn't to the left of any widget, we drop on the far right.&lt;/p&gt;
  3080. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3081. &lt;pre&gt;
  3082. &lt;code class="python"&gt;    def _find_drop_location(self, e):
  3083.        pos = e.position()
  3084.        spacing = self.blayout.spacing() / 2
  3085.  
  3086.        for n in range(self.blayout.count()):
  3087.            # Get the widget at each index in turn.
  3088.            w = self.blayout.itemAt(n).widget()
  3089.  
  3090.            if self.orientation == Qt.Orientation.Vertical:
  3091.                # Drag drop vertically.
  3092.                drop_here = (
  3093.                    pos.y() &gt;= w.y() - spacing
  3094.                    and pos.y() &lt;= w.y() + w.size().height() + spacing
  3095.                )
  3096.            else:
  3097.                # Drag drop horizontally.
  3098.                drop_here = (
  3099.                    pos.x() &gt;= w.x() - spacing
  3100.                    and pos.x() &lt;= w.x() + w.size().width() + spacing
  3101.                )
  3102.  
  3103.            if drop_here:
  3104.                # Drop over this target.
  3105.                break
  3106.  
  3107.        return n
  3108. &lt;/code&gt;
  3109. &lt;/pre&gt;&lt;/div&gt;
  3110. &lt;p&gt;The drop location &lt;code&gt;n&lt;/code&gt; is returned for use in the &lt;code&gt;dragMoveEvent&lt;/code&gt; to place the drop target indicator.&lt;/p&gt;
  3111. &lt;p&gt;Next wee need to update the &lt;code&gt;get_item_data&lt;/code&gt; handler to ignore the drop target indicator. To do this we check &lt;code&gt;w&lt;/code&gt; against &lt;code&gt;self._drag_target_indicator&lt;/code&gt; and skip if it is the same. With this change the method will work as expected.&lt;/p&gt;
  3112. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3113. &lt;pre&gt;
  3114. &lt;code class="python"&gt;    def get_item_data(self):
  3115.        data = []
  3116.        for n in range(self.blayout.count()):
  3117.            # Get the widget at each index in turn.
  3118.            w = self.blayout.itemAt(n).widget()
  3119.            if w != self._drag_target_indicator:
  3120.                # The target indicator has no data.
  3121.                data.append(w.data)
  3122.        return data
  3123.  
  3124. &lt;/code&gt;
  3125. &lt;/pre&gt;&lt;/div&gt;
  3126. &lt;p&gt;If you run the code a this point the drag behavior will work as expected. But if you drag the widget outside of the window and drop you'll notice a problem: the target indicator will stay in place, but dropping the item won't drop the item in that position (the drop will be cancelled).&lt;/p&gt;
  3127. &lt;p&gt;To fix that we need to implement a &lt;code&gt;dragLeaveEvent&lt;/code&gt; which hides the indicator.&lt;/p&gt;
  3128. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3129. &lt;pre&gt;
  3130. &lt;code class="python"&gt;    def dragLeaveEvent(self, e):
  3131.        self._drag_target_indicator.hide()
  3132.        e.accept()
  3133. &lt;/code&gt;
  3134. &lt;/pre&gt;&lt;/div&gt;
  3135. &lt;p&gt;With those changes, the drag-drop behavior should be working as intended. The complete code is shown below.&lt;/p&gt;
  3136. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3137. &lt;pre&gt;
  3138. &lt;code class="python"&gt;from PySide6.QtCore import QMimeData, Qt, Signal
  3139. from PySide6.QtGui import QDrag, QPixmap
  3140. from PySide6.QtWidgets import (
  3141.    QApplication,
  3142.    QHBoxLayout,
  3143.    QLabel,
  3144.    QMainWindow,
  3145.    QVBoxLayout,
  3146.    QWidget,
  3147. )
  3148.  
  3149.  
  3150. class DragTargetIndicator(QLabel):
  3151.    def __init__(self, parent=None):
  3152.        super().__init__(parent)
  3153.        self.setContentsMargins(25, 5, 25, 5)
  3154.        self.setStyleSheet(
  3155.            "QLabel { background-color: #ccc; border: 1px solid black; }"
  3156.        )
  3157.  
  3158.  
  3159. class DragItem(QLabel):
  3160.    def __init__(self, *args, **kwargs):
  3161.        super().__init__(*args, **kwargs)
  3162.        self.setContentsMargins(25, 5, 25, 5)
  3163.        self.setAlignment(Qt.AlignmentFlag.AlignCenter)
  3164.        self.setStyleSheet("border: 1px solid black;")
  3165.        # Store data separately from display label, but use label for default.
  3166.        self.data = self.text()
  3167.  
  3168.    def set_data(self, data):
  3169.        self.data = data
  3170.  
  3171.    def mouseMoveEvent(self, e):
  3172.        if e.buttons() == Qt.MouseButton.LeftButton:
  3173.            drag = QDrag(self)
  3174.            mime = QMimeData()
  3175.            drag.setMimeData(mime)
  3176.  
  3177.            pixmap = QPixmap(self.size())
  3178.            self.render(pixmap)
  3179.            drag.setPixmap(pixmap)
  3180.  
  3181.            drag.exec(Qt.DropAction.MoveAction)
  3182.            self.show() # Show this widget again, if it's dropped outside.
  3183.  
  3184.  
  3185. class DragWidget(QWidget):
  3186.    """
  3187.    Generic list sorting handler.
  3188.    """
  3189.  
  3190.    orderChanged = Signal(list)
  3191.  
  3192.    def __init__(self, *args, orientation=Qt.Orientation.Vertical, **kwargs):
  3193.        super().__init__()
  3194.        self.setAcceptDrops(True)
  3195.  
  3196.        # Store the orientation for drag checks later.
  3197.        self.orientation = orientation
  3198.  
  3199.        if self.orientation == Qt.Orientation.Vertical:
  3200.            self.blayout = QVBoxLayout()
  3201.        else:
  3202.            self.blayout = QHBoxLayout()
  3203.  
  3204.        # Add the drag target indicator. This is invisible by default,
  3205.        # we show it and move it around while the drag is active.
  3206.        self._drag_target_indicator = DragTargetIndicator()
  3207.        self.blayout.addWidget(self._drag_target_indicator)
  3208.        self._drag_target_indicator.hide()
  3209.  
  3210.        self.setLayout(self.blayout)
  3211.  
  3212.    def dragEnterEvent(self, e):
  3213.        e.accept()
  3214.  
  3215.    def dragLeaveEvent(self, e):
  3216.        self._drag_target_indicator.hide()
  3217.        e.accept()
  3218.  
  3219.    def dragMoveEvent(self, e):
  3220.        # Find the correct location of the drop target, so we can move it there.
  3221.        index = self._find_drop_location(e)
  3222.        if index is not None:
  3223.            # Inserting moves the item if its alreaady in the layout.
  3224.            self.blayout.insertWidget(index, self._drag_target_indicator)
  3225.            # Hide the item being dragged.
  3226.            e.source().hide()
  3227.            # Show the target.
  3228.            self._drag_target_indicator.show()
  3229.        e.accept()
  3230.  
  3231.    def dropEvent(self, e):
  3232.        widget = e.source()
  3233.        # Use drop target location for destination, then remove it.
  3234.        self._drag_target_indicator.hide()
  3235.        index = self.blayout.indexOf(self._drag_target_indicator)
  3236.        if index is not None:
  3237.            self.blayout.insertWidget(index, widget)
  3238.            self.orderChanged.emit(self.get_item_data())
  3239.            widget.show()
  3240.            self.blayout.activate()
  3241.        e.accept()
  3242.  
  3243.    def _find_drop_location(self, e):
  3244.        pos = e.position()
  3245.        spacing = self.blayout.spacing() / 2
  3246.  
  3247.        for n in range(self.blayout.count()):
  3248.            # Get the widget at each index in turn.
  3249.            w = self.blayout.itemAt(n).widget()
  3250.  
  3251.            if self.orientation == Qt.Orientation.Vertical:
  3252.                # Drag drop vertically.
  3253.                drop_here = (
  3254.                    pos.y() &gt;= w.y() - spacing
  3255.                    and pos.y() &lt;= w.y() + w.size().height() + spacing
  3256.                )
  3257.            else:
  3258.                # Drag drop horizontally.
  3259.                drop_here = (
  3260.                    pos.x() &gt;= w.x() - spacing
  3261.                    and pos.x() &lt;= w.x() + w.size().width() + spacing
  3262.                )
  3263.  
  3264.            if drop_here:
  3265.                # Drop over this target.
  3266.                break
  3267.  
  3268.        return n
  3269.  
  3270.    def add_item(self, item):
  3271.        self.blayout.addWidget(item)
  3272.  
  3273.    def get_item_data(self):
  3274.        data = []
  3275.        for n in range(self.blayout.count()):
  3276.            # Get the widget at each index in turn.
  3277.            w = self.blayout.itemAt(n).widget()
  3278.            if w != self._drag_target_indicator:
  3279.                # The target indicator has no data.
  3280.                data.append(w.data)
  3281.        return data
  3282.  
  3283.  
  3284. class MainWindow(QMainWindow):
  3285.    def __init__(self):
  3286.        super().__init__()
  3287.        self.drag = DragWidget(orientation=Qt.Orientation.Vertical)
  3288.        for n, l in enumerate(["A", "B", "C", "D"]):
  3289.            item = DragItem(l)
  3290.            item.set_data(n)  # Store the data.
  3291.            self.drag.add_item(item)
  3292.  
  3293.        # Print out the changed order.
  3294.        self.drag.orderChanged.connect(print)
  3295.  
  3296.        container = QWidget()
  3297.        layout = QVBoxLayout()
  3298.        layout.addStretch(1)
  3299.        layout.addWidget(self.drag)
  3300.        layout.addStretch(1)
  3301.        container.setLayout(layout)
  3302.  
  3303.        self.setCentralWidget(container)
  3304.  
  3305.  
  3306. app = QApplication([])
  3307. w = MainWindow()
  3308. w.show()
  3309.  
  3310. app.exec()
  3311.  
  3312. &lt;/code&gt;
  3313. &lt;/pre&gt;&lt;/div&gt;
  3314. &lt;p&gt;If you run this example on macOS you may notice that the widget drag preview (the &lt;code&gt;QPixmap&lt;/code&gt; created on &lt;code&gt;DragItem&lt;/code&gt;) is a bit blurry. On high-resolution screens you need to set the &lt;em&gt;device pixel ratio&lt;/em&gt; and scale up the pixmap when you create it. Below is a modified &lt;code&gt;DragItem&lt;/code&gt; class which does this.&lt;/p&gt;
  3315. &lt;p&gt;Update &lt;code&gt;DragItem&lt;/code&gt; to support high resolution screens.&lt;/p&gt;
  3316. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3317. &lt;pre&gt;
  3318. &lt;code class="python"&gt;class DragItem(QLabel):
  3319.    def __init__(self, *args, **kwargs):
  3320.        super().__init__(*args, **kwargs)
  3321.        self.setContentsMargins(25, 5, 25, 5)
  3322.        self.setAlignment(Qt.AlignmentFlag.AlignCenter)
  3323.        self.setStyleSheet("border: 1px solid black;")
  3324.        # Store data separately from display label, but use label for default.
  3325.        self.data = self.text()
  3326.  
  3327.    def set_data(self, data):
  3328.        self.data = data
  3329.  
  3330.    def mouseMoveEvent(self, e):
  3331.        if e.buttons() == Qt.MouseButton.LeftButton:
  3332.            drag = QDrag(self)
  3333.            mime = QMimeData()
  3334.            drag.setMimeData(mime)
  3335.  
  3336.            # Render at x2 pixel ratio to avoid blur on Retina screens.
  3337.            pixmap = QPixmap(self.size().width() * 2, self.size().height() * 2)
  3338.            pixmap.setDevicePixelRatio(2)
  3339.            self.render(pixmap)
  3340.            drag.setPixmap(pixmap)
  3341.  
  3342.            drag.exec(Qt.DropAction.MoveAction)
  3343.            self.show() # Show this widget again, if it's dropped outside.
  3344. &lt;/code&gt;
  3345. &lt;/pre&gt;&lt;/div&gt;
  3346. &lt;p&gt;That's it! We've created a generic drag-drop handled which can be added to any projects where you need to be able to reposition items within a list. You should feel free to experiment with the styling of the drag items and targets as this won't affect the behavior.&lt;/p&gt;
  3347. &lt;div style="padding: 79.5% 0 0 0;"&gt;&lt;/div&gt;</description>
  3348.    </item>
  3349.    <item>
  3350.      <guid isPermaLink="false">https://www.kdab.com/?p=33589</guid>
  3351.      <title>KDAB on Qt: Meet KDAB at Embedded World 2024 &#x2013; Hall 4-302</title>
  3352.      <pubDate>Wed, 28 Feb 2024 11:06:00 GMT</pubDate>
  3353.      <link>https://www.kdab.com/kdab-at-embedded-world-2024/</link>
  3354.      <description>&lt;p&gt;For the 14th time, KDAB exhibited at &lt;a href="https://www.embedded-world.de/en" rel="noopener" target="_blank"&gt;Embedded World&lt;/a&gt; &lt;em&gt;&#x2013; The meeting place for the global embedded community!&lt;/em&gt; Here, as expected, you got three days of pioneering technologies, solutions, new ideas, and intelligent concepts.&lt;/p&gt;
  3355. &lt;p&gt;Embedded World took place in N&#xFC;rnberg, Germany from &lt;strong&gt;9 &#x2013; 11 April 2024&lt;/strong&gt; and the &lt;strong&gt;KDAB booth&#xA0; was in Hall 4-302&lt;/strong&gt; showcasing outstanding demos featuring &lt;strong&gt;Qt, C++, 3D, Slint, Rust, and Flutter&lt;/strong&gt;.&lt;/p&gt;
  3356. &lt;p&gt;Visitors could use the code &lt;strong&gt;ew24518375&lt;/strong&gt; to get a free ticket.&lt;/p&gt;
  3357. &lt;p&gt;Here are the demos that you will have found at our booth, including an interstellar navigation interface built with Flutter&#x2026;&lt;/p&gt;
  3358. &lt;h2&gt;Augmenting 3D Support for Machine Control&lt;/h2&gt;
  3359. &lt;p&gt;&lt;strong&gt;Interactive 3D rendering using Qt3D&lt;/strong&gt;&lt;/p&gt;
  3360. &lt;p&gt;KDAB helped &lt;a href="https://www.idig-system.com/" rel="noopener" target="_blank"&gt;iDig, a provider of excavator machine controls,&lt;/a&gt; implement 3D-related work: loading CAD files, mesh data structures and algorithms, and rendering.&lt;/p&gt;
  3361. &lt;ul&gt;
  3362. &lt;li&gt;Embedded software for the control of machinery&lt;/li&gt;
  3363. &lt;li&gt;Integrate design models and field data&lt;/li&gt;
  3364. &lt;li&gt;Highly configurable user interface&lt;/li&gt;
  3365. &lt;li&gt;Embedded Linux system, C++ &amp; Qt application&lt;/li&gt;
  3366. &lt;/ul&gt;
  3367. &lt;p&gt;&lt;a href="https://www.qt.io/ew_2024" rel="noopener" target="_blank"&gt;&lt;img alt="KDAB Demos Built with Qt" class="alignleft wp-image-33619" height="37" src="https://www.kdab.com/wp-content/uploads/stories/Built_with_Qt_Pine_RGB.png" width="118"&gt;&lt;/a&gt;&lt;/p&gt;
  3368. &lt;h2&gt;Developing Next Generation UI for an EV Charger&lt;/h2&gt;
  3369. &lt;p&gt;&lt;strong&gt;High-quality touch-based interface based on Slint&lt;/strong&gt;&lt;/p&gt;
  3370. &lt;p&gt;KDAB and &lt;a href="https://www.tqcs.io/" rel="noopener" target="_blank"&gt;tQCS&lt;/a&gt; used &lt;a href="https://slint.dev/" rel="noopener" target="_blank"&gt;Slint, a UI toolkit built with Rust,&lt;/a&gt; to overhaul the user interface of SK Signet&#x2019;s flagship Electric Vehicle charger.&lt;/p&gt;
  3371. &lt;ul&gt;
  3372. &lt;li&gt;15-inch and 32-inch variants with dynamic dark/light mode&lt;/li&gt;
  3373. &lt;li&gt;Video playback with FFmpeg and networking with Curl&lt;/li&gt;
  3374. &lt;li&gt;Windows 10 IoT embedded hardware&lt;/li&gt;
  3375. &lt;/ul&gt;
  3376. &lt;p&gt;&lt;a href="https://www.kdab.com/wp-content/uploads/stories/MadeWithSlint-logo-light.svg"&gt;&lt;img alt="" class=" wp-image-34378 alignleft" height="51" src="https://www.kdab.com/wp-content/uploads/stories/MadeWithSlint-logo-light.svg" width="114"&gt;&lt;/a&gt;&lt;/p&gt;
  3377. &lt;h2&gt;Modernizing an Embedded Charge Amplifier UI with Qt&lt;/h2&gt;
  3378. &lt;p&gt;&lt;strong&gt;Multi Value Measurements device brought to market readiness&lt;/strong&gt;&lt;/p&gt;
  3379. &lt;p&gt;Starting from a legacy codebase, KDAB implemented a multi-measurement channel architecture, extended the UI, and improved stability and performance to reach production quality. The device helps with verification and quality control processes with sensitive measurements in cramped spaces.&lt;/p&gt;
  3380. &lt;ul&gt;
  3381. &lt;li&gt;Graphing and Result-Visualization of a High-Precision Measurement Process&lt;/li&gt;
  3382. &lt;li&gt;User Interface built with Qt and QML&lt;/li&gt;
  3383. &lt;li&gt;Maintaining 2 Product Variants in 1 Software Solution&lt;/li&gt;
  3384. &lt;li&gt;Texas Instruments AM335x Sitara, 1 x 1Ghz, with GPU&lt;/li&gt;
  3385. &lt;/ul&gt;
  3386. &lt;p&gt;&lt;a href="https://www.qt.io/ew_2024" rel="noopener" target="_blank"&gt;&lt;img alt="KDAB Demos Built with Qt" class="alignleft wp-image-33619" height="37" src="https://www.kdab.com/wp-content/uploads/stories/Built_with_Qt_Pine_RGB.png" width="118"&gt;&lt;/a&gt;&lt;/p&gt;
  3387. &lt;h2&gt;CXX-Qt &#x2013; Safe Rust Bindings for Qt&lt;/h2&gt;
  3388. &lt;p&gt;&lt;strong&gt;Integration for C++ and Rust applications&lt;/strong&gt;&lt;/p&gt;
  3389. &lt;p&gt;KDAB supports and maintains &lt;a href="https://github.com/KDAB/cxx-qt" rel="noopener" target="_blank"&gt;CXX-Qt&lt;/a&gt;. A set of Rust crates for creating bidirectional Rust &#x21C4; C++ bindings with Qt. It can be used to integrate Rust into C++ applications using CMake or used to build Rust applications with Cargo.&lt;/p&gt;
  3390. &lt;ul&gt;
  3391. &lt;li&gt;Enables Rust and C++ ecosystems to be used in the same application&lt;/li&gt;
  3392. &lt;li&gt;Allows for idiomatic Rust and C++ code&lt;/li&gt;
  3393. &lt;li&gt;Integrates easily into existing applications&lt;/li&gt;
  3394. &lt;/ul&gt;
  3395. &lt;p&gt;&lt;a href="https://www.qt.io/ew_2024" rel="noopener" target="_blank"&gt;&lt;img alt="KDAB Demos Built with Qt" class="alignleft wp-image-33619" height="37" src="https://www.kdab.com/wp-content/uploads/stories/Built_with_Qt_Pine_RGB.png" width="118"&gt;&lt;/a&gt;&lt;/p&gt;
  3396. &lt;h2 class="p1"&gt;3D Embedded Interstellar Navigation Interface&lt;/h2&gt;
  3397. &lt;p&gt;&lt;strong&gt;Flutter on embedded hardware using &lt;a href="https://github.com/ardera/flutter-pi" rel="noopener" target="_blank"&gt;flutter-pi&lt;/a&gt; and CAN-Bus Integration&lt;/strong&gt;&lt;/p&gt;
  3398. &lt;p&gt;To demonstrate the capabilities of Flutter on embedded we developed an interstellar navigation interface.&lt;/p&gt;
  3399. &lt;ul&gt;
  3400. &lt;li&gt;Smooth 3D components, running at 60fps&lt;/li&gt;
  3401. &lt;li&gt;Physical buttons connected via CAN-Bus (CANopen)&lt;/li&gt;
  3402. &lt;li&gt;Flutter Embedder: flutter-pi&lt;/li&gt;
  3403. &lt;li&gt;Image built with Yocto and meta-flutter&lt;/li&gt;
  3404. &lt;li&gt;Hardware: Toradex Verdin AM62, 4x Cortex-A53, 2GB RAM, PowerVR AXE-1-16M GPU&lt;/li&gt;
  3405. &lt;/ul&gt;
  3406. &lt;h2&gt;Developer Tools for Qt, C++, and Linux&lt;/h2&gt;
  3407. &lt;p&gt;&lt;strong&gt;A selection of useful developer tools for debugging and profiling&lt;/strong&gt;&lt;/p&gt;
  3408. &lt;p&gt;GammaRay: Remote Embedded Introspection&lt;/p&gt;
  3409. &lt;p&gt;Using &lt;a href="https://www.kdab.com/development-resources/qt-tools/gammaray/" rel="noopener" target="_blank"&gt;GammaRay&lt;/a&gt;, we introspect a Qt-based game at runtime on the SteamDeck (which is powered by KDE Plasma).&lt;/p&gt;
  3410. &lt;ul&gt;
  3411. &lt;li&gt;Inspection of a Qt-based SteamDeck game&lt;/li&gt;
  3412. &lt;li&gt;Full remote Qt introspection capabilities&lt;/li&gt;
  3413. &lt;li&gt;Visual forwarding and remote control&lt;/li&gt;
  3414. &lt;li&gt;Injection without recompilation of target software&lt;/li&gt;
  3415. &lt;/ul&gt;
  3416. &lt;p&gt;Further, there are also &lt;a href="https://www.kdab.com/hotspot-video/" rel="noopener noreferrer nofollow" target="_blank"&gt;Hotspot&lt;/a&gt;,&#xA0;&lt;a href="https://github.com/KDE/heaptrack" rel="noopener noreferrer nofollow" target="_blank"&gt;Heaptrack&lt;/a&gt;, and&#xA0;&lt;a href="https://github.com/KDE/clazy" rel="noopener noreferrer nofollow" target="_blank"&gt;Clazy&lt;/a&gt;, which are all useful helpers to make your code more performant.&lt;/p&gt;
  3417. &lt;p&gt;Last but not least, for those needing an advanced docking solution for Qt applications, the &lt;a href="https://github.com/KDAB/KDDockWidgets" rel="noopener noreferrer nofollow" target="_blank"&gt;KDDockWidgets&lt;/a&gt; demo.&lt;/p&gt;
  3418. &lt;ul&gt;
  3419. &lt;li&gt;KD DockWidgets: KDAB&#x2019;s Dock Widget Framework for Qt&lt;/li&gt;
  3420. &lt;li&gt;Clazy Static Code Analyzer: LLVM/Clang-based static analyzer for Qt&lt;/li&gt;
  3421. &lt;li&gt;Hotspot Profiler: GUI for Linux Perf to analyze profiling data&lt;/li&gt;
  3422. &lt;li&gt;Heaptrack: Heap memory profiler and analysis GUI for Linux&lt;/li&gt;
  3423. &lt;/ul&gt;
  3424. &lt;p&gt;&lt;a href="https://www.qt.io/ew_2024" rel="noopener" target="_blank"&gt;&lt;img alt="KDAB Demos Built with Qt" class="alignleft wp-image-33619" height="37" src="https://www.kdab.com/wp-content/uploads/stories/Built_with_Qt_Pine_RGB.png" width="118"&gt;&lt;/a&gt;&lt;/p&gt;
  3425. &lt;h2&gt;Getting Started with Customized Embedded Linux&lt;/h2&gt;
  3426. &lt;p&gt;&lt;strong&gt;Free four-part guide for Designing your first Embedded Linux device&lt;/strong&gt;&lt;/p&gt;
  3427. &lt;p&gt;Embedded Linux is widely used on embedded devices. Still, it is not trivial to implement. We have created a &lt;a href="https://www.kdab.com/publications/embedded-linux/" rel="noopener" target="_blank"&gt;comprehensive guide&lt;/a&gt;, starting from framing the development process, via choosing the software stack and the hardware to setting up your development environment.&lt;/p&gt;
  3428. &lt;h2&gt;Brochures, Whitepapers &amp; Articles&lt;/h2&gt;
  3429. &lt;p&gt;In the booth, we had a digital brochure kiosk with access to all &lt;a href="https://www.kdab.com/development-resources/whitepapers-brochures-articles/" rel="noopener" target="_blank"&gt;KDAB brochures, whitepapers, and articles&lt;/a&gt;. Here, you could easily scan the material you were interested in with your phone or grab a physical copy from our selection.&lt;/p&gt;
  3430. &lt;p&gt;Whether you like to dive into our multi-part series &lt;a href="https://www.kdab.com/publications/bestpractices/best-practices-embedded.html" rel="noopener" target="_blank"&gt;&#x201C;Best Practices for Embedded Development&#x201D;&lt;/a&gt; or &lt;a href="https://www.kdab.com/publications/bestpractices/best-practices-hybrid-rust-cpp-apps.html#building-hybrid-rust-and-c-c-applications" rel="noopener" target="_blank"&gt;&#x201C;Building Hybrid Rust and C/C++ Applications&#x201D;&lt;/a&gt;? KDAB has got you covered.&lt;/p&gt;
  3431. &lt;h2&gt;The free ticket!&lt;/h2&gt;
  3432. &lt;p&gt;We invited folk to visit &lt;a href="https://www.messe-ticket.de/Nuernberg/embeddedworld2024/Register/" rel="noopener" target="_blank"&gt;Embedded World&lt;/a&gt; free of charge with our voucher code &lt;strong&gt;ew24518375.&#xA0;&lt;/strong&gt;&lt;/p&gt;
  3433. &lt;p&gt;&lt;img alt="kdab at embedded world 2024" class="wp-image-33593 aligncenter" height="243" src="https://www.kdab.com/wp-content/uploads/stories/embedded-world-2024-en-SoMe-Asset-Facebook-WSD-1200x630px.jpg" width="462"&gt;&lt;/p&gt;
  3434. &lt;p&gt;The post &lt;a href="https://www.kdab.com/kdab-at-embedded-world-2024/"&gt;Meet KDAB at Embedded World 2024 &#x2013; Hall 4-302&lt;/a&gt; appeared first on &lt;a href="https://www.kdab.com"&gt;KDAB&lt;/a&gt;.&lt;/p&gt;</description>
  3435.    </item>
  3436.    <item>
  3437.      <guid isPermaLink="false">https://www.kdab.com/?p=33514</guid>
  3438.      <title>KDAB on Qt: Incredibly Simple QR Generation in QML</title>
  3439.      <pubDate>Thu, 22 Feb 2024 08:00:42 GMT</pubDate>
  3440.      <link>https://www.kdab.com/incredibly-simple-qr-generation-in-qml/</link>
  3441.      <description>&lt;div class="stackedit__html"&gt;
  3442. &lt;h2 id="the-need-for-simple--modular-qr-generation-in-qml"&gt;The Need for Simple &amp; Modular QR Generation in QML&lt;/h2&gt;
  3443. &lt;p&gt;Recently, our designer Nuno Pinheiro needed to generate QR codes for an Android app in QML and started asking around about a simple way to do this. The best existing QML solution was &lt;a href="https://github.com/ftylitak/qzxing"&gt;QZXing&lt;/a&gt;, a Qt/QML wrapper for the 1D/2D barcode image processing library ZXing. He felt this was too much.&lt;/p&gt;
  3444. &lt;p&gt;QZXing is quite a large and feature-rich library and is a great choice for something that requires a lot more rigorous work with encoding and decoding barcodes and QR. However, this application wasn&#x2019;t focused around barcode processing. It just needed to display a few QR codes below its other content; it didn&#x2019;t need something so heavy-duty. It seemed like too much work to build and link this library and register QML types in C++ if there was something simpler available.&lt;/p&gt;
  3445. &lt;h2 id="finding-a-javascript-library-to-wrap-in-qml"&gt;Finding A JavaScript Library to Wrap in QML&lt;/h2&gt;
  3446. &lt;p&gt;There are plenty of minimal QR Code libraries in JS, and JS files can be imported natively in QML. Why not just slap a minified JS file into our Qt resources and expose its functionality through a QML object? No compiling libraries, no CMake, simple setup for a simple task.&lt;/p&gt;
  3447. &lt;p&gt;My colleague, the one and only Javier O. Cordero P&#xE9;rez attempted to tackle this first using &lt;a href="https://github.com/davidshimjs/qrcodejs"&gt;QRCode.js&lt;/a&gt;. He found a few issues, which I&#x2019;ll let him explain. This is what Javier contributed:&lt;/p&gt;
  3448. &lt;h2 id="why-most-browser-libraries-don&#x2019;t-work-with-qml"&gt;Why Most Browser Libraries Don&#x2019;t Work With QML&lt;/h2&gt;
  3449. &lt;p&gt;Not all ECMAScript or JavaScript environments are created equal. &lt;a href="https://doc.qt.io/qt-6/qtqml-javascript-hostenvironment.html"&gt;QML, for example, doesn&#x2019;t have a DOM (Document Object Model) that represents the contents on screen&lt;/a&gt;. That feature comes from HTML, so when a JS library designed for use in the browser attempts to access the DOM from QML, it can&#x2019;t find these APIs. This limits the use of JS libraries in QML to business logic. Frontend JS libaries would have to be ported to QML in order to work.&lt;/p&gt;
  3450. &lt;blockquote&gt;
  3451. &lt;p&gt;&lt;em&gt;Note to those concerned with performance:&lt;/em&gt; At the time of writing, JS data structures, and many JS and C++ design patterns don&#x2019;t optimize well in QML code when using QML compilers. You should use C++ for backend code if you work in embedded or performance is a concern for you. Even JavaScript libraries have started a trend of moving away from pure JS in favor of Rust and WASM for backend code. Having said that, we cannot understate the convenience of having JS or QML modules or libraries you can simply plug and play. This is why we did this in the first place.&lt;/p&gt;
  3452. &lt;/blockquote&gt;
  3453. &lt;p&gt;In my first approach to using &lt;code&gt;qrcodejs&lt;/code&gt;, I tried using the library from within a QML slot (&lt;code&gt;Component.onCompleted&lt;/code&gt;) and found that &lt;code&gt;QRCode.js&lt;/code&gt; calls &lt;code&gt;document.documentElement&lt;/code&gt;, &lt;code&gt;document.getElementById&lt;/code&gt;, &lt;code&gt;document.documentElement&lt;/code&gt;, and &lt;code&gt;document.createElement&lt;/code&gt;, which are undefined, because &lt;code&gt;document&lt;/code&gt; is typically an &lt;code&gt;HTMLDocument&lt;/code&gt;, part of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API#structure_of_an_html_document"&gt;HTML DOM API&lt;/a&gt;.&lt;/p&gt;
  3454. &lt;p&gt;I then began attempting to refactor the code, but quickly realized there was no easy way to get the library to use QtQuick&#x2019;s Canvas element. I knew from past experiences that Canvas performs very poorly on Android, so, being pressed for time and Android being our target platform, I came up with a different solution.&lt;/p&gt;
  3455. &lt;h2 id="embedding-and-communicating-with-a-browser-view"&gt;Embedding and Communicating With A Browser View&lt;/h2&gt;
  3456. &lt;p&gt;My second approach was to give &lt;code&gt;QRCode.js&lt;/code&gt; a browser to work with. I chose to use &lt;code&gt;QtWebView&lt;/code&gt;, because on mobile, it displays web content using the operating system&#x2019;s web view.&lt;/p&gt;
  3457. &lt;p&gt;To keep things simple, I sent the QRCode&#x2019;s data to the web page by encoding it to a safe character space using Base64 encoding and passing the result as a URL attribute. This attribute is then decoded inside the page and then sent to the library to generate a QR code on the Canvas. The WebView dimensions are also passed as attributes so the image can be produced at the width of the shortest side.&lt;/p&gt;
  3458. &lt;p&gt;This is what my solution looked like at this point:&lt;/p&gt;
  3459. &lt;pre&gt;
  3460. &lt;code class="prism language-qml"&gt;import QtQuick 2.15
  3461. import QtQuick.Window 2.15
  3462.  
  3463. Window {
  3464.    id: document
  3465.    QRCode {
  3466.        id: qr
  3467.        text: "https://kdab.com/"
  3468.        anchors.centerIn: parent
  3469.        // The smallest dimension determines and fixes QR code size
  3470.        width: 400
  3471.        height: 600
  3472.    }
  3473.    width: 640
  3474.    height: 480
  3475.    visible: true
  3476.    title: qsTr("Web based embedded QR Code")
  3477. }
  3478. &lt;/code&gt;
  3479. &lt;/pre&gt;
  3480. &lt;pre&gt;
  3481. &lt;code class="prism language-qml"&gt;// QRCode.qml
  3482. import QtQuick 2.15
  3483. import QtWebView 1.15
  3484.  
  3485. Item {
  3486.    required property string text
  3487.    // Due to platform limitations, overlapping the WebView with other QML components is not supported.
  3488.    // Doing this will have unpredictable results which may differ from platform to platform.
  3489.    WebView {
  3490.        id: document
  3491.        // String is encoded using base64 and transfered through page URL
  3492.        url: "qrc:///qr-loader.html?w=" + width + "&amp;t=" + Qt.btoa(text)
  3493.        // Keep view dimensions to a minimum
  3494.        width: parent.width &lt; parent.height ? parent.width : parent.height
  3495.        height: parent.height &lt; parent.width ? parent.height : parent.width
  3496.        anchors.centerIn: parent
  3497.        // Note: To update the contents after the page has loaded, we could expand upon this
  3498.        // by calling runJavaScript(script: string, callback: var) from the WebView component.
  3499.        // Any method attributes, such as dimensions or the QR Code&#x2019;s contents would have to
  3500.        // be concatenated inside the script parameter.
  3501.    }
  3502. }
  3503. &lt;/code&gt;
  3504. &lt;/pre&gt;
  3505. &lt;pre&gt;
  3506. &lt;code class="prism language-html"&gt;// qr-loader.html&gt;
  3507. &lt;html&gt;
  3508. &lt;head&gt;
  3509. &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
  3510. &lt;style&gt;
  3511. body {
  3512.  margin: 0;
  3513.  padding: 0;
  3514. }
  3515. #qr {
  3516.  width: 100%;
  3517.  height: 100%;
  3518.  margin: auto;
  3519. }
  3520. &lt;/style&gt;
  3521. &lt;/head&gt;
  3522. &lt;body&gt;
  3523. &lt;h1&gt;u&lt;/h1&gt;
  3524. &lt;div id="q"&gt;&lt;/div&gt;
  3525. &lt;script src="jquery.min.js"&gt;&lt;/script&gt;
  3526. &lt;script src="qrcode.min.js"&gt;&lt;/script&gt;
  3527. &lt;script&gt;
  3528. function generateQRCode() {
  3529.  const s = new URLSearchParams(document.location.search);
  3530.  const w = Number(s.get("w"));
  3531.  const t = atob(s.get("t"));
  3532.  new QRCode(document.getElementById("q"), {
  3533.    text: t,
  3534.    width: w,
  3535.    height: w
  3536.  });
  3537. }
  3538. generateQRCode();
  3539. &lt;/script&gt;
  3540. &lt;/body&gt;
  3541. &lt;/code&gt;
  3542. &lt;/pre&gt;
  3543. &lt;h2 id="why-you-should-avoid-qtwebview-on-mobile"&gt;Why You Should Avoid QtWebView On Mobile&lt;/h2&gt;
  3544. &lt;p&gt;If you read the comments in the code, you&#x2019;ll notice that &lt;em&gt;&#x201C;due to platform limitations, overlapping the WebView with other QML components is not supported. Doing this will have unpredictable results which may differ from platform to platform.&#x201D;&lt;/em&gt; Additionally, there is so much overhead in loading an embedded site that you can see the exact moment the QR code appears on screen.&lt;/p&gt;
  3545. &lt;p&gt;Unfortunately for Nuno, &lt;code&gt;QtWebView&lt;/code&gt; is unable to load pages embedded as Qt resources on mobile systems. This is because by default, Qt resources become a part of the app&#x2019;s binary, which can&#x2019;t be read by the embedded browser. If the site was stored online or the app hosted its own web server, we could load our resources from there. Since this app didn&#x2019;t do either of those things, all resources had to be copied into a temporary folder and accessed via the &lt;code&gt;file://&lt;/code&gt; protocol. Even then, the embedded browser would fail to locate or load the resources, making it necessary to inline all of our resources into the HTML for this to work.&lt;/p&gt;
  3546. &lt;p&gt;As you can see, what started as a simple way to use a JS library on the desktop, quickly became cumbersome and difficult to maintain for mobile devices. Given more time, I would&#x2019;ve chosen to instead re-implement &lt;code&gt;QRCode.js&lt;/code&gt;'s algorithm using QtQuick&#x2019;s Shapes API. The Shapes API would allow the QR code to be rendered in a single pass of the scene graph.&lt;/p&gt;
  3547. &lt;p&gt;Fortunately, there&#x2019;s a better, simpler and more practical solution. I will defer back to Matt here, who figured it out:&lt;/p&gt;
  3548. &lt;p&gt;&lt;span style="color: #0077c8; font-family: inherit; font-size: 27px;"&gt;Proper JS in QML Solution&lt;/span&gt;&lt;/p&gt;
  3549. &lt;p&gt;I decided to expand on Javier&#x2019;s idea and try &lt;a href="https://github.com/papnkukn/qrcode-svg"&gt;qrcode-svg&lt;/a&gt;. This library uses a modified version of QRCode.js and enables creation of an SVG string from the QR Code data.&lt;/p&gt;
  3550. &lt;p&gt;Here&#x2019;s an example snipped from the project&#x2019;s README:&lt;/p&gt;
  3551. &lt;pre&gt;
  3552. &lt;code class="prism language-js"&gt;var qrcode = new QRCode({
  3553.  content: "Hello World!",
  3554.  container: "svg-viewbox", // Responsive use
  3555.  join: true // Crisp rendering and 4-5x reduced file size
  3556. });
  3557. var svg = qrcode.svg();
  3558. &lt;/code&gt;
  3559. &lt;/pre&gt;
  3560. &lt;p&gt;Since the data is SVG, it can be used with QML&#x2019;s &lt;code&gt;Image&lt;/code&gt; item natively by transforming it into a data URI and using that as the source for the image. There&#x2019;s no need to write or read anything to disk, just append the string to &lt;code&gt;"data:image/svg+xml;utf8,"&lt;/code&gt; and use that as the source file.&lt;/p&gt;
  3561. &lt;h2 id="starting-our-wrapper"&gt;Starting Our Wrapper&lt;/h2&gt;
  3562. &lt;p&gt;We can just wrap the function call up in a QML type, called QR, and use that wherever we need a QR code. Let&#x2019;s make a ridiculously basic &lt;code&gt;QtObject&lt;/code&gt; that takes a content string and uses the library to produce an SVG:&lt;/p&gt;
  3563. &lt;pre&gt;
  3564. &lt;code class="prism language-qml"&gt;// QR.qml
  3565.  
  3566. import QtQuick
  3567. import "qrcode.min.js" as QrSvg
  3568.  
  3569. QtObject {
  3570.    id: root
  3571.  
  3572.    required property string content
  3573.    property string svgString: ""
  3574.  
  3575.    Component.onCompleted: {
  3576.        root.svgString = new QrSvg.QRCode({
  3577.            content: root.content
  3578.        }).svg()
  3579.    }
  3580. }
  3581. &lt;/code&gt;
  3582. &lt;/pre&gt;
  3583. &lt;p&gt;So, whenever we make a &lt;code&gt;QR&lt;/code&gt; object, the string bound to &lt;code&gt;content&lt;/code&gt; is used to make the SVG and store it in &lt;code&gt;svgString&lt;/code&gt;. Then we can render it in an &lt;code&gt;Image&lt;/code&gt; item:&lt;/p&gt;
  3584. &lt;pre&gt;
  3585. &lt;code class="prism language-qml"&gt;// example.qml
  3586.  
  3587. import QtQuick
  3588. import QtQuick.Window
  3589.  
  3590. Window {
  3591.    visible: true
  3592.  
  3593.    QR {
  3594.        id: qrObj
  3595.        content: "hello QR!"
  3596.    }
  3597.  
  3598.    Image {
  3599.        source: "data:image/svg+xml;utf8," + qrObj.svgString
  3600.    }
  3601. }
  3602. &lt;/code&gt;
  3603. &lt;/pre&gt;
  3604. &lt;p&gt;This is basically effortless and works like a charm.&lt;/p&gt;
  3605. &lt;h2 id="finishing-up-the-wrapper"&gt;Finishing Up The Wrapper&lt;/h2&gt;
  3606. &lt;p&gt;Now let&#x2019;s completely wrap the QRCode constructor, so all the options from qrcode-svg are exposed by our QML object. We just need to set all options in the constructor through QML properties and give all the unrequired properties default values.&lt;/p&gt;
  3607. &lt;p&gt;While we&#x2019;re at it, let&#x2019;s go ahead and connect to &lt;code&gt;onContentChanged&lt;/code&gt;, so we can refresh the SVG automatically when the content changes.&lt;/p&gt;
  3608. &lt;pre&gt;
  3609. &lt;code class="prism language-qml"&gt;// QR.qml
  3610.  
  3611. import QtQuick
  3612.  
  3613. import "qrcode.min.js" as QrSvg
  3614.  
  3615. QtObject {
  3616.    id: root
  3617.  
  3618.    required property string content
  3619.    property int padding: 4
  3620.    property int width: 256
  3621.    property int height: 256
  3622.    property string color: "black"
  3623.    property string background: "white"
  3624.    property string ecl: "M"
  3625.    property bool join: false
  3626.    property bool predefined: false
  3627.    property bool pretty: true
  3628.    property bool swap: false
  3629.    property bool xmlDeclaration: true
  3630.    property string container: "svg"
  3631.  
  3632.    property string svgString: ""
  3633.  
  3634.    function createSvgString() {
  3635.        root.svgString = new QrSvg.QRCode({
  3636.            content: root.content,
  3637.            padding: root.padding,
  3638.            width: root.width,
  3639.            height: root.height,
  3640.            color: root.color,
  3641.            background: root.background,
  3642.            ecl: root.ecl,
  3643.            join: root.join,
  3644.            predefined: root.predefined,
  3645.            pretty: root.pretty,
  3646.            swap: root.swap,
  3647.            xmlDeclaration: root.xmlDeclaration,
  3648.            container: root.container
  3649.        }).svg()
  3650.    }
  3651.  
  3652.    onContentChanged: createSvgString()
  3653.    Component.onCompleted: createSvgString()
  3654. }
  3655. &lt;/code&gt;
  3656. &lt;/pre&gt;
  3657. &lt;h2 id="nice-and-easy"&gt;Nice and Easy&lt;/h2&gt;
  3658. &lt;p&gt;With these 45 lines of QML and the minified JS file, we have a QML wrapper for the library. Now any arbitrary QML project can include these two files and generate any QR Code that qrcode-svg can make.&lt;/p&gt;
  3659. &lt;p&gt;Here I use it to re-generate a QR code as you type the content into a TextInput:&lt;/p&gt;
  3660. &lt;pre&gt;
  3661. &lt;code class="prism language-qml"&gt;// example.qml
  3662.  
  3663. import QtQuick
  3664. import QtQuick.Window
  3665. import QtQuick.Controls
  3666.  
  3667. Window {
  3668.    id: root
  3669.  
  3670.    visible: true
  3671.  
  3672.    QR {
  3673.        id: qrObj
  3674.        content: txtField.text
  3675.        join: true
  3676.    }
  3677.  
  3678.    TextField {
  3679.        id: txtField
  3680.        width: parent.width
  3681.    }
  3682.  
  3683.    Image {
  3684.        anchors.top: txtField.bottom
  3685.        source: (qrObj.svgString === "")
  3686.                    ? ""
  3687.                    : ("data:image/svg+xml;utf8," + qrObj.svgString)
  3688.    }
  3689. }
  3690. &lt;/code&gt;
  3691. &lt;/pre&gt;
  3692. &lt;p&gt;This runs well when deployed on Android, and the image re-renders on content change in under 30 milliseconds, sometimes as low as 7.&lt;/p&gt;
  3693. &lt;p&gt;Hopefully this code will be useful to those looking for the simplest no-frills method to generate a QR code in QML, and maybe the post can inspire other QML developers who feel like they&#x2019;re overcomplicating something really simple.&lt;/p&gt;
  3694. &lt;blockquote&gt;
  3695. &lt;p&gt;&lt;em&gt;The solution associated with this post is available &lt;a href="https://github.com/KDABLabs/QR-Code-Generator-QML"&gt;in a GitHub repo linked here&lt;/a&gt;, so it can be used for your projects and tweaked if needed. There is also a branch that contains the code for Javier's alternate solution, &lt;a href="https://github.com/KDABLabs/QR-Code-Generator-QML/tree/alternative-web-solution"&gt;available here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
  3696. &lt;/blockquote&gt;
  3697. &lt;blockquote&gt;
  3698. &lt;p&gt;&lt;em&gt;Note: Nuno settled on QZXing before we got a chance to show him this solution, and was so frustrated about not having it earlier that he made us write this blog post &lt;img alt="&#x1F605;" class="wp-smiley" src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f605.png" style="height: 1em;"&gt;&lt;/em&gt;&lt;/p&gt;
  3699. &lt;/blockquote&gt;
  3700. &lt;div class="panel panel-info"&gt;
  3701. &lt;div class="panel-heading"&gt;About KDAB&lt;/div&gt;
  3702. &lt;div class="panel-body"&gt;
  3703. &lt;p&gt;If you like this article and want to read similar material, consider subscribing via &lt;a href="https://www.kdab.com/category/blogs/feed/"&gt;our RSS feed&lt;/a&gt;.&lt;/p&gt;
  3704. &lt;p&gt;Subscribe to &lt;a href="https://www.youtube.com/kdabtv"&gt;KDAB TV&lt;/a&gt; for similar informative short video content.&lt;/p&gt;
  3705. &lt;p&gt;KDAB provides market leading software consulting and development &lt;a href="https://www.kdab.com/software-services/"&gt;services&lt;/a&gt; and &lt;a href="https://training.kdab.com/"&gt;training&lt;/a&gt; in Qt, C++ and 3D/OpenGL. &lt;a href="https://www.kdab.com/about/contact/"&gt;Contact us&lt;/a&gt;.&lt;/p&gt;
  3706. &lt;/div&gt;
  3707. &lt;/div&gt;
  3708. &lt;/div&gt;
  3709. &lt;p&gt;The post &lt;a href="https://www.kdab.com/incredibly-simple-qr-generation-in-qml/"&gt;Incredibly Simple QR Generation in QML&lt;/a&gt; appeared first on &lt;a href="https://www.kdab.com"&gt;KDAB&lt;/a&gt;.&lt;/p&gt;</description>
  3710.    </item>
  3711.    <item>
  3712.      <guid isPermaLink="false">tag:www.pythonguis.com,2024-02-07:/faq/pyqt6-drag-drop-widgets/</guid>
  3713.      <title>Python GUIs - qt: Drag &amp; Drop Widgets with PyQt6 &#x2014; Sort widgets visually with drag and drop in a container</title>
  3714.      <pubDate>Wed, 07 Feb 2024 13:00:00 GMT</pubDate>
  3715.      <link>https://www.pythonguis.com/faq/pyqt6-drag-drop-widgets/</link>
  3716.      <description>&lt;p&gt;I had an interesting question from a reader of my &lt;a href="https://www.pythonguis.com/pyqt6-book/"&gt;PyQt6 book&lt;/a&gt;, about how to handle dragging and dropping of widgets in a container showing the dragged widget as it is moved.&lt;/p&gt;
  3717. &lt;blockquote&gt;
  3718. &lt;p&gt;I'm interested in managing movement of a QWidget with mouse in a container. I've implemented the application with drag &amp; drop, exchanging the position of buttons, but I want to show the motion of &lt;code&gt;QPushButton&lt;/code&gt;, like what you see in Qt Designer. Dragging a widget should show the widget itself, not just the mouse pointer.&lt;/p&gt;
  3719. &lt;/blockquote&gt;
  3720. &lt;p&gt;First, we'll implement the simple case which drags widgets without showing anything extra. Then we can extend it to answer the question. By the end of this quick tutorial we'll have a generic drag drop implementation which looks like the following.&lt;/p&gt;
  3721. &lt;div style="padding: 79.5% 0 0 0;"&gt;&lt;/div&gt;
  3722. &lt;div class="toc"&gt;&lt;span class="toctitle"&gt;Table of Contents&lt;/span&gt;
  3723. &lt;ul&gt;
  3724. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#drag-drop-widgets"&gt;Drag &amp; Drop Widgets&lt;/a&gt;&lt;/li&gt;
  3725. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#visual-drag-drop"&gt;Visual Drag &amp; Drop&lt;/a&gt;&lt;/li&gt;
  3726. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#generic-drag-drop-container"&gt;Generic Drag &amp; Drop Container&lt;/a&gt;&lt;/li&gt;
  3727. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#adding-a-visual-drop-target"&gt;Adding a Visual Drop Target&lt;/a&gt;&lt;/li&gt;
  3728. &lt;/ul&gt;
  3729. &lt;/div&gt;
  3730. &lt;h2 id="drag-drop-widgets"&gt;Drag &amp; Drop Widgets&lt;/h2&gt;
  3731. &lt;p&gt;We'll start with a simple application which creates a window using &lt;code&gt;QWidget&lt;/code&gt; and places a series of &lt;code&gt;QPushButton&lt;/code&gt; widgets into it.&lt;/p&gt;
  3732. &lt;p class="admonition admonition-tip"&gt;You can substitute &lt;code&gt;QPushButton&lt;/code&gt; for any other widget you like, e.g. &lt;code&gt;QLabel&lt;/code&gt;. Any widget can have drag behavior implemented on it, although some input widgets will not work well as we capture the mouse events for the drag.&lt;/p&gt;
  3733. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3734. &lt;pre&gt;
  3735. &lt;code class="python"&gt;from PyQt6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QWidget
  3736.  
  3737.  
  3738. class Window(QWidget):
  3739.    def __init__(self):
  3740.        super().__init__()
  3741.  
  3742.        self.blayout = QHBoxLayout()
  3743.        for l in ["A", "B", "C", "D"]:
  3744.            btn = QPushButton(l)
  3745.            self.blayout.addWidget(btn)
  3746.  
  3747.        self.setLayout(self.blayout)
  3748.  
  3749.  
  3750. app = QApplication([])
  3751. w = Window()
  3752. w.show()
  3753.  
  3754. app.exec()
  3755.  
  3756.  
  3757. &lt;/code&gt;
  3758. &lt;/pre&gt;&lt;/div&gt;
  3759. &lt;p&gt;If you run this you should see something like this.&lt;/p&gt;
  3760. &lt;p&gt;&lt;img alt="Widgets in a layout" height="93" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/windows-in-layout.png" width="421"&gt; &lt;em&gt;The series of &lt;code&gt;QPushButton widgets&lt;/code&gt; in a horizontal layout.&lt;/em&gt;&lt;/p&gt;
  3761. &lt;p class="admonition admonition-note"&gt;Here we're creating a window, but the &lt;code&gt;Window&lt;/code&gt; widget is subclassed from &lt;code&gt;QWidget&lt;/code&gt;, meaning you can add this widget to any other layout. See later for an example of a generic object sorting widget.&lt;/p&gt;
  3762. &lt;p&gt;&lt;code&gt;QPushButton&lt;/code&gt; objects aren't usually draggable, so to handle the mouse movements and initiate a drag we need to implement a subclass. We can add the following to the top of the file.&lt;/p&gt;
  3763. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3764. &lt;pre&gt;
  3765. &lt;code class="python"&gt;from PyQt6.QtCore import QMimeData, Qt
  3766. from PyQt6.QtGui import QDrag
  3767. from PyQt6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QWidget
  3768.  
  3769.  
  3770. class DragButton(QPushButton):
  3771.    def mouseMoveEvent(self, e):
  3772.        if e.buttons() == Qt.MouseButton.LeftButton:
  3773.            drag = QDrag(self)
  3774.            mime = QMimeData()
  3775.            drag.setMimeData(mime)
  3776.            drag.exec(Qt.DropAction.MoveAction)
  3777. &lt;/code&gt;
  3778. &lt;/pre&gt;&lt;/div&gt;
  3779. &lt;p&gt;We implement a &lt;code&gt;mouseMoveEvent&lt;/code&gt; which accepts the single &lt;code&gt;e&lt;/code&gt; parameter of the event. We check to see if the &lt;em&gt;left&lt;/em&gt; mouse button is pressed on this event -- as it would be when dragging -- and then initiate a drag. To start a drag, we create a &lt;code&gt;QDrag&lt;/code&gt; object, passing in &lt;code&gt;self&lt;/code&gt; to give us access later to the widget that was dragged. We also &lt;em&gt;must&lt;/em&gt; pass in mime data. This is used for including information about what is dragged, particularly for passing data between applications. However, as here, it is fine to leave this empty.&lt;/p&gt;
  3780. &lt;p&gt;Finally, we initiate a drag by calling &lt;code&gt;drag.exec_(Qt.MoveAction)&lt;/code&gt;. As with dialogs &lt;code&gt;exec_()&lt;/code&gt; starts a new event loop, blocking the main loop until the drag is complete. The parameter &lt;code&gt;Qt.MoveAction&lt;/code&gt; tells the drag handler what type of operation is happening, so it can show the appropriate icon tip to the user.&lt;/p&gt;
  3781. &lt;p&gt;You can update the main window code to use our new &lt;code&gt;DragButton&lt;/code&gt; class as follows.&lt;/p&gt;
  3782. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3783. &lt;pre&gt;
  3784. &lt;code class="python"&gt;class Window(QWidget):
  3785.    def __init__(self):
  3786.        super().__init__()
  3787.  
  3788.        self.blayout = QHBoxLayout()
  3789.        for l in ["A", "B", "C", "D"]:
  3790.            btn = DragButton(l)
  3791.            self.blayout.addWidget(btn)
  3792.  
  3793.        self.setLayout(self.blayout)
  3794.  
  3795. &lt;/code&gt;
  3796. &lt;/pre&gt;&lt;/div&gt;
  3797. &lt;p&gt;If you run the code now, you &lt;em&gt;can&lt;/em&gt; drag the buttons, but you'll notice the drag is forbidden.&lt;/p&gt;
  3798. &lt;p&gt;&lt;img alt="Drag forbidden" height="93" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-forbidden.png" width="421"&gt; &lt;em&gt;Dragging of the widget starts but is forbidden.&lt;/em&gt;&lt;/p&gt;
  3799. &lt;p&gt;What's happening? The mouse movement is being detected by our &lt;code&gt;DragButton&lt;/code&gt; object and the drag started, but the main window does not accept drag &amp; drop.&lt;/p&gt;
  3800. &lt;p&gt;To fix this we need to enable drops on the window and implement &lt;code&gt;dragEnterEvent&lt;/code&gt; to actually accept them.&lt;/p&gt;
  3801. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3802. &lt;pre&gt;
  3803. &lt;code class="python"&gt;class Window(QWidget):
  3804.    def __init__(self):
  3805.        super().__init__()
  3806.        self.setAcceptDrops(True)
  3807.  
  3808.        self.blayout = QHBoxLayout()
  3809.        for l in ["A", "B", "C", "D"]:
  3810.            btn = DragButton(l)
  3811.            self.blayout.addWidget(btn)
  3812.  
  3813.        self.setLayout(self.blayout)
  3814.  
  3815.    def dragEnterEvent(self, e):
  3816.        e.accept()
  3817.  
  3818. &lt;/code&gt;
  3819. &lt;/pre&gt;&lt;/div&gt;
  3820. &lt;p&gt;If you run this now, you'll see the drag is now accepted and you see the move icon. This indicates that the drag has started and been accepted by the window we're dragging onto. The icon shown is determined by the action we pass when calling &lt;code&gt;drag.exec_()&lt;/code&gt;.&lt;/p&gt;
  3821. &lt;p&gt;&lt;img alt="Drag accepted" height="93" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-accepted.png" width="421"&gt; &lt;em&gt;Dragging of the widget starts and is accepted, showing a move icon.&lt;/em&gt;&lt;/p&gt;
  3822. &lt;p&gt;Releasing the mouse button during a drag drop operation triggers a &lt;code&gt;dropEvent&lt;/code&gt; on the widget you're currently hovering the mouse over (if it is configured to accept drops). In our case that's the window. To handle the move we need to implement the code to do this in our &lt;code&gt;dropEvent&lt;/code&gt; method.&lt;/p&gt;
  3823. &lt;p&gt;The drop event contains the position the mouse was at when the button was released &amp; the drop triggered. We can use this to determine where to move the widget to.&lt;/p&gt;
  3824. &lt;p&gt;To determine where to place the widget, we iterate over all the widgets in the layout, &lt;em&gt;until&lt;/em&gt; we find one who's &lt;code&gt;x&lt;/code&gt; position is &lt;em&gt;greater&lt;/em&gt; than that of the mouse pointer. If so then when insert the widget directly to the left of this widget and exit the loop.&lt;/p&gt;
  3825. &lt;p&gt;If we get to the end of the loop without finding a match, we must be dropping past the end of the existing items, so we increment &lt;code&gt;n&lt;/code&gt; one further (in the &lt;code&gt;else:&lt;/code&gt; block below).&lt;/p&gt;
  3826. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3827. &lt;pre&gt;
  3828. &lt;code class="python"&gt;    def dropEvent(self, e):
  3829.        pos = e.position()
  3830.        widget = e.source()
  3831.        self.blayout.removeWidget(widget)
  3832.  
  3833.        for n in range(self.blayout.count()):
  3834.            # Get the widget at each index in turn.
  3835.            w = self.blayout.itemAt(n).widget()
  3836.            if pos.x() &lt; w.x():
  3837.                # We didn't drag past this widget.
  3838.                # insert to the left of it.
  3839.                break
  3840.        else:
  3841.            # We aren't on the left hand side of any widget,
  3842.            # so we're at the end. Increment 1 to insert after.
  3843.            n += 1
  3844.        self.blayout.insertWidget(n, widget)
  3845.  
  3846.        e.accept()
  3847.  
  3848. &lt;/code&gt;
  3849. &lt;/pre&gt;&lt;/div&gt;
  3850. &lt;p&gt;The effect of this is that if you drag 1 pixel past the start of another widget the drop will happen to the right of it, which is a bit confusing. To fix this we can adjust the cut off to use the middle of the widget using &lt;code&gt;if pos.x() &lt; w.x() + w.size().width() // 2:&lt;/code&gt; -- that is x + half of the width.&lt;/p&gt;
  3851. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3852. &lt;pre&gt;
  3853. &lt;code class="python"&gt;    def dropEvent(self, e):
  3854.        pos = e.position()
  3855.        widget = e.source()
  3856.        self.blayout.removeWidget(widget)
  3857.  
  3858.        for n in range(self.blayout.count()):
  3859.            # Get the widget at each index in turn.
  3860.            w = self.blayout.itemAt(n).widget()
  3861.            if pos.x() &lt; w.x() + w.size().width() // 2:
  3862.                # We didn't drag past this widget.
  3863.                # insert to the left of it.
  3864.                break
  3865.        else:
  3866.            # We aren't on the left hand side of any widget,
  3867.            # so we're at the end. Increment 1 to insert after.
  3868.            n += 1
  3869.        self.blayout.insertWidget(n, widget)
  3870.  
  3871.        e.accept()
  3872.  
  3873. &lt;/code&gt;
  3874. &lt;/pre&gt;&lt;/div&gt;
  3875. &lt;p&gt;The complete working drag-drop code is shown below.&lt;/p&gt;
  3876. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3877. &lt;pre&gt;
  3878. &lt;code class="python"&gt;from PyQt6.QtCore import QMimeData, Qt
  3879. from PyQt6.QtGui import QDrag
  3880. from PyQt6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QWidget
  3881.  
  3882.  
  3883. class DragButton(QPushButton):
  3884.    def mouseMoveEvent(self, e):
  3885.        if e.buttons() == Qt.MouseButton.LeftButton:
  3886.            drag = QDrag(self)
  3887.            mime = QMimeData()
  3888.            drag.setMimeData(mime)
  3889.            drag.exec(Qt.DropAction.MoveAction)
  3890.  
  3891.  
  3892. class Window(QWidget):
  3893.    def __init__(self):
  3894.        super().__init__()
  3895.        self.setAcceptDrops(True)
  3896.  
  3897.        self.blayout = QHBoxLayout()
  3898.        for l in ["A", "B", "C", "D"]:
  3899.            btn = DragButton(l)
  3900.            self.blayout.addWidget(btn)
  3901.  
  3902.        self.setLayout(self.blayout)
  3903.  
  3904.    def dragEnterEvent(self, e):
  3905.        e.accept()
  3906.  
  3907.    def dropEvent(self, e):
  3908.        pos = e.position()
  3909.        widget = e.source()
  3910.        self.blayout.removeWidget(widget)
  3911.  
  3912.        for n in range(self.blayout.count()):
  3913.            # Get the widget at each index in turn.
  3914.            w = self.blayout.itemAt(n).widget()
  3915.            if pos.x() &lt; w.x() + w.size().width() // 2:
  3916.                # We didn't drag past this widget.
  3917.                # insert to the left of it.
  3918.                break
  3919.        else:
  3920.            # We aren't on the left hand side of any widget,
  3921.            # so we're at the end. Increment 1 to insert after.
  3922.            n += 1
  3923.  
  3924.        self.blayout.insertWidget(n, widget)
  3925.  
  3926.        e.accept()
  3927.  
  3928.  
  3929. app = QApplication([])
  3930. w = Window()
  3931. w.show()
  3932.  
  3933. app.exec()
  3934.  
  3935. &lt;/code&gt;
  3936. &lt;/pre&gt;&lt;/div&gt;
  3937. &lt;h2 id="visual-drag-drop"&gt;Visual Drag &amp; Drop&lt;/h2&gt;
  3938. &lt;p&gt;We now have a working drag &amp; drop implementation. Next we'll move onto improving the UX by showing the drag visually. First we'll add support for showing the button being dragged next to the mouse point as it is dragged. That way the user knows exactly what it is they are dragging.&lt;/p&gt;
  3939. &lt;p&gt;Qt's &lt;code&gt;QDrag&lt;/code&gt; handler natively provides a mechanism for showing dragged objects which we can use. We can update our &lt;code&gt;DragButton&lt;/code&gt; class to pass a &lt;em&gt;pixmap&lt;/em&gt; image to &lt;code&gt;QDrag&lt;/code&gt; and this will be displayed under the mouse pointer as the drag occurs. To show the widget, we just need to get a &lt;code&gt;QPixmap&lt;/code&gt; of the widget we're dragging.&lt;/p&gt;
  3940. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3941. &lt;pre&gt;
  3942. &lt;code class="python"&gt;from PyQt6.QtCore import QMimeData, Qt
  3943. from PyQt6.QtGui import QDrag, QPixmap
  3944. from PyQt6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QWidget
  3945.  
  3946.  
  3947. class DragButton(QPushButton):
  3948.    def mouseMoveEvent(self, e):
  3949.        if e.buttons() == Qt.MouseButton.LeftButton:
  3950.            drag = QDrag(self)
  3951.            mime = QMimeData()
  3952.            drag.setMimeData(mime)
  3953.  
  3954.            pixmap = QPixmap(self.size())
  3955.            self.render(pixmap)
  3956.            drag.setPixmap(pixmap)
  3957.  
  3958.            drag.exec(Qt.DropAction.MoveAction)
  3959.  
  3960. &lt;/code&gt;
  3961. &lt;/pre&gt;&lt;/div&gt;
  3962. &lt;p&gt;To create the pixmap we create a &lt;code&gt;QPixmap&lt;/code&gt; object passing in the size of the widget this event is fired on with &lt;code&gt;self.size()&lt;/code&gt;. This creates an empty &lt;em&gt;pixmap&lt;/em&gt; which we can then pass into &lt;code&gt;self.render&lt;/code&gt; to &lt;em&gt;render&lt;/em&gt; -- or draw -- the current widget onto it. That's it. Then we set the resulting pixmap on the &lt;code&gt;drag&lt;/code&gt; object.&lt;/p&gt;
  3963. &lt;p&gt;If you run the code with this modification you'll see something like the following --&lt;/p&gt;
  3964. &lt;p&gt;&lt;img alt="Drag visual" height="93" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-visual.png" width="421"&gt; &lt;em&gt;Dragging of the widget showing the dragged widget.&lt;/em&gt;&lt;/p&gt;
  3965. &lt;h2 id="generic-drag-drop-container"&gt;Generic Drag &amp; Drop Container&lt;/h2&gt;
  3966. &lt;p&gt;We now have a working drag and drop behavior implemented on our window. We can take this a step further and implement a &lt;em&gt;generic&lt;/em&gt; drag drop widget which allows us to sort arbitrary objects. In the code below we've created a new widget &lt;code&gt;DragWidget&lt;/code&gt; which can be added to any window.&lt;/p&gt;
  3967. &lt;p&gt;You can add &lt;em&gt;items&lt;/em&gt; -- instances of &lt;code&gt;DragItem&lt;/code&gt; -- which you want to be sorted, as well as setting data on them. When items are re-ordered the new order is emitted as a signal &lt;code&gt;orderChanged&lt;/code&gt;.&lt;/p&gt;
  3968. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  3969. &lt;pre&gt;
  3970. &lt;code class="python"&gt;from PyQt6.QtCore import QMimeData, Qt, pyqtSignal
  3971. from PyQt6.QtGui import QDrag, QPixmap
  3972. from PyQt6.QtWidgets import (
  3973.    QApplication,
  3974.    QHBoxLayout,
  3975.    QLabel,
  3976.    QMainWindow,
  3977.    QVBoxLayout,
  3978.    QWidget,
  3979. )
  3980.  
  3981.  
  3982. class DragItem(QLabel):
  3983.    def __init__(self, *args, **kwargs):
  3984.        super().__init__(*args, **kwargs)
  3985.        self.setContentsMargins(25, 5, 25, 5)
  3986.        self.setAlignment(Qt.AlignmentFlag.AlignCenter)
  3987.        self.setStyleSheet("border: 1px solid black;")
  3988.        # Store data separately from display label, but use label for default.
  3989.        self.data = self.text()
  3990.  
  3991.    def set_data(self, data):
  3992.        self.data = data
  3993.  
  3994.    def mouseMoveEvent(self, e):
  3995.        if e.buttons() == Qt.MouseButton.LeftButton:
  3996.            drag = QDrag(self)
  3997.            mime = QMimeData()
  3998.            drag.setMimeData(mime)
  3999.  
  4000.            pixmap = QPixmap(self.size())
  4001.            self.render(pixmap)
  4002.            drag.setPixmap(pixmap)
  4003.  
  4004.            drag.exec(Qt.DropAction.MoveAction)
  4005.  
  4006.  
  4007. class DragWidget(QWidget):
  4008.    """
  4009.    Generic list sorting handler.
  4010.    """
  4011.  
  4012.    orderChanged = pyqtSignal(list)
  4013.  
  4014.    def __init__(self, *args, orientation=Qt.Orientation.Vertical, **kwargs):
  4015.        super().__init__()
  4016.        self.setAcceptDrops(True)
  4017.  
  4018.        # Store the orientation for drag checks later.
  4019.        self.orientation = orientation
  4020.  
  4021.        if self.orientation == Qt.Orientation.Vertical:
  4022.            self.blayout = QVBoxLayout()
  4023.        else:
  4024.            self.blayout = QHBoxLayout()
  4025.  
  4026.        self.setLayout(self.blayout)
  4027.  
  4028.    def dragEnterEvent(self, e):
  4029.        e.accept()
  4030.  
  4031.    def dropEvent(self, e):
  4032.        pos = e.position()
  4033.        widget = e.source()
  4034.        self.blayout.removeWidget(widget)
  4035.  
  4036.        for n in range(self.blayout.count()):
  4037.            # Get the widget at each index in turn.
  4038.            w = self.blayout.itemAt(n).widget()
  4039.            if self.orientation == Qt.Orientation.Vertical:
  4040.                # Drag drop vertically.
  4041.                drop_here = pos.y() &lt; w.y() + w.size().height() // 2
  4042.            else:
  4043.                # Drag drop horizontally.
  4044.                drop_here = pos.x() &lt; w.x() + w.size().width() // 2
  4045.  
  4046.            if drop_here:
  4047.                break
  4048.  
  4049.        else:
  4050.            # We aren't on the left hand/upper side of any widget,
  4051.            # so we're at the end. Increment 1 to insert after.
  4052.            n += 1
  4053.  
  4054.        self.blayout.insertWidget(n, widget)
  4055.        self.orderChanged.emit(self.get_item_data())
  4056.  
  4057.        e.accept()
  4058.  
  4059.    def add_item(self, item):
  4060.        self.blayout.addWidget(item)
  4061.  
  4062.    def get_item_data(self):
  4063.        data = []
  4064.        for n in range(self.blayout.count()):
  4065.            # Get the widget at each index in turn.
  4066.            w = self.blayout.itemAt(n).widget()
  4067.            data.append(w.data)
  4068.        return data
  4069.  
  4070.  
  4071. class MainWindow(QMainWindow):
  4072.    def __init__(self):
  4073.        super().__init__()
  4074.        self.drag = DragWidget(orientation=Qt.Orientation.Vertical)
  4075.        for n, l in enumerate(["A", "B", "C", "D"]):
  4076.            item = DragItem(l)
  4077.            item.set_data(n)  # Store the data.
  4078.            self.drag.add_item(item)
  4079.  
  4080.        # Print out the changed order.
  4081.        self.drag.orderChanged.connect(print)
  4082.  
  4083.        container = QWidget()
  4084.        layout = QVBoxLayout()
  4085.        layout.addStretch(1)
  4086.        layout.addWidget(self.drag)
  4087.        layout.addStretch(1)
  4088.        container.setLayout(layout)
  4089.  
  4090.        self.setCentralWidget(container)
  4091.  
  4092.  
  4093. app = QApplication([])
  4094. w = MainWindow()
  4095. w.show()
  4096.  
  4097. app.exec()
  4098.  
  4099. &lt;/code&gt;
  4100. &lt;/pre&gt;&lt;/div&gt;
  4101. &lt;p&gt;&lt;img alt="Generic drag drop horizontal" height="139" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-generic-horizontal.png" width="306"&gt; &lt;em&gt;Generic drag-drop sorting in horizontal orientation.&lt;/em&gt;&lt;/p&gt;
  4102. &lt;p&gt;You'll notice that when creating the item, you can set the label by passing it in as a parameter (just like for a normal &lt;code&gt;QLabel&lt;/code&gt; which we've subclassed from). But you can also set a data value, which is the internal value of this item -- this is what will be emitted when the order changes, or if you call &lt;code&gt;get_item_data&lt;/code&gt; yourself. This separates the visual representation from what is actually being sorted, meaning you can use this to sort &lt;em&gt;anything&lt;/em&gt; not just strings.&lt;/p&gt;
  4103. &lt;p&gt;In the example above we're passing in the enumerated index as the data, so dragging will output (via the &lt;code&gt;print&lt;/code&gt; connected to &lt;code&gt;orderChanged&lt;/code&gt;) something like:&lt;/p&gt;
  4104. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4105. &lt;pre&gt;
  4106. &lt;code class="python"&gt;[1, 0, 2, 3]
  4107. [1, 2, 0, 3]
  4108. [1, 0, 2, 3]
  4109. [1, 2, 0, 3]
  4110. &lt;/code&gt;
  4111. &lt;/pre&gt;&lt;/div&gt;
  4112. &lt;p&gt;If you remove the &lt;code&gt;item.set_data(n)&lt;/code&gt; you'll see the labels emitted on changes.&lt;/p&gt;
  4113. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4114. &lt;pre&gt;
  4115. &lt;code class="python"&gt;['B', 'A', 'C', 'D']
  4116. ['B', 'C', 'A', 'D']
  4117. &lt;/code&gt;
  4118. &lt;/pre&gt;&lt;/div&gt;
  4119. &lt;p&gt;We've also implemented &lt;em&gt;orientation&lt;/em&gt; onto the &lt;code&gt;DragWidget&lt;/code&gt; using the Qt built in flags &lt;code&gt;Qt.Orientation.Vertical&lt;/code&gt; or &lt;code&gt;Qt.Orientation.Horizontal&lt;/code&gt;. This setting this allows you sort items either vertically or horizontally -- the calculations are handled for both directions.&lt;/p&gt;
  4120. &lt;p&gt;&lt;img alt="Generic drag drop vertical" height="216" src="https://www.pythonguis.com/static/faq/drag-drop-widgets/drag-generic-vertical.png" width="202"&gt; &lt;em&gt;Generic drag-drop sorting in vertical orientation.&lt;/em&gt;&lt;/p&gt;
  4121. &lt;h2 id="adding-a-visual-drop-target"&gt;Adding a Visual Drop Target&lt;/h2&gt;
  4122. &lt;p&gt;If you experiment with the drag-drop tool above you'll notice that it doesn't feel completely intuitive. When dragging you don't know where an item will be inserted until you drop it. If it ends up in the wrong place, you'll then need to pick it up and re-drop it again, using &lt;em&gt;guesswork&lt;/em&gt; to get it right.&lt;/p&gt;
  4123. &lt;p&gt;With a bit of practice you can get the hang of it, but it would be nicer to make the behavior immediately obvious for users. Many drag-drop interfaces solve this problem by showing a preview of where the item will be dropped while dragging -- either by showing the item in the place where it will be dropped, or showing some kind of placeholder.&lt;/p&gt;
  4124. &lt;p&gt;In this final section we'll implement this type of drag and drop preview indicator.&lt;/p&gt;
  4125. &lt;p&gt;The first step is to define our target indicator. This is just another label, which in our example is empty, with custom styles applied to make it have a solid "shadow" like background. This makes it obviously different to the items in the list, so it stands out as something distinct.&lt;/p&gt;
  4126. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4127. &lt;pre&gt;
  4128. &lt;code class="python"&gt;from PyQt6.QtCore import QMimeData, Qt, pyqtSignal
  4129. from PyQt6.QtGui import QDrag, QPixmap
  4130. from PyQt6.QtWidgets import (
  4131.    QApplication,
  4132.    QHBoxLayout,
  4133.    QLabel,
  4134.    QMainWindow,
  4135.    QVBoxLayout,
  4136.    QWidget,
  4137. )
  4138.  
  4139.  
  4140. class DragTargetIndicator(QLabel):
  4141.    def __init__(self, parent=None):
  4142.        super().__init__(parent)
  4143.        self.setContentsMargins(25, 5, 25, 5)
  4144.        self.setStyleSheet(
  4145.            "QLabel { background-color: #ccc; border: 1px solid black; }"
  4146.        )
  4147.  
  4148.  
  4149. &lt;/code&gt;
  4150. &lt;/pre&gt;&lt;/div&gt;
  4151. &lt;p class="admonition admonition-tip"&gt;We've copied the contents margins from the items in the list. If you change your list items, remember to also update the indicator dimensions to match.&lt;/p&gt;
  4152. &lt;p&gt;The drag item is unchanged, but we need to implement some additional behavior on our &lt;code&gt;DragWidget&lt;/code&gt; to add the target, control showing and moving it.&lt;/p&gt;
  4153. &lt;p&gt;First we'll add the drag target indicator to the layout on our &lt;code&gt;DragWidget&lt;/code&gt;. This is hidden to begin with, but will be shown during the drag.&lt;/p&gt;
  4154. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4155. &lt;pre&gt;
  4156. &lt;code class="python"&gt;class DragWidget(QWidget):
  4157.    """
  4158.    Generic list sorting handler.
  4159.    """
  4160.  
  4161.    orderChanged = pyqtSignal(list)
  4162.  
  4163.    def __init__(self, *args, orientation=Qt.Orientation.Vertical, **kwargs):
  4164.        super().__init__()
  4165.        self.setAcceptDrops(True)
  4166.  
  4167.        # Store the orientation for drag checks later.
  4168.        self.orientation = orientation
  4169.  
  4170.        if self.orientation == Qt.Orientation.Vertical:
  4171.            self.blayout = QVBoxLayout()
  4172.        else:
  4173.            self.blayout = QHBoxLayout()
  4174.  
  4175.        # Add the drag target indicator. This is invisible by default,
  4176.        # we show it and move it around while the drag is active.
  4177.        self._drag_target_indicator = DragTargetIndicator()
  4178.        self.blayout.addWidget(self._drag_target_indicator)
  4179.        self._drag_target_indicator.hide()
  4180.  
  4181.        self.setLayout(self.blayout)
  4182. &lt;/code&gt;
  4183. &lt;/pre&gt;&lt;/div&gt;
  4184. &lt;p&gt;Next we modify the &lt;code&gt;DragWidget.dragMoveEvent&lt;/code&gt; to show the drag target indicator. We show it by &lt;em&gt;inserting&lt;/em&gt; it into the layout and then calling &lt;code&gt;.show&lt;/code&gt; -- inserting a widget which is already in a layout will move it. We also hide the original item which is being dragged.&lt;/p&gt;
  4185. &lt;p&gt;In the earlier examples we determined the position on drop by removing the widget being dragged, and then iterating over what is left. Because we now need to calculate the drop location before the drop, we take a different approach.&lt;/p&gt;
  4186. &lt;p class="admonition admonition-tip"&gt;If we wanted to do it the same way, we'd need to remove the item on drag start, hold onto it and implement re-inserting at it's old position on drag fail. That's a lot of work.&lt;/p&gt;
  4187. &lt;p&gt;Instead, the dragged item is left in place and hidden during move.&lt;/p&gt;
  4188. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4189. &lt;pre&gt;
  4190. &lt;code class="python"&gt;    def dragMoveEvent(self, e):
  4191.        # Find the correct location of the drop target, so we can move it there.
  4192.        index = self._find_drop_location(e)
  4193.        if index is not None:
  4194.            # Inserting moves the item if its alreaady in the layout.
  4195.            self.blayout.insertWidget(index, self._drag_target_indicator)
  4196.            # Hide the item being dragged.
  4197.            e.source().hide()
  4198.            # Show the target.
  4199.            self._drag_target_indicator.show()
  4200.        e.accept()
  4201.  
  4202. &lt;/code&gt;
  4203. &lt;/pre&gt;&lt;/div&gt;
  4204. &lt;p&gt;The method &lt;code&gt;self._find_drop_location&lt;/code&gt; finds the index where the drag target will be shown (or the item dropped when the mouse released). We'll implement that next.&lt;/p&gt;
  4205. &lt;p&gt;The calculation of the drop location follows the same pattern as before. We iterate over the items in the layout and calculate whether our mouse drop location is to the left of each widget. If it isn't to the left of any widget, we drop on the far right.&lt;/p&gt;
  4206. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4207. &lt;pre&gt;
  4208. &lt;code class="python"&gt;    def _find_drop_location(self, e):
  4209.        pos = e.position()
  4210.        spacing = self.blayout.spacing() / 2
  4211.  
  4212.        for n in range(self.blayout.count()):
  4213.            # Get the widget at each index in turn.
  4214.            w = self.blayout.itemAt(n).widget()
  4215.  
  4216.            if self.orientation == Qt.Orientation.Vertical:
  4217.                # Drag drop vertically.
  4218.                drop_here = (
  4219.                    pos.y() &gt;= w.y() - spacing
  4220.                    and pos.y() &lt;= w.y() + w.size().height() + spacing
  4221.                )
  4222.            else:
  4223.                # Drag drop horizontally.
  4224.                drop_here = (
  4225.                    pos.x() &gt;= w.x() - spacing
  4226.                    and pos.x() &lt;= w.x() + w.size().width() + spacing
  4227.                )
  4228.  
  4229.            if drop_here:
  4230.                # Drop over this target.
  4231.                break
  4232.  
  4233.        return n
  4234. &lt;/code&gt;
  4235. &lt;/pre&gt;&lt;/div&gt;
  4236. &lt;p&gt;The drop location &lt;code&gt;n&lt;/code&gt; is returned for use in the &lt;code&gt;dragMoveEvent&lt;/code&gt; to place the drop target indicator.&lt;/p&gt;
  4237. &lt;p&gt;Next wee need to update the &lt;code&gt;get_item_data&lt;/code&gt; handler to ignore the drop target indicator. To do this we check &lt;code&gt;w&lt;/code&gt; against &lt;code&gt;self._drag_target_indicator&lt;/code&gt; and skip if it is the same. With this change the method will work as expected.&lt;/p&gt;
  4238. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4239. &lt;pre&gt;
  4240. &lt;code class="python"&gt;    def get_item_data(self):
  4241.        data = []
  4242.        for n in range(self.blayout.count()):
  4243.            # Get the widget at each index in turn.
  4244.            w = self.blayout.itemAt(n).widget()
  4245.            if w != self._drag_target_indicator:
  4246.                # The target indicator has no data.
  4247.                data.append(w.data)
  4248.        return data
  4249.  
  4250. &lt;/code&gt;
  4251. &lt;/pre&gt;&lt;/div&gt;
  4252. &lt;p&gt;If you run the code a this point the drag behavior will work as expected. But if you drag the widget outside of the window and drop you'll notice a problem: the target indicator will stay in place, but dropping the item won't drop the item in that position (the drop will be cancelled).&lt;/p&gt;
  4253. &lt;p&gt;To fix that we need to implement a &lt;code&gt;dragLeaveEvent&lt;/code&gt; which hides the indicator.&lt;/p&gt;
  4254. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4255. &lt;pre&gt;
  4256. &lt;code class="python"&gt;    def dragLeaveEvent(self, e):
  4257.        self._drag_target_indicator.hide()
  4258.        e.accept()
  4259. &lt;/code&gt;
  4260. &lt;/pre&gt;&lt;/div&gt;
  4261. &lt;p&gt;With those changes, the drag-drop behavior should be working as intended. The complete code is shown below.&lt;/p&gt;
  4262. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4263. &lt;pre&gt;
  4264. &lt;code class="python"&gt;from PyQt6.QtCore import QMimeData, Qt, pyqtSignal
  4265. from PyQt6.QtGui import QDrag, QPixmap
  4266. from PyQt6.QtWidgets import (
  4267.    QApplication,
  4268.    QHBoxLayout,
  4269.    QLabel,
  4270.    QMainWindow,
  4271.    QVBoxLayout,
  4272.    QWidget,
  4273. )
  4274.  
  4275.  
  4276. class DragTargetIndicator(QLabel):
  4277.    def __init__(self, parent=None):
  4278.        super().__init__(parent)
  4279.        self.setContentsMargins(25, 5, 25, 5)
  4280.        self.setStyleSheet(
  4281.            "QLabel { background-color: #ccc; border: 1px solid black; }"
  4282.        )
  4283.  
  4284.  
  4285. class DragItem(QLabel):
  4286.    def __init__(self, *args, **kwargs):
  4287.        super().__init__(*args, **kwargs)
  4288.        self.setContentsMargins(25, 5, 25, 5)
  4289.        self.setAlignment(Qt.AlignmentFlag.AlignCenter)
  4290.        self.setStyleSheet("border: 1px solid black;")
  4291.        # Store data separately from display label, but use label for default.
  4292.        self.data = self.text()
  4293.  
  4294.    def set_data(self, data):
  4295.        self.data = data
  4296.  
  4297.    def mouseMoveEvent(self, e):
  4298.        if e.buttons() == Qt.MouseButton.LeftButton:
  4299.            drag = QDrag(self)
  4300.            mime = QMimeData()
  4301.            drag.setMimeData(mime)
  4302.  
  4303.            pixmap = QPixmap(self.size())
  4304.            self.render(pixmap)
  4305.            drag.setPixmap(pixmap)
  4306.  
  4307.            drag.exec(Qt.DropAction.MoveAction)
  4308.            self.show() # Show this widget again, if it's dropped outside.
  4309.  
  4310.  
  4311. class DragWidget(QWidget):
  4312.    """
  4313.    Generic list sorting handler.
  4314.    """
  4315.  
  4316.    orderChanged = pyqtSignal(list)
  4317.  
  4318.    def __init__(self, *args, orientation=Qt.Orientation.Vertical, **kwargs):
  4319.        super().__init__()
  4320.        self.setAcceptDrops(True)
  4321.  
  4322.        # Store the orientation for drag checks later.
  4323.        self.orientation = orientation
  4324.  
  4325.        if self.orientation == Qt.Orientation.Vertical:
  4326.            self.blayout = QVBoxLayout()
  4327.        else:
  4328.            self.blayout = QHBoxLayout()
  4329.  
  4330.        # Add the drag target indicator. This is invisible by default,
  4331.        # we show it and move it around while the drag is active.
  4332.        self._drag_target_indicator = DragTargetIndicator()
  4333.        self.blayout.addWidget(self._drag_target_indicator)
  4334.        self._drag_target_indicator.hide()
  4335.  
  4336.        self.setLayout(self.blayout)
  4337.  
  4338.    def dragEnterEvent(self, e):
  4339.        e.accept()
  4340.  
  4341.    def dragLeaveEvent(self, e):
  4342.        self._drag_target_indicator.hide()
  4343.        e.accept()
  4344.  
  4345.    def dragMoveEvent(self, e):
  4346.        # Find the correct location of the drop target, so we can move it there.
  4347.        index = self._find_drop_location(e)
  4348.        if index is not None:
  4349.            # Inserting moves the item if its alreaady in the layout.
  4350.            self.blayout.insertWidget(index, self._drag_target_indicator)
  4351.            # Hide the item being dragged.
  4352.            e.source().hide()
  4353.            # Show the target.
  4354.            self._drag_target_indicator.show()
  4355.        e.accept()
  4356.  
  4357.    def dropEvent(self, e):
  4358.        widget = e.source()
  4359.        # Use drop target location for destination, then remove it.
  4360.        self._drag_target_indicator.hide()
  4361.        index = self.blayout.indexOf(self._drag_target_indicator)
  4362.        if index is not None:
  4363.            self.blayout.insertWidget(index, widget)
  4364.            self.orderChanged.emit(self.get_item_data())
  4365.            widget.show()
  4366.            self.blayout.activate()
  4367.        e.accept()
  4368.  
  4369.    def _find_drop_location(self, e):
  4370.        pos = e.position()
  4371.        spacing = self.blayout.spacing() / 2
  4372.  
  4373.        for n in range(self.blayout.count()):
  4374.            # Get the widget at each index in turn.
  4375.            w = self.blayout.itemAt(n).widget()
  4376.  
  4377.            if self.orientation == Qt.Orientation.Vertical:
  4378.                # Drag drop vertically.
  4379.                drop_here = (
  4380.                    pos.y() &gt;= w.y() - spacing
  4381.                    and pos.y() &lt;= w.y() + w.size().height() + spacing
  4382.                )
  4383.            else:
  4384.                # Drag drop horizontally.
  4385.                drop_here = (
  4386.                    pos.x() &gt;= w.x() - spacing
  4387.                    and pos.x() &lt;= w.x() + w.size().width() + spacing
  4388.                )
  4389.  
  4390.            if drop_here:
  4391.                # Drop over this target.
  4392.                break
  4393.  
  4394.        return n
  4395.  
  4396.    def add_item(self, item):
  4397.        self.blayout.addWidget(item)
  4398.  
  4399.    def get_item_data(self):
  4400.        data = []
  4401.        for n in range(self.blayout.count()):
  4402.            # Get the widget at each index in turn.
  4403.            w = self.blayout.itemAt(n).widget()
  4404.            if w != self._drag_target_indicator:
  4405.                # The target indicator has no data.
  4406.                data.append(w.data)
  4407.        return data
  4408.  
  4409.  
  4410. class MainWindow(QMainWindow):
  4411.    def __init__(self):
  4412.        super().__init__()
  4413.        self.drag = DragWidget(orientation=Qt.Orientation.Vertical)
  4414.        for n, l in enumerate(["A", "B", "C", "D"]):
  4415.            item = DragItem(l)
  4416.            item.set_data(n)  # Store the data.
  4417.            self.drag.add_item(item)
  4418.  
  4419.        # Print out the changed order.
  4420.        self.drag.orderChanged.connect(print)
  4421.  
  4422.        container = QWidget()
  4423.        layout = QVBoxLayout()
  4424.        layout.addStretch(1)
  4425.        layout.addWidget(self.drag)
  4426.        layout.addStretch(1)
  4427.        container.setLayout(layout)
  4428.  
  4429.        self.setCentralWidget(container)
  4430.  
  4431.  
  4432. app = QApplication([])
  4433. w = MainWindow()
  4434. w.show()
  4435.  
  4436. app.exec()
  4437.  
  4438. &lt;/code&gt;
  4439. &lt;/pre&gt;&lt;/div&gt;
  4440. &lt;p&gt;If you run this example on macOS you may notice that the widget drag preview (the &lt;code&gt;QPixmap&lt;/code&gt; created on &lt;code&gt;DragItem&lt;/code&gt;) is a bit blurry. On high-resolution screens you need to set the &lt;em&gt;device pixel ratio&lt;/em&gt; and scale up the pixmap when you create it. Below is a modified &lt;code&gt;DragItem&lt;/code&gt; class which does this.&lt;/p&gt;
  4441. &lt;p&gt;Update &lt;code&gt;DragItem&lt;/code&gt; to support high resolution screens.&lt;/p&gt;
  4442. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4443. &lt;pre&gt;
  4444. &lt;code class="python"&gt;class DragItem(QLabel):
  4445.    def __init__(self, *args, **kwargs):
  4446.        super().__init__(*args, **kwargs)
  4447.        self.setContentsMargins(25, 5, 25, 5)
  4448.        self.setAlignment(Qt.AlignmentFlag.AlignCenter)
  4449.        self.setStyleSheet("border: 1px solid black;")
  4450.        # Store data separately from display label, but use label for default.
  4451.        self.data = self.text()
  4452.  
  4453.    def set_data(self, data):
  4454.        self.data = data
  4455.  
  4456.    def mouseMoveEvent(self, e):
  4457.        if e.buttons() == Qt.MouseButton.LeftButton:
  4458.            drag = QDrag(self)
  4459.            mime = QMimeData()
  4460.            drag.setMimeData(mime)
  4461.  
  4462.            # Render at x2 pixel ratio to avoid blur on Retina screens.
  4463.            pixmap = QPixmap(self.size().width() * 2, self.size().height() * 2)
  4464.            pixmap.setDevicePixelRatio(2)
  4465.            self.render(pixmap)
  4466.            drag.setPixmap(pixmap)
  4467.  
  4468.            drag.exec(Qt.DropAction.MoveAction)
  4469.            self.show() # Show this widget again, if it's dropped outside.
  4470. &lt;/code&gt;
  4471. &lt;/pre&gt;&lt;/div&gt;
  4472. &lt;p&gt;That's it! We've created a generic drag-drop handled which can be added to any projects where you need to be able to reposition items within a list. You should feel free to experiment with the styling of the drag items and targets as this won't affect the behavior.&lt;/p&gt;
  4473. &lt;div style="padding: 79.5% 0 0 0;"&gt;&lt;/div&gt;</description>
  4474.    </item>
  4475.    <item>
  4476.      <guid isPermaLink="false">tag:www.pythonguis.com,2024-02-05:/docs/qlineedit-widget/</guid>
  4477.      <title>Python GUIs - qt: QLineEdit &#x2014; A Simple Text Input Widget</title>
  4478.      <pubDate>Mon, 05 Feb 2024 06:00:00 GMT</pubDate>
  4479.      <link>https://www.pythonguis.com/docs/qlineedit-widget/</link>
  4480.      <description>&lt;p&gt;The &lt;code&gt;QLineEdit&lt;/code&gt; class is a versatile tool for single-line text input. The widget facilitates text manipulation by supporting insertion, deletion, selection, and cut-copy-paste operations natively. You can use line edits when you need to accept text input from your users in a PyQt/PySide application.&lt;/p&gt;
  4481. &lt;p&gt;The widget is highly customizable. You can set it up to include placeholder text, input masks, input validators, and more. It also supports many keyboard shortcuts out of the box and is able to process custom ones. This feature opens an opportunity to enhance user input speed and efficiency.&lt;/p&gt;
  4482. &lt;p&gt;In this article, you will learn the basics of using &lt;code&gt;QLineEdit&lt;/code&gt; by going through its most commonly used features and capabilities.&lt;/p&gt;
  4483. &lt;div class="toc"&gt;&lt;span class="toctitle"&gt;Table of Contents&lt;/span&gt;
  4484. &lt;ul&gt;
  4485. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#creating-line-edit-widgets-with-qlineedit"&gt;Creating Line Edit Widgets With QLineEdit&lt;/a&gt;
  4486. &lt;ul&gt;
  4487. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#creating-non-editable-line-edits"&gt;Creating Non-Editable Line Edits&lt;/a&gt;&lt;/li&gt;
  4488. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#creating-line-edits-for-passwords"&gt;Creating Line Edits for Passwords&lt;/a&gt;&lt;/li&gt;
  4489. &lt;/ul&gt;
  4490. &lt;/li&gt;
  4491. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#manipulating-the-input-in-a-line-edit"&gt;Manipulating the Input in a Line Edit&lt;/a&gt;&lt;/li&gt;
  4492. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#aligning-and-formatting-the-text-in-a-line-edit"&gt;Aligning and Formatting the Text in a Line Edit&lt;/a&gt;&lt;/li&gt;
  4493. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#connecting-signals-and-slots"&gt;Connecting Signals and Slots&lt;/a&gt;&lt;/li&gt;
  4494. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#validating-input-in-line-edits"&gt;Validating Input in Line Edits&lt;/a&gt;&lt;/li&gt;
  4495. &lt;li&gt;&lt;a href="https://www.pythonguis.com/feeds/qt.tag.atom.xml#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  4496. &lt;/ul&gt;
  4497. &lt;/div&gt;
  4498. &lt;h2 id="creating-line-edit-widgets-with-qlineedit"&gt;Creating Line Edit Widgets With &lt;code&gt;QLineEdit&lt;/code&gt;&lt;/h2&gt;
  4499. &lt;p&gt;A line edit allows the user to enter and edit a single line of plain text with a useful collection of editing functionalities, such as insertion, deletion, selection, cut-copy-paste, and drag-and-drop operations.&lt;/p&gt;
  4500. &lt;p&gt;If you've used &lt;a href="https://www.pythonguis.com/pyqt6/"&gt;PyQt&lt;/a&gt; or &lt;a href="https://www.pythonguis.com/pyside6/"&gt;PySide&lt;/a&gt; to create GUI applications in Python, then it'd be likely that you already know about the &lt;a href="https://doc.qt.io/qt-6/qlineedit.html"&gt;&lt;code&gt;QLineEdit&lt;/code&gt;&lt;/a&gt; class. This class allows you to create line edits in your graphical interfaces (GUI) quickly.&lt;/p&gt;
  4501. &lt;p&gt;The &lt;code&gt;QLineEidt&lt;/code&gt; class provides two different constructors that you can use to create line edits according to your needs:&lt;/p&gt;
  4502. &lt;table&gt;
  4503. &lt;thead&gt;
  4504. &lt;tr&gt;
  4505. &lt;th&gt;Constructor&lt;/th&gt;
  4506. &lt;th&gt;Description&lt;/th&gt;
  4507. &lt;/tr&gt;
  4508. &lt;/thead&gt;
  4509. &lt;tbody&gt;
  4510. &lt;tr&gt;
  4511. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#QLineEdit"&gt;&lt;code&gt;QLineEdit(parent: QWidget = None)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4512. &lt;td&gt;Constructs a line edit with a parent widget but without text&lt;/td&gt;
  4513. &lt;/tr&gt;
  4514. &lt;tr&gt;
  4515. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#QLineEdit-1"&gt;&lt;code&gt;QLineEdit(text: str, parent: QWidget = None)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4516. &lt;td&gt;Constructs a line edit with default text and a parent widget&lt;/td&gt;
  4517. &lt;/tr&gt;
  4518. &lt;/tbody&gt;
  4519. &lt;/table&gt;
  4520. &lt;p&gt;The parent widget would be the window or dialog where you need to place the line edit. The text can be a default text that will appear in the line edit when you run the application.&lt;/p&gt;
  4521. &lt;p&gt;To illustrate how to use the above constructors, we can code a demo example:&lt;/p&gt;
  4522. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4523. &lt;pre&gt;
  4524. &lt;code class="python"&gt;from PyQt6.QtWidgets import QApplication, QLineEdit, QVBoxLayout, QWidget
  4525.  
  4526. class Window(QWidget):
  4527.    def __init__(self, parent=None):
  4528.        super().__init__(parent)
  4529.        self.setWindowTitle("QLineEdit Constructors")
  4530.        self.resize(300, 100)
  4531.        # Line edit with a parent widget
  4532.        top_line_edit = QLineEdit(parent=self)
  4533.        # Line edit with a parent widget and a default text
  4534.        bottom_line_edit = QLineEdit(
  4535.            "Hello! This is a line edit.", parent=self
  4536.        )
  4537.  
  4538.        layout = QVBoxLayout()
  4539.        layout.addWidget(top_line_edit)
  4540.        layout.addWidget(bottom_line_edit)
  4541.        self.setLayout(layout)
  4542.  
  4543. app = QApplication([])
  4544. window = Window()
  4545. window.show()
  4546. app.exec()
  4547. &lt;/code&gt;
  4548. &lt;/pre&gt;&lt;/div&gt;
  4549. &lt;p&gt;In this example, we first do the required imports and then define the &lt;code&gt;Window&lt;/code&gt; class inheriting from &lt;code&gt;QWidget&lt;/code&gt;. Inside &lt;code&gt;Window&lt;/code&gt;, we create two &lt;code&gt;QLineEdit&lt;/code&gt; widgets.&lt;/p&gt;
  4550. &lt;p&gt;To create the first line edit, we use the first constructor of &lt;code&gt;QLineEdit&lt;/code&gt;, passing only a &lt;code&gt;parent&lt;/code&gt; widget. For the second line editor, we use the second constructor, which requires the parent widget and a default text. Note that the text is a regular Python string.&lt;/p&gt;
  4551. &lt;p&gt;Save the code to a file called &lt;code&gt;constructors.py&lt;/code&gt; file and run it from your command line. You'll get a window that looks something like this:&lt;/p&gt;
  4552. &lt;p&gt;&lt;img alt="QLineEdit constructors example" height="256" src="https://www.pythonguis.com/static/docs/qlineedit/qlineedit-constructors.png" width="600"&gt; &lt;em&gt;Standard window showing our two line edits.&lt;/em&gt;&lt;/p&gt;
  4553. &lt;p&gt;The first line edit has no text. In most cases, this is how you would create your line edits because they're designed for accepting input. If you'd like to just display some text, then you can use a &lt;code&gt;QLabel&lt;/code&gt; widget instead. The second line edit displays the text that you passed to the constructor.&lt;/p&gt;
  4554. &lt;p&gt;Both line edits are ready for accepting input text. Note that you can use all the following keyboard shortcuts to optimize your text input process:&lt;/p&gt;
  4555. &lt;table&gt;
  4556. &lt;thead&gt;
  4557. &lt;tr&gt;
  4558. &lt;th align="left"&gt;Keys&lt;/th&gt;
  4559. &lt;th align="left"&gt;Action&lt;/th&gt;
  4560. &lt;/tr&gt;
  4561. &lt;/thead&gt;
  4562. &lt;tbody&gt;
  4563. &lt;tr&gt;
  4564. &lt;td align="left"&gt;Left Arrow&lt;/td&gt;
  4565. &lt;td align="left"&gt;Moves the cursor one character to the left&lt;/td&gt;
  4566. &lt;/tr&gt;
  4567. &lt;tr&gt;
  4568. &lt;td align="left"&gt;Shift+Left Arrow&lt;/td&gt;
  4569. &lt;td align="left"&gt;Moves and selects text one character to the left&lt;/td&gt;
  4570. &lt;/tr&gt;
  4571. &lt;tr&gt;
  4572. &lt;td align="left"&gt;Right Arrow&lt;/td&gt;
  4573. &lt;td align="left"&gt;Moves the cursor one character to the right&lt;/td&gt;
  4574. &lt;/tr&gt;
  4575. &lt;tr&gt;
  4576. &lt;td align="left"&gt;Shift+Right Arrow&lt;/td&gt;
  4577. &lt;td align="left"&gt;Moves and selects text one character to the right&lt;/td&gt;
  4578. &lt;/tr&gt;
  4579. &lt;tr&gt;
  4580. &lt;td align="left"&gt;Home&lt;/td&gt;
  4581. &lt;td align="left"&gt;Moves the cursor to the beginning of the line&lt;/td&gt;
  4582. &lt;/tr&gt;
  4583. &lt;tr&gt;
  4584. &lt;td align="left"&gt;End&lt;/td&gt;
  4585. &lt;td align="left"&gt;Moves the cursor to the end of the line&lt;/td&gt;
  4586. &lt;/tr&gt;
  4587. &lt;tr&gt;
  4588. &lt;td align="left"&gt;Backspace&lt;/td&gt;
  4589. &lt;td align="left"&gt;Deletes the character to the left of the cursor&lt;/td&gt;
  4590. &lt;/tr&gt;
  4591. &lt;tr&gt;
  4592. &lt;td align="left"&gt;Ctrl+Backspace&lt;/td&gt;
  4593. &lt;td align="left"&gt;Deletes the word to the left of the cursor&lt;/td&gt;
  4594. &lt;/tr&gt;
  4595. &lt;tr&gt;
  4596. &lt;td align="left"&gt;Delete&lt;/td&gt;
  4597. &lt;td align="left"&gt;Deletes the character to the right of the cursor&lt;/td&gt;
  4598. &lt;/tr&gt;
  4599. &lt;tr&gt;
  4600. &lt;td align="left"&gt;Ctrl+Delete&lt;/td&gt;
  4601. &lt;td align="left"&gt;Deletes the word to the right of the cursor&lt;/td&gt;
  4602. &lt;/tr&gt;
  4603. &lt;tr&gt;
  4604. &lt;td align="left"&gt;Ctrl+A&lt;/td&gt;
  4605. &lt;td align="left"&gt;Select all&lt;/td&gt;
  4606. &lt;/tr&gt;
  4607. &lt;tr&gt;
  4608. &lt;td align="left"&gt;Ctrl+C&lt;/td&gt;
  4609. &lt;td align="left"&gt;Copies the selected text to the clipboard&lt;/td&gt;
  4610. &lt;/tr&gt;
  4611. &lt;tr&gt;
  4612. &lt;td align="left"&gt;Ctrl+Insert&lt;/td&gt;
  4613. &lt;td align="left"&gt;Copies the selected text to the clipboard&lt;/td&gt;
  4614. &lt;/tr&gt;
  4615. &lt;tr&gt;
  4616. &lt;td align="left"&gt;Ctrl+K&lt;/td&gt;
  4617. &lt;td align="left"&gt;Deletes to the end of the line&lt;/td&gt;
  4618. &lt;/tr&gt;
  4619. &lt;tr&gt;
  4620. &lt;td align="left"&gt;Ctrl+V&lt;/td&gt;
  4621. &lt;td align="left"&gt;Pastes the clipboard text into the line edit&lt;/td&gt;
  4622. &lt;/tr&gt;
  4623. &lt;tr&gt;
  4624. &lt;td align="left"&gt;Shift+Insert&lt;/td&gt;
  4625. &lt;td align="left"&gt;Pastes the clipboard text into the line edit&lt;/td&gt;
  4626. &lt;/tr&gt;
  4627. &lt;tr&gt;
  4628. &lt;td align="left"&gt;Ctrl+X&lt;/td&gt;
  4629. &lt;td align="left"&gt;Deletes the selected text and copies it to the clipboard&lt;/td&gt;
  4630. &lt;/tr&gt;
  4631. &lt;tr&gt;
  4632. &lt;td align="left"&gt;Shift+Delete&lt;/td&gt;
  4633. &lt;td align="left"&gt;Deletes the selected text and copies it to the clipboard&lt;/td&gt;
  4634. &lt;/tr&gt;
  4635. &lt;tr&gt;
  4636. &lt;td align="left"&gt;Ctrl+Z&lt;/td&gt;
  4637. &lt;td align="left"&gt;Undoes the last operation&lt;/td&gt;
  4638. &lt;/tr&gt;
  4639. &lt;tr&gt;
  4640. &lt;td align="left"&gt;Ctrl+Y&lt;/td&gt;
  4641. &lt;td align="left"&gt;Redoes the last undone operation&lt;/td&gt;
  4642. &lt;/tr&gt;
  4643. &lt;/tbody&gt;
  4644. &lt;/table&gt;
  4645. &lt;p&gt;That's a lot of shortcuts! This table is just a sample of all the features that the &lt;code&gt;QLineEdit&lt;/code&gt; class provides out of the box.&lt;/p&gt;
  4646. &lt;p&gt;In addition to these keyboard shortcuts, the &lt;code&gt;QLineEdit&lt;/code&gt; class provides a context menu that you can trigger by clicking on a line edit using the right button of your mouse:&lt;/p&gt;
  4647. &lt;p&gt;&lt;img alt="QLineEdit context menu" height="592" src="https://www.pythonguis.com/static/docs/qlineedit/qlineedit-context-menu.png" width="662"&gt; &lt;em&gt;QLineEdit with a context menu visible.&lt;/em&gt;&lt;/p&gt;
  4648. &lt;p&gt;The built-in context menu provides basic edition options, such as cut, copy, paste, and delete. It also has options for undoing and redoing edits, and for selecting all the content of a given line edit.&lt;/p&gt;
  4649. &lt;h3 id="creating-non-editable-line-edits"&gt;Creating Non-Editable Line Edits&lt;/h3&gt;
  4650. &lt;p&gt;Sometimes, we need to make a line edit non-editable. By default, all line edits are editable because their main use case is to provide text input for the user. However, in some situations, a non-editable line edit can be useful.&lt;/p&gt;
  4651. &lt;p&gt;For example, say that you're creating a GUI application that generates some recovery keys for the users. The user must be able to copy the key to a safe place so that they can use it to recover access if they forget their password. In this situation, creating a non-editable line edit can provide a suitable solution.&lt;/p&gt;
  4652. &lt;p&gt;To make a line edit read-only, we can use the &lt;a href="https://doc.qt.io/qt-6/qlineedit.html#readOnly-prop"&gt;&lt;code&gt;readOnly&lt;/code&gt;&lt;/a&gt; property and its setter method &lt;code&gt;setReadOnly()&lt;/code&gt; as in the following example:&lt;/p&gt;
  4653. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4654. &lt;pre&gt;
  4655. &lt;code class="python"&gt;import secrets
  4656.  
  4657. from PyQt6.QtWidgets import (
  4658.    QApplication,
  4659.    QLabel,
  4660.    QLineEdit,
  4661.    QVBoxLayout,
  4662.    QWidget,
  4663. )
  4664.  
  4665. class Window(QWidget):
  4666.    def __init__(self, parent=None):
  4667.        super().__init__(parent)
  4668.        self.setWindowTitle("Non-editable QLineEdit")
  4669.        self.resize(300, 100)
  4670.        non_editable_line_edit = QLineEdit(parent=self)
  4671.        non_editable_line_edit.setReadOnly(True)
  4672.        non_editable_line_edit.setText(secrets.token_hex(16))
  4673.  
  4674.        layout = QVBoxLayout()
  4675.        layout.addWidget(QLabel(parent=self, text="Your secret key:"))
  4676.        layout.addWidget(non_editable_line_edit)
  4677.        self.setLayout(layout)
  4678.  
  4679. app = QApplication([])
  4680. window = Window()
  4681. window.show()
  4682. app.exec()
  4683. &lt;/code&gt;
  4684. &lt;/pre&gt;&lt;/div&gt;
  4685. &lt;p&gt;In this example, we create a non-editable line edit by using the &lt;code&gt;setReadOnly()&lt;/code&gt; method. When we set the &lt;code&gt;readOnly&lt;/code&gt; property to &lt;code&gt;True&lt;/code&gt;, our line edit won't accept editions. It'll only allow us to select and copy its content.&lt;/p&gt;
  4686. &lt;p&gt;Go ahead and run the application from your command line to explore how this line edit works. You'll get a window like the following:&lt;/p&gt;
  4687. &lt;p&gt;&lt;img alt="Non-editable line edit" height="424" src="https://www.pythonguis.com/static/docs/qlineedit/non-editable-lineedit.png" width="662"&gt; &lt;em&gt;A read-only line edit with editing disabled.&lt;/em&gt;&lt;/p&gt;
  4688. &lt;p&gt;If you play a bit with this line edit, you'll soon discover that you can't change its text. You'll also note that the options in the context menu are now limited to &lt;em&gt;Copy&lt;/em&gt; and &lt;em&gt;Select All&lt;/em&gt;.&lt;/p&gt;
  4689. &lt;h3 id="creating-line-edits-for-passwords"&gt;Creating Line Edits for Passwords&lt;/h3&gt;
  4690. &lt;p&gt;Another cool feature of the &lt;code&gt;QLineEdit&lt;/code&gt; class is that it allows you to create text input for passwords. This can be pretty convenient for those applications that manage several users, and each user needs to have access credentials.&lt;/p&gt;
  4691. &lt;p&gt;You can create line edits for passwords by using the &lt;a href="https://www.riverbankcomputing.com/static/Docs/PyQt6/api/qtwidgets/qlineedit.html#echoMode"&gt;&lt;code&gt;echoMode()&lt;/code&gt;&lt;/a&gt; method. This method takes one of the following constants as an argument:&lt;/p&gt;
  4692. &lt;table&gt;
  4693. &lt;thead&gt;
  4694. &lt;tr&gt;
  4695. &lt;th&gt;Constant&lt;/th&gt;
  4696. &lt;th&gt;Value&lt;/th&gt;
  4697. &lt;th&gt;Description&lt;/th&gt;
  4698. &lt;/tr&gt;
  4699. &lt;/thead&gt;
  4700. &lt;tbody&gt;
  4701. &lt;tr&gt;
  4702. &lt;td&gt;&lt;code&gt;QLineEdit.EchoMode.Normal&lt;/code&gt;&lt;/td&gt;
  4703. &lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
  4704. &lt;td&gt;Display characters as you enter them.&lt;/td&gt;
  4705. &lt;/tr&gt;
  4706. &lt;tr&gt;
  4707. &lt;td&gt;&lt;code&gt;QLineEdit.EchoMode.NoEcho&lt;/code&gt;&lt;/td&gt;
  4708. &lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
  4709. &lt;td&gt;Display no characters when you enter them.&lt;/td&gt;
  4710. &lt;/tr&gt;
  4711. &lt;tr&gt;
  4712. &lt;td&gt;&lt;code&gt;QLineEdit.EchoMode.Password&lt;/code&gt;&lt;/td&gt;
  4713. &lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
  4714. &lt;td&gt;Display platform-dependent password mask characters instead of the characters you enter.&lt;/td&gt;
  4715. &lt;/tr&gt;
  4716. &lt;tr&gt;
  4717. &lt;td&gt;&lt;code&gt;QLineEdit.EchoMode.PasswordEchoOnEdit&lt;/code&gt;&lt;/td&gt;
  4718. &lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
  4719. &lt;td&gt;Display characters as you enter them while editing. Display characters as the &lt;code&gt;Password&lt;/code&gt; mode does when reading.&lt;/td&gt;
  4720. &lt;/tr&gt;
  4721. &lt;/tbody&gt;
  4722. &lt;/table&gt;
  4723. &lt;p&gt;The &lt;code&gt;Normal&lt;/code&gt; mode is the default. The &lt;code&gt;NoEcho&lt;/code&gt; mode may be appropriate for critical passwords where even the length of the password should be kept secret. The &lt;code&gt;Password&lt;/code&gt; mode is appropriate for most password use cases, however &lt;code&gt;PasswordEchoOnEdit&lt;/code&gt; can be used instead if you need to give users some confirmation of what they are typing.&lt;/p&gt;
  4724. &lt;p&gt;Here's a sample app that shows a user and password form:&lt;/p&gt;
  4725. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4726. &lt;pre&gt;
  4727. &lt;code class="python"&gt;from PyQt6.QtWidgets import (
  4728.    QApplication,
  4729.    QFormLayout,
  4730.    QLineEdit,
  4731.    QWidget,
  4732. )
  4733.  
  4734. class Window(QWidget):
  4735.    def __init__(self, parent=None):
  4736.        super().__init__(parent)
  4737.        self.setWindowTitle("Password QLineEdit")
  4738.        self.resize(300, 100)
  4739.        username_line_edit = QLineEdit(parent=self)
  4740.        password_line_edit = QLineEdit(parent=self)
  4741.        password_line_edit.setEchoMode(QLineEdit.EchoMode.Password)
  4742.  
  4743.        layout = QFormLayout()
  4744.        layout.addRow("Username:", username_line_edit)
  4745.        layout.addRow("Password:", password_line_edit)
  4746.        self.setLayout(layout)
  4747.  
  4748. app = QApplication([])
  4749. window = Window()
  4750. window.show()
  4751. app.exec()
  4752. &lt;/code&gt;
  4753. &lt;/pre&gt;&lt;/div&gt;
  4754. &lt;p&gt;In this example, you call &lt;code&gt;setEchoMode()&lt;/code&gt; on the &lt;code&gt;password_line_edit&lt;/code&gt; widget using the &lt;code&gt;Password&lt;/code&gt; mode as an argument. When you run this code from your command line, you get the following window on your screen:&lt;/p&gt;
  4755. &lt;p&gt;&lt;img alt="Password line edit" height="256" src="https://www.pythonguis.com/static/docs/qlineedit/password-qlineedit.png" width="600"&gt; &lt;em&gt;Window with a username and password line edit.&lt;/em&gt;&lt;/p&gt;
  4756. &lt;p&gt;The &lt;code&gt;username_line_edit&lt;/code&gt; line edit is in &lt;code&gt;Normal&lt;/code&gt; mode, so we can see the characters as we type them in. In contrast, the Password line edit is in &lt;code&gt;Password&lt;/code&gt; mode. In this case, when we enter a character, the line edit shows the platform's character for passwords.&lt;/p&gt;
  4757. &lt;h2 id="manipulating-the-input-in-a-line-edit"&gt;Manipulating the Input in a Line Edit&lt;/h2&gt;
  4758. &lt;p&gt;You can change the text of a line edit using the &lt;a href="https://doc.qt.io/qt-6/qlineedit.html#text-prop"&gt;&lt;code&gt;setText()&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://doc.qt.io/qt-6/qlineedit.html#insert"&gt;&lt;code&gt;insert()&lt;/code&gt;&lt;/a&gt; methods. You can retrieve the text with the &lt;a href="https://doc.qt.io/qt-6/qlineedit.html#text-prop"&gt;&lt;code&gt;text()&lt;/code&gt;&lt;/a&gt; method. However, these are not the only operations that you can perform with the text of a line edit.&lt;/p&gt;
  4759. &lt;p&gt;The following table shows a summary of some of the most commonly used methods for text manipulation in line edits:&lt;/p&gt;
  4760. &lt;table&gt;
  4761. &lt;thead&gt;
  4762. &lt;tr&gt;
  4763. &lt;th&gt;Method&lt;/th&gt;
  4764. &lt;th&gt;Description&lt;/th&gt;
  4765. &lt;/tr&gt;
  4766. &lt;/thead&gt;
  4767. &lt;tbody&gt;
  4768. &lt;tr&gt;
  4769. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#text-prop"&gt;&lt;code&gt;setText(text)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4770. &lt;td&gt;Sets the text of a line edit to &lt;code&gt;text&lt;/code&gt;, clears the selection, clears the undo/redo history, moves the cursor to the end of the line, and resets the &lt;a href="https://doc.qt.io/qt-6/qlineedit.html#modified-prop"&gt;modified&lt;/a&gt; property to false.&lt;/td&gt;
  4771. &lt;/tr&gt;
  4772. &lt;tr&gt;
  4773. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#insert"&gt;&lt;code&gt;insert(text)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4774. &lt;td&gt;Deletes any selected text, inserts &lt;code&gt;text&lt;/code&gt;, and validates the result. If it is valid, it sets it as the new contents of the line edit.&lt;/td&gt;
  4775. &lt;/tr&gt;
  4776. &lt;tr&gt;
  4777. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#clear"&gt;&lt;code&gt;clear()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4778. &lt;td&gt;Clears the contents of the line edit.&lt;/td&gt;
  4779. &lt;/tr&gt;
  4780. &lt;tr&gt;
  4781. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#copy"&gt;&lt;code&gt;copy()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4782. &lt;td&gt;Copies the selected text to the clipboard.&lt;/td&gt;
  4783. &lt;/tr&gt;
  4784. &lt;tr&gt;
  4785. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#cut"&gt;&lt;code&gt;cut()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4786. &lt;td&gt;Copies the selected text to the clipboard and deletes it from the line edit.&lt;/td&gt;
  4787. &lt;/tr&gt;
  4788. &lt;tr&gt;
  4789. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#paste"&gt;&lt;code&gt;paste()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4790. &lt;td&gt;Inserts the clipboard's text at the cursor position, deleting any selected text.&lt;/td&gt;
  4791. &lt;/tr&gt;
  4792. &lt;tr&gt;
  4793. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#redo"&gt;&lt;code&gt;redo()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4794. &lt;td&gt;Redoes the last operation if redo is &lt;a href="https://doc.qt.io/qt-6/qlineedit.html#redoAvailable-prop"&gt;available&lt;/a&gt;. Redo becomes available once the user has performed one or more undo operations on text in the line edit.&lt;/td&gt;
  4795. &lt;/tr&gt;
  4796. &lt;tr&gt;
  4797. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#undo"&gt;&lt;code&gt;undo()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4798. &lt;td&gt;Undoes the last operation if undo is &lt;a href="https://doc.qt.io/qt-6/qlineedit.html#undoAvailable-prop"&gt;available&lt;/a&gt;. Undo becomes available once the user has modified the text in the line edit.&lt;/td&gt;
  4799. &lt;/tr&gt;
  4800. &lt;tr&gt;
  4801. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#selectAll"&gt;&lt;code&gt;selectAll()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4802. &lt;td&gt;Selects all the text and moves the cursor to the end.&lt;/td&gt;
  4803. &lt;/tr&gt;
  4804. &lt;/tbody&gt;
  4805. &lt;/table&gt;
  4806. &lt;p&gt;You can use any of these methods to manipulate the text of a line edit from your code. Consider the following example where you have two line edits and two buttons that take advantage of some of the above methods to copy some text from one line edit to the other:&lt;/p&gt;
  4807. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4808. &lt;pre&gt;
  4809. &lt;code class="python"&gt;from PyQt6.QtWidgets import (
  4810.    QApplication,
  4811.    QGridLayout,
  4812.    QLabel,
  4813.    QLineEdit,
  4814.    QPushButton,
  4815.    QWidget,
  4816. )
  4817.  
  4818. class Window(QWidget):
  4819.    def __init__(self, parent=None):
  4820.        super().__init__(parent)
  4821.        self.setWindowTitle("Copy and Paste")
  4822.        self.resize(300, 100)
  4823.  
  4824.        self.source_line_edit = QLineEdit(parent=self)
  4825.        self.source_line_edit.setText("Hello, World!")
  4826.        self.dest_line_edit = QLineEdit(parent=self)
  4827.  
  4828.        copy_button = QPushButton(parent=self, text="Copy")
  4829.        paste_button = QPushButton(parent=self, text="Paste")
  4830.  
  4831.        copy_button.clicked.connect(self.copy)
  4832.        paste_button.clicked.connect(self.paste)
  4833.  
  4834.        layout = QGridLayout()
  4835.        layout.addWidget(self.source_line_edit, 0, 0)
  4836.        layout.addWidget(copy_button, 0, 1)
  4837.        layout.addWidget(self.dest_line_edit, 1, 0)
  4838.        layout.addWidget(paste_button, 1, 1)
  4839.        self.setLayout(layout)
  4840.  
  4841.    def copy(self):
  4842.        self.source_line_edit.selectAll()
  4843.        self.source_line_edit.copy()
  4844.  
  4845.    def paste(self):
  4846.        self.dest_line_edit.clear()
  4847.        self.dest_line_edit.paste()
  4848.  
  4849. app = QApplication([])
  4850. window = Window()
  4851. window.show()
  4852. app.exec()
  4853. &lt;/code&gt;
  4854. &lt;/pre&gt;&lt;/div&gt;
  4855. &lt;p&gt;In this example, we create two line edits. The first one will hold some sample text. The second line edit will receive the text. Then, we create two buttons and connect their &lt;code&gt;clicked&lt;/code&gt; signals to the &lt;code&gt;copy()&lt;/code&gt; and &lt;code&gt;paste()&lt;/code&gt; slots.&lt;/p&gt;
  4856. &lt;p&gt;Inside the &lt;code&gt;copy()&lt;/code&gt; method we first select all the text from the source line edit. Then we use the &lt;code&gt;copy()&lt;/code&gt; method to copy the selected text to the clipboard. In &lt;code&gt;paste()&lt;/code&gt;, we call &lt;code&gt;clear()&lt;/code&gt; on the destination line edit to remove any previous text. Then, we use the &lt;code&gt;paste()&lt;/code&gt; method to copy the clipboard's content.&lt;/p&gt;
  4857. &lt;p&gt;Go ahead and run the application. You'll get the following window on your screen:&lt;/p&gt;
  4858. &lt;p&gt;&lt;img alt="QLineEdit Copy and Paste" height="256" src="https://www.pythonguis.com/static/docs/qlineedit/qlineedit-text-manipulation.png" width="600"&gt; &lt;em&gt;QLineEdit with Copy &amp; Paste buttons attached to handlers.&lt;/em&gt;&lt;/p&gt;
  4859. &lt;p&gt;Once you've run the app, then you can click the &lt;em&gt;Copy&lt;/em&gt; button to copy the text in the first line edit. Next, you can click the &lt;em&gt;Paste&lt;/em&gt; button to paste the copied text to the second line edit. Go ahead and give it a try!&lt;/p&gt;
  4860. &lt;h2 id="aligning-and-formatting-the-text-in-a-line-edit"&gt;Aligning and Formatting the Text in a Line Edit&lt;/h2&gt;
  4861. &lt;p&gt;You can also align and format the text in a line edit. For example, for text alignment, you can use the &lt;a href="https://doc.qt.io/qt-6/qlineedit.html#alignment-prop"&gt;&lt;code&gt;setAlignment()&lt;/code&gt;&lt;/a&gt; method with one or more alignment flags. Some of the most useful flags that you can find in the &lt;a href="https://doc.qt.io/qt-6/qt.html#AlignmentFlag-enum"&gt;&lt;code&gt;Qt.AlignmentFlag&lt;/code&gt;&lt;/a&gt; namespace includes the following:&lt;/p&gt;
  4862. &lt;table&gt;
  4863. &lt;thead&gt;
  4864. &lt;tr&gt;
  4865. &lt;th&gt;Flag&lt;/th&gt;
  4866. &lt;th&gt;Description&lt;/th&gt;
  4867. &lt;/tr&gt;
  4868. &lt;/thead&gt;
  4869. &lt;tbody&gt;
  4870. &lt;tr&gt;
  4871. &lt;td&gt;&lt;code&gt;AlignLeft&lt;/code&gt;&lt;/td&gt;
  4872. &lt;td&gt;Aligns with the left edge.&lt;/td&gt;
  4873. &lt;/tr&gt;
  4874. &lt;tr&gt;
  4875. &lt;td&gt;&lt;code&gt;AlignRight&lt;/code&gt;&lt;/td&gt;
  4876. &lt;td&gt;Aligns with the right edge.&lt;/td&gt;
  4877. &lt;/tr&gt;
  4878. &lt;tr&gt;
  4879. &lt;td&gt;&lt;code&gt;AlignHCenter&lt;/code&gt;&lt;/td&gt;
  4880. &lt;td&gt;Centers horizontally in the available space.&lt;/td&gt;
  4881. &lt;/tr&gt;
  4882. &lt;tr&gt;
  4883. &lt;td&gt;&lt;code&gt;AlignJustify&lt;/code&gt;&lt;/td&gt;
  4884. &lt;td&gt;Justifies the text in the available space.&lt;/td&gt;
  4885. &lt;/tr&gt;
  4886. &lt;tr&gt;
  4887. &lt;td&gt;&lt;code&gt;AlignTop&lt;/code&gt;&lt;/td&gt;
  4888. &lt;td&gt;Aligns with the top.&lt;/td&gt;
  4889. &lt;/tr&gt;
  4890. &lt;tr&gt;
  4891. &lt;td&gt;&lt;code&gt;AlignBottom&lt;/code&gt;&lt;/td&gt;
  4892. &lt;td&gt;Aligns with the bottom.&lt;/td&gt;
  4893. &lt;/tr&gt;
  4894. &lt;tr&gt;
  4895. &lt;td&gt;&lt;code&gt;AlignVCenter&lt;/code&gt;&lt;/td&gt;
  4896. &lt;td&gt;Centers vertically in the available space.&lt;/td&gt;
  4897. &lt;/tr&gt;
  4898. &lt;tr&gt;
  4899. &lt;td&gt;&lt;code&gt;AlignCenter&lt;/code&gt;&lt;/td&gt;
  4900. &lt;td&gt;Centers in both dimensions.&lt;/td&gt;
  4901. &lt;/tr&gt;
  4902. &lt;/tbody&gt;
  4903. &lt;/table&gt;
  4904. &lt;p&gt;If you want to apply multiple alignment flags to a given line edit, you don't have to call &lt;code&gt;setAlignment()&lt;/code&gt; multiple times. You can just use the bitwise OR operator (&lt;code&gt;|&lt;/code&gt;) to combine them. Consider the following example:&lt;/p&gt;
  4905. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4906. &lt;pre&gt;
  4907. &lt;code class="python"&gt;from PyQt6.QtCore import Qt
  4908. from PyQt6.QtWidgets import QApplication, QLineEdit
  4909.  
  4910. class Window(QLineEdit):
  4911.    def __init__(self, parent=None):
  4912.        super().__init__(parent)
  4913.        self.setWindowTitle("Aligning Text")
  4914.        self.resize(300, 100)
  4915.        self.setText("Hello, World!")
  4916.        self.setAlignment(Qt.AlignmentFlag.AlignCenter)
  4917.  
  4918. app = QApplication([])
  4919. window = Window()
  4920. window.show()
  4921. app.exec()
  4922. &lt;/code&gt;
  4923. &lt;/pre&gt;&lt;/div&gt;
  4924. &lt;p&gt;In this example, we use a &lt;code&gt;QLineEdit&lt;/code&gt; as the only component of our app's GUI. Using the &lt;code&gt;setAlignment()&lt;/code&gt; method, we center the &lt;code&gt;"Hello, World!"&lt;/code&gt; message in both directions, horizontally and vertically. To do this, we use the &lt;code&gt;AlignCenter&lt;/code&gt; flag. Here's what the app looks like:&lt;/p&gt;
  4925. &lt;p&gt;&lt;img alt="QLineEdit text alignment" height="256" src="https://www.pythonguis.com/static/docs/qlineedit/qlineedit-text-alignment.png" width="600"&gt; &lt;em&gt;QLineEdit with text alignment set.&lt;/em&gt;&lt;/p&gt;
  4926. &lt;p&gt;Go ahead and play with other flags to see their effect on the text alignment. Use the &lt;code&gt;|&lt;/code&gt; bitwise operator to combine several alignment flags.&lt;/p&gt;
  4927. &lt;p&gt;Line edits also have a &lt;code&gt;textMargins&lt;/code&gt; property that you can tweak to customize the text alignment using specific values. To set margin values for your text, you can use the &lt;code&gt;setTextMargins()&lt;/code&gt; method, which has the following signatures:&lt;/p&gt;
  4928. &lt;table&gt;
  4929. &lt;thead&gt;
  4930. &lt;tr&gt;
  4931. &lt;th&gt;Method&lt;/th&gt;
  4932. &lt;th&gt;Description&lt;/th&gt;
  4933. &lt;/tr&gt;
  4934. &lt;/thead&gt;
  4935. &lt;tbody&gt;
  4936. &lt;tr&gt;
  4937. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#setTextMargins"&gt;&lt;code&gt;setTextMargins(left, top, right, bottom)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4938. &lt;td&gt;Sets the margins around the text to have the sizes &lt;code&gt;left&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, and &lt;code&gt;bottom&lt;/code&gt;.&lt;/td&gt;
  4939. &lt;/tr&gt;
  4940. &lt;tr&gt;
  4941. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#setTextMargins-1"&gt;&lt;code&gt;setTextMargins(margins)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4942. &lt;td&gt;Sets the &lt;code&gt;margins&lt;/code&gt; around the text using a &lt;a href="https://doc.qt.io/qt-6/qmargins.html"&gt;&lt;code&gt;QMargins&lt;/code&gt;&lt;/a&gt; object.&lt;/td&gt;
  4943. &lt;/tr&gt;
  4944. &lt;/tbody&gt;
  4945. &lt;/table&gt;
  4946. &lt;p&gt;The first signature allows you to provide four integer values as the left, top, right, and bottom margins for the text. The second signature accepts a &lt;code&gt;QMargins&lt;/code&gt; object as an argument. To build this object, you can use four integer values with the same meaning as the &lt;code&gt;left&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, and &lt;code&gt;bottom&lt;/code&gt; arguments in the first signature.&lt;/p&gt;
  4947. &lt;p&gt;Here's an example of how to set custom margins for the text in a line edit:&lt;/p&gt;
  4948. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  4949. &lt;pre&gt;
  4950. &lt;code class="python"&gt;from PyQt6.QtWidgets import QApplication, QLineEdit
  4951.  
  4952. class Window(QLineEdit):
  4953.    def __init__(self, parent=None):
  4954.        super().__init__(parent)
  4955.        self.setWindowTitle("Aligning Text")
  4956.        self.resize(300, 100)
  4957.        self.setText("Hello, World!")
  4958.        self.setTextMargins(30, 30, 0, 0)
  4959.  
  4960. app = QApplication([])
  4961. window = Window()
  4962. window.show()
  4963. app.exec()
  4964. &lt;/code&gt;
  4965. &lt;/pre&gt;&lt;/div&gt;
  4966. &lt;p&gt;In this example, you set the left and top margins to custom values. Here's how this app looks when you run it:&lt;/p&gt;
  4967. &lt;p&gt;&lt;img alt="QLineEdit text margins" height="256" src="https://www.pythonguis.com/static/docs/qlineedit/qlineedit-text-margins.png" width="600"&gt; &lt;em&gt;QLineEdit with text margins added.&lt;/em&gt;&lt;/p&gt;
  4968. &lt;p&gt;Using the &lt;code&gt;setTextMargins()&lt;/code&gt; method, we can place the text in the desired place in a line edit, which may be a requirement in some situations.&lt;/p&gt;
  4969. &lt;h2 id="connecting-signals-and-slots"&gt;Connecting Signals and Slots&lt;/h2&gt;
  4970. &lt;p&gt;When you're creating a GUI application and you need to use line edits, you may need to perform actions when the user enters or modifies the content of the line edit. To do this, you need to connect some of the signals of the line edit to specific slots or functions.&lt;/p&gt;
  4971. &lt;p&gt;Depending on specific user events, the &lt;code&gt;QLineEdit&lt;/code&gt; class can emit several different signals. Here's is a summary of these signals and their corresponding meaning:&lt;/p&gt;
  4972. &lt;table&gt;
  4973. &lt;thead&gt;
  4974. &lt;tr&gt;
  4975. &lt;th&gt;Signal&lt;/th&gt;
  4976. &lt;th&gt;Emitted&lt;/th&gt;
  4977. &lt;/tr&gt;
  4978. &lt;/thead&gt;
  4979. &lt;tbody&gt;
  4980. &lt;tr&gt;
  4981. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#textChanged"&gt;&lt;code&gt;textChanged(text)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4982. &lt;td&gt;Whenever the user changes the text either manually or programmatically. The &lt;code&gt;text&lt;/code&gt; argument is the new text.&lt;/td&gt;
  4983. &lt;/tr&gt;
  4984. &lt;tr&gt;
  4985. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#textEdited"&gt;&lt;code&gt;textEdited(text)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4986. &lt;td&gt;Whenever the user edits the text manually. The &lt;code&gt;text&lt;/code&gt; argument is the new text.&lt;/td&gt;
  4987. &lt;/tr&gt;
  4988. &lt;tr&gt;
  4989. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#editingFinished"&gt;&lt;code&gt;editingFinished&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4990. &lt;td&gt;When the user presses the &lt;em&gt;Return&lt;/em&gt; or &lt;em&gt;Enter&lt;/em&gt; key, or when the line edit loses focus, and its contents have changed since the last time this signal was emitted.&lt;/td&gt;
  4991. &lt;/tr&gt;
  4992. &lt;tr&gt;
  4993. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#inputRejected"&gt;&lt;code&gt;inputRejected&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4994. &lt;td&gt;When the user presses a key that is an unacceptable input.&lt;/td&gt;
  4995. &lt;/tr&gt;
  4996. &lt;tr&gt;
  4997. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#returnPressed"&gt;&lt;code&gt;returnPressed&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  4998. &lt;td&gt;When the user presses the &lt;em&gt;Return&lt;/em&gt; or &lt;em&gt;Enter&lt;/em&gt; key.&lt;/td&gt;
  4999. &lt;/tr&gt;
  5000. &lt;tr&gt;
  5001. &lt;td&gt;&lt;a href="https://doc.qt.io/qt-6/qlineedit.html#selectionChanged"&gt;&lt;code&gt;selectionChanged&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
  5002. &lt;td&gt;When the selection changes.&lt;/td&gt;
  5003. &lt;/tr&gt;
  5004. &lt;/tbody&gt;
  5005. &lt;/table&gt;
  5006. &lt;p&gt;We can connect either of these signals with any slot. A slot is a method or function that performs a concrete action in your application. We can connect a signal and a slot so that the slot gets called when the signal gets emitted. Here's the required syntax to do this:&lt;/p&gt;
  5007. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  5008. &lt;pre&gt;
  5009. &lt;code class="python"&gt;line_edit.&lt;signal&gt;.connect(&lt;method&gt;)
  5010. &lt;/code&gt;
  5011. &lt;/pre&gt;&lt;/div&gt;
  5012. &lt;p&gt;In this construct, &lt;code&gt;line_edit&lt;/code&gt; is the &lt;code&gt;QLineEdit&lt;/code&gt; object that we need to connect with a given slot. The &lt;code&gt;&lt;signal&gt;&lt;/code&gt; placeholder can be any of the abovementioned signals. Finally, &lt;code&gt;&lt;method&gt;&lt;/code&gt; represents the target slot or method.&lt;/p&gt;
  5013. &lt;p&gt;Let's write an example that puts this syntax into action. For this example, we'll connect the &lt;code&gt;textEdited&lt;/code&gt; signal with a method that updates the text of a &lt;code&gt;QLabel&lt;/code&gt; to match the text of our line edit:&lt;/p&gt;
  5014. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  5015. &lt;pre&gt;
  5016. &lt;code class="python"&gt;from PyQt6.QtWidgets import (
  5017.    QApplication,
  5018.    QLabel,
  5019.    QLineEdit,
  5020.    QVBoxLayout,
  5021.    QWidget,
  5022. )
  5023.  
  5024. class Window(QWidget):
  5025.    def __init__(self, parent=None):
  5026.        super().__init__(parent)
  5027.        self.setWindowTitle("Signal and Slot")
  5028.        self.resize(300, 100)
  5029.  
  5030.        self.line_edit = QLineEdit(parent=self)
  5031.        self.label = QLabel(parent=self)
  5032.        self.line_edit.textEdited.connect(self.update_label)
  5033.  
  5034.        layout = QVBoxLayout()
  5035.        layout.addWidget(self.line_edit)
  5036.        layout.addWidget(self.label)
  5037.        self.setLayout(layout)
  5038.  
  5039.    def update_label(self):
  5040.        self.label.setText(self.line_edit.text())
  5041.  
  5042. app = QApplication([])
  5043. window = Window()
  5044. window.show()
  5045. app.exec()
  5046. &lt;/code&gt;
  5047. &lt;/pre&gt;&lt;/div&gt;
  5048. &lt;p&gt;In this example, we connect the line edit's &lt;code&gt;textEdited&lt;/code&gt; signal with the &lt;code&gt;update_label()&lt;/code&gt; method, which sets the label's text to match the text we enter in our line edit. Go ahead and run the app. Then, enter some text in the line edit and see what happens with the label at the bottom of the app's window.&lt;/p&gt;
  5049. &lt;h2 id="validating-input-in-line-edits"&gt;Validating Input in Line Edits&lt;/h2&gt;
  5050. &lt;p&gt;We can provide input validators to our line edits using the &lt;a href="https://doc.qt.io/qt-6/qlineedit.html#setValidator"&gt;&lt;code&gt;setValidator()&lt;/code&gt;&lt;/a&gt; method. This method takes a &lt;code&gt;QValidator&lt;/code&gt; object as an argument. PyQt has a few built-in validators that you can use directly on a line edit:&lt;/p&gt;
  5051. &lt;ul&gt;
  5052. &lt;li&gt;&lt;a href="https://doc.qt.io/qt-6/qintvalidator.html"&gt;QIntValidator&lt;/a&gt; for integer validation&lt;/li&gt;
  5053. &lt;li&gt;&lt;a href="https://doc.qt.io/qt-6/qdoublevalidator.html"&gt;QDoubleValidator&lt;/a&gt; for floating-point validation&lt;/li&gt;
  5054. &lt;li&gt;&lt;a href="https://doc.qt.io/qt-6/qregularexpressionvalidator.html"&gt;QRegularExpressionValidator&lt;/a&gt; for validation based on regular expressions&lt;/li&gt;
  5055. &lt;/ul&gt;
  5056. &lt;p&gt;Validator objects process the input to check whether it's valid. In general, validator object has three possible states:&lt;/p&gt;
  5057. &lt;table&gt;
  5058. &lt;thead&gt;
  5059. &lt;tr&gt;
  5060. &lt;th&gt;Constant&lt;/th&gt;
  5061. &lt;th&gt;Value&lt;/th&gt;
  5062. &lt;th&gt;Description&lt;/th&gt;
  5063. &lt;/tr&gt;
  5064. &lt;/thead&gt;
  5065. &lt;tbody&gt;
  5066. &lt;tr&gt;
  5067. &lt;td&gt;&lt;code&gt;QValidator.State.Invalid&lt;/code&gt;&lt;/td&gt;
  5068. &lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
  5069. &lt;td&gt;The input is invalid.&lt;/td&gt;
  5070. &lt;/tr&gt;
  5071. &lt;tr&gt;
  5072. &lt;td&gt;&lt;code&gt;QValidator.State.Intermediate&lt;/code&gt;&lt;/td&gt;
  5073. &lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
  5074. &lt;td&gt;The input is a valid intermediate value.&lt;/td&gt;
  5075. &lt;/tr&gt;
  5076. &lt;tr&gt;
  5077. &lt;td&gt;&lt;code&gt;QValidator.State.Acceptable&lt;/code&gt;&lt;/td&gt;
  5078. &lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
  5079. &lt;td&gt;The input is acceptable as a final result.&lt;/td&gt;
  5080. &lt;/tr&gt;
  5081. &lt;/tbody&gt;
  5082. &lt;/table&gt;
  5083. &lt;p&gt;When you set a validator to a given line edit, the user may change the content to any &lt;a href="https://doc.qt.io/qt-6/qvalidator.html#State-enum"&gt;&lt;code&gt;Intermediate&lt;/code&gt;&lt;/a&gt; value during editing. However, they can't edit the text to a value that is &lt;a href="https://doc.qt.io/qt-6/qvalidator.html#State-enum"&gt;&lt;code&gt;Invalid&lt;/code&gt;&lt;/a&gt;. The line edit will emit the &lt;code&gt;returnPressed&lt;/code&gt; and &lt;code&gt;editingFinished&lt;/code&gt; signals only when the validator validates input as &lt;a href="https://doc.qt.io/qt-6/qvalidator.html#State-enum"&gt;&lt;code&gt;Acceptable&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
  5084. &lt;p&gt;Here's an example where we use a &lt;code&gt;QIntValidator&lt;/code&gt; and a &lt;code&gt;QRegularExpressionValidator&lt;/code&gt;&lt;/p&gt;
  5085. &lt;div class="code-block"&gt;&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
  5086. &lt;pre&gt;
  5087. &lt;code class="python"&gt;from PyQt6.QtCore import QRegularExpression
  5088. from PyQt6.QtGui import QIntValidator, QRegularExpressionValidator
  5089. from PyQt6.QtWidgets import (
  5090.    QApplication,
  5091.    QFormLayout,
  5092.    QLabel,
  5093.    QLineEdit,
  5094.    QWidget,
  5095. )
  5096.  
  5097. class Window(QWidget):
  5098.    def __init__(self, parent=None):
  5099.        super().__init__(parent)
  5100.        self.setWindowTitle("Input Validators")
  5101.        self.resize(300, 100)
  5102.  
  5103.        self.int_line_edit = QLineEdit(parent=self)
  5104.        self.int_line_edit.setValidator(QIntValidator())
  5105.  
  5106.        self.uppercase_line_edit = QLineEdit(parent=self)
  5107.        input_validator = QRegularExpressionValidator(
  5108.            QRegularExpression("[A-Z]+"), self.uppercase_line_edit
  5109.        )
  5110.        self.uppercase_line_edit.setValidator(input_validator)
  5111.        self.uppercase_line_edit.returnPressed.connect(self.update_label)
  5112.  
  5113.        self.signal_label = QLabel(parent=self)
  5114.  
  5115.        layout = QFormLayout()
  5116.        layout.addRow("Integers:", self.int_line_edit)
  5117.        layout.addRow("Uppercase letters:", self.uppercase_line_edit)
  5118.        layout.addRow("Signal:", self.signal_label)
  5119.        self.setLayout(layout)
  5120.  
  5121.    def update_label(self):
  5122.        self.signal_label.setText("Return pressed!")
  5123.  
  5124. if __name__ == "__main__":
  5125.    app = QApplication([])
  5126.    window = Window()
  5127.    window.show()
  5128.    app.exec()
  5129. &lt;/code&gt;
  5130. &lt;/pre&gt;&lt;/div&gt;
  5131. &lt;p&gt;In this example, we have two line edits. In the first line edit, we've used a &lt;code&gt;QIntValidator&lt;/code&gt; object. This way, the line edit will only accept valid integer numbers. If you try to type in something different, then the line edit won't accept your input.&lt;/p&gt;
  5132. &lt;p&gt;In the second line edit, we've used a &lt;code&gt;QRegularExpressionValidator&lt;/code&gt;. In this specific case, the regular expression accepts one or more uppercase letters. Again if you try to enter something else, then the line edit won't accept the input.&lt;/p&gt;
  5133. &lt;p&gt;The &lt;code&gt;QLabel&lt;/code&gt; will show the text &lt;code&gt;Return pressed!&lt;/code&gt; if the input in the second line edit is valid and you press the Enter key. Here's what the app looks like:&lt;/p&gt;
  5134. &lt;p&gt;&lt;img alt="QLineEdit with input validator" height="292" src="https://www.pythonguis.com/static/docs/qlineedit/qlineedit-input-validators.png" width="600"&gt; &lt;em&gt;QLineEdit with input validator.&lt;/em&gt;&lt;/p&gt;
  5135. &lt;p&gt;Validators provide a quick way to restrict the user input and set our own validation rules. This way, we can ensure valid user input in our applications.&lt;/p&gt;
  5136. &lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
  5137. &lt;p&gt;Line edits are pretty useful widgets in any GUI application. They allow text input through a single-line editor that has many cool features.&lt;/p&gt;
  5138. &lt;p&gt;In this tutorial, you've learned how to create, use, and customize your line edits while building a GUI application with PyQt/PySide.&lt;/p&gt;</description>
  5139.    </item>
  5140.    <item>
  5141.      <guid isPermaLink="false">https://blog.felgo.com/release-felgo-qml-hot-reload-for-qt-projects</guid>
  5142.      <title>Felgo: Felgo Hot Reload: Enhance your Qt Project Development with QML Code Reload</title>
  5143.      <pubDate>Thu, 25 Jan 2024 12:58:33 GMT</pubDate>
  5144.      <link>https://blog.felgo.com/release-felgo-qml-hot-reload-for-qt-projects</link>
  5145.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://blog.felgo.com/release-felgo-qml-hot-reload-for-qt-projects" title=""&gt;&lt;img alt="Felgo Hot Reload: Enhance your Qt Project Development with QML Code Reload" class="hs-featured-image" src="https://blog.felgo.com/hubfs/felgo-hot-reload-product-release.png" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  5146. &lt;p&gt;Felgo specializes in unique Qt products and tools to develop fast and efficiently. QML Hot Reload is one of them, and it transforms the way you develop Qt Quick applications.&lt;/p&gt;
  5147. &lt;p&gt;&lt;span style="font-weight: normal;"&gt;The&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;Felgo Hot Reload&lt;/span&gt; release now makes the tool available as a standalone product - independent from the Felgo SDK. This means that you can &lt;span style="font-weight: bold;"&gt;integrate code reloading to any Qt/QML project&lt;/span&gt; to enhance your development workflow. To do so, simply add the Felgo QML Hot Reload library to your project. No change to your production code is required.&lt;/p&gt;
  5148. &lt;p style="text-align: center;"&gt;&lt;a class="cta_button" href="https://hs.felgo.com/cs/ci/?pg=d3780ea5-44e6-4b22-a0b3-1875caeed7f4&amp;pid=6147417&amp;ecid=&amp;hseid=&amp;hsic="&gt;&lt;img alt="Get Felgo Hot Reload" class="hs-cta-img" src="https://no-cache.hubspot.com/cta/default/6147417/d3780ea5-44e6-4b22-a0b3-1875caeed7f4.png"&gt;&lt;/a&gt;&lt;br&gt;
  5149. &lt;br&gt;&lt;/p&gt;
  5150. &lt;p&gt;Read this post to learn why you should not miss QML Hot Reload in your development setup, and what benefits it brings to your project:&lt;/p&gt;
  5151. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=6147417&amp;k=14&amp;r=https%3A%2F%2Fblog.felgo.com%2Frelease-felgo-qml-hot-reload-for-qt-projects&amp;bu=https%253A%252F%252Fblog.felgo.com&amp;bvt=rss" width="1"&gt;</description>
  5152.    </item>
  5153.    <item>
  5154.      <guid isPermaLink="false">https://blog.felgo.com/develop-qt-quick-apps-with-visual-studio-code-qml-extension</guid>
  5155.      <title>Felgo: QML Extension for Visual Studio Code: Develop Qt Quick with VS Code and QML Hot Reload</title>
  5156.      <pubDate>Thu, 11 Jan 2024 17:15:00 GMT</pubDate>
  5157.      <link>https://blog.felgo.com/develop-qt-quick-apps-with-visual-studio-code-qml-extension</link>
  5158.      <description>&lt;div class="hs-featured-image-wrapper"&gt;&lt;a class="hs-featured-image-link" href="https://blog.felgo.com/develop-qt-quick-apps-with-visual-studio-code-qml-extension" title=""&gt;&lt;img alt="QML Extension for Visual Studio Code: Develop Qt Quick with VS Code and QML Hot Reload" class="hs-featured-image" src="https://blog.felgo.com/hubfs/develop-qt-quick-apps-with-vs-code-and-qml-hot-reload-2023.png" style="width: auto !important; float: left; margin: 0 15px 15px 0;"&gt;&lt;/a&gt;&lt;/div&gt;
  5159. &lt;p&gt;Visual Studio Code ranks &lt;strong&gt;#1 among the most popular development tools&lt;/strong&gt; in the annual developers survey of Stack Overflow. More than 70% of all participants use this code editor for development. And there&#x2019;s a reason why: It is fast, reliable, supports a wide range of languages and runs on Windows, macOS and Linux.&lt;/p&gt;
  5160. &lt;p&gt;With the right extensions and tools, you can set up and use Visual Studio Code to develop your Qt and QML projects. Watch the tutorial or read this guide to learn how:&lt;/p&gt;
  5161. &lt;div class="hs-embed-wrapper" style="overflow: hidden; width: 100%; height: auto; padding: 0px; display: block; margin: auto;"&gt;
  5162. &lt;div class="hs-embed-content-wrapper"&gt;
  5163. &lt;div style="overflow: hidden; padding-bottom: 56.5%; margin: 0px;"&gt;&lt;/div&gt;
  5164. &lt;/div&gt;
  5165. &lt;/div&gt;
  5166. &lt;p&gt;&#xA0;&lt;/p&gt;
  5167. &lt;img alt="" height="1" src="https://track.hubspot.com/__ptq.gif?a=6147417&amp;k=14&amp;r=https%3A%2F%2Fblog.felgo.com%2Fdevelop-qt-quick-apps-with-visual-studio-code-qml-extension&amp;bu=https%253A%252F%252Fblog.felgo.com&amp;bvt=rss" width="1"&gt;</description>
  5168.    </item>
  5169.    <item>
  5170.      <guid isPermaLink="false">http://planet.qt.io/rss20.xml#id8a10ab52a5df2a23ab8c1d542cfa111805687424</guid>
  5171.      <title>Cutelyst Framework: Cutelyst v4 - 10 years &#x1F389;</title>
  5172.      <pubDate>Thu, 21 Dec 2023 21:49:36 GMT</pubDate>
  5173.      <link>https://cutelyst.org/2023/12/21/cutelyst-v4-10-years</link>
  5174.      <description>&lt;p&gt;Cutelyst the Qt web framework is now at v4.0.0 just a bit later for it's 10th anniversary.&lt;/p&gt;
  5175. &lt;p&gt;With 2.5k commits it has been steadly improving, and in production for many high traffic applications. With this release we say good bye to our old Qt5 friend, also dropped uWSGI support, clearsilver and Grantlee were also removed, many methods now take a QStringView and Cutelyst::Header class was heavly refactored to allow usage of QByteArrayView, and stopped storing QStrings internally in a QHash, they are QByteArray inside a vector.&lt;/p&gt;
  5176. &lt;p&gt;Before, all headers were uppercased and dashes replaced with underscores, this was quite some work, so that when searching the string had to be converted to this format to be searcheable, this had the advantage of allowing the use of QHash and in templates you could c.request.header.CONTENT_TYPE. Turns out both cases aren't so important, speed is more important for the wider use cases.&lt;/p&gt;
  5177. &lt;p&gt;With these changes Cutelyst managed to get 10 - 15% faster on TechEmpower benchmarks, which is great as we are still well positioned as a full stack framework there.&lt;/p&gt;
  5178. &lt;p&gt;https://github.com/cutelyst/cutelyst/releases/tag/v4.0.0&lt;/p&gt;
  5179. &lt;p&gt;Have fun, Merry Christmas and Happy New Year!&lt;/p&gt;</description>
  5180.    </item>
  5181.    <item>
  5182.      <guid isPermaLink="false">https://scythe-studio.com/en/blog/qt-for-mcu</guid>
  5183.      <title>Scythe Studio Qt Blog: Qt Embedded Programming &amp;#8211; First Steps with Qt for MCUs</title>
  5184.      <pubDate>Wed, 20 Dec 2023 14:27:26 GMT</pubDate>
  5185.      <link>https://scythe-studio.com/en/blog/qt-for-mcu</link>
  5186.      <description>&lt;p&gt;On our blog, we have repeatedly covered various &#x2018;branches&#x2019; of Qt-a such as 3D, Android, DBus, etc (the latter topic [&#x2026;]&lt;/p&gt;</description>
  5187.    </item>
  5188.  </channel>
  5189. </rss>
  5190.  

If you would like to create a banner that links to this page (i.e. this validation result), do the following:

  1. Download the "valid RSS" banner.

  2. Upload the image to your own server. (This step is important. Please do not link directly to the image on this server.)

  3. Add this HTML to your page (change the image src attribute if necessary):

If you would like to create a text link instead, here is the URL you can use:

http://www.rssboard.org/rss-validator/check.cgi?url=http%3A//planet.qt-project.org/rss20.xml

Software created by Sam Ruby, Mark Pilgrim, Joseph Walton and Phil Ringnalda