[{"content":"","date":"2 April 2026","externalUrl":null,"permalink":"/","section":"CodeFlamingo","summary":"","title":"CodeFlamingo","type":"page"},{"content":"","date":"2 April 2026","externalUrl":null,"permalink":"/blog/","section":"The CodeFlamingo Blog","summary":"","title":"The CodeFlamingo Blog","type":"blog"},{"content":" Introduction # Developing custom embedded Linux systems poses unique challenges, from managing hardware configurations to optimizing software performance. Two leading tools in this domain are the Yocto Project and Buildroot. Both offer robust solutions for building tailored Linux images suited to various project needs. However, choosing the right tool is crucial, as each has its strengths and weaknesses that align better with different development environments and requirements.\n1. Understanding Yocto and Buildroot: The Basics # What is Yocto? # The Yocto Project is a comprehensive framework for building custom Linux images. It combines tools, metadata, and recipes to create a full-featured Linux OS from scratch. Key features include:\nMeta-layers and Recipes: Use .bb files to define build specifications, making customization extensive. Hardware and Software Support: Compatible with multiple hardware architectures and supports various application needs. Community and Documentation: Benefits from a large community and extensive documentation. What is Buildroot? # Buildroot is a lightweight tool aimed at creating a root file system for embedded systems. It optionally builds a complete Linux distribution. Key features include:\nSimplicity: Easy to use with a menu-driven configuration interface. Package Selection: Over 2000 packages available, selected through the .config file. Built-in Kernel and Toolchain Management: Handles kernel compilation and toolchains seamlessly. 2. Architecture and Workflow # Yocto\u0026rsquo;s Workflow # BitBake Role: The core build engine that processes recipes defined in .bb files. Layering Mechanism: Allows for customizing hardware and software configurations by stacking layers. CI/CD Integration: Supports integration with continuous integration and deployment pipelines, suitable for enterprise-level development. Buildroot\u0026rsquo;s Workflow # Configuration Process: Step-by-step menu-driven setup where developers select packages and build options. .config File: Centralizes configuration settings for package selection and build parameters. Toolchain and Rootfs Building: Automates the construction of the toolchain, kernel, and root filesystem. 3. Advanced Concepts for Developers # Customization and Flexibility # Yocto: Offers extensive customization through meta-layers and recipes, supporting multiple development streams. Buildroot: Provides a modular approach to package selection, though with less flexibility compared to Yocto, making it faster for basic use cases. Performance and Optimization # Building Optimized Systems: Yocto: Uses the oe-iso-image layer for minimal images. Buildroot: Offers package stripping features for size optimization. Cross-compilation and Toolchain Management: Yocto: Integrates an gcc recipe system. Buildroot: Features a built-in toolchain builder. Integration with CI/CD Pipelines # Automated Builds: Yocto: Utilizes devshell and Git repositories for integration. Buildroot: Automates configuration and build steps via scripts. Scaling for Large-scale Projects: Yocto: Supports distributed builds using tools like distbb. Buildroot: Lacks scalability compared to Yocto. Maintenance and Support # Community and Ecosystem: Yocto: Benefits from large community support, including backing by organizations like the Linux Foundation. Buildroot: Maintains a smaller, niche-focused community. Long-term Support: Yocto: Offers robust release cycles and security updates. Buildroot: Focuses on minimalism and compatibility. 4. Advanced Use Cases # Yocto for Industrial Applications # Custom BSPs: Building Board Support Packages tailored to specific hardware. IoT and Edge Computing: Integrating with IoT platforms and managing complex hardware-software co-engineering. Buildroot for Quick Prototyping # Rapid Development: Quickly developing proof-of-concept systems. Cost-effective Solutions: Providing lightweight, resource-optimized solutions for small-scale projects. 5. Performance Comparisons # Build Time Differences # Yocto: Known for longer build times due to its comprehensive nature and extensive customization options. Buildroot: Faster build times, particularly suitable for smaller, simpler systems. Image Size Optimization # Yocto: Uses the IMAGE_FSTYPES configuration to optimize image formats. Buildroot: Offers package stripping and compression options for efficient image sizes. Cross-platform Compatibility and Testing # Yocto: Features a robust testing infrastructure. Buildroot: Provides limited testing support, making it less suitable for extensive cross-platform compatibility testing. 6. Choosing the Right Tool: A Decision Guide # Criteria for Selection # Project Complexity: Yocto is better suited for large-scale, complex projects. Community and Ecosystem Support: Considerations include corporate backing and community size. Development Timeline: Buildroot offers faster setup for quick prototyping. Resource Availability: Large teams might find Yocto more manageable due to its extensive documentation and tools. Case Studies # Yocto Use Cases: Ideal for industrial projects requiring extensive customization and integration with IoT platforms. Buildroot Use Cases: Suitable for small teams looking for a quick, lightweight solution for prototyping. 7. Conclusion # In summary, both Yocto and Buildroot are powerful tools for embedded Linux development, each offering unique advantages. The choice between them should be guided by the specific requirements of your project, including scale, complexity, and community support. Whether you need a comprehensive solution like Yocto or a more streamlined approach with Buildroot, understanding their capabilities will help in making an informed decision.\n8. Advanced Technical References # Yocto Documentation: https://www.yoctoproject.org/docs/ Buildroot User Manual: https://buildroot.org/ GitHub Repositories: Yocto: https://github.com/YoeDistro/yocto-project Buildroot: https://git.buildroot.net/buildroot/ ","date":"2 April 2026","externalUrl":null,"permalink":"/blog/yocto-buildroot-comparison/","section":"The CodeFlamingo Blog","summary":"","title":"Yocto vs BuildRoot: A Deep Dive into Advanced Embedded Linux Development Tools","type":"blog"},{"content":"","date":"25 February 2026","externalUrl":null,"permalink":"/tags/c++/","section":"Tags","summary":"","title":"C++","type":"tags"},{"content":"","date":"25 February 2026","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"25 February 2026","externalUrl":null,"permalink":"/tags/rust/","section":"Tags","summary":"","title":"Rust","type":"tags"},{"content":"","date":"25 February 2026","externalUrl":null,"permalink":"/tags/system-programming/","section":"Tags","summary":"","title":"System-Programming","type":"tags"},{"content":"","date":"25 February 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"25 February 2026","externalUrl":null,"permalink":"/categories/tech/","section":"Categories","summary":"","title":"Tech","type":"categories"},{"content":" Introduction # In the dynamic landscape of programming languages, the choice between sticking with a tried-and-true language like C++ or exploring new technologies can often feel overwhelming. However, in 2026, it\u0026rsquo;s becoming increasingly clear that learning Rust could be a valuable investment for any C++ developer. With its unique features in memory safety, performance optimization, and concurrency support, Rust offers a powerful alternative that complements the strengths of C++. This blog post will explore why C++ developers should consider learning Rust, delve into advanced Rust concepts, and understand how Rust can enhance their skill set in low-level programming.\n1. Understanding Rust: A Modern Alternative to C++ # Rust\u0026rsquo;s Unique Features Compared to C++ # Rust stands out as a modern language that offers several advantages over traditional languages like C++. At its core, Rust avoids the pitfalls of memory management found in C++ by eliminating raw pointers and garbage collection. This leads to more robust and less error-prone code.\nMemory Safety # One of the standout features of Rust is its strong emphasis on memory safety without sacrificing performance. Unlike C++, where you have to manage memory manually, Rust uses a sophisticated ownership model that ensures memory is only used as long as it is needed. This eliminates common issues like memory leaks and dangling pointers.\nPerformance # Rust also offers excellent performance, often rivaling or surpassing the speed of languages like C++. Its compiler is designed with optimization in mind, making it capable of producing highly efficient code. By avoiding runtime overhead through features like zero-cost abstractions, Rust can deliver consistent performance even under heavy loads.\nConcurrency and Parallelism # Another area where Rust excels is in concurrency and parallelism. Unlike C++, which relies on RAII (Resource Acquisition Is Initialization) for managing resources during concurrent execution, Rust uses channels for communication between threads. This approach not only avoids common pitfalls like deadlocks but also leverages the language\u0026rsquo;s type system to ensure safety.\nWhy Rust is a Good Fit # Rust is particularly well-suited for scenarios where memory safety and performance are critical. Whether you\u0026rsquo;re working on device drivers, embedded systems, or high-performance network applications, Rust can provide the tools and guarantees you need to build robust and efficient software.\nMoreover, major tech companies like Facebook, Meta, and others have already adopted Rust for critical projects. This adoption underscores the potential of Rust in real-world applications and demonstrates its reliability and effectiveness.\n2. Advanced Rust Concepts for C++ Developers # Rust\u0026rsquo;s Ownership Model # Understanding Rust\u0026rsquo;s ownership model is crucial for effectively working with the language. Unlike C++, where you have to manually manage memory, Rust uses a system that tracks the lifecycle of data.\nRaw Types and Borrow Counting # Rust allows the use of raw pointers (*const and *mut) but does not allow dereferencing them unless explicitly marked as safe. This ensures that developers are aware of the risks involved with low-level memory manipulation. Rust also uses a borrowing-counting system to track how many parts of a program have access to a piece of data at any given time.\nSafe Tuple Types # Unlike C++ tuples, which can contain elements of different types and do not enforce safety, Rust\u0026rsquo;s tuple types are inherently safe. This means that accessing elements in a tuple is type-safe and will always work as expected, reducing the risk of runtime errors.\nConcurrency and Parallelism in Rust # Rust provides robust tools for managing concurrency without sacrificing safety.\nChannels (send/receive) # One of Rust\u0026rsquo;s most powerful features for concurrent programming is the std::sync::mpsc channel. Channels allow threads to communicate safely by sending messages back and forth. Unlike C++, where RAII can complicate thread management, Rust\u0026rsquo;s channels provide a clear, type-safe mechanism for managing communication between threads.\nComparing to RAII # While both languages support concurrent programming, the way they manage resources is different. Rust\u0026rsquo;s ownership model ensures that resources are only used as long as they are needed, reducing the risk of resource leaks and other common concurrency issues. C++, on the other hand, relies on RAII for managing resources during concurrent execution.\nZero-Cost Abstractions in Rust # Rust promotes zero-cost abstractions by providing a rich set of libraries that allow developers to write concise and efficient code without sacrificing performance.\nIterators and Lazy Evaluation # One of the most powerful features of Rust is its support for iterators. Iterators allow developers to process data lazily, meaning that elements are only processed as they are needed. This can significantly improve performance by reducing memory usage and avoiding unnecessary computations.\nPromotion of Ownership # Rust\u0026rsquo;s ownership model promotes safe reuse of data by allowing ownership to be transferred between variables without raw pointers. This ensures that data is always used safely and efficiently, reducing the risk of runtime errors.\n3. Memory Management in Rust # Effective memory management is a critical aspect of Rust development, especially for low-level applications.\nRaw Data and Advanced Techniques # Rust allows the use of raw pointers (*const and *mut) in certain cases where performance is critical. However, using raw pointers can also introduce risks like dangling pointers and data races if not managed carefully.\nRaw Pointers and Raw Aliases # Raw pointers should only be used when absolutely necessary. For example, you might use a raw pointer to pin memory in place or to interact with legacy C libraries. In these cases, it\u0026rsquo;s important to ensure that the memory is properly managed to avoid leaks or other issues.\nBorrow-Safe Data Structures # Rust provides several data structures that are designed to be safe and efficient. For example, Vec and HashMap are automatically resized as needed, ensuring that they can handle dynamic data without manual intervention.\n4. Rust for High-Performance Applications # Rust is particularly well-suited for high-performance applications where every cycle counts.\nOptimization Techniques # In some cases, using unsafe code in Rust can provide significant performance improvements.\nUnsafe Code # Unsafe code should be used only when absolutely necessary and with a clear understanding of the risks involved. However, in critical performance-critical applications, using unsafe code can make a noticeable difference in performance.\nConst and Lazy Initialization # Rust provides several techniques for optimizing performance, such as const initialization and lazy evaluation. By using these techniques, developers can reduce runtime overhead and improve overall efficiency.\nIterators Adapters # Rust\u0026rsquo;s iterator adaptors provide a powerful way to process data efficiently. For example, you can use the map, filter, and fold methods to transform and aggregate data in a concise and efficient manner.\n5. Rust\u0026rsquo;s Future and Advanced Development # Rust is constantly evolving, with new features and improvements being added regularly.\nLatest Developments # Rust has a long history of innovation and improvement. For example, the latest stable release (e.g., 1.34) introduced several major features, including improved ownership checker performance, support for raw types in std::mem::raw, and better garbage collection.\nNew Features # Looking ahead, Rust is expected to continue to evolve with new features and improvements. For example, future versions may introduce channels with timeouts or enum variants that can be promoted to enhance the language\u0026rsquo;s capabilities.\nConclusion # Rust offers a unique set of advantages that can enhance C++ developers\u0026rsquo; skill sets, particularly in low-level programming and concurrency. By learning Rust, you\u0026rsquo;ll gain access to powerful features that improve memory safety, performance, and concurrency support. As tech companies continue to adopt Rust for critical projects, now is the perfect time to explore this exciting language.\nWe encourage you to dive deeper into Rust through hands-on projects or further study. Here are some resources to help you get started:\nRust Official Documentation The Rust Programming Language Book Rust Community Tutorials By learning Rust, you\u0026rsquo;ll be better equipped to tackle the challenges of modern programming and build robust, efficient software that can handle the demands of today\u0026rsquo;s technology.\n","date":"25 February 2026","externalUrl":null,"permalink":"/blog/c-plus-plus-developers-learn-rust-2026/","section":"The CodeFlamingo Blog","summary":"","title":"Why Should C++ Developers Learn Rust in 2026?","type":"blog"},{"content":"","date":"26 December 2024","externalUrl":null,"permalink":"/categories/machine-learning/","section":"Categories","summary":"","title":"Machine Learning","type":"categories"},{"content":"","date":"26 December 2024","externalUrl":null,"permalink":"/tags/python/","section":"Tags","summary":"","title":"Python","type":"tags"},{"content":"","date":"26 December 2024","externalUrl":null,"permalink":"/tags/pytorch/","section":"Tags","summary":"","title":"Pytorch","type":"tags"},{"content":"Installation of Pytorch using Miniforge3 on Windows 11\nIntroduction # PyTorch is a widely-used open-source machine learning library originally developed by Meta AI. Over time, it has gained significant traction and emerged as one of the leading frameworks in the machine learning ecosystem. Today, PyTorch operates under the governance of the Linux Foundation, further solidifying its role in the open-source community.\nIn this tutorial, we will guide you through the process of installing PyTorch on a Windows 11 machine using the Miniforge package manager. Prerequisites # To follow this tutorial, ensure you have the following:\nA laptop or PC (preferably equipped with an NVIDIA GPU and CUDA support) Python version 3.9 or later (bundled with Miniforge during installation) Installation # PyTorch can typically be installed via Anaconda or Pip, but in this tutorial, we’ll use Miniforge. Miniforge is a free, community-driven, lightweight installer that includes useful packages like Conda and Python with minimal overhead. By default, Miniforge uses the conda-forge channel for package installations.\nStep 1: Download and Install Miniforge # To get started, download the 64-bit version of Miniforge for Windows 11. At the time of writing, we are using:\nMiniforge3-24.11.0-0-Windows-x86_64.exe\nYou can find the latest release on the Miniforge GitHub repository. Miniforge comes bundled with Python, so there’s no need for a separate Python installation. Once installed, open the Miniforge Prompt from the Windows Start Menu (Miniforge Prompt).\nStep 2: Verify Python Version # Ensure your Python version is 3.9 or later. Check the installed version by running:\npython --version\nIf your Python version is outdated, you may need to update or reinstall Miniforge.\nStep 3: Install PyTorch with CUDA Support # PyTorch can be installed in two modes: with or without CUDA. In this tutorial, we’ll install it with CUDA enabled for better performance, as CUDA accelerates computation on compatible NVIDIA GPUs.\nCreate a Conda Environment # To keep your setup organized, create a new Conda environment for PyTorch. Replace with the version you verified earlier:\nconda create -n pytorch-env python=\u0026lt;your-installed-python-version\u0026gt;\nconda activate pytorch-env\nCheck CUDA Installation # Before proceeding, confirm that CUDA is installed and check its version. On Windows 11, open Command Prompt and run:\nnvidia-smi\nThis command should display information about your GPU and the installed CUDA version. If CUDA is not installed, follow NVIDIA’s official guide.\nInstall PyTorch # With the Conda environment activated, install PyTorch and its dependencies:\nconda install pytorch torchvision torchaudio pytorch-cuda=12.4 -c pytorch -c nvidia\nDuring installation, you’ll be prompted to confirm the addition of multiple packages. After a successful installation, PyTorch will be ready to use.\nStep 4: Test Your Installation # To verify that PyTorch is working correctly, run the following in the Miniforge Prompt:\npython\nThen, in the Python interpreter, execute:\nimport torch x = torch.rand(5,3) print(x) You should see an output similar to:\ntensor([[0.2024, 0.3091, 0.9639], [0.3450, 0.1904, 0.8550], [0.6629, 0.4928, 0.6141], [0.7480, 0.6815, 0.2906], [0.3157, 0.1456, 0.3400]]) Verify CUDA Availability # To ensure PyTorch can utilize your GPU, check for CUDA availability:\nimport torch torch.cuda.is_available() If True is returned, PyTorch is ready to leverage CUDA for accelerated computations.\n","date":"26 December 2024","externalUrl":null,"permalink":"/blog/pytorch-installation-windows/","section":"The CodeFlamingo Blog","summary":"Installation of Pytorch using Miniforge3 on Windows 11\n","title":"Pytorch Installation on Windows 11","type":"blog"},{"content":"","date":"21 September 2021","externalUrl":null,"permalink":"/tags/cplusplus/","section":"Tags","summary":"","title":"Cplusplus","type":"tags"},{"content":"","date":"21 September 2021","externalUrl":null,"permalink":"/categories/programming/","section":"Categories","summary":"","title":"Programming","type":"categories"},{"content":"","date":"21 September 2021","externalUrl":null,"permalink":"/tags/qt/","section":"Tags","summary":"","title":"Qt","type":"tags"},{"content":"Set custom system tray icon with custom context menu for your application\nIntroduction # Modern operating systems usually provide a special area on the desktop, called the system tray or notification area, where long-running applications can display icons and short messages. These icons can also be customized to show short context menus for additional functionality.\nQt framework has native support to add tray icons using the class QSystemTray. In this tutorial, we will see how can we implement system tray icon with custom context menu for our application with just couple of lines of code.\nCode # Before we use the QSystemTray class we need to make sure we have a .ico file which we need to set as an icon for our application. A .ico file is nothing but an icon file. You can convert your .png or .jpg image into .ico file using online converters like this. Once we have the .ico file ready, we can either add it to our resource(.rc) file of our application if available.\nWith a couple of lines of code as shown below, we can create a tray icon with a custom menu for our application ready.\n// create system tray icon // assuming you have added .ico file to your resource .rc file // otherwise, provide a relative path to it QSystemTrayIcon* trayIcon = new QSystemTrayIcon(QIcon(\u0026#34;:/path/to/your/.ico file\u0026#34;), this); // add tray icon menu actions QMenu* trayMenu = new QMenu(this); trayMenu-\u0026gt;addAction(\u0026#34;Show\u0026#34;); trayMenu-\u0026gt;addAction(\u0026#34;Exit\u0026#34;); // set menu on the system tray icon trayIcon-\u0026gt;setContextMenu(trayMenu); // show tray icon m_systemTrayIcon-\u0026gt;show(); Conclusion # The above piece of code will create a tray icon and when you right-click on it you would have your custom context menu displayed for you. If this was helpful, please share this blog, and also feel free to add your thoughts or comments below.\nPhoto by Ben Schnell on Unsplash\n","date":"21 September 2021","externalUrl":null,"permalink":"/blog/systemtrayicon-with-custom-menu/","section":"The CodeFlamingo Blog","summary":"Set custom system tray icon with custom context menu for your application\n","title":"Systemtray icon with custom context menu on any modern OS","type":"blog"},{"content":"","date":"27 June 2021","externalUrl":null,"permalink":"/tags/cmake/","section":"Tags","summary":"","title":"Cmake","type":"tags"},{"content":"Authenticate samba server using Windows API\nIntroduction # Samba is an open-source service that runs on Linux/Unix based platforms while having the capability to communicate with Windows OS clients. Samba server offers services like:\nSharing of directories Sharing printers Windows clients authentication Name-server resolution and so on In this tutorial, we will discuss about how to implement communication between Qt application and samba server using authentication. We do not go into the depth of setting up or configuring samba servers as it will be beyond the scope of our discussion.\nProblem # A samba server without authentication is open to communicate with as many clients as possible if set up correctly. But communicating with a samba server with authentication can be challenging. Qt doesn\u0026rsquo;t have native support to mount network resources and deal with file protocols. So, we will use Windows APIs to get around the authentication issue. Of course, this would violate Qt\u0026rsquo;s cross-platform ability but this would be useful for anyone developing applications only for Windows platforms.\nSetup and Configuration # We will need the WNetAddConnection2A function from the Windows API to make the connection to a network resource as in our case samba server.\nWe need to set up 3 key components to achieving a successful connection:\nSetup network resource Samba server username Samba server password Network resource or NETRESOURCE needs attributes to be setup like:\nlocal name - Q: remote name - ////samba_ip_address//path//to//destination (extra / are for escape characters in the path) resource type - to any You can read more about NETRESOURCE here.\nAfter setting up our NETRESOURCE we need to call WNetAddConnection2A function to establish a connection to the samba server. WNetAddConnection2A takes in 4 arguments:\nnet resource - that we built above password - samba password username - samba username type of connection you would like WNetAddConnection2A returns with an error code which can be handled as you wish. Below is a sample function showing the creation of NETRESOURCE and add a new connection using WNetAddConnection2A.\n#include \u0026lt;windows.h\u0026gt; #include \u0026lt;Winnetwk.h\u0026gt; #include \u0026lt;system_error\u0026gt; #include \u0026lt;iostream\u0026gt; // Need to link with Netapi32.lib and Mpr.lib bool ServerConnection::create(const QString\u0026amp; remoteName, const QString\u0026amp; username, const QString\u0026amp; password) { DWORD dwRetVal; NETRESOURCE nr; DWORD dwFlags; // assign a drive name // avoid using commonly used names like C:, D: LPSTR szLocalName = \u0026#34;Q:\u0026#34;; LPSTR szRemoteName = new TCHAR[remoteName.toStdString().size() + 1]; //define std::strcpy(szRemoteName, remoteName.toStdString().c_str()); // Zero out the NETRESOURCE struct memset(\u0026amp;nr, 0, sizeof (NETRESOURCE)); // Assign our values to the NETRESOURCE structure. nr.dwType = RESOURCETYPE_ANY; nr.lpLocalName = szLocalName; nr.lpRemoteName = szRemoteName; nr.lpProvider = NULL; // Assign a value to the connection options // this flag makes sure windows doesn\u0026#39;t remember previous connections dwFlags = CONNECT_TEMPORARY; // Call the WNetAddConnection2 function to assign // a drive letter to the share. dwRetVal = WNetAddConnection2A(\u0026amp;nr, password.toStdString().c_str(), username.toStdString().c_str(), dwFlags); // get the message string std::string message = std::system_category().message(dwRetVal); std::cout \u0026lt;\u0026lt; message \u0026lt;\u0026lt; std::endl; // handle error statements switch (dwRetVal) { case NO_ERROR: case ERROR_ALREADY_ASSIGNED: case ERROR_DEVICE_ALREADY_REMEMBERED: return true; default: return false; } } This implementation to communicate with samba server using Windows API has dependencies too. To make this work you will need to link your application to 2 different libraries:\nMpr.lib NetAPI32.lib These libs are usually found inside *C:\\Program Files(x86)\\Windows Kits\\10*\nConclusion # To be able to communicate with the samba server beyond the authentication wall as a window client can be tricky. Using Windows API we learned how to mount the samba server locally as a network resource using WNetAddConnection2A function.\nIf this was helpful, please share this blog, and also feel free to add your thoughts or comments below.\nPhoto by FLY:D on Unsplash\n","date":"27 June 2021","externalUrl":null,"permalink":"/blog/samba-authentication-windows/","section":"The CodeFlamingo Blog","summary":"Authenticate samba server using Windows API\n","title":"Samba authentication in Qt app using Windows API","type":"blog"},{"content":"Set application icon using CMake on Windows\nIntroduction # In the previous tutorial we managed to simply set the application icon using QMake. In this tutorial, we will learn how to set the icon of an application using CMake scripts.\nSetup and Configuration # Before we can start writing CMake scripts we need to create a resource(.rc file). To create a .rc file, right-click in your current source directory where the CMakeLists.txt exists and choose a new document. Rename the new document to \u0026ldquo;appicon.rc\u0026rdquo;. Open the .rc file in an editor and paste this line in it:\nIDI_ICON1 ICON DISCARDABLE \u0026#34;appicon.ico\u0026#34; Make sure appicon.ico exists in the current source directory as well. If you do not have a .ico file. You can create one here.\nNow, we just need to add this .rc file in our CMake script like:\nset(APP_ICON_RESOURCE_WINDOWS \u0026#34;${CMAKE_CURRENT_SOURCE_DIR}/appicon.rc\u0026#34;) add_executable(${PROJECT_NAME} WIN32 main.cpp ${APP_ICON_RESOURCE_WINDOWS} ) When you build and run the application, you will see the icon on the top-left corner of the window, and also the icon is set on the executable(.exe) itself.\nConclusion # If this was helpful, please share this blog, and also feel free to add your thoughts or comments below.\nPhoto by Harpal Singh on Unsplash\n","date":"25 June 2021","externalUrl":null,"permalink":"/blog/icon-on-qt-application-cmake/","section":"The CodeFlamingo Blog","summary":"Set application icon using CMake on Windows\n","title":"Set application icon using CMake on Windows","type":"blog"},{"content":"Set icon on Qt application window and on executable\nIntroduction # Sometimes, simple tasks like setting an icon for application or executable can be very confusing and complicated. In this tutorial, we will see how easy it is to set an icon for Qt applications.\nWhat do we need? # A .ico file in the source directory. Icon can be any image of choice but it must be a .ico file for this to work.\nSetup # Setup is very simple. The .ico file must in the source directory and one single line inside .pro file of the project:\nRC_ICONS = my_icon.ico\nAfter this run qmake, build the project, and run. Now, the icon is set on the top left corner of the Qt application and also on our executable file.\nConclusion # If this was helpful, please share this blog and also feel free to add your thoughts or comments below.\nPhoto by Harpal Singh on Unsplash\n","date":"13 May 2021","externalUrl":null,"permalink":"/blog/icon-on-application/","section":"The CodeFlamingo Blog","summary":"Set icon on Qt application window and on executable\n","title":"Set icon on Qt application","type":"blog"},{"content":"Let\u0026rsquo;s talk about aspect ratio handling in QLabel.\nIntroduction # Displaying a big image on a QLabel is not always straight forward. For instance, we have an image of size 1920 x 1080 pixels, the label size may or may not be sufficient to show the whole image in the size of QLabel itself.\nIn this tutorial, we will address 2 issues:\nHow to keep aspect ratio of the image while resizing a QLabel? How to make QLabel follow the aspect ratio of the image it is showing? Formula # This is where, aspect ratio comes into the picture. Aspect ratio helps us to keep the entire image inside the size we have available with us.\nTo preserve aspect ratio, we need to calculate new dimensions for the original height and width of the image. Lets we have an image of 1920 x 1080 pixels and our width of our QLabel is only 400 pixels. New height of our image, preserving the aspect ratio would be:\n(original height of the image) / (original width of the image) x width of QLabel (1080 / 1920) x 400 = 225 Usually, i use this awesome and simple aspect ratio calculator.\nTutorial # For this tutorial, we will create a QLabel and load a QPixmap on QPushButton clicked. We will use QDialog as the container and QtDesigner to setup the UI. This is how our simple UI looks like:\nWe have a button Swap and a QLabel. I have added a stylesheet to our QLabel to make it more obvious. Otherwise, a QLabel without its default text is plain transparent. We will load a QPixmap whenever the button Swap is clicked.\nLets dig into code.\nOur main.cpp doesn\u0026rsquo;t look any special. Plain file created by QtCreator for us.\n#include \u0026#34;Dialog.h\u0026#34; #include \u0026lt;QApplication\u0026gt; int main(int argc, char* argv[]) { QApplication a(argc, argv); Dialog w; w.show(); return a.exec(); } To achieve our objective, we need to subclass QLabel and we call it PixmapLabel.\nLets see our PixmapLabel.h\n#ifndef PIXMAPLABEL_H #define PIXMAPLABEL_H #include \u0026lt;QLabel\u0026gt; #include \u0026lt;QPixmap\u0026gt; class PixmapLabel : public QLabel { public: PixmapLabel(QWidget* parent = nullptr); virtual QSize sizeHint() const override; void setImage(const QPixmap\u0026amp; image); int heightForWidth(int width) const override; protected: void paintEvent(QPaintEvent* event) override; private: QPixmap m_pixmap; int m_cols; int m_rows; }; #endif // PIXMAPLABEL_H Here we are going to re-implement 3 functions sizeHint(), heightForWidth() and paintEvent().\nHere is the implementation file PixmapLabel.cpp:\n#include \u0026#34;PixmapLabel.h\u0026#34; #include \u0026lt;QPainter\u0026gt; #include \u0026lt;QPaintEvent\u0026gt; PixmapLabel::PixmapLabel(QWidget* parent) : QLabel(parent), m_cols(0), m_rows(0) { QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); sizePolicy.setHeightForWidth(true); setSizePolicy(sizePolicy); setMinimumSize(sizeHint()); // set borders on the QLabel setStyleSheet(\u0026#34;QLabel{border: 1px solid black; background: gray;}\u0026#34;); } void PixmapLabel::setImage(const QPixmap\u0026amp; image) { m_pixmap = image; m_cols = m_pixmap.width(); m_rows = m_pixmap.height(); update(); } /* virtual */ QSize PixmapLabel::sizeHint() const { if (m_cols != 0) { int width = this-\u0026gt;width(); return QSize(width, heightForWidth(width)); } else { return QSize(200, 200); } } /* virtual */ int PixmapLabel::heightForWidth(int width) const { return (m_cols != 0) ? width * m_rows / m_cols : this-\u0026gt;height(); } /* virtual */ void PixmapLabel::paintEvent(QPaintEvent* event) { QLabel::paintEvent(event); // if there is no pixmap loaded yet if(m_pixmap.isNull()) { return; } // Create painter QPainter painter(this); // Get current pixmap size QSize pixmapSize = m_pixmap.size(); // Scale size to painted rect pixmapSize.scale(event-\u0026gt;rect().size(), Qt::KeepAspectRatio); // Scale the pixmap QPixmap pixmapScaled = m_pixmap.scaled(pixmapSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); // Draw the pixmap painter.drawPixmap(QPoint(), pixmapScaled); } Notice we are not using setPixmap() available in QLabel class but rather we are using paintEvent(). This allows us to resize QLabel and also scale its contents.\npaintEvent() is automatically called whenever QLabel is resized or Qt feels like it needs to repaint the contents of the QLabel as in our case a QPixmap. This solves our first issue as to how do we keep the aspect ratio while resizing and we do it without the need to explicitly implementing resizeEvent().\nTo fix our second issue, we need to manage the width() and height() of the QLabel explicitly in the container of our label i.e. QDialog.\nLets have a look at our Dialog.h\n#ifndef DIALOG_H #define DIALOG_H #include \u0026lt;QDialog\u0026gt; QT_BEGIN_NAMESPACE namespace Ui { class Dialog; } QT_END_NAMESPACE class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget* parent = nullptr); ~Dialog(); private slots: void on_pushButton_clicked(); protected: virtual void resizeEvent(QResizeEvent* event) override; private: Ui::Dialog* ui; bool m_swap; QImage m_image1; QImage m_image2; }; #endif // DIALOG_H Here is our implementation Dialog.cpp\n#include \u0026#34;Dialog.h\u0026#34; #include \u0026#34;ui_Dialog.h\u0026#34; Dialog::Dialog(QWidget* parent) : QDialog(parent) , ui(new Ui::Dialog) , m_swap(true) { ui-\u0026gt;setupUi(this); m_image1 = QImage(\u0026#34;:/images/images/1.png\u0026#34;); m_image2 = QImage(\u0026#34;:/images/images/2.jpg\u0026#34;); } Dialog::~Dialog() { delete ui; } void Dialog::on_pushButton_clicked() { if(m_swap) { ui-\u0026gt;label-\u0026gt;setImage(QPixmap::fromImage(m_image1)); m_swap = false; } else { ui-\u0026gt;label-\u0026gt;setImage(QPixmap::fromImage(m_image2)); m_swap = true; } // force QLabel to follow fixed dimensions // based on the loaded QPixmap aspect ratio int w = ui-\u0026gt;label-\u0026gt;width(); int h = ui-\u0026gt;label-\u0026gt;heightForWidth(w); ui-\u0026gt;label-\u0026gt;setFixedHeight(h); } void Dialog::resizeEvent(QResizeEvent* event) { Q_UNUSED(event); // force QLabel to follow fixed dimensions // based on the loaded QPixmap aspect ratio int w = ui-\u0026gt;label-\u0026gt;width(); int h = ui-\u0026gt;label-\u0026gt;heightForWidth(w); ui-\u0026gt;label-\u0026gt;setFixedHeight(h); } We force the QLabel to follow fixed dimensions.\nHere we have used it on 2 occasions, first when we set an image and second is in resizeEvent() of our QDialog. Whenever our QDialog is resized we resize our QLabel based on the formula we derived above. This not only allows us to preserve the aspect ratio of the image but also forces the QLabel to follow along.\nThis whole project can be found on my GitHub account.\nConclusion # Feel free to share this blog, if you feel it helped you. If you have any comments or suggestions, post it in the comments section below.\nPhoto by Daniil Kuželev on Unsplash\n","date":"31 January 2021","externalUrl":null,"permalink":"/blog/aspectratio-qpixmap/","section":"The CodeFlamingo Blog","summary":"Let’s talk about aspect ratio handling in QLabel.\n","title":"Resizing QLabel while maintaining the aspect ratio","type":"blog"},{"content":"Configuring medium-sized to large CMake projects in Qt Creator can be a challenge.\nIntroduction # Configuring medium-sized to large CMake projects in Qt Creator can be a challenge. I realized configuring my medium sized project in Qt Creator with MSVC 2015 is not straight forward. Until, I found out that there are some issues with MS build which Qt Creator doesn\u0026rsquo;t recognize.\nWhat\u0026rsquo;s the problem? # Qt Creator builds debug version even when CMAKE_BUILD_TYPE is set to RELEASE.\nSetup and Configuration # I have setup Visual Studio 14 2015 as my default generator for cmake projects in Qt Creator. So, my setup looks something like this:\nWe can configure our cmake variables the way we like it. Configuration and generation works fine. We encounter an issue when we start building the project in release configuration only to find that Qt Creator builds a debug version of the project.\nThis is an issue with ms build. To avoid this, we need to explicitly pass a cmake argument to let cmake build a release version. The build configuration for ms build would look like this /property:Configuration=Release. This argument can be added to the build steps of release configuration in Qt Creator as shown in the image below:\nThis should fix the issue of generating a proper release build for the project using MSVC 2015 generator in Qt Creator.\nConclusion # If this was helpful, please share this blog and also feel free to add your thoughts or comments below.\n","date":"29 January 2021","externalUrl":null,"permalink":"/blog/cmake-qtcreator-msvc2015/","section":"The CodeFlamingo Blog","summary":"Configuring medium-sized to large CMake projects in Qt Creator can be a challenge.\n","title":"Build CMake project in QtCreator using MSVC 2015 in Release Configuration","type":"blog"},{"content":"Imagine we want to add multiple widgets in QGridLayout dynamically but also remove widgets on the fly.\nIntroduction # Imagine we want to add multiple widgets in QGridLayout dynamically but also remove widgets on the fly. Adding widgets to grid layout is pretty straight forward but removing widgets is the tricky part. In this tutorial we will see how to achieve the same.\nGoal # Our goal would be to design a simple UI with buttons which enable us to achieve adding and removing widgets on a grid layout dynamically. Our application would ultimately look like this:\nAdding widgets to layout # Adding widgets to QGridLayout is very easy using the addWidget() which can be used further to specify row or column spans also. In our example, we add 4 QLabels to the layout when button Add is clicked.\nvoid MainWindow::on_pushButton_clicked() { // check if the grid layout is empty if(ui-\u0026gt;gridLayout-\u0026gt;count() == 0) { QLabel* label1 = new QLabel(this); QLabel* label2 = new QLabel(this); QLabel* label3 = new QLabel(this); QLabel* label4 = new QLabel(this); // set borders to labels for better visibility label1-\u0026gt;setStyleSheet(\u0026#34;border: 3px solid black;\u0026#34;); label2-\u0026gt;setStyleSheet(\u0026#34;border: 3px solid black;\u0026#34;); label3-\u0026gt;setStyleSheet(\u0026#34;border: 3px solid black;\u0026#34;); label4-\u0026gt;setStyleSheet(\u0026#34;border: 3px solid black;\u0026#34;); // add widget at (0,0) position inside the layout ui-\u0026gt;gridLayout-\u0026gt;addWidget(label1, 0,0); // add widget at (0,1) position inside the layout ui-\u0026gt;gridLayout-\u0026gt;addWidget(label2, 0,1); // add widget at (1,0) position inside the layout ui-\u0026gt;gridLayout-\u0026gt;addWidget(label3, 1,0); // add widget at (1,1) position inside the layout ui-\u0026gt;gridLayout-\u0026gt;addWidget(label4, 1,1); } } Removing widgets from layout # Removing widgets from grid layout can be little tricky. In our tutorial, we perform removing widgets using button Remove. We use convenient function removeWidget() from Qt for the purpose. First, we get the item at index 0 in the grid using itemAt(0) then after we can remove it from the layout using removeItem(). Keep in mind this will only remove the item from the layout but it is the callers responsibility to delete in explicitly. To delete the widget itself, we need to call widget() on QLayoutItem returned by itemAt(0). As it might be possible the widget at index 0 can be a nullptr, we add a check to see if its a valid widget and go on to delete the widget.\nvoid MainWindow::on_pushButton_2_clicked() { // get the item in the layout at index 0 QLayoutItem* item = ui-\u0026gt;gridLayout-\u0026gt;itemAt(0); ui-\u0026gt;gridLayout-\u0026gt;removeItem(item); // get the widget QWidget* widget = item-\u0026gt;widget(); // check if a valid widget if(widget) { delete widget; } } Conclusion # Adding and removing widgets from grid layout can be helpful specially when one wants to control the visibility of certain widgets inside the layout or moving widgets between layouts dynamically.\nThe whole project can be found on my GitHub page. If this was helpful, please share this blog and also feel free to add your thoughts or comments below.\nPhoto by Lance Anderson on Unsplash\n","date":"9 January 2021","externalUrl":null,"permalink":"/blog/gridlayouttest/","section":"The CodeFlamingo Blog","summary":"Imagine we want to add multiple widgets in QGridLayout dynamically but also remove widgets on the fly.\n","title":"Add or remove widgets in QGridLayout","type":"blog"},{"content":"Solution to cannot load library error.\nIntroduction # In QPluginLoader tutorial we learnt how to load plugins using Qt. This only works when the plugin has no dependencies to other third party plugins like OpenCV, Boost and proprietary plugins. Although, loading plugins which has other third party dependencies is not straight forward.\nThe Problem # I personally encountered a problem where i built a custom plugin like we did in part I tutorial but with additional dependencies to OpenCV, Boost and some other proprietary libraries. Problem?\nPlugins (.so/.dll) and its dependencies were located in their respective folders\nthe path to the plugins looks something like this: /path/to/exe-folder/plugins/plugins[.so/.dll] The plugin won\u0026rsquo;t load error - \u0026ldquo;QPluginloader error: “Cannot load library: The specified module could not be found”\nNotice, none of the plugins or its dependencies are located inside the exe directory. Important!\nAt first, i thought this is some kind of error in the path we are passing to QPluginLoader constructor. No! It goes deeper.\nTurns out, windows has a predefined Dynamic-Link Library Search Order. When loading a plugin using QPluginLoader load() as described in part II, by default, windows searches for plugin dependencies in the exe directory but cannot find the necessary dlls to load the plugin, hence the error.\nSolution # Simplest workaround for this would be to put plugin and all its dependencies in the exe folder of the application where windows can find the necessary dlls to load.\nThis is not the case when we have lots of plugins and its dependencies. We do not want all the dlls inside exe directory.\nOther workaround would be to actually handle it through the code itself. We need to somehow inform windows to search inside our plugins directory for dependencies.\nWith reference to our part II tutorial, our new code looks like this:\n#include \u0026lt;QDebug\u0026gt; #include \u0026lt;QtGlobal\u0026gt; #include \u0026#34;pluginloader.h\u0026#34; #define Q_OS_WIN #include \u0026lt;windows.h\u0026gt; #include \u0026lt;winbase.h\u0026gt; #endif PluginLoader::PluginLoader(QObject* parent) : QObject(parent), m_pluginLoader(nullptr) { } Device* PluginLoader::load(const QString\u0026amp; path) { m_pluginLoader = new QPluginLoader(path, this); qInfo() \u0026lt;\u0026lt; \u0026#34;Loading plugin...\u0026#34;; #define Q_OS_WIN // set the directory to \u0026#34;plugins\u0026#34; folder // windows will search for dlls in this folder SetDllDirectoryA((LPCSTR) \u0026#34;/path/to/exe-folder/plugins\u0026#34;); #endif if(m_pluginLoader-\u0026gt;load()) { qInfo() \u0026lt;\u0026lt; \u0026#34;Plugin loaded successfully...\u0026#34;; Device* device = dynamic_cast\u0026lt;Device*\u0026gt;(m_pluginLoader-\u0026gt;instance()); return device; } qWarning() \u0026lt;\u0026lt; \u0026#34;Plugin \u0026#34; \u0026lt;\u0026lt; path \u0026lt;\u0026lt; \u0026#34;failed to load...\u0026#34; \u0026lt;\u0026lt; m_pluginLoader-\u0026gt;errorString(); return nullptr; } SetDllDirectoryA() adds plugin directory path to windows search order.\nConclusion # This sample project can be found on my GitHub page.\nFeel free to share this blog, if you feel it helped you. If you have any comments or suggestions, post it in the comments section below.\nPhoto by Michael Geiger on Unsplash\n","date":"25 December 2020","externalUrl":null,"permalink":"/blog/qtplugin-dependencies/","section":"The CodeFlamingo Blog","summary":"Solution to cannot load library error.\n","title":"Loading custom qtplugin with dependencies on windows","type":"blog"},{"content":"Let\u0026rsquo;s learn to use QPluginLoader class to load custom plugins.\nIntroduction # In our part I of this tutorial we learnt how to create a qt plugin using Qt low level API to extend our application. In this tutorial, we will learn how to load/use the plugin we created using QPluginLoader class.\nQt docs also states that \u0026ldquo;QPluginLoader cannot be used if your application is statically linked against Qt. In this case, you will also have to link to plugins statically. You can use QLibrary if you need to load dynamic libraries in a statically linked application.\u0026rdquo;\nMotivation # As we have used Qt\u0026rsquo;s low level API to create our plugin, we have an option to use QPluginLoader class to load/use the plugin we created. Benefits? QPluginLoader provides convenient functions to access Qt plugin. Also, eliminates the use of platform specific loading e.g. to load a .dll file in windows we need to use \u0026quot;LoadLibraryA()\u0026quot; and in case of Linux we use \u0026quot;dlopen()\u0026quot; and so on. Although, we can use another Qt convenient class QLibrary but that would be a completely another tutorial.\nTutorial # In this short tutorial, we will learn how to load/use a Qt plugin using QPluginLoader class.\n// plugin_loader #include \u0026lt;QObject\u0026gt; #include \u0026lt;QPluginLoader\u0026gt; #include \u0026#34;interfaces/Device.h\u0026#34; class PluginLoader : public QObject { Q_OBJECT public: explicit PluginLoader(QObject* parent = nullptr); Device* load(const QString\u0026amp; path); private: QPluginLoader* m_pluginLoader; }; We create a PluginLoader class as a wrapper to load our plugins. Our implementation looks like this:\n#include \u0026lt;QDebug\u0026gt; #include \u0026#34;pluginloader.h\u0026#34; PluginLoader::PluginLoader(QObject* parent) : QObject(parent), m_pluginLoader(nullptr) { } Device* PluginLoader::load(const QString\u0026amp; path) { m_pluginLoader = new QPluginLoader(path, this); qInfo() \u0026lt;\u0026lt; \u0026#34;Loading plugin...\u0026#34;; if(m_pluginLoader-\u0026gt;load()) { qInfo() \u0026lt;\u0026lt; \u0026#34;Plugin loaded successfully...\u0026#34;; Device* device = dynamic_cast\u0026lt;Device*\u0026gt;(m_pluginLoader-\u0026gt;instance()); return device; } qWarning() \u0026lt;\u0026lt; \u0026#34;Plugin \u0026#34; \u0026lt;\u0026lt; path \u0026lt;\u0026lt; \u0026#34;failed to load...\u0026#34; \u0026lt;\u0026lt; m_pluginLoader-\u0026gt;errorString(); return nullptr; } Our load(const QString\u0026amp; path) function takes in an argument as a path to a plugin (.so/.dll). To be loadable, the file\u0026rsquo;s suffix must be a valid suffix for a loadable library in accordance with the platform, e.g. .so on Unix, - .dylib on macOS and iOS, and .dll on Windows.\nQt docs also states that \u0026ldquo;We recommend omitting the file\u0026rsquo;s suffix in the file name, since QPluginLoader will automatically look for the file with the appropriate suffix.\u0026rdquo;\nBefore loading, we check to see if m_pluginLoader is already loaded. If not, we try to load the plugin using load() and the get the instance of the plugin. In our case:\nDevice* device = dynamic_cast\u0026lt;Device*\u0026gt;(m_pluginLoader-\u0026gt;instance()); would evaluate to look something like this (check part I for PluginA):\nDevice* device = new PluginA(); On successful return of an instance, we can call the functions available in the plugin on the fly.\nNote: If the plugin has additional dependencies on other third party libraries, errorString() might throw an error as “Cannot load library: The specified module could not be found” unless the plugin is in the same folder as in .exe.\nConclusion # This sample project can be found on my GitHub page.\nFeel free to share this blog, if you feel it helped you. If you have any comments or suggestions, post it in the comments section below.\nPhoto by Markus Spiske on Unsplash\n","date":"21 December 2020","externalUrl":null,"permalink":"/blog/qpluginloader/","section":"The CodeFlamingo Blog","summary":"Let’s learn to use QPluginLoader class to load custom plugins.\n","title":"Custom qtplugin part II","type":"blog"},{"content":"Let\u0026rsquo;s learn how to create a custom qt plugin.\nIntroduction # Plugins are software components that adds a specific feature to an existing Qt application. This enables customization without actually disturbing the core structure of the application. In otherwords, these can be called as add-in, add-ons etc.\nAn existing Qt application functionality can be greatly extended without having to build the functionality into the application but load the plugin at run time whenever needed. Qt provides a powerful low level API to extend current Qt applications using plugins.\nThis would be a 2 part tutorial about how to create plugins using QtPlugin and how do we load/use QPluginLoader to load the plugins.\nMotivation # Lets have a look at an instance, where, we have different cameras which depend on various libraries like OpenCV, Boost or any proprietary libraries. We do not want to build/compile our main application with so many dependencies. Building a camera device along with its dependencies as a plugin would enable us to keep our main application free of all unnecessary dependencies.\nTutorial # In this short tutorial, we will learn how to create a Qt plugin interface and implement the interface to create a plugin.\n// plugin_interface #include \u0026lt;QString\u0026gt; #include \u0026lt;QStringList\u0026gt; #include \u0026lt;QtPlugin\u0026gt; class Device { public: virtual ~Device() = default; virtual void start() = 0; virtual void stop() = 0; }; // declare an interface to use #define iInterface_IID \u0026#34;com.company.Device/1.0\u0026#34; Q_DECLARE_INTERFACE(Device, iInterface_IID) Notice the declaration at the bottom. Q_DECLARE _INTERFACE needs to be declared using the unique iInterface_IID and also QtPlugin include. This allows Qt to assign this as an interface class with an unique ID.\nNow, we have an interface that needs to be implemented to create necessary plugins. This is how we implement plugins using the above interface:\n// pluginA class implemented using Device class #include \u0026lt;QObject\u0026gt; #include \u0026#34;Device.h\u0026#34; class PluginA : public QObject, public Device { Q_OBJECT // QtPlugin macros needs to be defined Q_PLUGIN_METADATA(IID \u0026#34;com.company.PluginA\u0026#34;) Q_INTERFACES(Device) public: explicit PluginA(QObject* parent = nullptr); // Device interface virtual void start() override; virtual void stop() override; }; In order to be considered as QtPlugin, we need to define macros Q_PLUGIN _METADATA and Q_INTERFACES. Q_PLUGIN _METADATA macro also takes in an optional parameter as json file with plugin metadata which looks something like this:\n{ \u0026#34;id\u0026#34; : \u0026#34;com.company.PluginA\u0026#34;, \u0026#34;name\u0026#34; : \u0026#34;pluginA\u0026#34;, \u0026#34;apiversion\u0026#34; : \u0026#34;1.0\u0026#34;, \u0026#34;version\u0026#34; : \u0026#34;1.0.0\u0026#34;, \u0026#34;author\u0026#34; : \u0026#34;user\u0026#34; } As per Qt docs \u0026ldquo;The json file must reside in one of the include directories specified by the build-system. moc exits with an error when it could not find the specified file\u0026rdquo;. To keep it simple for this tutorial we are not using metadata.\nBuilding this plugin app will create pluginA.[dll/.so] file which we can later use in our main Qt application. In the second part of this tutorial we will see how to load/use this plugin using QPluginLoader class.\nConclusion # This sample project can be found on my GitHub page.\nFeel free to share this blog, if you feel it helped you. If you have any comments or suggestions, post it in the comments section below.\nPhoto by Thomas Jensen on Unsplash\n","date":"19 December 2020","externalUrl":null,"permalink":"/blog/qtplugin/","section":"The CodeFlamingo Blog","summary":"Let’s learn how to create a custom qt plugin.\n","title":"Custom qtplugin part I","type":"blog"},{"content":" Introduction # QDockWidget provides the concept of dock widgets, also know as tool palettes or utility windows. Dock windows are secondary windows placed in the dock widget area around the central widget in a QMainWindow.\nQDockWidget acts as secondary utility windows which can be dragged, moved and docked using mouse gestures.\nHow to use # QDockWidget must always be used on a QMainWindow. MainWindow allows areas around the central widget to place secondary windows like QDockWidget.\nUser can choose to set the dock widget as desired in allowed areas: LeftDockWidgetArea, RightDockWidgetArea, TopDockWidgetArea, BottomDockWidgetArea, AllDockWidgetAreas or NoDockWidgetArea.\nTutorial # In this example, we will see how to set a widget inside a dock widget and move the dock widget to all allowed areas using mouse.\n#include \u0026#34;mainwindow.h\u0026#34; #include \u0026#34;ui_mainwindow.h\u0026#34; #include \u0026lt;QLabel\u0026gt; MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui-\u0026gt;setupUi(this); ui-\u0026gt;dockWidget-\u0026gt;setStyleSheet(\u0026#34;QDockWidget::title {background : lightgreen;}\u0026#34;); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { QLabel* label = new QLabel(ui-\u0026gt;dockWidget); label-\u0026gt;setPixmap(QPixmap(\u0026#34;:/img/dockImg.jpeg\u0026#34;)); ui-\u0026gt;dockWidget-\u0026gt;setWidget(label); } In the above code, we set a stylesheet to our dock widget to make it more visible against a white background. Additionally, we have a QPushButton on the QMainWindow.\nOn start, our mainwindow looks something like this:\nQDockWidget comes with a horizontal titlebar by default. Notice the green bar with an undock and a close button. The Show button is connect to the slot on_pushButton_clicked() which generates a QLabel. QLabel is set inside dock widget using setWidget(QWidget* widget). QLabel also contains a reference image which looks like this:\nDouble clicking on the title bar undocks the QDockWidget and can be freely dragged using mouse to a new position around QMainWindow. Here we can see how the QDockWidget is positioned at different allowed positions.\nConclusion # In this tutorial, we focused only on floating and changing positions of the QDockWidgets. There are a lot of convenient features the QDockWidget class offers. We might cover other aspects of QDockWidgets as well in future posts. If you have any thoughts or comments please use the comments section below to let us know.\nThis sample project can be found on my GitHub repo.\nPhoto by Tj Holowaychuk on Unsplash\n","date":"6 November 2020","externalUrl":null,"permalink":"/blog/dockwidget/","section":"The CodeFlamingo Blog","summary":"","title":"QDockWidget tutorial","type":"blog"},{"content":"Messagebox tutorial.\nIntroduction # In this tutorial, we will learn different ways we can use QMessageBox class.\nQMessageBox is a modal dialog i.e. user input is required in order to continue working with the application. To put it simply, It informs the user with a message and expects an answer. Modal windows block user inputs to background windows until the message box has an answer.\nThe message itself, can be a warning, question, information or a question. QMessageBox provides us with 2 different types of APIs, property-based API and static functions API. Both the APIs can be used based on the actual need of the situation.\nMotivation # Static functions API is built-in easy to use approach. Whereas, property-based API provides much more flexible and customizable option. In this tutorial, we will try both the options.\nTutorial # In this example, we\u0026rsquo;ll use QMessageBox in 2 different ways as discussed above.\n#include \u0026#34;dialog.h\u0026#34; #include \u0026#34;ui_dialog.h\u0026#34; #include \u0026lt;QMessageBox\u0026gt; Dialog::Dialog(QWidget* parent) : QDialog(parent) , ui(new Ui::Dialog) { ui-\u0026gt;setupUi(this); } Dialog::~Dialog() { delete ui; } void Dialog::on_pushButton_clicked() { // using static api // not much flexibility QMessageBox::information(this, \u0026#34;Information Box\u0026#34;, \u0026#34;This is an informative message\u0026#34;); QMessageBox::critical(this, \u0026#34;Critical Box\u0026#34;, \u0026#34;This is a critical message\u0026#34;); QMessageBox::question(this, \u0026#34;Question Box\u0026#34;, \u0026#34;This is a question\u0026#34;); QMessageBox::warning(this, \u0026#34;Warning Box\u0026#34;, \u0026#34;This is a warning message\u0026#34;); // using message box instances // very flexible and highly customizable QMessageBox msgBox; msgBox.setText(\u0026#34;Custom message\u0026#34;); msgBox.exec(); QMessageBox msgBox2; msgBox2.setText(\u0026#34;Highly customised message box\u0026#34;); msgBox2.setInformativeText(\u0026#34;Including standard buttons\u0026#34;); msgBox2.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); msgBox2.setDefaultButton(QMessageBox::Save); msgBox2.exec(); } Our Dialog.cpp contains a single button Generate as shown in the image\nClicking on Generate button, creates message boxes in an order.\nWe can always use convenient static functions API but it lacks a detailed informative text parameter. If the user needs to be alerted about the situation with a descriptive message, we must use property-based API, wherein we can not only convey a detailed informative message to the user but also ask the user what to do about this situation. User input must be subsequently handled there after.\nThis whole project can be found on my GitHub account.\nConclusion # Feel free to share this blog, if you feel it helped you. If you have any comments or suggestions, post it in the comments section below.\nPhoto by Andrew Measham on Unsplash\n","date":"29 October 2020","externalUrl":null,"permalink":"/blog/messagebox/","section":"The CodeFlamingo Blog","summary":"Messagebox tutorial.\n","title":"QMessageBox tutorial","type":"blog"},{"content":"Parallel programming using QtConcurrent.\nIntroduction # With computers getting more powerful, data computation is getting expensive. Many a times we need to perform heavy computations using multi threading to distribute this computing load. In C++ we use std::thread or std::async to achieve multi threading. In Qt5 we have QThread or QtConcurrent to achieve the same.\nAccording to QtConcurrent docs:\nThe QtConcurrent namespace provides high-level APIs that make it possible to write multi-threaded programs without using low-level threading primitives such as mutexes, read-write locks, wait conditions, or semaphores.\nIn simpler words, QtConcurrent provides functionality to spawn threads without explicit interaction from the user. In addition to this, we also have possibility to use signals and slots across the threads.\nIn this tutorial we will see how to run a function asynchronously using QtConcurrent and also use signals and slots to update GUI from the thread created by QtConcurrent.\nMotivation # While performing computationally expensive tasks, GUI becomes unresponsive or laggy because of the reason that the GUI/Main thread is blocked by a heavy task but at the same time cannot keep the GUI responsive.\nWe need multi threading to keep our GUI responsive while performing computationally expensive tasks.\nTutorial # Here we make a small application with Start and Stop buttons. Start button spawns a new thread and Stop button kills the thread.\nIn the layout we have a QLCDNumber and QProgressBar as a reference to see how the GUI is updated.\nLets have look at our Dialog.cpp:\n#include \u0026lt;QtConcurrent/QtConcurrent\u0026gt; #include \u0026lt;QFuture\u0026gt; #include \u0026#34;dialog.h\u0026#34; #include \u0026#34;ui_dialog.h\u0026#34; Dialog::Dialog(QWidget* parent) : QDialog(parent) , ui(new Ui::Dialog) { ui-\u0026gt;setupUi(this); m_worker = new Worker(this); // connections connect(m_worker, \u0026amp;Worker::updateGUI, this, \u0026amp;Dialog::onUpdateGUI); connect(this, \u0026amp;Dialog::stop, m_worker, \u0026amp;Worker::stop); connect(ui-\u0026gt;pushButton, \u0026amp;QPushButton::clicked, this, \u0026amp;Dialog::onStartClicked); connect(ui-\u0026gt;pushButton_2, \u0026amp;QPushButton::clicked, this, \u0026amp;Dialog::onStopClicked); } Dialog::~Dialog() { // stop the thread before closing the application // otherwise, the window will be destroyed but // the thread will continue running emit stop(); delete ui; } void Dialog::onStartClicked() { // prints current thread id // here it is the main thread qDebug() \u0026lt;\u0026lt; \u0026#34;Main thread: \u0026#34; \u0026lt;\u0026lt; this-\u0026gt;thread()-\u0026gt;currentThreadId(); // create an concurrent thread QFuture\u0026lt;void\u0026gt; future = QtConcurrent::run(m_worker, \u0026amp;Worker::asyncFunction); ui-\u0026gt;pushButton-\u0026gt;setEnabled(false); } void Dialog::onStopClicked() { emit stop(); ui-\u0026gt;pushButton-\u0026gt;setEnabled(true); } void Dialog::onUpdateGUI(int value) { // update lcd number and progress bar ui-\u0026gt;lcdNumber-\u0026gt;display(value); ui-\u0026gt;progressBar-\u0026gt;setValue(value); } We declare 3 slots OnStartClicked(), OnStopClicked(), OnUpdateGUI() and 1 signal stop().\nWe have a Worker class which has a function asyncFunction() and this function in our tutorial will run on a different thread.\nImplementation looks like this:\n#include \u0026lt;QThread\u0026gt; #include \u0026#34;worker.h\u0026#34; Worker::Worker(QObject* parent) : QObject(parent) , m_stop(false) { } void Worker::stop() { m_stop = true; } void Worker::asyncFunction() { // prints worker thread id qDebug() \u0026lt;\u0026lt; \u0026#34;Worker thread: \u0026#34; \u0026lt;\u0026lt; this-\u0026gt;thread()-\u0026gt;currentThreadId(); m_stop = false; for(int i = 0; i \u0026lt;= 100; i++) { // if stop requested // break this loop if(m_stop) { return; } // signal dialog class to update GUI emit updateGUI(i); // thread sleep for 50 ms // otherwise this is too fast this-\u0026gt;thread()-\u0026gt;msleep(50); } } Explanation # To make this work, we need proper connections like the ones we have defined in Dialog.cpp.\nconnect(m_worker, \u0026amp;Worker::updateGUI, this, \u0026amp;Dialog::onUpdateGUI); connect(this, \u0026amp;Dialog::stop, m_worker, \u0026amp;Worker::stop); First connection ensures that every time the worker class emits a signal updateGUI, the slot on onUpdateGUI is called in Dialog class.\nBy default, a connect statement in Qt looks something like this:\nQObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type = Qt::AutoConnection) The last parameter Qt::AutoConnection is the key here. Qt automatically decides to use Qt::QueuedConnection while connecting signals and slots across the threads. We can also specify explicitly to use Qt::QueuedConnection inside our connect statements.\nOur second connect statement is for stopping the thread. Notice we should always use signals and slots when working with multi threading since Qt handles most of the complications associated with it automatically.\nPoint of interest here is QtConcurrent::run(). It spawns a thread every time Start button is clicked and our function asyncFunction() runs asynchronously on a different thread.\nTo test it, we print the thread id:\nMain thread: 0x4d48 Worker thread: 0x39cc Conclusion # Running complex and heavy tasks on different threads not only distributes the load and makes the program run faster but also keeps GUI/Main thread free, which helps in keeping our UI responsive.\nHere is our demo project output in action:\nThe whole project can be found on my GitHub account. If this was helpful, please share this blog and also feel free to add your thoughts or comments below.\nPhoto by drmakete lab on Unsplash\n","date":"11 September 2020","externalUrl":null,"permalink":"/blog/concurrentrun/","section":"The CodeFlamingo Blog","summary":"Parallel programming using QtConcurrent.\n","title":"Run a function in separate thread using QtConcurrent","type":"blog"},{"content":"Senior Software Engineer specializing in the intersection of AI, Embedded Systems, and scalable architecture.\nCrafting robust digital ecosystems where precision logic meets elegant, high-performance execution.\nThe Mission # Building at the edge of what\u0026rsquo;s possible on a ThinkPad\u0026hellip;\n","externalUrl":null,"permalink":"/about/","section":"About Me","summary":"","title":"About Me","type":"about"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"}]