diff options
147 files changed, 1810 insertions, 2212 deletions
diff --git a/.cmake.conf b/.cmake.conf index 05b80d3..62cb061 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -1,4 +1,4 @@ -set(QT_REPO_MODULE_VERSION "6.5.0") +set(QT_REPO_MODULE_VERSION "6.8.0") set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1") -# Use cpp-based syncqt -set(QT_USE_SYNCQT_CPP TRUE) +set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1") +list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_FOREACH=1") @@ -36,6 +36,7 @@ ui_*.h tools/testcon/testcon.tlb qrc_*.cpp *_wrapper.bat +CMakeUserPresets.json # Test generated files QObject.log diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a647f6..bfddcf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,12 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qtactiveqt.pro. - cmake_minimum_required(VERSION 3.16) include(".cmake.conf") -project(QtActiveQt # special case +project(QtActiveQt VERSION "${QT_REPO_MODULE_VERSION}" - DESCRIPTION "Qt Active Qt Libraries" # special case + DESCRIPTION "Qt Active Qt Libraries" HOMEPAGE_URL "https://qt.io/" LANGUAGES CXX C ) @@ -18,6 +16,8 @@ if (NOT WIN32) # special case begin set(QT_NO_INTERNAL_COMPATIBILITY_FUNCTIONS TRUE) find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals) + qt_internal_project_setup() + qt_build_repo_begin() add_subdirectory(src/activeqt/doc) qt_build_repo_end() @@ -25,12 +25,12 @@ if (NOT WIN32) return() endif() -find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core) # special case -# special case begin +find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core) find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS Qml Quick Gui Widgets PrintSupport OpenGL OpenGLWidgets ) -# special case end +qt_internal_project_setup() + if(NOT TARGET Qt::Gui OR NOT TARGET Qt::Widgets OR NOT TARGET Qt::PrintSupport) message(NOTICE "Skipping the build as the condition \"TARGET Qt::Gui\", \"TARGET Qt::Widget\" " "or \"TARGET Qt::Printsupport\" is not met.") diff --git a/conanfile.py b/conanfile.py deleted file mode 100644 index 6f2dc89..0000000 --- a/conanfile.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (C) 2021 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -from conans import ConanFile -import re -from pathlib import Path - - -def _parse_qt_version_by_key(key: str) -> str: - with open(Path(__file__).parent.resolve() / ".cmake.conf") as f: - m = re.search(fr'{key} .*"(.*)"', f.read()) - return m.group(1) if m else "" - - -def _get_qt_minor_version() -> str: - return ".".join(_parse_qt_version_by_key("QT_REPO_MODULE_VERSION").split(".")[:2]) - - -class QtActiveQtFormats(ConanFile): - name = "qtactiveqt" - license = "LGPL-3.0, GPL-2.0+, Commercial Qt License Agreement" - author = "The Qt Company <https://www.qt.io/contact-us>" - url = "https://code.qt.io/cgit/qt/qtactiveqt.git" - description = "Active Qt adds support for ActiveX and COM functionality for Qt on Windows." - topics = "qt", "qt6", "addon", "ActiveX", "COM", "Windows" - settings = "os", "compiler", "arch", "build_type" - # for referencing the version number and prerelease tag and dependencies info - exports = ".cmake.conf", "dependencies.yaml" - exports_sources = "*", "!conan*.*" - python_requires = f"qt-conan-common/{_get_qt_minor_version()}@qt/everywhere" - python_requires_extend = "qt-conan-common.QtLeafModule" diff --git a/dependencies.yaml b/dependencies.yaml index fd103fd..2168de9 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,4 +1,4 @@ dependencies: ../qtbase: - ref: f562711c642cba7bed6c96d452437ffc9b25edc4 + ref: 4641945e45206508b44678011bb83da7722bad62 required: true diff --git a/examples/activeqt/CMakeLists.txt b/examples/activeqt/CMakeLists.txt index de0a97b..c95e04e 100644 --- a/examples/activeqt/CMakeLists.txt +++ b/examples/activeqt/CMakeLists.txt @@ -3,18 +3,6 @@ if(MSVC) qt_internal_add_example(comapp) - qt_internal_add_example(hierarchy) - qt_internal_add_example(menus) - qt_internal_add_example(multiple) qt_internal_add_example(simple) qt_internal_add_example(wrapper) - if(TARGET Qt6::OpenGLWidgets AND QT_FEATURE_opengl AND NOT QT_FEATURE_opengles2) - qt_internal_add_example(opengl) - endif() - if(TARGET Qt::QuickControls2) - qt_internal_add_example(simpleqml) - endif() -endif() -if(MINGW OR QT_BUILD_SHARED_LIBS) - qt_internal_add_example(mediaplayer) endif() diff --git a/examples/activeqt/activeqt.pro b/examples/activeqt/activeqt.pro index 6f189bc..3628f1c 100644 --- a/examples/activeqt/activeqt.pro +++ b/examples/activeqt/activeqt.pro @@ -1,14 +1,4 @@ TEMPLATE = subdirs SUBDIRS += comapp \ - hierarchy \ - menus \ - multiple \ simple \ wrapper - -contains(QT_CONFIG, shared):SUBDIRS += mediaplayer -contains(QT_CONFIG, opengl):!contains(QT_CONFIG, opengles2): SUBDIRS += opengl -qtHaveModule(quickcontrols2):SUBDIRS += simpleqml - -# Other examples need an IDL compiler -mingw:SUBDIRS = mediaplayer diff --git a/examples/activeqt/comapp/doc/src/comapp.qdoc b/examples/activeqt/comapp/doc/src/comapp.qdoc index 0a1e90f..92d65d0 100644 --- a/examples/activeqt/comapp/doc/src/comapp.qdoc +++ b/examples/activeqt/comapp/doc/src/comapp.qdoc @@ -4,6 +4,8 @@ /*! \example activeqt/comapp \title COM App Example (ActiveQt) + \examplecategory {Desktop} + \ingroup activeqt-examples \brief The COM App example shows how to use ActiveQt to develop a Qt application that can be automated via COM. Different QObject diff --git a/examples/activeqt/dotnet/walkthrough/Form1.cs b/examples/activeqt/dotnet/walkthrough/Form1.cs deleted file mode 100644 index 9fb572a..0000000 --- a/examples/activeqt/dotnet/walkthrough/Form1.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Drawing; -using System.Collections; -using System.ComponentModel; -using System.Windows.Forms; -using System.Data; - -namespace csharp -{ - /// <summary> - /// Summary description for Form1. - /// </summary> - public class Form1 : System.Windows.Forms.Form - { - private AxwrapperaxLib.AxQPushButton resetButton; - private AxmultipleaxLib.AxQAxWidget2 circleWidget; - /// <summary> - /// Required designer variable. - /// </summary> - private System.ComponentModel.Container components = null; - - public Form1() - { - // - // Required for Windows Form Designer support - // - InitializeComponent(); - - // - // TODO: Add any constructor code after InitializeComponent call - // - } - - /// <summary> - /// Clean up any resources being used. - /// </summary> - protected override void Dispose( bool disposing ) - { - if( disposing ) - { - if (components != null) - { - components.Dispose(); - } - } - base.Dispose( disposing ); - } - - #region Windows Form Designer generated code - /// <summary> - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// </summary> - private void InitializeComponent() - { - System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1)); - this.resetButton = new AxwrapperaxLib.AxQPushButton(); - this.circleWidget = new AxmultipleaxLib.AxQAxWidget2(); - ((System.ComponentModel.ISupportInitialize)(this.resetButton)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.circleWidget)).BeginInit(); - this.SuspendLayout(); - // - // resetButton - // - this.resetButton.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right); - this.resetButton.Enabled = true; - this.resetButton.Location = new System.Drawing.Point(160, 296); - this.resetButton.Name = "resetButton"; - this.resetButton.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("resetButton.OcxState"))); - this.resetButton.Size = new System.Drawing.Size(168, 32); - this.resetButton.TabIndex = 1; - this.resetButton.clicked += new System.EventHandler(this.resetLineWidth); - // - // circleWidget - // - this.circleWidget.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right); - this.circleWidget.Enabled = true; - this.circleWidget.Location = new System.Drawing.Point(8, 8); - this.circleWidget.Name = "circleWidget"; - this.circleWidget.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("circleWidget.OcxState"))); - this.circleWidget.Size = new System.Drawing.Size(320, 264); - this.circleWidget.TabIndex = 2; - this.circleWidget.ClickEvent += new System.EventHandler(this.circleClicked); - // - // Form1 - // - this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); - this.ClientSize = new System.Drawing.Size(336, 333); - this.Controls.AddRange(new System.Windows.Forms.Control[] { - this.circleWidget, - this.resetButton}); - this.Name = "Form1"; - this.Text = "Form1"; - ((System.ComponentModel.ISupportInitialize)(this.resetButton)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.circleWidget)).EndInit(); - this.ResumeLayout(false); - - } - #endregion - - /// <summary> - /// The main entry point for the application. - /// </summary> - [STAThread] - static void Main() - { - Application.Run(new Form1()); - } - -//! [0] - private void circleClicked(object sender, System.EventArgs e) - { - this.circleWidget.lineWidth++; - } -//! [0] - -//! [1] - private void resetLineWidth(object sender, System.EventArgs e) - { - this.circleWidget.lineWidth = 1; - this.resetButton.setFocus(); - } -//! [1] - } -} diff --git a/examples/activeqt/dotnet/walkthrough/Form1.resx b/examples/activeqt/dotnet/walkthrough/Form1.resx deleted file mode 100644 index 6353f82..0000000 --- a/examples/activeqt/dotnet/walkthrough/Form1.resx +++ /dev/null @@ -1,131 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<root> - <!-- - Microsoft ResX Schema - - Version 1.3 - - The primary goals of this format is to allow a simple XML format - that is mostly human readable. The generation and parsing of the - various data types are done through the TypeConverter classes - associated with the data types. - - Example: - - ... ado.net/XML headers & schema ... - <resheader name="resmimetype">text/microsoft-resx</resheader> - <resheader name="version">1.3</resheader> - <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> - <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> - <data name="Name1">this is my long string</data> - <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> - <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> - [base64 mime encoded serialized .NET Framework object] - </data> - <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> - [base64 mime encoded string representing a byte array form of the .NET Framework object] - </data> - - There are any number of "resheader" rows that contain simple - name/value pairs. - - Each data row contains a name, and value. The row also contains a - type or mimetype. Type corresponds to a .NET class that support - text/value conversion through the TypeConverter architecture. - Classes that don't support this are serialized and stored with the - mimetype set. - - The mimetype is used for serialized objects, and tells the - ResXResourceReader how to depersist the object. This is currently not - extensible. For a given mimetype the value must be set accordingly: - - Note - application/x-microsoft.net.object.binary.base64 is the format - that the ResXResourceWriter will generate, however the reader can - read any of the formats listed below. - - mimetype: application/x-microsoft.net.object.binary.base64 - value : The object must be serialized with - : System.Serialization.Formatters.Binary.BinaryFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.soap.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Soap.SoapFormatter - : and then encoded with base64 encoding. - mimetype: application/x-microsoft.net.object.bytearray.base64 - value : The object must be serialized into a byte array - : using a System.ComponentModel.TypeConverter - : and then encoded with base64 encoding. - --> - <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> - <xsd:element name="root" msdata:IsDataSet="true"> - <xsd:complexType> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="data"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> - <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> - <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="resheader"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - </xsd:element> - </xsd:choice> - </xsd:complexType> - </xsd:element> - </xsd:schema> - <resheader name="resmimetype"> - <value>text/microsoft-resx</value> - </resheader> - <resheader name="version"> - <value>1.3</value> - </resheader> - <resheader name="reader"> - <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> - <resheader name="writer"> - <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> - <data name="resetButton.OcxState" mimetype="application/x-microsoft.net.object.binary.base64"> - <value> - AAEAAAD/////AQAAAAAAAAAMAgAAAFpTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0xLjAuMzMw - MC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACFT - eXN0ZW0uV2luZG93cy5Gb3Jtcy5BeEhvc3QrU3RhdGUBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAGwMA - AAIBAAAAAQAAAAAAAAAAAAAAAAYDAAAAAAAFAAAACGVuYWJsZWQAAAAAEgEAAAACeAAAAAAQAAAAAAAA - AAJ5AAAAABAAAAAAAAAABndpZHRoAAAAABAAAACoAAAAB2hlaWdodAAAAAAQAAAAGgAAAA1taW5pbXVt - V2lkdGgAAAAAEAAAAAAAAAAObWluaW11bUhlaWdodAAAAAAQAAAAAAAAAA1tYXhpbXVtV2lkdGgAAAAA - EAAAf/8AAAAObWF4aW11bUhlaWdodAAAAAAQAAB//wAAAA9iYWNrZ3JvdW5kTW9kZQAAAAAQAAAABAAA - ABdwYWxldHRlRm9yZWdyb3VuZENvbG9yAAAAAAr/AAAAAAAAF3BhbGV0dGVCYWNrZ3JvdW5kQ29sb3IA - AAAACv/U0MgAAAARYmFja2dyb3VuZE9yaWdpbgAAAAAQAAAAAAAAAAVmb250AAAAAAUAAAAYAE0AUwAg - AFMAaABlAGwAbAAgAEQAbABnAFP//wUBADIAAAAACGNhcHRpb24AAAAAA/////8AAAAJaWNvblRleHQA - AAAAA/////8AAAAObW91c2VUcmFja2luZwAAAAASAAAAAAxmb2N1c1BvbGljeQAAAAAQAAAAAQAAAA91 - cGRhdGVzRW5hYmxlZAAAAAASAQAAAAptYXhpbWl6ZWQAAAAAEgAAAAALZnVsbFNjcmVlbgAAAAASAAAA - AAxhY2NlcHREcm9wcwAAAAASAAAAABNpbnB1dE1ldGhvZEVuYWJsZWQAAAAAEgAAAAAFdGV4dAAAAAAD - AAAADAAmAFIAZQBzAGUAdAAAAAt0b2dnbGVUeXBlAAAAABAAAAAAAAAABWRvd24AAAAAEgAAAAAMdG9n - Z2xlU3RhdGUAAAAAEAAAAAAAAAALYXV0b1Jlc2l6ZQAAAAASAAAAAAthdXRvUmVwZWF0AAAAABIAAAAA - EGV4Y2x1c2l2ZVRvZ2dsZQAAAAASAAAAAAxhdXRvRGVmYXVsdAAAAAASAQAAAAttZW51QnV0dG9uAAAA - ABIAAAAABWZsYXQAAAAAEgAL -</value> - </data> - <data name="circleWidget.OcxState" mimetype="application/x-microsoft.net.object.binary.base64"> - <value> - AAEAAAD/////AQAAAAAAAAAMAgAAAFpTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0xLjAuMzMw - MC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACFT - eXN0ZW0uV2luZG93cy5Gb3Jtcy5BeEhvc3QrU3RhdGUBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAALwAA - AAIBAAAAAQAAAAAAAAAAAAAAABoAAAAAAAAFAAAACmxpbmVXaWR0aAAAAAAQAAAAAAs= -</value> - </data> - <data name="$this.Name"> - <value>Form1</value> - </data> -</root>
\ No newline at end of file diff --git a/examples/activeqt/dotnet/walkthrough/Form1.vb b/examples/activeqt/dotnet/walkthrough/Form1.vb deleted file mode 100644 index f5f241b..0000000 --- a/examples/activeqt/dotnet/walkthrough/Form1.vb +++ /dev/null @@ -1,88 +0,0 @@ -Public Class Form1 - Inherits System.Windows.Forms.Form - -#Region " Windows Form Designer generated code " - - Public Sub New() - MyBase.New() - - 'This call is required by the Windows Form Designer. - InitializeComponent() - - 'Add any initialization after the InitializeComponent() call - - End Sub - - 'Form overrides dispose to clean up the component list. - Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) - If disposing Then - If Not (components Is Nothing) Then - components.Dispose() - End If - End If - MyBase.Dispose(disposing) - End Sub - - 'Required by the Windows Form Designer - Private components As System.ComponentModel.IContainer - - 'NOTE: The following procedure is required by the Windows Form Designer - 'It can be modified using the Windows Form Designer. - 'Do not modify it using the code editor. - Friend WithEvents circleWidget As AxmultipleaxLib.AxQAxWidget2 - Friend WithEvents resetButton As AxwrapperaxLib.AxQPushButton - <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() - Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(Form1)) - Me.circleWidget = New AxmultipleaxLib.AxQAxWidget2() - Me.resetButton = New AxwrapperaxLib.AxQPushButton() - CType(Me.circleWidget, System.ComponentModel.ISupportInitialize).BeginInit() - CType(Me.resetButton, System.ComponentModel.ISupportInitialize).BeginInit() - Me.SuspendLayout() - ' - 'circleWidget - ' - Me.circleWidget.Anchor = (((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _ - Or System.Windows.Forms.AnchorStyles.Left) _ - Or System.Windows.Forms.AnchorStyles.Right) - Me.circleWidget.Enabled = True - Me.circleWidget.Location = New System.Drawing.Point(8, 8) - Me.circleWidget.Name = "circleWidget" - Me.circleWidget.OcxState = CType(resources.GetObject("circleWidget.OcxState"), System.Windows.Forms.AxHost.State) - Me.circleWidget.Size = New System.Drawing.Size(280, 216) - Me.circleWidget.TabIndex = 0 - ' - 'resetButton - ' - Me.resetButton.Anchor = (System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right) - ' VB is case insensitive, but our C++ controls are not. - ' Me.resetButton.enabled = True - Me.resetButton.Location = New System.Drawing.Point(184, 240) - Me.resetButton.Name = "resetButton" - Me.resetButton.OcxState = CType(resources.GetObject("resetButton.OcxState"), System.Windows.Forms.AxHost.State) - Me.resetButton.Size = New System.Drawing.Size(104, 24) - Me.resetButton.TabIndex = 1 - ' - 'Form1 - ' - Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) - Me.ClientSize = New System.Drawing.Size(292, 273) - Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.resetButton, Me.circleWidget}) - Me.Name = "Form1" - Me.Text = "Form1" - CType(Me.circleWidget, System.ComponentModel.ISupportInitialize).EndInit() - CType(Me.resetButton, System.ComponentModel.ISupportInitialize).EndInit() - Me.ResumeLayout(False) - - End Sub - -#End Region - - Private Sub circleWidget_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles circleWidget.ClickEvent - Me.circleWidget.lineWidth = Me.circleWidget.lineWidth + 1 - End Sub - - Private Sub resetButton_clicked(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles resetButton.clicked - Me.circleWidget.lineWidth = 1 - Me.resetButton.setFocus() - End Sub -End Class diff --git a/examples/activeqt/dotnet/walkthrough/csharp.csproj b/examples/activeqt/dotnet/walkthrough/csharp.csproj deleted file mode 100644 index 4c5502b..0000000 --- a/examples/activeqt/dotnet/walkthrough/csharp.csproj +++ /dev/null @@ -1,143 +0,0 @@ -<VisualStudioProject> - <CSHARP - ProjectType = "Local" - ProductVersion = "7.0.9466" - SchemaVersion = "1.0" - ProjectGuid = "{F15600FD-7677-4C01-B98A-6776CE500617}" - > - <Build> - <Settings - ApplicationIcon = "" - AssemblyKeyContainerName = "" - AssemblyName = "csharp" - AssemblyOriginatorKeyFile = "" - DefaultClientScript = "JScript" - DefaultHTMLPageLayout = "Grid" - DefaultTargetSchema = "IE50" - DelaySign = "false" - OutputType = "WinExe" - RootNamespace = "csharp" - StartupObject = "" - > - <Config - Name = "Debug" - AllowUnsafeBlocks = "false" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "DEBUG;TRACE" - DocumentationFile = "" - DebugSymbols = "true" - FileAlignment = "4096" - IncrementalBuild = "true" - Optimize = "false" - OutputPath = "bin\Debug\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - <Config - Name = "Release" - AllowUnsafeBlocks = "false" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "TRACE" - DocumentationFile = "" - DebugSymbols = "false" - FileAlignment = "4096" - IncrementalBuild = "false" - Optimize = "true" - OutputPath = "bin\Release\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - </Settings> - <References> - <Reference - Name = "System" - AssemblyName = "System" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll" - /> - <Reference - Name = "System.Data" - AssemblyName = "System.Data" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll" - /> - <Reference - Name = "System.Drawing" - AssemblyName = "System.Drawing" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll" - /> - <Reference - Name = "System.Windows.Forms" - AssemblyName = "System.Windows.Forms" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll" - /> - <Reference - Name = "System.XML" - AssemblyName = "System.Xml" - HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll" - /> - <Reference - Name = "stdole" - Guid = "{00020430-0000-0000-C000-000000000046}" - VersionMajor = "2" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "primary" - /> - <Reference - Name = "wrapperaxLib" - Guid = "{3B756301-0075-4E40-8BE8-5A81DE2426B7}" - VersionMajor = "1" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "tlbimp" - /> - <Reference - Name = "AxwrapperaxLib" - Guid = "{3B756301-0075-4E40-8BE8-5A81DE2426B7}" - VersionMajor = "1" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "aximp" - /> - <Reference - Name = "multipleaxLib" - Guid = "{05828915-AD1C-47AB-AB96-D6AD1E25F0E2}" - VersionMajor = "1" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "tlbimp" - /> - <Reference - Name = "AxmultipleaxLib" - Guid = "{05828915-AD1C-47AB-AB96-D6AD1E25F0E2}" - VersionMajor = "1" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "aximp" - /> - </References> - </Build> - <Files> - <Include> - <File - RelPath = "Form1.cs" - SubType = "Form" - BuildAction = "Compile" - /> - <File - RelPath = "Form1.resx" - DependentUpon = "Form1.cs" - BuildAction = "EmbeddedResource" - /> - </Include> - </Files> - </CSHARP> -</VisualStudioProject> - diff --git a/examples/activeqt/dotnet/walkthrough/vb.vbproj b/examples/activeqt/dotnet/walkthrough/vb.vbproj deleted file mode 100644 index eb0a9d6..0000000 --- a/examples/activeqt/dotnet/walkthrough/vb.vbproj +++ /dev/null @@ -1,147 +0,0 @@ -<VisualStudioProject> - <VisualBasic - ProjectType = "Local" - ProductVersion = "7.0.9466" - SchemaVersion = "1.0" - ProjectGuid = "{BFF242A6-967C-4F73-BEBE-DED2D9C395C6}" - > - <Build> - <Settings - ApplicationIcon = "" - AssemblyKeyContainerName = "" - AssemblyName = "vb" - AssemblyOriginatorKeyFile = "" - AssemblyOriginatorKeyMode = "None" - DefaultClientScript = "JScript" - DefaultHTMLPageLayout = "Grid" - DefaultTargetSchema = "IE50" - DelaySign = "false" - OutputType = "WinExe" - OptionCompare = "Binary" - OptionExplicit = "On" - OptionStrict = "Off" - RootNamespace = "vb" - StartupObject = "vb.Form1" - > - <Config - Name = "Debug" - BaseAddress = "285212672" - ConfigurationOverrideFile = "" - DefineConstants = "" - DefineDebug = "true" - DefineTrace = "true" - DebugSymbols = "true" - IncrementalBuild = "true" - Optimize = "false" - OutputPath = "bin\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "1" - /> - <Config - Name = "Release" - BaseAddress = "285212672" - ConfigurationOverrideFile = "" - DefineConstants = "" - DefineDebug = "false" - DefineTrace = "true" - DebugSymbols = "false" - IncrementalBuild = "false" - Optimize = "true" - OutputPath = "bin\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "1" - /> - </Settings> - <References> - <Reference - Name = "System" - AssemblyName = "System" - /> - <Reference - Name = "System.Data" - AssemblyName = "System.Data" - /> - <Reference - Name = "System.Drawing" - AssemblyName = "System.Drawing" - /> - <Reference - Name = "System.Windows.Forms" - AssemblyName = "System.Windows.Forms" - /> - <Reference - Name = "System.XML" - AssemblyName = "System.Xml" - /> - <Reference - Name = "stdole" - Guid = "{00020430-0000-0000-C000-000000000046}" - VersionMajor = "2" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "primary" - /> - <Reference - Name = "wrapperaxLib" - Guid = "{3B756301-0075-4E40-8BE8-5A81DE2426B7}" - VersionMajor = "1" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "tlbimp" - /> - <Reference - Name = "multipleaxLib" - Guid = "{05828915-AD1C-47AB-AB96-D6AD1E25F0E2}" - VersionMajor = "1" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "tlbimp" - /> - <Reference - Name = "AxwrapperaxLib" - Guid = "{3B756301-0075-4E40-8BE8-5A81DE2426B7}" - VersionMajor = "1" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "aximp" - /> - <Reference - Name = "AxmultipleaxLib" - Guid = "{05828915-AD1C-47AB-AB96-D6AD1E25F0E2}" - VersionMajor = "1" - VersionMinor = "0" - Lcid = "0" - WrapperTool = "aximp" - /> - </References> - <Imports> - <Import Namespace = "Microsoft.VisualBasic" /> - <Import Namespace = "System" /> - <Import Namespace = "System.Collections" /> - <Import Namespace = "System.Data" /> - <Import Namespace = "System.Drawing" /> - <Import Namespace = "System.Diagnostics" /> - <Import Namespace = "System.Windows.Forms" /> - </Imports> - </Build> - <Files> - <Include> - <File - RelPath = "Form1.vb" - SubType = "Form" - BuildAction = "Compile" - /> - <File - RelPath = "Form1.resx" - DependentUpon = "Form1.vb" - BuildAction = "EmbeddedResource" - /> - </Include> - </Files> - </VisualBasic> -</VisualStudioProject> - diff --git a/examples/activeqt/dotnet/wrapper/app.csproj b/examples/activeqt/dotnet/wrapper/app.csproj deleted file mode 100644 index dce4bf0..0000000 --- a/examples/activeqt/dotnet/wrapper/app.csproj +++ /dev/null @@ -1,93 +0,0 @@ -<VisualStudioProject> - <CSHARP - ProjectType = "Local" - ProductVersion = "7.0.9466" - SchemaVersion = "1.0" - ProjectGuid = "{334C8F04-E034-4082-9380-43906DDE71AB}" - > - <Build> - <Settings - ApplicationIcon = "" - AssemblyKeyContainerName = "" - AssemblyName = "wrapper" - AssemblyOriginatorKeyFile = "" - DefaultClientScript = "JScript" - DefaultHTMLPageLayout = "Grid" - DefaultTargetSchema = "IE50" - DelaySign = "false" - OutputType = "Exe" - RootNamespace = "wrapper" - StartupObject = "" - > - <Config - Name = "Debug" - AllowUnsafeBlocks = "false" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "DEBUG;TRACE" - DocumentationFile = "" - DebugSymbols = "true" - FileAlignment = "4096" - IncrementalBuild = "true" - Optimize = "false" - OutputPath = "bin\Debug\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - <Config - Name = "Release" - AllowUnsafeBlocks = "false" - BaseAddress = "285212672" - CheckForOverflowUnderflow = "false" - ConfigurationOverrideFile = "" - DefineConstants = "TRACE" - DocumentationFile = "" - DebugSymbols = "false" - FileAlignment = "4096" - IncrementalBuild = "false" - Optimize = "true" - OutputPath = "bin\Release\" - RegisterForComInterop = "false" - RemoveIntegerChecks = "false" - TreatWarningsAsErrors = "false" - WarningLevel = "4" - /> - </Settings> - <References> - <Reference - Name = "System" - AssemblyName = "System" - HintPath = "D:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll" - /> - <Reference - Name = "System.Data" - AssemblyName = "System.Data" - HintPath = "D:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll" - /> - <Reference - Name = "System.XML" - AssemblyName = "System.Xml" - HintPath = "D:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll" - /> - <Reference - Name = "lib" - AssemblyName = "lib" - HintPath = "lib\lib.dll" - /> - </References> - </Build> - <Files> - <Include> - <File - RelPath = "main.cs" - SubType = "Code" - BuildAction = "Compile" - /> - </Include> - </Files> - </CSHARP> -</VisualStudioProject> - diff --git a/examples/activeqt/dotnet/wrapper/lib/lib.vcproj b/examples/activeqt/dotnet/wrapper/lib/lib.vcproj deleted file mode 100644 index f49c35d..0000000 --- a/examples/activeqt/dotnet/wrapper/lib/lib.vcproj +++ /dev/null @@ -1,149 +0,0 @@ -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="7.00" - Name="lib" - ProjectGUID="{2E94A303-45A2-47AC-B87A-7C3519E9D6D8}" - Keyword="ManagedCProj"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="Debug" - ConfigurationType="2" - CharacterSet="2" - ManagedExtensions="TRUE"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories=""$(QTDIR)\include";"$(QTDIR)\include\QtCore"" - PreprocessorDefinitions="WIN32;_DEBUG" - IgnoreStandardIncludePath="FALSE" - MinimalRebuild="FALSE" - BasicRuntimeChecks="0" - RuntimeLibrary="1" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="QtCored4.lib" - OutputFile="lib.dll" - LinkIncremental="2" - AdditionalLibraryDirectories="$(QTDIR)/lib" - GenerateDebugInformation="TRUE"/> - <Tool - Name="VCMIDLTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="Release" - ConfigurationType="2" - CharacterSet="2" - ManagedExtensions="TRUE"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories=""$(QTDIR)\include";"$(QTDIR)\include\QtCore"" - InlineFunctionExpansion="1" - PreprocessorDefinitions="WIN32;NDEBUG" - MinimalRebuild="FALSE" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="QtCore4.lib" - OutputFile="$(OutDir)/lib.dll" - LinkIncremental="1" - AdditionalLibraryDirectories="$(QTDIR)/lib" - GenerateDebugInformation="TRUE"/> - <Tool - Name="VCMIDLTool"/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"> - <File - RelativePath="networker.cpp"> - </File> - <File - RelativePath="tools.cpp"> - </File> - <File - RelativePath="worker.cpp"> - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc"> - <File - RelativePath="networker.h"> - </File> - <File - RelativePath="tools.h"> - </File> - <File - RelativePath="worker.h"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCustomBuildTool" - CommandLine="$(QTDIR)\bin\moc.exe $(InputName).h -o moc_$(InputName).cpp" - Outputs="moc_$(InputName).cpp"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCustomBuildTool" - CommandLine="$(QTDIR)\bin\moc.exe $(InputName).h -o moc_$(InputName).cpp" - Outputs="moc_$(InputName).cpp"/> - </FileConfiguration> - </File> - </Filter> - <Filter - Name="Generated MOC" - Filter=""> - <File - RelativePath="moc_worker.cpp"> - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/examples/activeqt/dotnet/wrapper/lib/networker.cpp b/examples/activeqt/dotnet/wrapper/lib/networker.cpp deleted file mode 100644 index ccbdf89..0000000 --- a/examples/activeqt/dotnet/wrapper/lib/networker.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2015 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -//! [0] -#include "networker.h" -#include "worker.h" -#include "tools.h" - -netWorker::netWorker() -{ - workerObject = new Worker(); -} -//! [0] //! [1] - -netWorker::~netWorker() -{ - delete workerObject; -} -//! [1] //! [2] - -String *netWorker::get_StatusString() -{ - return QStringToString(workerObject->statusString()); -} -//! [2] //! [3] - -void netWorker::set_StatusString(String *string) -{ - workerObject->setStatusString(StringToQString(string)); - __raise statusStringChanged(string); -} -//! [3] diff --git a/examples/activeqt/dotnet/wrapper/lib/networker.h b/examples/activeqt/dotnet/wrapper/lib/networker.h deleted file mode 100644 index 0c5babb..0000000 --- a/examples/activeqt/dotnet/wrapper/lib/networker.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) 2015 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -// lib.h - -#pragma once - -#using <mscorlib.dll> -using namespace System; - -//! [0] -class Worker; - -// .NET class -public __gc class netWorker -{ -public: - netWorker(); - ~netWorker(); - - __property String *get_StatusString(); - __property void set_StatusString(String *string); - - __event void statusStringChanged(String *args); - -private: - Worker *workerObject; -}; -//! [0] diff --git a/examples/activeqt/dotnet/wrapper/lib/tools.cpp b/examples/activeqt/dotnet/wrapper/lib/tools.cpp deleted file mode 100644 index eb6d009..0000000 --- a/examples/activeqt/dotnet/wrapper/lib/tools.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) 2015 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -//! [0] -#include <QString> - -#using <mscorlib.dll> -#include <vcclr.h> - -using namespace System; - -String *QStringToString(const QString &qstring) -{ - return new String((const wchar_t *)qstring.utf16()); -} -//! [0] //! [1] - -QString StringToQString(String *string) -{ - const wchar_t __pin *chars = PtrToStringChars(string); - return QString::fromWCharArray(chars); -} -//! [1] diff --git a/examples/activeqt/dotnet/wrapper/lib/tools.h b/examples/activeqt/dotnet/wrapper/lib/tools.h deleted file mode 100644 index cd34f82..0000000 --- a/examples/activeqt/dotnet/wrapper/lib/tools.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (C) 2015 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef TOOLS_H -#define TOOLS_H - -#using <mscorlib.dll> - -QT_BEGIN_NAMESPACE -class QString; -QT_END_NAMESPACE - -System::String *QStringToString(const QString &qstring); -QString StringToQString(System::String *string); - -#endif // TOOLS_H diff --git a/examples/activeqt/dotnet/wrapper/lib/worker.cpp b/examples/activeqt/dotnet/wrapper/lib/worker.cpp deleted file mode 100644 index b11c7e5..0000000 --- a/examples/activeqt/dotnet/wrapper/lib/worker.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (C) 2015 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include "worker.h" -#include "tools.h" - -Worker::Worker() -{ - status = "Idle"; -} - -void Worker::setStatusString(const QString &string) -{ - status = string; - emit statusStringChanged(status); -} - -QString Worker::statusString() const -{ - return status; -} diff --git a/examples/activeqt/dotnet/wrapper/lib/worker.h b/examples/activeqt/dotnet/wrapper/lib/worker.h deleted file mode 100644 index 5dc52a2..0000000 --- a/examples/activeqt/dotnet/wrapper/lib/worker.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2015 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef WORKER_H -#define WORKER_H - -#include <QObject> - -// native Qt/C++ class -//! [0] -class Worker : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString statusString READ statusString WRITE setStatusString) -public: - Worker(); - - QString statusString() const; - -public slots: - void setStatusString(const QString &string); - -signals: - void statusStringChanged(const QString &string); - -private: - QString status; -}; -//! [0] - -#endif // WORKER_H diff --git a/examples/activeqt/dotnet/wrapper/main.cs b/examples/activeqt/dotnet/wrapper/main.cs deleted file mode 100644 index 1d43029..0000000 --- a/examples/activeqt/dotnet/wrapper/main.cs +++ /dev/null @@ -1,40 +0,0 @@ -//! [0] -using System; - -namespace WrapperApp -{ - class App - { - void Run() - { - netWorker worker = new netWorker(); - - worker.statusStringChanged += new netWorker.__Delegate_statusStringChanged(onStatusStringChanged); - - System.Console.Out.WriteLine(worker.StatusString); - - System.Console.Out.WriteLine("Working cycle begins..."); - worker.StatusString = "Working"; - worker.StatusString = "Lunch Break"; - worker.StatusString = "Working"; - worker.StatusString = "Idle"; - System.Console.Out.WriteLine("Working cycle ends..."); - } - - private void onStatusStringChanged(string str) - { - System.Console.Out.WriteLine(str); - } - - [STAThread] -//! [0] //! [1] - static void Main(string[] args) - { - App app = new App(); - app.Run(); - } -//! [1] //! [2] - } -//! [2] //! [3] -} -//! [3] diff --git a/examples/activeqt/dotnet/wrapper/wrapper.sln b/examples/activeqt/dotnet/wrapper/wrapper.sln deleted file mode 100644 index e25e6bd..0000000 --- a/examples/activeqt/dotnet/wrapper/wrapper.sln +++ /dev/null @@ -1,28 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 7.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "app", "app.csproj", "{334C8F04-E034-4082-9380-43906DDE71AB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib", "lib\lib.vcproj", "{2E94A303-45A2-47AC-B87A-7C3519E9D6D8}" -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - ConfigName.0 = Debug - ConfigName.1 = Release - EndGlobalSection - GlobalSection(ProjectDependencies) = postSolution - {334C8F04-E034-4082-9380-43906DDE71AB}.0 = {2E94A303-45A2-47AC-B87A-7C3519E9D6D8} - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {334C8F04-E034-4082-9380-43906DDE71AB}.Debug.ActiveCfg = Debug|.NET - {334C8F04-E034-4082-9380-43906DDE71AB}.Debug.Build.0 = Debug|.NET - {334C8F04-E034-4082-9380-43906DDE71AB}.Release.ActiveCfg = Release|.NET - {334C8F04-E034-4082-9380-43906DDE71AB}.Release.Build.0 = Release|.NET - {2E94A303-45A2-47AC-B87A-7C3519E9D6D8}.Debug.ActiveCfg = Debug|Win32 - {2E94A303-45A2-47AC-B87A-7C3519E9D6D8}.Debug.Build.0 = Debug|Win32 - {2E94A303-45A2-47AC-B87A-7C3519E9D6D8}.Release.ActiveCfg = Release|Win32 - {2E94A303-45A2-47AC-B87A-7C3519E9D6D8}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/examples/activeqt/hierarchy/CMakeLists.txt b/examples/activeqt/hierarchy/CMakeLists.txt deleted file mode 100644 index 6f3466e..0000000 --- a/examples/activeqt/hierarchy/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(hierarchyax LANGUAGES CXX) - -set(CMAKE_AUTOMOC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/activeqt/hierarchy") - -find_package(Qt6 REQUIRED COMPONENTS AxServer Core Gui Widgets) - -qt6_add_axserver_library(hierarchyax - main.cpp - objects.cpp objects.h - hierarchy.def - hierarchy.rc -) - -target_link_libraries(hierarchyax PUBLIC - Qt::Core - Qt::Gui - Qt::Widgets -) - -install(TARGETS hierarchyax - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/activeqt/mediaplayer/CMakeLists.txt b/examples/activeqt/mediaplayer/CMakeLists.txt deleted file mode 100644 index 018708a..0000000 --- a/examples/activeqt/mediaplayer/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(mediaplayer_activeqt LANGUAGES CXX) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/activeqt/mediaplayer_activeqt") - -find_package(Qt6 REQUIRED COMPONENTS AxContainer Core Gui Widgets) - -qt_add_executable(mediaplayer_activeqt - main.cpp - mainwindow.ui - mediaaxwidget.h -) - -set_target_properties(mediaplayer_activeqt PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(mediaplayer_activeqt PUBLIC - Qt::AxContainer - Qt::Core - Qt::Gui - Qt::Widgets -) - -install(TARGETS mediaplayer_activeqt - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/activeqt/menus/CMakeLists.txt b/examples/activeqt/menus/CMakeLists.txt deleted file mode 100644 index bb06f93..0000000 --- a/examples/activeqt/menus/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(menusax LANGUAGES CXX) - -set(CMAKE_AUTOMOC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/activeqt/menus") - -find_package(Qt6 REQUIRED COMPONENTS AxServer Core Gui Widgets) - -qt6_add_axserver_executable(menusax - main.cpp - menus.cpp menus.h - menus.def - menus.rc -) - -target_link_libraries(menusax PUBLIC - Qt::Core - Qt::Gui - Qt::Widgets -) - -install(TARGETS menusax - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/activeqt/multiple/CMakeLists.txt b/examples/activeqt/multiple/CMakeLists.txt deleted file mode 100644 index ed8cf46..0000000 --- a/examples/activeqt/multiple/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(multipleax LANGUAGES CXX) - -set(CMAKE_AUTOMOC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/activeqt/multiple") - -find_package(Qt6 REQUIRED COMPONENTS AxServer Core Gui Widgets) - -qt6_add_axserver_library(multipleax - ax1.h - ax2.h - main.cpp - multipleax.def - multipleax.rc -) - -target_link_libraries(multipleax PUBLIC - Qt::Core - Qt::Gui - Qt::Widgets -) - -install(TARGETS multipleax - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/activeqt/opengl/CMakeLists.txt b/examples/activeqt/opengl/CMakeLists.txt deleted file mode 100644 index 7627048..0000000 --- a/examples/activeqt/opengl/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(openglax LANGUAGES CXX) - -set(CMAKE_AUTOMOC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/activeqt/opengl") - -find_package(Qt6 REQUIRED COMPONENTS AxServer Core Gui OpenGL OpenGLWidgets Widgets) - -qt6_add_axserver_executable(openglax - glbox.cpp glbox.h - globjwin.cpp globjwin.h - main.cpp - opengl.def - opengl.rc -) - -target_link_libraries(openglax PUBLIC - Qt::Core - Qt::Gui - Qt::OpenGL - Qt::OpenGLWidgets - Qt::Widgets -) - -install(TARGETS openglax - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/activeqt/qutlook/addressview.cpp b/examples/activeqt/qutlook/addressview.cpp index 2f5242a..f3d4fc7 100644 --- a/examples/activeqt/qutlook/addressview.cpp +++ b/examples/activeqt/qutlook/addressview.cpp @@ -23,7 +23,7 @@ public: private: Outlook::Application outlook; - Outlook::Items * contactItems; + Outlook::Items *folderItems = nullptr; mutable QHash<QModelIndex, QStringList> cache; }; @@ -36,10 +36,10 @@ AddressBookModel::AddressBookModel(AddressView *parent) Outlook::NameSpace session(outlook.Session()); session.Logon(); Outlook::MAPIFolder *folder = session.GetDefaultFolder(Outlook::olFolderContacts); - contactItems = new Outlook::Items(folder->Items()); - connect(contactItems, SIGNAL(ItemAdd(IDispatch*)), parent, SLOT(updateOutlook())); - connect(contactItems, SIGNAL(ItemChange(IDispatch*)), parent, SLOT(updateOutlook())); - connect(contactItems, SIGNAL(ItemRemove()), parent, SLOT(updateOutlook())); + folderItems = new Outlook::Items(folder->Items()); + connect(folderItems, SIGNAL(ItemAdd(IDispatch*)), parent, SLOT(updateOutlook())); + connect(folderItems, SIGNAL(ItemChange(IDispatch*)), parent, SLOT(updateOutlook())); + connect(folderItems, SIGNAL(ItemRemove()), parent, SLOT(updateOutlook())); delete folder; } @@ -48,7 +48,7 @@ AddressBookModel::AddressBookModel(AddressView *parent) //! [1] //! [2] AddressBookModel::~AddressBookModel() { - delete contactItems; + delete folderItems; if (!outlook.isNull()) Outlook::NameSpace(outlook.Session()).Logoff(); @@ -57,7 +57,7 @@ AddressBookModel::~AddressBookModel() //! [2] //! [3] int AddressBookModel::rowCount(const QModelIndex &) const { - return contactItems ? contactItems->Count() : 0; + return folderItems ? folderItems->Count() : 0; } int AddressBookModel::columnCount(const QModelIndex & /*parent*/) const @@ -97,8 +97,11 @@ QVariant AddressBookModel::data(const QModelIndex &index, int role) const if (cache.contains(index)) { data = cache.value(index); } else { - Outlook::ContactItem contact(contactItems->Item(index.row() + 1)); - data << contact.FirstName() << contact.LastName() << contact.HomeAddress() << contact.Email1Address(); + Outlook::ContactItem contact(folderItems->Item(index.row() + 1)); + + if (contact.Class() == Outlook::OlObjectClass::olContact) + data << contact.FirstName() << contact.LastName() << contact.HomeAddress() << contact.Email1Address(); + cache.insert(index, data); } @@ -111,7 +114,10 @@ QVariant AddressBookModel::data(const QModelIndex &index, int role) const //! [5] //! [6] void AddressBookModel::changeItem(const QModelIndex &index, const QString &firstName, const QString &lastName, const QString &address, const QString &email) { - Outlook::ContactItem item(contactItems->Item(index.row() + 1)); + Outlook::ContactItem item(folderItems->Item(index.row() + 1)); + + if (item.Class() != Outlook::OlObjectClass::olContact) + return; // Not a contact item.SetFirstName(firstName); item.SetLastName(lastName); diff --git a/examples/activeqt/qutlook/doc/src/qutlook.qdoc b/examples/activeqt/qutlook/doc/src/qutlook.qdoc index 0d621f3..04f9123 100644 --- a/examples/activeqt/qutlook/doc/src/qutlook.qdoc +++ b/examples/activeqt/qutlook/doc/src/qutlook.qdoc @@ -4,6 +4,8 @@ /*! \example activeqt/qutlook \title Qutlook Example (ActiveQt) + \examplecategory {Desktop} + \ingroup activeqt-examples \brief The Qutlook example demonstrates the use of ActiveQt to automate Outlook. The example makes use of the \l dumpcpp tool to generate diff --git a/examples/activeqt/simple/doc/src/simple.qdoc b/examples/activeqt/simple/doc/src/simple.qdoc index bb40701..8e0f6ae 100644 --- a/examples/activeqt/simple/doc/src/simple.qdoc +++ b/examples/activeqt/simple/doc/src/simple.qdoc @@ -49,6 +49,8 @@ /*! \example activeqt/simple \title Simple Example (ActiveQt) + \examplecategory {Desktop} + \ingroup activeqt-examples \brief The Simple example demonstrates the use of QAxBindable and QAxFactory. diff --git a/examples/activeqt/simpleqml/CMakeLists.txt b/examples/activeqt/simpleqml/CMakeLists.txt deleted file mode 100644 index 0d243b0..0000000 --- a/examples/activeqt/simpleqml/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(simpleqmlax LANGUAGES CXX) - -set(CMAKE_AUTOMOC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/activeqt/simpleqml") - -find_package(Qt6 REQUIRED COMPONENTS AxServer Core Gui Quick QuickWidgets Widgets) -qt6_add_axserver_library(simpleqmlax - main.cpp - simpleqml.def - simpleqml.rc -) - -target_link_libraries(simpleqmlax PUBLIC - Qt::Core - Qt::Gui - Qt::Quick - Qt::QuickWidgets - Qt::Widgets -) - -# Resources: -set(simpleqml_resource_files - "main.qml" -) - -qt6_add_resources(simpleqmlax "simpleqml" - PREFIX - "/" - FILES - ${simpleqml_resource_files} -) - -install(TARGETS simpleqmlax - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/activeqt/simpleqml/main.cpp b/examples/activeqt/simpleqml/main.cpp deleted file mode 100644 index 67c4c5f..0000000 --- a/examples/activeqt/simpleqml/main.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include <QAxBindable> -#include <QAxFactory> -#include <QMainWindow> -#include <QQuickWidget> -#include <QQmlContext> - -class Controller : public QObject -{ - Q_OBJECT - Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged) - Q_PROPERTY(QColor color READ color NOTIFY valueChanged) -public: - explicit Controller(QWidget *parent = nullptr) : - QObject(parent) - { } - - qreal value() const { return m_value; } - - void setValue(qreal value) - { - m_value = qBound(qreal(0.0), value, qreal(1.0)); - valueChanged(); - } - - QColor color() const - { - QColor start = Qt::yellow; - QColor end = Qt::magenta; - - // Linear interpolation between two colors in HSV space - return QColor::fromHsvF( - start.hueF() * (1.0f - m_value) + end.hueF() * m_value, - start.saturationF() * (1.0f - m_value) + end.saturationF() * m_value, - start.valueF() * (1.0f - m_value) + end.valueF() * m_value, - start.alphaF() * (1.0f - m_value) + end.alphaF() * m_value - ); - } - -signals: - void valueChanged(); - -private: - qreal m_value = 0; -}; - -class QSimpleQmlAx : public QMainWindow -{ - Q_OBJECT - Q_CLASSINFO("ClassID", "{50477337-58FE-4898-8FFC-6F6199CEAE08}") - Q_CLASSINFO("InterfaceID", "{A5EC7D99-CEC9-4BD1-8336-ED15A579B185}") - Q_CLASSINFO("EventsID", "{5BBFBCFD-20FD-48A3-96C7-1F6649CD1F52}") -public: - explicit QSimpleQmlAx(QWidget *parent = nullptr) : - QMainWindow(parent) - { - auto ui = new QQuickWidget(this); - - // Register our type to qml - qmlRegisterType<Controller>("app", 1, 0, "Controller"); - - // Initialize view - ui->rootContext()->setContextProperty(QStringLiteral("context"), QVariant::fromValue(new Controller(this))); - ui->setMinimumSize(200, 200); - ui->setResizeMode(QQuickWidget::SizeRootObjectToView); - ui->setSource(QUrl(QStringLiteral("qrc:/main.qml"))); - setCentralWidget(ui); - } -}; - -#include "main.moc" - -QAXFACTORY_BEGIN( - "{E544E321-EF8B-4CD4-91F6-DB55A59DBADB}", // type library ID - "{E37E3131-DEA2-44EB-97A2-01CDD09A5A4D}") // application ID - QAXCLASS(QSimpleQmlAx) -QAXFACTORY_END() diff --git a/examples/activeqt/simpleqml/main.qml b/examples/activeqt/simpleqml/main.qml deleted file mode 100644 index 92a23c8..0000000 --- a/examples/activeqt/simpleqml/main.qml +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick 2.5 -import QtQuick.Controls 2.0 - -import app 1.0 - -Rectangle { - // Properties from context - property Controller controller: context - - color: controller.color - - Label { - id: idText - text: "Color slider" - anchors.top: parent.top - anchors.left: parent.left - color: "black" - font.pixelSize: 12 - } - - Slider { - value: controller.value - onVisualPositionChanged: controller.value = visualPosition - - anchors.top: idText.bottom - anchors.left: parent.left - } -} diff --git a/examples/activeqt/simpleqml/simpleqml.def b/examples/activeqt/simpleqml/simpleqml.def deleted file mode 100644 index bc82a03..0000000 --- a/examples/activeqt/simpleqml/simpleqml.def +++ /dev/null @@ -1,6 +0,0 @@ -EXPORTS - DllCanUnloadNow PRIVATE - DllGetClassObject PRIVATE - DllRegisterServer PRIVATE - DllUnregisterServer PRIVATE - DumpIDL PRIVATE diff --git a/examples/activeqt/simpleqml/simpleqml.ico b/examples/activeqt/simpleqml/simpleqml.ico Binary files differdeleted file mode 100644 index c80d36a..0000000 --- a/examples/activeqt/simpleqml/simpleqml.ico +++ /dev/null diff --git a/examples/activeqt/simpleqml/simpleqml.pro b/examples/activeqt/simpleqml/simpleqml.pro deleted file mode 100644 index 9043e9d..0000000 --- a/examples/activeqt/simpleqml/simpleqml.pro +++ /dev/null @@ -1,15 +0,0 @@ -include(../shared.pri) - -TEMPLATE = lib -TARGET = simpleqmlax - -QT += widgets axserver quick quickwidgets - -SOURCES = main.cpp -RC_FILE = simpleqml.rc -DEF_FILE = simpleqml.def -RESOURCES = simpleqml.qrc - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/simpleqml -INSTALLS += target diff --git a/examples/activeqt/simpleqml/simpleqml.qrc b/examples/activeqt/simpleqml/simpleqml.qrc deleted file mode 100644 index 5f6483a..0000000 --- a/examples/activeqt/simpleqml/simpleqml.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>main.qml</file> - </qresource> -</RCC> diff --git a/examples/activeqt/simpleqml/simpleqml.rc b/examples/activeqt/simpleqml/simpleqml.rc deleted file mode 100644 index d2978ce..0000000 --- a/examples/activeqt/simpleqml/simpleqml.rc +++ /dev/null @@ -1,2 +0,0 @@ -1 TYPELIB "simpleqml.rc" -1 ICON "simpleqml.ico" diff --git a/examples/activeqt/wrapper/doc/src/wrapper.qdoc b/examples/activeqt/wrapper/doc/src/wrapper.qdoc index ac385b6..b2a50a8 100644 --- a/examples/activeqt/wrapper/doc/src/wrapper.qdoc +++ b/examples/activeqt/wrapper/doc/src/wrapper.qdoc @@ -12,6 +12,8 @@ /*! \example activeqt/wrapper \title Wrapper Example (ActiveQt) + \examplecategory {Desktop} + \ingroup activeqt-examples \brief The Wrapper example demonstrates how to export existing QWidget classes as ActiveX controls, and the use of QAxFactory together diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c5aa7db..d7ec6d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from src.pro. - add_subdirectory(activeqt) if(WIN32) add_subdirectory(tools) diff --git a/src/activeqt/CMakeLists.txt b/src/activeqt/CMakeLists.txt index 991a071..e0050d3 100644 --- a/src/activeqt/CMakeLists.txt +++ b/src/activeqt/CMakeLists.txt @@ -1,9 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from activeqt.pro. - -# special case begin add_subdirectory(axbase) add_subdirectory(control) add_subdirectory(container) @@ -31,19 +28,8 @@ qt_internal_add_module(ActiveQt control/qaxfactory.h control/qclassfactory_p.h shared/qaxtypes_p.h + NO_GENERATE_CPP_EXPORTS ) qt_internal_add_docs(ActiveQt doc/activeqt.qdocconf ) - -# special case end -## Scopes: -##################################################################### - -#### Keys ignored in scope 2:.:.:activeqt.pro:WIN32: -# SUBDIRS = "axbase" "control" "container" "activeqt" -# TEMPLATE = "subdirs" -# activeqt.file = "activeqt.prx" - -#### Keys ignored in scope 3:.:.:activeqt.pro:else: -# TEMPLATE = "aux" diff --git a/src/activeqt/axbase/CMakeLists.txt b/src/activeqt/axbase/CMakeLists.txt index 3dd26df..aba9ebc 100644 --- a/src/activeqt/axbase/CMakeLists.txt +++ b/src/activeqt/axbase/CMakeLists.txt @@ -1,13 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from axbase.pro. - ##################################################################### ## AxBase Module: ##################################################################### -qt_internal_add_module(AxBasePrivate # special case +qt_internal_add_module(AxBasePrivate STATIC INTERNAL_MODULE SOURCES @@ -25,11 +23,9 @@ qt_internal_add_module(AxBasePrivate # special case Qt::Gui Qt::GuiPrivate Qt::Widgets + NO_GENERATE_CPP_EXPORTS ) -#### Keys ignored in scope 1:.:.:axbase.pro:<TRUE>: -# MODULE = "axbase" - ## Scopes: ##################################################################### diff --git a/src/activeqt/container/CMakeLists.txt b/src/activeqt/container/CMakeLists.txt index ca14c4a..6458d3e 100644 --- a/src/activeqt/container/CMakeLists.txt +++ b/src/activeqt/container/CMakeLists.txt @@ -1,13 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from container.pro. - ##################################################################### ## AxContainer Module: ##################################################################### -qt_internal_add_module(AxContainer # special case +qt_internal_add_module(AxContainer STATIC QMAKE_MODULE_CONFIG dumpcpp SOURCES @@ -32,8 +30,11 @@ qt_internal_add_module(AxContainer # special case Qt::Widgets ENABLE_AUTOGEN_TOOLS uic + NO_GENERATE_CPP_EXPORTS ) -#### Keys ignored in scope 1:.:.:container.pro:<TRUE>: -# MODULE = "axcontainer" -# MODULE_CONFIG = "dumpcpp" +set_source_files_properties(qaxbase.cpp # defines QT_CHECK_STATE + qaxscriptwrapper.cpp # references qAxFactory() + PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) + +qt_internal_add_sync_header_dependencies(AxContainer AxServer) diff --git a/src/activeqt/container/Qt6AxContainerMacros.cmake b/src/activeqt/container/Qt6AxContainerMacros.cmake index e319b90..4d3bd7e 100644 --- a/src/activeqt/container/Qt6AxContainerMacros.cmake +++ b/src/activeqt/container/Qt6AxContainerMacros.cmake @@ -80,8 +80,11 @@ C indentifier") set(out_source "${out_filebasepath}.cpp") list(APPEND out_sources "${out_header}" "${out_source}") + _qt_internal_get_tool_wrapper_script_path(tool_wrapper) + set(dumpcpp_bin "${tool_wrapper}" "$<TARGET_FILE:${QT_CMAKE_EXPORT_NAMESPACE}::dumpcpp>") + add_custom_command(OUTPUT "${out_header}" "${out_source}" - COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::dumpcpp + COMMAND ${dumpcpp_bin} "${libpath}" -o "${out_filebasepath}" ${extra_args} DEPENDS ${QT_CMAKE_EXPORT_NAMESPACE}::dumpcpp diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp index d85ca1f..3463f3c 100644 --- a/src/activeqt/container/qaxbase.cpp +++ b/src/activeqt/container/qaxbase.cpp @@ -31,6 +31,7 @@ #include <private/qobject_p.h> #include <private/qmetaobject_p.h> #include <private/qmetaobjectbuilder_p.h> +#include <private/qtools_p.h> #include <qt_windows.h> #include <ocidl.h> @@ -2284,7 +2285,7 @@ void MetaObjectGenerator::addSetterSlot(const QByteArray &property) if (isupper(prototype.at(0))) { prototype.insert(0, "Set"); } else { - prototype[0] = char(toupper(prototype[0])); + prototype[0] = QtMiscUtils::toAsciiUpper(prototype[0]); prototype.insert(0, "set"); } const QByteArray type = propertyType(property); @@ -2482,7 +2483,7 @@ void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs) set = "Set"; } else { set = "set"; - prototype[0] = char(toupper(prototype[0])); + prototype[0] = QtMiscUtils::toAsciiUpper(prototype[0]); } prototype = set + prototype; @@ -2944,6 +2945,7 @@ void MetaObjectGenerator::buildMethods(const QMap<QByteArray, Method> &map, QMetaObject *MetaObjectGenerator::metaObject(const QMetaObject *parentObject, const QByteArray &className) { + QSignalBlocker blockSignals(that ? that->qObject() : nullptr); if (that) { readClassInfo(); if (typelib) { @@ -3451,7 +3453,7 @@ int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v) // get return value if (hres == S_OK && ret.vt != VT_EMPTY) { - QVariantToVoidStar(VARIANTToQVariant(ret, slot.typeName()), v[0], slot.typeName()); + QVariantToVoidStar(VARIANTToQVariant(ret, slot.typeName(), slot.returnType()), v[0], slot.typeName()); if (ret.vt != VT_DISPATCH) clearVARIANT(&ret); else @@ -3770,7 +3772,7 @@ bool QAxBase::dynamicCallHelper(const char *name, void *inout, QList<QVariant> & hres = Invoke(disp, dispid, IID_NULL, LOCALE_USER_DEFAULT, disptype, ¶ms, nullptr, &excepinfo, &argerr); } - if (disptype == (DISPATCH_METHOD|DISPATCH_PROPERTYGET) && hres == S_OK && varc) { + if ((disptype & (DISPATCH_METHOD|DISPATCH_PROPERTYGET)) && hres == S_OK && varc) { for (qsizetype i = 0; i < varc; ++i) if ((arg[varc-i-1].vt & VT_BYREF) || outArgs[i]) // update out-parameters vars[i] = VARIANTToQVariant(arg[varc-i-1], vars.at(i).typeName()); diff --git a/src/activeqt/container/qaxdump.cpp b/src/activeqt/container/qaxdump.cpp index 4a61ca7..5623e43 100644 --- a/src/activeqt/container/qaxdump.cpp +++ b/src/activeqt/container/qaxdump.cpp @@ -10,6 +10,7 @@ #include <qt_windows.h> #include <qtextstream.h> #include <qiodevicebase.h> +#include <private/qtools_p.h> #include <ctype.h> @@ -78,7 +79,7 @@ static QByteArray toType(const QByteArray &t) if (type.at(0) == 'Q') type.remove(0, 1); - type[0] = toupper(type.at(0)); + type[0] = QtMiscUtils::toAsciiLower(type.at(0)); if (type == "VariantList") type = "List"; else if (type == "Map<QVariant,QVariant>") @@ -316,7 +317,7 @@ QString qax_generateDocumentation(QAxBase *that) setterSlot = "Set" + name; } else { QByteArray nameUp = name; - nameUp[0] = char(toupper(nameUp.at(0))); + nameUp[0] = QtMiscUtils::toAsciiUpper(nameUp.at(0)); setterSlot = "set" + nameUp; } detail += QLatin1String("<a href=\"#") + QString::fromLatin1(setterSlot) + QLatin1String("\">") + diff --git a/src/activeqt/container/qaxscript.cpp b/src/activeqt/container/qaxscript.cpp index 161f25e..cc5da7d 100644 --- a/src/activeqt/container/qaxscript.cpp +++ b/src/activeqt/container/qaxscript.cpp @@ -35,6 +35,9 @@ static QList<QAxEngineDescriptor> engines; class QAxScriptManagerPrivate { public: + void updateScript(QAxScript*); + QAxScript *scriptForFunction(QString &function) const; + QHash<QString, QAxScript*> scriptDict; QHash<QString, QAxBase*> objectDict; }; @@ -641,8 +644,11 @@ script_engine(nullptr) { if (manager) { manager->d->scriptDict.insert(name, this); - connect(this, SIGNAL(error(int,QString,int,QString)), - manager, SLOT(scriptError(int,QString,int,QString))); + + connect(this, &QAxScript::error, script_manager, + [this](int code, const QString &description, int sourcePosition, const QString &sourceText){ + emit script_manager->error(this, code, description, sourcePosition, sourceText); + }); } #ifndef QT_NO_QAXSCRIPT @@ -795,7 +801,7 @@ void QAxScript::updateObjects() if (!script_manager) return; - script_manager->updateScript(this); + script_manager->d->updateScript(this); } /*! \internal @@ -977,7 +983,9 @@ void QAxScriptManager::addObject(QAxBase *object) return; d->objectDict.insert(name, object); - connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*))); + QObject::connect(obj, &QObject::destroyed, this, [this](QObject *o){ + d->objectDict.take(o->objectName()); + }); } /*! \fn void QAxScriptManager::addObject(QObject *object) @@ -1112,16 +1120,8 @@ QVariant QAxScriptManager::call(const QString &function, const QVariant &var1, const QVariant &var7, const QVariant &var8) { - QAxScript *s = script(function); - if (!s) { -#ifdef QT_CHECK_STATE - qWarning("QAxScriptManager::call: No script provides function %s, or this function\n" - "\tis provided through an engine that does not support introspection", function.latin1()); -#endif - return QVariant(); - } - - return s->call(function, var1, var2, var3, var4, var5, var6, var7, var8); + QList<QVariant> list{var1, var2, var3, var4, var5, var6, var7, var8}; + return call(function, list); } /*! @@ -1133,17 +1133,19 @@ QVariant QAxScriptManager::call(const QString &function, const QVariant &var1, */ QVariant QAxScriptManager::call(const QString &function, QList<QVariant> &arguments) { - QAxScript *s = script(function); + QString signature = function; + QAxScript *s = d->scriptForFunction(signature); if (!s) { #ifdef QT_CHECK_STATE qWarning("QAxScriptManager::call: No script provides function %s, or this function\n" - "\tis provided through an engine that does not support introspection", function.latin1()); + "\tis provided through an engine that does not support introspection", + qPrintable(function)); #endif return QVariant(); } QVariantList args(arguments); - return s->call(function, args); + return s->call(signature, args); } /*! @@ -1213,59 +1215,51 @@ QString QAxScriptManager::scriptFileFilter() */ /*! - \fn QAxScript *QAxScriptManager::scriptForFunction(const QString &function) const \internal Returns a pointer to the first QAxScript that knows - about \a function, or 0 if this function is unknown. + about \a function, or nullptr if this function is unknown. \a function + is changed to the callable signature. */ -QAxScript *QAxScriptManager::scriptForFunction(const QString &function) const +QAxScript *QAxScriptManagerPrivate::scriptForFunction(QString &function) const { - // check full prototypes if included - if (function.contains(QLatin1Char('('))) { - for (auto it = d->scriptDict.cbegin(), end = d->scriptDict.cend(); it != end; ++it) { - if (it.value()->functions(QAxScript::FunctionSignatures).contains(function)) - return it.value(); + const auto startPrototype = function.indexOf(u'('); + + for (const auto &script : scriptDict) { + const QMetaObject *mo = script->scriptEngine()->metaObject(); + for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) { + const QMetaMethod slot(mo->method(i)); + if (slot.methodType() != QMetaMethod::Slot || slot.access() != QMetaMethod::Public) + continue; + const QString slotname = QString::fromLatin1(slot.methodSignature()); + if (slotname.contains(u'_')) + continue; + + // finding script for prototype + if (startPrototype != -1) { + if (slotname == function) + return script; + } else if (slotname.length() > function.length() + && slotname.at(function.length()) == u'(' + && slotname.startsWith(function)) { + function = slotname; + return script; + } } } - QString funcName = function; - funcName.truncate(funcName.indexOf(QLatin1Char('('))); - // second try, checking only names, not prototypes - for (auto it = d->scriptDict.cbegin(), end = d->scriptDict.cend(); it != end; ++it) { - if (it.value()->functions(QAxScript::FunctionNames).contains(funcName)) - return it.value(); - } - return nullptr; } /*! \internal */ -void QAxScriptManager::updateScript(QAxScript *script) +void QAxScriptManagerPrivate::updateScript(QAxScript *script) { if (QAxScriptEngine *engine = script->scriptEngine()) { - for (auto it = d->objectDict.constBegin(), end = d->objectDict.constEnd(); it != end; ++it) + for (auto it = objectDict.constBegin(), end = objectDict.constEnd(); it != end; ++it) engine->addItem(it.key()); } } -/*! - \internal -*/ -void QAxScriptManager::objectDestroyed(QObject *o) -{ - d->objectDict.take(o->objectName()); -} - -/*! - \internal -*/ -void QAxScriptManager::scriptError(int code, const QString &desc, int spos, const QString &stext) -{ - QAxScript *source = qobject_cast<QAxScript*>(sender()); - emit error(source, code, desc, spos, stext); -} - QT_END_NAMESPACE diff --git a/src/activeqt/container/qaxscript.h b/src/activeqt/container/qaxscript.h index 6aad2f8..f40262d 100644 --- a/src/activeqt/container/qaxscript.h +++ b/src/activeqt/container/qaxscript.h @@ -141,16 +141,9 @@ public: Q_SIGNALS: void error(QAxScript *script, int code, const QString &description, int sourcePosition, const QString &sourceText); -private Q_SLOTS: - void objectDestroyed(QObject *o); - void scriptError(int code, const QString &description, int sourcePosition, const QString &sourceText); - private: friend class QAxScript; QAxScriptManagerPrivate *d; - - void updateScript(QAxScript*); - QAxScript *scriptForFunction(const QString &function) const; }; diff --git a/src/activeqt/container/qaxselect.cpp b/src/activeqt/container/qaxselect.cpp index e53def7..20bf72d 100644 --- a/src/activeqt/container/qaxselect.cpp +++ b/src/activeqt/container/qaxselect.cpp @@ -30,6 +30,8 @@ QT_BEGIN_NAMESPACE \value SandboxingNone No specific sandboxing desired \value SandboxingProcess Run ActiveX control in a separate process \value SandboxingLowIntegrity Run ActiveX control in a separate low-integrity process + \value SandboxingAppContainer [since 6.5] Run ActiveX control in a separate + AppContainer-isolated process Sandboxing requires that the ActiveX is either built as an EXE, or as a DLL with AppID "DllSurrogate" enabled. */ @@ -327,7 +329,8 @@ QAxSelect::QAxSelect(QWidget *parent, Qt::WindowFlags flags) d->filterModel->setSourceModel(new ControlList(this)); d->selectUi.ActiveXList->setModel(d->filterModel); - QStringList sandboxingOptions = { QLatin1String("None"), QLatin1String("Process isolation"), QLatin1String("Low integrity process") }; + QStringList sandboxingOptions = { QLatin1String("None"), QLatin1String("Process isolation"), + QLatin1String("Low integrity process"), QLatin1String("AppContainer process") }; d->selectUi.SandboxingCombo->addItems(sandboxingOptions); connect(d->selectUi.ActiveXList->selectionModel(), &QItemSelectionModel::currentChanged, @@ -373,6 +376,8 @@ QAxSelect::SandboxingLevel QAxSelect::sandboxingLevel() const return SandboxingProcess; case 2: return SandboxingLowIntegrity; + case 3: + return SandboxingAppContainer; default: break; } diff --git a/src/activeqt/container/qaxselect.h b/src/activeqt/container/qaxselect.h index 3e10485..5146d5e 100644 --- a/src/activeqt/container/qaxselect.h +++ b/src/activeqt/container/qaxselect.h @@ -18,6 +18,7 @@ public: SandboxingNone = 0, SandboxingProcess, SandboxingLowIntegrity, + SandboxingAppContainer, }; explicit QAxSelect(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()); diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index 80a6ab4..76ac6d9 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -25,6 +25,7 @@ #include <quuid.h> #include <qwhatsthis.h> #include <qabstractnativeeventfilter.h> +#include <private/qpixmap_win_p.h> #include <windowsx.h> #include <ocidl.h> @@ -1800,9 +1801,6 @@ void QAxHostWidget::focusOutEvent(QFocusEvent *e) axhost->m_spInPlaceObject->UIDeactivate(); } -Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0); -Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0); - void QAxHostWidget::paintEvent(QPaintEvent*) { // QWidget having redirected paint device indicates non-regular paint, which implies diff --git a/src/activeqt/control/CMakeLists.txt b/src/activeqt/control/CMakeLists.txt index f00e0f2..74e4fb7 100644 --- a/src/activeqt/control/CMakeLists.txt +++ b/src/activeqt/control/CMakeLists.txt @@ -1,13 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from control.pro. - ##################################################################### ## AxServer Module: ##################################################################### -qt_internal_add_module(AxServer # special case +qt_internal_add_module(AxServer STATIC QMAKE_MODULE_CONFIG idcidl force_import_plugins SOURCES @@ -35,11 +33,12 @@ qt_internal_add_module(AxServer # special case Qt::Gui Qt::Widgets shell32 + NO_GENERATE_CPP_EXPORTS ) -#### Keys ignored in scope 1:.:.:control.pro:<TRUE>: -# MODULE = "axserver" -# MODULE_CONFIG = "idcidl" "force_import_plugins" +set_source_files_properties(qaxservermain.cpp # define main() + qaxmain.cpp + PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) ## Scopes: ##################################################################### diff --git a/src/activeqt/control/qaxbindable.cpp b/src/activeqt/control/qaxbindable.cpp index d079925..5922559 100644 --- a/src/activeqt/control/qaxbindable.cpp +++ b/src/activeqt/control/qaxbindable.cpp @@ -40,9 +40,6 @@ QT_BEGIN_NAMESPACE control, reimplement createAggregate() to return a new object of a QAxAggregated subclass. - The ActiveQt \l{activeqt/opengl}{OpenGL} example shows how to use - QAxBindable to implement additional COM interfaces. - \sa QAxAggregated, QAxFactory, {ActiveQt Framework} */ diff --git a/src/activeqt/control/qaxserver.cpp b/src/activeqt/control/qaxserver.cpp index d7ea1d2..aa4b951 100644 --- a/src/activeqt/control/qaxserver.cpp +++ b/src/activeqt/control/qaxserver.cpp @@ -438,8 +438,7 @@ HRESULT UpdateRegistry(bool bRegister, bool perUser) // we try to create the ActiveX widgets later on... bool delete_qApp = false; if (!qApp) { - static int argc = 0; // static lifetime, since it's passed as reference to QApplication, which has a lifetime exceeding the stack frame - (void)new QApplication(argc, nullptr); + (void)new QApplication(__argc, __argv); delete_qApp = true; } @@ -1145,8 +1144,7 @@ extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver) // dummy application to create widgets bool delete_qApp = false; if (!qApp) { - static int argc = 0; // static lifetime, since it's passed as reference to QApplication, which has a lifetime exceeding the stack frame - (void)new QApplication(argc, nullptr); + (void)new QApplication(__argc, __argv); delete_qApp = true; } diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp index ac52583..d92b9b1 100644 --- a/src/activeqt/control/qaxserverbase.cpp +++ b/src/activeqt/control/qaxserverbase.cpp @@ -1,10 +1,6 @@ // Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#ifndef NOMINMAX -# define NOMINMAX -#endif - #include <qabstracteventdispatcher.h> #include <qapplication.h> #include <qbuffer.h> @@ -28,6 +24,7 @@ #include <olectl.h> #include <private/qcoreapplication_p.h> #include <qwindow.h> +#include <private/qpixmap_win_p.h> #include <qpa/qplatformnativeinterface.h> #include <qabstractnativeeventfilter.h> @@ -882,8 +879,7 @@ HRESULT QClassFactory::CreateInstanceHelper(IUnknown *pUnkOuter, REFIID iid, voi // Make sure a QApplication instance is present (inprocess case) if (!qApp) { qax_ownQApp = true; - static int argc = 0; // static lifetime, since it's passed as reference to QApplication, which has a lifetime exceeding the stack frame - new QApplication(argc, nullptr); + new QApplication(__argc, __argv); } QGuiApplication::setQuitOnLastWindowClosed(false); @@ -3103,8 +3099,6 @@ HRESULT WINAPI QAxServerBase::Save(LPCOLESTR fileName, BOOL fRemember) return E_FAIL; } -Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0); - //**** IViewObject /* Draws the widget into the provided device context. diff --git a/src/activeqt/doc/ActiveQtDoc b/src/activeqt/doc/ActiveQtDoc index 57bcc57..4b5e674 100644 --- a/src/activeqt/doc/ActiveQtDoc +++ b/src/activeqt/doc/ActiveQtDoc @@ -14,3 +14,7 @@ #include "qaxtypes.h" #include "qaxwidget.h" #include "qaxutils_p.h" + +#ifndef WINAPI +#define WINAPI +#endif diff --git a/src/activeqt/doc/CMakeLists.txt b/src/activeqt/doc/CMakeLists.txt index d1392dd..c9ff536 100644 --- a/src/activeqt/doc/CMakeLists.txt +++ b/src/activeqt/doc/CMakeLists.txt @@ -1,8 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# special case skip regeneration - add_library(ActiveQt INTERFACE) target_link_libraries(ActiveQt INTERFACE Qt::Core) qt_internal_add_docs(ActiveQt activeqt.qdocconf) diff --git a/src/activeqt/doc/snippets/doc_src_examples_activeqt_dotnet.qdoc b/src/activeqt/doc/snippets/doc_src_examples_activeqt_dotnet.qdoc deleted file mode 100644 index f5e5659..0000000 --- a/src/activeqt/doc/snippets/doc_src_examples_activeqt_dotnet.qdoc +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (C) 2015 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -//! [0] -' VB is case insensitive, but our C++ controls are not. -' Me.resetButton.enabled = True -//! [0] diff --git a/src/activeqt/doc/src/activeqt-index.qdoc b/src/activeqt/doc/src/activeqt-index.qdoc index 8383b8b..6a5d503 100644 --- a/src/activeqt/doc/src/activeqt-index.qdoc +++ b/src/activeqt/doc/src/activeqt-index.qdoc @@ -12,6 +12,15 @@ */ /*! + \group activeqt-examples + \title ActiveQt Examples and Tutorials + \brief List of ActiveQt examples and tutorials. + \ingroup groups + + This page lists ActiveQt examples and tutorials: +*/ + +/*! \page activeqt-index.html \ingroup qt-activex \keyword ActiveQt @@ -74,14 +83,8 @@ \section1 Examples \list - \li \l{Multiple Example (ActiveQt)} \li \l{Qutlook Example (ActiveQt)} \li \l{COM App Example (ActiveQt)} - \li \l{Dot Net Example (ActiveQt)} - \li \l{OpenGL Example (ActiveQt)} - \li \l{Hierarchy Example (ActiveQt)} - \li \l{Media Player Example (ActiveQt)} - \li \l{Menus Example (ActiveQt)} \li \l{Wrapper Example (ActiveQt)} \li \l{Simple Example (ActiveQt)} \endlist diff --git a/src/activeqt/doc/src/examples/dotnet.qdoc b/src/activeqt/doc/src/examples/dotnet.qdoc deleted file mode 100644 index 7f4451d..0000000 --- a/src/activeqt/doc/src/examples/dotnet.qdoc +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \page activeqt-dotnet.html - \title Dot Net Example (ActiveQt) - - \brief The Dot Net example demonstrates how Qt objects can be used in a - .NET environment, and how .NET objects can be used in a Qt - environment. - - Contents: - - \tableofcontents - - \section1 Qt vs. .NET - - Qt is a C++ library and is compiled into traditional, native - binaries that make full use of the performance provided by the - runtime environment. - - One of the key concepts of .NET is the idea of "intermediate language - code" - the source code is compiled into a bytecode format, and at - runtime, that bytecode is executed in a virtual machine - the \e - {Common Language Runtime} (CLR). - - Another key concept is that of \e {managed code}. This is essentially - intermediate language code written in such a way that the CLR can take - care of the memory management, i.e. the CLR will do automatic garbage - collection, so the application code does not need to explicitly free - the memory for unused objects. - - The MS compilers for C# and VB.NET will only produce managed - code. Such programs cannot directly call normal, native functions - or classes. \footnote The .NET framework provides Platform Invocation - Services - P/Invoke - that enable managed code to call native C (not - C++) functions located in DLLs directly. The resulting application - then becomes partially unmanaged.\endfootnote - - The MS C++ compiler for .NET on the other hand, can produce both - normal and managed code. To write a C++ class that can be compiled - into managed code, the developer must flag the class as managed using - the \c __gc keyword, and restrict the code to only use the subset of - C++ known as "Managed Extensions for C++", or MC++ for short. The - advantage is that MC++ code can freely call and use normal C++ - functions and classes. And it also works the other way around: normal - C++ code can call managed functions and use managed classes (e.g. the - entire .NET framework class library), including managed functions and - classes implemented in C# or VB.NET. This feature of mixing managed - and normal C++ code immensely eases the interoperability with .NET, - and is by Microsoft referred to as the "It Just Works" (IJW) feature. - - This document demonstrates two different ways of integrating normal - C++ code (that uses Qt) with managed .NET code. First, the manual way - is presented, which includes using a thin MC++ wrapper class around - the normal Qt/C++ class. Then, the automated way is presented, which - utilizes the ActiveQt framework as a generic bridge. The advantage of - the first method is that it gives the application developer full - control, while the second method requires less coding and relieves the - developer of dealing with the conversion between managed and normal - data objects. - - The impatient reader, who right away wants to see a QPushButton - and a custom Qt widget (\l{activeqt/multiple}{QAxWidget2}) run in - a .NET GUI application is referred to the example directory of - ActiveQt. It contains the result of this walkthrough using both - C# and VB.NET, created with Visual Studio .NET (not 2003). - Load \c {examples/dotnet/walkthrough/csharp.csproj}, - \c {examples/dotnet/walkthrough/vb.vbproj} - or \c {examples/dotnet/wrapper/wrapper.sln} into the IDE and run - the solution. - - \b{Remark:} You will notice that in the generated code the following line is - commented out: - - \snippet doc_src_examples_activeqt_dotnet.qdoc 0 - - This line is regenerated without comment whenever you change the - dialog, in which case you have to comment it out again to be able - to run the project. This is a bug in the original version of - Visual Studio.NET, and is fixed in the 2003 edition. - - \section1 Walkthrough: .NET Interop with MC++ and IJW - - Normal C++ classes and functions can be used from managed .NET code by - providing thin wrapper classes written in MC++. The wrapper class will - take care of forwarding the calls to the normal C++ functions or - methods, and converting parameter data as necessary. Since the wrapper - class is a managed class, it can be used without further ado in any - managed .NET application, whether written in C#, VB.NET, MC++ or other - managed programming language. - - \snippet activeqt/dotnet/wrapper/lib/worker.h 0 - - The Qt class has nothing unusual for Qt users, and as even the Qt - specialities like \c Q_PROPERTY, \c slots and \c signals are - implemented with straight C++ they don't cause any trouble when - compiling this class with any C++ compiler. - - \snippet activeqt/dotnet/wrapper/lib/networker.h 0 - - The .NET wrapper class uses keywords that are part of MC++ to indicate - that the class is managed/garbage collected (\c {__gc}), and that \c - StatusString should be accessible as a property in languages that - support this concept (\c {__property}). We also declare an event - function \c statusStringChanged(String*) (\c {__event}), the - equivalent of the respective signal in the Qt class. - - Before we can start implementing the wrapper class we need a way to - convert Qt's datatypes (and potentionally your own) into .NET - datatypes, e.g. \c QString objects need to be converted into objects - of type \c {String*}. - - When operating on managed objects in normal C++ code, a little extra - care must be taken because of the CLR's garbage collection. A normal - pointer variable should not \footnote Indeed, the compiler will in - many cases disallow it. \endfootnote be used to refer to a managed - object. The reason is that the garbage collection can kick in at any - time and move the object to another place on the heap, leaving you - with an invalid pointer. - - However, two methods are provided that solves this problem easily. The - first is to use a \e pinned pointer, i.e. declare the pointer variable - with the \c __pin keyword. This guarantees that the object pointed to - will not be moved by the garbage collector. It is recommended that - this method not be used to keep a references to managed objects for a - long time, since it will decrease the efficiency of the garbage - collector. The second way is to use the \c gcroot smartpointer - template type. This lets you create safe pointers to managed - objects. E.g. a variable of type \c gcroot<String> will always point - to the String object, even if it has been moved by the garbage - collector, and it can be used just like a normal pointer. - - \snippet activeqt/dotnet/wrapper/lib/tools.cpp 0 - \codeline - \snippet activeqt/dotnet/wrapper/lib/tools.cpp 1 - - The convertor functions can then be used in the wrapper class - implementation to call the functions in the native C++ class. - - \snippet activeqt/dotnet/wrapper/lib/networker.cpp 0 - \codeline - \snippet activeqt/dotnet/wrapper/lib/networker.cpp 1 - - The constructor and destructor simply create and destroy the Qt - object wrapped using the C++ operators \c new and \c delete. - - \snippet activeqt/dotnet/wrapper/lib/networker.cpp 2 - - The netWorker class delegates calls from the .NET code to the native - code. Although the transition between those two worlds implies a small - performance hit for each function call, and for the type conversion, - this should be negligible since we are anyway going to run within the - CLR. - - \snippet activeqt/dotnet/wrapper/lib/networker.cpp 3 - - The property setter calls the native Qt class before firing the - event using the \c __raise keyword. - - This wrapper class can now be used in .NET code, e.g. using C++, C#, - Visual Basic or any other programming language available for .NET. - - \snippet activeqt/dotnet/wrapper/main.cs 0 - \snippet activeqt/dotnet/wrapper/main.cs 1 - \snippet activeqt/dotnet/wrapper/main.cs 2 - \snippet activeqt/dotnet/wrapper/main.cs 3 - - \section1 Walkthrough: .NET/COM Interop with ActiveQt - - Fortunately .NET provides a generic wrapper for COM objects, the - \e {Runtime Callable Wrapper} (RCW). This RCW is a proxy for the - COM object and is generated by the CLR when a .NET Framework client - activates a COM object. This provides a generic way to reuse COM - objects in a .NET Framework project. - - Making a QObject class into a COM object is easily achieved with - ActiveQt and demonstrated in the QAxServer examples (e.g., the - \l{activeqt/simple}{Simple} example). The walkthrough will use - the Qt classes implemented in those examples, so the first thing - to do is to make sure that those examples have been built - correctly, e.g. by opening the - \l{qaxserver-demo-multiple.html}{demonstration pages} in Internet - Explorer to verify that the controls are functional. - - \section2 Starting a Project - - Start Visual Studio.NET, and create a new C# project for writing a - Windows application. This will present you with an empty form in - Visual Studio's dialog editor. You should see the toolbox, which - presents you with a number of available controls and objects in - different categories. If you right-click on the toolbox it allows - you to add new tabs. We will add the tab "Qt". - - \section2 Importing Qt Widgets - - The category only has a pointer tool by default, and we have to add - the Qt objects we want to use in our form. Right-click on the empty - space, and select "Customize". This opens a dialog that has two - tabs, "COM Components" and ".NET Framework Components". We used - ActiveQt to wrap \l {QWidget}s into COM objects, so we select the "COM - Components" page, and look for the classes we want to use, e.g. - "QPushButton" and "QAxWidget2". - - When we select those widgets and close the dialog the two widgets - will now be available from the toolbox as grey squares with their - name next to it \footnote Icons could be added by modifying the - way the controls register themselves. \endfootnote. - - \section2 Using Qt Widgets - - We can now add an instance of QAxWidget2 and a QPushButton to - the form. Visual Studio will automatically generate the RCW for the - object servers. The QAxWidget2 instance takes most of the upper - part of the form, with the QPushButton in the lower right corner. - - In the property editor of Visual Studio we can modify the properties - of our controls - QPushButton exposes the \c QWidget API and has many - properties, while QAxWidget2 has only the Visual Studio standard - properties in addition to its own property "lineWidth" in the - "Miscellaneous" category. The objects are named "axQPushButton1" and - "axQAxWidget21", and since especially the last name is a bit - confusing we rename the objects to "resetButton" and "circleWidget". - - We can also change the Qt properties, e.g. set the "text" property - of the \c resetButton to "Reset", and the "lineWidth" property of the - \c circleWidget to 5. We can also put those objects into the layout - system that Visual Studio's dialog editor provides, e.g. by setting - the anchors of the \c circleWidget to "Left, Top, Right, Bottom", and - the anchors of the \c resetButton to "Bottom, Right". - - Now we can compile and start the project, which will open a user - interface with our two Qt widgets. If we can resize the dialog, - the widgets will resize appropriately. - - \section2 Handling Qt Signals - - We will now implement event handlers for the widgets. Select the - \c circleWidget and select the "Events" page in the property - editor. The widget exposes events because the QAxWidget2 class has - the "StockEvents" attribute set in its class definition. We implement - the event handler \c circleClicked for the \c ClickEvent to increase - the line width by one for every click: - - \snippet activeqt/dotnet/walkthrough/Form1.cs 0 - - In general we can implement a default event handler by double - clicking on the widget in the form, but the default events for - our widgets are right now not defined. - - We will also implement an event handler for the \c clicked signal - emitted by QPushButton. Add the event handler \c resetLineWidth to - the \c clicked event, and implement the generated function: - - \snippet activeqt/dotnet/walkthrough/Form1.cs 1 - - We reset the property to 1, and also call the \c setFocus() slot - to simulate the user style on Windows, where a button grabs focus - when you click it (so that you can click it again with the spacebar). - - If we now compile and run the project we can click on the circle - widget to increase its line width, and press the reset button to - set the line width back to 1. - - \section1 Summary - - Using ActiveQt as a universal interoperability bridge between the - .NET world and the native world of Qt is very easy, and makes it - often unnecessary to implement a lot of handwritten wrapper classes. - Instead, the QAxFactory implementation in the otherwise completely - cross-platform Qt project provides the glue that .NET needs to to - generate the RCW. - - If this is not sufficient we can implement our own wrapper classes - thanks to the C++ extensions provided by Microsoft. - - \section2 Limitations - - All the limitations when using ActiveQt are implied when using this - technique to interoperate with .NET, e.g. the datatypes we can use - in the APIs can only be those supported by ActiveQt and COM. However, - since this includes subclasses of QObject and QWidget we can wrap - any of our datatypes into a QObject subclass to make its API - available to .NET. - - When using the "IJW" method, in principle the only limitation is the - time required to write the wrapper classes and data type conversion - functions. - - \section2 Performance Considerations - - Every call from CLR bytecode to native code implies a small - performance hit, and necessary type conversions introduce an - additional delay with every layer that exists between the two - frameworks. Consequently every approach to mix .NET and native - code should try to minimize the communication necessary between - the different worlds. - - As ActiveQt introduces three layers at once - the RCW, COM and finally - ActiveQt itself - the performance penalty when using the generic - Qt/ActiveQt/COM/RCW/.NET bridge is larger than when using a - hand-crafted IJW-wrapper class. The execution speed however is still - sufficient for connecting to and modifying interactive elements in a - user interface, and as soon as the benefit of using Qt and C++ to - implement and compile performance critical algorithms into native code - kicks in, ActiveQt becomes a valid choice for making even non-visual - parts of your application accessible to .NET. -*/ diff --git a/src/activeqt/doc/src/qtaxcontainer.qdoc b/src/activeqt/doc/src/qtaxcontainer.qdoc index b359f6b..b139a81 100644 --- a/src/activeqt/doc/src/qtaxcontainer.qdoc +++ b/src/activeqt/doc/src/qtaxcontainer.qdoc @@ -136,8 +136,6 @@ object and its subobjects; note that not all of the COM object's APIs might be available. - See the \l{activeqt/mediaplayer}{Media Player} example for more information. - \section2 Calling Function Through a Script Engine A Qt application can host any ActiveScript engine installed on the system. diff --git a/src/activeqt/doc/src/qtaxserver.qdoc b/src/activeqt/doc/src/qtaxserver.qdoc index 60cc30c..c7fa1ff 100644 --- a/src/activeqt/doc/src/qtaxserver.qdoc +++ b/src/activeqt/doc/src/qtaxserver.qdoc @@ -395,8 +395,8 @@ \li [in, out] struct QPoint (user defined) \endtable - Also supported are exported enums and flags (see Q_ENUMS() and - Q_FLAGS()). The in-parameter types are also supported as + Also supported are exported enums and flags (see Q_ENUM() and + Q_FLAG()). The in-parameter types are also supported as return values. Properties and signals/slots that have parameters using any other @@ -658,6 +658,24 @@ If the server runs, see the following section for information on debugging your server. + \section3 Crashes when unloading and reloading COM servers + + If ActiveQt COM servers utilize Qt modules beyond those found in Qt Base, it + is necessary to activate the COM server as an out-of-process COM server. + Attempting to activate an in-process COM server that includes modules such + as Qt Quick may result in a crash after unloading the COM server. + + \section3 Crash or unexpected behavior during outgoing COM calls + + Be aware that an out-of-process COM server will be processing its message + queue while it is performing an outgoing call to the client. This can lead to + unexpected behavior or crash if the client is at the same time calling the + server. In this situation, the incoming call will be executed in the server + before the outgoing call returns. In particular, if the client closes + an ActiveX control while the control is calling back into the client, this + can lead to crash. Such reentrancy problems can be mitigated using message + filters (IMessageFilter and CoRegisterMessageFilter). + \section2 Debugging Runtime Errors To debug an in-process server in Visual Studio, set the server project diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp index 83845b9..d9175ea 100644 --- a/src/activeqt/shared/qaxtypes.cpp +++ b/src/activeqt/shared/qaxtypes.cpp @@ -1,10 +1,6 @@ // Copyright (C) 2015 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#ifndef NOMINMAX -# define NOMINMAX -#endif - #include <ocidl.h> #include <olectl.h> @@ -15,6 +11,7 @@ #include <qcursor.h> #include <qpixmap.h> #include <qpainter.h> +#include <private/qpixmap_win_p.h> #include <qobject.h> #include <qdebug.h> #ifdef QAX_SERVER @@ -94,9 +91,6 @@ static QFont IFontToQFont(IFont *f) return font; } -Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0); -Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0); - static IPictureDisp *QPixmapToIPicture(const QPixmap &pixmap) { IPictureDisp *pic = nullptr; @@ -218,6 +212,19 @@ static QByteArray msgOutParameterNotSupported(const QByteArray &type) } \ } +static qsizetype columnCount2D(const QVariantList &list) +{ + if (!list.isEmpty()) { + const auto &firstElement = list.at(0); + const auto type = firstElement.typeId(); + if (type != QMetaType::QString && type != QMetaType::QByteArray + && firstElement.canConvert<QVariantList>()) { + return firstElement.toList().size(); + } + } + return 0; +} + bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out) { QVariant qvar = var; @@ -240,7 +247,7 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type return QVariantToVARIANT(var, *arg.pvarVal, typeName, false); } - if (out && proptype == QMetaType::User && typeName == "QVariant") { + if (out && proptype == QMetaType::QVariant) { VARIANT *pVariant = new VARIANT; QVariantToVARIANT(var, *pVariant, QByteArray(), false); arg.vt = VT_VARIANT|VT_BYREF; @@ -435,36 +442,28 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type break; } SAFEARRAY *array = nullptr; - bool is2D = false; // If the first element in the array is a list the whole list is // treated as a 2D array. The column count is taken from the 1st element. - if (count) { - QVariantList col = list.at(0).toList(); - qsizetype maxColumns = col.size(); - if (maxColumns) { - is2D = true; - SAFEARRAYBOUND rgsabound[2] = { {0, 0}, {0, 0} }; - rgsabound[0].cElements = count; - rgsabound[1].cElements = maxColumns; - array = SafeArrayCreate(VT_VARIANT, 2, rgsabound); - LONG rgIndices[2]; - for (LONG i = 0; i < count; ++i) { - rgIndices[0] = i; - QVariantList columns = list.at(i).toList(); - qsizetype columnCount = qMin(maxColumns, columns.size()); - for (LONG j = 0; j < columnCount; ++j) { - const QVariant &elem = columns.at(j); - VariantInit(&variant); - QVariantToVARIANT(elem, variant, elem.typeName()); - rgIndices[1] = j; - SafeArrayPutElement(array, rgIndices, pElement); - clearVARIANT(&variant); - } + if (qsizetype maxColumns = columnCount2D(list)) { + SAFEARRAYBOUND rgsabound[2] = { {0, 0}, {0, 0} }; + rgsabound[0].cElements = count; + rgsabound[1].cElements = maxColumns; + array = SafeArrayCreate(VT_VARIANT, 2, rgsabound); + LONG rgIndices[2]; + for (LONG i = 0; i < count; ++i) { + rgIndices[0] = i; + QVariantList columns = list.at(i).toList(); + qsizetype columnCount = qMin(maxColumns, columns.size()); + for (LONG j = 0; j < columnCount; ++j) { + const QVariant &elem = columns.at(j); + VariantInit(&variant); + QVariantToVARIANT(elem, variant, elem.typeName()); + rgIndices[1] = j; + SafeArrayPutElement(array, rgIndices, pElement); + clearVARIANT(&variant); } - } - } - if (!is2D) { + } else { array = SafeArrayCreateVector(vt, 0, count); for (LONG index = 0; index < count; ++index) { QVariant elem = list.at(index); @@ -724,7 +723,10 @@ static QVariant axServer(IUnknown *unknown, const QByteArray &typeName) #undef QVARIANT_TO_VARIANT_POD /* - Returns \a arg as a QVariant of type \a type. + Returns \a arg as a QVariant of type \a typeName or \a type. + + NOTE: If a \a typeName is specified, value type is assumed. to + get/create a pointer type, provide the type id in the \a type argument. Used by @@ -939,24 +941,43 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, int t { if (!typeName.isEmpty()) { if (arg.vt & VT_BYREF) { + // When the dispinterface is a return value, just assign it to a QVariant static const int dispatchId = qRegisterMetaType<IDispatch**>("IDispatch**"); var = QVariant(QMetaType(dispatchId), &arg.ppdispVal); } else { #ifndef QAX_SERVER if (typeName == "QVariant") { + // If a QVariant is requested, wrap the dispinterface in a QAxObject QAxObject *object = new QAxObject(disp); var = QVariant::fromValue<QAxObject*>(object); } else if (typeName != "IDispatch*" && QMetaType::fromName(typeName).id() != QMetaType::UnknownType) { - QByteArray typeNameStr = QByteArray(typeName); + // Conversion from IDispatch* to a wrapper type is requested. Here, the requested + // wrapper type is constructed around the dispinterface, and then returned as + // a QVariant containing a pointer to the wrapper type. + + // Calculate the value type from a potential pointer type + QByteArray valueTypeStr = QByteArray(typeName); int pIndex = typeName.lastIndexOf('*'); if (pIndex != -1) - typeNameStr = typeName.left(pIndex); - const QMetaType metaType = QMetaType::fromName(typeNameStr); - Q_ASSERT(metaType.id() != QMetaType::UnknownType); - auto object = static_cast<QAxObject*>(qax_createObjectWrapper(metaType.id(), disp)); - var = QVariant(metaType, &object); + valueTypeStr = typeName.left(pIndex); + + const QMetaType metaValueType = QMetaType::fromName(valueTypeStr); + Q_ASSERT(metaValueType.id() != QMetaType::UnknownType); + + auto object = static_cast<QAxObject*>(qax_createObjectWrapper(metaValueType.id(), disp)); + + // Return object as the original type + const QMetaType returnType = QMetaType::fromName(typeName); + Q_ASSERT(metaValueType.id() != QMetaType::UnknownType); + + var = QVariant(returnType, &object); + + // The result must be a pointer to an instance derived from QObject + Q_ASSERT((var.metaType().flags() & QMetaType::PointerToQObject) != 0); } else { #endif + // An IDispatch pointer is requested, no conversion required, just return as QVariant + // containing the pointer. static const int dispatchId = qRegisterMetaType<IDispatch*>(typeName.constData()); var = QVariant(QMetaType(dispatchId), &disp); #ifndef QAX_SERVER diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 343f962..2f6644c 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -1,6 +1,4 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from tools.pro. - add_subdirectory(idc) diff --git a/src/tools/idc/CMakeLists.txt b/src/tools/idc/CMakeLists.txt index c7ad1c5..f1d784e 100644 --- a/src/tools/idc/CMakeLists.txt +++ b/src/tools/idc/CMakeLists.txt @@ -1,22 +1,15 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from idc.pro. - ##################################################################### ## idc Tool: ##################################################################### qt_get_tool_target_name(target_name idc) -qt_internal_add_tool(${target_name} # special case -# BOOTSTRAP # special case +qt_internal_add_tool(${target_name} TARGET_DESCRIPTION "Active Qt Interface Description Compiler" - TOOLS_TARGET AxServer # special case + TOOLS_TARGET AxServer SOURCES main.cpp ) qt_internal_return_unless_building_tools() - -#### Keys ignored in scope 1:.:.:idc.pro:<TRUE>: -# QMAKE_TARGET_DESCRIPTION = "Active Qt Interface Description Compiler" -# _OPTION = "host_build" diff --git a/src/tools/idc/main.cpp b/src/tools/idc/main.cpp index a1e0712..2cf3bd3 100644 --- a/src/tools/idc/main.cpp +++ b/src/tools/idc/main.cpp @@ -268,7 +268,7 @@ const char usage[] = "Usage: idc [options] [input_file]\n" "Interface Description Compiler " QT_VERSION_STR "\n\n" "Options:\n" -" -?, /h, -h, -help Displays this help.\n" +" /?, -?, /h, -h, /help, -help Displays this help.\n" " /v, -v Displays version information.\n" " /version, -version <version> Specify the interface version.\n" " /idl, -idl <file> Specify the interface definition file.\n" @@ -322,7 +322,9 @@ int runIdc(int argc, char **argv) } else if (p == QLatin1String("/v") || p == QLatin1String("-v")) { fprintf(stdout, "Qt Interface Definition Compiler version 1.0 using Qt %s\n", QT_VERSION_STR); return 0; - } else if (p == QLatin1String("/h") || p == QLatin1String("-h") || p == QLatin1String("-?") || p == QLatin1String("/?")) { + } else if (p == QLatin1String("/h") || p == QLatin1String("-h") + || p == QLatin1String("/?") || p == QLatin1String("-?") + || p == QLatin1String("/help") || p == QLatin1String("-help")) { fprintf(stdout, "%s\n", usage); return 0; } else if (p == QLatin1String("/regserver") || p == QLatin1String("-regserver")) { diff --git a/sync.profile b/sync.profile deleted file mode 100644 index 190bea0..0000000 --- a/sync.profile +++ /dev/null @@ -1,10 +0,0 @@ -%modules = ( # path to module name map - "QtAxBase" => "$basedir/src/activeqt/axbase", - "QtAxContainer" => "$basedir/src/activeqt/container", - "QtAxServer" => "$basedir/src/activeqt/control", - "ActiveQt" => "$basedir/src/activeqt" -); -%moduleheaders = ( # restrict the module headers to those found in relative path -); -%classnames = ( -); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 800bc26..05cc44c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,8 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from tests.pro. - if(QT_BUILD_STANDALONE_TESTS) # Add qt_find_package calls for extra dependencies that need to be found when building # the standalone tests here. diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt index 21dd4e5..4cba078 100644 --- a/tests/auto/CMakeLists.txt +++ b/tests/auto/CMakeLists.txt @@ -1,12 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from auto.pro. - add_subdirectory(conversion) add_subdirectory(qaxobject) add_subdirectory(dumpcpp) add_subdirectory(cmake) if(NOT GCC) add_subdirectory(qaxscript) + add_subdirectory(qaxscriptmanager) endif() diff --git a/tests/auto/conversion/CMakeLists.txt b/tests/auto/conversion/CMakeLists.txt index 83ff23c..97e6c7f 100644 --- a/tests/auto/conversion/CMakeLists.txt +++ b/tests/auto/conversion/CMakeLists.txt @@ -1,16 +1,23 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from conversion.pro. - ##################################################################### ## conversion Test: ##################################################################### -qt_internal_add_test(conversion # special case +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(conversion LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(conversion SOURCES tst_conversion.cpp + INCLUDE_DIRECTORIES + ../../../src/activeqt/shared/ LIBRARIES Qt::AxContainer Qt::Gui + Qt::AxBasePrivate ) diff --git a/tests/auto/conversion/comutil_p.h b/tests/auto/conversion/comutil_p.h new file mode 100644 index 0000000..ac39c91 --- /dev/null +++ b/tests/auto/conversion/comutil_p.h @@ -0,0 +1,304 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef COMUTIL_P_H +#define COMUTIL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QtGlobal> +#include <comdef.h> +#include <type_traits> +#include <oleauto.h> +#include <wrl/client.h> + +using Microsoft::WRL::ComPtr; + +template<typename T> +ComPtr<T> makeComObject() +{ + ComPtr<T> ptr; + *ptr.GetAddressOf() = new T; + return ptr; +} + +class ComBstr +{ +public: + ComBstr() = default; + + ComBstr(decltype(nullptr)) { } + + ~ComBstr() { ::SysFreeString(m_str); } + + explicit ComBstr(const wchar_t *str) noexcept + { + if (!str) + return; + + m_str = ::SysAllocString(str); + Q_ASSERT(m_str); + } + + ComBstr(const ComBstr &src) noexcept + { + if (!src.m_str) + return; + + m_str = ::SysAllocStringByteLen(reinterpret_cast<char *>(src.m_str), + ::SysStringByteLen(m_str)); + Q_ASSERT(m_str); + } + + ComBstr(ComBstr &&src) noexcept : m_str{ src.m_str } { src.m_str = nullptr; } + + ComBstr &operator=(const ComBstr &rhs) noexcept + { + if (&rhs == this) + return *this; + + clear(); + + m_str = rhs.copy(); + + return *this; + } + + ComBstr &operator=(ComBstr &&rhs) noexcept + { + if (&rhs == this) + return *this; + + clear(); + + m_str = rhs.m_str; + rhs.m_str = nullptr; + + return *this; + } + + [[nodiscard]] BSTR copy() const + { + if (!m_str) + return nullptr; + + return ::SysAllocStringByteLen(reinterpret_cast<char *>(m_str), ::SysStringByteLen(m_str)); + } + +private: + void clear() { ::SysFreeString(m_str); } + + BSTR m_str = nullptr; +}; + +template<typename T> +constexpr VARTYPE ValueType() +{ + using ValueType = std::remove_cv_t<std::remove_pointer_t<T>>; + + constexpr VARTYPE maybeByref = std::is_pointer_v<T> ? VT_BYREF : VT_EMPTY; + if constexpr (std::is_same_v<ValueType, bool>) + return VT_BOOL | maybeByref; + else if constexpr (std::is_same_v<ValueType, char>) + return VT_I1 | maybeByref; + else if constexpr (std::is_same_v<ValueType, unsigned char>) + return VT_UI1 | maybeByref; + else if constexpr (std::is_same_v<ValueType, short>) + return VT_I2 | maybeByref; + else if constexpr (std::is_same_v<ValueType, unsigned short>) + return VT_UI2 | maybeByref; + else if constexpr (std::is_same_v<ValueType, int>) + return VT_I4 | maybeByref; + else if constexpr (std::is_same_v<ValueType, unsigned int>) + return VT_UI4 | maybeByref; + else if constexpr (std::is_same_v<ValueType, long long>) + return VT_I8 | maybeByref; + else if constexpr (std::is_same_v<ValueType, unsigned long long>) + return VT_UI8 | maybeByref; + else if constexpr (std::is_same_v<ValueType, float>) + return VT_R4 | maybeByref; + else if constexpr (std::is_same_v<ValueType, double>) + return VT_R8 | maybeByref; + else if constexpr (std::is_same_v<const ValueType *, const wchar_t *>) + return VT_BSTR; + else if constexpr (std::is_base_of_v<IDispatch, ValueType>) + return VT_DISPATCH; + else if constexpr (std::is_base_of_v<IUnknown, ValueType>) + return VT_UNKNOWN; + else + return VT_EMPTY; +}; + +template<typename T> +constexpr auto ValueField() +{ + using Type = std::remove_const_t<T>; + if constexpr (std::is_same_v<Type, bool>) + return &VARIANT::boolVal; + else if constexpr (std::is_same_v<Type, bool *>) + return &VARIANT::pboolVal; + else if constexpr (std::is_same_v<Type, char>) + return &VARIANT::cVal; + else if constexpr (std::is_same_v<Type, char *>) + return &VARIANT::pcVal; + else if constexpr (std::is_same_v<Type, unsigned char>) + return &VARIANT::bVal; + else if constexpr (std::is_same_v<Type, unsigned char *>) + return &VARIANT::pbVal; + else if constexpr (std::is_same_v<Type, short>) + return &VARIANT::iVal; + else if constexpr (std::is_same_v<Type, short *>) + return &VARIANT::piVal; + else if constexpr (std::is_same_v<Type, unsigned short>) + return &VARIANT::uiVal; + else if constexpr (std::is_same_v<Type, unsigned short *>) + return &VARIANT::puiVal; + else if constexpr (std::is_same_v<Type, int>) + return &VARIANT::intVal; + else if constexpr (std::is_same_v<Type, int *>) + return &VARIANT::pintVal; + else if constexpr (std::is_same_v<Type, unsigned int>) + return &VARIANT::uintVal; + else if constexpr (std::is_same_v<Type, unsigned int *>) + return &VARIANT::puintVal; + else if constexpr (std::is_same_v<Type, long long>) + return &VARIANT::llVal; + else if constexpr (std::is_same_v<Type, long long *>) + return &VARIANT::pllVal; + else if constexpr (std::is_same_v<Type, unsigned long long>) + return &VARIANT::ullVal; + else if constexpr (std::is_same_v<Type, unsigned long long *>) + return &VARIANT::pullVal; + else if constexpr (std::is_same_v<Type, float>) + return &VARIANT::fltVal; + else if constexpr (std::is_same_v<Type, float *>) + return &VARIANT::pfltVal; + else if constexpr (std::is_same_v<Type, double>) + return &VARIANT::dblVal; + else if constexpr (std::is_same_v<Type, double *>) + return &VARIANT::pdblVal; + else if constexpr (std::is_same_v<T, const wchar_t *>) + return &VARIANT::bstrVal; + else if constexpr (std::is_base_of_v<IDispatch, std::remove_pointer_t<Type>>) + return &VARIANT::pdispVal; + else if constexpr (std::is_base_of_v<IUnknown, std::remove_pointer_t<Type>>) + return &VARIANT::punkVal; +} + +class ComVariant : public tagVARIANT +{ +public: + ComVariant() noexcept : VARIANT{} { ::VariantInit(this); } + + ~ComVariant() + { + const HRESULT hr = ::VariantClear(this); + Q_ASSERT(hr == S_OK); + Q_UNUSED(hr) + } + + ComVariant(const ComVariant &src) : ComVariant() { copy(&src); } + ComVariant(const VARIANT &src) noexcept : ComVariant() { copy(&src); } + + template<typename T> + ComVariant(const T &value) : ComVariant() + { + assign(value); + } + + ComVariant &operator=(const ComVariant &rhs) noexcept + { + if (this == &rhs) + return *this; + + clear(); + copy(&rhs); + + return *this; + } + + template<typename T> + ComVariant &operator=(const T &rhs) + { + assign(rhs); + return *this; + } + + void clear() + { + const HRESULT hr = ::VariantClear(this); + + Q_ASSERT(hr == S_OK); + Q_UNUSED(hr) + } + + void copy(const VARIANT *src) + { + vt = VT_EMPTY; + const HRESULT hr = ::VariantCopy(this, const_cast<VARIANT *>(src)); + + Q_ASSERT(hr == S_OK); + Q_UNUSED(hr) + } + + bool operator==(const ComVariant &rhs) const + { + auto *lhs = const_cast<tagVARIANT *>(static_cast<const tagVARIANT *>(this)); + auto *other = const_cast<tagVARIANT *>(static_cast<const tagVARIANT *>(&rhs)); + return compare(lhs, other, LOCALE_USER_DEFAULT, 0) == static_cast<HRESULT>(VARCMP_EQ); + } + +private: + template<typename T> + void assign(const T &value) + { + constexpr VARTYPE valueType = ValueType<T>(); + static_assert(valueType != VT_EMPTY, "Invalid type for ComVariant"); + + vt = valueType; + + constexpr auto VARIANT::*field = ValueField<T>(); + if constexpr (valueType == VT_BSTR) + this->*field = ComBstr{ value }.copy(); + else + this->*field = value; + + if constexpr (valueType == VT_UNKNOWN || valueType == VT_DISPATCH) + value->AddRef(); + } + + static HRESULT compare(VARIANT *lhs, VARIANT *rhs, LCID lcid, ULONG flags) + { + // Workaround missing support for VT_I1, VT_UI2, VT_UI4 and VT_UI8 in VarCmp + switch (lhs->vt) { + case VT_I1: + if (lhs->cVal == rhs->cVal) + return VARCMP_EQ; + return lhs->cVal > rhs->cVal ? VARCMP_GT : VARCMP_LT; + case VT_UI2: + if (lhs->uiVal == rhs->uiVal) + return VARCMP_EQ; + return lhs->uiVal > rhs->uiVal ? VARCMP_GT : VARCMP_LT; + case VT_UI4: + if (lhs->uintVal == rhs->uintVal) + return VARCMP_EQ; + return lhs->uintVal > rhs->uintVal ? VARCMP_GT : VARCMP_LT; + case VT_UI8: + if (lhs->ullVal == rhs->ullVal) + return VARCMP_EQ; + return lhs->ullVal > rhs->ullVal ? VARCMP_GT : VARCMP_LT; + } + return ::VarCmp(lhs, rhs, lcid, flags); + } +}; + +#endif diff --git a/tests/auto/conversion/testutil_p.h b/tests/auto/conversion/testutil_p.h new file mode 100644 index 0000000..4521811 --- /dev/null +++ b/tests/auto/conversion/testutil_p.h @@ -0,0 +1,98 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef TESTUTIL_P_H +#define TESTUTIL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qtcore/qt_windows.h> +#include <qtcore/qtglobal> +#include <wrl/client.h> +#include <atomic> + +using Microsoft::WRL::ComPtr; + +template<typename T> +struct ComBase : T +{ + ~ComBase() { Q_ASSERT(m_refCount == 0); } + + ULONG AddRef() final + { + return m_refCount++; + } + + ULONG Release() final + { + const int refCount = --m_refCount; + if (refCount == 0) + delete this; + return refCount; + } + + std::atomic_int m_refCount = 1u; +}; + +struct IUnknownStub : ComBase<IUnknown> +{ + HRESULT QueryInterface(const IID &riid, void **ppvObject) override + { + if (!ppvObject) + return E_POINTER; + + if (riid == IID_IUnknown) { + *ppvObject = this; + return S_OK; + } + + return E_NOINTERFACE; + } +}; + +struct IDispatchStub : ComBase<IDispatch> +{ + HRESULT QueryInterface(const IID &riid, void **ppvObject) override + { + if (!ppvObject) + return E_POINTER; + + if (riid == IID_IUnknown || riid == IID_IDispatch) { + *ppvObject = this; + return S_OK; + } + + return E_NOINTERFACE; + } + + HRESULT GetTypeInfoCount(UINT * /*pctinfo*/) override { return E_NOTIMPL; } + + HRESULT GetTypeInfo(UINT /*iTInfo*/, LCID /*lcid*/, ITypeInfo ** /*ppTInfo*/) override + { + return E_NOTIMPL; + } + + HRESULT GetIDsOfNames(const IID & /*riid*/, LPOLESTR * /*rgszNames*/, UINT /*cNames*/, + LCID /*lcid*/, DISPID * /*rgDispId*/) override + { + return E_NOTIMPL; + } + + HRESULT Invoke(DISPID /*dispIdMember*/, const IID & /*riid*/, LCID /*lcid*/, WORD /*wFlags*/, + DISPPARAMS * /*pDispParams*/, VARIANT * /*pVarResult*/, + EXCEPINFO * /*pExcepInfo*/, UINT * /*puArgErr*/) override + { + return E_NOTIMPL; + } +}; + +#endif diff --git a/tests/auto/conversion/tst_conversion.cpp b/tests/auto/conversion/tst_conversion.cpp index aa08855..61ffb85 100644 --- a/tests/auto/conversion/tst_conversion.cpp +++ b/tests/auto/conversion/tst_conversion.cpp @@ -1,24 +1,25 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +#include "comutil_p.h" +#include "testutil_p.h" + +#include <qaxtypes_p.h> +#include <ActiveQt/qaxobject.h> + #include <QtTest/QtTest> #include <QtCore/QVariant> #include <QtCore/QDateTime> #include <QtCore/QMetaType> #include <qt_windows.h> +#include <wrl/client.h> -QT_BEGIN_NAMESPACE - -// Conversion functions from statically linked library (axtypes.h) -bool QVariantToVARIANT_container(const QVariant &var, VARIANT &arg, - const QByteArray &typeName = QByteArray(), - bool out = false); +using Microsoft::WRL::ComPtr; -QVariant VARIANTToQVariant_container(const VARIANT &arg, const QByteArray &typeName, - int type = 0); +QT_BEGIN_NAMESPACE -QT_END_NAMESPACE +using namespace Qt::StringLiterals; class tst_Conversion : public QObject { @@ -27,6 +28,36 @@ class tst_Conversion : public QObject private slots: void conversion_data(); void conversion(); + + void VARIANTToQVariant_ReturnsBool_WhenCalledWithVariantBool(); + void QVariantToVARIANT_ReturnsVariantBool_WhenCalledWithBool(); + + void VARIANTToQVariant_ReturnsString_WhenCalledWithString_data(); + void VARIANTToQVariant_ReturnsString_WhenCalledWithString(); + + void QVariantToVARIANT_ReturnsString_WhenCalledWithString_data(); + void QVariantToVARIANT_ReturnsString_WhenCalledWithString(); + + void VARIANTToQVariant_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValueOrPointer_data(); + void VARIANTToQVariant_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValueOrPointer(); + + void QVariantToVARIANT_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValue_data(); + void QVariantToVARIANT_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValue(); + + void VARIANTToQVariant_DoesNotIncreaseRefCount_WhenGivenAnIUnknown(); + void QVariantToVARIANT_RecoversIUnknown_WhenQVariantHasIUnknown(); + + void VARIANTToQVariant_DoesNotIncreaseRefCount_WhenGivenAnIDispatch(); + void QVariantToVARIANT_RecoversIDispatch_WhenQVariantHasIDispatch(); + + void VARIANTToQVariant_IncreasesRefCount_WhenCalledWithQVariantTypeName(); + + void ObserveThat_VARIANTToQVariant_ReturnsEmptyQVariant_WhenWrappingIDispatchInQAxObjectPtr(); + void VARIANTToQVariant_CreatesQAxObject_WhenCalledWithMetaTypeId(); + +private: + template<typename T> + static void addScalarMaxValueRow(); }; enum Mode { @@ -145,6 +176,11 @@ void tst_Conversion::conversion_data() << qvar << uint(VT_DATE | VT_BYREF) << typeName << ByReference; QTest::newRow("datetime-out") << qvar << uint(VT_DATE | VT_BYREF) << typeName << OutParameter; + + // QTBUG-122762; do not create a 2-dimensional array from a string (sequence). + qvar = QVariant(QVariantList{QVariant(QString("test"_L1)), QVariant(42)}); + QTest::newRow("list") + << qvar << uint(VT_VARIANT | VT_ARRAY | VT_BYREF) << typeName << OutParameter; } void tst_Conversion::conversion() @@ -170,5 +206,267 @@ void tst_Conversion::conversion() delete variant.pullVal; } +void tst_Conversion::VARIANTToQVariant_ReturnsBool_WhenCalledWithVariantBool() +{ + { + const ComVariant v = true; + const QVariant result = VARIANTToQVariant(v, "canBeAnything"); + QVERIFY(result == true); + } + + { + const ComVariant v = false; + const QVariant result = VARIANTToQVariant(v, "canBeAnything"); + QVERIFY(result == false); + } +} + +void tst_Conversion::QVariantToVARIANT_ReturnsVariantBool_WhenCalledWithBool() +{ + { + const QVariant v = true; + ComVariant result; + QVERIFY(QVariantToVARIANT(v, result)); + QVERIFY(result.vt == VT_BOOL); + QVERIFY(result.boolVal == VARIANT_TRUE); + } + + { + const QVariant v = false; + ComVariant result; + QVERIFY(QVariantToVARIANT(v, result)); + QVERIFY(result.vt == VT_BOOL); + QVERIFY(result.boolVal == VARIANT_FALSE); + } +} + +void tst_Conversion::VARIANTToQVariant_ReturnsString_WhenCalledWithString_data() +{ + QTest::addColumn<QString>("text"); + QTest::newRow("empty") << QString{ "" }; + QTest::newRow("nonempty") << QString{ "Some Latin 1 text" }; +} + +void tst_Conversion::VARIANTToQVariant_ReturnsString_WhenCalledWithString() +{ + QFETCH(QString, text); + + const ComVariant comVariant = text.toStdWString().c_str(); + const QVariant actual = VARIANTToQVariant(comVariant, {}); + + QCOMPARE(actual, text); +} + +void tst_Conversion::QVariantToVARIANT_ReturnsString_WhenCalledWithString_data() +{ + QTest::addColumn<QString>("text"); + QTest::newRow("empty") << QString{ "" }; + QTest::newRow("nonempty") << QString{ "Some Latin 1 text" }; +} + +void tst_Conversion::QVariantToVARIANT_ReturnsString_WhenCalledWithString() +{ + QFETCH(QString, text); + + ComVariant comVariant; + QVERIFY(QVariantToVARIANT(text, comVariant)); + + const QString actual = QString::fromWCharArray(comVariant.bstrVal); + + QCOMPARE(actual, text); +} + +void tst_Conversion:: + VARIANTToQVariant_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValueOrPointer_data() +{ + QTest::addColumn<ComVariant>("comVariant"); + QTest::addColumn<QVariant>("qvariant"); + + addScalarMaxValueRow<char>(); + addScalarMaxValueRow<unsigned char>(); + addScalarMaxValueRow<short>(); + addScalarMaxValueRow<unsigned short>(); + addScalarMaxValueRow<int>(); + addScalarMaxValueRow<unsigned int>(); + addScalarMaxValueRow<long long>(); + addScalarMaxValueRow<unsigned long long>(); + addScalarMaxValueRow<float>(); + addScalarMaxValueRow<double>(); + + addScalarMaxValueRow<char *>(); + addScalarMaxValueRow<unsigned char *>(); + addScalarMaxValueRow<short *>(); + addScalarMaxValueRow<unsigned short *>(); + addScalarMaxValueRow<int *>(); + addScalarMaxValueRow<unsigned int *>(); + addScalarMaxValueRow<long long *>(); + addScalarMaxValueRow<unsigned long long *>(); + addScalarMaxValueRow<float *>(); + addScalarMaxValueRow<double *>(); +} + +void tst_Conversion::VARIANTToQVariant_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValueOrPointer() +{ + QFETCH(ComVariant, comVariant); + QFETCH(QVariant, qvariant); + + const QVariant actual = VARIANTToQVariant(comVariant, qvariant.typeName()); + + QCOMPARE(actual, qvariant); +} + +void tst_Conversion::QVariantToVARIANT_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValue_data() +{ + QTest::addColumn<ComVariant>("comVariant"); + QTest::addColumn<QVariant>("qvariant"); + + addScalarMaxValueRow<int>(); + addScalarMaxValueRow<unsigned int>(); + addScalarMaxValueRow<long long>(); + addScalarMaxValueRow<unsigned long long>(); + addScalarMaxValueRow<float>(); + addScalarMaxValueRow<double>(); +} + +void tst_Conversion::QVariantToVARIANT_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValue() +{ + QFETCH(ComVariant, comVariant); + QFETCH(QVariant, qvariant); + + ComVariant actual; + QVERIFY(QVariantToVARIANT(qvariant, actual)); + + QCOMPARE(actual, comVariant); +} + +void tst_Conversion::VARIANTToQVariant_DoesNotIncreaseRefCount_WhenGivenAnIUnknown() +{ + const auto stub = makeComObject<IUnknownStub>(); + + const ComVariant value = stub.Get(); + + QVERIFY(stub->m_refCount == 2u); + + const QVariant qVariant = VARIANTToQVariant(value, {}); + + QVERIFY(stub->m_refCount == 2u); + + Q_UNUSED(qVariant); +} + +void tst_Conversion::QVariantToVARIANT_RecoversIUnknown_WhenQVariantHasIUnknown() +{ + const auto stub = makeComObject<IUnknownStub>(); + const ComVariant value = stub.Get(); + + const QVariant qvar = VARIANTToQVariant(value, {}); + + ComVariant comVariant; + QVERIFY(QVariantToVARIANT(qvar, comVariant)); + + QCOMPARE(stub->m_refCount, 3u); + + const ComPtr<IUnknown> recovered = comVariant.punkVal; + + QCOMPARE(recovered, stub); +} + +void tst_Conversion::VARIANTToQVariant_DoesNotIncreaseRefCount_WhenGivenAnIDispatch() +{ + const auto stub = makeComObject<IDispatchStub>(); + + const ComVariant value = stub.Get(); + + QCOMPARE(stub->m_refCount, 2u); + const QVariant qVariant = VARIANTToQVariant(value, "IDispatch*"); + + QCOMPARE(stub->m_refCount, 2u); + + Q_UNUSED(qVariant); +} + +struct IDispatchFixture +{ + const ComPtr<IDispatchStub> m_iDispatchStub = makeComObject<IDispatchStub>(); + const ComVariant m_comVariant = m_iDispatchStub.Get(); + const QVariant m_qVariant = VARIANTToQVariant(m_comVariant, "IDispatch*"); +}; + +void tst_Conversion::QVariantToVARIANT_RecoversIDispatch_WhenQVariantHasIDispatch() +{ + const IDispatchFixture testFixture; + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 2u); + + ComVariant comVariant; + QVERIFY(QVariantToVARIANT(testFixture.m_qVariant, comVariant)); + + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 3u); + + const ComPtr<IUnknown> recovered = comVariant.pdispVal; + + QCOMPARE(recovered, testFixture.m_iDispatchStub); +} + +void tst_Conversion::VARIANTToQVariant_IncreasesRefCount_WhenCalledWithQVariantTypeName() +{ + const IDispatchFixture testFixture; + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 2u); + + QVariant qVariant = VARIANTToQVariant(testFixture.m_comVariant, "QVariant"); + qVariant = {}; + + // Observe that IDispatch interface is leaked here, since + // the QVariant destructor does not decrement the refcount + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 3u); + + // Workaround to ensure cleanup + testFixture.m_iDispatchStub->Release(); +} + +void tst_Conversion::ObserveThat_VARIANTToQVariant_ReturnsEmptyQVariant_WhenWrappingIDispatchInQAxObjectPtr() +{ + const IDispatchFixture testFixture; + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 2u); + + qRegisterMetaType<QAxObject *>("QAxObject*"); + qRegisterMetaType<QAxObject>("QAxObject"); + + const QVariant qVariant = VARIANTToQVariant(testFixture.m_comVariant, "QAxObject*"); + QVERIFY(qVariant.isNull()); +} + +void tst_Conversion::VARIANTToQVariant_CreatesQAxObject_WhenCalledWithMetaTypeId() +{ + const IDispatchFixture testFixture; + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 2u); + + qRegisterMetaType<QAxObject *>("QAxObject*"); + qRegisterMetaType<QAxObject>("QAxObject"); + + const QVariant qVariant = VARIANTToQVariant(testFixture.m_comVariant, "QAxObject*", QMetaType::fromType<QAxObject*>().id()); + + QAxObject *recovered = qVariant.value<QAxObject *>(); + QVERIFY(recovered != nullptr); +} + +template<typename T> +void tst_Conversion::addScalarMaxValueRow() +{ + using ValueType = std::remove_pointer_t<T>; + static ValueType v = std::numeric_limits<ValueType>::max(); + + ComVariant comVariant; + if constexpr (std::is_pointer_v<T>) + comVariant = &v; + else + comVariant = v; + + const char *typeName = QMetaType::fromType<T>().name(); + QTest::newRow(typeName) << comVariant << QVariant{ v }; +} + QTEST_MAIN(tst_Conversion) + +QT_END_NAMESPACE + #include "tst_conversion.moc" diff --git a/tests/auto/dumpcpp/CMakeLists.txt b/tests/auto/dumpcpp/CMakeLists.txt index 85cdfe1..a5ff2dc 100644 --- a/tests/auto/dumpcpp/CMakeLists.txt +++ b/tests/auto/dumpcpp/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from dumpcpp.pro. - ##################################################################### ## tst_dumpcpp Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_dumpcpp LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_dumpcpp SOURCES tst_dumpcpp.cpp @@ -16,10 +20,5 @@ qt_internal_add_test(tst_dumpcpp Qt::Widgets ) -#### Keys ignored in scope 1:.:.:dumpcpp.pro:<TRUE>: -# TYPELIBS = "$$(SystemRoot)\\system32\\ieframe.dll" - -qt6_target_typelibs(tst_dumpcpp LIBRARIES "ieframe.dll") # special case - -## Scopes: -##################################################################### +qt6_target_typelibs(tst_dumpcpp LIBRARIES "ieframe.dll") +qt6_target_typelibs(tst_dumpcpp LIBRARIES "msxml6.dll") diff --git a/tests/auto/dumpcpp/tst_dumpcpp.cpp b/tests/auto/dumpcpp/tst_dumpcpp.cpp index 2519000..aad0e51 100644 --- a/tests/auto/dumpcpp/tst_dumpcpp.cpp +++ b/tests/auto/dumpcpp/tst_dumpcpp.cpp @@ -3,20 +3,53 @@ #include <QtTest/QtTest> #include "ieframe.h" // generated header +#include "msxml6.h" // generated header #include <QApplication> + +struct XmlFixture +{ + MSXML2::DOMDocument60 doc; + MSXML2::IXMLDOMNodeList *root; + + const QString xml{ + R"( + <root prop="The root property"> + The value + </root> + )" }; +}; + class tst_dumpcpp : public QObject { Q_OBJECT private slots: + void init(); void toggleAddressBar(); + void propertyGetter_ReturnsValue_WhenValueIsInt(); + void propertyGetter_ReturnsValue_WhenValueIsString(); + void invokeGetter_ReturnsValue_WhenValueInheritsIDispatch(); + void propertyGetter_ReturnsValue_WhenValueInheritsIDispatch(); + + void propertySetter_SetsValue_WhenValueIsVariantInt(); + void propertySetter_SetsValue_WhenValueIsString(); + void invoke_SetsValue_WhenValueDerivesFromIDispatch(); + +private: + XmlFixture m_xml; }; +void tst_dumpcpp::init() +{ + m_xml.doc.loadXML(m_xml.xml); + m_xml.root = m_xml.doc.childNodes(); +} + // A simple test to verify that an object can be instantiated and interacted with void tst_dumpcpp::toggleAddressBar() { - SHDocVw::WebBrowser* webBrowser = new SHDocVw::WebBrowser; + SHDocVw::WebBrowser *webBrowser = new SHDocVw::WebBrowser; QVERIFY(webBrowser); bool addressBar = webBrowser->AddressBar(); addressBar = !addressBar; @@ -25,5 +58,60 @@ void tst_dumpcpp::toggleAddressBar() delete webBrowser; } +void tst_dumpcpp::propertyGetter_ReturnsValue_WhenValueIsInt() +{ + int length = m_xml.root->length(); + QVERIFY(length == 1); +} + +void tst_dumpcpp::invokeGetter_ReturnsValue_WhenValueInheritsIDispatch() +{ + // item(...) takes an argument and is called as a function invocation + MSXML2::IXMLDOMNode *firstChild = m_xml.root->item(0); + QVERIFY(firstChild); +} + +void tst_dumpcpp::propertyGetter_ReturnsValue_WhenValueInheritsIDispatch() +{ + // attributes() takes an argument and is called as property getter + MSXML2::IXMLDOMNamedNodeMap *attributes = m_xml.root->item(0)->attributes(); + QVERIFY(attributes); +} + +void tst_dumpcpp::propertyGetter_ReturnsValue_WhenValueIsString() +{ + MSXML2::IXMLDOMNamedNodeMap *attributes = m_xml.root->item(0)->attributes(); + + // nodeValue is a property getter + QVariant p = attributes->getNamedItem("prop")->nodeValue(); + QCOMPARE(p, "The root property"); +} + +void tst_dumpcpp::propertySetter_SetsValue_WhenValueIsVariantInt() +{ + MSXML2::IXMLDOMNamedNodeMap *attributes = m_xml.root->item(0)->attributes(); + MSXML2::IXMLDOMNode *attribNode = attributes->item(0); + attribNode->setNodeValue(QVariant { 42 } ); + + QVariant p = attributes->getNamedItem("prop")->nodeValue(); + QCOMPARE(p, 42); +} + +void tst_dumpcpp::propertySetter_SetsValue_WhenValueIsString() +{ + m_xml.root->item(0)->setText("The new value"); + QCOMPARE(m_xml.root->item(0)->text(), "The new value"); +} + +void tst_dumpcpp::invoke_SetsValue_WhenValueDerivesFromIDispatch() +{ + MSXML2::IXMLDOMNode *node = m_xml.doc.createNode(MSXML2::NODE_ELEMENT, "sometag", ""); + node->setText("The new text"); + + m_xml.root->item(0)->appendChild(node); + + QCOMPARE(m_xml.root->item(0)->childNodes()->item(1)->text(), "The new text"); +} + QTEST_MAIN(tst_dumpcpp) #include "tst_dumpcpp.moc" diff --git a/tests/auto/qaxobject/CMakeLists.txt b/tests/auto/qaxobject/CMakeLists.txt index b94a9e0..87fe2e1 100644 --- a/tests/auto/qaxobject/CMakeLists.txt +++ b/tests/auto/qaxobject/CMakeLists.txt @@ -1,13 +1,17 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qaxobject.pro. - ##################################################################### -## qaxobject Test: +## QAxObject Test: ##################################################################### -qt_internal_add_test(qaxobject # special case +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qaxobject LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qaxobject SOURCES tst_qaxobject.cpp LIBRARIES diff --git a/tests/auto/qaxscript/CMakeLists.txt b/tests/auto/qaxscript/CMakeLists.txt index 95746a7..351ab2f 100644 --- a/tests/auto/qaxscript/CMakeLists.txt +++ b/tests/auto/qaxscript/CMakeLists.txt @@ -1,13 +1,17 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qaxscript.pro. - ##################################################################### -## qaxscript Test: +## tst_QAxScript Test: ##################################################################### -qt_internal_add_test(qaxscript # special case +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qaxscript LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qaxscript SOURCES tst_qaxscript.cpp LIBRARIES diff --git a/tests/auto/qaxscript/tst_qaxscript.cpp b/tests/auto/qaxscript/tst_qaxscript.cpp index 9617087..4134b2d 100644 --- a/tests/auto/qaxscript/tst_qaxscript.cpp +++ b/tests/auto/qaxscript/tst_qaxscript.cpp @@ -6,27 +6,157 @@ #include <QAxScriptManager> #include <QAxScript> +using namespace Qt::StringLiterals; + class tst_QAxScript : public QObject { Q_OBJECT private slots: + void call(); void scriptReturnValue(); + void scriptOutParameters(); + void error_data(); + void error(); }; +void tst_QAxScript::call() +{ + QAxScriptManager scriptManager; + const auto scriptCode_js = uR"JS( + function test1() { + return 'JScript'; + } + )JS"_s; + const auto scriptCode_vb = uR"VB( + Function test2() + test2 = "VBScript" + End Function + )VB"_s; + QAxScript *jsscript = scriptManager.load(scriptCode_js, u"JS"_s, u"JScript"_s); + QVERIFY2(jsscript, "Unable to load script (CoInitializeEx() called?)"); + QVERIFY(jsscript->scriptEngine()->hasIntrospection()); + QAxScript *vbscript = scriptManager.load(scriptCode_vb, u"VB"_s, u"VBScript"_s); + QVERIFY2(vbscript, "Unable to load script (CoInitializeEx() called?)"); + QVERIFY(vbscript->scriptEngine()->hasIntrospection()); + + QCOMPARE(jsscript->call("test1()"), "JScript"); + QTest::ignoreMessage(QtWarningMsg, "QAxBase::dynamicCallHelper: test1(): No such method in [unknown]"); + QTest::ignoreMessage(QtWarningMsg, "\tCandidates are:"); + QCOMPARE(vbscript->call("test1()"), QVariant()); + QCOMPARE(vbscript->call("test2()"), "VBScript"); + QTest::ignoreMessage(QtWarningMsg, "QAxBase::dynamicCallHelper: test2(): No such method in [unknown]"); + QTest::ignoreMessage(QtWarningMsg, "\tCandidates are:"); + QCOMPARE(jsscript->call("test2()"), QVariant()); +} + void tst_QAxScript::scriptReturnValue() { QAxScriptManager scriptManager; - const char scriptCode[] = - "function foo() {\n" - " return 'test';\n" - "}\n"; // QTBUG-42289, fails when DISPATCH_PROPERTYGET is used. - QAxScript *script = scriptManager.load(QLatin1String(scriptCode), - QStringLiteral("Test"), - QStringLiteral("JScript")); + const auto scriptCode = uR"JS( + function foo() { + return 'test'; + } + )JS"_s; // QTBUG-42289, fails when DISPATCH_PROPERTYGET is used. + QAxScript *script = scriptManager.load(scriptCode, u"Test"_s, u"JScript"_s); QVERIFY2(script, "Unable to load script (CoInitializeEx() called?)"); const QVariant result = script->call("foo()"); - QCOMPARE(result, QVariant(QStringLiteral("test"))); + QCOMPARE(result, QVariant(u"test"_s)); +} + +void tst_QAxScript::scriptOutParameters() +{ + QAxScriptManager scriptManager; + const auto scriptCode = uR"VB( + Function GetProductName(ByRef manufacturer, ByRef name, ByRef version) + manufacturer = "The Qt Company" + name = "ActiveQt" + version = 650 + On Error Resume Next + GetProductName = 42 + End Function + )VB"_s; + + QAxScript *script = scriptManager.load(scriptCode, u"Test"_s, u"VBScript"_s); + QVERIFY2(script, "Unable to load script (CoInitializeEx() called?)"); + + QVariant returnValue; + QList<QVariant> results = {{}, {}, {}}; + + returnValue = script->scriptEngine()->dynamicCall("GetProductName(QVariant&,QVariant&,QVariant&)", results); + QCOMPARE(returnValue, 42); + QCOMPARE(results.size(), 3); + QCOMPARE(results.at(0), "The Qt Company"); + QCOMPARE(results.at(1), "ActiveQt"); + QCOMPARE(results.at(2), 650); + + results = {{}, {}, {}}; + returnValue = script->call("GetProductName(QVariant&,QVariant&,QVariant&)", results); + QCOMPARE(returnValue, 42); + QCOMPARE(results.size(), 3); + QCOMPARE(results.at(0), "The Qt Company"); + QCOMPARE(results.at(1), "ActiveQt"); + QCOMPARE(results.at(2), 650); +} + +void tst_QAxScript::error_data() +{ + QTest::addColumn<QString>("scriptCode"); + QTest::addColumn<QString>("language"); + QTest::addColumn<int>("expectedErrorCode"); + QTest::addColumn<QString>("expectedDescription"); + QTest::addColumn<int>("expectedSourcePosition"); + QTest::addColumn<QString>("expectedSourceText"); + + QTest::addRow("JS syntax error") + << "function foo {}" + << "JScript" + << 0 << "Expected '('" << 0 << "function foo {}"; + + QTest::addRow("VB syntax error") + << "Funktion test" + << "VBScript" + << 0 << "Type mismatch: 'Funktion'" << 0 << ""; +} + +void tst_QAxScript::error() +{ + QFETCH(QString, scriptCode); + QFETCH(QString, language); + QFETCH(int, expectedErrorCode); + QFETCH(QString, expectedDescription); + QFETCH(int, expectedSourcePosition); + QFETCH(QString, expectedSourceText); + + QAxScriptManager scriptManager; + QAxScript script(u"Test"_s, &scriptManager); + + QAxScript *actualScript = nullptr; + int actualCode; + QString actualDescription; + int actualSourcePosition; + QString actualSourceText; + + connect(&scriptManager, &QAxScriptManager::error, + this, [&](QAxScript *script){ + actualScript = script; + }); + + connect(&script, &QAxScript::error, + this, [&](int code, const QString &description, int sourcePosition, const QString &sourceText){ + actualCode = code; + actualDescription = description; + actualSourcePosition = sourcePosition; + actualSourceText = sourceText.trimmed(); + }); + + script.load(scriptCode, language); + + QCOMPARE(actualScript, &script); + QCOMPARE(actualCode, expectedErrorCode); + QCOMPARE(actualDescription, expectedDescription); + QCOMPARE(actualSourcePosition, expectedSourcePosition); + QCOMPARE(actualSourceText, expectedSourceText); } QTEST_MAIN(tst_QAxScript) diff --git a/tests/auto/qaxscriptmanager/CMakeLists.txt b/tests/auto/qaxscriptmanager/CMakeLists.txt new file mode 100644 index 0000000..37b83ab --- /dev/null +++ b/tests/auto/qaxscriptmanager/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## QAxScriptManager Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qaxscriptmanager LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qaxscriptmanager + SOURCES + tst_qaxscriptmanager.cpp + LIBRARIES + Qt::AxContainer +) diff --git a/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp b/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp new file mode 100644 index 0000000..5c92bdf --- /dev/null +++ b/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp @@ -0,0 +1,188 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + + +#include <QtTest/QtTest> +#include <QAxScriptManager> +#include <QAxScript> + +using namespace Qt::StringLiterals; + +class tst_QAxScriptManager : public QObject +{ + Q_OBJECT + +public: + struct Script { + QString language; + QString name; + QString code; + }; + +private slots: + void functions_data(); + void functions(); + + void scriptNames_data(); + void scriptNames(); + + void script_data(); + void script(); + + void call_data(); + void call(); +}; + +void tst_QAxScriptManager::functions_data() +{ + const auto scriptCode_js = Script{u"JScript"_s, u"test1"_s, uR"JS( + function js1() { + return 'JScript 1'; + } + function js2(value) { + return 'JScript 2'; + } + )JS"_s}; + const auto scriptCode_vb = Script{u"VBScript"_s, u"test2"_s, uR"VB( + Function vb1() + vb1 = "VBScript 1" + End Function + + Function vb2(value) + vb2 = "VBScript 2" + End Function + )VB"_s}; + + QTest::addColumn<QList<Script>>("scripts"); + QTest::addColumn<QStringList>("functions"); + QTest::addColumn<QStringList>("signatures"); + + QTest::addRow("js") << QList{scriptCode_js} + << QStringList{"js1", "js2"} + << QStringList{"js1()", "js2(QVariant)"}; + QTest::addRow("vb") << QList{scriptCode_vb} + << QStringList{"vb1", "vb2"} + << QStringList{"vb1()", "vb2(QVariant)"}; + QTest::addRow("both") << QList{scriptCode_js, scriptCode_vb} + << QStringList{"js1", "js2", "vb1", "vb2"} + << QStringList{"js1()", "js2(QVariant)", "vb1()", "vb2(QVariant)"}; +} + +void tst_QAxScriptManager::functions() +{ + // QStringList functions(QAxScript::FunctionFlags = QAxScript::FunctionNames) const; + + QFETCH(QList<Script>, scripts); + QFETCH(QStringList, functions); + QFETCH(QStringList, signatures); + + QAxScriptManager scriptManager; + for (const auto &script : scripts) { + QVERIFY2(scriptManager.load(script.code, script.name, script.language), + "Unable to load script (CoInitializeEx() called?)"); + } + functions.sort(); + QStringList actualFunctions = scriptManager.functions(); + actualFunctions.sort(); + QCOMPARE(actualFunctions, functions); + + QStringList actualSignatures = scriptManager.functions(QAxScript::FunctionSignatures); + actualSignatures.sort(); + QCOMPARE(actualSignatures, signatures); +} + +void tst_QAxScriptManager::scriptNames_data() +{ + functions_data(); +} + +void tst_QAxScriptManager::scriptNames() +{ + // QStringList scriptNames() const; + QFETCH(QList<Script>, scripts); + QFETCH(QStringList, functions); + + QAxScriptManager scriptManager; + QStringList expectedNames; + for (const auto &script : scripts) { + expectedNames << script.name; + QVERIFY2(scriptManager.load(script.code, script.name, script.language), + "Unable to load script (CoInitializeEx() called?)"); + } + expectedNames.sort(); + QStringList actualNames = scriptManager.scriptNames(); + actualNames.sort(); + QCOMPARE(actualNames, expectedNames); +} + +void tst_QAxScriptManager::script_data() +{ + functions_data(); +} + +void tst_QAxScriptManager::script() +{ + QFETCH(QList<Script>, scripts); + QFETCH(QStringList, functions); + + QAxScriptManager scriptManager; + QStringList expectedNames; + for (const auto &script : scripts) { + expectedNames << script.name; + QVERIFY2(scriptManager.load(script.code, script.name, script.language), + "Unable to load script (CoInitializeEx() called?)"); + } + + for (const auto &script : scripts) { + QAxScript *axscript = scriptManager.script(script.name); + QVERIFY(axscript); + QVERIFY(axscript->scriptEngine()); + QVERIFY(axscript->scriptEngine()->isValid()); + const auto scriptFunctions = axscript->functions(); + for (const auto &scriptFunction : scriptFunctions) { + auto index = functions.indexOf(scriptFunction); + QCOMPARE_NE(index, -1); + functions.remove(index); + } + + QCOMPARE(axscript->scriptEngine()->scriptLanguage(), script.language); + } + + // verify that all functions were found across the different QAxScript objects + QVERIFY(functions.isEmpty()); +} + +void tst_QAxScriptManager::call_data() +{ + functions_data(); +} + +void tst_QAxScriptManager::call() +{ + QFETCH(QList<Script>, scripts); + QFETCH(QStringList, functions); + QFETCH(QStringList, signatures); + + QAxScriptManager scriptManager; + for (const auto &script : scripts) { + QAxScript *axScript = scriptManager.load(script.code, script.name, script.language); + + QVERIFY2(axScript, "Unable to load script (CoInitializeEx() called?)"); + QVERIFY(axScript->scriptEngine()); + QVERIFY(axScript->scriptEngine()->hasIntrospection()); + } + + // QAxScriptManager::call finds the script based on function name... + for (const auto &function : std::as_const(functions)) { + QVariant result = scriptManager.call(function); + QCOMPARE(result.metaType(), QMetaType::fromType<QString>()); + } + // ...or fully qualified function signature + for (const auto &function : std::as_const(signatures)) { + QVariant result = scriptManager.call(function); + QCOMPARE(result.metaType(), QMetaType::fromType<QString>()); + } +} + +QTEST_MAIN(tst_QAxScriptManager) +#include "tst_qaxscriptmanager.moc" diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt index 1cdb27f..f911543 100644 --- a/tests/manual/CMakeLists.txt +++ b/tests/manual/CMakeLists.txt @@ -1,8 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from manual.pro. - add_subdirectory(axviewer) add_subdirectory(dumpcpp) +add_subdirectory(hierarchy) +add_subdirectory(mediaplayer) +add_subdirectory(menus) +add_subdirectory(multiple) +add_subdirectory(opengl) add_subdirectory(testcontrol) diff --git a/tests/manual/axviewer/CMakeLists.txt b/tests/manual/axviewer/CMakeLists.txt index bb769f9..22f8f3a 100644 --- a/tests/manual/axviewer/CMakeLists.txt +++ b/tests/manual/axviewer/CMakeLists.txt @@ -1,13 +1,12 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from axviewer.pro. ##################################################################### ## axviewer Binary: ##################################################################### -qt_internal_add_manual_test(tst_axviewer_manual # special case +qt_internal_add_manual_test(tst_axviewer_manual SOURCES ../shared/metaobjectdump.cpp ../shared/metaobjectdump.h ../shared/textdialog.cpp ../shared/textdialog.h @@ -20,14 +19,9 @@ qt_internal_add_manual_test(tst_axviewer_manual # special case Qt::Widgets ) -#### Keys ignored in scope 1:.:.:axviewer.pro:<TRUE>: -# DIAGLIB = "../../../../qtbase/tests/manual/diaglib" -# TEMPLATE = "app" - ## Scopes: ##################################################################### -# special case begin set(diaglib_path "${CMAKE_CURRENT_SOURCE_DIR}/../../../../qtbase/tests/manual/diaglib") qt_internal_extend_target(tst_axviewer_manual CONDITION EXISTS "${diaglib_path}" SOURCES @@ -74,4 +68,3 @@ qt_internal_extend_target(tst_axviewer_manual CONDITION (EXISTS "${diaglib_path} Qt::OpenGL Qt::OpenGLWidgets ) -# special case end diff --git a/tests/manual/dumpcpp/CMakeLists.txt b/tests/manual/dumpcpp/CMakeLists.txt index d0ba74e..e9ffc1a 100644 --- a/tests/manual/dumpcpp/CMakeLists.txt +++ b/tests/manual/dumpcpp/CMakeLists.txt @@ -1,13 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from dumpcpp.pro. - ##################################################################### ## dumpcpp Binary: ##################################################################### -qt_internal_add_manual_test(tst_dumpcpp_manual # special case +qt_internal_add_manual_test(tst_dumpcpp_manual SOURCES ../shared/metaobjectdump.cpp ../shared/metaobjectdump.h ../shared/textdialog.cpp ../shared/textdialog.h @@ -21,11 +19,4 @@ qt_internal_add_manual_test(tst_dumpcpp_manual # special case Qt::Widgets ) -#### Keys ignored in scope 1:.:.:dumpcpp.pro:<TRUE>: -# TEMPLATE = "app" -# TYPELIBS = "$$(SystemRoot)\\system32\\ieframe.dll" - -qt6_target_typelibs(tst_dumpcpp_manual LIBRARIES "ieframe.dll") # special case - -## Scopes: -##################################################################### +qt6_target_typelibs(tst_dumpcpp_manual LIBRARIES "ieframe.dll") diff --git a/tests/manual/hierarchy/CMakeLists.txt b/tests/manual/hierarchy/CMakeLists.txt new file mode 100644 index 0000000..3db0a0e --- /dev/null +++ b/tests/manual/hierarchy/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## hierarchy Library: +##################################################################### + +set(CMAKE_AUTOMOC ON) + +qt_internal_add_manual_test(tst_hierarchy + GUI + SOURCES + main.cpp + objects.cpp objects.h + hierarchy.def + hierarchy.rc + LIBRARIES + Qt::AxServer + Qt::Gui + Qt::Widgets +) + +qt_disable_warnings(tst_hierarchy) +qt6_target_idl(tst_hierarchy) diff --git a/examples/activeqt/hierarchy/doc/snippets/hierarchy-demo-snippet.qdoc b/tests/manual/hierarchy/doc/snippets/hierarchy-demo-snippet.qdoc index 9b14316..9b14316 100644 --- a/examples/activeqt/hierarchy/doc/snippets/hierarchy-demo-snippet.qdoc +++ b/tests/manual/hierarchy/doc/snippets/hierarchy-demo-snippet.qdoc diff --git a/examples/activeqt/hierarchy/doc/src/hierarchy.qdoc b/tests/manual/hierarchy/doc/src/hierarchy.qdoc index bc1c6e5..fbfaca9 100644 --- a/examples/activeqt/hierarchy/doc/src/hierarchy.qdoc +++ b/tests/manual/hierarchy/doc/src/hierarchy.qdoc @@ -11,6 +11,7 @@ /*! \example activeqt/hierarchy \title Hierarchy Example (ActiveQt) + \ingroup activeqt-examples \brief The Hierarchy example is shows how to write an in-process ActiveX control. The control is a QWidget subclass with child widgets diff --git a/examples/activeqt/hierarchy/hierarchy.def b/tests/manual/hierarchy/hierarchy.def index bc82a03..bc82a03 100644 --- a/examples/activeqt/hierarchy/hierarchy.def +++ b/tests/manual/hierarchy/hierarchy.def diff --git a/examples/activeqt/hierarchy/hierarchy.ico b/tests/manual/hierarchy/hierarchy.ico Binary files differindex c80d36a..c80d36a 100644 --- a/examples/activeqt/hierarchy/hierarchy.ico +++ b/tests/manual/hierarchy/hierarchy.ico diff --git a/examples/activeqt/hierarchy/hierarchy.inf b/tests/manual/hierarchy/hierarchy.inf index cb7e90f..cb7e90f 100644 --- a/examples/activeqt/hierarchy/hierarchy.inf +++ b/tests/manual/hierarchy/hierarchy.inf diff --git a/examples/activeqt/hierarchy/hierarchy.pro b/tests/manual/hierarchy/hierarchy.pro index acc108a..acc108a 100644 --- a/examples/activeqt/hierarchy/hierarchy.pro +++ b/tests/manual/hierarchy/hierarchy.pro diff --git a/examples/activeqt/hierarchy/hierarchy.rc b/tests/manual/hierarchy/hierarchy.rc index 70eb503..70eb503 100644 --- a/examples/activeqt/hierarchy/hierarchy.rc +++ b/tests/manual/hierarchy/hierarchy.rc diff --git a/examples/activeqt/hierarchy/main.cpp b/tests/manual/hierarchy/main.cpp index 5ebe6e8..5ebe6e8 100644 --- a/examples/activeqt/hierarchy/main.cpp +++ b/tests/manual/hierarchy/main.cpp diff --git a/examples/activeqt/hierarchy/objects.cpp b/tests/manual/hierarchy/objects.cpp index 6dfda44..6dfda44 100644 --- a/examples/activeqt/hierarchy/objects.cpp +++ b/tests/manual/hierarchy/objects.cpp diff --git a/examples/activeqt/hierarchy/objects.h b/tests/manual/hierarchy/objects.h index 6b8bea6..6b8bea6 100644 --- a/examples/activeqt/hierarchy/objects.h +++ b/tests/manual/hierarchy/objects.h diff --git a/tests/manual/mediaplayer/CMakeLists.txt b/tests/manual/mediaplayer/CMakeLists.txt new file mode 100644 index 0000000..6f443e7 --- /dev/null +++ b/tests/manual/mediaplayer/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## mediaplayer Binary: +##################################################################### + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) + +qt_internal_add_manual_test(tst_mediaplayer + SOURCES + mainwindow.ui + mediaaxwidget.h + main.cpp + INCLUDE_DIRECTORIES + ../shared + LIBRARIES + Qt::AxContainer + Qt::Core + Qt::Gui + Qt::Widgets +) + +set_target_properties(tst_mediaplayer PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) diff --git a/examples/activeqt/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg b/tests/manual/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg Binary files differindex 4839242..4839242 100644 --- a/examples/activeqt/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg +++ b/tests/manual/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg diff --git a/examples/activeqt/mediaplayer/doc/src/mediaplayer.qdoc b/tests/manual/mediaplayer/doc/src/mediaplayer.qdoc index 02b6977..e6cd19b 100644 --- a/examples/activeqt/mediaplayer/doc/src/mediaplayer.qdoc +++ b/tests/manual/mediaplayer/doc/src/mediaplayer.qdoc @@ -4,6 +4,7 @@ /*! \example activeqt/mediaplayer \title Media Player Example (ActiveQt) + \ingroup activeqt-examples \brief The Media Player example uses the Microsoft Media Player ActiveX control to implement a functional media player application. diff --git a/examples/activeqt/mediaplayer/main.cpp b/tests/manual/mediaplayer/main.cpp index bedb97f..bedb97f 100644 --- a/examples/activeqt/mediaplayer/main.cpp +++ b/tests/manual/mediaplayer/main.cpp diff --git a/examples/activeqt/mediaplayer/mainwindow.ui b/tests/manual/mediaplayer/mainwindow.ui index b83d392..b83d392 100644 --- a/examples/activeqt/mediaplayer/mainwindow.ui +++ b/tests/manual/mediaplayer/mainwindow.ui diff --git a/examples/activeqt/mediaplayer/mediaaxwidget.h b/tests/manual/mediaplayer/mediaaxwidget.h index 3a49b61..3a49b61 100644 --- a/examples/activeqt/mediaplayer/mediaaxwidget.h +++ b/tests/manual/mediaplayer/mediaaxwidget.h diff --git a/examples/activeqt/mediaplayer/mediaplayer.pro b/tests/manual/mediaplayer/mediaplayer.pro index ad787a3..ad787a3 100644 --- a/examples/activeqt/mediaplayer/mediaplayer.pro +++ b/tests/manual/mediaplayer/mediaplayer.pro diff --git a/tests/manual/menus/CMakeLists.txt b/tests/manual/menus/CMakeLists.txt new file mode 100644 index 0000000..a8b3899 --- /dev/null +++ b/tests/manual/menus/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## menus Executable: +##################################################################### + +set(CMAKE_AUTOMOC ON) + +qt_internal_add_manual_test(tst_menus + GUI + SOURCES + main.cpp + menus.cpp menus.h + menus.def + menus.rc + LIBRARIES + Qt::AxServer + Qt::Core + Qt::Gui + Qt::Widgets +) + +qt_disable_warnings(tst_menus) +qt6_target_idl(tst_menus) diff --git a/examples/activeqt/menus/doc/snippets/doc_src_examples_activeqt_menus.qdoc b/tests/manual/menus/doc/snippets/doc_src_examples_activeqt_menus.qdoc index a889f0f..a889f0f 100644 --- a/examples/activeqt/menus/doc/snippets/doc_src_examples_activeqt_menus.qdoc +++ b/tests/manual/menus/doc/snippets/doc_src_examples_activeqt_menus.qdoc diff --git a/examples/activeqt/menus/doc/src/menus.qdoc b/tests/manual/menus/doc/src/menus.qdoc index fdbe4ce..2ed7ea1 100644 --- a/examples/activeqt/menus/doc/src/menus.qdoc +++ b/tests/manual/menus/doc/src/menus.qdoc @@ -20,6 +20,7 @@ /*! \example activeqt/menus \title Menus Example (ActiveQt) + \ingroup activeqt-examples \brief The Menus example demonstrates the use of QMenuBar and QStatusBar in a QMainWindow to implement an in-place active control. diff --git a/examples/activeqt/menus/fileopen.xpm b/tests/manual/menus/fileopen.xpm index 880417e..880417e 100644 --- a/examples/activeqt/menus/fileopen.xpm +++ b/tests/manual/menus/fileopen.xpm diff --git a/examples/activeqt/menus/filesave.xpm b/tests/manual/menus/filesave.xpm index bd6870f..bd6870f 100644 --- a/examples/activeqt/menus/filesave.xpm +++ b/tests/manual/menus/filesave.xpm diff --git a/examples/activeqt/menus/main.cpp b/tests/manual/menus/main.cpp index 70e84eb..70e84eb 100644 --- a/examples/activeqt/menus/main.cpp +++ b/tests/manual/menus/main.cpp diff --git a/examples/activeqt/menus/menus.cpp b/tests/manual/menus/menus.cpp index 3093862..3093862 100644 --- a/examples/activeqt/menus/menus.cpp +++ b/tests/manual/menus/menus.cpp diff --git a/examples/activeqt/menus/menus.def b/tests/manual/menus/menus.def index bc82a03..bc82a03 100644 --- a/examples/activeqt/menus/menus.def +++ b/tests/manual/menus/menus.def diff --git a/examples/activeqt/menus/menus.h b/tests/manual/menus/menus.h index b21a9c3..b21a9c3 100644 --- a/examples/activeqt/menus/menus.h +++ b/tests/manual/menus/menus.h diff --git a/examples/activeqt/menus/menus.ico b/tests/manual/menus/menus.ico Binary files differindex c80d36a..c80d36a 100644 --- a/examples/activeqt/menus/menus.ico +++ b/tests/manual/menus/menus.ico diff --git a/examples/activeqt/menus/menus.inf b/tests/manual/menus/menus.inf index f97efe8..f97efe8 100644 --- a/examples/activeqt/menus/menus.inf +++ b/tests/manual/menus/menus.inf diff --git a/examples/activeqt/menus/menus.pro b/tests/manual/menus/menus.pro index f5a7890..f5a7890 100644 --- a/examples/activeqt/menus/menus.pro +++ b/tests/manual/menus/menus.pro diff --git a/examples/activeqt/menus/menus.rc b/tests/manual/menus/menus.rc index d466b35..d466b35 100644 --- a/examples/activeqt/menus/menus.rc +++ b/tests/manual/menus/menus.rc diff --git a/tests/manual/multiple/CMakeLists.txt b/tests/manual/multiple/CMakeLists.txt new file mode 100644 index 0000000..8e5d7c7 --- /dev/null +++ b/tests/manual/multiple/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## multiple Binary: +##################################################################### + +set(CMAKE_AUTOMOC ON) + +qt_internal_add_manual_test(tst_multiple + GUI + SOURCES + ax1.h + ax2.h + main.cpp + multipleax.def + multipleax.rc + LIBRARIES + Qt::AxServer + Qt::Gui + Qt::Widgets + +) +# qt_disable_warnings(tst_multiple) +qt6_target_idl(tst_multiple) diff --git a/examples/activeqt/multiple/ax1.h b/tests/manual/multiple/ax1.h index e3a7b10..e3a7b10 100644 --- a/examples/activeqt/multiple/ax1.h +++ b/tests/manual/multiple/ax1.h diff --git a/examples/activeqt/multiple/ax2.h b/tests/manual/multiple/ax2.h index 0509a12..0509a12 100644 --- a/examples/activeqt/multiple/ax2.h +++ b/tests/manual/multiple/ax2.h diff --git a/examples/activeqt/multiple/doc/src/multiple.qdoc b/tests/manual/multiple/doc/src/multiple.qdoc index 8713d9f..95e587c 100644 --- a/examples/activeqt/multiple/doc/src/multiple.qdoc +++ b/tests/manual/multiple/doc/src/multiple.qdoc @@ -11,6 +11,7 @@ /*! \example activeqt/multiple \title Multiple Example (ActiveQt) + \ingroup activeqt-examples \brief The Multiple example demonstrates the implementation of a QAxFactory to provide multiple ActiveX controls in a single in diff --git a/examples/activeqt/multiple/main.cpp b/tests/manual/multiple/main.cpp index 6ce4346..6ce4346 100644 --- a/examples/activeqt/multiple/main.cpp +++ b/tests/manual/multiple/main.cpp diff --git a/examples/activeqt/multiple/multiple.inf b/tests/manual/multiple/multiple.inf index 7f6be76..7f6be76 100644 --- a/examples/activeqt/multiple/multiple.inf +++ b/tests/manual/multiple/multiple.inf diff --git a/examples/activeqt/multiple/multiple.pro b/tests/manual/multiple/multiple.pro index f08d3a2..f08d3a2 100644 --- a/examples/activeqt/multiple/multiple.pro +++ b/tests/manual/multiple/multiple.pro diff --git a/examples/activeqt/multiple/multipleax.def b/tests/manual/multiple/multipleax.def index bc82a03..bc82a03 100644 --- a/examples/activeqt/multiple/multipleax.def +++ b/tests/manual/multiple/multipleax.def diff --git a/examples/activeqt/multiple/multipleax.ico b/tests/manual/multiple/multipleax.ico Binary files differindex c80d36a..c80d36a 100644 --- a/examples/activeqt/multiple/multipleax.ico +++ b/tests/manual/multiple/multipleax.ico diff --git a/examples/activeqt/multiple/multipleax.rc b/tests/manual/multiple/multipleax.rc index a9bcc1a..a9bcc1a 100644 --- a/examples/activeqt/multiple/multipleax.rc +++ b/tests/manual/multiple/multipleax.rc diff --git a/tests/manual/opengl/CMakeLists.txt b/tests/manual/opengl/CMakeLists.txt new file mode 100644 index 0000000..e8e4255 --- /dev/null +++ b/tests/manual/opengl/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testcontrol Binary: +##################################################################### + +set(CMAKE_AUTOMOC ON) + +qt_internal_add_manual_test(tst_opengl + GUI + SOURCES + glbox.cpp glbox.h + globjwin.cpp globjwin.h + main.cpp + opengl.def + opengl.rc + LIBRARIES + Qt::AxServer + Qt::Gui + Qt::OpenGL + Qt::OpenGLWidgets + Qt::Widgets +) + +# qt_disable_warnings(tst_opengl) +qt6_target_idl(tst_opengl) diff --git a/examples/activeqt/opengl/doc/src/opengl.qdoc b/tests/manual/opengl/doc/src/opengl.qdoc index 2558363..b95e89d 100644 --- a/examples/activeqt/opengl/doc/src/opengl.qdoc +++ b/tests/manual/opengl/doc/src/opengl.qdoc @@ -36,6 +36,7 @@ /*! \example activeqt/opengl \title OpenGL Example (ActiveQt) + \ingroup activeqt-examples \brief The OpenGL example demonstrates the use of the default factory and QAxFactory::isServer(), and the implementation of an diff --git a/examples/activeqt/opengl/glbox.cpp b/tests/manual/opengl/glbox.cpp index 3388670..3388670 100644 --- a/examples/activeqt/opengl/glbox.cpp +++ b/tests/manual/opengl/glbox.cpp diff --git a/examples/activeqt/opengl/glbox.h b/tests/manual/opengl/glbox.h index a1b58da..a1b58da 100644 --- a/examples/activeqt/opengl/glbox.h +++ b/tests/manual/opengl/glbox.h diff --git a/examples/activeqt/opengl/globjwin.cpp b/tests/manual/opengl/globjwin.cpp index 0b9cea1..0b9cea1 100644 --- a/examples/activeqt/opengl/globjwin.cpp +++ b/tests/manual/opengl/globjwin.cpp diff --git a/examples/activeqt/opengl/globjwin.h b/tests/manual/opengl/globjwin.h index 58ff614..58ff614 100644 --- a/examples/activeqt/opengl/globjwin.h +++ b/tests/manual/opengl/globjwin.h diff --git a/examples/activeqt/opengl/main.cpp b/tests/manual/opengl/main.cpp index 2f78324..2f78324 100644 --- a/examples/activeqt/opengl/main.cpp +++ b/tests/manual/opengl/main.cpp diff --git a/examples/activeqt/opengl/opengl.def b/tests/manual/opengl/opengl.def index bc82a03..bc82a03 100644 --- a/examples/activeqt/opengl/opengl.def +++ b/tests/manual/opengl/opengl.def diff --git a/examples/activeqt/opengl/opengl.ico b/tests/manual/opengl/opengl.ico Binary files differindex c80d36a..c80d36a 100644 --- a/examples/activeqt/opengl/opengl.ico +++ b/tests/manual/opengl/opengl.ico diff --git a/examples/activeqt/opengl/opengl.inf b/tests/manual/opengl/opengl.inf index 4a79e67..4a79e67 100644 --- a/examples/activeqt/opengl/opengl.inf +++ b/tests/manual/opengl/opengl.inf diff --git a/examples/activeqt/opengl/opengl.pro b/tests/manual/opengl/opengl.pro index 1ece9b9..1ece9b9 100644 --- a/examples/activeqt/opengl/opengl.pro +++ b/tests/manual/opengl/opengl.pro diff --git a/examples/activeqt/opengl/opengl.rc b/tests/manual/opengl/opengl.rc index 02c0898..02c0898 100644 --- a/examples/activeqt/opengl/opengl.rc +++ b/tests/manual/opengl/opengl.rc diff --git a/tests/manual/testcontrol/CMakeLists.txt b/tests/manual/testcontrol/CMakeLists.txt index 5513e96..78e410c 100644 --- a/tests/manual/testcontrol/CMakeLists.txt +++ b/tests/manual/testcontrol/CMakeLists.txt @@ -1,13 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from testcontrol.pro. - ##################################################################### ## testcontrol Binary: ##################################################################### -qt_internal_add_manual_test(tst_testcontrol_manual # special case +qt_internal_add_manual_test(tst_testcontrol_manual GUI SOURCES main.cpp @@ -19,7 +17,3 @@ qt_internal_add_manual_test(tst_testcontrol_manual # special case ) qt_disable_warnings(tst_testcontrol_manual) qt6_target_idl(tst_testcontrol_manual) - -#### Keys ignored in scope 1:.:.:testcontrol.pro:<TRUE>: -# RC_FILE = "testcontrol.rc" -# TEMPLATE = "app" diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index a379fba..bfbe5fd 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,9 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from tools.pro. - - qt_exclude_tool_directories_from_default_target( testcon ) diff --git a/tools/dumpcpp/CMakeLists.txt b/tools/dumpcpp/CMakeLists.txt index f1982ac..571f830 100644 --- a/tools/dumpcpp/CMakeLists.txt +++ b/tools/dumpcpp/CMakeLists.txt @@ -1,16 +1,14 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from dumpcpp.pro. - ##################################################################### ## dumpcpp Tool: ##################################################################### qt_get_tool_target_name(target_name dumpcpp) -qt_internal_add_tool(${target_name} # special case +qt_internal_add_tool(${target_name} TARGET_DESCRIPTION "Active Qt DumpCpp" - TOOLS_TARGET AxContainer # special case + TOOLS_TARGET AxContainer SOURCES main.cpp moc.cpp moc.h @@ -24,6 +22,3 @@ qt_internal_add_tool(${target_name} # special case Qt::Widgets ) qt_internal_return_unless_building_tools() - -#### Keys ignored in scope 1:.:.:dumpcpp.pro:<TRUE>: -# QMAKE_TARGET_DESCRIPTION = "Active Qt DumpCpp" diff --git a/tools/dumpcpp/main.cpp b/tools/dumpcpp/main.cpp index 9820a76..1b6fbeb 100644 --- a/tools/dumpcpp/main.cpp +++ b/tools/dumpcpp/main.cpp @@ -537,12 +537,13 @@ bool generateClassImpl(QTextStream &out, const QMetaObject *mo, const QByteArray bool useControlName, QString *errorString) { - Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 11, "dumpcpp should generate the same version as moc"); + Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 12, "dumpcpp should generate the same version as moc"); QByteArray qualifiedClassName; if (!nameSpace.isEmpty()) qualifiedClassName = nameSpace + "::"; qualifiedClassName += className; + const QByteArray nestedQualifier = className + "::"; QString moCode = mocCode(mo, QLatin1String(qualifiedClassName), errorString); if (moCode.isEmpty()) { @@ -567,7 +568,21 @@ bool generateClassImpl(QTextStream &out, const QMetaObject *mo, const QByteArray if (type.endsWith(u'*')) type.chop(1); type = type.trimmed(); - const auto namespaceForTypeEntry = namespaceForType.constFind(type.toUtf8()); + + // If ActiveQt thinks it's a nested type within the class, but it really is a type in the + // namespace, then we need to replace the nested type qualifier with the real namespace. + const bool isNestedType = type.startsWith(QString::fromUtf8(nestedQualifier)); + auto namespaceForTypeEntry = namespaceForType.constEnd(); + if (isNestedType) { + const QString rawType = type.mid(nestedQualifier.length()); + namespaceForTypeEntry = namespaceForType.constFind(rawType.toUtf8()); + if (namespaceForTypeEntry != namespaceForType.constEnd()) { + moCode.remove(startType, nestedQualifier.length()); + type = rawType; + } + } + if (namespaceForTypeEntry == namespaceForType.constEnd()) + namespaceForTypeEntry = namespaceForType.constFind(type.toUtf8()); if (namespaceForTypeEntry != namespaceForType.constEnd()) { const auto ns = QString::fromUtf8(namespaceForTypeEntry.value()); moCode.insert(startType, ns + QStringView(u"::")); diff --git a/tools/dumpcpp/moc.cpp b/tools/dumpcpp/moc.cpp index 78507bc..99f41c2 100644 --- a/tools/dumpcpp/moc.cpp +++ b/tools/dumpcpp/moc.cpp @@ -10,6 +10,8 @@ #include <QTemporaryFile> #include <QTextStream> +#include <private/qtools_p.h> + QT_BEGIN_NAMESPACE QByteArray setterName(const QByteArray &propertyName) @@ -18,7 +20,7 @@ QByteArray setterName(const QByteArray &propertyName) if (isupper(setter.at(0))) { setter = "Set" + setter; } else { - setter[0] = char(toupper(setter[0])); + setter[0] = QtMiscUtils::toAsciiUpper(setter[0]); setter = "set" + setter; } return setter; diff --git a/tools/dumpdoc/CMakeLists.txt b/tools/dumpdoc/CMakeLists.txt index d3d26aa..84b4018 100644 --- a/tools/dumpdoc/CMakeLists.txt +++ b/tools/dumpdoc/CMakeLists.txt @@ -1,16 +1,14 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from dumpdoc.pro. - ##################################################################### ## dumpdoc Tool: ##################################################################### qt_get_tool_target_name(target_name dumpdoc) -qt_internal_add_tool(${target_name} # special case +qt_internal_add_tool(${target_name} TARGET_DESCRIPTION "Active Qt DumpDoc" - TOOLS_TARGET AxContainer # special case + TOOLS_TARGET AxContainer SOURCES main.cpp LIBRARIES @@ -19,6 +17,3 @@ qt_internal_add_tool(${target_name} # special case Qt::Widgets ) qt_internal_return_unless_building_tools() - -#### Keys ignored in scope 1:.:.:dumpdoc.pro:<TRUE>: -# QMAKE_TARGET_DESCRIPTION = "Active Qt DumpDoc" diff --git a/tools/testcon/CMakeLists.txt b/tools/testcon/CMakeLists.txt index 0a5c4e6..50ebd69 100644 --- a/tools/testcon/CMakeLists.txt +++ b/tools/testcon/CMakeLists.txt @@ -1,15 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from testcon.pro. - ##################################################################### ## testcon Binary: ##################################################################### -qt_internal_add_app(testcon # special case -# OUTPUT_DIRECTORY "$$[QT_INSTALL_BINS]" # special case -# INSTALL_DIRECTORY "$$[QT_INSTALL_BINS]" # special case +qt_internal_add_app(testcon SOURCES ambientproperties.cpp ambientproperties.h ambientproperties.ui changeproperties.cpp changeproperties.h changeproperties.ui @@ -18,6 +14,7 @@ qt_internal_add_app(testcon # special case invokemethod.cpp invokemethod.h invokemethod.ui main.cpp mainwindow.cpp mainwindow.h mainwindow.ui + sandboxing.cpp sandboxing.h LIBRARIES Qt::AxContainer Qt::AxContainerPrivate @@ -36,20 +33,9 @@ set(testcon_resource_files "images/filenew.png" ) -qt_internal_add_resource(testcon "testcon" # special case +qt_internal_add_resource(testcon "testcon" PREFIX "/" FILES ${testcon_resource_files} ) - - -#### Keys ignored in scope 1:.:.:testcon.pro:<TRUE>: -# RC_FILE = "testcon.rc" -# TEMPLATE = "app" - -## Scopes: -##################################################################### - -#### Keys ignored in scope 2:.:.:testcon.pro:NOT MINGW: -# QMAKE_POST_LINK = "midl" "$$shell_quote($$shell_path $$PWD/testcon.idl)" "&&" "move" "testcon.tlb" "$(TARGETDIR)" diff --git a/tools/testcon/mainwindow.cpp b/tools/testcon/mainwindow.cpp index f613fe3..df81e42 100644 --- a/tools/testcon/mainwindow.cpp +++ b/tools/testcon/mainwindow.cpp @@ -22,8 +22,7 @@ #include <QtAxContainer/QAxScriptManager> #include <QtAxContainer/QAxWidget> #include <QtAxContainer/private/qaxbase_p.h> -#include <memory> -#include <sddl.h> +#include "sandboxing.h" QT_BEGIN_NAMESPACE @@ -90,70 +89,28 @@ QList<QAxWidget *> MainWindow::axWidgets() const return result; } - -/** RAII class for temporarily impersonating low-integrity level for the current thread. - Intended to be used together with CLSCTX_ENABLE_CLOAKING when creating COM objects. - Based on "Designing Applications to Run at a Low Integrity Level" https://msdn.microsoft.com/en-us/library/bb625960.aspx */ -struct LowIntegrity { - LowIntegrity() - { - HANDLE cur_token = nullptr; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &cur_token)) - abort(); - - if (!DuplicateTokenEx(cur_token, 0, nullptr, SecurityImpersonation, TokenPrimary, &m_token)) - abort(); - - CloseHandle(cur_token); - - PSID li_sid = nullptr; - if (!ConvertStringSidToSid(L"S-1-16-4096", &li_sid)) // low integrity SID - abort(); - - // reduce process integrity level - TOKEN_MANDATORY_LABEL TIL = {}; - TIL.Label.Attributes = SE_GROUP_INTEGRITY; - TIL.Label.Sid = li_sid; - if (!SetTokenInformation(m_token, TokenIntegrityLevel, &TIL, sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(li_sid))) - abort(); - - if (!ImpersonateLoggedOnUser(m_token)) // change current thread integrity - abort(); - - LocalFree(li_sid); - li_sid = nullptr; - } - - ~LowIntegrity() - { - if (!RevertToSelf()) - abort(); - - CloseHandle(m_token); - m_token = nullptr; - } - -private: - HANDLE m_token = nullptr; -}; - bool MainWindow::addControlFromClsid(const QString &clsid, QAxSelect::SandboxingLevel sandboxing) { QAxWidget *container = new QAxWidget; bool result = false; { - std::unique_ptr<LowIntegrity> low_integrity; + // RAII object for impersonating sandboxing on current thread + std::unique_ptr<Sandboxing> sandbox_impl; - if (sandboxing == QAxSelect::SandboxingProcess) { + switch (sandboxing) { + case QAxSelect::SandboxingNone: + break; // sandboxing disabled + case QAxSelect::SandboxingProcess: // require out-of-process container->setClassContext(CLSCTX_LOCAL_SERVER); - } else if (sandboxing == QAxSelect::SandboxingLowIntegrity) { - // impersonate "low integrity" - low_integrity.reset(new LowIntegrity); - // require out-of-process and - // propagate integrity level when calling setControl + break; + default: + // impersonate desired sandboxing + sandbox_impl = Sandboxing::Create(sandboxing, clsid); + // require out-of-process and activate impersonation container->setClassContext(CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING); + break; } result = container->setControl(clsid); diff --git a/tools/testcon/sandboxing.cpp b/tools/testcon/sandboxing.cpp new file mode 100644 index 0000000..e0c0eea --- /dev/null +++ b/tools/testcon/sandboxing.cpp @@ -0,0 +1,204 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "sandboxing.h" +#include <memory> +#include <windows.h> +#include <sddl.h> +#include <userenv.h> +#include <QProcess> +#include <QSettings> + + +/** RAII wrapper of STARTUPINFOEX. */ +struct StartupInfoExWrap +{ + STARTUPINFOEX si = {}; + + StartupInfoExWrap () + { + si.StartupInfo.cb = sizeof(STARTUPINFOEX); + + const DWORD attr_count = 1; // SECURITY_CAPABILITIES + SIZE_T attr_size = 0; + InitializeProcThreadAttributeList(NULL, attr_count, 0, &attr_size); + si.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)new BYTE[attr_size](); + if (!InitializeProcThreadAttributeList(si.lpAttributeList, attr_count, 0, &attr_size)) + qFatal("InitializeProcThreadAttributeList failed"); + } + + void SetSecurity(SECURITY_CAPABILITIES *sc) + { + if (!UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, + sc, sizeof(SECURITY_CAPABILITIES), NULL, NULL)) + qFatal("UpdateProcThreadAttribute failed"); + } + + ~StartupInfoExWrap() + { + DeleteProcThreadAttributeList(si.lpAttributeList); + delete [] (BYTE*)si.lpAttributeList; + } +}; + +/** RAII wrapper of PROCESS_INFORMATION. */ +struct ProcessInformationWrap +{ + PROCESS_INFORMATION pi = {}; + + ~ProcessInformationWrap() + { + CloseHandle(pi.hThread); + pi.hThread = nullptr; + CloseHandle(pi.hProcess); + pi.hProcess = nullptr; + } +}; + +/** RAII class for temporarily impersonating an AppContainer-isolated process + * for the current thread. Intended to be used together with CLSCTX_ENABLE_CLOAKING + * when creating COM objects. There's no direct support for AppContainer + * impersonation in Windows, so the impl. will instead create a suspended throw-away + * process within the AppContainer to use as basis for AppContainer impersonation. + * This seem kind of weird, but is the approach recommended by Microsoft when opening + * a support case on the matter. Based on "AppContainer Isolation" + * https://learn.microsoft.com/en-us/windows/win32/secauthz/appcontainer-isolation */ +struct AppContainer : public Sandboxing +{ + AppContainer(const QString &clsid) + { + // Create AppContainer sandbox without any special capabilities + static const wchar_t name[] = L"Qt_testcon"; + static const wchar_t desc[] = L"Qt ActiveQt Test Container"; + HRESULT hr = CreateAppContainerProfile(name, name, desc, nullptr, 0, &m_sid); + if (HRESULT_CODE(hr) == ERROR_ALREADY_EXISTS) + hr = DeriveAppContainerSidFromAppContainerName(name, &m_sid); // fallback to existing container + if (FAILED(hr)) + qFatal("CreateAppContainerProfile and DeriveAppContainerSidFromAppContainerName failed"); + + SECURITY_CAPABILITIES sec_cap = {}; + sec_cap.AppContainerSid = m_sid; + + StartupInfoExWrap si; + si.SetSecurity(&sec_cap); + + // Create suspended COM server process in AppContainer + QString exe_path = GetExePath(clsid); + ProcessInformationWrap pi; + DWORD flags = EXTENDED_STARTUPINFO_PRESENT | CREATE_SUSPENDED; // don't start main thread + if (!CreateProcess(exe_path.toStdWString().data(), nullptr, nullptr, nullptr, + FALSE, flags, nullptr, nullptr, (STARTUPINFO*)&si.si, &pi.pi)) + qFatal("CreateProcess failed"); + + // Kill process since we're only interested in the handle for now. + // The COM runtime will later recreate the process when calling CoCreateInstance. + TerminateProcess(pi.pi.hProcess, 0); + + // Create AppContainer impersonation token + HANDLE cur_token = nullptr; + if (!OpenProcessToken(pi.pi.hProcess, + TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, + &cur_token)) + qFatal("OpenProcessToken failed"); + + if (!DuplicateTokenEx(cur_token, 0, NULL, SecurityImpersonation, TokenPrimary, &m_token)) + qFatal("DuplicateTokenEx failed"); + + CloseHandle(cur_token); + cur_token = nullptr; + + // Impersonate AppContainer on current thread + if (!ImpersonateLoggedOnUser(m_token)) + qFatal("ImpersonateLoggedOnUser failed"); + } + + ~AppContainer() + { + if (!RevertToSelf()) + qFatal("RevertToSelf failed"); + + CloseHandle(m_token); + m_token = nullptr; + + FreeSid(m_sid); + m_sid = nullptr; + } + +private: + /** Get EXE path for a COM class. Input is on "{hex-guid}" format. + * Returns empty string if the COM class is DLL-based and on failure. */ + static QString GetExePath (const QString &clsid) + { + // extract COM class + QSettings cls_folder("HKEY_LOCAL_MACHINE\\Software\\Classes\\CLSID\\" + clsid, QSettings::NativeFormat); + QString command = cls_folder.value("LocalServer32/.").toString(); + if (command.isEmpty()) + return ""; // not exe path found + + // remove any quotes and "/automation" or "-activex" arguments + QStringList arguments = QProcess::splitCommand(command); + return arguments[0]; // executable is first argument + } + + PSID m_sid = nullptr; + HANDLE m_token = nullptr; +}; + +/** RAII class for temporarily impersonating low-integrity level for the current thread. + Intended to be used together with CLSCTX_ENABLE_CLOAKING when creating COM objects. + Based on "Designing Applications to Run at a Low Integrity Level" https://msdn.microsoft.com/en-us/library/bb625960.aspx */ +class LowIntegrity : public Sandboxing +{ +public: + LowIntegrity() + { + HANDLE cur_token = nullptr; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &cur_token)) + qFatal("OpenProcessToken failed"); + + if (!DuplicateTokenEx(cur_token, 0, nullptr, SecurityImpersonation, TokenPrimary, &m_token)) + qFatal("DuplicateTokenEx failed"); + + CloseHandle(cur_token); + + PSID li_sid = nullptr; + if (!ConvertStringSidToSid(L"S-1-16-4096", &li_sid)) // low integrity SID + qFatal("ConvertStringSidToSid failed"); + + // reduce process integrity level + TOKEN_MANDATORY_LABEL TIL = {}; + TIL.Label.Attributes = SE_GROUP_INTEGRITY; + TIL.Label.Sid = li_sid; + if (!SetTokenInformation(m_token, TokenIntegrityLevel, &TIL, sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(li_sid))) + qFatal("SetTokenInformation failed"); + + if (!ImpersonateLoggedOnUser(m_token)) // change current thread integrity + qFatal("ImpersonateLoggedOnUser failed"); + + LocalFree(li_sid); + li_sid = nullptr; + } + + ~LowIntegrity() + { + if (!RevertToSelf()) + qFatal("RevertToSelf failed"); + + CloseHandle(m_token); + m_token = nullptr; + } + +private: + HANDLE m_token = nullptr; +}; + +std::unique_ptr<Sandboxing> Sandboxing::Create(QAxSelect::SandboxingLevel level, const QString &clsid) +{ + if (level == QAxSelect::SandboxingLowIntegrity) + return std::make_unique<LowIntegrity>(); + else if (level == QAxSelect::SandboxingAppContainer) + return std::make_unique<AppContainer>(clsid); + + Q_ASSERT_X(false, "Sandboxing::Create", "unknown sandboxing level"); + return {}; +} diff --git a/tools/testcon/sandboxing.h b/tools/testcon/sandboxing.h new file mode 100644 index 0000000..5f51227 --- /dev/null +++ b/tools/testcon/sandboxing.h @@ -0,0 +1,20 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef SANDBOXING_H +#define SANDBOXING_H +#include <QString> +#include <QAxSelect> + + +class Sandboxing +{ +public: + static std::unique_ptr<Sandboxing> Create(QAxSelect::SandboxingLevel level, const QString &clsid); + + Sandboxing() {} + + virtual ~Sandboxing() {} +}; + +#endif // SANDBOXING_H |