From ca47896204482bf4a6979e3838bf7f09f61cebeb Mon Sep 17 00:00:00 2001 From: giy <giy@omp-system.ru> Date: Fri, 02 Sep 2022 14:16:56 +0300 Subject: [PATCH] Обновление до версии 2.9.0 --- vsconfig/2017.vsconfig | 48 Templates/quick/quick.vcxproj.filters | 4 Templates/widgetsclass/Properties/AssemblyInfo.cs | 67 QtVsTools.Package/Legacy/FormProjectQtSettings.resx | 120 QtVsTools.Wizards/ProjectWizard/Server/ServerWizard.cs | 170 Templates/qtclass/qtclass.vstemplate_TT | 71 GUIDELINES.using-directive.md | 54 QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs | 28 QtVsTools.Core/Legacy/QtProject.cs | 290 doc/images/qtvstools-quick-addressbook-mainwindow.png | 0 doc/images/qtvstools-remote-debugging.png | 0 Tests/Test_QtVsTools.Package/Test_QtVersionsPage.cs | 247 QtVsTools.Core/CommandLineParser.cs | 35 Templates/widget/QtTemplate.Item.Widget.csproj | 49 Tests/BigSolution/template/StaticLib/StaticLib.vcxproj | 93 QtVsTools.Package/QML/Parser/QmlParserInterop.cs | 16 QtVsTools.Core/OutputWindowPane.cs | 180 doc/images/front-help.png | 0 Templates/widgetsclass/widget.cpp | 11 QtVsTools.Core/QtModules.cs | 66 Tests/ProjectFormats/304/QtProjectV304.cpp | 10 Templates/qtclass/Properties/AssemblyInfo.cs | 67 QtVsTools.Core/QrcPrefix.cs | 2 QtVsTools.Core/LinkerToolWrapper.cs | 4 doc/images/front-gs.png | 0 Templates/console/QtTemplate.Project.Console.csproj | 47 Templates/console/console.vcxproj.filters | 6 QtVsTools.Package/QtVsTools.Icons.pkgdef | 20 Tests/ProjectFormats/304/QtProjectV304.vcxproj.filters | 48 Tests/BigSolution/template/loop_msbuild.bat | 36 Tests/Test_QtMsBuild.Tasks/Test_QtMsBuild.Tasks.csproj | 33 Tests/BigSolution/template/BigProjectNNN/BigProjectQtClassNNN.h | 2 QtVsTools.Package/Legacy/ChangeFor.cs | 32 Tests/ProjectFormats/100/QtProjectV100.qrc | 4 QtVsTools.Core/QtVSIPSettings.cs | 477 QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs | 13 QtVsTools.Core/Common/QtVSIPSettingsShared.cs | 261 QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml | 8 doc/images/qtvstools-msbuild-diagram.png | 0 QtVsTools.Core/ProFileContent.cs | 40 Templates/server/QtTemplate.Project.Server.csproj | 49 Tests/ProjectFormats/302/QtProjectV302.h | 15 QtVsTools.Wizards/ProjectWizard/Library/LibraryClassPage.xaml | 238 QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4JsObject.cs | 1 QtVsTools.Wizards/ItemWizard/QtClass/QtClassWizard.cs | 193 Tests/ProjectFormats/300/main.cpp | 10 QtVsTools.Package/Legacy/FormChangeQtVersion.cs | 107 QtVsTools.Core/QMakeQuery.cs | 22 QtVsTools.RegExpr/Properties/AssemblyInfo.cs | 1 QtVsTools.Wizards/ProjectWizard/Server/ServerPage.xaml.cs | 64 QtVsTools.Wizards/Common/WizardWindow.xaml | 44 Tests/Test_QtVsTools.Package/Properties/AssemblyInfo.cs | 20 Tests/ProjectFormats/301/QtProjectV301.ui | 29 doc/tutorial/QuickAddressBook/QuickAddressBookTypes/AddressBookItem.qml | 59 QtVsTools.Package/Marketplace/Overview.html_TT | 39 QtVsTools.Core/MsBuildProject.cs | 104 QtVsTools.Package/Legacy/FormProjectQtSettings.cs | 166 Tests/Test_QtVsTools.RegExpr/Properties/AssemblyInfo.cs | 1 Tests/ProjectFormats/303/QtProjectV303.vcxproj | 106 doc/tutorial/QuickAddressBook/main.qml | 74 QtMSBuild/QtMsBuild/qt_settings.xml | 52 Tests/ProjectFormats/100/QtProjectV100.cpp | 10 QtVsTools.Wizards/Util/FileNameValidationRule.cs | 55 Templates/lib/QtTemplate.Project.Lib.csproj | 49 QtVsTools.Package/QML/Syntax/QmlSyntax.cs | 2 QtVsTools.Core/VisualStudio/InfoBarMessage.cs | 166 Templates/widgetsclass/widgetsclass.ico | 0 QtVsTools.Wizards/ProjectWizard/Designer/DesignerPage.xaml | 310 Tests/Test_QtVsTools.RegExpr/Test_QtVsTools.RegExpr.csproj | 6 Templates/qmldir/QtTemplate.Item.QMLDir.csproj | 49 QtVsTools.Package/Common/Timestamp.cs | 9 QtVsTools.Package/Package/QtItemContextMenu.cs | 41 QtVsTools.Wizards/ProjectWizard/Designer/DesignerWizard.cs | 179 Tests/Test_QtVsTools.Core/Test_LazyFactory.cs | 77 doc/qtvstools-online.qdocconf | 2 QtMSBuild/QtMsBuild/qt6.natvis.xml | 406 QtVsTools.Package/QML/Parser/QmlParserDiagnostics.cs | 4 QtVsTools.Core/Legacy/QtVersionManager.cs | 63 Templates/gui/gui.vcxproj.filters | 2 Tests/ProjectFormats/100/QtProjectV100.ui | 28 Tests/BigSolution/template/BigProjectNNN/BigProjectNNN.vcxproj | 8 Tests/ProjectFormats/200/QtProjectV200.vcxproj.filters | 75 QtVsTools.Package/Package/QtProjectContextMenu.cs | 128 QtVsTools.Package/QtMsBuild/QtVersionProvider.cs | 1 Tests/ProjectFormats/304/QtProjectV304.sln | 25 QtVsTools.Core/QMakeConf.cs | 16 .github/ISSUE_TEMPLATE/feature.md | 20 QtVsTools.Core/ProSolution.cs | 23 doc/tutorial/AddressBook/adddialog.h | 2 QtVsTools.Wizards/ProjectWizard/ConfigPage.xaml.cs | 489 + Tests/Test_QtVsTools.RegExpr/Test_SubTokens.cs | 1 Tests/Test_QtVsTools.Core/Properties/AssemblyInfo.cs | 20 doc/images/qtvstools-qt-translation-file-wizard.png | 0 Tests/ProjectFormats/303/QtProjectV303.ui | 28 Tests/ProjectFormats/302/QtProjectV302.sln | 25 QtVsTools.Package/QtVsTools.Package.csproj | 166 QtVsTools.Core/QtVsTools.Core.csproj | 57 Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.vcxproj | 114 Tests/Test_QtMsBuild.Tasks/Test_Join.cs | 25 QtVsTools.Core/QtMsBuild.cs | 80 Tests/ProjectFormats/100/main.cpp | 10 doc/tutorial/QuickAddressBook/QuickAddressBookTypes/NewAddressPopup.qml | 88 Tests/ProjectFormats/100/QtProjectV100.vcxproj.filters | 95 QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Engine.cs | 46 QtVsTools.RegExpr/expression/RegExprToken.cs | 18 Templates/translation/translation.ico | 0 QtVsTools.Wizards/ProjectWizard/ConfigPage.xaml | 298 doc/images/front-advanced.png | 0 QtVsTools.Wizards/Util/NativeMethods.cs | 41 Templates/widgetsclass/widget.ui | 22 Templates/dialogbuttonright/QtTemplate.Item.DialogButtonRight.csproj | 49 QtVsTools.Package/QML/Classification/QmlTag.cs | 18 Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.cpp | 33 Tests/BigSolution/generator/Program.cs | 115 .github/ISSUE_TEMPLATE/bug.md | 31 QtVsTools.Package/Package/Notifications.cs | 111 doc/tutorial/QuickAddressBook/main.cpp | 45 QtVsTools.Wizards/ItemWizard/QtClass/QtClassPage.xaml.cs | 68 QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs | 4 doc/images/qtvstools-quick-addressbook-entries.png | 0 QtMSBuild/QtMsBuild/translation/qttranslation.targets | 16 QtVsTools.Package/QtMsBuild/QtProjectTracker.cs | 170 QtVsTools.Core/Resources.resx | 40 QtVsTools.Package/Package/QtHelpLinkChooser.xaml | 60 Tests/BigSolution/template/QtClassLibrary/qtclasslibrary_global.h | 41 Templates/mainwindow/QtTemplate.Item.MainWindow.csproj | 49 Templates/quick/QtTemplate.Project.Quick.csproj | 42 Tests/BigSolution/template/BigSolution.sln | 12 QtMSBuild/Tasks/QtRunTask.cs | 246 QtVsTools.Package/Common/Json/DeferredObject.cs | 2 QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Continue.cs | 3 version.targets | 2 QtMSBuild/QtMsBuild/qt_private.props | 116 QtVsTools.Package/QtMenus.vsct_TT | 93 QtVsTools.Package/Common/Prototyped.cs | 9 QtVsTools.Package/qtmodules.xml | 56 Tests/Test_QtVsTools.RegExpr/Test_MacroParser.cs | 3 QtVsTools.Package/Icons/prf32.png | 0 QtVsTools.RegExpr/production/Production.cs | 14 QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Program.cs | 80 QtVsTools.Package/Package/ExtLoader.cs | 19 QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Expression.cs | 11 QtVsTools.Wizards/Common/WizardIntroPage.xaml.cs | 39 QtVsTools.Package/Common/PriorityQueue.cs | 19 Tests/ProjectFormats/100/QtProjectV100.pro | 6 Templates/server/server.vcxproj.filters | 2 Tests/ProjectFormats/302/QtProjectV302.ui | 28 Tests/ProjectFormats/303/QtProjectV303.cpp | 7 Templates/translation/translation.ts | 4 .editorconfig | 2 QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml.cs | 8 QtVsTools.Core/VisualStudio/VsSearch.cs | 146 Templates/qml/QtTemplate.Item.QMLFile.csproj | 49 QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml.cs | 91 QtVsTools.Wizards/Common/WizardIntroPage.xaml | 102 Templates/translation/translation.vstemplate_TT | 69 README.md | 2 QtVsTest/QtVsTest.cs | 4 QtVsTools.Wizards/Common/WizardWindow.xaml.cs | 133 QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml | 149 QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Message.cs | 6 Templates/translation/Properties/AssemblyInfo.cs | 67 QtVsTools.Package/qt6modules.xml | 510 + QtVsTools.Package/Icons/qml32.png | 0 QtVsTools.Wizards/Common/WizardData.cs | 68 Tests/ProjectFormats/302/QtProjectV302.vcxproj | 102 Templates/qtclass/qtclass.ico | 0 Tests/ProjectFormats/301/main.cpp | 10 Tests/ProjectFormats/304/main.cpp | 10 QtVsTools.Wizards/Common/WizardResult.cs | 37 QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7InfoHelpers.cs | 10 QtVsTools.Core/FakeFilter.cs | 7 Tests/Test_QtMsBuild.Tasks/TestTaskLoggingHelper.cs | 4 QtVsTools.Package/Common/Json/Serializable.cs | 8 doc/tutorial/QuickAddressBook/QuickAddressBook.vcxproj.filters | 45 Tests/ProjectFormats/300/QtProjectV300.qrc | 4 QtVsTools.Core/ProjectImporter.cs | 112 QtVsTools.Core/ProFileOption.cs | 100 QtVsTools.Core/Resources.cs | 7 Tests/ProjectFormats/303/QtProjectV303.sln | 25 Tests/Test_QtVsTools.Core/Test_QtVsTools.Core.csproj | 129 QtVsTools.Core/RccOptions.cs | 15 Tests/ProjectFormats/304/QtProjectV304.qrc | 4 Tests/BigSolution/template/StaticLib/StaticLib.vcxproj.filters | 27 vstools.bat | 37 doc/images/front-projects.png | 0 QtVsTools.Package/Icons/pri32.png | 0 QtVsTools.Package/qt5.natvis.xml | 51 QtVsTools.Wizards/ProjectWizard/Library/LibraryWizard.cs | 142 QtVsTools.Core/VisualStudio/VsShell.cs | 107 QtVsTools.Wizards/ItemWizard/Translation/TranslationWizard.cs | 119 QtMSBuild/QtMsBuild/qt_vars.targets | 74 Templates/resource/QtTemplate.Item.Resource.csproj | 49 Tests/Test_QtMsBuild.Tasks/Properties/AssemblyInfo.cs | 1 Tests/Test_QtMsBuild.Tasks/Test_QtRunTask.cs | 90 vstools.sln | 99 Tests/ProjectFormats/304/QtProjectV304.h | 16 doc/tutorial/QuickAddressBook/QuickAddressBook.sln | 25 QtVsTools.Package/QtVsToolsPackage.cs | 82 Tests/ProjectFormats/300/QtProjectV300.cpp | 7 QtVsTools.Package/source.extension.vsixmanifest_TT | 18 Tests/ProjectFormats/ProjectFormats.md | 1324 ++ QtVsTools.Core/WaitDialog.cs | 41 QtVsTools.Package/Resources.resx | 39 QtVsTools.Package/Editors/Editor.QtDesigner.cs | 21 QtVsTools.Core/BuildConfig.cs | 1 QtVsTools.RegExpr/expression/CharClassSet.cs | 13 Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.h | 37 Tests/ProjectFormats/100/QtProjectV100.vcxproj | 215 QtVsTools.Core/QMake.cs | 30 QtVsTools.Package/Icons/Monikers.imagemanifest | 54 QtVsTools.Package/Package/QMakeWrapper.cs | 2 Tests/ProjectFormats/200/QtProjectV200.h | 15 QtVsTools.Core/HelperFunctions.cs | 629 Tests/ProjectFormats/302/main.cpp | 10 doc/tutorial/QuickAddressBook/QuickAddressBook.vcxproj | 135 QtVsTools.Core/ExportProjectDialog.cs | 6 QtVsTools.Core/VisualStudio/VsServiceProvider.cs | 9 Templates/gui/gui.vstemplate_TT | 2 Tests/ProjectFormats/200/QtProjectV200.sln | 22 QtMSBuild/QtMsBuild/qt_defaults.props | 7 Templates/gui/widget.cpp | 10 doc/config/style/qt5-sidebar.html | 51 QtVsTools.Package/QtMsBuild/QtProjectBuild.cs | 377 Tests/BigSolution/template/QtClassLibrary/QtClass.h | 41 QtVsTools.Package/Editors/Editor.cs | 100 QtVsTools.Package/QML/Debugging/QmlDebugger.cs | 47 QtVsTools.Core/CompilerToolWrapper.cs | 81 Templates/designer/widget.h | 2 doc/images/qtvstools-qt-project-settings.png | 0 QtVsTools.Package/Legacy/Translation.cs | 134 QtVsTools.Wizards/Common/UiClassInclusion.cs | 37 QtVsTools.Core/Common/LazyFactory.cs | 57 Tests/BigSolution/template/StaticLib/StaticLib.cpp | 31 Templates/widgetsclass/widget.h | 15 QtVsTools.Package/Common/ConcurrentStopwatch.cs | 2 QtVsTools.Package/Legacy/QtOptionsPage.cs | 161 QtVsTest/Macro.cs | 127 QtVsTools.Wizards/Common/GuiPage.xaml | 307 QtVsTools.Package/Options/QtVersionsTable.xaml | 24 QtVsTools.Core/ProjectExporter.cs | 85 Templates/server/header.h | 2 QtVsTools.Core/Messages.cs | 134 Сборка.md | 2 Templates/gui/widget.qrc | 4 QtVsTools.RegExpr/production/ProductionRule.cs | 5 Templates/translation/QtTemplate.Item.Translation.csproj | 155 QtVsTools.Wizards/QtVsTools.Wizards.csproj | 157 QtVsTools.Wizards/Util/ClassNameValidationRule.cs | 67 doc/images/qtvstools-qt-widget-class-wizard.png | 0 references.props | 163 QtVsTools.Package/Icons/pro32.png | 0 Tests/ProjectFormats/100/QtProjectV100.h | 16 Tests/ProjectFormats/304/QtProjectV304.vcxproj | 105 QtVsTools.Wizards/ItemWizard/WidgetsClass/WidgetsClassWizard.cs | 245 QtVsTools.Package/QML/Syntax/QmlAst.cs | 2 Tests/Test_QtVsTools.Package/QtVsTestClient.cs | 144 QtVsTools.Wizards/Util/VCRulePropertyStorageHelper.cs | 69 Tests/ProjectFormats/300/QtProjectV300.h | 15 Templates/widgetsclass/widgetsclass.vstemplate_TT | 70 QtVsTest/QtVsTest.csproj | 94 QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Events.cs | 28 doc/images/front-coding.png | 0 vsconfig/2019.vsconfig | 44 QtVsTools.RegExpr/expression/RegExprAssert.cs | 4 Tests/Test_QtVsTools.RegExpr/Test_XmlIntParser.cs | 3 doc/images/qtvstools-quick-addressbook-popup.png | 0 .gitignore | 6 QtVsTools.Core/CxxStreamReader.cs | 4 QtVsTools.Core/MocCmdChecker.cs | 4 Tests/BigSolution/template/StaticLib/Header.h | 4 QtVsTools.RegExpr/expression/RegExprRepeat.cs | 1 QtVsTools.Package/Common/Concurrent.cs | 7 Tests/ProjectFormats/303/QtProjectV303.qrc | 4 Tests/ProjectFormats/200/QtProjectV200.cpp | 7 QtVsTools.Core/Extensions.cs | 9 QtVsTools.Wizards/ProjectWizard/Server/ServerPage.xaml | 259 QtVsTools.RegExpr/production/ProductionRuleAction.cs | 6 QtVsTools.Wizards/ProjectWizard/ProjectTemplateWizard.cs | 722 + Tests/ProjectFormats/301/QtProjectV301.h | 15 Tests/ProjectFormats/301/QtProjectV301.qrc | 4 QtVsTools.Package/Legacy/FormChangeQtVersion.resx | 120 QtVsTools.RegExpr/utils/Consts.cs | 21 QtVsTools.Wizards/Util/UnsafeNativeMethods.cs | 41 vsconfig/2022.vsconfig | 42 doc/images/qtvstools-options-qt-general.png | 0 QtVsTools.Package/Common/Json/SerializableEnum.cs | 3 QtVsTools.Package/Options/QtOptionsPage.cs | 67 QtVsTools.Package/qt6.natvis.xml | 33 QtVsTools.Package/Options/QtVersionsPage.cs | 92 Tests/ProjectFormats/300/QtProjectV300.sln | 25 QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs | 4 Templates/empty/QtTemplate.Project.Empty.csproj | 49 QtVsTools.Package/Legacy/FormChangeQtVersion.Designer.cs | 87 doc/images/front-preview.png | 0 Templates/lib/lib.vcxproj.filters | 6 Tests/ProjectFormats/303/QtProjectV303.h | 15 Tests/ProjectFormats/301/QtProjectV301.vcxproj | 109 QtVsTools.Package/Icons/qrc32.png | 0 QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs | 42 Tests/ProjectFormats/200/QtProjectV200.ui | 29 QtVsTools.Package/QML/Debugging/QmlFileSystem.cs | 15 QtVsTools.Wizards/Common/GuiPage.xaml.cs | 74 Tests/ProjectFormats/302/QtProjectV302.vcxproj.filters | 46 Tests/ProjectFormats/302/QtProjectV302.cpp | 7 QtVsTools.Package/Legacy/ProjectQtSettings.cs | 336 Tests/ProjectFormats/303/main.cpp | 10 QtVsTools.Wizards/Common/WizardPage.cs | 115 QtVsTools.Core/QtConfig.cs | 17 QtVsTools.Core/QtVersionManager.cs | 246 Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.vcxproj.filters | 42 Tests/BigSolution/template/QtClassLibrary/QtClass.cpp | 38 Templates/qtclass/header.h | 9 QtMSBuild/QtMsBuild/qt_globals.targets | 259 Templates/designer/QtTemplate.Project.Designer.csproj | 49 QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Breakpoint.cs | 19 Tests/Test_QtVsTools.PriorityQueue/Test_QtVsTools.PriorityQueue.csproj | 6 Templates/designer/plugin.h | 2 QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs | 32 QtVsTools.Core/QtProject.cs | 944 - QtVsTools.Package/QML/Debugging/QmlDebugLauncher.cs | 63 QtVsTools.Wizards/ProjectWizard/Gui/GuiWizard.cs | 365 Changelog | 31 QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Property.cs | 46 Tests/Test_QtVsTools.PriorityQueue/Properties/AssemblyInfo.cs | 1 QtVsTools.Core/MainWinWrapper.cs | 20 Tests/ProjectFormats/200/main.cpp | 10 QtVsTools.Core/Common/EnumExt.cs | 12 QtVsTools.RegExpr/expression/Renderer.cs | 1 QtVsTools.Wizards/ProjectWizard/Library/LibraryClassPage.xaml.cs | 64 Tests/Test_QtVsTools.Package/Test_QtVsTools.Package.csproj | 120 doc/images/qtvstools-qtquick-app-modules.png | 0 Templates/widgetsclass/QtTemplate.Item.WidgetsClass.csproj | 157 QtVsTools.RegExpr/parser/Parser.cs | 10 QtVsTools.Package/Package/QtSolutionContextMenu.cs | 107 Templates/qtclass/source.cpp | 8 Templates/gui/main.cpp | 2 Tests/ProjectFormats/300/QtProjectV300.vcxproj | 106 QtVsTools.Core/Filters.cs | 21 QtVsTools.Core/SR.cs | 29 QtVsTools.Package/Package/QtHelp.cs | 113 QtVsTools.Wizards/Util/UiClassInclusionConverter.cs | 43 QtVsTools.Package/Icons/ts32.png | 0 QMakeFileReader/evaluator/proitems.cpp | 2 QtMSBuild/QtMsBuild/qt_inner.targets | 138 QtVsTools.Package/QtMsBuild/QtModulesEditor.cs | 38 Tests/ProjectFormats/301/QtProjectV301.cpp | 7 QtMSBuild/Tasks/CriticalSection.cs | 2 Templates/qtclass/QtTemplate.Item.QtClass.csproj | 157 Tests/ProjectFormats/200/QtProjectV200.vcxproj | 133 doc/tutorial/QuickAddressBook/qmldir | 2 QtVsTools.Wizards/ItemWizard/QtClass/QtClassPage.xaml | 298 QtVsTools.Package/Common/NativeAPI.cs | 8 QtVsTools.RegExpr/parser/ParseTree.cs | 11 QtVsTools.Package/Icons/ui32.png | 0 doc/config/qtvstools-project.qdocconf | 8 QtVsTest/MacroParser.cs | 9 Tests/ProjectFormats/200/QtProjectV200.qrc | 4 QtVsTools.Wizards/Util/VCLanguageManagerValidationRule.cs | 53 Templates/dialogbuttonbottom/QtTemplate.Item.DialogButtonBottom.csproj | 49 QtVsTools.Package/Package/QtMainMenu.cs | 115 QtVsTools.Wizards/Util/FileExistsInFilterValidationRule.cs | 68 QtMSBuild/QtMsBuild/qt5.natvis.xml | 835 + QtVsTools.Wizards/ProjectWizard/Quick/QuickWizard.cs | 75 Tests/ProjectFormats/303/QtProjectV303.vcxproj.filters | 49 QtVsTools.Core/QtModule.cs | 12 doc/tutorial/QuickAddressBook/qml.qrc | 8 Templates/designer/designer.vcxproj.filters | 6 Tests/Test_QtVsTools.PriorityQueue/Test_PriorityQueue.cs | 15 QtVsTools.Package/Package/DteEventsHandler.cs | 143 QtVsTools.RegExpr/QtVsTools.RegExpr.csproj | 11 Tests/ProjectFormats/300/QtProjectV300.vcxproj.filters | 50 QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Client.cs | 32 Tests/ProjectFormats/300/QtProjectV300.ui | 29 QtVsTest/MacroServer.cs | 10 QtVsTools.Wizards/ProjectWizard/Console/ConsoleWizard.cs | 89 QtMSBuild/QtMSBuild.csproj | 47 QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7StackFrame.cs | 24 QtVsTools.Package/Package/Translation.cs | 171 Tests/ProjectFormats/301/QtProjectV301.vcxproj.filters | 50 QtVsTools.Core/Legacy/QtVSIPSettings.cs | 226 QtVsTools.Package/Legacy/QtMenu.cs | 109 QtVsTools.Package/Legacy/FormProjectQtSettings.Designer.cs | 159 Tests/ProjectFormats/302/QtProjectV302.qrc | 4 doc/src/qtvstools.qdoc | 868 + QtVsTools.Wizards/ProjectWizard/Empty/EmptyWizard.cs | 75 QtVsTools.Package/Common/Json/Serializer.cs | 28 QtVsTools.Package/Options/QtVersionsTable.cs | 348 QtVsTools.Core/VersionInformation.cs | 25 QtVsTools.Package/Package/SR.cs | 53 QtVsTools.Package/Editors/Editor.QtResourceEditor.cs | 13 Tests/ProjectFormats/301/QtProjectV301.sln | 25 QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Protocol.cs | 16 Tests/ProjectFormats/304/QtProjectV304.ui | 28 QtVsTools.Package/Package/QtMsBuildConverter.cs | 33 QtVsTools.Wizards/ProjectWizard/Designer/DesignerPage.xaml.cs | 70 Templates/gui/QtTemplate.Project.Gui.csproj | 55 Templates/gui/widget.h | 10 398 files changed, 23,085 insertions(+), 5,153 deletions(-) diff --git a/.editorconfig b/.editorconfig index e8c7721..5d522eb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -19,7 +19,7 @@ # Organize usings dotnet_separate_import_directive_groups = false -dotnet_sort_system_directives_first = false +dotnet_sort_system_directives_first = true file_header_template = unset # this. and Me. preferences diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 0000000..f7d109d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,31 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - Qt VS Tool Version [e.g. 2.7.1, 2.8.1, 2.8.1 (Rev.06)] + - Visual Studio version [e.g. VS2017, VS2019, VS2022] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 0000000..72718d5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore index 30aff55..9b2efd8 100644 --- a/.gitignore +++ b/.gitignore @@ -315,3 +315,9 @@ QtNatvisPoC/*.txt Tests/BigSolution/generated/ vstools.pri +templates/widgetsclass/Properties/AssemblyInfo.tt.cs +templates/widgetsclass/widgetsclass.vstemplate +templates/qtclass/Properties/AssemblyInfo.tt.cs +templates/qtclass/qtclass.vstemplate +templates/translation/Properties/AssemblyInfo.tt.cs +templates/translation/translation.vstemplate diff --git a/Changelog b/Changelog index 84198b6..811ebba 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,34 @@ +Qt Visual Studio Tools version 2.9.0: + +Changes +------- + - Added QStringRef and QStringView debug visualizers + - Check if Qt translation tools are available + - New widget class wizards accessible from "Add New Item" + - New Qt class wizards accessible from "Add New Item" + - InfoBar notification of missing Qt installation + - InfoBar notification of recently installed new Qt VS Tools version + - Additional compiler options from Qt included in the build + - Enabled reporting issues and feature requests via GitHub + - Debug visualizer for Qt types added to PDB + - Improved intellisense performance for Qt projects +- Fixed QTVSADDINBUG-626: Qt VS Tools does not generate the same code as Qt Creator +- Fixed QTVSADDINBUG-707: Integrating the main window widget into the Qt Gui application wizard. +- Fixed QTVSADDINBUG-884: QStringRef and QStringView have no natvis definitions +- Fixed QTVSADDINBUG-925: Can't add an "add-on" module to project using GUI +- Fixed QTVSADDINBUG-937: OpenGL Widgets module missing +- Fixed QTVSADDINBUG-951: Can't build QT6 WebEngine example +- Fixed QTVSADDINBUG-965: Pragma warning not working with "external header warning level" option +- Fixed QTVSADDINBUG-966: Debug version of Qt Dlls are linked even if we asked for release mode +- Fixed QTVSADDINBUG-970: Qt6 in Visual Studio plugin doesn't load qmake projects +- Fixed QTVSADDINBUG-972: VS Plugin is ignoring module core5compat when loading project with QT6 +- Fixed QTVSADDINBUG-973: unable to add a new qt version with visual studio 2022 +- Fixed QTVSADDINBUG-979: Project Properties are overwritten by Qt Vs Tools +- Fixed QTVSADDINBUG-980: The "Release Notes" link does not work +- Fixed QTVSADDINBUG-982: Can't add new Qt Version + + + Qt Visual Studio Tools version 2.8.1: Changes diff --git a/GUIDELINES.using-directive.md b/GUIDELINES.using-directive.md new file mode 100644 index 0000000..89c471b --- /dev/null +++ b/GUIDELINES.using-directive.md @@ -0,0 +1,54 @@ +# Coding guidelines -- `using` directives + +Three kinds of `using` directives are available: + * **Reference**: `using <namespace>` -- _namespace_ can be omitted when referencing types. + * **Alias**: `using <alias> = <namespace|type>` -- _alias_ can be used in place of _namespace_ + or _type_. + * **Static**: `using static <type>` -- all static members of _type_ are accessible without + having to specify the type name. + +The following conventions apply to `using` directives in the Qt VS Tools code: + * `using` directives are grouped by root namespace, and ordered alphabetically within each group. + * Directives that reference external namespaces are located at the start of the source file, + before the local namespace declaration. + * The order of external namespace groups is as follows: + 1. `System*` namespaces. + 2. `Microsoft*` namespaces. + 3. `EnvDTE*` namespaces. + 4. All other external namespaces. + * Directives referencing in-solution namespaces (i.e. `QtVsTools*` or `QtVsTest*` namespaces) are + nested within the local namespace block. + * In-solution reference directives will use an abbreviated form of the namespace, whenever + possible. + * Alias and static directives can be specified either at top-level or nested in the local + namespace. + * Alias directives are specified after all reference directives. + * Static directives are specified after all reference directives and all alias directives. + * Optionally, directives of different kinds can be separated with an empty line. + +## Example +```csharp +using System; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; +using EnvDTE; +using EnvDTE80; + +using Task = System.Threading.Tasks.Task; + +namespace QtVsTools +{ + using Core; + using QtMsBuild; + + using RegExprParser = SyntaxAnalysis.RegExpr.Parser; + + using static SyntaxAnalysis.RegExpr; + + class ... +``` diff --git a/QMakeFileReader/evaluator/proitems.cpp b/QMakeFileReader/evaluator/proitems.cpp index 4212155..59ab2e0 100644 --- a/QMakeFileReader/evaluator/proitems.cpp +++ b/QMakeFileReader/evaluator/proitems.cpp @@ -341,7 +341,7 @@ totalLength += this_.at(i).size(); if (sz) - totalLength += sepSize * (sz - 1); + totalLength += int(sepSize) * (sz - 1); QString res(totalLength, Qt::Uninitialized); QChar *ptr = (QChar *)res.constData(); diff --git a/QtMSBuild/QtMSBuild.csproj b/QtMSBuild/QtMSBuild.csproj index 5898f7f..6f5d35c 100644 --- a/QtMSBuild/QtMSBuild.csproj +++ b/QtMSBuild/QtMSBuild.csproj @@ -67,24 +67,42 @@ <ItemGroup> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> <Reference Include="System" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Runtime" /> <Reference Include="$(VCTargetsPath)\Application Type\Linux\1.0\Microsoft.Build.Linux.Tasks.dll" /> <Reference Include="$(VCTargetsPath)\Application Type\Linux\1.0\liblinux.dll" /> </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - // Version specific references + // General package references // --> <Import Project="$(SolutionDir)\references.props" /> <ItemGroup> - <PackageReference Include="Microsoft.Build" - Version="$(Version_Microsoft_Build)" /> - <PackageReference Include="Microsoft.Build.Framework" - Version="$(Version_Microsoft_Build_Framework)" /> - <PackageReference Include="Microsoft.Build.Tasks.Core" - Version="$(Version_Microsoft_Build_Tasks_Core)" /> - <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" - Version="$(Version_Microsoft_Bcl_AsyncInterfaces)" /> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + <PackageReference Include="$(Name_Microsoft_Build)" Version="$(Version_Microsoft_Build)" /> + <PackageReference Include="$(Name_Microsoft_Build_Tasks_Core)" Version="$(Version_Microsoft_Build_Tasks_Core)" /> </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_RpcContracts)" Version="$(Version_Microsoft_VisualStudio_RpcContracts)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// // Solution project references @@ -112,6 +130,12 @@ <DesignTime>True</DesignTime> <DependentUpon>AssemblyInfo.cs</DependentUpon> </Compile> + <Content Include="QtMSBuild\qt5.natvis.xml"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </Content> + <Content Include="QtMSBuild\qt6.natvis.xml"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </Content> <!-- /////////////////////////////////////////////////////////////////////////////////////////////// // Qt/MSBuild common property pages and targets @@ -145,6 +169,10 @@ <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> <Content Include="QtMSBuild\qt_vars.targets"> + <SubType>Designer</SubType> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </Content> + <Content Include="QtMSBuild\qt_inner.targets"> <SubType>Designer</SubType> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> @@ -380,6 +408,7 @@ // Inline tasks // --> <Compile Include="Tasks\CriticalSection.cs" /> + <Compile Include="Tasks\QtRunTask.cs" /> <Compile Include="Tasks\GetVarsFromMSBuild.cs" /> <Compile Include="Tasks\HostExec_LinuxWSL_Error.cs" /> <Compile Include="Tasks\HostTranslatePaths_LinuxWSL_Error.cs" /> diff --git a/QtMSBuild/QtMsBuild/qt5.natvis.xml b/QtMSBuild/QtMsBuild/qt5.natvis.xml new file mode 100644 index 0000000..935d20b --- /dev/null +++ b/QtMSBuild/QtMsBuild/qt5.natvis.xml @@ -0,0 +1,835 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + **************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + **************************************************************************** +--> + +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + + <Type Name="##NAMESPACE##::QPoint"> + <AlternativeType Name="##NAMESPACE##::QPointF"/> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QRect"> + <DisplayString>{{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }}</DisplayString> + <Expand> + <Item Name="[x]">x1</Item> + <Item Name="[y]">y1</Item> + <Item Name="[width]">x2 - x1 + 1</Item> + <Item Name="[height]">y2 - y1 + 1</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QRectF"> + <DisplayString>{{ x = {xp}, y = {yp}, width = {w}, height = {h} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[width]">w</Item> + <Item Name="[height]">h</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QSize"> + <AlternativeType Name="##NAMESPACE##::QSizeF"/> + <DisplayString>{{ width = {wd}, height = {ht} }}</DisplayString> + <Expand> + <Item Name="[width]">wd</Item> + <Item Name="[height]">ht</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QLine"> + <AlternativeType Name="##NAMESPACE##::QLineF"/> + <DisplayString>{{ start point = {pt1}, end point = {pt2} }}</DisplayString> + <Expand> + <Synthetic Name="[start point]"> + <DisplayString>{pt1}</DisplayString> + <Expand> + <ExpandedItem>pt1</ExpandedItem> + </Expand> + </Synthetic> + <Synthetic Name="[end point]"> + <DisplayString>{pt2}</DisplayString> + <Expand> + <ExpandedItem>pt2</ExpandedItem> + </Expand> + </Synthetic> + + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QPolygon"> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(##NAMESPACE##::QPoint*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QPolygonF"> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[closed]"> + d->size > 0 + && ((((##NAMESPACE##::QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).xp + == (((##NAMESPACE##::QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).xp) + && ((((##NAMESPACE##::QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).yp + == (((##NAMESPACE##::QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).yp) + </Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(##NAMESPACE##::QPointF*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name ="##NAMESPACE##::QVector2D"> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name ="##NAMESPACE##::QVector3D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + </Expand> + </Type> + + <Type Name ="##NAMESPACE##::QVector4D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + <Item Name="[w]">wp</Item> + </Expand> + </Type> + + <Type Name ="##NAMESPACE##::QMatrix"> + <DisplayString> + {{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">_m11</Item> + <Item Name="[m12]">_m12</Item> + <Item Name="[m21]">_m21</Item> + <Item Name="[m22]">_m22</Item> + <Item Name="[dx]">_dx</Item> + <Item Name="[dy]">_dy</Item> + </Expand> + </Type> + + <Type Name ="##NAMESPACE##::QMatrix4x4"> + <DisplayString> + {{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">m[0][0]</Item> + <Item Name="[m12]">m[1][0]</Item> + <Item Name="[m13]">m[2][0]</Item> + <Item Name="[m14]">m[3][0]</Item> + <Item Name="[m21]">m[0][1]</Item> + <Item Name="[m22]">m[1][1]</Item> + <Item Name="[m23]">m[2][1]</Item> + <Item Name="[m24]">m[3][1]</Item> + <Item Name="[m31]">m[0][2]</Item> + <Item Name="[m32]">m[1][2]</Item> + <Item Name="[m33]">m[2][2]</Item> + <Item Name="[m34]">m[3][2]</Item> + <Item Name="[m41]">m[0][3]</Item> + <Item Name="[m42]">m[1][3]</Item> + <Item Name="[m43]">m[2][3]</Item> + <Item Name="[m44]">m[3][3]</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QSizePolicy"> + <DisplayString> + {{ horizontal = {static_cast<Policy>(bits.horPolicy)}, vertical = {static_cast<Policy>(bits.verPolicy)}, type = {ControlType(1 << bits.ctype)} }} + </DisplayString> + <Expand> + <Synthetic Name="[vertical policy]"> + <DisplayString>##NAMESPACE##::QSizePolicy::Policy::{static_cast<Policy>(bits.verPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[horizontal policy]"> + <DisplayString>##NAMESPACE##::QSizePolicy::Policy::{static_cast<Policy>(bits.horPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[control type]"> + <DisplayString>##NAMESPACE##::QSizePolicy::ControlType::{ControlType(1 << bits.ctype)}</DisplayString> + </Synthetic> + <Synthetic Name="[expanding directions]"> + <DisplayString + Condition="(static_cast<Policy>(bits.verPolicy) & ExpandFlag)"> + ##NAMESPACE##::Qt::Vertical (2) + </DisplayString> + <DisplayString + Condition="(static_cast<Policy>(bits.horPolicy) & ExpandFlag)"> + ##NAMESPACE##::Qt::Horizontal (1) + </DisplayString> + </Synthetic> + <Item Name="[vertical stretch]">static_cast<int>(bits.verStretch)</Item> + <Item Name="[horizontal stretch]">static_cast<int>(bits.horStretch)</Item> + <Item Name="[has height for width]">bits.hfw == 1</Item> + <Item Name="[has width for height]">bits.wfh == 1</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QChar"> + <DisplayString>{ucs,c}</DisplayString> + <StringView>ucs,c</StringView> + <Expand> + <Item Name="[latin 1]">ucs > 0xff ? '\0' : char(ucs),c</Item> + <Item Name="[unicode]">ucs,c</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QString"> + <DisplayString>{((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub}</DisplayString> + <StringView>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub</StringView> + <Expand> + <Item Name="[size]">d->size</Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),c</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QStringRef"> + <Intrinsic Name="offset" Expression="(reinterpret_cast<char16_t*>(m_string->d)) + + m_string->d->offset / 2" /> + <DisplayString Condition="m_string == nullptr">{m_string,[m_size]} u""</DisplayString> + <DisplayString Condition="m_string != nullptr">{offset() + m_position,[m_size]}</DisplayString> + <Expand> + <Item Name="[position]" ExcludeView="simple">m_position</Item> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems Condition="m_string != nullptr"> + <Size>m_size</Size> + <ValuePointer>offset()+m_position</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QStringView"> + <DisplayString>{m_data,[m_size]}</DisplayString> + <StringView>m_data,[m_size]</StringView> + <Expand> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems> + <Size>m_size</Size> + <ValuePointer>m_data</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QByteArray"> + <DisplayString>{((reinterpret_cast<char*>(d)) + d->offset),sb}</DisplayString> + <StringView>((reinterpret_cast<char*>(d)) + d->offset),sb</StringView> + <Expand> + <Item Name="[size]">d->size</Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>((reinterpret_cast<char*>(d)) + d->offset),c</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QUrl"> + <Intrinsic Name="isEmpty" Expression="size==0"> + <Parameter Name="size" Type="int"/> + </Intrinsic> + <Intrinsic Name="memberOffset" Expression="sizeof(QAtomicInt) + sizeof(int) + (sizeof(QString) * count)"> + <Parameter Name="count" Type="int"/> + </Intrinsic> + <Intrinsic Name="scheme" Expression="*((QString*)(((char*)(d) + memberOffset(0))))" /> + <Intrinsic Name="username" Expression="*((QString*)(((char*)(d) + memberOffset(1))))" /> + <Intrinsic Name="password" Expression="*((QString*)(((char*)(d) + memberOffset(2))))" /> + <Intrinsic Name="host" Expression="*((QString*)(((char*)(d) + memberOffset(3))))" /> + <Intrinsic Name="path" Expression="*((QString*)(((char*)(d) + memberOffset(4))))" /> + <Intrinsic Name="query" Expression="*((QString*)(((char*)(d) + memberOffset(5))))" /> + <Intrinsic Name="fragment" Expression="*((QString*)(((char*)(d) + memberOffset(6))))" /> + + <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> + <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> + <Expand> + <Item Name="[scheme]">scheme()</Item> + <Item Name="[username]">username()</Item> + <Item Name="[password]">password()</Item> + <Item Name="[host]">host()</Item> + <Item Name="[path]">path()</Item> + <Item Name="[query]">query()</Item> + <Item Name="[fragment]">fragment()</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QBitArray"> + <DisplayString>{{ size = {(d.d->size << 3) - *((reinterpret_cast<char*>(d.d)) + d.d->offset)} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d.d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>(d.d->size << 3) - *((reinterpret_cast<char*>(d.d)) + d.d->offset)</Size> + <ValueNode> + (*(reinterpret_cast<const unsigned char*>((reinterpret_cast<char*>(d.d)) + d.d->offset) + 1 + + ($i >> 3)) & (1 << ($i & 7))) != 0 + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QVarLengthArray<*>"> + <AlternativeType Name="##NAMESPACE##::QVarLengthArray<*, int>"/> + <DisplayString>{{ size = {s} }}</DisplayString> + <Expand> + <Item Name="[capacity]">a</Item> + <ArrayItems> + <Size>s</Size> + <ValuePointer>ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QDate"> + <DisplayString>{{ julian day = {jd} }}</DisplayString> + <Expand></Expand> + </Type> + + <Type Name="##NAMESPACE##::QTime"> + <DisplayString + Condition="mds == 1">{{ millisecond = {mds} }}</DisplayString> + <DisplayString + Condition="mds != 1">{{ milliseconds = {mds} }}</DisplayString> + <Expand> + <Item Name="[hour]" + Condition="(mds / 3600000) == 1">mds / 3600000, d</Item> + <Item Name="[hours]" + Condition="(mds / 3600000) != 1">mds / 3600000, d</Item> + <Item Name="[minute]" + Condition="((mds % 3600000) / 60000) == 1">(mds % 3600000) / 60000, d</Item> + <Item Name="[minutes]" + Condition="((mds % 3600000) / 60000) != 1">(mds % 3600000) / 60000, d</Item> + <Item Name="[second]" + Condition="((mds / 1000) % 60) == 1">(mds / 1000) % 60, d</Item> + <Item Name="[seconds]" + Condition="((mds / 1000) % 60) != 1">(mds / 1000) % 60, d</Item> + <Item Name="[millisecond]" + Condition="(mds % 1000) == 1">mds % 1000, d</Item> + <Item Name="[milliseconds]" + Condition="(mds % 1000) != 1">mds % 1000, d</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QRegularExpression"> + <DisplayString>{d.pattern}</DisplayString> + </Type> + + <Type Name="##NAMESPACE##::QSharedData"> + <Expand> + <Item Name="[referenced]">ref._q_value</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QSharedPointer<*>"> + <DisplayString>strong reference to shared pointer of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">value == 0</Item> + <Item Name="[weak referenced]">d->weakref._q_value</Item> + <Item Name="[strong referenced]">d->strongref._q_value</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QSharedDataPointer<*>"> + <DisplayString>pointer to implicit shared object of type {"$T1"}</DisplayString> + <Expand> + <ExpandedItem>d</ExpandedItem> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QExplicitlySharedDataPointer<*>"> + <DisplayString>pointer to explicit shared object of type {"$T1"}</DisplayString> + <Expand> + <ExpandedItem>d</ExpandedItem> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QPointer<*>"> + <DisplayString>guarded pointer to subclass of QObject of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">wp.d == 0 || wp.d->strongref._q_value == 0 || wp.value == 0</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QWeakPointer<*>"> + <DisplayString>weak reference to shared pointer of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">d == 0 || d->strongref._q_value == 0 || value == 0</Item> + <Item Name="[weak referenced]">d->weakref._q_value</Item> + <Item Name="[strong referenced]">d->strongref._q_value</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QScopedPointer<*>"> + <DisplayString>scoped pointer to a dynamically allocated object of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">!d</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QScopedArrayPointer<*>"> + <DisplayString>scoped pointer to dynamically allocated array of objects of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">!d</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QPair<*,*>"> + <DisplayString>({first}, {second})</DisplayString> + <Expand> + <Item Name="[first]">first</Item> + <Item Name="[second]">second</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QVector<*>"> + <AlternativeType Name="##NAMESPACE##::QStack<*>"></AlternativeType> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>($T1*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QList<*>"> + <AlternativeType Name="##NAMESPACE##::QQueue<*>"></AlternativeType> + <DisplayString>{{ size = {d->end - d->begin} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>d->end - d->begin</Size> + <ValueNode>*reinterpret_cast<$T1*>((sizeof($T1) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<$T1*>(d->array + d->begin + $i)) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QStringList"> + <DisplayString>{{ size = {d->end - d->begin} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>d->end - d->begin</Size> + <ValueNode> + *reinterpret_cast<QString*>((sizeof(QString) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QString*>(d->array + d->begin + $i)) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QList<QVariant>"> + <DisplayString>{{ size = {d->end - d->begin} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>d->end - d->begin</Size> + <ValueNode> + *reinterpret_cast<QVariant*>((sizeof(QVariant) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QVariant*>(d->array + d->begin + $i)) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QLinkedList<*>"> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <LinkedListItems> + <Size>d->size</Size> + <HeadPointer>d->n</HeadPointer> + <NextPointer>n</NextPointer> + <ValueNode>(*(##NAMESPACE##::QLinkedListNode<$T1>*)this).t</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QMapNode<*,*>"> + <DisplayString>({key}, {value})</DisplayString> + <Expand> + <Item Name="[key]">key</Item> + <Item Name="[value]">value</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QMap<*,*>"> + <AlternativeType Name="##NAMESPACE##::QMultiMap<*,*>"/> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <TreeItems> + <Size>d->size</Size> + <HeadPointer>d->header.left</HeadPointer> + <LeftPointer>left</LeftPointer> + <RightPointer>right</RightPointer> + <ValueNode>*((##NAMESPACE##::QMapNode<$T1,$T2>*)this)</ValueNode> + </TreeItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QHashNode<*,*>"> + <DisplayString Condition="next == 0">(empty)</DisplayString> + <DisplayString Condition="next != 0">({key}, {value})</DisplayString> + <Expand> + <Item Name="[key]" Condition="next != 0">key</Item> + <Item Name="[value]" Condition="next != 0">value</Item> + <Item Name="[next]" Condition="next != 0">next</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QHash<*,*>"> + <AlternativeType Name="##NAMESPACE##::QMultiHash<*,*>"/> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <ArrayItems IncludeView="buckets"> + <Size>d->numBuckets</Size> + <ValuePointer>reinterpret_cast<Node **>(d->buckets)</ValuePointer> + </ArrayItems> + <CustomListItems ExcludeView="buckets"> + <Variable Name="n" InitialValue="d->numBuckets"/> + <Variable Name="bucket" InitialValue="d->buckets"/> + <Variable Name="node" InitialValue="d->buckets[0]"/> + <Variable Name="keyValuePair" InitialValue="reinterpret_cast<Node *>(0)"/> + <Size>d->size</Size> + <Loop> + <Break Condition="n == 0"/> + <Exec>node = *(bucket++)</Exec> + <Exec>--n</Exec> + <Loop> + <Break Condition="!node || !node->next"/> + <Exec>keyValuePair = reinterpret_cast<Node *>(node)</Exec> + <Item Name="[{keyValuePair->key}]">keyValuePair->value</Item> + <Exec>node = node->next</Exec> + </Loop> + </Loop> + </CustomListItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QHashNode<*,##NAMESPACE##::QHashDummyValue>"> + <DisplayString Condition="next == 0">(empty)</DisplayString> + <DisplayString Condition="next != 0">({key})</DisplayString> + <Expand> + <Item Name="[key]" Condition="next != 0">key</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QSet<*>"> + <DisplayString>{{ size = {q_hash.d->size} }}</DisplayString> + <Expand> + <ExpandedItem>q_hash</ExpandedItem> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QCache<*,*>::Node"> + <DisplayString>({*keyPtr}, {*t})</DisplayString> + <Expand> + <Item Name="[key]">*keyPtr</Item> + <Item Name="[value]">*t</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QCache<*,*>"> + <DisplayString>{{ size = {hash.d->size} }}</DisplayString> + <Expand> + <Item Name="[max coast]">mx</Item> + <Item Name="[total coast]">total</Item> + <Item Name="[referenced]">hash.d->ref.atomic._q_value</Item> + <LinkedListItems> + <Size>hash.d->size</Size> + <HeadPointer>f</HeadPointer> + <NextPointer>n</NextPointer> + <ValueNode>*((Node*)this)</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QStandardItemPrivate"> + <Intrinsic Name="memberOffset" Expression="sizeof(QStandardItemModel *) + + sizeof(QStandardItem *) + + sizeof(int *) + + sizeof(int *) + + (sizeof(int) * count)"> + <Parameter Name="count" Type="int"/> + </Intrinsic> + <Intrinsic Name="rows" Expression="*((int*)(((char*)(this)) + memberOffset(0)))" /> + <Intrinsic Name="columns" Expression="*((int*)(((char*)(this)) + memberOffset(1)))" /> + </Type> + + <Type Name="##NAMESPACE##::QStandardItem"> + <DisplayString>{{ row count = {(*d_ptr.d).rows()}, column count = {(*d_ptr.d).columns()} }}</DisplayString> + <Expand> + <Item Name="[d]">d_ptr.d,!</Item> + <Item Name="[row count]">(*d_ptr.d).rows()</Item> + <Item Name="[column count]">(*d_ptr.d).columns()</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QVariant"> + <!--Region DisplayString QVariant--> + + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::UnknownType">Invalid</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::Bool">{d.data.b}</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::Int">{d.data.i}</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::UInt">{d.data.u}</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::LongLong">{d.data.ll}</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::ULongLong">{d.data.ull}</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::Double">{d.data.d}</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QChar">{d.data.c}</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QVariantMap"> + {*((##NAMESPACE##::QMap<##NAMESPACE##::QString,##NAMESPACE##::QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QVariantList"> + {*((##NAMESPACE##::QList<##NAMESPACE##::QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QString"> + {*((##NAMESPACE##::QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QStringList"> + {*((##NAMESPACE##::QStringList*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QByteArray"> + {*((##NAMESPACE##::QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QBitArray"> + {*((##NAMESPACE##::QBitArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QDate"> + {*((##NAMESPACE##::QDate*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QTime"> + {*((##NAMESPACE##::QTime*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QDateTime">DateTime</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QUrl">Url</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QLocale">Locale</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QRect"> + {*((##NAMESPACE##::QRect*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QRectF"> + {*((##NAMESPACE##::QRectF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QSize"> + {*((##NAMESPACE##::QSize*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QSizeF"> + {*((##NAMESPACE##::QSizeF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QLine"> + {*((##NAMESPACE##::QLine*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QLineF"> + {*((##NAMESPACE##::QLineF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QPoint"> + {*((##NAMESPACE##::QPoint*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QPointF"> + {*((##NAMESPACE##::QPointF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QRegExp">RegExp</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QRegularExpression">RegularExpression</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QVariantHash"> + {*((##NAMESPACE##::QHash<##NAMESPACE##::QString,##NAMESPACE##::QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QEasingCurve">EasingCurve</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QUuid">Uuid</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QModelIndex">ModelIndex</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::LastCoreType">LastCoreType</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QFont">Font</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QPixmap">Pixmap</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QBrush">Brush</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QColor">Color</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QPalette">Palette</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QImage">Image</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QPolygon">Polygon</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QRegion">Region</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QBitmap">Bitmap</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QCursor">Cursor</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QKeySequence">KeySequence</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QPen">Pen</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QTextLength">TextLength</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QTextFormat">TextFormat</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QMatrix">Matrix</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QTransform">Transform</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QMatrix4x4">Matrix4x4</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QVector2D">Vector2D</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QVector3D">Vector3D</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QVector4D">Vector4D</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QQuaternion">Quaternion</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QPolygonF">PolygonF</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QIcon">Icon</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::LastGuiType">LastGuiType</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::QSizePolicy">SizePolicy</DisplayString> + <DisplayString Condition="d.type == ##NAMESPACE##::QMetaType::User">UserType</DisplayString> + <DisplayString Condition="d.type == 0xffffffff">LastType</DisplayString> + + <!--End region DisplayString QVariant--> + + <!--Region DisplayView QVariant--> + + <StringView Condition="d.type == ##NAMESPACE##::QMetaType::QChar">d.data.c</StringView> + + <StringView Condition="d.type == ##NAMESPACE##::QMetaType::QString"> + *((##NAMESPACE##::QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </StringView> + + <StringView Condition="d.type == ##NAMESPACE##::QMetaType::QByteArray"> + *((##NAMESPACE##::QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </StringView> + + <!--End region DisplayView QVariant--> + + <!--Region Expand QVariant--> + + <Expand> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QVariantMap"> + *((##NAMESPACE##::QMap<##NAMESPACE##::QString,##NAMESPACE##::QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QVariantList"> + *((##NAMESPACE##::QList<##NAMESPACE##::QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QString"> + *((##NAMESPACE##::QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QStringList"> + *((##NAMESPACE##::QStringList*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QByteArray"> + *((##NAMESPACE##::QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QBitArray"> + *((##NAMESPACE##::QBitArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QDate"> + *((##NAMESPACE##::QDate*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QTime"> + *((##NAMESPACE##::QTime*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QRect"> + *((##NAMESPACE##::QRect*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QRectF"> + *((##NAMESPACE##::QRectF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QSize"> + *((##NAMESPACE##::QSize*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QSizeF"> + *((##NAMESPACE##::QSizeF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QLine"> + *((##NAMESPACE##::QLine*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QLineF"> + *((##NAMESPACE##::QLineF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QPoint"> + *((##NAMESPACE##::QPoint*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QPointF"> + *((##NAMESPACE##::QPointF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == ##NAMESPACE##::QMetaType::QVariantHash"> + *((##NAMESPACE##::QHash<##NAMESPACE##::QString,##NAMESPACE##::QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + </Expand> + + <!--End region Expand QVariant--> + </Type> + +</AutoVisualizer> diff --git a/QtMSBuild/QtMsBuild/qt6.natvis.xml b/QtMSBuild/QtMsBuild/qt6.natvis.xml new file mode 100644 index 0000000..6f4a131 --- /dev/null +++ b/QtMSBuild/QtMsBuild/qt6.natvis.xml @@ -0,0 +1,406 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + **************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + **************************************************************************** +--> + +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + + <Type Name="##NAMESPACE##::QSpecialInteger<*>"> + <DisplayString>{val}</DisplayString> + <Expand> + <Item Name="[value]">val</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QBasicAtomicInteger<*>"> + <DisplayString>{_q_value}</DisplayString> + <Expand> + <Item Name="[value]">_q_value</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QBasicAtomicPointer<*>"> + <Intrinsic Name="isNull" Expression="value()==0" /> + <Intrinsic Name="value" Expression="_q_value.value()" /> + <DisplayString Condition="isNull()">empty</DisplayString> + <DisplayString Condition="!isNull()">{_q_value}</DisplayString> + <Expand> + <Item Name=" " Condition="!isNull()">*value()</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QPoint"> + <AlternativeType Name="##NAMESPACE##::QPointF"/> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QRect"> + <DisplayString>{{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }}</DisplayString> + <Expand> + <Item Name="[x]">x1</Item> + <Item Name="[y]">y1</Item> + <Item Name="[width]">x2 - x1 + 1</Item> + <Item Name="[height]">y2 - y1 + 1</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QRectF"> + <DisplayString>{{ x = {xp}, y = {yp}, width = {w}, height = {h} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[width]">w</Item> + <Item Name="[height]">h</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QSize"> + <AlternativeType Name="##NAMESPACE##::QSizeF"/> + <DisplayString>{{ width = {wd}, height = {ht} }}</DisplayString> + <Expand> + <Item Name="[width]">wd</Item> + <Item Name="[height]">ht</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QLine"> + <AlternativeType Name="##NAMESPACE##::QLineF"/> + <DisplayString>{{ start point = {pt1}, end point = {pt2} }}</DisplayString> + <Expand> + <Synthetic Name="[start point]"> + <DisplayString>{pt1}</DisplayString> + <Expand> + <ExpandedItem>pt1</ExpandedItem> + </Expand> + </Synthetic> + <Synthetic Name="[end point]"> + <DisplayString>{pt2}</DisplayString> + <Expand> + <ExpandedItem>pt2</ExpandedItem> + </Expand> + </Synthetic> + + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QPolygon"> + <DisplayString>{{ size={d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPoint*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QPolygonF"> + <DisplayString>{{ size={d->size} }}</DisplayString> + <Expand> + <Item Name="[closed]"> + d->size > 0 + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).xp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).xp) + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).yp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).yp) + </Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPointF*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QVector2D"> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QVector3D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QVector4D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + <Item Name="[w]">wp</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QMatrix"> + <DisplayString> + {{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">_m11</Item> + <Item Name="[m12]">_m12</Item> + <Item Name="[m21]">_m21</Item> + <Item Name="[m22]">_m22</Item> + <Item Name="[dx]">_dx</Item> + <Item Name="[dy]">_dy</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QMatrix4x4"> + <DisplayString> + {{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">m[0][0]</Item> + <Item Name="[m12]">m[1][0]</Item> + <Item Name="[m13]">m[2][0]</Item> + <Item Name="[m14]">m[3][0]</Item> + <Item Name="[m21]">m[0][1]</Item> + <Item Name="[m22]">m[1][1]</Item> + <Item Name="[m23]">m[2][1]</Item> + <Item Name="[m24]">m[3][1]</Item> + <Item Name="[m31]">m[0][2]</Item> + <Item Name="[m32]">m[1][2]</Item> + <Item Name="[m33]">m[2][2]</Item> + <Item Name="[m34]">m[3][2]</Item> + <Item Name="[m41]">m[0][3]</Item> + <Item Name="[m42]">m[1][3]</Item> + <Item Name="[m43]">m[2][3]</Item> + <Item Name="[m44]">m[3][3]</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QSizePolicy"> + <DisplayString> + {{ horizontal = {static_cast<Policy>(bits.horPolicy)}, vertical = {static_cast<Policy>(bits.verPolicy)}, type = {ControlType(1 << bits.ctype)} }} + </DisplayString> + <Expand> + <Synthetic Name="[vertical policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.verPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[horizontal policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.horPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[control type]"> + <DisplayString>QSizePolicy::ControlType::{ControlType(1 << bits.ctype)}</DisplayString> + </Synthetic> + <Synthetic Name="[expanding directions]"> + <DisplayString + Condition="(static_cast<Policy>(bits.verPolicy) & ExpandFlag)"> + Qt::Vertical (2) + </DisplayString> + <DisplayString + Condition="(static_cast<Policy>(bits.horPolicy) & ExpandFlag)"> + Qt::Horizontal (1) + </DisplayString> + </Synthetic> + <Item Name="[vertical stretch]">static_cast<int>(bits.verStretch)</Item> + <Item Name="[horizontal stretch]">static_cast<int>(bits.horStretch)</Item> + <Item Name="[has height for width]">bits.hfw == 1</Item> + <Item Name="[has width for height]">bits.wfh == 1</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QChar"> + <DisplayString>{ucs,c}</DisplayString> + <StringView>ucs,c</StringView> + <Expand> + <Item Name="[latin 1]">ucs > 0xff ? '\0' : char(ucs),c</Item> + <Item Name="[unicode]">ucs,c</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QString"> + <DisplayString>"{(reinterpret_cast<unsigned short*>(d.ptr)),sub}"</DisplayString> + <StringView>(reinterpret_cast<unsigned short*>(d.ptr)),sub</StringView> + <Expand> + <Item Name="[size]">d.size</Item> + <ArrayItems> + <Size>d.size</Size> + <ValuePointer>d.ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QStringRef"> + <DisplayString Condition="m_string == nullptr">{m_string,[m_size]} u""</DisplayString> + <DisplayString Condition="m_string != nullptr">{m_string->d.ptr+m_position,[m_size]}</DisplayString> + <StringView Condition="m_string == nullptr">""</StringView> + <StringView Condition="m_string != nullptr">m_string,[m_position+m_size]</StringView> + <Expand> + <Item Name="[position]" ExcludeView="simple">m_position</Item> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems Condition="m_string != nullptr"> + <Size>m_size</Size> + <ValuePointer>m_string->d.ptr+m_position</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QStringView"> + <DisplayString>{m_data,[m_size]}</DisplayString> + <StringView>m_data,[m_size]</StringView> + <Expand> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems> + <Size>m_size</Size> + <ValuePointer>m_data</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QByteArray"> + <DisplayString>"{((reinterpret_cast<char*>(d.ptr))),sb}"</DisplayString> + <StringView>((reinterpret_cast<char*>(d.ptr))),sb</StringView> + <Expand> + <Item Name="[size]">d.size</Item> + <ArrayItems> + <Size>d.size</Size> + <ValuePointer>d.ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QUrl"> + <Intrinsic Name="isEmpty" Expression="size==0"> + <Parameter Name="size" Type="int"/> + </Intrinsic> + <Intrinsic Name="memberOffset" Expression="sizeof(QAtomicInt) + sizeof(int) + (sizeof(QString) * count)"> + <Parameter Name="count" Type="int"/> + </Intrinsic> + <Intrinsic Name="scheme" Expression="*((QString*)(((char*)(d) + memberOffset(0))))" /> + <Intrinsic Name="username" Expression="*((QString*)(((char*)(d) + memberOffset(1))))" /> + <Intrinsic Name="password" Expression="*((QString*)(((char*)(d) + memberOffset(2))))" /> + <Intrinsic Name="host" Expression="*((QString*)(((char*)(d) + memberOffset(3))))" /> + <Intrinsic Name="path" Expression="*((QString*)(((char*)(d) + memberOffset(4))))" /> + <Intrinsic Name="query" Expression="*((QString*)(((char*)(d) + memberOffset(5))))" /> + <Intrinsic Name="fragment" Expression="*((QString*)(((char*)(d) + memberOffset(6))))" /> + + <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> + <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> + <Expand> + <Item Name="[scheme]">scheme()</Item> + <Item Name="[username]">username()</Item> + <Item Name="[password]">password()</Item> + <Item Name="[host]">host()</Item> + <Item Name="[path]">path()</Item> + <Item Name="[query]">query()</Item> + <Item Name="[fragment]">fragment()</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QDate"> + <DisplayString>{{ julian day = {jd} }}</DisplayString> + </Type> + + <Type Name="##NAMESPACE##::QTime"> + <Intrinsic Name="hour" Expression="mds / 3600000" /> + <Intrinsic Name="minute" Expression="(mds % 3600000) / 60000" /> + <Intrinsic Name="second" Expression="(mds / 1000) % 60" /> + <Intrinsic Name="millisecond" Expression="mds % 1000" /> + <DisplayString Condition="mds == 1">{{ millisecond = {mds} }}</DisplayString> + <DisplayString Condition="mds != 1">{{ milliseconds = {mds} }}</DisplayString> + <Expand> + <Item Name="[hour]" + Condition="(mds / 3600000) == 1">hour(), d</Item> + <Item Name="[hours]" + Condition="(mds / 3600000) != 1">hour(), d</Item> + <Item Name="[minute]" + Condition="((mds % 3600000) / 60000) == 1">minute(), d</Item> + <Item Name="[minutes]" + Condition="((mds % 3600000) / 60000) != 1">minute(), d</Item> + <Item Name="[second]" + Condition="((mds / 1000) % 60) == 1">second(), d</Item> + <Item Name="[seconds]" + Condition="((mds / 1000) % 60) != 1">second(), d</Item> + <Item Name="[millisecond]" + Condition="(mds % 1000) == 1">millisecond(), d</Item> + <Item Name="[milliseconds]" + Condition="(mds % 1000) != 1">millisecond(), d</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QPair<*,*>"> + <DisplayString>({first}, {second})</DisplayString> + <Expand> + <Item Name="[first]">first</Item> + <Item Name="[second]">second</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QList<*>"> + <AlternativeType Name="##NAMESPACE##::QVector<*>"/> + <DisplayString>{{ size={d.size} }}</DisplayString> + <Expand> + <ArrayItems> + <Size>d.size</Size> + <ValuePointer>reinterpret_cast<$T1*>(d.ptr)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QVarLengthArray<*>"> + <DisplayString>{{ size={s} }}</DisplayString> + <Expand> + <Item Name="[capacity]">a</Item> + <ArrayItems> + <Size>s</Size> + <ValuePointer>ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QMap<*,*>"> + <AlternativeType Name="##NAMESPACE##::QMultiMap<*,*>"/> + <DisplayString>{{ size={d.d->m._Mypair._Myval2._Myval2._Mysize} }}</DisplayString> + <Expand> + <Item Name="[std::map]">d.d->m</Item> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QHash<*,*>"> + <AlternativeType Name="##NAMESPACE##::QMultiHash<*,*>"/> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + </Expand> + </Type> + +</AutoVisualizer> diff --git a/QtMSBuild/QtMsBuild/qt_defaults.props b/QtMSBuild/QtMsBuild/qt_defaults.props index d351b61..ee94d6b 100644 --- a/QtMSBuild/QtMsBuild/qt_defaults.props +++ b/QtMSBuild/QtMsBuild/qt_defaults.props @@ -71,6 +71,9 @@ <QtPathBinaries>bin</QtPathBinaries> <QtPathLibraryExecutables>bin</QtPathLibraryExecutables> + <!--// Run Qt tools during design-time build --> + <QtToolsDesignTime>true</QtToolsDesignTime> + <!--// qmake template --> <QtQMakeTemplate>vcapp</QtQMakeTemplate> @@ -89,6 +92,7 @@ DEFINES=/Project/ItemDefinitionGroup/ClCompile/PreprocessorDefinitions; INCLUDEPATH=/Project/ItemDefinitionGroup/ClCompile/AdditionalIncludeDirectories; STDCPP=/Project/ItemDefinitionGroup/ClCompile/LanguageStandard; + RUNTIME=/Project/ItemDefinitionGroup/ClCompile/RuntimeLibrary; CL_OPTIONS=/Project/ItemDefinitionGroup/ClCompile/AdditionalOptions; LIBS=/Project/ItemDefinitionGroup/Link/AdditionalDependencies; LINK_OPTIONS=/Project/ItemDefinitionGroup/Link/AdditionalOptions; @@ -103,6 +107,9 @@ <!--// Qt build config --> <QtBuildConfig Condition="'$(Configuration)' == 'Debug'">debug</QtBuildConfig> <QtBuildConfig Condition="'$(Configuration)' != 'Debug'">release</QtBuildConfig> + + <!--// Qt Plugin default--> + <QtPlugin>false</QtPlugin> </PropertyGroup> <!-- diff --git a/QtMSBuild/QtMsBuild/qt_globals.targets b/QtMSBuild/QtMsBuild/qt_globals.targets index a8cb31c..966a084 100644 --- a/QtMSBuild/QtMsBuild/qt_globals.targets +++ b/QtMSBuild/QtMsBuild/qt_globals.targets @@ -84,6 +84,29 @@ <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// + // Set up inner build if Qt vars property file is outdated + // --> + <PropertyGroup Condition="'$(QtInnerBuild)' == ''"> + <QtVarsOutdated>false</QtVarsOutdated> + <QtVarsOutdated + Condition="!Exists('$(QtVarsFilePath)') + OR '$(QtBkup_QtInstall)' != '$(QtInstall)' + OR '$(QtBkup_QtModules)' != '$(QtModules)' + OR '$(QtBkup_QtPathBinaries)' != '$(QtPathBinaries)' + OR '$(QtBkup_QtPathLibraryExecutables)' != '$(QtPathLibraryExecutables)' + OR '$(QtBkup_QtHeaderSearchPath)' != '$(QtHeaderSearchPath)' + OR '$(QtBkup_QtLibrarySearchPath)' != '$(QtLibrarySearchPath)' + OR '$(QtBkup_QtVars)' != '$(QtVars)' + OR '$(QtBkup_QMakeCodeLines)' != '$(QMakeCodeLines)' + OR '$(QtBkup_QtBuildConfig)' != '$(QtBuildConfig)'" + >true</QtVarsOutdated> + </PropertyGroup> + + <!-- // Enable inner build targets --> + <Import Condition="'$(QtVarsOutdated)' == 'true'" Project="qt_inner.targets"/> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// /// TARGET QtGetDefaultClCompile ///////////////////////////////////////////////////////////////////////////////////////////////// // Get default C++ properties @@ -201,7 +224,8 @@ OR ('$(project_changed)' == 'true' AND '$(log_hash)' != '$(work_hash)')" >true</do_work> <skip_work - Condition="'$(do_work)' != 'true' OR '$(DesignTimeBuild)' == 'true'" + Condition="'$(do_work)' != 'true' + OR ('$(QtDesignTimeBuild)' == 'true' AND '$(QtToolsDesignTime)' != 'true')" >true</skip_work> </PropertyGroup> @@ -268,8 +292,7 @@ // --> <QtRunWork Condition="'$(ApplicationType)' != 'Linux' AND '@(QtWork)' != '' - AND '%(QtWork.ParallelBuild)' == 'true' - AND '$(DesignTimeBuild)' != 'true'" + AND '%(QtWork.ParallelBuild)' == 'true'" QtWork="@(QtWork)" QtMaxProcs="$(QtMaxProcs)" QtDebug="$(QtDebug)"> <Output TaskParameter="Result" ItemName="QtWorkResult" /> </QtRunWork> @@ -280,8 +303,7 @@ // --> <QtRunWork Condition="'$(ApplicationType)' != 'Linux' AND '@(QtWork)' != '' - AND '%(QtWork.ParallelBuild)' != 'true' - AND '$(DesignTimeBuild)' != 'true'" + AND '%(QtWork.ParallelBuild)' != 'true'" QtWork="@(QtWork)" QtMaxProcs="1" QtDebug="$(QtDebug)"> <Output TaskParameter="Result" ItemName="QtWorkResult" /> </QtRunWork> @@ -293,13 +315,13 @@ <!-- // Translate local paths to host paths --> <Flatten Condition="'$(ApplicationType)' == 'Linux' - AND '@(QtWork)' != '' AND '$(DesignTimeBuild)' != 'true'" + AND '@(QtWork)' != '' AND '$(QtDesignTimeBuild)' != 'true'" Items="@(QtWork)" Metadata="ResourceFiles"> <Output TaskParameter="Result" ItemName="ResourceFiles"/> </Flatten> <ItemGroup Condition="'$(ApplicationType)' == 'Linux' - AND '@(QtWork)' != '' AND '$(DesignTimeBuild)' != 'true'"> + AND '@(QtWork)' != '' AND '$(QtDesignTimeBuild)' != 'true'"> <LocalPath Include="%(QtWork.Identity)"> <Name>InputPath</Name> <Item>%(QtWork.Identity)</Item> @@ -320,7 +342,7 @@ </ItemGroup> <HostTranslatePaths Condition="'$(ApplicationType)' == 'Linux' - AND '@(QtWork)' != '' AND '$(DesignTimeBuild)' != 'true'" + AND '@(QtWork)' != '' AND '$(QtDesignTimeBuild)' != 'true'" Items="@(LocalPath)" Names="InputPath;OutputPath"> <Output TaskParameter="Result" ItemName="HostPath"/> </HostTranslatePaths> @@ -332,7 +354,7 @@ <!-- // Run command --> <HostExec Condition="'$(ApplicationType)' == 'Linux' - AND '%(Identity)' != '' AND '$(DesignTimeBuild)' != 'true'" + AND '%(Identity)' != '' AND '$(QtDesignTimeBuild)' != 'true'" Message="@(QtWork->'%(WorkType) %(Identity)')" Command="@(QtWork->'%(ToolPath) %(Options)')" Inputs="@(InputPath)" @@ -344,7 +366,7 @@ <!-- // Generate result item --> <ItemGroup Condition="'$(ApplicationType)' == 'Linux' - AND '@(QtWork)' != '' AND '$(DesignTimeBuild)' != 'true'"> + AND '@(QtWork)' != '' AND '$(QtDesignTimeBuild)' != 'true'"> <QtWorkResult Include="@(QtWork)"> <ExitCode>0</ExitCode> </QtWorkResult> @@ -354,9 +376,11 @@ /////////////////////////////////////////////////////////////////////////////////////////////// // Save tracking log of files read during build; used by VS to check the up-to-date status // --> - <ItemGroup Condition="'$(DesignTimeBuild)' != 'true' AND '$(QtVSToolsBuild)' != 'true'"> + <ItemGroup> <read_log Include="^%(QtWorkResult.FullPath);%(QtWorkResult.AdditionalDependencies)" - Condition="'%(QtWorkResult.ExitCode)' == '0' AND '%(QtWorkResult.DisableLog)' != 'true'"> + Condition="'%(QtWorkResult.ExitCode)' == '0' + AND '%(QtWorkResult.DisableLog)' != 'true' + AND '%(QtWorkResult.Skipped)' != 'true'"> <WorkType>%(QtWorkResult.WorkType)</WorkType> </read_log> <read_log> @@ -377,9 +401,11 @@ /////////////////////////////////////////////////////////////////////////////////////////////// // Save tracking log of files written during build; used by VS to check the up-to-date status // --> - <ItemGroup Condition="'$(DesignTimeBuild)' != 'true' AND '$(QtVSToolsBuild)' != 'true'"> + <ItemGroup> <write_log Include="^%(QtWorkResult.FullPath);%(QtWorkResult.OutputFile)" - Condition="'%(QtWorkResult.ExitCode)' == '0' AND '%(QtWorkResult.DisableLog)' != 'true'"> + Condition="'%(QtWorkResult.ExitCode)' == '0' + AND '%(QtWorkResult.DisableLog)' != 'true' + AND '%(QtWorkResult.Skipped)' != 'true'"> <WorkType>%(QtWorkResult.WorkType)</WorkType> </write_log> <write_log> @@ -398,7 +424,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////// // Log output files; this is used by VS to determine what files to delete on "Clean" // --> - <ItemGroup Condition="'$(DesignTimeBuild)' != 'true' AND '$(QtVSToolsBuild)' != 'true'"> + <ItemGroup> <clean_log Include="%(QtWorkResult.OutputFile)" Condition="'%(QtWorkResult.ExitCode)' == '0'"> <Source>@(QtWorkResult, '|')</Source> @@ -414,7 +440,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////// // Log calls to Qt tools; used in QtWorkPrepare to detect changes to the options of Qt tools // --> - <WriteLinesToFile Condition="'@(QtWorkLog)' != '' AND '$(DesignTimeBuild)' != 'true'" + <WriteLinesToFile Condition="'@(QtWorkLog)' != ''" File="$(QtLogFilePath)" Lines="@(QtWorkLog->'%(Identity)|%(Hash)')" Overwrite="true" Encoding="Unicode"/> @@ -425,8 +451,7 @@ // --> <Error Condition="'%(QtWorkResult.ExitCode)' != '' - AND '%(QtWorkResult.ExitCode)' != '0' - AND '$(DesignTimeBuild)' != 'true'" + AND '%(QtWorkResult.ExitCode)' != '0'" File="%(QtWorkResult.Identity)" Code="%(QtWorkResult.ExitCode)" Text="%(QtWorkResult.WorkType) (%(QtWorkResult.ToolPath))"/> @@ -513,6 +538,7 @@ // Clean-up // --> <ItemGroup> + <ClCompile Remove="DefaultClCompile" /> <QtWork Remove="@(QtWork)"/> <QtWorkResult Remove="@(QtWorkResult)"/> <QtWorkLog Remove="@(QtWorkLog)"/> @@ -524,51 +550,158 @@ <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - /// TARGET Qt + /// TARGET QtSetAdditionalOptions ///////////////////////////////////////////////////////////////////////////////////////////////// - // Root Qt target + // Adds additional compiler options flowing from Qt. + // Skips options that are already specified in the user project. // --> - <Target Name="Qt" DependsOnTargets="QtPrepare;QtWork" BeforeTargets="FixupCLCompileOptions"> + <Target Name="QtSetAdditionalOptions" Condition="'@(ClCompile)' != ''"> + + <!-- Command line parser regex --> + <PropertyGroup> + <CmdLineParser>"[^"]*"|[^\s]+</CmdLineParser> + </PropertyGroup> + + <!-- Parse compiler options from Qt --> + <PropertyGroup> + <QtCmdLine + >$([System.Text.RegularExpressions.Regex]::Matches( + '$(Qt_CL_OPTIONS_)', '$(CmdLineParser)'))</QtCmdLine> + </PropertyGroup> + + <!-- Calculate command line for each source file in the project --> + <QtRunTask + Items="@(ClCompile)" + AssemblyPath="$(VCTargetsPath)\Microsoft.Build.CPPTasks.Common.dll" + TaskName="Microsoft.Build.CPPTasks.CLCommandLine" + TaskInput="Sources" + TaskOutput="CommandLines" + NewMetadata="ProjectOptions"> + <Output TaskParameter="Result" ItemName="ClCompile_CmdLine" /> + </QtRunTask> + + <!-- Append excluded Qt options to calculated command line --> <ItemGroup> - <ClCompile Remove="DefaultClCompile" /> + <ClCompile_CmdLine Condition="'$(QtExcludedOptions)' != ''"> + <ProjectOptions>%(ProjectOptions) $(QtExcludedOptions)</ProjectOptions> + </ClCompile_CmdLine> </ItemGroup> - <CriticalSection Lock="false" Name="$(ProjectGuid)" /> - <OnError ExecuteTargets="QtLeaveCriticalSection_OnError"/> + + <!-- Parse compiler command line of each source file --> + <ItemGroup> + <ClCompile_CmdLine> + <ProjectOptions + >$([System.Text.RegularExpressions.Regex]::Matches( + '%(ProjectOptions)', '$(CmdLineParser)'))</ProjectOptions> + </ClCompile_CmdLine> + </ItemGroup> + + <!-- Add (previously parsed) Qt options to each source file --> + <ItemGroup> + <ClCompile_CmdLine> + <QtOptions>$(QtCmdLine)</QtOptions> + </ClCompile_CmdLine> + </ItemGroup> + + <!-- Result of parsing command lines, per source file: + * ClCompile_CmdLine ::= (Item x ProjectOptions x QtOptions), where: + * Item ::= source file + * ProjectOptions ::= list of tokens from the compiler command line for Item + * QtOptions ::= list of tokens from the Qt additional options --> + + <!-- Flatten results into a list of tokens per source file: + * ClOptions ::= (Item x Name x Value), where: + * Item ::= source file + * Name ::= token origin: from compiler command line or from Qt + * Value ::= token value --> + <Flatten Items="@(ClCompile_CmdLine)" Metadata="ProjectOptions;QtOptions"> + <Output TaskParameter="Result" ItemName="ClOptions" /> + </Flatten> + + <!-- Remove non-switch tokens, i.e. tokens that do not start with '/' or '-' --> + <ItemGroup> + <ClOptions + Remove="@(ClOptions)" + Condition="!$([System.String]::Copy('%(Value)').StartsWith('-')) + AND !$([System.String]::Copy('%(Value)').StartsWith('/'))"/> + </ItemGroup> + + <!-- Calculate option id: token without leading '/' or '-', and without trailing '-' --> + <ItemGroup> + <ClOptions> + <OptionId>$([System.String]::Copy('%(Value)').Substring(1).TrimEnd('-'))</OptionId> + </ClOptions> + </ItemGroup> + + <!-- Split into list of Qt options and list of project options --> + <ItemGroup> + <QtOptions + Include="@(ClOptions->'%(Item)')" + Condition="'%(ClOptions.Name)' == 'QtOptions'"/> + <ProjectOptions + Include="@(ClOptions->'%(Item)')" + Condition="'%(ClOptions.Name)' == 'ProjectOptions'"/> + </ItemGroup> + + <!-- Find conflicting options, i.e. defined both in Qt options and project options --> + <ItemGroup> + <QtOptions + Condition="'@(QtOptions)' != '' + AND '@(ProjectOptions)' != '' + AND '%(Item)' != '' + AND '%(OptionId)' != ''"> + <Conflict>true</Conflict> + </QtOptions> + </ItemGroup> + + <!-- Set additional compiler options for all source files --> + <ItemGroup> + <ClCompile Condition="'%(Identity)' != '' AND '%(QtOptions.Conflict)' != 'true'"> + <AdditionalOptions + >@(QtOptions->'%(Value)', ' ') @(ClCompile->'%(AdditionalOptions)')</AdditionalOptions> + </ClCompile> + <ClCompile Condition="'%(AdditionalOptions)' != ''"> + <AdditionalOptions + >$([System.String]::Copy('%(AdditionalOptions)').Trim())</AdditionalOptions> + </ClCompile> + </ItemGroup> + + <!-- Print result to build log, if requested --> + <Message + Condition="'$(QtOptionsBuildLog)' == 'true'" + Importance="High" + Text=" Qt - Additional Compiler Options"/> + <Message + Condition="'$(QtOptionsBuildLog)' == 'true' + AND '%(Identity)' != '' AND '%(QtOptions.Conflict)' != 'true'" + Importance="High" + Text=" [%(Identity)]: @(QtOptions->'%(Value)', ' ')"/> + + <!-- Clean-up --> + <PropertyGroup> + <CmdLineParser/> + <QtCmdLine/> + </PropertyGroup> + <ItemGroup> + <ClCompile_CmdLine Remove="@(ClCompile_CmdLine)"/> + <ClOptions Remove="@(ClOptions)"/> + <ProjectOptions Remove="@(ProjectOptions)"/> + <QtOptions Remove="@(QtOptions)"/> + </ItemGroup> </Target> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - /// TARGET QtOuterBuild + /// TARGET Qt ///////////////////////////////////////////////////////////////////////////////////////////////// - // Run targets in $(QtOuterBuildDependsOn) and then recursively invoke build + // Root Qt target // --> - <Target Name="QtOuterBuild" DependsOnTargets="$(QtOuterBuildDependsOn)"> - <!--// Invoke inner build: recursive build in second MSBuild instance --> - <MSBuild - Projects="$(MSBuildProjectFullPath)" - Targets="Build" - Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false"> - </MSBuild> + <Target + Name="Qt" + DependsOnTargets="QtPrepare;QtWork;QtSetAdditionalOptions"> + <CriticalSection Lock="false" Name="$(ProjectGuid)" /> <OnError ExecuteTargets="QtLeaveCriticalSection_OnError"/> </Target> - - <PropertyGroup - Condition="'$(QtInnerBuild)' == '' AND '$(DesignTimeBuild)' != 'true'"> - <!--// Outer build: invoke inner build --> - <BuildDependsOn> - $(QtOuterBuildPrepare); - QtOuterBuild; - $(QtOuterBuildFinalize) - </BuildDependsOn> - <QtInnerBuild>$(MSBuildProjectFullPath)</QtInnerBuild> - <RandomFileName>$([System.IO.Path]::GetRandomFileName())</RandomFileName> - </PropertyGroup> - - <PropertyGroup - Condition="'$(QtInnerBuild)' != '$(MSBuildProjectFullPath)' AND '$(DesignTimeBuild)' != 'true'"> - <!--// Dependent project inner build: skip build --> - <BuildDependsOn>$(QtOuterBuildPrepare);$(QtOuterBuildFinalize)</BuildDependsOn> - </PropertyGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// @@ -633,4 +766,28 @@ <Target Name="QtLeaveCriticalSection_OnError"> <CriticalSection Lock="false" Name="$(ProjectGuid)" /> </Target> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + /// TARGET QtNatvis + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Copies the .natvis file matching the Qt version and replaces the namespace placeholder + // --> + <Target Name="QtNatvis" BeforeTargets="Link" + Condition="'$(Configuration)' == 'Debug' AND '$(LinkNatvisFile)' == 'true'" + Inputs="$(MSBuildProjectFile);$(QtMsBuild)\qt$(QtVersionMajor).natvis.xml" + Outputs="$(IntDir)\qt.natvis"> + <PropertyGroup> + <InputFile>$(QtMsBuild)\qt$(QtVersionMajor).natvis.xml</InputFile> + </PropertyGroup> + <WriteLinesToFile Condition="'$(QtNamespace)' == ''" + Overwrite="true" + File="$(IntDir)\qt.natvis" + Lines="$([System.IO.File]::ReadAllText($(InputFile)).Replace('##NAMESPACE##::',''))" /> + <WriteLinesToFile Condition="'$(QtNamespace)' != ''" + Overwrite="true" + File="$(IntDir)\qt.natvis" + Lines="$([System.IO.File]::ReadAllText($(InputFile)).Replace('##NAMESPACE##','$(QtNamespace)'))" /> + </Target> + </Project> diff --git a/QtMSBuild/QtMsBuild/qt_inner.targets b/QtMSBuild/QtMsBuild/qt_inner.targets new file mode 100644 index 0000000..06f88c7 --- /dev/null +++ b/QtMSBuild/QtMsBuild/qt_inner.targets @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +--> +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + + <PropertyGroup + Condition="'$(QtInnerBuild)' == ''"> + <!--// Outer build: invoke inner build --> + <BuildDependsOn> + $(QtOuterBuildPrepare); + QtOuterBuild; + $(QtOuterBuildFinalize) + </BuildDependsOn> + <QtInnerBuild>$(MSBuildProjectFullPath)</QtInnerBuild> + <RandomFileName>$([System.IO.Path]::GetRandomFileName())</RandomFileName> + </PropertyGroup> + + <PropertyGroup + Condition="'$(QtInnerBuild)' != '$(MSBuildProjectFullPath)'"> + <!--// Dependent project inner build: skip build --> + <BuildDependsOn>$(QtOuterBuildPrepare);$(QtOuterBuildFinalize)</BuildDependsOn> + </PropertyGroup> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + /// TARGET QtOuterBuild + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Run targets in $(QtOuterBuildDependsOn) and then recursively invoke build + // --> + <Target Name="QtOuterBuild" DependsOnTargets="$(QtOuterBuildDependsOn)"> + <!--// Invoke inner build: recursive build in second MSBuild instance --> + <MSBuild + Projects="$(MSBuildProjectFullPath)" + Targets="Build" + Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false"> + </MSBuild> + <OnError ExecuteTargets="QtLeaveCriticalSection_OnError"/> + </Target> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + /// TARGET GetClCommandLineForReference + ///////////////////////////////////////////////////////////////////////////////////////////////// + // + // --> + <Target + Name="GetClCommandLineForReference" + DependsOnTargets="$(QtOuterBuildDependsOn)" + Returns="@(ClCommandLineForReference)"> + <MSBuild + Projects="$(MSBuildProjectFullPath)" + Targets="GetClCommandLineForReference" + Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false"> + <Output TaskParameter="TargetOutputs" ItemName="ClCommandLineForReference"/> + </MSBuild> + </Target> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + /// TARGET GetGeneratedFiles + ///////////////////////////////////////////////////////////////////////////////////////////////// + // + // --> + <Target + Name="GetGeneratedFiles" + DependsOnTargets="$(QtOuterBuildDependsOn)" + Returns="@(_GeneratedFiles)"> + <MSBuild + Projects="$(MSBuildProjectFullPath)" + Targets="GetGeneratedFiles" + Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false"> + <Output TaskParameter="TargetOutputs" ItemName="_GeneratedFiles"/> + </MSBuild> + </Target> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + /// TARGET GetProjectReferencesInfo + ///////////////////////////////////////////////////////////////////////////////////////////////// + // + // --> + <Target + Name="GetProjectReferencesInfo" + DependsOnTargets="$(QtOuterBuildDependsOn)" + Returns="@(_ProjectReferencesInfo)"> + <MSBuild + Projects="$(MSBuildProjectFullPath)" + Targets="GetProjectReferencesInfo" + Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false"> + <Output TaskParameter="TargetOutputs" ItemName="_ProjectReferencesInfo"/> + </MSBuild> + </Target> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + /// TARGET GetClCommandLines + ///////////////////////////////////////////////////////////////////////////////////////////////// + // + // --> + <Target + Name="GetClCommandLines" + DependsOnTargets="$(QtOuterBuildDependsOn)" + Returns="@(ClCommandLines)"> + <MSBuild + Projects="$(MSBuildProjectFullPath)" + Targets="GetClCommandLines" + Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false"> + <Output TaskParameter="TargetOutputs" ItemName="ClCommandLines"/> + </MSBuild> + </Target> +</Project> diff --git a/QtMSBuild/QtMsBuild/qt_private.props b/QtMSBuild/QtMsBuild/qt_private.props index c1303e0..eb76f1f 100644 --- a/QtMSBuild/QtMsBuild/qt_private.props +++ b/QtMSBuild/QtMsBuild/qt_private.props @@ -57,6 +57,18 @@ <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// + // Check if design-time build + // --> + <PropertyGroup> + <QtDesignTimeBuild>false</QtDesignTimeBuild> + <QtDesignTimeBuild + Condition="'$(DesignTimeBuild)' == 'true' + OR '$(QtVSToolsBuild)' == 'true'" + >true</QtDesignTimeBuild> + </PropertyGroup> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// // Setup Qt installation path // --> <PropertyGroup Condition="'$(QtVsProjectSettings)' == 'true'"> @@ -112,21 +124,29 @@ >$([System.String]::Copy($([System.IO.File]::ReadAllText('$(QtVarsIndexPathDesignTime)'))).Replace('
',''))</QtVarsDesignTime> </PropertyGroup> - <!--// Import Qt variables (full build) --> - <Import - Condition="'$(DesignTimeBuild)' != 'true' AND Exists('$(QtVarsFilePath)')" - Project="$(QtVarsFilePath)"/> + <PropertyGroup> + <!--// Path to Qt variables .props: full build --> + <QtVarsImportPath + Condition="'$(QtDesignTimeBuild)' != 'true' + AND Exists('$(QtVarsFilePath)')" + >$(QtVarsFilePath)</QtVarsImportPath> - <!--// Import Qt variables (design-time build) --> - <Import - Condition="'$(DesignTimeBuild)' == 'true' AND Exists('$(QtVarsDesignTime)')" - Project="$(QtVarsDesignTime)"/> + <!--// Path to Qt variables .props: design-time build --> + <QtVarsImportPath + Condition="'$(QtDesignTimeBuild)' == 'true' + AND Exists('$(QtVarsDesignTime)')" + >$(QtVarsDesignTime)</QtVarsImportPath> - <!--// Import Qt variables (fall-back) --> - <Import - Condition= -"'$(DesignTimeBuild)' == 'true' AND !Exists('$(QtVarsDesignTime)') AND Exists('$(QtVarsFilePath)')" - Project="$(QtVarsFilePath)"/> + <!--// Path to Qt variables .props: fall-back --> + <QtVarsImportPath + Condition="'$(QtDesignTimeBuild)' == 'true' + AND !Exists('$(QtVarsDesignTime)') + AND Exists('$(QtVarsFilePath)')" + >$(QtVarsFilePath)</QtVarsImportPath> + </PropertyGroup> + + <!--// Import Qt vars property file --> + <Import Condition="Exists('$(QtVarsImportPath)')" Project="$(QtVarsImportPath)"/> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// @@ -175,6 +195,61 @@ <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// + // Normalize QtVars (incl. backup) + // --> + <PropertyGroup> + <QtVars + Condition="'$(QtVars)' !=''" + >$(QtVars + .Replace(' ', '') + .Replace('%0a', '') + .Replace('%0d', '') + .Trim(';'))</QtVars> + <QtBkup_QtVars + Condition="'$(QtBkup_QtVars)' !=''" + >$(QtBkup_QtVars + .Replace(' ', '') + .Replace('%0a', '') + .Replace('%0d', '') + .Trim(';'))</QtBkup_QtVars> + </PropertyGroup> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Figure out depending on the user settings if we need to link the .natvis file into the PDB + // file. Reads the content of qconfig.pri to find Qt's namespace if set. Predefines the path to + // the .natvis file used during link which corresponds to the final output generated by the + // QtNatvis target. + // Evaluation order: first look at the project settings, if empty take from the global settings. + // --> + <PropertyGroup> + <LinkNatvisFile>$(QtLinkNatvisFile)</LinkNatvisFile> + </PropertyGroup> + <PropertyGroup Condition="'$(QtLinkNatvisFile)' == ''"> + <LinkNatvisRegValue>$([MSBuild]::GetRegistryValue( + 'HKEY_CURRENT_USER\SOFTWARE\Digia\Qt5VS2017','LinkNatvis' + ))</LinkNatvisRegValue> + <LinkNatvisFile>true</LinkNatvisFile> + <LinkNatvisFile Condition="'$(LinkNatvisRegValue)' == '0'">false</LinkNatvisFile> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)' == 'Debug' + AND '$(LinkNatvisFile)' == 'true' AND '$(QtInstallDir)' != ''"> + <QConfigPriPath>$([System.IO.Path]::Combine('$(QtInstallDir)', + 'mkspecs', 'qconfig.pri' + ))</QConfigPriPath> + <QConfigPriContent>$([MSBuild]::Unescape( + $([System.IO.File]::ReadAllText('$(QConfigPriPath)') + .Replace('
', ';') + .Replace(' =', '=') + .Replace('= ', '=')) + ))</QConfigPriContent> + <QtNamespace>$([System.Text.RegularExpressions.Regex]::Match($(QConfigPriContent), + 'QT_NAMESPACE=([a-zA-Z0-9]+)').get_Groups().get_Item(1) + )</QtNamespace> + </PropertyGroup> + + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// // Default item metadata // --> <ItemDefinitionGroup> @@ -186,24 +261,27 @@ <PreprocessorDefinitions Condition="'$(QtQMLDebugEnable)' == 'true'" >QT_QML_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <AdditionalIncludeDirectories Condition="'$(Qt_INCLUDEPATH_)' != ''" - >$(Qt_INCLUDEPATH_);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + >%(AdditionalIncludeDirectories);$(Qt_INCLUDEPATH_)</AdditionalIncludeDirectories> <LanguageStandard Condition="'$(Qt_STDCPP_)' != ''" >$(Qt_STDCPP_)</LanguageStandard> - <AdditionalOptions Condition="'$(Qt_CL_OPTIONS_)' != ''" - >$(Qt_CL_OPTIONS_) %(AdditionalOptions)</AdditionalOptions> + <RuntimeLibrary Condition="'$(Qt_RUNTIME_)' != ''" + >$(Qt_RUNTIME_)</RuntimeLibrary> </ClCompile> <!--// Linker (.obj files) --> <Link> <AdditionalDependencies Condition="'$(Qt_LIBS_)' != ''" - >$(Qt_LIBS_);%(AdditionalDependencies)</AdditionalDependencies> + >%(AdditionalDependencies);$(Qt_LIBS_)</AdditionalDependencies> <AdditionalLibraryDirectories Condition="'$(Qt_LIBPATH_)' != ''" - >$(Qt_LIBPATH_);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + >%(AdditionalLibraryDirectories);$(Qt_LIBPATH_)</AdditionalLibraryDirectories> <SharedLibrarySearchPath Condition="'$(Qt_LIBPATH_)' != ''" - >$(Qt_LIBPATH_);%(SharedLibrarySearchPath)</SharedLibrarySearchPath> + >%(SharedLibrarySearchPath);$(Qt_LIBPATH_)</SharedLibrarySearchPath> <AdditionalOptions Condition="'$(Qt_LINK_OPTIONS_)' != ''" >$(Qt_LINK_OPTIONS_) %(AdditionalOptions)</AdditionalOptions> + <AdditionalOptions Condition="'$(Configuration)' == 'Debug' AND '$(LinkNatvisFile)' == 'true'" + >/NATVIS:"$(IntDir)\qt.natvis" %(AdditionalOptions)</AdditionalOptions> </Link> + </ItemDefinitionGroup> <!-- diff --git a/QtMSBuild/QtMsBuild/qt_settings.xml b/QtMSBuild/QtMsBuild/qt_settings.xml index d078dc6..37ed382 100644 --- a/QtMSBuild/QtMsBuild/qt_settings.xml +++ b/QtMSBuild/QtMsBuild/qt_settings.xml @@ -43,6 +43,8 @@ <Category Name="QtSettings_02_Paths" DisplayName="Paths"/> <Category Name="QtSettings_03_QMake" DisplayName="qmake"/> <Category Name="QtSettings_04_QML" DisplayName="QML"/> + <Category Name="QtSettings_05_AdditionalOptions" DisplayName="Qt Additional Compiler Options"/> + <Category Name="QtSettings_06_AdditionalLinkOptions" DisplayName="Qt Additional Linker Options"/> </Rule.Categories> <EnumProperty Name="Keyword" @@ -85,6 +87,12 @@ <ValueEditor EditorType="QtModulesEditor" DisplayName="<Select Modules...>" /> </StringListProperty.ValueEditors> </StringListProperty> + <BoolProperty + Name="QtPlugin" + Category="QtSettings_01_General" + DisplayName="Qt Plugin" + Description="Select whether this project is used to generate a Qt plugin."> + </BoolProperty> <EnumProperty Name="QtBuildConfig" Category="QtSettings_01_General" @@ -98,6 +106,14 @@ Category="QtSettings_01_General" DisplayName="Run Deployment Tool" Description="Select whether Qt for Windows Deployment Tool (windeployqt) should be called after build."/> + <EnumProperty + Name="QtToolsDesignTime" + Category="QtSettings_01_General" + DisplayName="Design Time Build" + Description="Run Qt tools during IntelliSense builds."> + <EnumValue Name="true" DisplayName="Run Qt Tools"/> + <EnumValue Name="false" DisplayName="Skip Qt Tools"/> + </EnumProperty> <StringProperty Name="QtPathBinaries" Category="QtSettings_02_Paths" @@ -145,4 +161,38 @@ DisplayName="Enable QML Debugging" Description="Select whether to launch a QML session when debugging."> </BoolProperty> -</Rule> + <StringProperty + Name="Qt_CL_OPTIONS_" + ReadOnly="true" + Category="QtSettings_05_AdditionalOptions" + DisplayName="Additional Options" + Description=" +Additional compiler options required by Qt. These options will be passed +to the compiler, unless specifically excluded in the next field." /> + <StringProperty + Name="QtExcludedOptions" + Category="QtSettings_05_AdditionalOptions" + DisplayName="Excluded Options" + Description=" +Options to exclude from the above compiler options required by Qt. +These options will NOT be passed to the compiler. Prefix options +with '/' or '-', and separate them with spaces." /> + <BoolProperty + Name="QtOptionsBuildLog" + Category="QtSettings_05_AdditionalOptions" + DisplayName="Show in Build Log" + Description=" +Print to the build log the list of additional options passed to the compiler." /> + <EnumProperty + Name="QtLinkNatvisFile" + Category="QtSettings_06_AdditionalLinkOptions" + DisplayName="Embed .natvis file into PDB" + Description= +"Embeds the debugger visualizations (.natvis file) into the PDB file +generated by LINK. While setting this option, the embedded Natvis file +will take precedence over user-specific Natvis files (for example the +files located in %USERPROFILE%\\Documents\\Visual Studio 2022\\Visualizers)."> + <EnumValue Name="false" DisplayName="No" /> + <EnumValue Name="true" DisplayName="Yes" /> + </EnumProperty> + </Rule> diff --git a/QtMSBuild/QtMsBuild/qt_vars.targets b/QtMSBuild/QtMsBuild/qt_vars.targets index 80c141c..2ad7445 100644 --- a/QtMSBuild/QtMsBuild/qt_vars.targets +++ b/QtMSBuild/QtMsBuild/qt_vars.targets @@ -199,7 +199,8 @@ <ItemGroup> <QMakeArgsList Condition="'$(QMakeOptionEarly)' == 'true'" Include="-early"/> <QMakeArgsList Include="CONFIG -= debug release debug_and_release"/> - <QMakeArgsList Include="CONFIG += $(QtBuildConfig)"/> + <QMakeArgsList Include="CONFIG += $(QtBuildConfig) warn_off"/> + <QMakeArgsList Condition="'$(QtPlugin)' == 'true'" Include="CONFIG += plugin"/> <QMakeArgsList Include="$(QMakeExtraArgs)"/> </ItemGroup> <ItemGroup> @@ -281,7 +282,32 @@ $(QtVarsProFileInput) DEFINES -= UNICODE _UNICODE </QtVarsProFileInput> + <!-- +# Add dummy QML object if needed --> + <QtVarsProFileInput Condition="$(QtModules.Contains('quick'))"> + $(QtVarsProFileInput) + RESOURCES += qml.qrc + </QtVarsProFileInput> </PropertyGroup> + + <!--// Write dummy QML and QRC files --> + <WriteLinesToFile + Condition="$(QtModules.Contains('quick'))" + File="$(QtVarsWorkDir)\main.qml" + Lines=" +import QtQuick +DummyQmlObject { } +"/> + <WriteLinesToFile + Condition="$(QtModules.Contains('quick'))" + File="$(QtVarsWorkDir)\qml.qrc" + Lines=" +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> +"/> <!--// Write .pro file to temp path --> <WriteLinesToFile @@ -313,6 +339,7 @@ <Cmd><![CDATA["$(QtToolsPath)/qmake" $(QMakeArgs) qtvars.pro]]></Cmd> </PropertyGroup> <HostExec + Condition="'$(ApplicationType)' == 'Linux'" Command="$(Cmd)" RedirectStdOut="qtvars.log" RedirectStdErr="STDOUT" WorkingDirectory="@(WorkDir->'%(HostPath)')" Inputs="@(QMakeProj)" @@ -322,6 +349,45 @@ IgnoreExitCode="true"> <Output TaskParameter="ExitCode" PropertyName="ErrorLevel"/> </HostExec> + + <!--// Run qmake in Windows: set %CD% to subfolder of %TEMP% --> + <PropertyGroup + Condition="'$(ApplicationType)' != 'Linux'"> + <QMakeTempDir>$(Temp)\$([System.IO.Path]::GetRandomFileName())</QMakeTempDir> + </PropertyGroup> + <MakeDir + Condition="'$(ApplicationType)' != 'Linux'" + Directories="$(QMakeTempDir)" /> + <Copy + Condition="'$(ApplicationType)' != 'Linux'" + SourceFiles="$(QtVarsWorkDir)\qtvars.pro" + DestinationFolder="$(QMakeTempDir)" /> + <Copy + Condition="'$(ApplicationType)' != 'Linux' AND Exists('$(QtVarsWorkDir)\main.qml')" + SourceFiles="$(QtVarsWorkDir)\main.qml" + DestinationFolder="$(QMakeTempDir)" /> + <Copy + Condition="'$(ApplicationType)' != 'Linux' AND Exists('$(QtVarsWorkDir)\qml.qrc')" + SourceFiles="$(QtVarsWorkDir)\qml.qrc" + DestinationFolder="$(QMakeTempDir)" /> + <HostExec + Condition="'$(ApplicationType)' != 'Linux'" + Command="$(Cmd)" RedirectStdOut="qtvars.log" RedirectStdErr="STDOUT" + WorkingDirectory="$(QMakeTempDir)" + IgnoreExitCode="true"> + <Output TaskParameter="ExitCode" PropertyName="ErrorLevel"/> + </HostExec> + <ItemGroup> + <QMakeGeneratedFiles Include="$(QMakeTempDir)\*" /> + </ItemGroup> + <Copy + Condition="'$(ApplicationType)' != 'Linux'" + SkipUnchangedFiles="true" + SourceFiles="@(QMakeGeneratedFiles)" + DestinationFolder="$(QtVarsWorkDir)" /> + <RemoveDir + Condition="'$(ApplicationType)' != 'Linux'" + Directories="$(QMakeTempDir)" /> <!--// Check qmake result --> <PropertyGroup @@ -501,15 +567,15 @@ <!--// In design-time, copy generated .props to randomly named file --> <PropertyGroup> <QtVarsDesignTimeNew - Condition="'$(ErrorLevel)' == '0' AND '$(QtVSToolsBuild)' == 'true'" + Condition="'$(ErrorLevel)' == '0' AND '$(QtDesignTimeBuild)' == 'true'" >$([System.IO.Path]::Combine('$(TEMP)','$([System.IO.Path]::GetRandomFileName()).designtime.props')) </QtVarsDesignTimeNew> </PropertyGroup> <Copy - Condition="'$(ErrorLevel)' == '0' AND '$(QtVSToolsBuild)' == 'true'" + Condition="'$(ErrorLevel)' == '0' AND '$(QtDesignTimeBuild)' == 'true'" SourceFiles="$(QtVarsFilePath)" DestinationFiles="$(QtVarsDesignTimeNew)"/> <WriteLinesToFile - Condition="'$(ErrorLevel)' == '0' AND '$(QtVSToolsBuild)' == 'true'" + Condition="'$(ErrorLevel)' == '0' AND '$(QtDesignTimeBuild)' == 'true'" File="$(QtVarsIndexPathDesignTime)" Overwrite="true" Lines="$(QtVarsDesignTimeNew)"/> <!--// Clean-up --> diff --git a/QtMSBuild/QtMsBuild/translation/qttranslation.targets b/QtMSBuild/QtMsBuild/translation/qttranslation.targets index 6b599f9..4f15175 100644 --- a/QtMSBuild/QtMsBuild/translation/qttranslation.targets +++ b/QtMSBuild/QtMsBuild/translation/qttranslation.targets @@ -90,10 +90,14 @@ <QtTranslation> <InputFiles >$(QtTranslationInput)</InputFiles> - <LUpdate + <LUpdate Condition="'$(ApplicationType)' == 'Linux'" >$(QtToolsPath)/lupdate</LUpdate> - <LRelease + <LRelease Condition="'$(ApplicationType)' == 'Linux'" >$(QtToolsPath)/lrelease</LRelease> + <LUpdate Condition="'$(ApplicationType)' != 'Linux'" + >$(QtToolsPath)/lupdate.exe</LUpdate> + <LRelease Condition="'$(ApplicationType)' != 'Linux'" + >$(QtToolsPath)/lrelease.exe</LRelease> <TsFile >%(Identity)</TsFile> <QmFile @@ -395,6 +399,7 @@ <Cmd>$(Cmd.Trim())</Cmd> </PropertyGroup> <HostExec + Condition="Exists(@(Options->'%(CmdExec)', ''))" Message="%(QtTranslationUpdate.UpdateDescription)" Command="$(Cmd)" Inputs="@(Options->'%(InputListFile)');@(Options->'%(InputFiles)')" @@ -402,6 +407,9 @@ RemoteTarget="$(ResolvedRemoteTarget)" RemoteProjectDir="$(_ResolvedRemoteProjectDir)"> </HostExec> + <Warning + Condition="!Exists(@(Options->'%(CmdExec)', ''))" + File="%(QtTranslationUpdate.Identity)" Text="'lupdate' not found; skipping" /> <!-- /////////////////////////////////////////////////////////////////////////////////////////////// @@ -556,6 +564,7 @@ <Cmd>$(Cmd.Trim())</Cmd> </PropertyGroup> <HostExec + Condition="Exists(@(Options->'%(CmdExec)', ''))" Message="%(QtTranslationRelease.ReleaseDescription)" Command="$(Cmd)" Inputs="@(Options->'%(InputFile)')" @@ -563,6 +572,9 @@ RemoteTarget="$(ResolvedRemoteTarget)" RemoteProjectDir="$(_ResolvedRemoteProjectDir)"> </HostExec> + <Warning + Condition="!Exists(@(Options->'%(CmdExec)', ''))" + File="%(QtTranslationRelease.Identity)" Text="'lrelease' not found; skipping" /> <!-- /////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/QtMSBuild/Tasks/CriticalSection.cs b/QtMSBuild/Tasks/CriticalSection.cs index e2a44d6..53423f3 100644 --- a/QtMSBuild/Tasks/CriticalSection.cs +++ b/QtMSBuild/Tasks/CriticalSection.cs @@ -84,8 +84,6 @@ if (Lock) { // Wait until locked if (!buildLock.WaitOne(1000)) { - // Issue waiting warning - Log.LogWarning("Qt::BuildLock[{0}]: Waiting...", Name); var t = Stopwatch.StartNew(); do { // Check for build errors diff --git a/QtMSBuild/Tasks/QtRunTask.cs b/QtMSBuild/Tasks/QtRunTask.cs new file mode 100644 index 0000000..447543e --- /dev/null +++ b/QtMSBuild/Tasks/QtRunTask.cs @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#region Task TaskName="QtRunTask" + +#region Reference +//System.Runtime +#endregion + +#region Using +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +#endregion + +#region Comment +///////////////////////////////////////////////////////////////////////////////////////////////// +/// TASK QtRunTask +///////////////////////////////////////////////////////////////////////////////////////////////// +// Execute a task from the specified assembly, taking as input a list of items. Each item +// metadata is copied to a task property with the same name. After the task is executed, the +// result for each item is then stored in a new metadata for that item. The final output is the +// list of modified items. +// Parameters ///////////////////////////////////////////////////////////////////////////////// +// in ITaskItem[] Items........................List of source items. +// in String AssemblyPath.................Path to assembly containing the task. +// in String TaskName.....................Full name of task, including namespace. +// in String TaskInput....................Name of task input property. +// in String TaskOutput (optional)........Name of task output property. +// If unspecified, task output is ignored. +// in String NewMetadata (optional).......Name of new item metadata to store result. +// If unspecified, defaults to TaskOutput. +// out ITaskItem[] Result.......................Output list of modified items. +// If TaskOutput is unspecified, Result will be empty. +// Example ////////////////////////////////////////////////////////////////////////////////////// +// Items = { +// ClCompile { +// Identity = "main.cpp", +// ... +// EnforceTypeConversionRules = False, +// ... +// } +// } +// AssemblyPath = "$(VCTargetsPath)\Microsoft.Build.CPPTasks.Common.dll" +// TaskName = "Microsoft.Build.CPPTasks.CLCommandLine" +// TaskInput = "Sources" +// TaskOutput = "CommandLines" +// NewMetadata = "CommandLine" +// Result = { +// ClCompile_Modified { +// Identity = "main.cpp", +// ... +// EnforceTypeConversionRules = False, +// ... +// CommandLine = "... /Zc:rvalueCast- ..." +// } +// } +#endregion + +namespace QtVsTools.QtMsBuild.Tasks +{ + public static class QtRunTask + { + public static QtMSBuild.ITaskLoggingHelper Log { get; set; } + public static IBuildEngine BuildEngine { get; set; } + public static ITaskHost HostObject { get; set; } + + public static bool Execute( + #region Parameters + Microsoft.Build.Framework.ITaskItem[] Items, + System.String AssemblyPath, + System.String TaskName, + System.String TaskInput, + out Microsoft.Build.Framework.ITaskItem[] Result, + System.String TaskOutput = null, + System.String NewMetadata = null) + #endregion + { + #region Code + var reserved = new HashSet<string> + { + "AccessedTime", "CreatedTime", "DefiningProjectDirectory", + "DefiningProjectExtension", "DefiningProjectFullPath", "DefiningProjectName", + "Directory", "Extension", "Filename", "FullPath", "Identity", "ModifiedTime", + "RecursiveDir", "RelativeDir", "RootDir", + }; + + // Output default values + Result = null; + + // Load specified assembly + var taskAssembly = Assembly.LoadFile(AssemblyPath); + if (taskAssembly == null) + throw new ArgumentException("AssemblyPath"); + + // Access task type + var taskType = taskAssembly.GetType(TaskName); + if (taskType == null) + throw new ArgumentException("TaskName"); + + // Task type has the following requirements: + // * Must be a descendant of the ToolTask type + // * Cannot be an abstract class + // * Cannot have generic type arguments + // * Must have a public default constructor + if (!typeof(ToolTask).IsAssignableFrom(taskType)) + throw new NotSupportedException("Not a ToolTask derived type"); + if (taskType.IsAbstract) + throw new NotSupportedException("Abstract class"); + if (taskType.ContainsGenericParameters) + throw new NotSupportedException("Generic class"); + var ctorInfo = ((TypeInfo)taskType).DeclaredConstructors + .Where(x => x.GetParameters().Length == 0) + .FirstOrDefault(); + if (ctorInfo == null) + throw new NotSupportedException("No default constructor"); + + // Access input property of task type + var inputProperty = taskType.GetProperty(TaskInput); + if (inputProperty == null) + throw new ArgumentException("TaskInput"); + if (inputProperty.PropertyType != typeof(ITaskItem) + && inputProperty.PropertyType != typeof(ITaskItem[])) { + throw new NotSupportedException("Input property type is not supported"); + } + + // If output was specified, access corresponding property of task type + PropertyInfo outputProperty = null; + if (TaskOutput != null) { + outputProperty = taskType.GetProperty(TaskOutput); + if (outputProperty == null) + throw new ArgumentException("TaskOutput"); + if (outputProperty.PropertyType != typeof(string) + && outputProperty.PropertyType != typeof(string[]) + && outputProperty.PropertyType != typeof(ITaskItem[])) { + throw new NotSupportedException("Output property type is not supported"); + } + if (NewMetadata == null) + NewMetadata = TaskOutput; + } + + var resultItems = new List<ITaskItem>(); + foreach (var item in Items) { + // For each source item ... + + // Instantiate task + var task = ctorInfo.Invoke(new object[0]) as ToolTask; + task.BuildEngine = BuildEngine; + task.HostObject = HostObject; + + // Set task input property to the source item + var inputPropertyType = inputProperty.PropertyType; + if (inputPropertyType == typeof(ITaskItem)) { + inputProperty.SetValue(task, item); + } else if (inputPropertyType == typeof(ITaskItem[])) { + inputProperty.SetValue(task, new ITaskItem[] { item }); + } + + var names = item.MetadataNames.Cast<string>() + .Where(x => !reserved.Contains(x)); + foreach (var name in names) { + // For each metadata in the source item ... + + // Try to obtain a task property with the same name + var taskProperty = taskType.GetProperty(name); + if (taskProperty != null) { + // If the property exists, set it to the metadata value + string metadataValue = item.GetMetadata(name); + var propertyType = taskProperty.PropertyType; + if (propertyType == typeof(bool)) { + taskProperty.SetValue(task, metadataValue.Equals("true", + StringComparison.InvariantCultureIgnoreCase)); + } else if (propertyType == typeof(string)) { + taskProperty.SetValue(task, metadataValue); + } else if (propertyType == typeof(string[])) { + taskProperty.SetValue(task, metadataValue.Split(';')); + } + } + } + + // Run task + if (!task.Execute()) + throw new Exception(string.Format("Task failed ({0})", item.ItemSpec)); + + // Record task output + if (TaskOutput != null) { + // Create output item as copy of source item + var resultItem = new TaskItem(item); + + // Set new metadata and add output item to the result list + string outputValue; + object propertyValue = outputProperty.GetValue(task); + if (propertyValue == null) + outputValue = string.Empty; + else if (outputProperty.PropertyType == typeof(string)) + outputValue = propertyValue as string; + else if (outputProperty.PropertyType == typeof(string[])) + outputValue = (propertyValue as string[]).FirstOrDefault(); + else if (outputProperty.PropertyType == typeof(ITaskItem[])) + outputValue = (propertyValue as ITaskItem[]).FirstOrDefault().ItemSpec; + else + outputValue = string.Empty; + if (NewMetadata != null) + resultItem.SetMetadata(NewMetadata, outputValue); + resultItems.Add(resultItem); + } + } + + // Return the list of output items + Result = resultItems.ToArray(); + + #endregion + + return true; + } + } +} +#endregion diff --git a/QtVsTest/Macro.cs b/QtVsTest/Macro.cs index 1c1004d..e4477e8 100644 --- a/QtVsTest/Macro.cs +++ b/QtVsTest/Macro.cs @@ -82,7 +82,7 @@ /// <summary> /// Name of reusable macro /// </summary> - public string Name { get; private set; } + private string Name { get; set; } /// <summary> /// True if macro compilation was successful @@ -104,8 +104,9 @@ /// </summary> public bool QuitWhenDone { get; private set; } - AsyncPackage Package { get; set; } - EnvDTE80.DTE2 Dte { get; set; } + AsyncPackage Package { get; } + EnvDTE80.DTE2 Dte { get; } + IntPtr MainWindowHWnd { get; } AutomationElement UiRoot => AutomationElement.RootElement; @@ -115,65 +116,55 @@ get { if (_UiVsRoot == null) -#if VS2022 - _UiVsRoot = AutomationElement.FromHandle(Dte.MainWindow.HWnd); -#else - _UiVsRoot = AutomationElement.FromHandle(new IntPtr(Dte.MainWindow.HWnd)); -#endif + _UiVsRoot = AutomationElement.FromHandle(MainWindowHWnd); return _UiVsRoot; } } - JoinableTaskFactory JoinableTaskFactory { get; set; } - CancellationToken ServerLoop { get; set; } + JoinableTaskFactory JoinableTaskFactory { get; } + CancellationToken ServerLoop { get; } string Message { get; set; } static MacroParser Parser { get; set; } MacroLines MacroLines { get; set; } - List<string> SelectedAssemblies { get { return _SelectedAssemblies; } } - List<string> _SelectedAssemblies = - new List<string> - { - "QtVsTest", - "System.Core", - }; + private List<string> SelectedAssemblies { get; } = new List<string> + { + typeof(Macro).Assembly.FullName, + typeof(EnvDTE.DTE).Assembly.FullName, + typeof(AutomationElement).Assembly.FullName, + "System.Core", + }; IEnumerable<string> RefAssemblies { get; set; } - List<string> Namespaces { get { return _Namespaces; } } - List<string> _Namespaces = - new List<string> - { - "System", - "System.Linq", - "System.Reflection", - "Task = System.Threading.Tasks.Task", - "System.Windows.Automation", - "EnvDTE", - "EnvDTE80", - }; + private List<string> Namespaces { get; } = new List<string> + { + "System", + "System.Linq", + "System.Reflection", + "Task = System.Threading.Tasks.Task", + "System.Windows.Automation", + "EnvDTE", + "EnvDTE80", + }; - Dictionary<string, VSServiceRef> ServiceRefs { get { return _ServiceRefs; } } - Dictionary<string, VSServiceRef> _ServiceRefs = - new Dictionary<string, VSServiceRef> + private Dictionary<string, VSServiceRef> ServiceRefs { get; } = new Dictionary<string, VSServiceRef> + { { - { - "Dte", new VSServiceRef + "Dte", new VSServiceRef { Name = "Dte", Interface = "DTE2", Type = "DTE" } - }, - }; + }, + }; - Dictionary<string, GlobalVar> GlobalVars { get { return _GlobalVars; } } - Dictionary<string, GlobalVar> _GlobalVars = - new Dictionary<string, GlobalVar> + private Dictionary<string, GlobalVar> GlobalVars { get; } = new Dictionary<string, GlobalVar> + { { - { - "Result", new GlobalVar + "Result", new GlobalVar { Type = "string", Name = "Result", InitialValueExpr = "string.Empty" } - }, - }; + }, + }; string CSharpMethodCode { get; set; } string CSharpClassCode { get; set; } @@ -187,10 +178,10 @@ const BindingFlags PUBLIC_STATIC = BindingFlags.Public | BindingFlags.Static; const StringComparison IGNORE_CASE = StringComparison.InvariantCultureIgnoreCase; - static ConcurrentDictionary<string, Macro> Macros + static readonly ConcurrentDictionary<string, Macro> Macros = new ConcurrentDictionary<string, Macro>(); - static ConcurrentDictionary<string, object> Globals + static readonly ConcurrentDictionary<string, object> Globals = new ConcurrentDictionary<string, object>(); /// <summary> @@ -202,6 +193,7 @@ public Macro( AsyncPackage package, EnvDTE80.DTE2 dte, + IntPtr mainWindowHWnd, JoinableTaskFactory joinableTaskFactory, CancellationToken serverLoop) { @@ -209,6 +201,7 @@ JoinableTaskFactory = joinableTaskFactory; ServerLoop = serverLoop; Dte = dte; + MainWindowHWnd = mainWindowHWnd; ErrorMsg("Uninitialized"); } @@ -510,6 +503,8 @@ return false; break; } + + csharp.AppendLine(); return true; } @@ -615,6 +610,38 @@ csharp.AppendFormat(@" await WaitExpr({0}, () => UiContext = {1});", timeout, context); + + } else if (s.Args[0].Equals("find", IGNORE_CASE)) { + //# ui find [all] [_var_name_] [_timeout_] => <_scope_>, <_condition_> + + var args = new Queue<string>(s.Args.Skip(1)); + + bool findAll = false; + if (args.Any() && args.Peek().Equals("all", IGNORE_CASE)) { + findAll = true; + args.Dequeue(); + } + string funcName = findAll ? "FindAll" : "FindFirst"; + string varType = findAll ? "AutomationElementCollection" : "AutomationElement"; + + string varName = null; + if (args.Any() && !char.IsDigit(args.Peek()[0])) + varName = args.Dequeue(); + if (findAll && string.IsNullOrEmpty(varName)) + return ErrorMsg("Invalid #ui statement"); + + int timeout = 3000; + if (args.Any() && char.IsDigit(args.Peek()[0])) + timeout = int.Parse(args.Dequeue()); + + if (varName == null) { + varName = "UiContext"; + } else { + csharp.Append($@" + {varType} {varName} = null;"); + } + csharp.Append($@" + await WaitExpr({timeout}, () => {varName} = UiContext.{funcName}({s.Code}));"); } else if (s.Args[0].Equals("pattern", IGNORE_CASE)) { //# ui pattern <_TypeName_> <_VarName_> [ => _string_ [, _string_, ... ] ] @@ -790,7 +817,9 @@ File.Delete(macroDllPath); return ErrorMsg(string.Join("\r\n", CompilerResults.Errors.Cast<CompilerError>() - .Select(x => x.ErrorText))); + .Select(x => $"{x.Line}: {x.ErrorText}") + .Append(CSharpClassCode) + .Union(RefAssemblies))); } MacroAssembly = AppDomain.CurrentDomain.Load(File.ReadAllBytes(macroDllPath)); @@ -927,8 +956,7 @@ foreach (var globalVar in GlobalVars.Values) { string varName = globalVar.Name; Type varType = globalVar.FieldInfo.FieldType; - object value; - if (Globals.TryGetValue(varName, out value)) { + if (Globals.TryGetValue(varName, out object value)) { Type valueType = value.GetType(); if (!varType.IsAssignableFrom(valueType)) { throw new InvalidCastException(string.Format( @@ -968,8 +996,7 @@ static Macro GetMacro(string name) { - Macro macro; - if (!Macros.TryGetValue(name, out macro)) + if (!Macros.TryGetValue(name, out Macro macro)) return null; return macro; } diff --git a/QtVsTest/MacroParser.cs b/QtVsTest/MacroParser.cs index 4f8d240..3d67713 100644 --- a/QtVsTest/MacroParser.cs +++ b/QtVsTest/MacroParser.cs @@ -27,17 +27,18 @@ ****************************************************************************/ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; +using QtVsTools.SyntaxAnalysis; namespace QtVsTest.Macros { - using System.Collections; - using static QtVsTools.SyntaxAnalysis.RegExpr; + using static RegExpr; class MacroLines : IEnumerable<MacroLine> { - List<MacroLine> Lines = new List<MacroLine>(); + readonly List<MacroLine> Lines = new List<MacroLine>(); public void Add(MacroLine line) { Lines.Add(line); } @@ -120,7 +121,7 @@ public class CodeLine : MacroLine { - public string Code; + public readonly string Code; public CodeLine(string code) { Code = code; diff --git a/QtVsTest/MacroServer.cs b/QtVsTest/MacroServer.cs index 24f0033..b00fba5 100644 --- a/QtVsTest/MacroServer.cs +++ b/QtVsTest/MacroServer.cs @@ -46,10 +46,10 @@ /// </summary> class MacroServer { - public CancellationTokenSource Loop { get; private set; } + public CancellationTokenSource Loop { get; } - AsyncPackage Package { get; set; } - JoinableTaskFactory JoinableTaskFactory { get; set; } + AsyncPackage Package { get; } + JoinableTaskFactory JoinableTaskFactory { get; } /// <summary> /// Macro server constructor @@ -70,6 +70,7 @@ { await JoinableTaskFactory.SwitchToMainThreadAsync(Loop.Token); var DTE = await Package.GetServiceAsync(typeof(DTE)) as DTE2; + var mainWindowHWnd = new IntPtr((long)DTE.MainWindow.HWnd); await TaskScheduler.Default; var pipeName = string.Format("QtVSTest_{0}", Process.GetCurrentProcess().Id); @@ -97,7 +98,8 @@ if (Loop.Token.IsCancellationRequested) break; - var macro = new Macro(Package, DTE, JoinableTaskFactory, Loop.Token); + var macro = new Macro( + Package, DTE, mainWindowHWnd, JoinableTaskFactory, Loop.Token); await macro.CompileAsync(Encoding.UTF8.GetString(data)); if (macro.AutoRun) await macro.RunAsync(); diff --git a/QtVsTest/QtVsTest.cs b/QtVsTest/QtVsTest.cs index 74a7939..15ed031 100644 --- a/QtVsTest/QtVsTest.cs +++ b/QtVsTest/QtVsTest.cs @@ -27,6 +27,7 @@ ****************************************************************************/ using System; +using System.IO; using System.Runtime.InteropServices; using System.Threading; using Microsoft.VisualStudio.Shell; @@ -38,7 +39,6 @@ namespace QtVsTest { using Macros; - using System.IO; [Guid(PackageGuidString)] [InstalledProductRegistration( @@ -53,7 +53,7 @@ public sealed class QtVsTest : AsyncPackage { public const string PackageGuidString = "0e258dce-fc8a-49a2-81c5-c9e138bfe500"; - MacroServer MacroServer { get; set; } + MacroServer MacroServer { get; } public QtVsTest() { diff --git a/QtVsTest/QtVsTest.csproj b/QtVsTest/QtVsTest.csproj index c1c2aa4..d9a4894 100644 --- a/QtVsTest/QtVsTest.csproj +++ b/QtVsTest/QtVsTest.csproj @@ -2,7 +2,7 @@ <!-- /**************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -69,6 +69,8 @@ <DefineConstants>DEBUG;TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> + <PlatformTarget Condition="'$(VisualStudioVersion)' == '17.0'">x64</PlatformTarget> + <PlatformTarget Condition="'$(VisualStudioVersion)' != '17.0'">x86</PlatformTarget> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> @@ -87,55 +89,36 @@ <Reference Include="System" /> <Reference Include="System.Design" /> <Reference Include="System.Drawing" /> - <Reference Include="Microsoft.VisualStudio.ProjectSystem"> - <HintPath>$(VsInstallRoot)\Common7\IDE\CommonExtensions\Microsoft\Project\Microsoft.VisualStudio.ProjectSystem.dll</HintPath> - </Reference> - <Reference Include="Microsoft.VisualStudio.Composition"> - <HintPath>$(VsInstallRoot)\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.Composition.dll</HintPath> - </Reference> </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - // Version specific references + // General package references // --> <Import Project="$(SolutionDir)\references.props" /> <ItemGroup> - <PackageReference Include="System.ComponentModel.Composition" - Version="$(Version_System_ComponentModel_Composition)" /> - <PackageReference Include="Stub.System.Data.SQLite.Core.NetFramework" - Version="$(Version_Stub_System_Data_SQLite_Core_NetFramework)" /> - <PackageReference Include="Newtonsoft.Json" - Version="$(Version_Newtonsoft_Json)" /> - <PackageReference Include="Microsoft.Build" - Version="$(Version_Microsoft_Build)" /> - <PackageReference Include="Microsoft.Build.Framework" - Version="$(Version_Microsoft_Build_Framework)" /> - <PackageReference Include="Microsoft.Build.Tasks.Core" - Version="$(Version_Microsoft_Build_Tasks_Core)" /> - <PackageReference Include="Microsoft.VisualStudio.SDK" - Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> - <PackageReference Include="Microsoft.VSSDK.BuildTools" - Version="$(Version_Microsoft_VSSDK_BuildTools)" /> - <PackageReference Include="Microsoft.VisualStudio.Shell.Framework" - Version="$(Version_Microsoft_VisualStudio_Shell_Framework)" /> - <PackageReference Include="Microsoft.VisualStudio.Validation" - Version="$(Version_Microsoft_VisualStudio_Validation)" /> - <PackageReference Include="$(Name_Microsoft_VisualStudio_Threading)" - Version="$(Version_Microsoft_VisualStudio_Threading)" /> - <PackageReference Include="System.Collections.Immutable" - Version="$(Version_System_Collections_Immutable)" /> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_ProjectSystem)" Version="$(Version_Microsoft_VisualStudio_ProjectSystem)" /> </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='17.0'"> - <PackageReference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" - Version="$(Version_Microsoft_VisualStudio_VCProjectEngine)" /> - </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='16.0'"> - <PackageReference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" - Version="$(Version_Microsoft_VisualStudio_VCProjectEngine)" /> - </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='15.0'"> - <Reference Include="Microsoft.VisualStudio.VCProjectEngine" /> - </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// // Solution project references @@ -210,6 +193,26 @@ </Content> </ItemGroup> <Choose> + <When Condition="Exists('$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.22000.0')"> + <PropertyGroup> + <Win10SDKPath>$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.22000.0</Win10SDKPath> + </PropertyGroup> + </When> + <When Condition="Exists('$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.20348.0')"> + <PropertyGroup> + <Win10SDKPath>$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.20348.0</Win10SDKPath> + </PropertyGroup> + </When> + <When Condition="Exists('$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.19041.0')"> + <PropertyGroup> + <Win10SDKPath>$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.19041.0</Win10SDKPath> + </PropertyGroup> + </When> + <When Condition="Exists('$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.18362.0')"> + <PropertyGroup> + <Win10SDKPath>$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.18362.0</Win10SDKPath> + </PropertyGroup> + </When> <When Condition="Exists('$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.17763.0')"> <PropertyGroup> <Win10SDKPath>$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.17763.0</Win10SDKPath> @@ -232,7 +235,7 @@ </When> </Choose> <PropertyGroup Condition="'$(Win10SDKPath)' != ''"> - <UIAVerifyPath>$(Win10SDKPath)\x86\UIAVerify</UIAVerifyPath> + <UIAVerifyPath>$(Win10SDKPath)\$(PlatformTarget)\UIAVerify</UIAVerifyPath> </PropertyGroup> <ItemGroup Condition="'$(UIAVerifyPath)' != ''"> <Reference Include="Interop.UIAutomationClient"> @@ -246,9 +249,6 @@ <Aliases>global</Aliases> <EmbedInteropTypes>False</EmbedInteropTypes> </Reference> - </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> diff --git a/QtVsTools.Core/BuildConfig.cs b/QtVsTools.Core/BuildConfig.cs index 713e9f8..ac8647c 100644 --- a/QtVsTools.Core/BuildConfig.cs +++ b/QtVsTools.Core/BuildConfig.cs @@ -30,7 +30,6 @@ { public struct BuildConfig { - public const uint Both = 0x03; public const uint Release = 0x01; public const uint Debug = 0x02; diff --git a/QtVsTools.Core/CommandLineParser.cs b/QtVsTools.Core/CommandLineParser.cs index 7380cc8..995d064 100644 --- a/QtVsTools.Core/CommandLineParser.cs +++ b/QtVsTools.Core/CommandLineParser.cs @@ -29,10 +29,10 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; -using System.IO; namespace QtVsTools.Core.CommandLine { @@ -40,13 +40,12 @@ public class Parser { - - List<Option> commandLineOptionList = new List<Option>(); - Dictionary<string, int> nameHash = new Dictionary<string, int>(); - Dictionary<int, List<string>> optionValuesHash = new Dictionary<int, List<string>>(); - List<string> optionNames = new List<string>(); - List<string> positionalArgumentList = new List<string>(); - List<string> unknownOptionNames = new List<string>(); + readonly List<Option> commandLineOptionList = new List<Option>(); + readonly Dictionary<string, int> nameHash = new Dictionary<string, int>(); + readonly Dictionary<int, List<string>> optionValuesHash = new Dictionary<int, List<string>>(); + readonly List<string> optionNames = new List<string>(); + readonly List<string> positionalArgumentList = new List<string>(); + readonly List<string> unknownOptionNames = new List<string>(); bool needsParsing = true; public enum SingleDashWordOptionMode @@ -118,8 +117,7 @@ IEnumerable<string> Aliases(string optionName) { - int optionIndex; - if (!nameHash.TryGetValue(optionName, out optionIndex)) { + if (!nameHash.TryGetValue(optionName, out int optionIndex)) { return new List<string>(); } return commandLineOptionList[optionIndex].Names; @@ -204,8 +202,7 @@ IEnumerator<string> argumentEnumerator, ref bool atEnd) { const char assignChar = '='; - int optionOffset; - if (nameHash.TryGetValue(optionName, out optionOffset)) { + if (nameHash.TryGetValue(optionName, out int optionOffset)) { int assignPos = argument.IndexOf(assignChar); bool withValue = !string.IsNullOrEmpty( commandLineOptionList[optionOffset].ValueName); @@ -267,7 +264,7 @@ var optFilePath = macros.ExpandString(argData.Substring(1)); string[] additionalArgs = File.ReadAllLines( Path.Combine(workingDir, optFilePath)); - if (additionalArgs != null) { + if (additionalArgs.Length != 0) { var additionalArgsString = string.Join(" ", additionalArgs .Select(x => "\"" + x.Replace("\"", "\\\"") + "\"")); arguments.AddRange(TokenizeArgs(additionalArgsString, macros)); @@ -356,10 +353,9 @@ if (!RegisterFoundOption(optionName)) { error = true; } else { - int optionOffset; Trace.Assert(nameHash.TryGetValue( optionName, - out optionOffset)); + out int optionOffset)); bool withValue = !string.IsNullOrEmpty( commandLineOptionList[optionOffset].ValueName); if (withValue) { @@ -397,10 +393,9 @@ if (argument.Length > 2) { string possibleShortOptionStyleName = argument.Substring(1, 1); - int shortOptionIdx; if (nameHash.TryGetValue( possibleShortOptionStyleName, - out shortOptionIdx)) { + out int shortOptionIdx)) { var arg = commandLineOptionList[shortOptionIdx]; if ((arg.Flags & Option.Flag.ShortOptionStyle) != 0) { RegisterFoundOption(possibleShortOptionStyleName); @@ -466,8 +461,7 @@ public IEnumerable<string> Values(string optionName) { CheckParsed("Values"); - int optionOffset; - if (nameHash.TryGetValue(optionName, out optionOffset)) { + if (nameHash.TryGetValue(optionName, out int optionOffset)) { var values = optionValuesHash[optionOffset]; return values; } @@ -525,7 +519,6 @@ public IEnumerable<string> Names { get; - private set; } public string ValueName @@ -558,7 +551,7 @@ static class Lexer { - static Regex lexer = new Regex( + static readonly Regex lexer = new Regex( /* Newline */ @"(\n)" + /* Unquoted */ @"|((?:(?:[^\s\""])|(?:(?<=\\)\""))+)" + /* Quoted */ @"|(?:\""((?:(?:[^\""])|(?:(?<=\\)\""))+)\"")" + diff --git a/QtVsTools.Core/Common/EnumExt.cs b/QtVsTools.Core/Common/EnumExt.cs index 0406e2c..c05f7bc 100644 --- a/QtVsTools.Core/Common/EnumExt.cs +++ b/QtVsTools.Core/Common/EnumExt.cs @@ -40,6 +40,8 @@ /// </summary> public static class EnumExt { + static LazyFactory StaticLazy { get; } = new LazyFactory(); + /// <summary> /// Wrapper for enum cast values. /// </summary> @@ -64,7 +66,7 @@ [AttributeUsage(AttributeTargets.All)] public sealed class StringAttribute : Attribute, ICast<string> { - public string Value { get; private set; } + public string Value { get; } public StringAttribute(string str) { Value = str; } } @@ -128,8 +130,7 @@ /// </summary> public static TEnum Cast<T, TEnum>(this T valueT, TEnum defaultValue) where TEnum : struct { - TEnum value; - return TryCast(valueT, out value) ? value : defaultValue; + return TryCast(valueT, out TEnum value) ? value : defaultValue; } /// <summary> @@ -201,15 +202,14 @@ .FirstOrDefault(); } - static IEnumerable<Type> _CastAttribTypes; /// <summary> /// List of cast attribute types. /// </summary> /// <remarks> /// Future cast attribute types need to be added to this list. /// </remarks> - static IEnumerable<Type> CastAttribTypes => _CastAttribTypes - ?? (_CastAttribTypes = new[] + static IEnumerable<Type> CastAttribTypes => StaticLazy.Get(() => + CastAttribTypes, () => new[] { typeof(StringAttribute) }); diff --git a/QtVsTools.Core/Common/LazyFactory.cs b/QtVsTools.Core/Common/LazyFactory.cs new file mode 100644 index 0000000..c914cee --- /dev/null +++ b/QtVsTools.Core/Common/LazyFactory.cs @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Linq.Expressions; +using System.Reflection; + +namespace QtVsTools.Common +{ + public class LazyFactory + { + private Lazy<ConcurrentDictionary<PropertyInfo, Lazy<object>>> LazyObjs { get; } + private ConcurrentDictionary<PropertyInfo, Lazy<object>> Objs => LazyObjs.Value; + + public LazyFactory() + { + LazyObjs = new Lazy<ConcurrentDictionary<PropertyInfo, Lazy<object>>>(); + } + + public T Get<T>(Expression<Func<T>> propertyRef, Func<T> initFunc) where T : class + { + var lazyPropertyExpr = propertyRef?.Body as MemberExpression; + var lazyProperty = lazyPropertyExpr?.Member as PropertyInfo; + if (lazyProperty == null) + throw new ArgumentException("Invalid property reference", "propertyRef"); + var lazyObj = Objs.GetOrAdd(lazyProperty, (_) => new Lazy<object>(() => initFunc())); + return lazyObj.Value as T; + } + } +} diff --git a/QtVsTools.Core/Common/QtVSIPSettingsShared.cs b/QtVsTools.Core/Common/QtVSIPSettingsShared.cs new file mode 100644 index 0000000..5d86492 --- /dev/null +++ b/QtVsTools.Core/Common/QtVSIPSettingsShared.cs @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; +using Microsoft.Win32; +using QtVsTools.Core; + +namespace QtVsTools.Common +{ + public static class QtVSIPSettingsShared + { + private static readonly Dictionary<string, string> mocDirCache + = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + private static readonly Dictionary<string, string> uicDirCache + = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + private static readonly Dictionary<string, string> rccDirCache + = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + + public static string GetDirectory(EnvDTE.Project project, string type) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + // check for directory in following order: + // - stored in project + // - stored in cache + // - retrieve from moc/uic steps + // - fall-back on hard-coded directory + + var fullName = project?.FullName; + if (string.IsNullOrEmpty(fullName)) + return GetDirectory(type); // - fall-back on hard-coded directory + + if (project.Globals.get_VariablePersists(type)) // - stored in project + return HelperFunctions.NormalizeRelativeFilePath(project.Globals[type] as string); + + switch (type) { // - stored in cache + case Resources.mocDirKeyword: + if (mocDirCache.ContainsKey(fullName)) + return mocDirCache[fullName]; + break; + case Resources.uicDirKeyword: + if (uicDirCache.ContainsKey(fullName)) + return uicDirCache[fullName]; + break; + case Resources.rccDirKeyword: + if (rccDirCache.ContainsKey(fullName)) + return rccDirCache[fullName]; + break; + default: + return GetDirectory(type); // - fall-back on hard-coded directory + } + + try { + string configName = null; + string platformName = null; + QtCustomBuildTool tool = null; + foreach (VCFile vcfile in (project.Object as VCProject).Files as IVCCollection) { + var name = vcfile?.Name; + if (string.IsNullOrEmpty(name)) + continue; + if (!(HelperFunctions.IsHeaderFile(name) || HelperFunctions.IsMocFile(name) + || HelperFunctions.IsUicFile(name) || HelperFunctions.IsQrcFile(name))) + continue; + + foreach (VCFileConfiguration config in vcfile?.FileConfigurations as IVCCollection) { + tool = new QtCustomBuildTool(config); + if (tool == null) + continue; + configName = config.Name.Remove(config.Name.IndexOf('|')); + var vcConfig = config.ProjectConfiguration as VCConfiguration; + platformName = (vcConfig.Platform as VCPlatform).Name; + var cmd = tool.CommandLine; + if (cmd.Contains("moc.exe") || cmd.Contains("uic.exe") || cmd.Contains("rcc.exe")) + break; + tool = null; + } + + if (tool != null) + break; + } + + if (tool == null) + return GetDirectory(type); // - fall-back on hard-coded directory + + var dir = "."; + var lastindex = tool.Outputs.LastIndexOf('\\'); + if (tool.Outputs.LastIndexOf('/') > lastindex) + lastindex = tool.Outputs.LastIndexOf('/'); + + if (lastindex != -1) + dir = tool.Outputs.Substring(0, lastindex); + dir = dir.Replace("\"", ""); + + if (type == Resources.mocDirKeyword) { + int index = dir.IndexOf(configName, StringComparison.OrdinalIgnoreCase); + if (index != -1) + dir = dir.Replace(dir.Substring(index, configName.Length), "$(ConfigurationName)"); + + index = dir.IndexOf(platformName, StringComparison.OrdinalIgnoreCase); + if (index != -1) + dir = dir.Replace(dir.Substring(index, platformName.Length), "$(PlatformName)"); + dir = HelperFunctions.NormalizeRelativeFilePath(dir); + + mocDirCache.Add(fullName, dir); + } else if (type == Resources.uicDirKeyword) { + dir = HelperFunctions.NormalizeRelativeFilePath(dir); + uicDirCache.Add(fullName, dir); + } else if (type == Resources.rccDirKeyword) { + dir = HelperFunctions.NormalizeRelativeFilePath(dir); + rccDirCache.Add(fullName, dir); + } else { + dir = HelperFunctions.NormalizeRelativeFilePath(dir); + } + + CleanUpCache(project); + return dir; // - retrieved from moc/uic/rcc steps + } catch { } + return GetDirectory(type); // - fall-back on hard-coded directory + } + + private const string registryPath = "SOFTWARE\\" + Resources.registryPackagePath; + + public static string GetDirectory(string type) + { + try { + var key = Registry.CurrentUser.OpenSubKey(registryPath); + if (key != null) { + if (key.GetValue(type, null) is string path) + return HelperFunctions.NormalizeRelativeFilePath(path); + } + } catch { } + if (type == Resources.mocDirKeyword) + return Resources.generatedFilesDir + "\\$(ConfigurationName)"; + return Resources.generatedFilesDir; + } + + public static string GetOption(EnvDTE.Project project, string type) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + // check for directory in following order: + // - stored in project + // - globally defined default option + // - empty options + if (project != null && project.Globals.get_VariablePersists(type)) + return project.Globals[type] as string; + return GetOption(type); + } + + public static string GetOption(string type) + { + try { + var key = Registry.CurrentUser.OpenSubKey(registryPath); + if (key != null) { + if (key.GetValue(type, null) is string opt) + return opt; + } + } catch { } + return null; + } + + public static bool GetBoolValue(EnvDTE.Project project, string type) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + // check for directory in following order: + // - stored in project + // - globally defined default option + // - empty options + if (project != null && project.Globals.get_VariablePersists(type)) + return Convert.ToInt32(project.Globals[type] as string) > 0; + return GetBoolValue(type, false); + } + + public static bool GetBoolValue(string key, bool defaultValue) + { + var regKey = Registry.CurrentUser.OpenSubKey(registryPath); + if (regKey == null) + return defaultValue; + return ((int)regKey.GetValue(key, defaultValue ? 1 : 0)) > 0; + } + + public static bool ValueExists(string key) + { + var regKey = Registry.CurrentUser.OpenSubKey(registryPath); + if (regKey != null) { + foreach (var s in regKey.GetValueNames()) { + if (s == key) + return true; + } + } + return false; + } + + public static string GetProjectQtSetting(EnvDTE.Project project, string propertyName) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var activeConfig = project?.ConfigurationManager?.ActiveConfiguration; + if (activeConfig == null) + return null; + var activeConfigId = $"{activeConfig.ConfigurationName}|{activeConfig.PlatformName}"; + + try { + var props = project.Object as VCProject as IVCBuildPropertyStorage; + return props?.GetPropertyValue(propertyName, activeConfigId, "ProjectFile"); + } catch { + return null; + } + } + + public static void CleanUpCache(EnvDTE.Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var projects = new HashSet<string>(StringComparer.OrdinalIgnoreCase); + foreach (var p in HelperFunctions.ProjectsInSolution(project.DTE)) + projects.Add(p.FullName); + + mocDirCache.RemoveValues(projects); + uicDirCache.RemoveValues(projects); + rccDirCache.RemoveValues(projects); + } + + static void RemoveValues(this Dictionary<string, string> cache, HashSet<string> projects) + { + foreach (var key in cache.Keys) { + if (projects.Contains(key)) + cache.Remove(key); + } + } + } +} diff --git a/QtVsTools.Core/CompilerToolWrapper.cs b/QtVsTools.Core/CompilerToolWrapper.cs index b9d95fc..f502f62 100644 --- a/QtVsTools.Core/CompilerToolWrapper.cs +++ b/QtVsTools.Core/CompilerToolWrapper.cs @@ -26,11 +26,11 @@ ** ****************************************************************************/ -using Microsoft.VisualStudio.VCProjectEngine; using System; using System.Collections.Generic; using System.IO; using System.Reflection; +using Microsoft.VisualStudio.VCProjectEngine; namespace QtVsTools.Core { @@ -44,7 +44,7 @@ /// Using VCCLCompilerTool directly will break the VS integration for Win CE. class CompilerToolWrapper { - private VCCLCompilerTool compilerTool; + private readonly VCCLCompilerTool compilerTool; private readonly Object compilerObj; private readonly Type compilerType; @@ -302,13 +302,6 @@ return GetStringProperty("AdditionalIncludeDirectories"); } - public string GetPrecompiledHeaderFile() - { - if (compilerTool != null) - return compilerTool.PrecompiledHeaderFile; - return GetStringProperty("PrecompiledHeaderFile"); - } - public string GetPrecompiledHeaderThrough() { if (compilerTool != null) @@ -326,20 +319,6 @@ if (obj == null) return pchOption.pchNone; return (pchOption)obj; - } - - public void SetDebugInformationFormat(debugOption value) - { - if (compilerTool != null) { - compilerTool.DebugInformationFormat = value; - } else { - compilerType.InvokeMember( - "DebugInformationFormat", - BindingFlags.SetProperty, - null, - compilerObj, - new object[] { value }); - } } public runtimeLibraryOption RuntimeLibrary @@ -364,62 +343,6 @@ } else { compilerTool.RuntimeLibrary = value; } - } - } - - public void SetOptimization(optimizeOption value) - { - if (compilerTool != null) { - compilerTool.Optimization = value; - } else { - compilerType.InvokeMember( - "Optimization", - BindingFlags.SetProperty, - null, - compilerObj, - new object[] { value }); - } - } - - public void SetTreatWChar_tAsBuiltInType(bool value) - { - if (compilerTool != null) { - compilerTool.TreatWChar_tAsBuiltInType = value; - } else { - compilerType.InvokeMember( - "TreatWChar_tAsBuiltInType", - BindingFlags.SetProperty, - null, - compilerObj, - new object[] { value }); - } - } - - public void SetPrecompiledHeaderFile(string file) - { - if (compilerTool != null) { - compilerTool.PrecompiledHeaderFile = file; - } else { - compilerType.InvokeMember( - "PrecompiledHeaderFile", - BindingFlags.SetProperty, - null, - compilerObj, - new object[] { file }); - } - } - - public void SetPrecompiledHeaderThrough(string value) - { - if (compilerTool != null) { - compilerTool.PrecompiledHeaderThrough = value; - } else { - compilerType.InvokeMember( - "PrecompiledHeaderThrough", - BindingFlags.SetProperty, - null, - compilerObj, - new object[] { value }); } } diff --git a/QtVsTools.Core/CxxStreamReader.cs b/QtVsTools.Core/CxxStreamReader.cs index eb758eb..b3a6394 100644 --- a/QtVsTools.Core/CxxStreamReader.cs +++ b/QtVsTools.Core/CxxStreamReader.cs @@ -42,12 +42,12 @@ Normal, Comment, String } private State state = State.Normal; - private StreamReader sr; + private readonly StreamReader sr; private string partialLine; bool disposed; int _lineNum; - string[] _lines; + readonly string[] _lines; public CxxStreamReader(string[] lines) { diff --git a/QtVsTools.Core/ExportProjectDialog.cs b/QtVsTools.Core/ExportProjectDialog.cs index 13aea35..2c5d3ad 100644 --- a/QtVsTools.Core/ExportProjectDialog.cs +++ b/QtVsTools.Core/ExportProjectDialog.cs @@ -68,11 +68,7 @@ optionTextBox.Text = ""; openCheckBox.Text = SR.GetString("ExportProjectDialog_Open"); createPriFileCheckBox.Text = SR.GetString("ExportProjectDialog_CreatePri"); - - if (SR.LanguageName == "de") - Size = new Size(470, 300); - else - Size = new Size(400, 300); + Size = new Size(400, 300); ShowInTaskbar = false; Shown += ExportProjectDialog_Shown; diff --git a/QtVsTools.Core/Extensions.cs b/QtVsTools.Core/Extensions.cs index 4f14aa6..dee20a0 100644 --- a/QtVsTools.Core/Extensions.cs +++ b/QtVsTools.Core/Extensions.cs @@ -32,15 +32,6 @@ { public static class Extensions { - public static string Quoute(this string input) - { - if (!input.StartsWith("\"", StringComparison.Ordinal)) - input = "\"" + input; - if (!input.EndsWith("\"", StringComparison.Ordinal)) - input += "\""; - return input; - } - public static string Replace(this string original, string oldValue, string newValue, StringComparison comparison) { diff --git a/QtVsTools.Core/FakeFilter.cs b/QtVsTools.Core/FakeFilter.cs index 8851174..a557d09 100644 --- a/QtVsTools.Core/FakeFilter.cs +++ b/QtVsTools.Core/FakeFilter.cs @@ -34,11 +34,6 @@ public string Filter { get; set; } public string UniqueIdentifier { get; set; } - private bool parseFiles = true; - public bool ParseFiles - { - get { return parseFiles; } - set { parseFiles = value; } - } + public bool ParseFiles { get; set; } = true; } } diff --git a/QtVsTools.Core/Filters.cs b/QtVsTools.Core/Filters.cs index ab55d55..7746152 100644 --- a/QtVsTools.Core/Filters.cs +++ b/QtVsTools.Core/Filters.cs @@ -71,17 +71,6 @@ }; } - public static FakeFilter TranslationFiles() - { - return new FakeFilter - { - UniqueIdentifier = "{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}", - Name = SR.GetString("Resources_TranslationFiles"), - Filter = "ts", - ParseFiles = false - }; - } - public static FakeFilter GeneratedFiles() { return new FakeFilter @@ -89,16 +78,6 @@ UniqueIdentifier = "{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}", Name = SR.GetString("Resources_GeneratedFiles"), Filter = "moc;h;cpp", - }; - } - - public static FakeFilter OtherFiles() - { - return new FakeFilter - { - UniqueIdentifier = "{B67473BF-9FA1-4674-831E-CB28F72D4791}", - Name = SR.GetString("Resources_OtherFiles"), - Filter = "*", }; } } diff --git a/QtVsTools.Core/HelperFunctions.cs b/QtVsTools.Core/HelperFunctions.cs index b6fe0ff..a07fa89 100644 --- a/QtVsTools.Core/HelperFunctions.cs +++ b/QtVsTools.Core/HelperFunctions.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,10 +26,6 @@ ** ****************************************************************************/ -using EnvDTE; -using Microsoft.VisualStudio.VCProjectEngine; -using Microsoft.Win32; -using QtVsTools.Core.QtMsBuild; using System; using System.Collections.Generic; using System.Diagnostics; @@ -40,105 +36,31 @@ using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; +#if VS2017 +using Microsoft.Win32; +#endif +using EnvDTE; using Process = System.Diagnostics.Process; namespace QtVsTools.Core { + using QtMsBuild; + public static class HelperFunctions { - public static string FindQtDirWithTools(Project project) - { - var versionManager = QtVersionManager.The(); - string projectQtVersion = null; - if (IsQtProject(project)) - projectQtVersion = versionManager.GetProjectQtVersion(project); - return FindQtDirWithTools(projectQtVersion); - } - - public static string FindQtDirWithTools(string projectQtVersion) - { - string tool = null; - return FindQtDirWithTools(tool, projectQtVersion); - } - - public static string FindQtDirWithTools(string tool, string projectQtVersion) - { - if (!string.IsNullOrEmpty(tool)) { - if (!tool.StartsWith("\\bin\\", StringComparison.OrdinalIgnoreCase)) - tool = "\\bin\\" + tool; - if (!tool.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) - tool += ".exe"; - } - - var versionManager = QtVersionManager.The(); - string qtDir = null; - if (projectQtVersion != null) - qtDir = versionManager.GetInstallPath(projectQtVersion); - - if (qtDir == null) - qtDir = Environment.GetEnvironmentVariable("QTDIR"); - - var found = false; - if (tool == null) { - found = File.Exists(qtDir + "\\bin\\designer.exe") - && File.Exists(qtDir + "\\bin\\linguist.exe"); - } else { - found = File.Exists(qtDir + tool); - } - if (!found) { - VersionInformation exactlyMatchingVersion = null; - VersionInformation matchingVersion = null; - VersionInformation somehowMatchingVersion = null; - var viProjectQtVersion = versionManager.GetVersionInfo(projectQtVersion); - foreach (var qtVersion in versionManager.GetVersions()) { - var vi = versionManager.GetVersionInfo(qtVersion); - if (tool == null) { - found = File.Exists(vi.qtDir + "\\bin\\designer.exe") - && File.Exists(vi.qtDir + "\\bin\\linguist.exe"); - } else { - found = File.Exists(vi.qtDir + tool); - } - if (!found) - continue; - - if (viProjectQtVersion != null - && vi.qtMajor == viProjectQtVersion.qtMajor - && vi.qtMinor == viProjectQtVersion.qtMinor) { - exactlyMatchingVersion = vi; - break; - } - if (matchingVersion == null - && viProjectQtVersion != null - && vi.qtMajor == viProjectQtVersion.qtMajor) { - matchingVersion = vi; - } - if (somehowMatchingVersion == null) - somehowMatchingVersion = vi; - } - - if (exactlyMatchingVersion != null) - qtDir = exactlyMatchingVersion.qtDir; - else if (matchingVersion != null) - qtDir = matchingVersion.qtDir; - else if (somehowMatchingVersion != null) - qtDir = somehowMatchingVersion.qtDir; - else - qtDir = null; - } - return qtDir; - } - static readonly HashSet<string> _sources = new HashSet<string>(new[] { ".c", ".cpp", ".cxx" }, StringComparer.OrdinalIgnoreCase); - static public bool IsSourceFile(string fileName) + public static bool IsSourceFile(string fileName) { return _sources.Contains(Path.GetExtension(fileName)); } static readonly HashSet<string> _headers = new HashSet<string>(new[] { ".h", ".hpp", ".hxx" }, StringComparer.OrdinalIgnoreCase); - static public bool IsHeaderFile(string fileName) + public static bool IsHeaderFile(string fileName) { return _headers.Contains(Path.GetExtension(fileName)); } @@ -173,23 +95,28 @@ return ".qml".Equals(Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase); } - static public void SetDebuggingEnvironment(Project prj) + public static void SetDebuggingEnvironment(Project prj) { + ThreadHelper.ThrowIfNotOnUIThread(); SetDebuggingEnvironment(prj, string.Empty); } - static public void SetDebuggingEnvironment(Project prj, string solutionConfig) + public static void SetDebuggingEnvironment(Project prj, string solutionConfig) { + ThreadHelper.ThrowIfNotOnUIThread(); SetDebuggingEnvironment(prj, "PATH=$(QTDIR)\\bin;$(PATH)", false, solutionConfig); } - static public void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite) + public static void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite) { + ThreadHelper.ThrowIfNotOnUIThread(); SetDebuggingEnvironment(prj, envpath, overwrite, string.Empty); } - static public void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite, string solutionConfig) + public static void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite, string solutionConfig) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (QtProject.GetFormatVersion(prj) >= Resources.qtMinFormatVersion_Settings) return; @@ -252,28 +179,29 @@ } } - public static bool IsProjectInSolution(DTE dteObject, string fullName) + public static Project ProjectFromSolution(DTE dteObject, string fullName) { - var fi = new FileInfo(fullName); + ThreadHelper.ThrowIfNotOnUIThread(); + fullName = new FileInfo(fullName).FullName; foreach (var p in ProjectsInSolution(dteObject)) { - if (p.FullName.ToLower() == fi.FullName.ToLower()) - return true; + if (p.FullName.Equals(fullName, StringComparison.OrdinalIgnoreCase)) + return p; } - return false; + return null; } /// <summary> /// Returns the normalized file path of a given file. /// </summary> /// <param name="name">file name</param> - static public string NormalizeFilePath(string name) + public static string NormalizeFilePath(string name) { var fi = new FileInfo(name); return fi.FullName; } - static public string NormalizeRelativeFilePath(string path) + public static string NormalizeRelativeFilePath(string path) { if (path == null) return ".\\"; @@ -299,7 +227,7 @@ return path; } - static public bool IsAbsoluteFilePath(string path) + public static bool IsAbsoluteFilePath(string path) { path = path.Trim(); if (path.Length >= 2 && path[1] == ':') @@ -316,7 +244,7 @@ /// </summary> /// <param name="streamReader"></param> /// <returns>the composite string</returns> - static private string ReadProFileLine(StreamReader streamReader) + private static string ReadProFileLine(StreamReader streamReader) { var line = streamReader.ReadLine(); if (line == null) @@ -337,7 +265,7 @@ /// </summary> /// <param name="profile">full name of .pro file to read</param> /// <returns>true if this is a subdirs file</returns> - static public bool IsSubDirsFile(string profile) + public static bool IsSubDirsFile(string profile) { StreamReader sr = null; try { @@ -407,55 +335,6 @@ } /// <summary> - /// Replaces a string in the commandLine, description, outputs and additional dependencies - /// in all Custom build tools of the project - /// </summary> - /// <param name="project">Project</param> - /// <param name="oldString">String, which is going to be replaced</param> - /// <param name="oldString">String, which is going to replace the other one</param> - /// <returns></returns> - public static void ReplaceInCustomBuildTools(Project project, string oldString, string replaceString) - { - var vcPro = (VCProject)project.Object; - if (vcPro == null) - return; - - var qtMsBuild = new QtMsBuildContainer(new VCPropertyStorageProvider()); - qtMsBuild.BeginSetItemProperties(); - foreach (VCFile vcfile in (IVCCollection)vcPro.Files) { - foreach (VCFileConfiguration config in (IVCCollection)vcfile.FileConfigurations) { - try { - if (vcfile.ItemType == "CustomBuild") { - var tool = GetCustomBuildTool(config); - if (tool == null) - continue; - - tool.CommandLine = tool.CommandLine - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - tool.Description = tool.Description - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - tool.Outputs = tool.Outputs - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - tool.AdditionalDependencies = tool.AdditionalDependencies - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - } else { - var tool = new QtCustomBuildTool(config, qtMsBuild); - tool.CommandLine = tool.CommandLine - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - } - } catch (Exception) { - } - } - } - qtMsBuild.EndSetItemProperties(); - } - - /// <summary> /// Since VS2010 it is possible to have VCCustomBuildTools without commandlines /// for certain filetypes. We are not interested in them and thus try to read the /// tool's commandline. If this causes an exception, we ignore it. @@ -463,23 +342,19 @@ /// </summary> /// <param name="config">File configuration</param> /// <returns></returns> - static public VCCustomBuildTool GetCustomBuildTool(VCFileConfiguration config) + public static VCCustomBuildTool GetCustomBuildTool(VCFileConfiguration config) { - var file = config.File as VCFile; - if (file == null || file.ItemType != "CustomBuild") - return null; - - var tool = config.Tool as VCCustomBuildTool; - if (tool == null) - return null; - - try { - // TODO: The return value is not used at all? - var cmdLine = tool.CommandLine; - } catch { - return null; + if (config.File is VCFile file + && file.ItemType == "CustomBuild" + && config.Tool is VCCustomBuildTool tool) { + try { + _ = tool.CommandLine; + } catch { + return null; + } + return tool; } - return tool; + return null; } /// <summary> @@ -488,8 +363,10 @@ /// has to be "CustomBuild" /// </summary> /// <param name="projectItem">Project Item which needs to have custom build tool</param> - static public void EnsureCustomBuildToolAvailable(ProjectItem projectItem) + public static void EnsureCustomBuildToolAvailable(ProjectItem projectItem) { + ThreadHelper.ThrowIfNotOnUIThread(); + foreach (Property prop in projectItem.Properties) { if (prop.Name == "ItemType") { if ((string)prop.Value != "CustomBuild") @@ -499,169 +376,10 @@ } } - /// <summary> - /// As Qmake -tp vc Adds the full path to the additional dependencies - /// we need to do the same when toggling project kind to qmake generated. - /// </summary> - /// <returns></returns> - private static string AddFullPathToAdditionalDependencies(string qtDir, string additionalDependencies) - { - var returnString = additionalDependencies; - returnString = - Regex.Replace(returnString, "Qt(\\S+5?)\\.lib", qtDir + "\\lib\\Qt${1}.lib"); - returnString = - Regex.Replace(returnString, "(qtmaind?5?)\\.lib", qtDir + "\\lib\\${1}.lib"); - returnString = - Regex.Replace(returnString, "(enginiod?5?)\\.lib", qtDir + "\\lib\\${1}.lib"); - return returnString; - } - - /// <summary> - /// Toggles the kind of a project. If the project is a QMake generated project (qmake -tp vc) - /// it is transformed to an Qt VS Tools project and vice versa. - /// </summary> - /// <param name="project">Project</param> - /// <returns></returns> - public static void ToggleProjectKind(Project project) - { - if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings) - return; - - string qtDir = null; - var vcPro = (VCProject)project.Object; - if (!IsQMakeProject(project)) - return; - if (IsQtProject(project)) { - // TODO: qtPro is never used. - var qtPro = QtProject.Create(project); - var vm = QtVersionManager.The(); - qtDir = vm.GetInstallPath(project); - - foreach (var global in (string[])project.Globals.VariableNames) { - if (global.StartsWith("Qt5Version", StringComparison.Ordinal)) - project.Globals.set_VariablePersists(global, false); - } - - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - var compiler = CompilerToolWrapper.Create(config); - var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); - var librarian = (VCLibrarianTool)((IVCCollection)config.Tools).Item("VCLibrarianTool"); - if (compiler != null) { - var additionalIncludes = compiler.GetAdditionalIncludeDirectories(); - additionalIncludes = additionalIncludes.Replace("$(QTDIR)", qtDir, - StringComparison.OrdinalIgnoreCase); - compiler.SetAdditionalIncludeDirectories(additionalIncludes); - } - if (linker != null) { - linker.AdditionalLibraryDirectories = linker.AdditionalLibraryDirectories. - Replace("$(QTDIR)", qtDir, StringComparison.OrdinalIgnoreCase); - linker.AdditionalDependencies = AddFullPathToAdditionalDependencies(qtDir, linker.AdditionalDependencies); - } else { - librarian.AdditionalLibraryDirectories = librarian.AdditionalLibraryDirectories - .Replace("$(QTDIR)", qtDir, StringComparison.OrdinalIgnoreCase); - librarian.AdditionalDependencies = AddFullPathToAdditionalDependencies(qtDir, librarian.AdditionalDependencies); - } - } - - ReplaceInCustomBuildTools(project, "$(QTDIR)", qtDir); - } else { - qtDir = GetQtDirFromQMakeProject(project); - - var vm = QtVersionManager.The(); - var qtVersion = vm.GetQtVersionFromInstallDir(qtDir); - if (qtVersion == null) - qtVersion = vm.GetDefaultVersion(); - if (qtDir == null) - qtDir = vm.GetInstallPath(qtVersion); - var vi = vm.GetVersionInfo(qtVersion); - var platformName = vi.GetVSPlatformName(); - vm.SaveProjectQtVersion(project, qtVersion, platformName); - var qtPro = QtProject.Create(project); - if (!qtPro.SelectSolutionPlatform(platformName) || !qtPro.HasPlatform(platformName)) { - var newProject = false; - qtPro.CreatePlatform("Win32", platformName, null, vi, ref newProject); - if (!qtPro.SelectSolutionPlatform(platformName)) - Messages.Print("Can't select the platform " + platformName + "."); - } - - var activeConfig = project.ConfigurationManager.ActiveConfiguration.ConfigurationName; - var activeVCConfig = (VCConfiguration)((IVCCollection)qtPro.VCProject.Configurations).Item(activeConfig); - if (activeVCConfig.ConfigurationType == ConfigurationTypes.typeDynamicLibrary) { - var compiler = CompilerToolWrapper.Create(activeVCConfig); - var linker = (VCLinkerTool)((IVCCollection)activeVCConfig.Tools).Item("VCLinkerTool"); - var ppdefs = compiler.GetPreprocessorDefinitions(); - if (ppdefs != null - && ppdefs.IndexOf("QT_PLUGIN", StringComparison.Ordinal) > -1 - && ppdefs.IndexOf("QDESIGNER_EXPORT_WIDGETS", StringComparison.Ordinal) > -1 - && ppdefs.IndexOf("QtDesigner", StringComparison.Ordinal) > -1 - && linker.AdditionalDependencies != null - && linker.AdditionalDependencies.IndexOf("QtDesigner", StringComparison.Ordinal) > -1) { - qtPro.MarkAsDesignerPluginProject(); - } - } - - CleanupQMakeDependencies(project); - - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - var compiler = CompilerToolWrapper.Create(config); - var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); - - if (compiler != null) { - var additionalIncludes = compiler.AdditionalIncludeDirectories; - if (additionalIncludes != null) { - ReplaceDirectory(ref additionalIncludes, qtDir, "$(QTDIR)", project); - compiler.AdditionalIncludeDirectories = additionalIncludes; - } - } - if (linker != null) { - var linkerToolWrapper = new LinkerToolWrapper(linker); - var paths = linkerToolWrapper.AdditionalLibraryDirectories; - if (paths != null) { - ReplaceDirectory(ref paths, qtDir, "$(QTDIR)", project); - linkerToolWrapper.AdditionalLibraryDirectories = paths; - } - } - } - - ReplaceInCustomBuildTools(project, qtDir, "$(QTDIR)"); - qtPro.TranslateFilterNames(); - } - project.Save(project.FullName); - } - - /// <summary> - /// Replaces every occurrence of oldDirectory with replacement in the array of strings. - /// Parameter oldDirectory must be an absolute path. - /// This function converts relative directories to absolute paths internally - /// and replaces them, if necessary. If no replacement is done, the path isn't altered. - /// </summary> - /// <param name="project">The project is needed to convert relative paths to absolute paths.</param> - private static void ReplaceDirectory(ref List<string> paths, string oldDirectory, string replacement, Project project) - { - for (var i = 0; i < paths.Count; ++i) { - var dirName = paths[i]; - if (dirName.StartsWith("\"", StringComparison.Ordinal) && dirName.EndsWith("\"", StringComparison.Ordinal)) { - dirName = dirName.Substring(1, dirName.Length - 2); - } - if (!Path.IsPathRooted(dirName)) { - // convert to absolute path - dirName = Path.Combine(Path.GetDirectoryName(project.FullName), dirName); - dirName = Path.GetFullPath(dirName); - var alteredDirName = dirName.Replace(oldDirectory, replacement, StringComparison - .OrdinalIgnoreCase); - if (alteredDirName == dirName) - continue; - dirName = alteredDirName; - } else { - dirName = dirName.Replace(oldDirectory, replacement, StringComparison - .OrdinalIgnoreCase); - } - paths[i] = dirName; - } - } - public static string GetQtDirFromQMakeProject(Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + var vcProject = project.Object as VCProject; if (vcProject == null) return null; @@ -742,13 +460,25 @@ } /// <summary> - /// Return true if the project is a Qt project, otherwise false. + /// Return true if the project is a VS tools project; false otherwise. /// </summary> /// <param name="proj">project</param> - /// <returns></returns> - public static bool IsQtProject(VCProject proj) + public static bool IsVsToolsProject(Project proj) { - if (!IsQMakeProject(proj)) + ThreadHelper.ThrowIfNotOnUIThread(); // C++ Project Type GUID + if (proj == null || proj.Kind != "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") + return false; + return IsVsToolsProject(proj.Object as VCProject); + } + + /// <summary> + /// Return true if the project is a VS tools project; false otherwise. + /// </summary> + /// <param name="proj">project</param> + public static bool IsVsToolsProject(VCProject proj) + { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!IsQtProject(proj)) return false; if (QtProject.GetFormatVersion(proj) >= Resources.qtMinFormatVersion_Settings) @@ -759,95 +489,39 @@ return false; foreach (var global in envPro.Globals.VariableNames as string[]) { - if (global.StartsWith("Qt5Version", StringComparison.Ordinal) && envPro.Globals.get_VariablePersists(global)) + if (global.StartsWith("Qt5Version", StringComparison.Ordinal) + && envPro.Globals.get_VariablePersists(global)) { return true; + } } return false; } /// <summary> - /// Returns true if the specified project is a Qt Project. + /// Return true if the project is a Qt project; false otherwise. /// </summary> /// <param name="proj">project</param> public static bool IsQtProject(Project proj) { - try { - if (proj != null && proj.Kind == "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") - return IsQtProject(proj.Object as VCProject); - } catch { } - return false; + ThreadHelper.ThrowIfNotOnUIThread(); //C++ Project Type GUID + if (proj == null || proj.Kind != "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") + return false; + return IsQtProject(proj.Object as VCProject); } /// <summary> - /// Return true if the project is a QMake -tp vc project, otherwise false. + /// Return true if the project is a Qt project; false otherwise. /// </summary> /// <param name="proj">project</param> - /// <returns></returns> - public static bool IsQMakeProject(VCProject proj) + public static bool IsQtProject(VCProject proj) { if (proj == null) return false; var keyword = proj.keyword; - if (keyword == null || - (!keyword.StartsWith(Resources.qtProjectV2Keyword, StringComparison.Ordinal) - && !keyword.StartsWith(Resources.qtProjectKeyword, StringComparison.Ordinal))) { + if (string.IsNullOrEmpty(keyword)) return false; - } - - return true; - } - - /// <summary> - /// Returns true if the specified project is a QMake -tp vc Project. - /// </summary> - /// <param name="proj">project</param> - public static bool IsQMakeProject(Project proj) - { - try { - if (proj != null && proj.Kind == "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") - return IsQMakeProject(proj.Object as VCProject); - } catch { } - return false; - } - - public static void CleanupQMakeDependencies(Project project) - { - var vcPro = (VCProject)project.Object; - // clean up qmake mess - var rxp1 = new Regex("\\bQt\\w+d?5?\\.lib\\b"); - var rxp2 = new Regex("\\bQAx\\w+\\.lib\\b"); - var rxp3 = new Regex("\\bqtmaind?.lib\\b"); - var rxp4 = new Regex("\\benginiod?.lib\\b"); - foreach (VCConfiguration cfg in (IVCCollection)vcPro.Configurations) { - var linker = (VCLinkerTool)((IVCCollection)cfg.Tools).Item("VCLinkerTool"); - if (linker == null || linker.AdditionalDependencies == null) - continue; - var linkerWrapper = new LinkerToolWrapper(linker); - var deps = linkerWrapper.AdditionalDependencies; - var newDeps = new List<string>(); - foreach (var lib in deps) { - var m1 = rxp1.Match(lib); - var m2 = rxp2.Match(lib); - var m3 = rxp3.Match(lib); - var m4 = rxp4.Match(lib); - if (m1.Success) - newDeps.Add(m1.ToString()); - else if (m2.Success) - newDeps.Add(m2.ToString()); - else if (m3.Success) - newDeps.Add(m3.ToString()); - else if (m4.Success) - newDeps.Add(m4.ToString()); - else - newDeps.Add(lib); - } - // Remove Duplicates - var uniques = new Dictionary<string, int>(); - foreach (var dep in newDeps) - uniques[dep] = 1; - var uniqueList = new List<string>(uniques.Keys); - linkerWrapper.AdditionalDependencies = uniqueList; - } + return keyword.StartsWith(Resources.qtProjectKeyword, StringComparison.Ordinal) + || keyword.StartsWith(Resources.qtProjectV2Keyword, StringComparison.Ordinal); } /// <summary> @@ -951,6 +625,30 @@ } } + /// <summary> + /// Converts all directory separators of the path to the alternate character + /// directory separator. For instance, FromNativeSeparators("c:\\winnt\\system32") + /// returns "c:/winnt/system32". + /// </summary> + /// <param name="path">The path to convert.</param> + /// <returns>Returns path using '/' as file separator.</returns> + public static string FromNativeSeparators(string path) + { + return path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + } + + /// <summary> + /// Converts all alternate directory separators characters of the path to the native + /// directory separator. For instance, ToNativeSeparators("c:/winnt/system32") + /// returns "c:\\winnt\\system32". + /// </summary> + /// <param name="path">The path to convert.</param> + /// <returns>Returns path using '\' as file separator.</returns> + public static string ToNativeSeparator(string path) + { + return path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + public static string ChangePathFormat(string path) { return path.Replace('\\', '/'); @@ -981,6 +679,8 @@ public static void CollapseFilter(UIHierarchyItem item, UIHierarchy hierarchy, string nodeToCollapseFilter) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (string.IsNullOrEmpty(nodeToCollapseFilter)) return; @@ -994,6 +694,8 @@ public static void CollapseFilter(UIHierarchyItem item, UIHierarchy hierarchy) { + ThreadHelper.ThrowIfNotOnUIThread(); + var subItems = item.UIHierarchyItems; if (subItems != null) { foreach (UIHierarchyItem innerItem in subItems) { @@ -1042,7 +744,7 @@ public static List<string> GetProjectFiles(Project pro, FilesToList filter) { - var fileList = new List<string>(); + ThreadHelper.ThrowIfNotOnUIThread(); VCProject vcpro; try { @@ -1052,6 +754,7 @@ return null; } + var fileList = new List<string>(); var configurationName = pro.ConfigurationManager.ActiveConfiguration.ConfigurationName; foreach (VCFile vcfile in (IVCCollection)vcpro.Files) { @@ -1120,21 +823,24 @@ /// <param name="fileName"></param> public static void RemoveFileInProject(VCProject vcpro, string fileName) { - var qtProj = QtProject.Create(vcpro); - var fi = new FileInfo(fileName); + ThreadHelper.ThrowIfNotOnUIThread(); + fileName = new FileInfo(fileName).FullName; foreach (VCFile vcfile in (IVCCollection)vcpro.Files) { - if (vcfile.FullPath.ToLower() == fi.FullName.ToLower()) { + if (vcfile.FullPath.Equals(fileName, StringComparison.OrdinalIgnoreCase)) { vcpro.RemoveFile(vcfile); - qtProj.MoveFileToDeletedFolder(vcfile); + QtProject.Create(vcpro)?.MoveFileToDeletedFolder(vcfile); } } } public static Project GetSelectedProject(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (dteObject == null) return null; + Array prjs = null; try { prjs = (Array)dteObject.ActiveSolutionProjects; @@ -1146,30 +852,23 @@ return null; // don't handle multiple selection... use the first one - if (prjs.GetValue(0) is Project) - return (Project)prjs.GetValue(0); + if (prjs.GetValue(0) is Project project) + return project; return null; } public static Project GetActiveDocumentProject(DTE dteObject) { - if (dteObject == null) - return null; - var doc = dteObject.ActiveDocument; - if (doc == null) - return null; - - if (doc.ProjectItem == null) - return null; - - return doc.ProjectItem.ContainingProject; + ThreadHelper.ThrowIfNotOnUIThread(); + return dteObject?.ActiveDocument?.ProjectItem?.ContainingProject; } public static Project GetSingleProjectInSolution(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + var projectList = ProjectsInSolution(dteObject); - if (dteObject == null || dteObject.Solution == null || - projectList.Count != 1) + if (projectList.Count != 1) return null; // no way to know which one to select return projectList[0]; @@ -1182,22 +881,24 @@ /// </summary> public static Project GetSelectedQtProject(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + // can happen sometimes shortly after starting VS - if (dteObject == null || dteObject.Solution == null - || ProjectsInSolution(dteObject).Count == 0) + if (ProjectsInSolution(dteObject).Count == 0) return null; - Project pro; - - if ((pro = GetSelectedProject(dteObject)) == null) { + var pro = GetSelectedProject(dteObject); + if (pro == null) { if ((pro = GetSingleProjectInSolution(dteObject)) == null) pro = GetActiveDocumentProject(dteObject); } - return IsQtProject(pro) ? pro : null; + return IsVsToolsProject(pro) ? pro : null; } public static VCFile[] GetSelectedFiles(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (GetSelectedQtProject(dteObject) == null) return null; @@ -1239,6 +940,8 @@ public static RccOptions ParseRccOptions(string cmdLine, VCFile qrcFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + var pro = VCProjectToProject((VCProject)qrcFile.project); var rccOpts = new RccOptions(pro, qrcFile); @@ -1261,11 +964,17 @@ public static Project VCProjectToProject(VCProject vcproj) { + ThreadHelper.ThrowIfNotOnUIThread(); return (Project)vcproj.Object; } public static List<Project> ProjectsInSolution(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (dteObject == null) + return new List<Project>(); + var projects = new List<Project>(); var solution = dteObject.Solution; if (solution != null) { @@ -1287,6 +996,8 @@ private static void addSubProjects(Project prj, ref List<Project> projects) { + ThreadHelper.ThrowIfNotOnUIThread(); + // If the actual object of the project is null then the project was probably unloaded. if (prj.Object == null) return; @@ -1303,6 +1014,8 @@ private static void addSubProjects(ProjectItems subItems, ref List<Project> projects) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (subItems == null) return; @@ -1393,21 +1106,6 @@ return true; } - public static string FindFileInPATH(string fileName) - { - var envPATH = Environment.ExpandEnvironmentVariables("%PATH%"); - var directories = envPATH.Split(';'); - foreach (var directory in directories) { - var fullFilePath = directory; - if (!fullFilePath.EndsWith("\\", StringComparison.Ordinal)) - fullFilePath += '\\'; - fullFilePath += fileName; - if (File.Exists(fullFilePath)) - return fullFilePath; - } - return null; - } - /// <summary> /// This method copies the specified directory and all its child directories and files to /// the specified destination. The destination directory is created if it does not exist. @@ -1453,13 +1151,14 @@ string platformName, string filePath = null) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project == null || string.IsNullOrEmpty(configName) || string.IsNullOrEmpty(platformName)) return false; var vcProject = project.Object as VCProject; - if (filePath == null) { var vcConfig = (from VCConfiguration _config in (IVCCollection)vcProject.Configurations @@ -1503,12 +1202,10 @@ VCProject vcProj = null; VCFile vcFile = null; string configName = "", platformName = ""; - var vcConfig = config as VCConfiguration; - if (vcConfig != null) { + if (config is VCConfiguration vcConfig) { vcProj = vcConfig.project as VCProject; configName = vcConfig.ConfigurationName; - var vcPlatform = vcConfig.Platform as VCPlatform; - if (vcPlatform != null) + if (vcConfig.Platform is VCPlatform vcPlatform) platformName = vcPlatform.Name; try { expanded = vcConfig.Evaluate(expanded); @@ -1520,11 +1217,9 @@ vcFile = vcFileConfig.File as VCFile; if (vcFile != null) vcProj = vcFile.project as VCProject; - var vcProjConfig = vcFileConfig.ProjectConfiguration as VCConfiguration; - if (vcProjConfig != null) { + if (vcFileConfig.ProjectConfiguration is VCConfiguration vcProjConfig) { configName = vcProjConfig.ConfigurationName; - var vcPlatform = vcProjConfig.Platform as VCPlatform; - if (vcPlatform != null) + if (vcProjConfig.Platform is VCPlatform vcPlatform) platformName = vcPlatform.Name; } try { @@ -1637,6 +1332,7 @@ return true; } +#if VS2017 private static string GetRegistrySoftwareString(string subKeyName, string valueName) { var keyName = new StringBuilder(); @@ -1644,28 +1340,25 @@ if (System.Environment.Is64BitOperatingSystem && IntPtr.Size == 4) keyName.Append(@"WOW6432Node\"); keyName.Append(subKeyName); - try { using (var key = Registry.LocalMachine.OpenSubKey(keyName.ToString(), false)) { if (key == null) return ""; //key not found - RegistryValueKind valueKind = key.GetValueKind(valueName); if (valueKind != RegistryValueKind.String && valueKind != RegistryValueKind.ExpandString) { return ""; //wrong value kind } - Object objValue = key.GetValue(valueName); if (objValue == null) return ""; //error getting value - return objValue.ToString(); } } catch { return ""; } } +#endif public static string GetWindows10SDKVersion() { @@ -1713,11 +1406,6 @@ string vcPath = Path.Combine(vsPath, "VC"); #endif return vcPath; - } - - public static bool SetVCVars(ProcessStartInfo startInfo) - { - return SetVCVars(null, startInfo); } public static bool SetVCVars(VersionInformation VersionInfo, ProcessStartInfo startInfo) @@ -1820,8 +1508,21 @@ } } } + + // Get PATH string envPath = startInfo.EnvironmentVariables["PATH"]; - string clPath = envPath.Split(';') + + // Remove invalid chars + envPath = string.Join("", envPath.Split(Path.GetInvalidPathChars())); + + // Split into list of paths + var paths = envPath + .Split(';') + .Where(x => !string.IsNullOrEmpty(x)) + .Select(x => x.Trim()); + + // Check if cl.exe is in PATH + string clPath = paths .Select(path => Path.Combine(path, "cl.exe")) .Where(pathToCl => File.Exists(pathToCl)) .FirstOrDefault(); @@ -1872,12 +1573,6 @@ } else { return canonicalPath; } - } - - public static bool PathEquals(string path1, string path2) - { - return (CanonicalPath(path1).Equals(CanonicalPath(path2), - StringComparison.InvariantCultureIgnoreCase)); } public static bool PathIsRelativeTo(string path, string subPath) diff --git a/QtVsTools.Core/Legacy/QtProject.cs b/QtVsTools.Core/Legacy/QtProject.cs new file mode 100644 index 0000000..0d02208 --- /dev/null +++ b/QtVsTools.Core/Legacy/QtProject.cs @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using EnvDTE; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; + +namespace QtVsTools.Core.Legacy +{ + using Core; + + public static class QtProject + { + public static void MarkAsDesignerPluginProject(Core.QtProject qtPro) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + qtPro.Project.Globals["IsDesignerPlugin"] = true.ToString(); + if (!qtPro.Project.Globals.get_VariablePersists("IsDesignerPlugin")) + qtPro.Project.Globals.set_VariablePersists("IsDesignerPlugin", true); + } + + public static bool PromptChangeQtVersion(Project project, string oldVersion, string newVersion) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var versionManager = Core.QtVersionManager.The(); + var viOld = versionManager.GetVersionInfo(oldVersion); + var viNew = versionManager.GetVersionInfo(newVersion); + + if (viOld == null || viNew == null) + return true; + + var oldIsWinRt = viOld.isWinRT(); + var newIsWinRt = viNew.isWinRT(); + + if (newIsWinRt == oldIsWinRt || newIsWinRt == IsWinRT(project)) + return true; + + var caption = string.Format("Change Qt Version ({0})", project.Name); + var text = string.Format( + "Changing Qt version from {0} to {1}.\r\n" + + "Project might not build. Are you sure?", + newIsWinRt ? "Win32" : "WinRT", + newIsWinRt ? "WinRT" : "Win32" + ); + + return MessageBox.Show(text, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) + == DialogResult.Yes; + } + + public static bool HasModule(Project project, int id, string qtVersion = null) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var foundInIncludes = false; + var foundInLibs = false; + + var vm = Core.QtVersionManager.The(); + var versionInfo = qtVersion != null ? vm.GetVersionInfo(qtVersion) + : vm.GetVersionInfo(project); + if (versionInfo == null) + versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); + if (versionInfo == null) + return false; // neither a default or project Qt version + var info = QtModules.Instance.Module(id, versionInfo.qtMajor); + if (info == null) + return false; + + var vcPro = project.Object as VCProject; + foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { + var compiler = CompilerToolWrapper.Create(config); + var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); + + if (compiler != null) { + if (compiler.GetAdditionalIncludeDirectories() == null) + continue; + var incPathList = info.GetIncludePath(); + var includeDirs = compiler.GetAdditionalIncludeDirectoriesList(); + foundInIncludes = (incPathList.Count > 0); + foreach (var incPath in incPathList) { + var fixedIncludeDir = FixFilePathForComparison(incPath); + if (!includeDirs.Any(dir => + FixFilePathForComparison(dir) == fixedIncludeDir)) { + foundInIncludes = false; + break; + } + } + } + + if (foundInIncludes) + break; + + List<string> libs = null; + if (linker != null) { + var linkerWrapper = new LinkerToolWrapper(linker); + libs = linkerWrapper.AdditionalDependencies; + } + + if (libs != null) { + var moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo); + foundInLibs = moduleLibs.All(moduleLib => libs.Contains(moduleLib)); + } + } + return foundInIncludes || foundInLibs; + } + + public static void AddModule(Project project, int id) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (HasModule(project, id)) + return; + + var vm = Core.QtVersionManager.The(); + var versionInfo = vm.GetVersionInfo(project); + if (versionInfo == null) + versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); + + var vcPro = project.Object as VCProject; + foreach (VCConfiguration config in vcPro.Configurations as IVCCollection) { + + var info = QtModules.Instance.Module(id, versionInfo.qtMajor); + if (Core.QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings) { + var config3 = config as VCConfiguration3; + if (config3 == null) + continue; + if (!string.IsNullOrEmpty(info.proVarQT)) { + var qtModulesValue = config.GetUnevaluatedPropertyValue("QtModules"); + var qtModules = new HashSet<string>( + !string.IsNullOrEmpty(qtModulesValue) + ? qtModulesValue.Split(';') + : new string[] { }); + qtModules.UnionWith(info.proVarQT.Split(' ')); + config3.SetPropertyValue(Resources.projLabelQtSettings, true, + "QtModules", string.Join(";", qtModules)); + } + // In V3 project format, compiler and linker options + // required by modules are set by Qt/MSBuild. + continue; + } + + var compiler = CompilerToolWrapper.Create(config); + var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); + + if (compiler != null) { + foreach (var define in info.Defines) + compiler.AddPreprocessorDefinition(define); + + var incPathList = info.GetIncludePath(); + foreach (var incPath in incPathList) + compiler.AddAdditionalIncludeDirectories(incPath); + } + if (linker != null) { + var moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo); + var linkerWrapper = new LinkerToolWrapper(linker); + var additionalDeps = linkerWrapper.AdditionalDependencies; + var dependenciesChanged = false; + if (additionalDeps == null || additionalDeps.Count == 0) { + additionalDeps = moduleLibs; + dependenciesChanged = true; + } else { + foreach (var moduleLib in moduleLibs) { + if (!additionalDeps.Contains(moduleLib)) { + additionalDeps.Add(moduleLib); + dependenciesChanged = true; + } + } + } + if (dependenciesChanged) + linkerWrapper.AdditionalDependencies = additionalDeps; + } + } + } + + public static void RemoveModule(Project project, int id) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var vm = Core.QtVersionManager.The(); + var versionInfo = vm.GetVersionInfo(project); + if (versionInfo == null) + versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); + + var vcPro = project.Object as VCProject; + foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { + var compiler = CompilerToolWrapper.Create(config); + var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); + + var info = QtModules.Instance.Module(id, versionInfo.qtMajor); + if (compiler != null) { + foreach (var define in info.Defines) + compiler.RemovePreprocessorDefinition(define); + var additionalIncludeDirs = compiler.AdditionalIncludeDirectories; + if (additionalIncludeDirs != null) { + var lst = new List<string>(additionalIncludeDirs); + foreach (var includePath in info.IncludePath) { + lst.Remove(includePath); + lst.Remove('\"' + includePath + '\"'); + } + compiler.AdditionalIncludeDirectories = lst; + } + } + if (linker != null && linker.AdditionalDependencies != null) { + var linkerWrapper = new LinkerToolWrapper(linker); + var moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo); + var additionalDependencies = linkerWrapper.AdditionalDependencies; + var dependenciesChanged = false; + foreach (var moduleLib in moduleLibs) + dependenciesChanged |= additionalDependencies.Remove(moduleLib); + if (dependenciesChanged) + linkerWrapper.AdditionalDependencies = additionalDependencies; + } + } + } + + internal static bool IsDesignerPluginProject(Core.QtProject qtPro) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var b = false; + if (qtPro.Project.Globals.get_VariablePersists("IsDesignerPlugin")) { + var s = qtPro.Project.Globals["IsDesignerPlugin"] as string; + try { + b = bool.Parse(s); + } catch { } + } + return b; + } + + + private static bool IsWinRT(Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + try { + var vcProject = project.Object as VCProject; + var vcConfigs = vcProject.Configurations as IVCCollection; + var vcConfig = vcConfigs.Item(1) as VCConfiguration; + var appType = vcConfig.GetEvaluatedPropertyValue("ApplicationType"); + if (appType == "Windows Store") + return true; + } catch { } + return false; + } + + private static string FixFilePathForComparison(string path) + { + return HelperFunctions.NormalizeRelativeFilePath(path).ToLower(); + } + + private static bool IsDebugConfiguration(VCConfiguration conf) + { + var tool = CompilerToolWrapper.Create(conf); + if (tool != null) { + return tool.RuntimeLibrary == runtimeLibraryOption.rtMultiThreadedDebug + || tool.RuntimeLibrary == runtimeLibraryOption.rtMultiThreadedDebugDLL; + } + return false; + } + } +} diff --git a/QtVsTools.Core/Legacy/QtVSIPSettings.cs b/QtVsTools.Core/Legacy/QtVSIPSettings.cs new file mode 100644 index 0000000..b54940d --- /dev/null +++ b/QtVsTools.Core/Legacy/QtVSIPSettings.cs @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using Microsoft.VisualStudio.Shell; +using QtVsTools.Common; + +namespace QtVsTools.Core.Legacy +{ + public static class QtVSIPSettings + { + #region UIC + + public static string GetUicDirectory(EnvDTE.Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + return QtVSIPSettingsShared.GetDirectory(project, Resources.uicDirKeyword); + } + + public static void SaveUicDirectory(EnvDTE.Project project, string directory) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (directory == null) + directory = QtVSIPSettingsShared.GetDirectory(project, Resources.uicDirKeyword); + SaveDirectory(project, Resources.uicDirKeyword, directory); + } + #endregion + + #region MOC + + public static string GetMocDirectory(EnvDTE.Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + return QtVSIPSettingsShared.GetDirectory(project, Resources.mocDirKeyword); + } + + public static void SaveMocDirectory(EnvDTE.Project project, string directory) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (directory == null) + directory = QtVSIPSettingsShared.GetDirectory(project, Resources.mocDirKeyword); + SaveDirectory(project, Resources.mocDirKeyword, directory); + } + + public static string GetMocOptions() + { + return QtVSIPSettingsShared.GetOption(Resources.mocOptionsKeyword); + } + + public static string GetMocOptions(EnvDTE.Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + return QtVSIPSettingsShared.GetOption(project, Resources.mocOptionsKeyword); + } + + public static void SaveMocOptions(EnvDTE.Project project, string options) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (options == null) + options = GetMocOptions(); + + SaveOption(project, Resources.mocOptionsKeyword, options); + } + #endregion + + #region LUpdate + + public static bool GetLUpdateOnBuild(EnvDTE.Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (QtVSIPSettingsShared.GetProjectQtSetting(project, "QtRunLUpdateOnBuild") == "true") + return true; + return QtVSIPSettingsShared.GetBoolValue(project, Resources.lupdateKeyword); + } + + public static void SaveLUpdateOnBuild(EnvDTE.Project project, bool value) + { + ThreadHelper.ThrowIfNotOnUIThread(); + SetBoolValue(project, Resources.lupdateKeyword, value); + } + + public static string GetLUpdateOptions() + { + return QtVSIPSettingsShared.GetOption(Resources.lupdateOptionsKeyword); + } + + public static string GetLUpdateOptions(EnvDTE.Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + string qtLUpdateOptions = QtVSIPSettingsShared.GetProjectQtSetting(project, "QtLUpdateOptions"); + if (!string.IsNullOrEmpty(qtLUpdateOptions)) + return qtLUpdateOptions; + return QtVSIPSettingsShared.GetOption(project, Resources.lupdateOptionsKeyword); + } + + public static void SaveLUpdateOptions(EnvDTE.Project project, string options) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (options == null) + options = GetLUpdateOptions(); + + SaveOption(project, Resources.lupdateOptionsKeyword, options); + } + #endregion + + #region LRelease + + public static string GetLReleaseOptions() + { + return QtVSIPSettingsShared.GetOption(Resources.lreleaseOptionsKeyword); + } + + public static string GetLReleaseOptions(EnvDTE.Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + string qtLReleaseOptions = QtVSIPSettingsShared.GetProjectQtSetting(project, "QtLReleaseOptions"); + if (!string.IsNullOrEmpty(qtLReleaseOptions)) + return qtLReleaseOptions; + return QtVSIPSettingsShared.GetOption(project, Resources.lreleaseOptionsKeyword); + } + + public static void SaveLReleaseOptions(EnvDTE.Project project, string options) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (options == null) + options = GetLReleaseOptions(); + + SaveOption(project, Resources.lreleaseOptionsKeyword, options); + } + #endregion + + #region RCC + + public static string GetRccDirectory(EnvDTE.Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + return QtVSIPSettingsShared.GetDirectory(project, Resources.rccDirKeyword); + } + + public static void SaveRccDirectory(EnvDTE.Project project, string directory) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (directory == null) + directory = QtVSIPSettingsShared.GetDirectory(project, Resources.rccDirKeyword); + SaveDirectory(project, Resources.rccDirKeyword, directory); + } + #endregion + + #region QML + + public static bool GetQmlDebug(EnvDTE.Project project) + { + return Core.QtProject.Create(project).QmlDebug; + } + + public static void SaveQmlDebug(EnvDTE.Project project, bool enabled) + { + Core.QtProject.Create(project).QmlDebug = enabled; + } + #endregion + + private static void SaveDirectory(EnvDTE.Project project, string type, string dir) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + dir = HelperFunctions.NormalizeRelativeFilePath(dir); + project.Globals[type] = dir; + if (!project.Globals.get_VariablePersists(type)) + project.Globals.set_VariablePersists(type, true); + + QtVSIPSettingsShared.CleanUpCache(project); + } + + private static void SaveOption(EnvDTE.Project project, string type, string option) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + project.Globals[type] = option; + if (!project.Globals.get_VariablePersists(type)) + project.Globals.set_VariablePersists(type, true); + } + + private static void SetBoolValue(EnvDTE.Project project, string type, bool value) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + project.Globals[type] = Convert.ToInt32(value).ToString(); + if (!project.Globals.get_VariablePersists(type)) + project.Globals.set_VariablePersists(type, true); + } + } +} diff --git a/QtVsTools.Core/Legacy/QtVersionManager.cs b/QtVsTools.Core/Legacy/QtVersionManager.cs new file mode 100644 index 0000000..940dbea --- /dev/null +++ b/QtVsTools.Core/Legacy/QtVersionManager.cs @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using Microsoft.VisualStudio.Shell; + +namespace QtVsTools.Core.Legacy +{ + public static class QtVersionManager + { + public static string GetSolutionQtVersion(EnvDTE.Solution solution) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (solution == null) + return null; + + if (solution.Globals.get_VariableExists("Qt5Version")) { + var version = (string)solution.Globals["Qt5Version"]; + return Core.QtVersionManager.The().VerifyIfQtVersionExists(version) ? version : null; + } + + return null; + } + + public static bool SaveSolutionQtVersion(EnvDTE.Solution solution, string version) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (!Core.QtVersionManager.The().IsVersionAvailable(version) && version != "$(DefaultQtVersion)") + return false; + + solution.Globals["Qt5Version"] = version; + if (!solution.Globals.get_VariablePersists("Qt5Version")) + solution.Globals.set_VariablePersists("Qt5Version", true); + return true; + } + } +} diff --git a/QtVsTools.Core/LinkerToolWrapper.cs b/QtVsTools.Core/LinkerToolWrapper.cs index cc57a34..7db3506 100644 --- a/QtVsTools.Core/LinkerToolWrapper.cs +++ b/QtVsTools.Core/LinkerToolWrapper.cs @@ -26,11 +26,11 @@ ** ****************************************************************************/ -using Microsoft.VisualStudio.VCProjectEngine; using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; +using Microsoft.VisualStudio.VCProjectEngine; namespace QtVsTools.Core { @@ -39,7 +39,7 @@ /// </summary> public class LinkerToolWrapper { - private VCLinkerTool linker; + private readonly VCLinkerTool linker; public LinkerToolWrapper(VCLinkerTool linkerTool) { diff --git a/QtVsTools.Core/MainWinWrapper.cs b/QtVsTools.Core/MainWinWrapper.cs index f42ca31..2da7105 100644 --- a/QtVsTools.Core/MainWinWrapper.cs +++ b/QtVsTools.Core/MainWinWrapper.cs @@ -28,30 +28,18 @@ using System; using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; namespace QtVsTools.Core { public class MainWinWrapper : IWin32Window { - private readonly EnvDTE.DTE dteObject; + public IntPtr Handle { get; } public MainWinWrapper(EnvDTE.DTE dte) { - dteObject = dte; - } - - public IntPtr Handle - { - get - { - if (dteObject != null) -#if VS2022 - return dteObject.MainWindow.HWnd; -#else - return new IntPtr(dteObject.MainWindow.HWnd); -#endif - return new IntPtr(0); - } + ThreadHelper.ThrowIfNotOnUIThread(); + Handle = new IntPtr((long)dte.MainWindow.HWnd); } } } diff --git a/QtVsTools.Core/Messages.cs b/QtVsTools.Core/Messages.cs index c5eea32..507bcbb 100644 --- a/QtVsTools.Core/Messages.cs +++ b/QtVsTools.Core/Messages.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,34 +26,25 @@ ** ****************************************************************************/ -using EnvDTE; +using System; using System.Collections.Concurrent; -using System.Diagnostics; -using System.Linq; using System.Threading; -using Thread = System.Threading.Thread; using System.Windows.Forms; -using System.Threading.Tasks; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Threading; -using QtVsTools.VisualStudio; + +using Task = System.Threading.Tasks.Task; namespace QtVsTools.Core { + using VisualStudio; + public static class Messages { - private static OutputWindow Window { get; set; } private static OutputWindowPane Pane { get; set; } - private static OutputWindowPane _BuildPane; - private static OutputWindowPane BuildPane - { - get - { - return _BuildPane ?? (_BuildPane = Window.OutputWindowPanes.Cast<OutputWindowPane>() - .Where(pane => pane.Guid == "{1BD8A850-02D1-11D1-BEE7-00A0C913D1F8}") - .FirstOrDefault()); - } - } + private static readonly string PaneName = "Qt VS Tools"; + private static readonly Guid PaneGuid = new Guid("8f6a1e44-fa0b-49e5-9934-1c050555350e"); /// <summary> /// Show a message on the output pane. @@ -69,13 +60,15 @@ FlushMessages(); } - static void OutputWindowPane_Print(string text) + public static void Log(this Exception exception, bool clear = false, bool activate = false) { - OutputWindowPane_Init(); - Pane.OutputString(text + "\r\n"); - // show buildPane if a build is in progress - if (Dte.Solution.SolutionBuild.BuildState == vsBuildState.vsBuildStateInProgress) - BuildPane?.Activate(); + msgQueue.Enqueue(new Msg() + { + Clear = clear, + Text = ExceptionToString(exception), + Activate = activate + }); + FlushMessages(); } /// <summary> @@ -90,50 +83,44 @@ FlushMessages(); } - static void OutputWindowPane_Activate() + static async Task OutputWindowPane_ActivateAsync() { - OutputWindowPane_Init(); - Pane?.Activate(); + await OutputWindowPane_InitAsync(); + await Pane?.ActivateAsync(); } - private static string ExceptionToString(System.Exception e) + private static string ExceptionToString(System.Exception exception) { - return e.Message + "\r\n" + "(" + e.StackTrace.Trim() + ")"; + return $"An exception ({exception.GetType().Name}) occurred.\r\n" + + $"Message:\r\n {exception.Message}\r\n" + + $"Stack Trace:\r\n {exception.StackTrace.Trim()}\r\n"; } private static readonly string ErrorString = SR.GetString("Messages_ErrorOccured"); private static readonly string WarningString = SR.GetString("Messages_Warning"); private static readonly string SolutionString = SR.GetString("Messages_SolveProblem"); - static public void DisplayCriticalErrorMessage(System.Exception e) - { - MessageBox.Show(ErrorString + - ExceptionToString(e), - SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Error); - } - - static public void DisplayCriticalErrorMessage(string msg) + public static void DisplayCriticalErrorMessage(string msg) { MessageBox.Show(ErrorString + msg, SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Error); } - static public void DisplayErrorMessage(System.Exception e) + public static void DisplayErrorMessage(System.Exception e) { - MessageBox.Show(ErrorString + - ExceptionToString(e), + MessageBox.Show(ExceptionToString(e), SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Error); } - static public void DisplayErrorMessage(string msg) + public static void DisplayErrorMessage(string msg) { MessageBox.Show(ErrorString + msg, SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Error); } - static public void DisplayWarningMessage(System.Exception e, string solution) + public static void DisplayWarningMessage(System.Exception e, string solution) { MessageBox.Show(WarningString + ExceptionToString(e) + @@ -142,7 +129,7 @@ SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Warning); } - static public void DisplayWarningMessage(string msg) + public static void DisplayWarningMessage(string msg) { MessageBox.Show(WarningString + msg, @@ -158,10 +145,10 @@ FlushMessages(); } - static void OutputWindowPane_Clear() + static async Task OutputWindowPane_ClearAsync() { - OutputWindowPane_Init(); - Pane?.Clear(); + await OutputWindowPane_InitAsync(); + await Pane?.ClearAsync(); } class Msg @@ -171,33 +158,20 @@ public bool Activate { get; set; } = false; } - static bool shuttingDown = false; - static ConcurrentQueue<Msg> msgQueue = new ConcurrentQueue<Msg>(); - static DTE Dte { get; set; } = null; + static readonly ConcurrentQueue<Msg> msgQueue = new ConcurrentQueue<Msg>(); - private static void OnBeginShutdown() + private static async Task OutputWindowPane_InitAsync() { - shuttingDown = true; - } - - private static void OutputWindowPane_Init() - { - if (Dte == null) - Dte = VsServiceProvider.GetService<DTE>(); - var t = Stopwatch.StartNew(); - while (Pane == null && t.ElapsedMilliseconds < 5000) { - try { - Window = Dte.Windows.Item(Constants.vsWindowKindOutput).Object as OutputWindow; - Pane = Window?.OutputWindowPanes.Add(SR.GetString("Resources_QtVsTools")); - } catch { - } + try { if (Pane == null) - Thread.Yield(); + Pane = await OutputWindowPane.CreateAsync(PaneName, PaneGuid); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine(ex); } - Dte.Events.DTEEvents.OnBeginShutdown += OnBeginShutdown; } public static JoinableTaskFactory JoinableTaskFactory { get; set; } + static readonly object staticCriticalSection = new object(); static Task FlushTask { get; set; } static EventWaitHandle MessageReady { get; set; } @@ -209,27 +183,21 @@ MessageReady = new EventWaitHandle(false, EventResetMode.AutoReset); FlushTask = Task.Run(async () => { - while (!shuttingDown) { + var package = VsServiceProvider.Instance as Package; + while (!package.Zombied) { if (!await MessageReady.ToTask(3000)) continue; while (!msgQueue.IsEmpty) { - Msg msg; - if (!msgQueue.TryDequeue(out msg)) { + if (!msgQueue.TryDequeue(out Msg msg)) { await Task.Yield(); continue; } - //////////////////////////////////////////////////////////////////// - // Switch to main (UI) thread - await JoinableTaskFactory.SwitchToMainThreadAsync(); if (msg.Clear) - OutputWindowPane_Clear(); + await OutputWindowPane_ClearAsync(); if (msg.Text != null) - OutputWindowPane_Print(msg.Text); + await OutputWindowPane_PrintAsync(msg.Text); if (msg.Activate) - OutputWindowPane_Activate(); - //////////////////////////////////////////////////////////////////// - // Switch to background thread - await TaskScheduler.Default; + await OutputWindowPane_ActivateAsync(); } } }); @@ -237,5 +205,15 @@ } MessageReady.Set(); } + + static async Task OutputWindowPane_PrintAsync(string text) + { + var active = await OutputWindowPane.GetActiveAsync(); + + await OutputWindowPane_InitAsync(); + await Pane.PrintAsync(text); + + (active?.ActivateAsync()).Forget(); + } } } diff --git a/QtVsTools.Core/MocCmdChecker.cs b/QtVsTools.Core/MocCmdChecker.cs index dc0df1b..16ffaba 100644 --- a/QtVsTools.Core/MocCmdChecker.cs +++ b/QtVsTools.Core/MocCmdChecker.cs @@ -34,8 +34,8 @@ { class MocCmdChecker { - private Regex backslashRegEx = new Regex(@"\\+\.?\\+"); - private Regex endRegEx = new Regex(@"\\\.?$"); + private readonly Regex backslashRegEx = new Regex(@"\\+\.?\\+"); + private readonly Regex endRegEx = new Regex(@"\\\.?$"); private string NormalizePath(string path) { diff --git a/QtVsTools.Core/MsBuildProject.cs b/QtVsTools.Core/MsBuildProject.cs index 3b11f34..3eff430 100644 --- a/QtVsTools.Core/MsBuildProject.cs +++ b/QtVsTools.Core/MsBuildProject.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -30,22 +30,22 @@ using System.IO; using System.Collections.Generic; using System.Text; +using System.Text.RegularExpressions; using System.Linq; using System.Xml; using System.Xml.Linq; -using QtVsTools.Core.QtMsBuild; -using System.Text.RegularExpressions; using Microsoft.Build.Construction; using Microsoft.Build.Execution; using Microsoft.Build.Evaluation; -using QtVsTools.VisualStudio; -using QtVsTools.SyntaxAnalysis; -using EnvDTE; +using Microsoft.VisualStudio.Shell; namespace QtVsTools.Core { + using QtMsBuild; + using SyntaxAnalysis; + using static HelperFunctions; - using static RegExpr; + using static SyntaxAnalysis.RegExpr; public class MsBuildProject { @@ -65,7 +65,8 @@ User, Count } - MsBuildXmlFile[] files = new MsBuildXmlFile[(int)Files.Count]; + + readonly MsBuildXmlFile[] files = new MsBuildXmlFile[(int)Files.Count]; MsBuildProject() { @@ -94,7 +95,7 @@ } } - private static XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003"; + private static readonly XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003"; public static MsBuildProject Load(string pathToProject) { @@ -293,12 +294,8 @@ if (ConfigCondition == null) return false; - // Get default Qt dir - string defaultQtDir = null; var defaultVersionName = QtVersionManager.The().GetDefaultVersion(); var defaultVersion = QtVersionManager.The().GetVersionInfo(defaultVersionName); - if (defaultVersion != null) - defaultQtDir = defaultVersion.qtDir; // Get project configurations var configs = this[Files.Project].xml @@ -314,15 +311,6 @@ .FirstOrDefault(); if (globals == null) return false; - - // Get project configuration properties - var configProps = this[Files.Project].xml - .Elements(ns + "Project") - .Elements(ns + "PropertyGroup") - .Where(pg => - (string)pg.Attribute("Label") == "Configuration" - && pg.Attribute("Condition") != null) - .ToDictionary(pg => (string)pg.Attribute("Condition")); // Set Qt project format version var projKeyword = globals @@ -386,10 +374,8 @@ foreach (var pg in uncategorizedPropertyGroups) { foreach (var p in pg.Elements().ToList()) { var condition = p.Attribute("Condition") ?? pg.Attribute("Condition"); - XElement configPropertyGroup = null; - if (condition != null) - propertyGroups.TryGetValue((string)condition, out configPropertyGroup); - if (configPropertyGroup != null) { + if (condition != null && propertyGroups + .TryGetValue((string)condition, out XElement configPropertyGroup)) { p.Remove(); p.SetAttributeValue("Condition", null); configPropertyGroup.Add(p); @@ -535,12 +521,10 @@ foreach (var configQtSettings in qtSettings) { var configCondition = (string)configQtSettings.Attribute("Condition"); - XElement oldConfigQtInstall; - if (oldQtInstall.TryGetValue(configCondition, out oldConfigQtInstall)) + if (oldQtInstall.TryGetValue(configCondition, out XElement oldConfigQtInstall)) configQtSettings.Add(oldConfigQtInstall); - XElement oldConfigQtSettings; - if (oldQtSettings.TryGetValue(configCondition, out oldConfigQtSettings)) { + if (oldQtSettings.TryGetValue(configCondition, out XElement oldConfigQtSettings)) { foreach (var qtSetting in oldConfigQtSettings.Elements()) configQtSettings.Add(qtSetting); } @@ -600,6 +584,11 @@ .Elements(ns + "ItemDefinitionGroup") .Elements(ns + "Link"); + var resourceCompiler = this[Files.Project].xml + .Elements(ns + "Project") + .Elements(ns + "ItemDefinitionGroup") + .Elements(ns + "ResourceCompile"); + // Qt module names, to copy to QtModules property var moduleNames = new HashSet<string>(); @@ -613,9 +602,9 @@ var moduleLibs = new HashSet<string>(); // Go through all known Qt modules and check which ones are currently being used - foreach (var module in QtModules.Instance.GetAvailableModules()) { + foreach (var module in QtModules.Instance.GetAvailableModules(defaultVersion.qtMajor)) { - if (IsModuleUsed(module, compiler, linker)) { + if (IsModuleUsed(module, compiler, linker, resourceCompiler)) { // Qt module names, to copy to QtModules property if (!string.IsNullOrEmpty(module.proVarQT)) @@ -670,6 +659,12 @@ .Select(x => Unquote(x)) // Exclude paths rooted on $(QTDIR) .Where(x => !x.StartsWith("$(QTDIR)", IGNORE_CASE)))); + } + + // Remove Qt module macros from resource compiler properties + foreach (var defines in resourceCompiler.Elements(ns + "PreprocessorDefinitions")) { + defines.SetValue(string.Join(";", defines.Value.Split(';') + .Where(x => !moduleDefines.Contains(x)))); } // Add Qt module names to QtModules project property @@ -778,7 +773,8 @@ bool IsModuleUsed( QtModule module, IEnumerable<XElement> compiler, - IEnumerable<XElement> linker) + IEnumerable<XElement> linker, + IEnumerable<XElement> resourceCompiler) { // Module .lib is present in linker additional dependencies if (linker.Elements(ns + "AdditionalDependencies") @@ -788,8 +784,15 @@ return true; } - // Module macro is present in pre-processor definitions + // Module macro is present in the compiler pre-processor definitions if (compiler.Elements(ns + "PreprocessorDefinitions") + .SelectMany(x => x.Value.Split(';')) + .Any(x => module.Defines.Contains(x))) { + return true; + } + + // Module macro is present in resource compiler pre-processor definitions + if (resourceCompiler.Elements(ns + "PreprocessorDefinitions") .SelectMany(x => x.Value.Split(';')) .Any(x => module.Defines.Contains(x))) { return true; @@ -958,9 +961,9 @@ commandLine = replace(row.itemName, commandLine); // // * Configuration/platform, e.g. x64\Debug --> $(Platform)\$(Configuration) - commandLine = commandLine - .Replace(configName, "$(Configuration)", - StringComparison.InvariantCultureIgnoreCase) + // * ignore any word other than the expected configuration, e.g. lrelease.exe + commandLine = Regex.Replace(commandLine, @"\b" + configName + @"\b", + "$(Configuration)", RegexOptions.IgnoreCase) .Replace(platformName, "$(Platform)", StringComparison.InvariantCultureIgnoreCase); @@ -969,8 +972,7 @@ evaluator.Properties.Add(configProp.Name.LocalName, (string)configProp); if (!qtMsBuild.SetCommandLine(itemType, item, commandLine, evaluator)) { int lineNumber = 1; - var errorLine = row.command as IXmlLineInfo; - if (errorLine != null && errorLine.HasLineInfo()) + if (row.command is IXmlLineInfo errorLine && errorLine.HasLineInfo()) lineNumber = errorLine.LineNumber; Messages.Print(string.Format( @@ -1059,8 +1061,7 @@ return (string)cbt.Attribute("Include"); } } - string ouputFile; - if (!properties.TryGetValue(QtMoc.Property.InputFile, out ouputFile)) + if (!properties.TryGetValue(QtMoc.Property.InputFile, out string ouputFile)) return (string)cbt.Attribute("Include"); return ouputFile; } @@ -1085,8 +1086,7 @@ Path.IsPathRooted(x) ? x : Path.Combine(projDir, x))); var outputItems = new List<XElement>(); foreach (var outputFile in outputFiles) { - List<XElement> mocOutput = null; - if (projItemsByPath.TryGetValue(outputFile, out mocOutput)) { + if (projItemsByPath.TryGetValue(outputFile, out List<XElement> mocOutput)) { outputItems.AddRange(mocOutput); hasGeneratedFiles |= hasGeneratedFiles ? true : mocOutput .Where(x => !x.Elements(ns + "ExcludedFromBuild") @@ -1469,17 +1469,16 @@ class MSBuildEvaluator : IVSMacroExpander, IDisposable { - MsBuildXmlFile projFile; - string tempProjFilePath; - XElement evaluateTarget; - XElement evaluateProperty; - ProjectRootElement projRoot; - public Dictionary<string, string> expansionCache; + private readonly MsBuildXmlFile projFile; + private string tempProjFilePath; + private XElement evaluateTarget; + private XElement evaluateProperty; + private ProjectRootElement projRoot; + private readonly Dictionary<string, string> expansionCache; public Dictionary<string, string> Properties { get; - private set; } public MSBuildEvaluator(MsBuildXmlFile projFile) @@ -1522,8 +1521,7 @@ public string ExpandString(string stringToExpand) { - string expandedString; - if (TryExpansionCache(stringToExpand, out expandedString)) + if (TryExpansionCache(stringToExpand, out string expandedString)) return expandedString; if (evaluateTarget == null) { @@ -1649,7 +1647,7 @@ return true; } - static Regex ConditionParser = + static readonly Regex ConditionParser = new Regex(@"\'\$\(Configuration[^\)]*\)\|\$\(Platform[^\)]*\)\'\=\=\'([^\']+)\'"); class MsBuildConverterProvider : IPropertyStorageProvider diff --git a/QtVsTools.Core/OutputWindowPane.cs b/QtVsTools.Core/OutputWindowPane.cs new file mode 100644 index 0000000..1563acb --- /dev/null +++ b/QtVsTools.Core/OutputWindowPane.cs @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Threading.Tasks; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Threading; + +using Task = System.Threading.Tasks.Task; + +namespace QtVsTools.Core +{ + using VisualStudio; + + public class OutputWindowPane + { + public enum VSOutputWindowPane + { + General, + Build, + Debug, + } + + public static Task<OutputWindowPane> GetVSOutputWindowPaneAsync(VSOutputWindowPane pane) + { + switch (pane) { + case VSOutputWindowPane.General: + return GetAsync(VSConstants.OutputWindowPaneGuid.GeneralPane_guid); + case VSOutputWindowPane.Build: + return GetAsync(VSConstants.OutputWindowPaneGuid.BuildOutputPane_guid); + case VSOutputWindowPane.Debug: + return GetAsync(VSConstants.OutputWindowPaneGuid.DebugPane_guid); + default: + throw new InvalidOperationException("Unsupported Visual Studio output pane"); + }; + } + + public static async Task<OutputWindowPane> GetAsync(Guid guid) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + try { + IVsOutputWindow w = null; + if (guid == VSConstants.OutputWindowPaneGuid.GeneralPane_guid) { + w = await VsServiceProvider.GetServiceAsync<SVsGeneralOutputWindowPane, + IVsOutputWindow>(); + } else { + w = await VsServiceProvider.GetServiceAsync<SVsOutputWindow, IVsOutputWindow>(); + } + ErrorHandler.ThrowOnFailure(w.GetPane(guid, out IVsOutputWindowPane pane)); + + return new OutputWindowPane(guid, pane); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine(ex); + return null; + } + } + + public static async Task<OutputWindowPane> CreateAsync(string name, Guid guid) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException($"{ nameof(name) } cannot be null"); + + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + try { + var w = await VsServiceProvider.GetServiceAsync<SVsOutputWindow, IVsOutputWindow>(); + + const int visible = 1, clear = 1; + ErrorHandler.ThrowOnFailure(w.CreatePane(guid, name, visible, clear)); + ErrorHandler.ThrowOnFailure(w.GetPane(guid, out IVsOutputWindowPane pane)); + + return new OutputWindowPane(guid, pane); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine(ex); + return null; + } + } + + public static async Task<OutputWindowPane> GetActiveAsync() + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + try { + var w2 = await VsServiceProvider + .GetServiceAsync<SVsOutputWindow, IVsOutputWindow>() as IVsOutputWindow2; + ErrorHandler.ThrowOnFailure(w2.GetActivePaneGUID(out Guid guid)); + + IVsOutputWindow w = w2 as IVsOutputWindow; + ErrorHandler.ThrowOnFailure(w.GetPane(guid, out IVsOutputWindowPane pane)); + + return new OutputWindowPane(guid, pane); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine(ex); + return null; + } + } + + private Guid Guid { get; } + private IVsOutputWindowPane Pane { get; set; } = null; + + private OutputWindowPane(Guid guid, IVsOutputWindowPane pane) + { + Guid = guid; + Pane = pane; + } + + public async Task ActivateAsync() + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + if (Pane == null) + throw new InvalidOperationException($"{ nameof(Pane) } cannot be null"); + Pane.Activate(); + } + + public async Task HideAsync() + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + if (Pane == null) + throw new InvalidOperationException($"{ nameof(Pane) } cannot be null"); + Pane.Hide(); + } + + public async Task ClearAsync() + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + if (Pane == null) + throw new InvalidOperationException($"{ nameof(Pane) } cannot be null"); + Pane.Clear(); + } + + public void Print() + { + ThreadHelper.JoinableTaskFactory.Run(async () => { await PrintAsync(""); }); + } + + public void Print(string value) + { + ThreadHelper.JoinableTaskFactory.Run(async () => { await PrintAsync(value); }); + } + + public Task PrintAsync() + { + return PrintAsync(""); + } + + public async Task PrintAsync(string value) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + if (Pane is IVsOutputWindowPaneNoPump noPumpPane) + noPumpPane.OutputStringNoPump(value + Environment.NewLine); + else + ErrorHandler.ThrowOnFailure(Pane.OutputStringThreadSafe(value + Environment.NewLine)); + } + } +} diff --git a/QtVsTools.Core/ProFileContent.cs b/QtVsTools.Core/ProFileContent.cs index 8bd3d2b..a505a16 100644 --- a/QtVsTools.Core/ProFileContent.cs +++ b/QtVsTools.Core/ProFileContent.cs @@ -35,46 +35,20 @@ { public ProFileContent(VCProject proj) { - export = true; - vcproj = proj; - options = new List<ProFileOption>(); + Export = true; + Project = proj; + Options = new List<ProFileOption>(); } public override string ToString() { - return vcproj.Name; + return Project.Name; } - public VCProject Project - { - get - { - return vcproj; - } - } + public VCProject Project { get; } - public bool Export - { - get - { - return export; - } - set - { - export = value; - } - } + public bool Export { get; set; } - public List<ProFileOption> Options - { - get - { - return options; - } - } - - private VCProject vcproj; - private bool export; - private List<ProFileOption> options; + public List<ProFileOption> Options { get; } } } diff --git a/QtVsTools.Core/ProFileOption.cs b/QtVsTools.Core/ProFileOption.cs index 54468ef..8a5ad3d 100644 --- a/QtVsTools.Core/ProFileOption.cs +++ b/QtVsTools.Core/ProFileOption.cs @@ -34,95 +34,33 @@ { public ProFileOption(string optname) { - name = optname; - astype = AssignType.AT_PlusEquals; - comment = null; - shortComment = "Default"; - incComment = false; - newOpt = " \\\r\n "; - list = new List<string>(); + Name = optname; + AssignSymbol = AssignType.AT_PlusEquals; + Comment = null; + ShortComment = "Default"; + IncludeComment = false; + NewOption = " \\\r\n "; + List = new List<string>(); } public override string ToString() { - return shortComment; + return ShortComment; } - public string Comment - { - get - { - return comment; - } - set - { - comment = value; - } - } + public string Comment { get; set; } - public string ShortComment - { - get - { - return shortComment; - } - set - { - shortComment = value; - } - } + public string ShortComment { get; set; } - public AssignType AssignSymbol - { - get - { - return astype; - } - set - { - astype = value; - } - } + public AssignType AssignSymbol { get; set; } - public string NewOption - { - get - { - return newOpt; - } - set - { - newOpt = value; - } - } + public string NewOption { get; set; } - public string Name - { - get - { - return name; - } - } + public string Name { get; } - public List<string> List - { - get - { - return list; - } - } + public List<string> List { get; } - public bool IncludeComment - { - get - { - return incComment; - } - set - { - incComment = value; - } - } + public bool IncludeComment { get; set; } public enum AssignType { @@ -131,13 +69,5 @@ AT_MinusEquals = 3, AT_Function = 4 } - - private AssignType astype; - private string shortComment; - private bool incComment; - private string comment; - private string newOpt; - private string name; - private List<string> list; } } diff --git a/QtVsTools.Core/ProSolution.cs b/QtVsTools.Core/ProSolution.cs index 497f213..2eb9990 100644 --- a/QtVsTools.Core/ProSolution.cs +++ b/QtVsTools.Core/ProSolution.cs @@ -35,27 +35,12 @@ { public ProSolution(Solution sln) { - prosln = sln; - proFiles = new List<ProFileContent>(); + ProjectSolution = sln; + ProFiles = new List<ProFileContent>(); } - public List<ProFileContent> ProFiles - { - get - { - return proFiles; - } - } + public List<ProFileContent> ProFiles { get; } - public Solution ProjectSolution - { - get - { - return prosln; - } - } - - private List<ProFileContent> proFiles; - private Solution prosln; + public Solution ProjectSolution { get; } } } diff --git a/QtVsTools.Core/ProjectExporter.cs b/QtVsTools.Core/ProjectExporter.cs index 681bd33..357c713 100644 --- a/QtVsTools.Core/ProjectExporter.cs +++ b/QtVsTools.Core/ProjectExporter.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,15 +26,16 @@ ** ****************************************************************************/ -using EnvDTE; -using EnvDTE80; -using Microsoft.VisualStudio.VCProjectEngine; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; +using EnvDTE; +using EnvDTE80; namespace QtVsTools.Core { @@ -43,7 +44,7 @@ /// </summary> public class ProjectExporter { - private DTE dteObject; + private readonly DTE dteObject; public ProjectExporter(DTE dte) { @@ -91,13 +92,15 @@ private ProSolution CreateProFileSolution(Solution sln) { + ThreadHelper.ThrowIfNotOnUIThread(); + ProFileContent content; var prosln = new ProSolution(sln); foreach (var proj in HelperFunctions.ProjectsInSolution(sln.DTE)) { try { // only add qt projects - if (HelperFunctions.IsQtProject(proj)) { + if (HelperFunctions.IsVsToolsProject(proj)) { content = CreateProFileContent(proj); prosln.ProFiles.Add(content); } else if (proj.Kind == ProjectKinds.vsProjectKindSolutionFolder) { @@ -113,9 +116,11 @@ private void addProjectsInFolder(Project solutionFolder, ProSolution sln) { + ThreadHelper.ThrowIfNotOnUIThread(); + foreach (ProjectItem pi in solutionFolder.ProjectItems) { var containedProject = pi.Object as Project; - if (HelperFunctions.IsQtProject(containedProject)) { + if (HelperFunctions.IsVsToolsProject(containedProject)) { var content = CreateProFileContent(containedProject); sln.ProFiles.Add(content); } else if (containedProject.Kind == ProjectKinds.vsProjectKindSolutionFolder) { @@ -126,6 +131,8 @@ private static ProFileContent CreateProFileContent(Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + ProFileOption option; var qtPro = QtProject.Create(project); var content = new ProFileContent(qtPro.VCProject); @@ -192,8 +199,7 @@ if (config.ConfigurationType == ConfigurationTypes.typeStaticLibrary) option.List.Add("staticlib"); if (linker != null) { - var linkerRule = linker as IVCRulePropertyStorage; - var generateDebugInformation = (linkerRule != null) ? + var generateDebugInformation = (linker is IVCRulePropertyStorage linkerRule) ? linkerRule.GetUnevaluatedPropertyValue("GenerateDebugInformation") : null; if (generateDebugInformation != "false") option.List.Add("debug"); @@ -213,10 +219,12 @@ } } - if (qtPro.IsDesignerPluginProject()) { - option.List.Add("designer"); + var legacyDesigner = Legacy.QtProject.IsDesignerPluginProject(qtPro); + var plugin = legacyDesigner | Core.QtProject.IsQtPlugin(qtPro); + if (plugin) option.List.Add("plugin"); - } + if (legacyDesigner) + option.List.Add("designer"); // add defines option = new ProFileOption("DEFINES"); @@ -323,12 +331,18 @@ option.List.Add(project.Name + ".rc"); } - if (qtPro.IsDesignerPluginProject()) { + if (plugin) { option = new ProFileOption("target.path"); - option.ShortComment = "Install the plugin in the designer plugins directory."; + if (legacyDesigner) + option.ShortComment = "Installs the plugin in the designer plugins directory."; + else + option.ShortComment = "Installs the plugin in the plugins directory."; option.IncludeComment = true; option.AssignSymbol = ProFileOption.AssignType.AT_Equals; - option.List.Add("$$[QT_INSTALL_PLUGINS]/designer"); + if (legacyDesigner) + option.List.Add("$$[QT_INSTALL_PLUGINS]/designer"); + else + option.List.Add("$$[QT_INSTALL_PLUGINS]"); content.Options.Add(option); option = new ProFileOption("INSTALLS"); @@ -343,6 +357,8 @@ private static ProFileContent CreatePriFileContent(Project project, string priFileDirectory) { + ThreadHelper.ThrowIfNotOnUIThread(); + ProFileOption option; var qtPro = QtProject.Create(project); var content = new ProFileContent(qtPro.VCProject); @@ -417,6 +433,8 @@ private static void AddIncludePaths(Project project, ProFileOption option, string includePaths) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_ClProperties) return; @@ -437,10 +455,7 @@ if (!d.StartsWith("$(qtdir)\\include", StringComparison.OrdinalIgnoreCase) && !d.StartsWith(qtDir + "\\include", StringComparison.OrdinalIgnoreCase) && !d.EndsWith("win32-msvc2005", StringComparison.OrdinalIgnoreCase)) { - - var vcConfig = project.ConfigurationManager.ActiveConfiguration.Object - as VCConfiguration; - if (vcConfig != null) + if (project.ConfigurationManager.ActiveConfiguration.Object is VCConfiguration vcConfig) HelperFunctions.ExpandString(ref d, vcConfig); if (HelperFunctions.IsAbsoluteFilePath(d)) d = HelperFunctions.GetRelativePath(project.FullName, d); @@ -461,8 +476,9 @@ qtDir = Environment.GetEnvironmentVariable("QTDIR"); if (qtDir == null) qtDir = ""; - qtDir = HelperFunctions.NormalizeRelativeFilePath(qtDir); + + ThreadHelper.ThrowIfNotOnUIThread(); if (paths != null) { foreach (var s in paths.Split(';', ',')) { @@ -491,7 +507,14 @@ private static void AddModules(QtProject qtPrj, ProFileOption optionQT, ProFileOption optionCONFIG) { - foreach (var module in QtModules.Instance.GetAvailableModules()) { + ThreadHelper.ThrowIfNotOnUIThread(); + + var vm = QtVersionManager.The(); + var versionInfo = vm.GetVersionInfo(qtPrj.Project); + if (versionInfo == null) + versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); + + foreach (var module in QtModules.Instance.GetAvailableModules(versionInfo.qtMajor)) { if (!qtPrj.HasModule(module.Id)) continue; @@ -504,6 +527,8 @@ private void WriteProSolution(ProSolution prosln, bool openFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + var sln = prosln.ProjectSolution; if (string.IsNullOrEmpty(sln.FileName)) return; @@ -573,6 +598,8 @@ private void WriteProFile(ProFileContent content, string proFile, string priFileToInclude, bool openFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + StreamWriter sw; if (File.Exists(proFile)) { if (MessageBox.Show(SR.GetString("ExportProject_ExistsOverwriteQuestion", proFile), @@ -605,8 +632,7 @@ WriteProFileOptions(sw, content.Options); } - // open the file in vs - if (openFile) + if (openFile) // open the file in vs dteObject.OpenFile(Constants.vsViewKindTextView, proFile).Activate(); } @@ -705,6 +731,8 @@ public static void SyncIncludeFiles(VCProject vcproj, List<string> priFiles, List<string> projFiles, DTE dte, bool flat, FakeFilter fakeFilter) { + ThreadHelper.ThrowIfNotOnUIThread(); + var cmpPriFiles = new List<string>(priFiles.Count); foreach (var s in priFiles) cmpPriFiles.Add(HelperFunctions.NormalizeFilePath(s).ToLower()); @@ -779,7 +807,7 @@ public void ExportToProFile() { - var expDlg = new ExportProjectDialog(); + ThreadHelper.ThrowIfNotOnUIThread(); var sln = dteObject.Solution; var prosln = CreateProFileSolution(sln); @@ -789,6 +817,7 @@ return; } + var expDlg = new ExportProjectDialog(); expDlg.ProFileSolution = prosln; expDlg.StartPosition = FormStartPosition.CenterParent; var ww = new MainWinWrapper(dteObject); @@ -814,9 +843,10 @@ public string ExportToPriFile(Project proj) { - VCProject vcproj; + ThreadHelper.ThrowIfNotOnUIThread(); - if (HelperFunctions.IsQtProject(proj)) { + VCProject vcproj; + if (HelperFunctions.IsVsToolsProject(proj)) { try { vcproj = (VCProject)proj.Object; } catch (Exception e) { @@ -844,8 +874,9 @@ public void ExportToPriFile(Project proj, string fileName) { - var priFile = new FileInfo(fileName); + ThreadHelper.ThrowIfNotOnUIThread(); + var priFile = new FileInfo(fileName); var content = CreatePriFileContent(proj, priFile.DirectoryName); WritePriFile(content, priFile.FullName); } diff --git a/QtVsTools.Core/ProjectImporter.cs b/QtVsTools.Core/ProjectImporter.cs index bd5da86..8d14767 100644 --- a/QtVsTools.Core/ProjectImporter.cs +++ b/QtVsTools.Core/ProjectImporter.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,18 +26,19 @@ ** ****************************************************************************/ -using EnvDTE; -using Microsoft.VisualStudio.VCProjectEngine; using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; +using EnvDTE; +using Microsoft.VisualStudio.VCProjectEngine; namespace QtVsTools.Core { public class ProjectImporter { - private DTE dteObject; + private readonly DTE dteObject; const string projectFileExtension = ".vcxproj"; public ProjectImporter(DTE dte) @@ -47,6 +48,8 @@ public void ImportProFile(string qtVersion) { + ThreadHelper.ThrowIfNotOnUIThread(); + FileDialog toOpen = new OpenFileDialog(); toOpen.FilterIndex = 1; toOpen.CheckFileExists = true; @@ -78,6 +81,8 @@ private void ImportSolution(FileInfo mainInfo, string qtVersion) { + ThreadHelper.ThrowIfNotOnUIThread(); + var versionInfo = QtVersionManager.The().GetVersionInfo(qtVersion); var VCInfo = RunQmake(mainInfo, ".sln", true, versionInfo); if (null == VCInfo) @@ -88,7 +93,7 @@ if (CheckQtVersion(versionInfo)) { dteObject.Solution.Open(VCInfo.FullName); if (qtVersion != null) { - QtVersionManager.The().SaveSolutionQtVersion(dteObject.Solution, qtVersion); + Legacy.QtVersionManager.SaveSolutionQtVersion(dteObject.Solution, qtVersion); foreach (var prj in HelperFunctions.ProjectsInSolution(dteObject)) { QtVersionManager.The().SaveProjectQtVersion(prj, qtVersion); var qtPro = QtProject.Create(prj); @@ -100,12 +105,14 @@ Messages.Print("--- (Import): Finished opening " + VCInfo.Name); } catch (Exception e) { - Messages.DisplayCriticalErrorMessage(e); + Messages.DisplayErrorMessage(e); } } public void ImportProject(FileInfo mainInfo, string qtVersion) { + ThreadHelper.ThrowIfNotOnUIThread(); + var versionInfo = QtVersionManager.The().GetVersionInfo(qtVersion); var VCInfo = RunQmake(mainInfo, projectFileExtension, false, versionInfo); if (null == VCInfo) @@ -116,9 +123,11 @@ try { if (CheckQtVersion(versionInfo)) { // no need to add the project again if it's already there... - if (!HelperFunctions.IsProjectInSolution(dteObject, VCInfo.FullName)) { + var fullName = VCInfo.FullName; + var pro = HelperFunctions.ProjectFromSolution(dteObject, fullName); + if (pro == null) { try { - dteObject.Solution.AddFromFile(VCInfo.FullName, false); + pro = dteObject.Solution.AddFromFile(fullName, false); } catch (Exception /*exception*/) { Messages.Print("--- (Import): Generated project could not be loaded."); Messages.Print("--- (Import): Please look in the output above for errors and warnings."); @@ -129,13 +138,6 @@ Messages.Print("Project already in Solution"); } - Project pro = null; - foreach (var p in HelperFunctions.ProjectsInSolution(dteObject)) { - if (p.FullName.ToLower() == VCInfo.FullName.ToLower()) { - pro = p; - break; - } - } if (pro != null) { var qtPro = QtProject.Create(pro); qtPro.SetQtEnvironment(); @@ -151,21 +153,16 @@ Messages.Print("Can't select the platform " + platformName + "."); } - // try to figure out if the project is a plugin project - try { - var activeConfig = pro.ConfigurationManager.ActiveConfiguration.ConfigurationName; - var config = (VCConfiguration)((IVCCollection)qtPro.VCProject.Configurations).Item(activeConfig); - if (config.ConfigurationType == ConfigurationTypes.typeDynamicLibrary) { - var compiler = CompilerToolWrapper.Create(config); - var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); - if (compiler.GetPreprocessorDefinitions().IndexOf("QT_PLUGIN", StringComparison.Ordinal) > -1 - && compiler.GetPreprocessorDefinitions().IndexOf("QDESIGNER_EXPORT_WIDGETS", StringComparison.Ordinal) > -1 - && compiler.GetAdditionalIncludeDirectories().IndexOf("QtDesigner", StringComparison.Ordinal) > -1 - && linker.AdditionalDependencies.IndexOf("QtDesigner", StringComparison.Ordinal) > -1) { - qtPro.MarkAsDesignerPluginProject(); - } - } - } catch (Exception) { } + // figure out if the imported project is a plugin project + var tmp = qtPro.Project.ConfigurationManager.ActiveConfiguration + .ConfigurationName; + var vcConfig = (qtPro.VCProject.Configurations as IVCCollection).Item(tmp) + as VCConfiguration; + var def = CompilerToolWrapper.Create(vcConfig)?.GetPreprocessorDefinitions(); + if (!string.IsNullOrEmpty(def) + && def.IndexOf("QT_PLUGIN", StringComparison.Ordinal) > -1) { + QtProject.MarkAsQtPlugin(qtPro); + } qtPro.SetQtEnvironment(); ApplyPostImportSteps(qtPro); @@ -222,18 +219,19 @@ if (ok) ok = xmlProject.UpdateProjectFormatVersion(); - if (!ok) { - Messages.Print( - SR.GetString("ImportProject_CannotConvertProject", projectFile.Name)); + if (ok) { + xmlProject.Save(); + // Initialize Qt variables + xmlProject.BuildTarget("QtVarsDesignTime"); + } else { + Messages.Print($"Could not convert project file {projectFile.Name} to Qt/MSBuild."); } - xmlProject.Save(); - - // Initialize Qt variables - xmlProject.BuildTarget("QtVarsDesignTime"); } private static void ApplyPostImportSteps(QtProject qtProject) { + ThreadHelper.ThrowIfNotOnUIThread(); + qtProject.RemoveResFilesFromGeneratedFilesFilter(); qtProject.TranslateFilterNames(); @@ -249,32 +247,38 @@ private FileInfo RunQmake(FileInfo mainInfo, string ext, bool recursive, VersionInformation vi) { + ThreadHelper.ThrowIfNotOnUIThread(); + var name = mainInfo.Name.Remove(mainInfo.Name.IndexOf('.')); - var VCInfo = new FileInfo(mainInfo.DirectoryName + "\\" + name + ext); - - if (!VCInfo.Exists || DialogResult.Yes == MessageBox.Show(SR.GetString("ExportProject_ProjectExistsRegenerateOrReuse", VCInfo.Name), - SR.GetString("ProjectExists"), MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { - Messages.Print("--- (Import): Generating new project of " + mainInfo.Name + " file"); - - var waitDialog = WaitDialog.Start( - "Open Qt Project File", - "Generating Visual Studio project...", delay: 2); - - var qmake = new QMakeImport(vi, mainInfo.FullName, recursive, dteObject); - int exitCode = qmake.Run(setVCVars: true); - waitDialog.Stop(); - - if (exitCode == 0) - return VCInfo; + var vcxproj = new FileInfo(mainInfo.DirectoryName + "\\" + name + ext); + if (vcxproj.Exists) { + var result = MessageBox.Show($@"{vcxproj.Name} already exists. Select 'OK' to " + + "regenerate the file or 'Cancel' to quit importing the project.", + "Project file already exists.", + MessageBoxButtons.OKCancel, MessageBoxIcon.Question); + if (result == DialogResult.Cancel) + return null; } + Messages.Print("--- (Import): Generating new project of " + mainInfo.Name + " file"); + + var waitDialog = WaitDialog.Start("Open Qt Project File", + "Generating Visual Studio project...", delay: 2); + + var qmake = new QMakeImport(vi, mainInfo.FullName, recursive, dteObject); + int exitCode = qmake.Run(setVCVars: true); + + waitDialog.Stop(); + + if (exitCode == 0) + return vcxproj; return null; } private static bool CheckQtVersion(VersionInformation vi) { - if (!vi.qt5Version) { + if (vi.qtMajor < 5) { Messages.DisplayWarningMessage(SR.GetString("ExportProject_EditProjectFileManually")); return false; } diff --git a/QtVsTools.Core/QMake.cs b/QtVsTools.Core/QMake.cs index 4c0a985..3ee46d5 100644 --- a/QtVsTools.Core/QMake.cs +++ b/QtVsTools.Core/QMake.cs @@ -32,23 +32,24 @@ using System.IO; using System.Linq; using System.Text; -using QtVsTools.VisualStudio; namespace QtVsTools.Core { + using VisualStudio; + public abstract class QMake { public Dictionary<string, string> Vars { get; protected set; } public string OutputFile { get; protected set; } - public uint DebugLevel { get; protected set; } + private uint DebugLevel { get; set; } public string TemplatePrefix { get; protected set; } public bool Recursive { get; protected set; } public string ProFile { get; protected set; } public string Query { get; protected set; } public bool DisableWarnings { get; set; } - protected VersionInformation QtVersion { get; private set; } - protected EnvDTE.DTE Dte { get; private set; } + protected VersionInformation QtVersion { get; } + private EnvDTE.DTE Dte { get; } public QMake(VersionInformation qtVersion, EnvDTE.DTE dte = null) { @@ -196,14 +197,27 @@ exitCode = qmakeProc.ExitCode; InfoExit(qmakeProc); } - } catch (Exception e) { - ErrMsg(string.Format("Exception \"{0}\":\r\n{1}", - e.Message, - e.StackTrace)); + } catch (Exception exception) { + exception.Log(); } } return exitCode; } + + public static bool Exists(string path) + { + var possibleQMakePaths = new[] { + // Path points to qmake.exe + path, + // Path points to folder containing qmake.exe + Path.Combine(path, "qmake.exe"), + // Path points to folder containing bin\qmake.exe + Path.Combine(path, "bin", "qmake.exe"), + }; + return possibleQMakePaths.Where(p => File.Exists(p) + && Path.GetFileName(p).Equals("qmake.exe", StringComparison.OrdinalIgnoreCase)) + .Any(); + } } public class QMakeImport : QMake diff --git a/QtVsTools.Core/QMakeConf.cs b/QtVsTools.Core/QMakeConf.cs index c66a6c6..c719314 100644 --- a/QtVsTools.Core/QMakeConf.cs +++ b/QtVsTools.Core/QMakeConf.cs @@ -29,13 +29,14 @@ using System; using System.Collections; using System.IO; +using Microsoft.VisualStudio.Shell; namespace QtVsTools.Core { public class QMakeConf { - public Hashtable Entries { get; private set; } - public string QMakeSpecDirectory { get; private set; } + public Hashtable Entries { get; } + public string QMakeSpecDirectory { get; } public QMakeConf(VersionInformation versionInfo, QMakeQuery qmakeQuery = null) { @@ -64,6 +65,17 @@ qmakeConf = Path.Combine(qtPrefix, qtArchData, "mkspecs", qmakeXSpec, "qmake.conf"); + if (!File.Exists(qmakeConf)) { + // Check if this is a shadow build of Qt. + qtPrefix = qmakeQuery["QT_INSTALL_PREFIX/src"]; + if (string.IsNullOrEmpty(qtPrefix)) + throw new QtVSException("qmake error: no value for QT_INSTALL_PREFIX/src"); + qtArchData = qmakeQuery["QT_INSTALL_ARCHDATA/src"]; + if (string.IsNullOrEmpty(qtArchData)) + throw new QtVSException("qmake error: no value for QT_INSTALL_ARCHDATA/src"); + + qmakeConf = Path.Combine(qtPrefix, qtArchData, "mkspecs", qmakeXSpec, "qmake.conf"); + } if (!File.Exists(qmakeConf)) throw new QtVSException("qmake.conf expected at " + qmakeConf + " not found"); } diff --git a/QtVsTools.Core/QMakeQuery.cs b/QtVsTools.Core/QMakeQuery.cs index 2dc1be5..1534deb 100644 --- a/QtVsTools.Core/QMakeQuery.cs +++ b/QtVsTools.Core/QMakeQuery.cs @@ -26,18 +26,15 @@ ** ****************************************************************************/ -using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; using System.Text; -using System.Threading; -using QtVsTools.SyntaxAnalysis; +using Microsoft.VisualStudio.Shell; namespace QtVsTools.Core { - using static RegExpr; + using static SyntaxAnalysis.RegExpr; public class QMakeQuery : QMake { @@ -58,7 +55,6 @@ public Dictionary<string, string> QueryAllValues() { - string result = string.Empty; stdOutput = new StringBuilder(); Query = " "; @@ -78,16 +74,20 @@ { get { - string value = string.Empty; - if (Properties.TryGetValue(name, out value)) + if (Properties.TryGetValue(name, out string value)) return value; - else - return null; + return null; } } Dictionary<string, string> _Properties; - Dictionary<string, string> Properties => _Properties ?? (_Properties = QueryAllValues()); + Dictionary<string, string> Properties + { + get + { + return _Properties ?? (_Properties = QueryAllValues()); + } + } Parser _PropertyParser; Parser PropertyParser diff --git a/QtVsTools.Core/QrcPrefix.cs b/QtVsTools.Core/QrcPrefix.cs index 79686a5..bb11eec 100644 --- a/QtVsTools.Core/QrcPrefix.cs +++ b/QtVsTools.Core/QrcPrefix.cs @@ -34,7 +34,7 @@ { public string Prefix { get; set; } public string Language { get; set; } - public List<QrcItem> Items { get; private set; } + public List<QrcItem> Items { get; } public QrcPrefix() { diff --git a/QtVsTools.Core/QtConfig.cs b/QtVsTools.Core/QtConfig.cs index d3a3682..5cb6974 100644 --- a/QtVsTools.Core/QtConfig.cs +++ b/QtVsTools.Core/QtConfig.cs @@ -44,17 +44,18 @@ /// </summary> class QtConfig { - public BuildType BuildType { get; private set; } + public BuildType BuildType { get; } - public string LibInfix { get; private set; } + public string LibInfix { get; } - public bool Is64Bit { get; private set; } + public bool Is64Bit { get; } - public string Namespace { get; private set; } + public string Namespace { get; } - public uint VersionMajor { get; private set; } - public uint VersionMinor { get; private set; } - public uint VersionPatch { get; private set; } + public uint VersionMajor { get; } + public uint VersionMinor { get; } + public uint VersionPatch { get; } + public string VersionString { get; } public QtConfig(string qtdir) { @@ -110,6 +111,8 @@ Is64Bit = (data == "x86_64"); } else if (name == "QT_NAMESPACE") { Namespace = data; + } else if (name == "QT_VERSION") { + VersionString = data; } else if (name == "QT_MAJOR_VERSION") { if (uint.TryParse(data, out uint versionMajor)) VersionMajor = versionMajor; diff --git a/QtVsTools.Core/QtModule.cs b/QtVsTools.Core/QtModule.cs index 812b6d5..d4ad594 100644 --- a/QtVsTools.Core/QtModule.cs +++ b/QtVsTools.Core/QtModule.cs @@ -28,7 +28,6 @@ using System; using System.Collections.Generic; -using System.IO; namespace QtVsTools.Core { @@ -38,12 +37,12 @@ public bool Selectable; public List<string> Defines = new List<string>(); public string LibraryPrefix = string.Empty; - public bool HasDLL = true; public List<string> AdditionalLibraries = new List<string>(); public List<string> AdditionalLibrariesDebug = new List<string>(); public List<string> IncludePath = new List<string>(); public string proVarQT; public string proVarCONFIG; + private string majorVersion; public string LibRelease { @@ -51,7 +50,7 @@ { return LibraryPrefix.StartsWith("Qt", StringComparison.Ordinal) - ? "Qt5" + LibraryPrefix.Substring(2) + ".lib" + ? "Qt" + majorVersion + LibraryPrefix.Substring(2) + ".lib" : LibraryPrefix + ".lib"; } } @@ -62,14 +61,15 @@ { return LibraryPrefix.StartsWith("Qt", StringComparison.Ordinal) - ? "Qt5" + LibraryPrefix.Substring(2) + "d.lib" + ? "Qt" + majorVersion + LibraryPrefix.Substring(2) + "d.lib" : LibraryPrefix + "d.lib"; } } - public QtModule(int id) + public QtModule(int id, string major) { Id = id; + majorVersion = major; } public int Id { get; } = -1; @@ -90,7 +90,7 @@ var libs = new List<string>(); var libName = LibraryPrefix; if (libName.StartsWith("Qt", StringComparison.Ordinal)) - libName = "Qt5" + libName.Substring(2); + libName = "Qt" + majorVersion + libName.Substring(2); libName += libInfix; if (isDebugCfg) libName += "d"; diff --git a/QtVsTools.Core/QtModules.cs b/QtVsTools.Core/QtModules.cs index 0b1bdde..8634ece 100644 --- a/QtVsTools.Core/QtModules.cs +++ b/QtVsTools.Core/QtModules.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -38,37 +38,58 @@ { public class QtModules { - private static QtModules instance = new QtModules(); - private readonly Dictionary<int, QtModule> modules = new Dictionary<int, QtModule>(); + public static QtModules Instance { get; } = new QtModules(); - public static QtModules Instance - { - get { return instance; } - } + private List<QtModule> qt5list = null, qt6list = null; + private readonly Dictionary<int, QtModule> qt5modules = new Dictionary<int, QtModule>(); + private readonly Dictionary<int, QtModule> qt6modules = new Dictionary<int, QtModule>(); - public QtModule Module(int id) + public QtModule Module(int id, uint major) { - QtModule module; - modules.TryGetValue(id, out module); + QtModule module = null; + if (major < 6) + qt5modules.TryGetValue(id, out module); + if (major == 6) + qt6modules.TryGetValue(id, out module); + if (major > 6) + throw new QtVSException("Unsupported Qt version."); return module; } - public List<QtModule> GetAvailableModules() + public List<QtModule> GetAvailableModules(uint major) { - var lst = new List<QtModule>(modules.Count); - foreach (var entry in modules) - lst.Add(entry.Value); - return lst; + if (major < 6) { + if (qt5list == null) { + qt5list = new List<QtModule>(qt5modules.Count); + foreach (var entry in qt5modules) + qt5list.Add(entry.Value); + } + return qt5list; + } + if (major == 6) { + if (qt6list == null) { + qt6list = new List<QtModule>(qt6modules.Count); + foreach (var entry in qt6modules) + qt6list.Add(entry.Value); + } + return qt6list; + } + if (major > 6) + throw new QtVSException("Unsupported Qt version."); + return null; } private QtModules() { - var uri = new Uri( - System.Reflection.Assembly.GetExecutingAssembly().EscapedCodeBase); - var pkgInstallPath = Path.GetDirectoryName( - Uri.UnescapeDataString(uri.AbsolutePath)) + @"\"; + var uri = new Uri(System.Reflection.Assembly.GetExecutingAssembly().EscapedCodeBase); + var pkgInstallPath = Path.GetDirectoryName(Uri.UnescapeDataString(uri.AbsolutePath)); - var modulesFile = Path.Combine(pkgInstallPath, "qtmodules.xml"); + FillModules(Path.Combine(pkgInstallPath, "qtmodules.xml"), "5", ref qt5modules); + FillModules(Path.Combine(pkgInstallPath, "qt6modules.xml"), "6", ref qt6modules); + } + + private void FillModules(string modulesFile, string major, ref Dictionary<int, QtModule> dict) + { if (!File.Exists(modulesFile)) return; @@ -85,11 +106,10 @@ foreach (var xModule in xml.Elements("QtVsTools").Elements("Module")) { int id = (int)xModule.Attribute("Id"); - QtModule module = new QtModule(id); + QtModule module = new QtModule(id, major); module.Name = (string)xModule.Element("Name"); module.Selectable = ((string)xModule.Element("Selectable") == "true"); module.LibraryPrefix = (string)xModule.Element("LibraryPrefix"); - module.HasDLL = ((string)xModule.Element("HasDLL") == "true"); module.proVarQT = (string)xModule.Element("proVarQT"); module.proVarCONFIG = (string)xModule.Element("proVarCONFIG"); module.IncludePath = xModule.Elements("IncludePath") @@ -106,7 +126,7 @@ Messages.Print("\r\nCritical error: incorrect format of qtmodules.xml"); throw new QtVSException("qtmodules.xml"); } - modules.Add(id, module); + dict.Add(id, module); } } } diff --git a/QtVsTools.Core/QtMsBuild.cs b/QtVsTools.Core/QtMsBuild.cs index 45ce0b9..02a1d99 100644 --- a/QtVsTools.Core/QtMsBuild.cs +++ b/QtVsTools.Core/QtMsBuild.cs @@ -26,17 +26,17 @@ ** ****************************************************************************/ +using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; -using System; -using System.IO; - -using CommandLineParser = QtVsTools.Core.CommandLine.Parser; -using CommandLineOption = QtVsTools.Core.CommandLine.Option; namespace QtVsTools.Core.QtMsBuild { + using CommandLineParser = CommandLine.Parser; + using CommandLineOption = CommandLine.Option; + public interface IVSMacroExpander { string ExpandString(string stringToExpand); @@ -84,8 +84,7 @@ public class QtMsBuildContainer { - - IPropertyStorageProvider provider; + readonly IPropertyStorageProvider provider; public QtMsBuildContainer(IPropertyStorageProvider provider) { this.provider = provider; @@ -198,16 +197,15 @@ return provider.GetProjectConfiguration(GetProject(), configName); } - Dictionary<string, ItemPropertyChange> itemPropertyChanges + readonly Dictionary<string, ItemPropertyChange> itemPropertyChanges = new Dictionary<string, ItemPropertyChange>(); - Dictionary<string, List<ItemPropertyChange>> itemPropertyChangesGrouped + readonly Dictionary<string, List<ItemPropertyChange>> itemPropertyChangesGrouped = new Dictionary<string, List<ItemPropertyChange>>(); bool pendingChanges = false; void AddChange(ItemPropertyChange newChange) { - ItemPropertyChange oldChange; - if (itemPropertyChanges.TryGetValue(newChange.Key, out oldChange)) { + if (itemPropertyChanges.TryGetValue(newChange.Key, out ItemPropertyChange oldChange)) { if (oldChange.GroupKey == newChange.GroupKey) { oldChange.CopyFrom(newChange); return; @@ -509,7 +507,8 @@ #region QtRcc static QtRcc qtRccInstance; - public static QtRcc QtRccInstance + + private static QtRcc QtRccInstance { get { @@ -558,7 +557,8 @@ #region QtRepc static QtRepc qtRepcInstance; - public static QtRepc QtRepcInstance + + private static QtRepc QtRepcInstance { get { @@ -607,7 +607,8 @@ #region QtUic static QtUic qtUicInstance; - public static QtUic QtUicInstance + + private static QtUic QtUicInstance { get { @@ -658,10 +659,10 @@ public abstract class QtTool { - protected CommandLineParser parser; - protected CommandLineOption outputOption; - protected CommandLineOption helpOption; - protected CommandLineOption versionOption; + protected readonly CommandLineParser parser; + private readonly CommandLineOption outputOption; + private CommandLineOption helpOption; + private CommandLineOption versionOption; protected QtTool(bool defaultInputOutput = true) { @@ -779,7 +780,7 @@ AdditionalDependencies, } - Dictionary<Property, CommandLineOption> options + readonly Dictionary<Property, CommandLineOption> options = new Dictionary<Property, CommandLineOption>(); public QtMoc() : base() @@ -881,14 +882,13 @@ { properties = new Dictionary<Property, string>(); - string qtDir, inputPath, outputPath; if (!ParseCommandLine( commandLine, macros, ToolExecName, - out qtDir, - out inputPath, - out outputPath)) { + out string qtDir, + out string inputPath, + out string outputPath)) { return false; } @@ -1078,7 +1078,7 @@ AdditionalDependencies, } - Dictionary<Property, CommandLineOption> options + readonly Dictionary<Property, CommandLineOption> options = new Dictionary<Property, CommandLineOption>(); public QtRcc() : base() @@ -1130,14 +1130,13 @@ { properties = new Dictionary<Property, string>(); - string qtDir, inputPath, outputPath; if (!ParseCommandLine( commandLine, macros, ToolExecName, - out qtDir, - out inputPath, - out outputPath)) { + out string qtDir, + out string inputPath, + out string outputPath)) { return false; } @@ -1157,8 +1156,7 @@ properties[Property.Root] = parser.Value(options[Property.Root]); if (parser.IsSet(options[Property.Compression])) { - int level; - if (!int.TryParse(parser.Value(options[Property.Compression]), out level)) + if (!int.TryParse(parser.Value(options[Property.Compression]), out int level)) return false; if (level < 1 || 9 < level) return false; @@ -1272,7 +1270,7 @@ PrintDebug, } - Dictionary<Property, CommandLineOption> options + readonly Dictionary<Property, CommandLineOption> options = new Dictionary<Property, CommandLineOption>(); public QtRepc() : base(defaultInputOutput: false) @@ -1330,14 +1328,13 @@ { properties = new Dictionary<Property, string>(); - string qtDir, inputPath, outputPath; if (!ParseCommandLine( commandLine, macros, ToolExecName, - out qtDir, - out inputPath, - out outputPath)) { + out string qtDir, + out string inputPath, + out string outputPath)) { return false; } @@ -1385,8 +1382,8 @@ GenerateCommandLineOption(cmd, options[Property.InputFileType], inputType); var outputType = container.GetPropertyValue(propertyStorage, Property.OutputFileType); - if (!string.IsNullOrEmpty(inputType)) - GenerateCommandLineOption(cmd, options[Property.InputFileType], inputType); + if (!string.IsNullOrEmpty(outputType)) + GenerateCommandLineOption(cmd, options[Property.OutputFileType], outputType); string value = container.GetPropertyValue(propertyStorage, Property.IncludePath); if (!string.IsNullOrEmpty(value)) @@ -1436,7 +1433,7 @@ AdditionalDependencies, } - Dictionary<Property, CommandLineOption> options + readonly Dictionary<Property, CommandLineOption> options = new Dictionary<Property, CommandLineOption>(); public QtUic() : base() @@ -1473,14 +1470,13 @@ { properties = new Dictionary<Property, string>(); - string qtDir, inputPath, outputPath; if (!ParseCommandLine( commandLine, macros, ToolExecName, - out qtDir, - out inputPath, - out outputPath)) { + out string qtDir, + out string inputPath, + out string outputPath)) { return false; } diff --git a/QtVsTools.Core/QtProject.cs b/QtVsTools.Core/QtProject.cs index 613b4e5..a935f54 100644 --- a/QtVsTools.Core/QtProject.cs +++ b/QtVsTools.Core/QtProject.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,22 +26,22 @@ ** ****************************************************************************/ -using EnvDTE; -using Microsoft.VisualStudio.VCProjectEngine; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; using System.Windows.Forms; using System.Xml; -using QtVsTools.Core.QtMsBuild; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; +using EnvDTE; namespace QtVsTools.Core { + using QtMsBuild; + /// <summary> /// QtProject holds the Qt specific properties for a Visual Studio project. /// There exists at most one QtProject per EnvDTE.Project. @@ -54,13 +54,14 @@ private VCProject vcPro; private MocCmdChecker mocCmdChecker; private Array lastConfigurationRowNames; - private static Dictionary<Project, QtProject> instances = new Dictionary<Project, QtProject>(); - private QtMsBuildContainer qtMsBuild; + private static readonly Dictionary<Project, QtProject> instances = new Dictionary<Project, QtProject>(); + private readonly QtMsBuildContainer qtMsBuild; public static QtVsTools.VisualStudio.IProjectTracker ProjectTracker { get; set; } public static QtProject Create(VCProject vcProject) { + ThreadHelper.ThrowIfNotOnUIThread(); return Create((Project)vcProject.Object); } @@ -81,6 +82,8 @@ private QtProject(Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project == null) throw new QtVSException(SR.GetString("QtProject_CannotConstructWithoutValidProject")); envPro = project; @@ -105,35 +108,10 @@ return string.Empty; try { return config.GetEvaluatedPropertyValue(itemType + "RuleName"); - } catch (Exception e) { - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); return string.Empty; } - } - - public static string GetRuleName(VCProject project, string itemType) - { - if (project == null) - return string.Empty; - var configs = project.Configurations as IVCCollection; - if (configs.Count == 0) - return string.Empty; - try { - var firstConfig = configs.Item(1) as VCConfiguration; - if (firstConfig == null) - return string.Empty; - return GetRuleName(firstConfig, itemType); - } catch (Exception e) { - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); - return string.Empty; - } - } - - public string GetRuleName(string itemType) - { - return GetRuleName(vcPro, itemType); } public static bool IsQtMsBuildEnabled(VCProject project) @@ -157,6 +135,8 @@ public static bool IsQtMsBuildEnabled(Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project == null) return false; return IsQtMsBuildEnabled(project.Object as VCProject); @@ -165,6 +145,8 @@ private bool? isQtMsBuildEnabled = null; public bool IsQtMsBuildEnabled() { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!isQtMsBuildEnabled.HasValue) { if (vcPro != null) isQtMsBuildEnabled = IsQtMsBuildEnabled(vcPro); @@ -192,6 +174,8 @@ { get { + ThreadHelper.ThrowIfNotOnUIThread(); + var ret = false; if (lastConfigurationRowNames == null) { lastConfigurationRowNames = envPro.ConfigurationManager.ConfigurationRowNames as Array; @@ -213,6 +197,8 @@ /// <param name="uiFile">name of the ui file</param> public string GetUiGeneratedFileName(string uiFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + var fi = new FileInfo(uiFile); var file = fi.Name; if (HelperFunctions.IsUicFile(file)) { @@ -248,8 +234,11 @@ /// replaced by the value of configName. /// <param name="file">full file name of either the header or the source file</param> /// <returns></returns> - private string GetRelativeMocFilePath(string file, string configName, string platformName) + private string GetRelativeMocFilePath(string file, string configName = null, + string platformName = null) { + ThreadHelper.ThrowIfNotOnUIThread(); + var fileName = GetMocFileName(file); if (fileName == null) return null; @@ -260,65 +249,38 @@ return mocDir; } - /// <summary> - /// Returns the file name of the generated moc file relative to the - /// project directory. - /// </summary> - /// The returned file path may contain the macros $(ConfigurationName) and $(PlatformName). - /// <param name="file">full file name of either the header or the source file</param> - /// <returns></returns> - private string GetRelativeMocFilePath(string file) - { - return GetRelativeMocFilePath(file, null, null); - } - - /// <summary> - /// Marks the specified project as a Qt project. - /// </summary> - public void MarkAsQtProject() - { - vcPro.keyword = string.Format("{0}_v{1}", - Resources.qtProjectKeyword, Resources.qtProjectFormatVersion); - } - public static int GetFormatVersion(VCProject vcPro) { if (vcPro == null) return 0; - if (vcPro.keyword.StartsWith(Resources.qtProjectKeyword, - StringComparison.InvariantCultureIgnoreCase)) { + if (vcPro.keyword.StartsWith(Resources.qtProjectKeyword, StringComparison.Ordinal)) return Convert.ToInt32(vcPro.keyword.Substring(6)); - } else if (vcPro.keyword.StartsWith(Resources.qtProjectV2Keyword, - StringComparison.InvariantCultureIgnoreCase)) { + if (vcPro.keyword.StartsWith(Resources.qtProjectV2Keyword, StringComparison.Ordinal)) return 200; - } else { - return 0; - } + return 0; } public static int GetFormatVersion(Project pro) { - if (pro == null) - return 0; - return GetFormatVersion(pro.Object as VCProject); + ThreadHelper.ThrowIfNotOnUIThread(); + return GetFormatVersion(pro?.Object as VCProject); } - public int FormatVersion { get { return GetFormatVersion(Project); } } - - public string GetPropertyValue(string propName) + public int FormatVersion { - return GetPropertyValue(Project, propName); - } - - public string GetPropertyValue(string configName, string platformName, string propName) - { - return GetPropertyValue(Project, configName, platformName, propName); + get + { + ThreadHelper.ThrowIfNotOnUIThread(); + return GetFormatVersion(Project); + } } public static string GetPropertyValue( EnvDTE.Project dteProject, string propName) { + ThreadHelper.ThrowIfNotOnUIThread(); + var activeConfig = dteProject.ConfigurationManager?.ActiveConfiguration; if (activeConfig == null) return null; @@ -331,6 +293,8 @@ EnvDTE.Configuration dteConfig, string propName) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (dteProject == null || dteConfig == null) return null; return GetPropertyValue( @@ -338,16 +302,6 @@ dteConfig.ConfigurationName, dteConfig.PlatformName, propName); - } - - public static string GetPropertyValue( - EnvDTE.Project dteProject, - string configName, - string platformName, - string propName) - { - return GetPropertyValue( - dteProject.Object as VCProject, configName, platformName, propName); } public static string GetPropertyValue( @@ -374,123 +328,10 @@ return vcConfig.GetEvaluatedPropertyValue(propName); } - public void AddDefine(string define, uint bldConf) - { - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - var compiler = CompilerToolWrapper.Create(config); - - if (((!IsDebugConfiguration(config)) && ((bldConf & BuildConfig.Release) != 0)) || - ((IsDebugConfiguration(config)) && ((bldConf & BuildConfig.Debug) != 0))) { - compiler.AddPreprocessorDefinition(define); - } - } - } - - public void AddModule(int id) - { - if (HasModule(id)) - return; - - var vm = QtVersionManager.The(); - var versionInfo = vm.GetVersionInfo(Project); - if (versionInfo == null) - versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); - - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - - var info = QtModules.Instance.Module(id); - if (FormatVersion >= Resources.qtMinFormatVersion_Settings) { - var config3 = config as VCConfiguration3; - if (config3 == null) - continue; - if (!string.IsNullOrEmpty(info.proVarQT)) { - var qtModulesValue = config.GetUnevaluatedPropertyValue("QtModules"); - var qtModules = new HashSet<string>( - !string.IsNullOrEmpty(qtModulesValue) - ? qtModulesValue.Split(';') - : new string[] { }); - qtModules.UnionWith(info.proVarQT.Split(' ')); - config3.SetPropertyValue(Resources.projLabelQtSettings, true, - "QtModules", string.Join(";", qtModules)); - } - // In V3 project format, compiler and linker options - // required by modules are set by Qt/MSBuild. - continue; - } - - var compiler = CompilerToolWrapper.Create(config); - var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); - - if (compiler != null) { - foreach (var define in info.Defines) - compiler.AddPreprocessorDefinition(define); - - var incPathList = info.GetIncludePath(); - foreach (var incPath in incPathList) - compiler.AddAdditionalIncludeDirectories(incPath); - } - if (linker != null) { - var moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo); - var linkerWrapper = new LinkerToolWrapper(linker); - var additionalDeps = linkerWrapper.AdditionalDependencies; - var dependenciesChanged = false; - if (additionalDeps == null || additionalDeps.Count == 0) { - additionalDeps = moduleLibs; - dependenciesChanged = true; - } else { - foreach (var moduleLib in moduleLibs) { - if (!additionalDeps.Contains(moduleLib)) { - additionalDeps.Add(moduleLib); - dependenciesChanged = true; - } - } - } - if (dependenciesChanged) - linkerWrapper.AdditionalDependencies = additionalDeps; - } - } - } - - public void RemoveModule(int id) - { - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - var compiler = CompilerToolWrapper.Create(config); - var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); - - var info = QtModules.Instance.Module(id); - if (compiler != null) { - foreach (var define in info.Defines) - compiler.RemovePreprocessorDefinition(define); - var additionalIncludeDirs = compiler.AdditionalIncludeDirectories; - if (additionalIncludeDirs != null) { - var lst = new List<string>(additionalIncludeDirs); - foreach (var includePath in info.IncludePath) { - lst.Remove(includePath); - lst.Remove('\"' + includePath + '\"'); - } - compiler.AdditionalIncludeDirectories = lst; - } - } - if (linker != null && linker.AdditionalDependencies != null) { - var linkerWrapper = new LinkerToolWrapper(linker); - var vm = QtVersionManager.The(); - var versionInfo = vm.GetVersionInfo(Project); - if (versionInfo == null) - versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); - - var moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo); - var additionalDependencies = linkerWrapper.AdditionalDependencies; - var dependenciesChanged = false; - foreach (var moduleLib in moduleLibs) - dependenciesChanged |= additionalDependencies.Remove(moduleLib); - if (dependenciesChanged) - linkerWrapper.AdditionalDependencies = additionalDependencies; - } - } - } - public void UpdateModules(VersionInformation oldVersion, VersionInformation newVersion) { + ThreadHelper.ThrowIfNotOnUIThread(); + foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); @@ -500,7 +341,7 @@ var additionalDependencies = linkerWrapper.AdditionalDependencies; var libsDesktop = new List<string>(); - foreach (var module in QtModules.Instance.GetAvailableModules()) { + foreach (var module in QtModules.Instance.GetAvailableModules(newVersion.qtMajor)) { if (HasModule(module.Id)) libsDesktop.AddRange(module.AdditionalLibraries); } @@ -538,133 +379,11 @@ } } + // TODO: remove once all callers are moved into Legacy namespace public bool HasModule(int id) { - var foundInIncludes = false; - var foundInLibs = false; - - var vm = QtVersionManager.The(); - var versionInfo = vm.GetVersionInfo(Project); - if (versionInfo == null) - versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); - if (versionInfo == null) - return false; // neither a default or project Qt version - var info = QtModules.Instance.Module(id); - if (info == null) - return false; - - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - var compiler = CompilerToolWrapper.Create(config); - var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); - - if (compiler != null) { - if (compiler.GetAdditionalIncludeDirectories() == null) - continue; - var incPathList = info.GetIncludePath(); - var includeDirs = compiler.GetAdditionalIncludeDirectoriesList(); - foundInIncludes = (incPathList.Count > 0); - foreach (var incPath in incPathList) { - var fixedIncludeDir = FixFilePathForComparison(incPath); - if (!includeDirs.Any(dir => - FixFilePathForComparison(dir) == fixedIncludeDir)) { - foundInIncludes = false; - break; - } - } - } - - if (foundInIncludes) - break; - - List<string> libs = null; - if (linker != null) { - var linkerWrapper = new LinkerToolWrapper(linker); - libs = linkerWrapper.AdditionalDependencies; - } - - if (libs != null) { - var moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo); - foundInLibs = moduleLibs.All(moduleLib => libs.Contains(moduleLib)); - } - } - return foundInIncludes || foundInLibs; - } - - public void WriteProjectBasicConfigurations(uint type, bool usePrecompiledHeader) - { - WriteProjectBasicConfigurations(type, usePrecompiledHeader, null); - } - - public void WriteProjectBasicConfigurations(uint type, bool usePrecompiledHeader, VersionInformation vi) - { - var configType = ConfigurationTypes.typeApplication; - var targetExtension = ".exe"; - string qtVersion = null; - var vm = QtVersionManager.The(); - if (vi == null) { - qtVersion = vm.GetDefaultVersion(); - vi = vm.GetVersionInfo(qtVersion); - } - - switch (type & TemplateType.ProjectType) { - case TemplateType.DynamicLibrary: - configType = ConfigurationTypes.typeDynamicLibrary; - targetExtension = ".dll"; - break; - case TemplateType.StaticLibrary: - configType = ConfigurationTypes.typeStaticLibrary; - targetExtension = ".lib"; - break; - } - - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - config.ConfigurationType = configType; - var compiler = CompilerToolWrapper.Create(config); - var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); - var librarian = (VCLibrarianTool)((IVCCollection)config.Tools).Item("VCLibrarianTool"); - - if (linker != null) { - if ((type & TemplateType.ConsoleSystem) != 0) - linker.SubSystem = subSystemOption.subSystemConsole; - else - linker.SubSystem = subSystemOption.subSystemWindows; - - linker.OutputFile = "$(OutDir)\\$(ProjectName)" + targetExtension; - } else { - librarian.OutputFile = "$(OutDir)\\$(ProjectName)" + targetExtension; - } - - if ((type & TemplateType.PluginProject) != 0) - compiler.AddPreprocessorDefinition("QT_PLUGIN"); - - var isDebugConfiguration = false; - if (config.Name.StartsWith("Release", StringComparison.Ordinal)) { - compiler.SetDebugInformationFormat(debugOption.debugDisabled); - compiler.RuntimeLibrary = runtimeLibraryOption.rtMultiThreadedDLL; - } else if (config.Name.StartsWith("Debug", StringComparison.Ordinal)) { - isDebugConfiguration = true; - compiler.SetOptimization(optimizeOption.optimizeDisabled); - compiler.SetDebugInformationFormat(debugOption.debugEnabled); - compiler.RuntimeLibrary = runtimeLibraryOption.rtMultiThreadedDebugDLL; - } - - compiler.SetTreatWChar_tAsBuiltInType(true); - - if (linker != null) - linker.GenerateDebugInformation = isDebugConfiguration; - - if (usePrecompiledHeader) - UsePrecompiledHeaders(config); - } - if ((type & TemplateType.PluginProject) != 0) - MarkAsDesignerPluginProject(); - } - - public void MarkAsDesignerPluginProject() - { - Project.Globals["IsDesignerPlugin"] = true.ToString(); - if (!Project.Globals.get_VariablePersists("IsDesignerPlugin")) - Project.Globals.set_VariablePersists("IsDesignerPlugin", true); + ThreadHelper.ThrowIfNotOnUIThread(); + return Legacy.QtProject.HasModule(envPro, id); } public void AddUic4BuildStepMsBuild( @@ -672,8 +391,7 @@ string description, string outputFile) { - var file = config.File as VCFile; - if (file != null) + if (config.File is VCFile file) file.ItemType = QtUic.ItemTypeName; qtMsBuild.SetItemProperty(config, QtUic.Property.ExecutionDescription, description); qtMsBuild.SetItemProperty(config, QtUic.Property.OutputFile, outputFile); @@ -701,6 +419,8 @@ /// <param name="file">file</param> public void AddUic4BuildStep(VCFile file) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (GetFormatVersion(vcPro) >= Resources.qtMinFormatVersion_Settings) { file.ItemType = QtUic.ItemTypeName; return; @@ -736,7 +456,7 @@ } } if (toolSettings == CustomTool.CustomBuildStep && !uiFileExists) - AddFileInFilter(Filters.GeneratedFiles(), uiFile); + AddFileInFilter(Filters.GeneratedFiles(), uiFile, false); } catch { throw new QtVSException(SR.GetString("QtProject_CannotAddUicStep", file.FullPath)); } @@ -796,15 +516,15 @@ public string GetDefines(VCFileConfiguration conf) { var defines = string.Empty; - var propsFile = conf.Tool as IVCRulePropertyStorage; - var projectConfig = conf.ProjectConfiguration as VCConfiguration; - var propsProject = projectConfig.Rules.Item("CL") as IVCRulePropertyStorage; - if (propsFile != null) { + if (conf.Tool is IVCRulePropertyStorage propsFile) { try { defines = propsFile.GetUnevaluatedPropertyValue("PreprocessorDefinitions"); } catch { } } - if (string.IsNullOrEmpty(defines) && propsProject != null) { + + var projectConfig = conf.ProjectConfiguration as VCConfiguration; + if (string.IsNullOrEmpty(defines) + && projectConfig?.Rules.Item("CL") is IVCRulePropertyStorage propsProject) { try { defines = propsProject.GetUnevaluatedPropertyValue("PreprocessorDefinitions"); } catch { } @@ -846,12 +566,11 @@ var projectConfig = conf.ProjectConfiguration as VCConfiguration; includeList.AddRange(GetIncludesFromCompilerTool(CompilerToolWrapper.Create(projectConfig))); - var propertySheets = projectConfig.PropertySheets as IVCCollection; - if (propertySheets != null) { + if (projectConfig.PropertySheets is IVCCollection propertySheets) { foreach (VCPropertySheet sheet in propertySheets) includeList.AddRange(GetIncludesFromPropertySheet(sheet)); } - + var ompModified = new List<string>(); string sDir = "$(SolutionDir)"; foreach (string inc in includeList) { @@ -884,8 +603,7 @@ private List<string> GetIncludesFromPropertySheet(VCPropertySheet sheet) { var includeList = GetIncludesFromCompilerTool(CompilerToolWrapper.Create(sheet)); - var propertySheets = sheet.PropertySheets as IVCCollection; - if (propertySheets != null) { + if (sheet.PropertySheets is IVCCollection propertySheets) { foreach (VCPropertySheet subSheet in propertySheets) includeList.AddRange(GetIncludesFromPropertySheet(subSheet)); } @@ -903,18 +621,10 @@ return new List<string>(); } - private static bool IsDebugConfiguration(VCConfiguration conf) - { - var tool = CompilerToolWrapper.Create(conf); - if (tool != null) { - return tool.RuntimeLibrary == runtimeLibraryOption.rtMultiThreadedDebug - || tool.RuntimeLibrary == runtimeLibraryOption.rtMultiThreadedDebugDLL; - } - return false; - } - private string GetPCHMocOptions(VCFile file, CompilerToolWrapper compiler) { + ThreadHelper.ThrowIfNotOnUIThread(); + // As .moc files are included, we should not add anything there if (!HelperFunctions.IsHeaderFile(file.Name)) return string.Empty; @@ -941,12 +651,13 @@ VCFileConfiguration workFileConfig, VCFile mocFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + var hasDifferentMocFilePerConfig = QtVSIPSettings.HasDifferentMocFilePerConfig(envPro); var hasDifferentMocFilePerPlatform = QtVSIPSettings.HasDifferentMocFilePerPlatform(envPro); - var workFile = workFileConfig.File as VCFile; var mocFileName = GetMocFileName(sourceFile.FullPath); var mocableIsCPP = HelperFunctions.IsMocFile(mocFileName); var vcConfig = workFileConfig.ProjectConfiguration as VCConfiguration; @@ -1025,6 +736,8 @@ string includes, string description) { + ThreadHelper.ThrowIfNotOnUIThread(); + var workFile = workFileConfig.File as VCFile; var mocFileName = GetMocFileName(sourceFile.FullPath); var mocableIsCPP = HelperFunctions.IsMocFile(mocFileName); @@ -1068,6 +781,7 @@ + mocFileName + "))"; var regExp = new Regex(pattern); var matchList = regExp.Matches(tool.Outputs.Replace(ProjectMacros.Name, baseFileName)); + if (matchList.Count > 0) { if (matchList[0].Length > 0) outputMocFile = matchList[0].ToString(); @@ -1202,6 +916,8 @@ string includes, string description) { + ThreadHelper.ThrowIfNotOnUIThread(); + var baseFileName = sourceFile.Name.Remove(sourceFile.Name.LastIndexOf('.')); var outputMocFile = GetRelativeMocFilePath(sourceFile.FullPath); var outputMocPath = Path.GetDirectoryName(outputMocFile); @@ -1233,7 +949,8 @@ VCFileConfiguration workConfig, CustomTool toolSettings) { - var workFile = workConfig.File as VCFile; + ThreadHelper.ThrowIfNotOnUIThread(); + var mocFileName = GetMocFileName(sourceFile.FullPath); var mocableIsCPP = HelperFunctions.IsMocFile(mocFileName); var vcConfig = workConfig.ProjectConfiguration as VCConfiguration; @@ -1316,6 +1033,8 @@ /// <param name="file">file</param> public void AddMocStep(VCFile file) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (GetFormatVersion(vcPro) >= Resources.qtMinFormatVersion_Settings) { file.ItemType = QtMoc.ItemTypeName; if (HelperFunctions.IsSourceFile(file.FullPath)) { @@ -1343,8 +1062,7 @@ File.WriteAllText(cbtFullPath, string.Format( "This is a dummy file needed to create {0}", mocFileName)); file = AddFileInSubfilter(Filters.GeneratedFiles(), null, cbtFullPath, true); - var mocFileItem = file.Object as ProjectItem; - if (mocFileItem != null) + if (file.Object is ProjectItem mocFileItem) HelperFunctions.EnsureCustomBuildToolAvailable(mocFileItem); } @@ -1417,6 +1135,8 @@ public bool HasMocStep(VCFile file, string mocOutDir = null) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (file.ItemType == QtMoc.ItemTypeName) return true; @@ -1452,6 +1172,8 @@ public void RefreshRccSteps() { + ThreadHelper.ThrowIfNotOnUIThread(); + Messages.Print("\r\n=== Update rcc steps ==="); var files = GetResourceFiles(); @@ -1482,6 +1204,8 @@ public void RefreshRccSteps(string oldRccDir) { + ThreadHelper.ThrowIfNotOnUIThread(); + RefreshRccSteps(); UpdateCompilerIncludePaths(oldRccDir, QtVSIPSettings.GetRccDirectory(envPro)); } @@ -1493,8 +1217,7 @@ string nameOnly, string qrcCppFile) { - var file = vfc.File as VCFile; - if (file != null) + if (vfc.File is VCFile file) file.ItemType = QtRcc.ItemTypeName; qtMsBuild.SetItemProperty(vfc, QtRcc.Property.ExecutionDescription, "Rcc'ing " + ProjectMacros.FileName + "..."); @@ -1509,16 +1232,15 @@ string nameOnly, string qrcCppFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + var qrcFile = vfc.File as VCFile; var rccOptsCfg = rccOpts; var cmdLine = string.Empty; var cbt = HelperFunctions.GetCustomBuildTool(vfc); - cbt.AdditionalDependencies = filesInQrcFile; - cbt.Description = "Rcc'ing " + ProjectMacros.FileName + "..."; - cbt.Outputs = qrcCppFile.Replace(nameOnly, ProjectMacros.Name); cmdLine += "\"" + Resources.rcc4Command + "\"" @@ -1539,6 +1261,8 @@ public void UpdateRccStep(VCFile qrcFile, RccOptions rccOpts) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (GetFormatVersion(vcPro) >= Resources.qtMinFormatVersion_Settings) { qrcFile.ItemType = QtRcc.ItemTypeName; return; @@ -1548,8 +1272,6 @@ IsQtMsBuildEnabled() ? CustomTool.MSBuildTarget : CustomTool.CustomBuildStep; var vcpro = (VCProject)qrcFile.project; - var dteObject = ((Project)vcpro.Object).DTE; - var qtPro = Create(vcpro); var parser = new QrcParser(qrcFile.FullPath); var filesInQrcFile = ProjectMacros.Path; @@ -1606,7 +1328,7 @@ } } - static public void ExcludeFromAllBuilds(VCFile file) + public static void ExcludeFromAllBuilds(VCFile file) { if (file == null) return; @@ -1672,8 +1394,7 @@ List<VCFile> GetCppMocFiles(VCFile cppFile) { List<VCFile> mocFiles = new List<VCFile>(); - var vcProj = cppFile.project as VCProject; - if (vcProj != null) { + if (cppFile.project is VCProject vcProj) { mocFiles.AddRange(from VCFile vcFile in (IVCCollection)vcProj.Files where vcFile.ItemType == "CustomBuild" @@ -1697,27 +1418,29 @@ bool HasCppMocFiles(VCFile cppFile) { - if (!IsQtMsBuildEnabled()) { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (!IsQtMsBuildEnabled()) return File.Exists(Path.ChangeExtension(cppFile.FullPath, ".cbt")); - } else { - var vcProj = cppFile.project as VCProject; - if (vcProj != null) { - foreach (VCFile vcFile in (IVCCollection)vcProj.Files) { - if (vcFile.ItemType == "CustomBuild") { - if (IsCppMocFileCustomBuild(vcProj, vcFile, cppFile)) - return true; - } else if (vcFile.ItemType == QtMoc.ItemTypeName) { - if (IsCppMocFileQtMsBuild(vcProj, vcFile, cppFile)) - return true; - } + + if (cppFile.project is VCProject vcProj) { + foreach (VCFile vcFile in (IVCCollection)vcProj.Files) { + if (vcFile.ItemType == "CustomBuild") { + if (IsCppMocFileCustomBuild(vcProj, vcFile, cppFile)) + return true; + } else if (vcFile.ItemType == QtMoc.ItemTypeName) { + if (IsCppMocFileQtMsBuild(vcProj, vcFile, cppFile)) + return true; } } - return false; } + return false; } public void RemoveMocStep(VCFile file) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (file.ItemType == QtMoc.ItemTypeName) { RemoveMocStepQtMsBuild(file); } else if (HelperFunctions.IsHeaderFile(file.Name)) { @@ -1756,6 +1479,7 @@ /// <param name="file">file</param> public void RemoveMocStepCustomBuild(VCFile file) { + ThreadHelper.ThrowIfNotOnUIThread(); try { if (!HasMocStep(file)) return; @@ -1890,14 +1614,11 @@ public VCFile GetFileFromProject(string fileName) { fileName = HelperFunctions.NormalizeRelativeFilePath(fileName); - - var nf = fileName; if (!HelperFunctions.IsAbsoluteFilePath(fileName)) - nf = HelperFunctions.NormalizeFilePath(vcPro.ProjectDirectory + "\\" + fileName); - nf = nf.ToLower(); + fileName = HelperFunctions.NormalizeFilePath(vcPro.ProjectDirectory + "\\" + fileName); foreach (VCFile f in (IVCCollection)vcPro.Files) { - if (f.FullPath.ToLower() == nf) + if (f.FullPath.Equals(fileName, StringComparison.OrdinalIgnoreCase)) return f; } return null; @@ -1913,7 +1634,7 @@ { var fi = new FileInfo(HelperFunctions.NormalizeRelativeFilePath(fileName)); foreach (VCFile f in (IVCCollection)vcPro.Files) { - if (string.Equals(f.Name, fi.Name, StringComparison.OrdinalIgnoreCase)) + if (f.Name.Equals(fi.Name, StringComparison.OrdinalIgnoreCase)) yield return f; } } @@ -1924,34 +1645,6 @@ foreach (VCFilter subfilter in (IVCCollection)filter.Filters) tmpList.AddRange(GetAllFilesFromFilter(subfilter)); return tmpList; - } - - /// <summary> - /// Adds a file to a filter. If the filter doesn't exist yet, it - /// will be created. (Doesn't check for duplicates) - /// </summary> - /// <param name="filter">fake filter</param> - /// <param name="fileName">relative file name</param> - /// <returns>A VCFile object of the added file.</returns> - public VCFile AddFileInFilter(FakeFilter filter, string fileName) - { - return AddFileInFilter(filter, fileName, false); - } - - public void RemoveItem(ProjectItem item) - { - foreach (ProjectItem tmpFilter in Project.ProjectItems) { - if (tmpFilter.Name == item.Name) { - tmpFilter.Remove(); - return; - } - foreach (ProjectItem tmpItem in tmpFilter.ProjectItems) { - if (tmpItem.Name == item.Name) { - tmpItem.Remove(); - return; - } - } - } } /// <summary> @@ -1972,7 +1665,8 @@ return AddFileInSubfilter(filter, subfilterName, fileName, false); } - public VCFile AddFileInSubfilter(FakeFilter filter, string subfilterName, string fileName, bool checkForDuplicates) + public VCFile AddFileInSubfilter(FakeFilter filter, string subfilterName, string fileName, + bool checkForDuplicates) { try { var vfilt = FindFilterFromGuid(filter.UniqueIdentifier); @@ -1981,7 +1675,7 @@ // check if user already created this filter... then add guid vfilt = FindFilterFromName(filter.Name); if (vfilt == null) - throw new QtVSException(SR.GetString("QtProject_CannotAddFilter", filter.Name)); + throw new QtVSException($"Project cannot add filter {filter.Name}"); } else { vfilt = (VCFilter)vcPro.AddFilter(filter.Name); } @@ -2014,14 +1708,7 @@ } if (!subfilterFound) { if (!vfilt.CanAddFilter(subfilterName)) - throw new QtVSException(SR.GetString("QtProject_CannotAddFilter", filter.Name)); - -#if !(VS2017 || VS2019 || VS2022) - // TODO: Enable once the freeze gets fixed in VS. - vfilt = (VCFilter)vfilt.AddFilter(subfilterName); - vfilt.Filter = "cpp;moc"; - vfilt.SourceControlFiles = false; -#endif + throw new QtVSException($"Project cannot add filter {filter.Name}"); } } @@ -2034,10 +1721,13 @@ if (vfilt.CanAddFile(fileName)) return (VCFile)(vfilt.AddFile(fileName)); - throw new QtVSException(SR.GetString("QtProject_CannotAddFile", fileName)); - } catch { - throw new QtVSException(SR.GetString("QtProject_CannotAddFile", fileName)); + throw new QtVSException($"Cannot add file {fileName} to filter."); + } catch (QtVSException) { + throw; + } catch (Exception e){ + throw new QtVSException($"Cannot add file {fileName} to filter.", e); } + } /// <summary> @@ -2165,94 +1855,38 @@ } } - public void AddDirectories() + public static bool IsQtPlugin(Core.QtProject qtPro) { - try { - // resource directory - var fi = new FileInfo(envPro.FullName); - var dfi = new DirectoryInfo(fi.DirectoryName + "\\" + Resources.resourceDir); - dfi.Create(); - } catch { - throw new QtVSException(SR.GetString("QtProject_CannotCreateResourceDir")); - } - AddFilterToProject(Filters.ResourceFiles()); - } + ThreadHelper.ThrowIfNotOnUIThread(); - public void Finish() - { - try { - var solutionExplorer = dte.Windows.Item(Constants.vsWindowKindSolutionExplorer); - if (solutionExplorer != null) { - var hierarchy = (UIHierarchy)solutionExplorer.Object; - var projects = hierarchy.UIHierarchyItems.Item(1).UIHierarchyItems; + if (qtPro.FormatVersion < Resources.qtMinFormatVersion_Settings) + return false; - foreach (UIHierarchyItem itm in projects) { - if (itm.Name == envPro.Name) { - foreach (UIHierarchyItem i in itm.UIHierarchyItems) { - if (i.Name == Filters.GeneratedFiles().Name) - i.UIHierarchyItems.Expanded = false; - } - break; - } - } - } - } catch { } - - ProjectTracker?.AddProject(envPro); - } - - public bool IsDesignerPluginProject() - { - var b = false; - if (Project.Globals.get_VariablePersists("IsDesignerPlugin")) { - var s = (string)Project.Globals["IsDesignerPlugin"]; - try { - b = bool.Parse(s); - } catch { } - } - return b; - } - - /// <summary> - /// Adds a file to a specified filter in a project. - /// </summary> - /// <param name="destName">name of the file in the project (relative to the project directory)</param> - /// <param name="filter">filter</param> - /// <returns>VCFile</returns> - public VCFile AddFileToProject(string destName, FakeFilter filter) - { - VCFile file = null; - if (filter != null) - file = AddFileInFilter(filter, destName); - else - file = (VCFile)vcPro.AddFile(destName); - - if (file == null) - return null; - - if (HelperFunctions.IsHeaderFile(file.Name)) { - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - var compiler = CompilerToolWrapper.Create(config); - if (compiler == null) - continue; - - var paths = compiler.GetAdditionalIncludeDirectoriesList(); - var fi = new FileInfo(file.FullPath); - var relativePath = HelperFunctions.GetRelativePath(ProjectDir, fi.Directory.ToString()); - var fixedRelativePath = FixFilePathForComparison(relativePath); - if (!paths.Any(p => FixFilePathForComparison(p) == fixedRelativePath)) - compiler.AddAdditionalIncludeDirectories(relativePath); + foreach (VCConfiguration config in qtPro.VCProject.Configurations as IVCCollection) { + if ((config.Rules.Item("QtRule10_Settings") as IVCRulePropertyStorage) + .GetEvaluatedPropertyValue("QtPlugin") == "true") { + return true; } } - return file; + return false; + } + + public static void MarkAsQtPlugin(Core.QtProject qtPro) + { + foreach (VCConfiguration config in qtPro.VCProject.Configurations as IVCCollection) { + (config.Rules.Item("QtRule10_Settings") as IVCRulePropertyStorage) + .SetPropertyValue("QtPlugin", "true"); + } } /// <summary> /// adjusts the whitespaces, tabs in the given file according to VS settings /// </summary> /// <param name="file"></param> - public void AdjustWhitespace(string file) + public static void AdjustWhitespace(DTE dte, string file) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!File.Exists(file)) return; @@ -2299,89 +1933,6 @@ return whitespaces; } - /// <summary> - /// Copy a file to the projects folder. Does not add the file to the project. - /// </summary> - /// <param name="srcFile">full name of the file to add</param> - /// <param name="destFolder">the name of the project folder</param> - /// <param name="destName">name of the file in the project (relative to the project directory)</param> - /// <returns>full name of the destination file</returns> - public static string CopyFileToFolder(string srcFile, string destFolder, string destName) - { - var fullDestName = destFolder + "\\" + destName; - var fi = new FileInfo(fullDestName); - - var replace = true; - if (File.Exists(fullDestName)) { - if (DialogResult.No == MessageBox.Show(SR.GetString("QtProject_FileExistsInProjectFolder", destName) - , SR.GetString("Resources_QtVsTools"), MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { - replace = false; - } - } - - if (replace) { - if (!fi.Directory.Exists) - fi.Directory.Create(); - File.Copy(srcFile, fullDestName, true); - var attribs = File.GetAttributes(fullDestName); - File.SetAttributes(fullDestName, attribs & (~FileAttributes.ReadOnly)); - } - return fi.FullName; - } - - public static void ReplaceTokenInFile(string file, string token, string replacement) - { - var text = string.Empty; - try { - var reader = new StreamReader(file); - text = reader.ReadToEnd(); - reader.Close(); - } catch (Exception e) { - Messages.DisplayErrorMessage( - SR.GetString("QtProject_CannotReplaceTokenRead", token, replacement, e.ToString())); - return; - } - - try { - if (token.ToUpper() == "%PRE_DEF%" && !Char.IsLetter(replacement[0])) - replacement = "_" + replacement; - - text = text.Replace(token, replacement); - var writer = new StreamWriter(file); - writer.Write(text); - writer.Close(); - } catch (Exception e) { - Messages.DisplayErrorMessage( - SR.GetString("QtProject_CannotReplaceTokenWrite", token, replacement, e.ToString())); - } - } - - public void RepairGeneratedFilesStructure() - { - DeleteGeneratedFiles(); - - var files = new ConcurrentBag<VCFile>(); - Task.WaitAll( - Task.Run(() => - Parallel.ForEach(((IVCCollection)vcPro.Files).Cast<VCFile>(), file => - { - var name = file.Name; - if (!HelperFunctions.IsHeaderFile(name) && !HelperFunctions.IsSourceFile(name)) - return; - if (HelperFunctions.HasQObjectDeclaration(file)) - files.Add(file); - }) - ) - ); - - qtMsBuild.BeginSetItemProperties(); - foreach (var file in files) { - RemoveMocStep(file); - AddMocStep(file); - } - qtMsBuild.EndSetItemProperties(); - } - public void TranslateFilterNames() { var filters = vcPro.Filters as IVCCollection; @@ -2402,37 +1953,10 @@ } } - public static string CreateQrcFile(string projectDir, string className, string destName) - { - var fullDestName = projectDir + "\\" + destName; - - if (!File.Exists(fullDestName)) { - FileStream s = null; - try { - s = File.Open(fullDestName, FileMode.CreateNew); - if (s.CanWrite) { - using (var sw = new StreamWriter(s)) { - s = null; - sw.WriteLine("<RCC>"); - sw.WriteLine(" <qresource prefix=\"" + className + "\">"); - sw.WriteLine(" </qresource>"); - sw.WriteLine("</RCC>"); - } - } - } finally { - if (s != null) - s.Dispose(); - } - var attribs = File.GetAttributes(fullDestName); - File.SetAttributes(fullDestName, attribs & (~FileAttributes.ReadOnly)); - } - - var fi = new FileInfo(fullDestName); - return fi.FullName; - } - public void AddActiveQtBuildStep(string version, string defFile = null) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (FormatVersion < Resources.qtMinFormatVersion_ClProperties) return; @@ -2463,6 +1987,8 @@ private void UpdateCompilerIncludePaths(string oldDir, string newDir) { + ThreadHelper.ThrowIfNotOnUIThread(); + var fixedOldDir = FixFilePathForComparison(oldDir); var dirs = new[] { FixFilePathForComparison(QtVSIPSettings.GetUicDirectory(envPro)), @@ -2516,6 +2042,8 @@ public void UpdateUicSteps(string oldUicDir, bool update_inc_path) { + ThreadHelper.ThrowIfNotOnUIThread(); + Messages.Print("\r\n=== Update uic steps ==="); var vcFilter = FindFilterFromGuid(Filters.GeneratedFiles().UniqueIdentifier); if (vcFilter != null) { @@ -2538,7 +2066,7 @@ qtMsBuild.BeginSetItemProperties(); foreach (var file in files) { - if (HelperFunctions.IsUicFile(file.Name) && !IsUic3File(file)) { + if (HelperFunctions.IsUicFile(file.Name)) { AddUic4BuildStep(file); Messages.Print("Update uic step for " + file.Name + "."); ++updatedFiles; @@ -2549,42 +2077,6 @@ UpdateCompilerIncludePaths(oldUicDir, QtVSIPSettings.GetUicDirectory(envPro)); Messages.Print("\r\n=== " + updatedFiles + " uic steps updated. ===\r\n"); - } - - private static bool IsUic3File(VCFile file) - { - foreach (VCFileConfiguration config in (IVCCollection)file.FileConfigurations) { - var tool = HelperFunctions.GetCustomBuildTool(config); - if (tool == null) - return false; - if (tool.CommandLine.IndexOf("uic3.exe", StringComparison.OrdinalIgnoreCase) > -1) - return true; - } - return false; - } - - public bool UsePrecompiledHeaders(VCConfiguration config) - { - var compiler = CompilerToolWrapper.Create(config); - return UsePrecompiledHeaders(compiler); - } - - private bool UsePrecompiledHeaders(CompilerToolWrapper compiler) - { - try { - compiler.SetUsePrecompiledHeader(pchOption.pchUseUsingSpecific); - var pcHeaderThrough = GetPrecompiledHeaderThrough(); - if (string.IsNullOrEmpty(pcHeaderThrough)) - pcHeaderThrough = "stdafx.h"; - compiler.SetPrecompiledHeaderThrough(pcHeaderThrough); - var pcHeaderFile = GetPrecompiledHeaderFile(); - if (string.IsNullOrEmpty(pcHeaderFile)) - pcHeaderFile = ".\\$(ConfigurationName)/" + Project.Name + ".pch"; - compiler.SetPrecompiledHeaderFile(pcHeaderFile); - return true; - } catch { - return false; - } } public bool UsesPrecompiledHeaders() @@ -2637,32 +2129,6 @@ return null; } - public string GetPrecompiledHeaderFile() - { - foreach (VCConfiguration config in vcPro.Configurations as IVCCollection) { - var file = GetPrecompiledHeaderFile(config); - if (!string.IsNullOrEmpty(file)) - return file; - } - return null; - } - - public static string GetPrecompiledHeaderFile(VCConfiguration config) - { - var compiler = CompilerToolWrapper.Create(config); - return GetPrecompiledHeaderFile(compiler); - } - - private static string GetPrecompiledHeaderFile(CompilerToolWrapper compiler) - { - try { - var file = compiler.GetPrecompiledHeaderFile(); - if (!string.IsNullOrEmpty(file)) - return file; - } catch { } - return null; - } - public static void SetPCHOption(VCFile vcFile, pchOption option) { foreach (VCFileConfiguration config in vcFile.FileConfigurations as IVCCollection) { @@ -2692,6 +2158,8 @@ /// <returns></returns> private VCFile GetGeneratedMocFile(string fileName, VCFileConfiguration fileConfig) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (QtVSIPSettings.HasDifferentMocFilePerConfig(envPro) || QtVSIPSettings.HasDifferentMocFilePerPlatform(envPro)) { var projectConfig = (VCConfiguration)fileConfig.ProjectConfiguration; @@ -2763,6 +2231,8 @@ public void RefreshMocSteps() { + ThreadHelper.ThrowIfNotOnUIThread(); + // Ignore when using shared compiler properties if (GetFormatVersion(vcPro) >= Resources.qtMinFormatVersion_ClProperties) return; @@ -2790,6 +2260,7 @@ public void RefreshMocStep(VCFile vcfile) { + ThreadHelper.ThrowIfNotOnUIThread(); RefreshMocStep(vcfile, true); } @@ -2803,6 +2274,8 @@ /// <param name="vcfile"></param> private void RefreshMocStep(VCFile vcfile, bool singleFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + var isHeaderFile = HelperFunctions.IsHeaderFile(vcfile.FullPath); if (!isHeaderFile && !HelperFunctions.IsSourceFile(vcfile.FullPath)) return; @@ -2942,6 +2415,8 @@ public void OnExcludedFromBuildChanged(VCFile vcFile, VCFileConfiguration vcFileCfg) { + ThreadHelper.ThrowIfNotOnUIThread(); + // Update the ExcludedFromBuild flags of the mocced file // according to the ExcludedFromBuild flag of the mocable source file. var moccedFileName = GetMocFileName(vcFile.Name); @@ -3011,6 +2486,8 @@ public void UpdateMocSteps(string oldMocDir) { + ThreadHelper.ThrowIfNotOnUIThread(); + Messages.Print("\r\n=== Update moc steps ==="); var orgFiles = new List<VCFile>(); var abandonedMocFiles = new List<string>(); @@ -3053,8 +2530,8 @@ try { RemoveMocStep(file); AddMocStep(file); - } catch (QtVSException e) { - Messages.Print(e.Message); + } catch (QtVSException exception) { + exception.Log(); continue; } Messages.Print("Moc step updated successfully for " + file.Name + "."); @@ -3073,6 +2550,8 @@ private void Clean() { + ThreadHelper.ThrowIfNotOnUIThread(); + var solutionConfigs = envPro.DTE.Solution.SolutionBuild.SolutionConfigurations; var backup = new List<KeyValuePair<SolutionContext, bool>>(); foreach (SolutionConfiguration config in solutionConfigs) { @@ -3125,47 +2604,6 @@ } } - public bool isWinRT() - { - try { - var vcProject = Project.Object as VCProject; - var vcConfigs = vcProject.Configurations as IVCCollection; - var vcConfig = vcConfigs.Item(1) as VCConfiguration; - var appType = vcConfig.GetEvaluatedPropertyValue("ApplicationType"); - if (appType == "Windows Store") - return true; - } catch { } - return false; - } - - public bool PromptChangeQtVersion(string oldVersion, string newVersion) - { - var versionManager = QtVersionManager.The(); - var viOld = versionManager.GetVersionInfo(oldVersion); - var viNew = versionManager.GetVersionInfo(newVersion); - - if (viOld == null || viNew == null) - return true; - - var oldIsWinRt = viOld.isWinRT(); - var newIsWinRt = viNew.isWinRT(); - - if (newIsWinRt == oldIsWinRt || newIsWinRt == isWinRT()) - return true; - - var promptCaption = string.Format("Change Qt Version ({0})", Project.Name); - var promptText = string.Format( - "Changing Qt version from {0} to {1}.\r\n" + - "Project might not build. Are you sure?", - newIsWinRt ? "Win32" : "WinRT", - newIsWinRt ? "WinRT" : "Win32" - ); - - return (MessageBox.Show( - promptText, promptCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) - == DialogResult.Yes); - } - /// <summary> /// Changes the Qt version of this project. /// </summary> @@ -3175,6 +2613,8 @@ /// <returns>true, if the operation performed successfully</returns> public bool ChangeQtVersion(string oldVersion, string newVersion, ref bool newProjectCreated) { + ThreadHelper.ThrowIfNotOnUIThread(); + newProjectCreated = false; var versionManager = QtVersionManager.The(); var viNew = versionManager.GetVersionInfo(newVersion); @@ -3243,6 +2683,8 @@ public bool SelectSolutionPlatform(string platformName) { + ThreadHelper.ThrowIfNotOnUIThread(); + foreach (SolutionConfiguration solutionCfg in dte.Solution.SolutionBuild.SolutionConfigurations) { var contexts = solutionCfg.SolutionContexts; for (var i = 1; i <= contexts.Count; ++i) { @@ -3268,6 +2710,8 @@ public void CreatePlatform(string oldPlatform, string newPlatform, VersionInformation viOld, VersionInformation viNew, ref bool newProjectCreated) { + ThreadHelper.ThrowIfNotOnUIThread(); + try { var cfgMgr = envPro.ConfigurationManager; cfgMgr.AddPlatform(newPlatform, oldPlatform, true); @@ -3329,9 +2773,7 @@ if (genVCFilter == null) return; - var error = false; - error = DeleteFilesFromFilter(genVCFilter); - if (error) + if (DeleteFilesFromFilter(genVCFilter)) Messages.Print(SR.GetString("DeleteGeneratedFilesError")); } @@ -3389,7 +2831,7 @@ resFile.Remove(); } - static private void AddPlatformToVCProj(string projectFileName, string oldPlatformName, string newPlatformName) + private static void AddPlatformToVCProj(string projectFileName, string oldPlatformName, string newPlatformName) { var tempFileName = Path.GetTempFileName(); var fi = new FileInfo(projectFileName); @@ -3404,7 +2846,7 @@ fi.Delete(); } - static private void AddPlatformToVCProj(XmlDocument doc, string oldPlatformName, string newPlatformName) + private static void AddPlatformToVCProj(XmlDocument doc, string oldPlatformName, string newPlatformName) { var vsProj = doc.DocumentElement.SelectSingleNode("/VisualStudioProject"); var platforms = vsProj.SelectSingleNode("Platforms"); @@ -3438,7 +2880,7 @@ } } - static private void SetTargetMachine(VCLinkerTool linker, VersionInformation versionInfo) + private static void SetTargetMachine(VCLinkerTool linker, VersionInformation versionInfo) { var qMakeLFlagsWindows = versionInfo.GetQMakeConfEntry("QMAKE_LFLAGS_WINDOWS"); var rex = new Regex("/MACHINE:(\\S+)"); @@ -3476,6 +2918,8 @@ public void CollapseFilter(string filterName) { + ThreadHelper.ThrowIfNotOnUIThread(); + var solutionExplorer = (UIHierarchy)dte.Windows.Item(Constants.vsext_wk_SProjectWindow).Object; if (solutionExplorer.UIHierarchyItems.Count == 0) return; @@ -3489,6 +2933,8 @@ private UIHierarchyItem FindProjectHierarchyItem(UIHierarchy hierarchy) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (hierarchy.UIHierarchyItems.Count == 0) return null; @@ -3504,6 +2950,8 @@ private UIHierarchyItem FindProjectHierarchyItem(UIHierarchyItem root) { + ThreadHelper.ThrowIfNotOnUIThread(); + UIHierarchyItem projectItem = null; try { if (root.Name == envPro.Name) @@ -3524,6 +2972,7 @@ /// </summary> public string GetQtVersion() { + ThreadHelper.ThrowIfNotOnUIThread(); return QtVersionManager.The().GetProjectQtVersion(envPro); } @@ -3532,6 +2981,7 @@ /// </summary> public void SetQtEnvironment() { + ThreadHelper.ThrowIfNotOnUIThread(); SetQtEnvironment(QtVersionManager.The().GetProjectQtVersion(envPro)); } @@ -3540,6 +2990,7 @@ /// </summary> public void SetQtEnvironment(string qtVersion) { + ThreadHelper.ThrowIfNotOnUIThread(); SetQtEnvironment(qtVersion, string.Empty); } @@ -3548,6 +2999,8 @@ /// </summary> public void SetQtEnvironment(string qtVersion, string solutionConfig, bool build = false) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (string.IsNullOrEmpty(qtVersion)) return; @@ -3558,6 +3011,7 @@ if (qtVersion != "$(QTDIR)") qtDir = QtVersionManager.The().GetInstallPath(qtVersion); HelperFunctions.SetEnvironmentVariableEx("QTDIR", qtDir); + try { var propertyAccess = (IVCBuildPropertyStorage)vcPro; var vcprj = envPro.Object as VCProject; @@ -3590,8 +3044,7 @@ debuggerEnv = propertyAccess.GetPropertyValue( "LocalDebuggerEnvironment", cur_solution, "UserFile"); if (!string.IsNullOrEmpty(debuggerEnv)) { - var debugSettings = conf.DebugSettings as VCDebugSettings; - if (debugSettings != null) { + if (conf.DebugSettings is VCDebugSettings debugSettings) { //Get original value without expanded properties debuggerEnv = debugSettings.Environment; } @@ -3624,9 +3077,8 @@ var projProps = vcProj as IVCBuildPropertyStorage; try { return projProps.GetPropertyValue(pszPropName, Config.Name, "UserFile"); - } catch (Exception e) { - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); return string.Empty; } } @@ -3637,9 +3089,8 @@ var projProps = vcProj as IVCBuildPropertyStorage; try { projProps.SetPropertyValue(pszPropName, Config.Name, "UserFile", pszPropValue); - } catch (Exception e) { - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); } } @@ -3649,9 +3100,8 @@ var projProps = vcProj as IVCBuildPropertyStorage; try { projProps.RemoveProperty(pszPropName, Config.Name, "UserFile"); - } catch (Exception e) { - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); } } } @@ -3970,10 +3420,10 @@ { if (propertyStorage == null) return null; - if (propertyStorage is VCFileConfiguration) - return GetParentProject(propertyStorage as VCFileConfiguration); - else if (propertyStorage is VCConfiguration) - return GetParentProject(propertyStorage as VCConfiguration); + if (propertyStorage is VCFileConfiguration configuration) + return GetParentProject(configuration); + else if (propertyStorage is VCConfiguration storage) + return GetParentProject(storage); return null; } @@ -4026,8 +3476,7 @@ public class VCMacroExpander : IVSMacroExpander { - object config; - + readonly object config; public VCMacroExpander(object config) { this.config = config; @@ -4042,14 +3491,15 @@ public class QtCustomBuildTool { - QtMsBuildContainer qtMsBuild; - VCFileConfiguration vcConfig; - VCFile vcFile; - VCCustomBuildTool tool; - VCMacroExpander macros; + readonly QtMsBuildContainer qtMsBuild; + readonly VCFileConfiguration vcConfig; + readonly VCFile vcFile; + readonly VCCustomBuildTool tool; + readonly VCMacroExpander macros; enum FileItemType { Other = 0, CustomBuild, QtMoc, QtRcc, QtRepc, QtUic }; - FileItemType itemType = FileItemType.Other; + readonly FileItemType itemType = FileItemType.Other; + public QtCustomBuildTool(VCFileConfiguration vcConfig, QtMsBuildContainer container = null) { if (container != null) diff --git a/QtVsTools.Core/QtVSIPSettings.cs b/QtVsTools.Core/QtVSIPSettings.cs index bbd3a45..7eb4146 100644 --- a/QtVsTools.Core/QtVSIPSettings.cs +++ b/QtVsTools.Core/QtVSIPSettings.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,11 +26,9 @@ ** ****************************************************************************/ +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.VCProjectEngine; -using Microsoft.Win32; -using QtVsTools.Core.QtMsBuild; -using System; -using System.Collections; +using QtVsTools.Common; namespace QtVsTools.Core { @@ -46,41 +44,26 @@ { public static IQtVsToolsOptions Options { get; set; } - static Hashtable mocDirCache = new Hashtable(); - static Hashtable uicDirCache = new Hashtable(); - static Hashtable rccDirCache = new Hashtable(); - public static bool GetDisableAutoMocStepsUpdate() { - return GetBoolValue(Resources.disableAutoMocStepsUpdateKeyword, false); - } - - public static void SaveDisableAutoMocStepsUpdate(bool b) - { - SetBoolValue(Resources.disableAutoMocStepsUpdateKeyword, b); + return QtVSIPSettingsShared.GetBoolValue(Resources.disableAutoMocStepsUpdateKeyword, false); } public static string GetUicDirectory(EnvDTE.Project project) { - return GetDirectory(project, Resources.uicDirKeyword); - } - - public static void SaveUicDirectory(EnvDTE.Project project, string directory) - { - if (directory == null) - SaveDirectory(project, Resources.uicDirKeyword, GetDirectory(project, Resources.uicDirKeyword)); - else - SaveDirectory(project, Resources.uicDirKeyword, directory); + ThreadHelper.ThrowIfNotOnUIThread(); + return QtVSIPSettingsShared.GetDirectory(project, Resources.uicDirKeyword); } public static string GetMocDirectory() { - return GetDirectory(Resources.mocDirKeyword); + return QtVSIPSettingsShared.GetDirectory(Resources.mocDirKeyword); } public static string GetMocDirectory(EnvDTE.Project project) { - return GetDirectory(project, Resources.mocDirKeyword); + ThreadHelper.ThrowIfNotOnUIThread(); + return QtVSIPSettingsShared.GetDirectory(project, Resources.mocDirKeyword); } public static string GetMocDirectory( @@ -88,6 +71,8 @@ string configName, string platformName, VCFile vCFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + string filePath = null; if (vCFile != null) filePath = vCFile.FullPath; @@ -100,7 +85,9 @@ string platformName, string filePath = null) { - var dir = GetDirectory(project, Resources.mocDirKeyword); + ThreadHelper.ThrowIfNotOnUIThread(); + + var dir = QtVSIPSettingsShared.GetDirectory(project, Resources.mocDirKeyword); if (!string.IsNullOrEmpty(configName) && !string.IsNullOrEmpty(platformName)) HelperFunctions.ExpandString(ref dir, project, configName, platformName, filePath); @@ -109,458 +96,56 @@ public static bool HasDifferentMocFilePerConfig(EnvDTE.Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + var mocDir = GetMocDirectory(project); return mocDir.Contains("$(ConfigurationName)"); } public static bool HasDifferentMocFilePerPlatform(EnvDTE.Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + var mocDir = GetMocDirectory(project); return mocDir.Contains("$(PlatformName)"); } - public static string GetMocOptions() - { - return GetOption(Resources.mocOptionsKeyword); - } - public static string GetMocOptions(EnvDTE.Project project) { - return GetOption(project, Resources.mocOptionsKeyword); + ThreadHelper.ThrowIfNotOnUIThread(); + return QtVSIPSettingsShared.GetOption(project, Resources.mocOptionsKeyword); } public static bool GetLUpdateOnBuild(EnvDTE.Project project) { - if (GetProjectQtSetting(project, "QtRunLUpdateOnBuild") == "true") + ThreadHelper.ThrowIfNotOnUIThread(); + + if (QtVSIPSettingsShared.GetProjectQtSetting(project, "QtRunLUpdateOnBuild") == "true") return true; - return GetBoolValue(project, Resources.lupdateKeyword); - } - - public static string GetLUpdateOptions() - { - return GetOption(Resources.lupdateOptionsKeyword); - } - - static string GetProjectQtSetting(EnvDTE.Project project, string propertyName) - { - var vcProject = project.Object as VCProject; - if (vcProject == null) - return null; - - var vcConfigs = vcProject.Configurations as IVCCollection; - if (vcConfigs == null) - return null; - - var activeConfig = project.ConfigurationManager.ActiveConfiguration; - if (activeConfig == null) - return null; - - var activeConfigId = string.Format("{0}|{1}", - activeConfig.ConfigurationName, activeConfig.PlatformName); - - var props = vcProject as IVCBuildPropertyStorage; - if (props == null) - return null; - - try { - return props.GetPropertyValue(propertyName, activeConfigId, "ProjectFile"); - } catch { - return null; - } - } - - public static string GetLUpdateOptions(EnvDTE.Project project) - { - string qtLUpdateOptions = GetProjectQtSetting(project, "QtLUpdateOptions"); - if (!string.IsNullOrEmpty(qtLUpdateOptions)) - return qtLUpdateOptions; - return GetOption(project, Resources.lupdateOptionsKeyword); - } - - public static string GetLReleaseOptions() - { - return GetOption(Resources.lreleaseOptionsKeyword); - } - - public static string GetLReleaseOptions(EnvDTE.Project project) - { - string qtLReleaseOptions = GetProjectQtSetting(project, "QtLReleaseOptions"); - if (!string.IsNullOrEmpty(qtLReleaseOptions)) - return qtLReleaseOptions; - return GetOption(project, Resources.lreleaseOptionsKeyword); - } - - public static bool GetAskBeforeCheckoutFile() - { - return GetBoolValue(Resources.askBeforeCheckoutFileKeyword, true); - } - - public static void SaveAskBeforeCheckoutFile(bool value) - { - SetBoolValue(Resources.askBeforeCheckoutFileKeyword, value); - } - - public static bool GetDisableCheckoutFiles() - { - return GetBoolValue(Resources.disableCheckoutFilesKeyword, false); - } - - public static void SaveDisableCheckoutFiles(bool value) - { - SetBoolValue(Resources.disableCheckoutFilesKeyword, value); - } - - public static void SaveMocDirectory(EnvDTE.Project project, string directory) - { - if (directory == null) - SaveDirectory(project, Resources.mocDirKeyword, GetDirectory(project, Resources.mocDirKeyword)); - else - SaveDirectory(project, Resources.mocDirKeyword, directory); - } - - public static void SaveMocOptions(EnvDTE.Project project, string options) - { - if (options == null) - options = GetMocOptions(); - SaveOption(project, Resources.mocOptionsKeyword, options); - } - - public static void SaveMocOptions(string options) - { - SaveOption(Resources.mocOptionsKeyword, options); - } - - public static void SaveLUpdateOnBuild(EnvDTE.Project project) - { - SetBoolValue(project, Resources.lupdateKeyword, GetLUpdateOnBuild()); - } - - public static void SaveLUpdateOnBuild(EnvDTE.Project project, bool value) - { - SetBoolValue(project, Resources.lupdateKeyword, value); - } - - public static void SaveLUpdateOptions(EnvDTE.Project project, string options) - { - if (options == null) - options = GetLUpdateOptions(); - - SaveOption(project, Resources.lupdateOptionsKeyword, options); - } - - public static void SaveLUpdateOptions(string options) - { - SaveOption(Resources.lupdateOptionsKeyword, options); - } - - public static void SaveLReleaseOptions(EnvDTE.Project project, string options) - { - if (options == null) - options = GetLReleaseOptions(); - SaveOption(project, Resources.lreleaseOptionsKeyword, options); - } - - public static void SaveLReleaseOptions(string options) - { - SaveOption(Resources.lreleaseOptionsKeyword, options); + return QtVSIPSettingsShared.GetBoolValue(project, Resources.lupdateKeyword); } public static string GetRccDirectory(EnvDTE.Project project) { - return GetDirectory(project, Resources.rccDirKeyword); - } - - public static void SaveRccDirectory(string dir) - { - SaveDirectory(Resources.rccDirKeyword, dir); - } - - public static void SaveRccDirectory(EnvDTE.Project project, string directory) - { - if (directory == null) - SaveDirectory(project, Resources.rccDirKeyword, GetDirectory(project, Resources.rccDirKeyword)); - else - SaveDirectory(project, Resources.rccDirKeyword, directory); - } - - private static string GetDirectory(string type) - { - try { - var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\" + Resources.registryPackagePath); - if (key != null) { - var path = (string)key.GetValue(type, null); - if (path != null) - return HelperFunctions.NormalizeRelativeFilePath(path); - } - } catch { } - if (type == Resources.mocDirKeyword) - return Resources.generatedFilesDir + "\\$(ConfigurationName)"; - return Resources.generatedFilesDir; - } - - private static string GetOption(string type) - { - try { - var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\" + Resources.registryPackagePath); - if (key != null) { - var opt = (string)key.GetValue(type, null); - if (opt != null) - return opt; - } - } catch { } - return null; - } - - public static bool GetLUpdateOnBuild() - { - return GetBoolValue(Resources.lupdateKeyword, false); + ThreadHelper.ThrowIfNotOnUIThread(); + return QtVSIPSettingsShared.GetDirectory(project, Resources.rccDirKeyword); } public static string GetRccDirectory() { - return GetDirectory(Resources.rccDirKeyword); + return QtVSIPSettingsShared.GetDirectory(Resources.rccDirKeyword); } public static string GetUicDirectory() { - return GetDirectory(Resources.uicDirKeyword); - } - - private static string GetDirectory(EnvDTE.Project project, string type) - { - // check for directory in following order: - // - stored in project - // - stored in cache - // - retrieve from moc/uic steps - // - globally defined default directory - // - fallback on hardcoded directory - if (project != null) { - if (project.Globals.get_VariablePersists(type)) - return HelperFunctions.NormalizeRelativeFilePath((string)project.Globals[type]); - - try { - if (type == Resources.mocDirKeyword && mocDirCache.Contains(project.FullName)) - return (string)mocDirCache[project.FullName]; - if (type == Resources.uicDirKeyword && uicDirCache.Contains(project.FullName)) - return (string)uicDirCache[project.FullName]; - if (type == Resources.rccDirKeyword && rccDirCache.Contains(project.FullName)) - return (string)rccDirCache[project.FullName]; - - QtCustomBuildTool tool = null; - string configName = null; - string platformName = null; - var vcpro = (VCProject)project.Object; - foreach (VCFile vcfile in (IVCCollection)vcpro.Files) { - var name = vcfile.Name; - if ((type == Resources.mocDirKeyword && HelperFunctions.IsHeaderFile(name)) - || (type == Resources.mocDirKeyword && HelperFunctions.IsMocFile(name)) - || (type == Resources.uicDirKeyword && HelperFunctions.IsUicFile(name)) - || (type == Resources.rccDirKeyword && HelperFunctions.IsQrcFile(name))) { - foreach (VCFileConfiguration config in (IVCCollection)vcfile.FileConfigurations) { - tool = new QtCustomBuildTool(config); - configName = config.Name.Remove(config.Name.IndexOf('|')); - var vcConfig = config.ProjectConfiguration as VCConfiguration; - var platform = vcConfig.Platform as VCPlatform; - platformName = platform.Name; - if (tool != null && (tool.CommandLine.IndexOf("moc.exe", StringComparison.OrdinalIgnoreCase) != -1 - || (tool.CommandLine.IndexOf("uic.exe", StringComparison.OrdinalIgnoreCase) != -1) - || (tool.CommandLine.IndexOf("rcc.exe", StringComparison.OrdinalIgnoreCase) != -1))) - break; - tool = null; - } - - if (tool != null) - break; - } - } - - if (tool != null) { - string dir = null; - var lastindex = tool.Outputs.LastIndexOf('\\'); - if (tool.Outputs.LastIndexOf('/') > lastindex) - lastindex = tool.Outputs.LastIndexOf('/'); - - if (lastindex == -1) - dir = "."; - else - dir = tool.Outputs.Substring(0, lastindex); - dir = dir.Replace("\"", ""); - - if (type == Resources.mocDirKeyword) { - int index; - if ((index = dir.IndexOf(configName, StringComparison.OrdinalIgnoreCase)) != -1) - dir = dir.Replace(dir.Substring(index, configName.Length), "$(ConfigurationName)"); - if ((index = dir.IndexOf(platformName, StringComparison.OrdinalIgnoreCase)) != -1) - dir = dir.Replace(dir.Substring(index, platformName.Length), "$(PlatformName)"); - - mocDirCache.Add(project.FullName, HelperFunctions.NormalizeRelativeFilePath(dir)); - } else if (type == Resources.uicDirKeyword) - uicDirCache.Add(project.FullName, HelperFunctions.NormalizeRelativeFilePath(dir)); - else if (type == Resources.rccDirKeyword) - rccDirCache.Add(project.FullName, HelperFunctions.NormalizeRelativeFilePath(dir)); - - cleanUpCache(project); - - return HelperFunctions.NormalizeRelativeFilePath(dir); - } - } catch { } - } - - return GetDirectory(type); - } - - private static string GetOption(EnvDTE.Project project, string type) - { - // check for directory in following order: - // - stored in project - // - globally defined default option - // - empty options - if (project != null && project.Globals.get_VariablePersists(type)) - return (string)project.Globals[type]; - return GetOption(type); - } - - private static bool GetBoolValue(EnvDTE.Project project, string type) - { - // check for directory in following order: - // - stored in project - // - globally defined default option - // - empty options - if (project != null && project.Globals.get_VariablePersists(type)) - return Convert.ToInt32(project.Globals[type] as string) > 0; - return GetBoolValue(type, false); - } - - private static void SaveDirectory(EnvDTE.Project project, string type, string dir) - { - dir = HelperFunctions.NormalizeRelativeFilePath(dir); - project.Globals[type] = dir; - if (!project.Globals.get_VariablePersists(type)) - project.Globals.set_VariablePersists(type, true); - - cleanUpCache(project); - } - - private static void SaveOption(EnvDTE.Project project, string type, string option) - { - project.Globals[type] = option; - if (!project.Globals.get_VariablePersists(type)) - project.Globals.set_VariablePersists(type, true); - } - - private static void SetBoolValue(EnvDTE.Project project, string type, bool value) - { - project.Globals[type] = Convert.ToInt32(value).ToString(); - if (!project.Globals.get_VariablePersists(type)) - project.Globals.set_VariablePersists(type, true); - } - - public static void SaveUicDirectory(string dir) - { - SaveDirectory(Resources.uicDirKeyword, dir); - } - - public static void SaveMocDirectory(string dir) - { - SaveDirectory(Resources.mocDirKeyword, dir); - } - - public static void SaveLUpdateOnBuild(bool val) - { - SetBoolValue(Resources.lupdateKeyword, val); - } - - public static void cleanUpCache(EnvDTE.Project project) - { - try { - var mocEnumerator = mocDirCache.GetEnumerator(); - while (mocEnumerator.MoveNext()) { - if (!HelperFunctions.IsProjectInSolution(project.DTE, (string)mocEnumerator.Key)) { - mocDirCache.Remove(mocEnumerator.Key); - mocEnumerator = mocDirCache.GetEnumerator(); - } - } - - var uicEnumerator = uicDirCache.GetEnumerator(); - while (uicEnumerator.MoveNext()) { - if (!HelperFunctions.IsProjectInSolution(project.DTE, (string)uicEnumerator.Key)) { - uicDirCache.Remove(uicEnumerator.Key); - uicEnumerator = uicDirCache.GetEnumerator(); - } - } - - var rccEnumerator = rccDirCache.GetEnumerator(); - while (rccEnumerator.MoveNext()) { - if (!HelperFunctions.IsProjectInSolution(project.DTE, (string)rccEnumerator.Key)) { - rccDirCache.Remove(rccEnumerator.Key); - rccEnumerator = rccDirCache.GetEnumerator(); - } - } - } catch { } - } - - private static void SaveDirectory(string type, string dir) - { - dir = HelperFunctions.NormalizeRelativeFilePath(dir); - var key = Registry.CurrentUser.CreateSubKey("SOFTWARE\\" + Resources.registryPackagePath); - if (key == null) - return; - key.SetValue(type, dir); - } - - private static void SaveOption(string type, string option) - { - var key = Registry.CurrentUser.CreateSubKey("SOFTWARE\\" + Resources.registryPackagePath); - if (key == null) - return; - if (option == null) - option = ""; - key.SetValue(type, option); + return QtVSIPSettingsShared.GetDirectory(Resources.uicDirKeyword); } public static bool AutoUpdateUicSteps() { - if (ValueExists("AutoUpdateUicSteps")) - return GetBoolValue("AutoUpdateUicSteps", true); - return GetBoolValue("AutoUpdateBuildSteps", true); - } - - private static bool GetBoolValue(string key, bool defaultValue) - { - var regKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\" + Resources.registryPackagePath); - if (regKey == null) - return defaultValue; - return ((int)regKey.GetValue(key, defaultValue ? 1 : 0)) > 0; - } - - private static bool ValueExists(string key) - { - var regKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\" + Resources.registryPackagePath); - if (regKey != null) { - foreach (var s in regKey.GetValueNames()) { - if (s == key) - return true; - } - } - return false; - } - - private static void SetBoolValue(string key, bool val) - { - var regKey = Registry.CurrentUser.CreateSubKey("SOFTWARE\\" + Resources.registryPackagePath); - if (regKey == null) - return; - regKey.SetValue(key, val ? 1 : 0); - } - - public static bool GetQmlDebug(EnvDTE.Project project) - { - return QtProject.Create(project).QmlDebug; - } - - public static void SaveQmlDebug(EnvDTE.Project project, bool enabled) - { - QtProject.Create(project).QmlDebug = enabled; + if (QtVSIPSettingsShared.ValueExists("AutoUpdateUicSteps")) + return QtVSIPSettingsShared.GetBoolValue("AutoUpdateUicSteps", true); + return QtVSIPSettingsShared.GetBoolValue("AutoUpdateBuildSteps", true); } } } diff --git a/QtVsTools.Core/QtVersionManager.cs b/QtVsTools.Core/QtVersionManager.cs index 000a198..15a3ae2 100644 --- a/QtVsTools.Core/QtVersionManager.cs +++ b/QtVsTools.Core/QtVersionManager.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,16 +26,14 @@ ** ****************************************************************************/ -using Microsoft.VisualStudio.VCProjectEngine; -using Microsoft.Win32; using System; using System.Collections; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading; -using QtVsTools.VisualStudio; -using EnvDTE; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; +using Microsoft.Win32; namespace QtVsTools.Core { @@ -45,37 +43,20 @@ public class QtVersionManager { private static QtVersionManager instance; - private string regVersionPath; - private string strVersionKey; + private readonly string regVersionPath; + private readonly string strVersionKey; private Hashtable versionCache; protected QtVersionManager() { strVersionKey = "Versions"; regVersionPath = Resources.registryVersionPath; - RefreshVersionNames(); } - void RefreshVersionNames() - { - var rootKeyPath = "SOFTWARE\\" + Resources.registryRootPath; - try { - using (var rootKey = Registry.CurrentUser.OpenSubKey(rootKeyPath, true)) - using (var versionsKey = rootKey.OpenSubKey(strVersionKey, true)) { - versionsKey.SetValue("VersionNames", string.Join(";", GetVersions())); - } + private static readonly EventWaitHandle packageInit = new EventWaitHandle(false, EventResetMode.ManualReset); + private static EventWaitHandle packageInitDone = null; - } catch (Exception e) { - Messages.Print( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); - } - } - - static EventWaitHandle - packageInit = new EventWaitHandle(false, EventResetMode.ManualReset), - packageInitDone = null; - - static public QtVersionManager The(EventWaitHandle initDone = null) + public static QtVersionManager The(EventWaitHandle initDone = null) { if (initDone == null) { packageInit.WaitOne(); @@ -92,10 +73,10 @@ public VersionInformation GetVersionInfo(string name) { - if (name == "$(DefaultQtVersion)") - name = GetDefaultVersion(); if (name == null) return null; + if (name == "$(DefaultQtVersion)") + name = GetDefaultVersion(); if (versionCache == null) versionCache = new Hashtable(); @@ -111,13 +92,8 @@ public VersionInformation GetVersionInfo(EnvDTE.Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); return GetVersionInfo(GetProjectQtVersion(project)); - } - - public void ClearVersionCache() - { - if (versionCache != null) - versionCache.Clear(); } public string[] GetVersions() @@ -130,13 +106,12 @@ if (qtDir == null) return null; - qtDir = qtDir.ToLower(); var versions = GetVersions(); foreach (var version in versions) { var installPath = GetInstallPath(version); if (installPath == null) continue; - if (installPath.ToLower() == qtDir) + if (installPath.Equals(qtDir, StringComparison.OrdinalIgnoreCase)) return version; } @@ -157,84 +132,61 @@ /// <summary> /// Check if all Qt versions are valid and readable. /// </summary> - /// Also sets the default Qt version to the newest version, if needed. /// <param name="errorMessage"></param> - /// <returns>true, if we found an invalid version</returns> - public bool HasInvalidVersions(out string errorMessage) + /// <returns>true, if there are one or more invalid Qt version</returns> + public bool HasInvalidVersions(out string errorMessage, out bool defaultVersionInvalid) { - var validVersions = new Dictionary<string, QtConfig>(); - var invalidVersions = new List<string>(); + var defaultVersion = GetDefaultVersionString(); + defaultVersionInvalid = string.IsNullOrEmpty(defaultVersion); - foreach (var v in GetVersions()) { - if (v == "$(DefaultQtVersion)") - continue; - - var vPath = GetInstallPath(v); - if (string.IsNullOrEmpty(vPath)) { - invalidVersions.Add(v); - continue; - } - - if (vPath.StartsWith("SSH:") || vPath.StartsWith("WSL:")) - continue; - - var qmakePath = Path.Combine(vPath, "bin", "qmake.exe"); - if (!File.Exists(qmakePath)) - qmakePath = Path.Combine(vPath, "qmake.exe"); - if (!File.Exists(qmakePath)) { - invalidVersions.Add(v); - continue; - } - - validVersions[v] = new QtConfig(vPath); - } - - if (invalidVersions.Count > 0) { - errorMessage = "These Qt version are inaccessible:\n"; - foreach (var invalidVersion in invalidVersions) - errorMessage += invalidVersion + " in " + GetInstallPath(invalidVersion) + "\n"; - errorMessage += "Make sure that you have read access to all files in your Qt directories."; - - // Is the default Qt version invalid? - var isDefaultQtVersionInvalid = false; - var defaultQtVersionName = GetDefaultVersion(); - if (string.IsNullOrEmpty(defaultQtVersionName)) { - isDefaultQtVersionInvalid = true; - } else { - foreach (var name in invalidVersions) { - if (name == defaultQtVersionName) { - isDefaultQtVersionInvalid = true; - break; - } - } - } - - // find the newest valid Qt version that can be used as default version - if (isDefaultQtVersionInvalid && validVersions.Count > 0) { - QtConfig defaultQtVersionConfig = null; - foreach (var vNameConfig in validVersions) { - var vName = vNameConfig.Key; - var v = vNameConfig.Value; - if (defaultQtVersionConfig == null) { - defaultQtVersionConfig = v; - defaultQtVersionName = vName; - continue; - } - if (defaultQtVersionConfig.VersionMajor < v.VersionMajor || - (defaultQtVersionConfig.VersionMajor == v.VersionMajor && (defaultQtVersionConfig.VersionMinor < v.VersionMinor || - (defaultQtVersionConfig.VersionMinor == v.VersionMinor && defaultQtVersionConfig.VersionPatch < v.VersionPatch)))) { - defaultQtVersionConfig = v; - defaultQtVersionName = vName; - } - } - if (defaultQtVersionConfig != null) - SaveDefaultVersion(defaultQtVersionName); - } - - return true; - } errorMessage = null; - return false; + foreach (var version in GetVersions()) { + if (version == "$(DefaultQtVersion)") + continue; + + var path = GetInstallPath(version); + if (path != null && (path.StartsWith("SSH:") || path.StartsWith("WSL:"))) + continue; + + if (string.IsNullOrEmpty(path) || !QMake.Exists(path)) { + errorMessage += version + " in " + path + "\n"; + defaultVersionInvalid |= version == defaultVersion; + } + + if (!string.IsNullOrEmpty(errorMessage)) { + errorMessage = "These Qt version are inaccessible:\n" + + errorMessage + + "Make sure that you have read access to all files in your Qt directories."; + } + } + return errorMessage != null; + } + + public void SetLatestQtVersionAsDefault() + { + var validVersions = new Dictionary<string, Version>(); + foreach (var version in GetVersions()) { + if (version == "$(DefaultQtVersion)") + continue; + + var path = GetInstallPath(version); + if (!string.IsNullOrEmpty(path) && QMake.Exists(path)) + validVersions[version] = new Version(new QtConfig(path).VersionString); + } + + if (validVersions.Count <= 0) + return; + + var defaultName = ""; + Version defaultVersion = null; + foreach (var tmp in validVersions) { + var version = tmp.Value; + if (defaultVersion == null || defaultVersion < version) { + defaultName = tmp.Key; + defaultVersion = version; + } + } + SaveDefaultVersion(defaultName); } public string GetInstallPath(string version) @@ -252,16 +204,14 @@ return Environment.GetEnvironmentVariable("QTDIR"); var key = root.OpenSubKey("SOFTWARE\\" + Resources.registryRootPath, false); - if (key == null) - return null; - var versionKey = key.OpenSubKey(strVersionKey + "\\" + version, false); - if (versionKey == null) - return null; - return (string)versionKey.GetValue("InstallDir"); + var versionKey = key?.OpenSubKey(strVersionKey + "\\" + version, false); + return versionKey?.GetValue("InstallDir") as string; } public string GetInstallPath(EnvDTE.Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + var version = GetProjectQtVersion(project); if (version == "$(DefaultQtVersion)") version = GetDefaultVersion(); @@ -309,7 +259,6 @@ versionKey.SetValue("InstallDir", dir); } } - RefreshVersionNames(); return true; } @@ -320,10 +269,9 @@ return; key.DeleteSubKey(versionName); key.Close(); - RefreshVersionNames(); } - private bool IsVersionAvailable(string version) + internal bool IsVersionAvailable(string version) { var versionAvailable = false; var versions = GetVersions(); @@ -338,13 +286,17 @@ public bool SaveProjectQtVersion(EnvDTE.Project project, string version) { + ThreadHelper.ThrowIfNotOnUIThread(); return SaveProjectQtVersion(project, version, project.ConfigurationManager.ActiveConfiguration.PlatformName); } public bool SaveProjectQtVersion(EnvDTE.Project project, string version, string platform) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!IsVersionAvailable(version) && version != "$(DefaultQtVersion)") return false; + if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings) { var vcPro = project.Object as VCProject; if (vcPro == null) @@ -365,6 +317,8 @@ public string GetProjectQtVersion(EnvDTE.Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + EnvDTE.Configuration config = null; try { config = project.ConfigurationManager.ActiveConfiguration; @@ -382,13 +336,15 @@ } if (version == null) - version = GetSolutionQtVersion(project.DTE.Solution); + version = Legacy.QtVersionManager.GetSolutionQtVersion(project.DTE.Solution); return version; } public string GetProjectQtVersion(EnvDTE.Project project, EnvDTE.Configuration config) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings) return QtProject.GetPropertyValue(project, config, "QtInstall"); @@ -402,6 +358,8 @@ public string GetProjectQtVersion(EnvDTE.Project project, string platform) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings) return GetProjectQtVersion(project); @@ -426,29 +384,6 @@ version = Environment.GetEnvironmentVariable(env); } } - } - - public bool SaveSolutionQtVersion(EnvDTE.Solution solution, string version) - { - if (!IsVersionAvailable(version) && version != "$(DefaultQtVersion)") - return false; - solution.Globals["Qt5Version"] = version; - if (!solution.Globals.get_VariablePersists("Qt5Version")) - solution.Globals.set_VariablePersists("Qt5Version", true); - return true; - } - - public string GetSolutionQtVersion(EnvDTE.Solution solution) - { - if (solution == null) - return null; - - if (solution.Globals.get_VariableExists("Qt5Version")) { - var version = (string)solution.Globals["Qt5Version"]; - return VerifyIfQtVersionExists(version) ? version : null; - } - - return null; } public string GetDefaultVersion() @@ -489,6 +424,25 @@ } } return VerifyIfQtVersionExists(defaultVersion) ? defaultVersion : null; + } + + public string GetDefaultVersionString() + { + string defaultVersion = null; + try { + var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\" + regVersionPath, false); + if (key != null) + defaultVersion = key.GetValue("DefaultQtVersion") as string; + } catch { + Messages.Print("Cannot read the default Qt version from registry."); + } + + if (defaultVersion == null) { + var qtDir = Environment.GetEnvironmentVariable("QTDIR"); + if (string.IsNullOrEmpty(qtDir)) + return defaultVersion; + } + return defaultVersion; } public bool SaveDefaultVersion(string version) @@ -540,7 +494,7 @@ } } - private bool VerifyIfQtVersionExists(string version) + internal bool VerifyIfQtVersionExists(string version) { if (version == "$(DefaultQtVersion)") version = GetDefaultVersion(); diff --git a/QtVsTools.Core/QtVsTools.Core.csproj b/QtVsTools.Core/QtVsTools.Core.csproj index c436e03..19e3727 100644 --- a/QtVsTools.Core/QtVsTools.Core.csproj +++ b/QtVsTools.Core/QtVsTools.Core.csproj @@ -69,36 +69,45 @@ // --> <ItemGroup> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + <Reference Include="PresentationFramework" /> <Reference Include="System" /> <Reference Include="System.Drawing" /> <Reference Include="System.Xml" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Windows.Forms" /> + <Reference Include="WindowsBase" /> </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - // Version specific references + // General package references // --> <Import Project="$(SolutionDir)\references.props" /> <ItemGroup> - <PackageReference Include="Microsoft.VisualStudio.SDK" - Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> - <PackageReference Include="Microsoft.VSSDK.BuildTools" - Version="$(Version_Microsoft_VSSDK_BuildTools)" /> - <PackageReference Include="Microsoft.Build" - Version="$(Version_Microsoft_Build)" /> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + <PackageReference Include="$(Name_Microsoft_Build)" Version="$(Version_Microsoft_Build)" /> </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='17.0'"> - <PackageReference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" - Version="$(Version_Microsoft_VisualStudio_VCProjectEngine)" /> - </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='16.0'"> - <PackageReference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" - Version="$(Version_Microsoft_VisualStudio_VCProjectEngine)" /> - </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='15.0'"> - <Reference Include="Microsoft.VisualStudio.VCProjectEngine" /> - </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" Version="$(Version_Microsoft_VisualStudio_VCProjectEngine)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + <Reference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" /> + </ItemGroup> + </When> + </Choose> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// // Solution project references @@ -117,6 +126,8 @@ <Compile Include="BuildConfig.cs" /> <Compile Include="CommandLineParser.cs" /> <Compile Include="Common\EnumExt.cs" /> + <Compile Include="Common\LazyFactory.cs" /> + <Compile Include="Common\QtVSIPSettingsShared.cs" /> <Compile Include="CompilerToolWrapper.cs" /> <Compile Include="CxxStreamReader.cs" /> <Compile Include="ExportProjectDialog.cs"> @@ -130,12 +141,16 @@ <Compile Include="ImageButton.cs"> <SubType>Component</SubType> </Compile> + <Compile Include="Legacy\QtProject.cs" /> + <Compile Include="Legacy\QtVersionManager.cs" /> + <Compile Include="Legacy\QtVSIPSettings.cs" /> <Compile Include="LinkerToolWrapper.cs" /> <Compile Include="MainWinWrapper.cs" /> <Compile Include="Messages.cs" /> <Compile Include="MocCmdChecker.cs" /> <Compile Include="MsBuildProject.cs" /> <Compile Include="Observable.cs" /> + <Compile Include="OutputWindowPane.cs" /> <Compile Include="ProFileContent.cs" /> <Compile Include="ProFileOption.cs" /> <Compile Include="ProjectExporter.cs" /> @@ -170,10 +185,12 @@ <Compile Include="RccOptions.cs" /> <Compile Include="Resources.cs" /> <Compile Include="SR.cs" /> - <Compile Include="TemplateType.cs" /> <Compile Include="VersionInformation.cs" /> + <Compile Include="VisualStudio\InfoBarMessage.cs" /> <Compile Include="VisualStudio\IProjectTracker.cs" /> + <Compile Include="VisualStudio\VsSearch.cs" /> <Compile Include="VisualStudio\VsServiceProvider.cs" /> + <Compile Include="VisualStudio\VsShell.cs" /> <Compile Include="WaitDialog.cs" /> <EmbeddedResource Include="ExportProjectDialog.resx"> <DependentUpon>ExportProjectDialog.cs</DependentUpon> @@ -188,4 +205,4 @@ </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> -</Project> +</Project> \ No newline at end of file diff --git a/QtVsTools.Core/RccOptions.cs b/QtVsTools.Core/RccOptions.cs index 44e8b2e..3d3dd48 100644 --- a/QtVsTools.Core/RccOptions.cs +++ b/QtVsTools.Core/RccOptions.cs @@ -26,8 +26,9 @@ ** ****************************************************************************/ -using Microsoft.VisualStudio.VCProjectEngine; using System; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; namespace QtVsTools.Core { @@ -57,6 +58,8 @@ { get { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project.Globals.get_VariablePersists("RccCompressFiles" + id) && (string)project.Globals["RccCompressFiles" + id] == "true") return true; @@ -64,6 +67,8 @@ } set { + ThreadHelper.ThrowIfNotOnUIThread(); + if (value) project.Globals["RccCompressFiles" + id] = "true"; else @@ -77,12 +82,16 @@ { get { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project.Globals.get_VariablePersists("RccCompressLevel" + id)) return Convert.ToInt32((string)project.Globals["RccCompressLevel" + id], 10); return 0; } set { + ThreadHelper.ThrowIfNotOnUIThread(); + project.Globals["RccCompressLevel" + id] = value.ToString(); if (!project.Globals.get_VariablePersists("RccCompressLevel" + id)) project.Globals.set_VariablePersists("RccCompressLevel" + id, true); @@ -93,12 +102,16 @@ { get { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project.Globals.get_VariablePersists("RccCompressThreshold" + id)) return Convert.ToInt32((string)project.Globals["RccCompressThreshold" + id], 10); return 0; } set { + ThreadHelper.ThrowIfNotOnUIThread(); + project.Globals["RccCompressThreshold" + id] = value.ToString(); if (!project.Globals.get_VariablePersists("RccCompressThreshold" + id)) project.Globals.set_VariablePersists("RccCompressThreshold" + id, true); diff --git a/QtVsTools.Core/Resources.cs b/QtVsTools.Core/Resources.cs index c8db0c9..79e97a0 100644 --- a/QtVsTools.Core/Resources.cs +++ b/QtVsTools.Core/Resources.cs @@ -100,18 +100,11 @@ public const int qtMinFormatVersion_PropertyEval = 303; // Project properties labels - public const string projLabelGlobals = "Globals"; public const string projLabelQtSettings = "QtSettings"; public const string uic4Command = "$(QTDIR)\\bin\\uic.exe"; public const string moc4Command = "$(QTDIR)\\bin\\moc.exe"; public const string rcc4Command = "$(QTDIR)\\bin\\rcc.exe"; - public const string lupdateCommand = "\\bin\\lupdate.exe"; - public const string lreleaseCommand = "\\bin\\lrelease.exe"; - - // All defined paths have to be relative to the project directory!!! - - public const string resourceDir = "Resources"; // If those directories do not equal to the project directory // they have to be added to the include directories for diff --git a/QtVsTools.Core/Resources.resx b/QtVsTools.Core/Resources.resx index 7861f15..ad354aa 100644 --- a/QtVsTools.Core/Resources.resx +++ b/QtVsTools.Core/Resources.resx @@ -123,9 +123,6 @@ <data name="OpenSolution" xml:space="preserve"> <value>Open Solution</value> </data> - <data name="ProjectExists" xml:space="preserve"> - <value>Project file already exists.</value> - </data> <data name="ExportProject_EditProjectFileManually" xml:space="preserve"> <value>qmake has generated a .vcproj file, but it needs to be converted. To do this you must open the .vcproj file manually. @@ -140,17 +137,13 @@ <value>Export to .pri File</value> </data> <data name="ExportProject_NoProjectsToExport" xml:space="preserve"> - <value>Cannot find any Qt 4 projects to export.</value> + <value>Cannot find any Qt projects to export.</value> </data> <data name="ExportProject_PriFileContainsSpaces" xml:space="preserve"> <value>The generated .pri file contains paths with spaces. You will not be able to import from this file. 1. Manually edit the generated .pri file. 2. Move your project to a location without spaces in the path. 3. Place the .pri file in another directory.</value> - </data> - <data name="ExportProject_ProjectExistsRegenerateOrReuse" xml:space="preserve"> - <value>{0} already exists. -Select 'Yes' to regenerate the file, and 'No' to use the existing one.</value> </data> <data name="ExportProject_ProjectOrSolutionCorrupt" xml:space="preserve"> <value>{0} @@ -216,12 +209,6 @@ <data name="QtProject_CannotRemoveMocStep" xml:space="preserve"> <value>Cannot remove a moc step from file {0}</value> </data> - <data name="QtProject_CannotAddFilter" xml:space="preserve"> - <value>Project cannot add filter {0}</value> - </data> - <data name="QtProject_CannotAddFile" xml:space="preserve"> - <value>Cannot add file {0} to filter.</value> - </data> <data name="QtProject_CannotRemoveFile" xml:space="preserve"> <value>Cannot remove file {0} from filter.</value> </data> @@ -238,25 +225,9 @@ <data name="QtProject_ProjectCannotAddResourceFilter" xml:space="preserve"> <value>Cannot add a resource filter.</value> </data> - <data name="QtProject_CannotCreateResourceDir" xml:space="preserve"> - <value>Cannot create a resource directory.</value> - </data> <data name="QtProject_CannotAdjustWhitespaces" xml:space="preserve"> <value>Cannot adjust whitespace or tabs in file (write). ({0})</value> - </data> - <data name="QtProject_CannotReplaceTokenRead" xml:space="preserve"> - <value>Cannot replace token ({0} -> {1}) in file (read). -({3})</value> - </data> - <data name="QtProject_CannotReplaceTokenWrite" xml:space="preserve"> - <value>Cannot replace token ({0} -> {1}) in file (write). -({3})</value> - </data> - <data name="QtProject_FileExistsInProjectFolder" xml:space="preserve"> - <value>The file {0} exists in your project folder. Qt VS Tools will overwrite the existing file. - -Select 'Yes' to overwrite, select 'No' to keep the existing file and automatically add it to the project.</value> </data> <data name="QtVersionManager_CannotLoadQtVersion" xml:space="preserve"> <value>Cannot load the default Qt version.</value> @@ -276,9 +247,6 @@ <data name="Resources_ResourceFiles" xml:space="preserve"> <value>Resource Files</value> </data> - <data name="Resources_TranslationFiles" xml:space="preserve"> - <value>Translation Files</value> - </data> <data name="Resources_GeneratedFiles" xml:space="preserve"> <value>Generated Files</value> </data> @@ -287,12 +255,6 @@ </data> <data name="QtProject_CannotAccessUserFile" xml:space="preserve"> <value>Could not add QTDIR to {0}'s .user file.</value> - </data> - <data name="ImportProject_CannotConvertProject" xml:space="preserve"> - <value>Could not convert project file {0} to Qt/MSBuild.</value> - </data> - <data name="Resources_OtherFiles" xml:space="preserve"> - <value>Other Files</value> </data> <data name="WaitDialogRefreshMoc" xml:space="preserve"> <value>Updating moc steps...</value> diff --git a/QtVsTools.Core/SR.cs b/QtVsTools.Core/SR.cs index ef66800..d5ed78b 100644 --- a/QtVsTools.Core/SR.cs +++ b/QtVsTools.Core/SR.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,10 +26,7 @@ ** ****************************************************************************/ -using System; -using System.Globalization; using System.Resources; -using System.Threading; namespace QtVsTools.Core { @@ -37,7 +34,7 @@ { static SR loader; readonly ResourceManager resources; - static readonly Object obj = new Object(); + static readonly object obj = new object(); internal SR() { @@ -52,20 +49,7 @@ loader = new SR(); } } - return loader; - } - - private static CultureInfo Culture - { - get { return null/*use ResourceManager default, CultureInfo.CurrentUICulture*/; } - //get { return new CultureInfo("de-DE"); } - } - - public static string LanguageName - { - get { return Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName; } - //get { return Culture.TwoLetterISOLanguageName; } } public static string GetString(string name, params object[] args) @@ -73,19 +57,16 @@ var sys = GetLoader(); if (sys == null) return null; - var res = sys.resources.GetString(name, Culture); - if (args != null && args.Length > 0) + var res = sys.resources.GetString(name, null); + if (args != null && args.Length > 0 && !string.IsNullOrEmpty(res)) return string.Format(res, args); return res; } public static string GetString(string name) { - var sys = GetLoader(); - if (sys == null) - return null; - return sys.resources.GetString(name, Culture); + return GetString(name, null); } } } diff --git a/QtVsTools.Core/VersionInformation.cs b/QtVsTools.Core/VersionInformation.cs index fd8cc1a..12d6c81 100644 --- a/QtVsTools.Core/VersionInformation.cs +++ b/QtVsTools.Core/VersionInformation.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -34,6 +34,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; +using Microsoft.VisualStudio.Shell; namespace QtVsTools.Core { @@ -42,11 +43,10 @@ { //fields public string name; - public string qtDir; + public readonly string qtDir; public uint qtMajor; // X in version x.y.z public uint qtMinor; // Y in version x.y.z public uint qtPatch; // Z in version x.y.z - public bool qt5Version = true; private QtConfig qtConfig; private QMakeConf qmakeConf; private string vsPlatformName; @@ -79,18 +79,18 @@ _cache.Clear(); } - Dictionary<string, bool> _IsModuleAvailable; + readonly Dictionary<string, bool> _IsModuleAvailable; public bool IsModuleAvailable(string module) { return _IsModuleAvailable?[module] ?? false; } - public string VC_MinimumVisualStudioVersion { get; private set; } - public string VC_ApplicationTypeRevision { get; private set; } - public string VC_WindowsTargetPlatformMinVersion { get; private set; } - public string VC_WindowsTargetPlatformVersion { get; private set; } - public string VC_Link_TargetMachine { get; private set; } - public string VC_PlatformToolset { get; private set; } + public string VC_MinimumVisualStudioVersion { get; } + public string VC_ApplicationTypeRevision { get; } + public string VC_WindowsTargetPlatformMinVersion { get; } + public string VC_WindowsTargetPlatformVersion { get; } + public string VC_Link_TargetMachine { get; } + private string VC_PlatformToolset { get; } private VersionInformation(string qtDirIn) { @@ -128,7 +128,6 @@ qtMinor = (version >> 8) & 0xFF; qtPatch = version & 0xFF; } - qt5Version = (qtMajor == 5); try { QtInstallDocs = qmakeQuery["QT_INSTALL_DOCS"]; @@ -143,7 +142,7 @@ var tempProData = new StringBuilder(); tempProData.AppendLine("SOURCES = main.cpp"); - var modules = QtModules.Instance.GetAvailableModules() + var modules = QtModules.Instance.GetAvailableModules(qtMajor) .Where((QtModule mi) => mi.Selectable); foreach (QtModule mi in modules) { @@ -194,7 +193,7 @@ public string QtInstallDocs { - get; private set; + get; } public string QMakeSpecDirectory diff --git a/QtVsTools.Core/VisualStudio/InfoBarMessage.cs b/QtVsTools.Core/VisualStudio/InfoBarMessage.cs new file mode 100644 index 0000000..b5572b0 --- /dev/null +++ b/QtVsTools.Core/VisualStudio/InfoBarMessage.cs @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Diagnostics; +using System.Linq; +using Microsoft.VisualStudio.Imaging.Interop; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace QtVsTools.VisualStudio +{ + using Common; + + public abstract class InfoBarMessage + { + protected abstract ImageMoniker Icon { get; } + protected abstract TextSpan[] Text { get; } + protected abstract Hyperlink[] Hyperlinks { get; } + + protected class TextSpan + { + public string Text { get; set; } + public bool Bold { get; set; } + public bool Italic { get; set; } + public bool Underline { get; set; } + public static implicit operator TextSpan(string text) => new TextSpan { Text = text }; + } + + protected class TextSpacer : TextSpan + { + public TextSpacer(int spaces) + { + Text = new string(' ', spaces); + } + } + + protected class Hyperlink + { + public string Text { get; set; } + public bool CloseInfoBar { get; set; } + public Action OnClicked { get; set; } + } + + private MessageUI UI { get; set; } + + public InfoBarMessage() + { + UI = new MessageUI { Message = this }; + } + + public virtual void Show() + { + ThreadHelper.ThrowIfNotOnUIThread(); + UI.Show(); + } + + public virtual void Close() + { + ThreadHelper.ThrowIfNotOnUIThread(); + UI.Close(); + } + + public bool IsOpen => UI.IsOpen; + + protected virtual void OnClosed() + { } + + private class MessageUI : IVsInfoBarUIEvents + { + static LazyFactory StaticLazy { get; } = new LazyFactory(); + static IVsInfoBarUIFactory Factory => StaticLazy.Get(() => + Factory, () => VsServiceProvider + .GetService<SVsInfoBarUIFactory, IVsInfoBarUIFactory>()); + + private IVsInfoBarUIElement UIElement { get; set; } + private uint eventNotificationCookie; + + public bool IsOpen => UIElement != null; + + public InfoBarMessage Message { get; set; } + + public void Show() + { + ThreadHelper.ThrowIfNotOnUIThread(); + if (Factory == null) + return; + if (UIElement != null) // Message already shown + return; + var textSpans = Enumerable.Empty<InfoBarTextSpan>(); + if (Message.Text != null) { + textSpans = Message.Text + .Select(x => new InfoBarTextSpan(x.Text, x.Bold, x.Italic, x.Underline)); + } + var hyperlinks = Enumerable.Empty<InfoBarHyperlink>(); + if (Message.Hyperlinks != null) { + hyperlinks = Message.Hyperlinks + .Select(x => new InfoBarHyperlink(x.Text, x)); + } + var model = new InfoBarModel(textSpans, hyperlinks, Message.Icon, true); + UIElement = Factory.CreateInfoBar(model); + if (UIElement != null) { + UIElement.Advise(this, out eventNotificationCookie); + VsShell.InfoBarHost?.AddInfoBar(UIElement); + } + } + + public void Close() + { + ThreadHelper.ThrowIfNotOnUIThread(); + UIElement?.Close(); + } + + void IVsInfoBarUIEvents.OnActionItemClicked( + IVsInfoBarUIElement infoBarUIElement, + IVsInfoBarActionItem actionItem) + { + ThreadHelper.ThrowIfNotOnUIThread(); + Debug.Assert(infoBarUIElement == UIElement); + var hyperlink = actionItem.ActionContext as Hyperlink; + if (hyperlink == null) + return; + if (hyperlink.CloseInfoBar) + Close(); + hyperlink.OnClicked(); + } + + void IVsInfoBarUIEvents.OnClosed(IVsInfoBarUIElement infoBarUIElement) + { + ThreadHelper.ThrowIfNotOnUIThread(); + Debug.Assert(infoBarUIElement == UIElement); + if (UIElement != null) { + UIElement.Unadvise(eventNotificationCookie); + UIElement = null; + eventNotificationCookie = 0; + Message.OnClosed(); + } + } + } + } +} diff --git a/QtVsTools.Core/VisualStudio/VsSearch.cs b/QtVsTools.Core/VisualStudio/VsSearch.cs new file mode 100644 index 0000000..1a79603 --- /dev/null +++ b/QtVsTools.Core/VisualStudio/VsSearch.cs @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Controls; +using System.Windows.Data; +using Microsoft.Internal.VisualStudio.PlatformUI; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.PlatformUI; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace QtVsTools.VisualStudio +{ + public class SearchTask : VsSearchTask + { + private readonly Action _clearCallback = null; + private readonly Func<IEnumerable<string>, uint> _searchCallBack = null; + + public SearchTask(uint cookie, IVsSearchQuery query, IVsSearchCallback callback, + Action clearCallback, Func<IEnumerable<string>, uint> searchCallBack) + : base(cookie, query, callback) + { + _clearCallback = clearCallback; + _searchCallBack = searchCallBack; + } + + protected override void OnStartSearch() + { + ErrorCode = VSConstants.S_OK; + try { + _ = ThreadHelper.JoinableTaskFactory.RunAsync(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + if (TaskStatus != VSConstants.VsSearchTaskStatus.Stopped) { + SearchResults = _searchCallBack( + SearchUtilities.ExtractSearchTokens(SearchQuery).Select(token => + { + ThreadHelper.ThrowIfNotOnUIThread(); + return token.ParsedTokenText; + }) + ); + } else if (TaskStatus == VSConstants.VsSearchTaskStatus.Stopped) { + _clearCallback(); + } + }); + } catch { + ErrorCode = VSConstants.E_FAIL; + } + base.OnStartSearch(); + } + + protected override void OnStopSearch() + { + SearchResults = 0; + } + } + + public abstract class VsWindowSearch : IVsWindowSearch + { + public abstract IVsSearchTask CreateSearch(uint cookie, IVsSearchQuery query, + IVsSearchCallback callback); + + public virtual void ClearSearch() + {} + + public virtual void ProvideSearchSettings(IVsUIDataSource settings) + { + Utilities.SetValue(settings, SearchSettingsDataSource.PropertyNames.ControlMaxWidth, + (uint)10000); + Utilities.SetValue(settings, SearchSettingsDataSource.PropertyNames.SearchStartType, + (uint)VSSEARCHSTARTTYPE.SST_INSTANT); + } + + public virtual bool OnNavigationKeyDown(uint dwNavigationKey, uint dwModifiers) => false; + + public virtual bool SearchEnabled => true; + + public virtual Guid Category => Guid.Empty; + + public virtual IVsEnumWindowSearchFilters SearchFiltersEnum => null; + + public virtual IVsEnumWindowSearchOptions SearchOptionsEnum => null; + } + + public class ListBoxSearch : VsWindowSearch + { + private readonly ListBox _listBox = null; + private Action<string> _setSearchText = null; + + public ListBoxSearch(ListBox listBox, Action<string> action) + { + _listBox = listBox; + _setSearchText = action; + } + + public override IVsSearchTask CreateSearch(uint cookie, IVsSearchQuery query, + IVsSearchCallback callback) + { + return new SearchTask(cookie, query, callback, ClearSearch, + searchCallBack: (IEnumerable<string> tokens) => + { + _setSearchText(string.Join(" ", tokens)); + var view = CollectionViewSource.GetDefaultView(_listBox.ItemsSource); + + view.Refresh(); + if (_listBox.Items.Count == 1 || _listBox.SelectedItem == null) + _listBox.SelectedIndex = 0; + return (uint)view.Cast<object>().Count(); + }); + } + + public override void ClearSearch() + { + _setSearchText(string.Empty); + CollectionViewSource.GetDefaultView(_listBox.ItemsSource).Refresh(); + } + } +} diff --git a/QtVsTools.Core/VisualStudio/VsServiceProvider.cs b/QtVsTools.Core/VisualStudio/VsServiceProvider.cs index ed53ed5..d9060ed 100644 --- a/QtVsTools.Core/VisualStudio/VsServiceProvider.cs +++ b/QtVsTools.Core/VisualStudio/VsServiceProvider.cs @@ -26,7 +26,6 @@ ** ****************************************************************************/ -using Microsoft.VisualStudio.Shell; using System; using System.Collections.Concurrent; using System.Threading.Tasks; @@ -45,7 +44,7 @@ { public static IVsServiceProvider Instance { get; set; } - static ConcurrentDictionary<ServiceType, object> services + static readonly ConcurrentDictionary<ServiceType, object> services = new ConcurrentDictionary<ServiceType, object>(); public static I GetService<I>() @@ -61,8 +60,7 @@ if (Instance == null) return null; - object serviceObj; - if (services.TryGetValue(new ServiceType(typeof(T), typeof(I)), out serviceObj)) + if (services.TryGetValue(new ServiceType(typeof(T), typeof(I)), out object serviceObj)) return serviceObj as I; var serviceInterface = Instance.GetService<T, I>(); @@ -83,8 +81,7 @@ if (Instance == null) return null; - object serviceObj; - if (services.TryGetValue(new ServiceType(typeof(T), typeof(I)), out serviceObj)) + if (services.TryGetValue(new ServiceType(typeof(T), typeof(I)), out object serviceObj)) return serviceObj as I; var serviceInterface = await Instance.GetServiceAsync<T, I>(); diff --git a/QtVsTools.Core/VisualStudio/VsShell.cs b/QtVsTools.Core/VisualStudio/VsShell.cs new file mode 100644 index 0000000..1bccafc --- /dev/null +++ b/QtVsTools.Core/VisualStudio/VsShell.cs @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace QtVsTools.VisualStudio +{ + public static class VsShell + { + public static string InstallRootDir + { + get + { + ThreadHelper.ThrowIfNotOnUIThread(); + + Initialize(); + return _InstallRootDir; + } + } + + private static IVsShell vsShell; + private static string _InstallRootDir; + + private static void Initialize() + { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (vsShell != null) + return; + vsShell = VsServiceProvider.GetService<IVsShell>(); + + int res = vsShell.GetProperty((int)__VSSPROPID2.VSSPROPID_InstallRootDir, out object o); + if (res == VSConstants.S_OK && o is string property) + _InstallRootDir = property; + } + + public static EnvDTE.Project GetProject(IVsHierarchy context) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + int res = context.GetProperty( + (uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_ExtObject, out object value); + if (res == VSConstants.S_OK && value is EnvDTE.Project project) + return project; + return null; + } + + public static EnvDTE.ProjectItem GetProjectItem(IVsHierarchy context, uint itemid) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + int res = context.GetProperty( + itemid, (int)__VSHPROPID.VSHPROPID_ExtObject, out object value); + if (res == VSConstants.S_OK && value is EnvDTE.ProjectItem item) + return item; + return null; + } + + public static EnvDTE.Document GetDocument(IVsHierarchy context, uint itemid) + { + ThreadHelper.ThrowIfNotOnUIThread(); + return GetProjectItem(context, itemid)?.Document; + } + + private static IVsInfoBarHost _InfoBarHost = null; + public static IVsInfoBarHost InfoBarHost + { + get + { + ThreadHelper.ThrowIfNotOnUIThread(); + if (_InfoBarHost != null) + return _InfoBarHost; + Initialize(); + object host = null; + vsShell?.GetProperty((int)__VSSPROPID7.VSSPROPID_MainWindowInfoBarHost, out host); + return _InfoBarHost = host as IVsInfoBarHost; + } + } + } +} diff --git a/QtVsTools.Core/WaitDialog.cs b/QtVsTools.Core/WaitDialog.cs index cff8851..60a6adc 100644 --- a/QtVsTools.Core/WaitDialog.cs +++ b/QtVsTools.Core/WaitDialog.cs @@ -27,25 +27,21 @@ ****************************************************************************/ using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Windows.Forms; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.VCProjectEngine; -using QtVsTools.VisualStudio; namespace QtVsTools.Core { + using VisualStudio; + public class WaitDialog : IDisposable { static IVsThreadedWaitDialogFactory factory = null; - public IVsThreadedWaitDialog2 VsWaitDialog { get; private set; } + private IVsThreadedWaitDialog2 VsWaitDialog { get; set; } - public bool Running { get; private set; } + private bool Running { get; set; } bool? vsDialogCanceled = null; @@ -53,14 +49,15 @@ { get { + ThreadHelper.ThrowIfNotOnUIThread(); + if (vsDialogCanceled.HasValue) return vsDialogCanceled.Value; if (VsWaitDialog == null) return false; - bool canceled = false; - int res = VsWaitDialog.HasCanceled(out canceled); + int res = VsWaitDialog.HasCanceled(out bool canceled); if (res != VSConstants.S_OK) return false; @@ -76,6 +73,8 @@ static WaitDialog Create(IVsThreadedWaitDialogFactory dialogFactory) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (factory == null) { factory = dialogFactory ?? VsServiceProvider .GetService<SVsThreadedWaitDialogFactory, IVsThreadedWaitDialogFactory>(); @@ -83,8 +82,7 @@ return null; } - IVsThreadedWaitDialog2 vsWaitDialog = null; - factory.CreateInstance(out vsWaitDialog); + factory.CreateInstance(out IVsThreadedWaitDialog2 vsWaitDialog); if (vsWaitDialog == null) return null; @@ -105,6 +103,8 @@ bool showMarqueeProgress = true, IVsThreadedWaitDialogFactory dialogFactory = null) { + ThreadHelper.ThrowIfNotOnUIThread(); + var dialog = Create(dialogFactory); if (dialog == null) return null; @@ -129,6 +129,8 @@ bool isCancelable = false, IVsThreadedWaitDialogFactory dialogFactory = null) { + ThreadHelper.ThrowIfNotOnUIThread(); + var dialog = Create(dialogFactory); if (dialog == null) return null; @@ -151,12 +153,13 @@ string statusBarText = null, bool disableCancel = false) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!Running) return; - bool canceled = false; int res = VsWaitDialog.UpdateProgress(message, progressText, - statusBarText, currentStep, totalSteps, disableCancel, out canceled); + statusBarText, currentStep, totalSteps, disableCancel, out bool canceled); if (res != VSConstants.S_OK) return; @@ -167,18 +170,22 @@ public void Stop() { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!Running) return; Running = false; - int canceled = 0; - VsWaitDialog.EndWaitDialog(out canceled); + VsWaitDialog.EndWaitDialog(out int canceled); Canceled = (canceled != 0); } void IDisposable.Dispose() { - Stop(); + ThreadHelper.JoinableTaskFactory.Run(async () => { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + Stop(); + }); } } } diff --git a/QtVsTools.Package/Common/Concurrent.cs b/QtVsTools.Package/Common/Concurrent.cs index d1426f4..c963968 100644 --- a/QtVsTools.Package/Common/Concurrent.cs +++ b/QtVsTools.Package/Common/Concurrent.cs @@ -40,12 +40,9 @@ public abstract class Concurrent<TSubClass> where TSubClass : Concurrent<TSubClass> { - private static readonly object _StaticCriticalSection = new object(); - protected static object StaticCriticalSection => _StaticCriticalSection; + protected static object StaticCriticalSection { get; } = new object(); - private object _CriticalSection = null; - protected object CriticalSection => - StaticThreadSafeInit(() => _CriticalSection, () => _CriticalSection = new object()); + protected object CriticalSection { get; } = new object(); protected T ThreadSafeInit<T>(Func<T> getValue, Action init) where T : class diff --git a/QtVsTools.Package/Common/ConcurrentStopwatch.cs b/QtVsTools.Package/Common/ConcurrentStopwatch.cs index 82547e0..35f78b3 100644 --- a/QtVsTools.Package/Common/ConcurrentStopwatch.cs +++ b/QtVsTools.Package/Common/ConcurrentStopwatch.cs @@ -33,7 +33,7 @@ { public class ConcurrentStopwatch : Concurrent<ConcurrentStopwatch> { - Stopwatch Stopwatch { get; set; } + Stopwatch Stopwatch { get; } public ConcurrentStopwatch() { diff --git a/QtVsTools.Package/Common/Json/DeferredObject.cs b/QtVsTools.Package/Common/Json/DeferredObject.cs index 9ecc47b..d8c2a06 100644 --- a/QtVsTools.Package/Common/Json/DeferredObject.cs +++ b/QtVsTools.Package/Common/Json/DeferredObject.cs @@ -26,8 +26,6 @@ ** ****************************************************************************/ -using System; -using System.Collections.Generic; using System.Runtime.Serialization; namespace QtVsTools.Json diff --git a/QtVsTools.Package/Common/Json/Serializable.cs b/QtVsTools.Package/Common/Json/Serializable.cs index 2d2b990..32e02b4 100644 --- a/QtVsTools.Package/Common/Json/Serializable.cs +++ b/QtVsTools.Package/Common/Json/Serializable.cs @@ -48,7 +48,7 @@ { #region //////////////////// Prototype //////////////////////////////////////////////////// - protected Serializer Serializer { get; set; } + private Serializer Serializer { get; set; } protected Serializable() { } @@ -192,9 +192,11 @@ var container = toDo.Dequeue(); foreach (var defObj in container.PendingObjects) { defObj.Deserialize(); - var subContainer = defObj.Object as IDeferredObjectContainer; - if (subContainer != null && subContainer.PendingObjects.Any()) + if (defObj.Object is IDeferredObjectContainer subContainer + && subContainer.PendingObjects.Any()) { toDo.Enqueue(subContainer); + + } } } return obj; diff --git a/QtVsTools.Package/Common/Json/SerializableEnum.cs b/QtVsTools.Package/Common/Json/SerializableEnum.cs index 6493668..832c42c 100644 --- a/QtVsTools.Package/Common/Json/SerializableEnum.cs +++ b/QtVsTools.Package/Common/Json/SerializableEnum.cs @@ -27,7 +27,6 @@ ****************************************************************************/ using System; -using System.ComponentModel; using System.Linq; using System.Reflection; @@ -106,7 +105,7 @@ class EnumStringAttribute : Attribute { - public string ValueString { get; private set; } + public string ValueString { get; } public EnumStringAttribute(string enumValueString) { diff --git a/QtVsTools.Package/Common/Json/Serializer.cs b/QtVsTools.Package/Common/Json/Serializer.cs index d263207..8121eed 100644 --- a/QtVsTools.Package/Common/Json/Serializer.cs +++ b/QtVsTools.Package/Common/Json/Serializer.cs @@ -36,6 +36,7 @@ using System.Runtime.Serialization.Json; using System.Text; using System.Xml; +using QtVsTools.Core; /// <summary> /// The classes in this namespace provide support to the serialization and deserialization of @@ -127,11 +128,10 @@ serializer.WriteObject(writer, obj); writer.Close(); return new JsonData() { Stream = stream }; - } catch (Exception e) { + } catch (Exception exception) { + exception.Log(); if (stream != null && stream.CanRead && stream.Length > 0) stream.Dispose(); - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); return null; } } @@ -151,16 +151,14 @@ using (reader = XmlReader.Create(data.XmlStream)) { var obj = serializer.ReadObject(reader, false); - var container = obj as IDeferredObjectContainer; - if (container != null) + if (obj is IDeferredObjectContainer container) deferredObjects.ForEach(x => container.Add(x)); return obj; } - } catch (Exception e) { - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); return null; } finally { @@ -206,9 +204,8 @@ data.XmlStream = new MemoryStream(xmlData); } return true; - } catch (Exception e) { - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); return false; } } @@ -245,9 +242,9 @@ #region //////////////////// Data Contract Surrogate ////////////////////////////////////// - static Exclusive<Serializer> sharedInstance = new Exclusive<Serializer>(); + static readonly Exclusive<Serializer> sharedInstance = new Exclusive<Serializer>(); private XmlReader reader = null; - private List<IDeferredObject> deferredObjects = new List<IDeferredObject>(); + private readonly List<IDeferredObject> deferredObjects = new List<IDeferredObject>(); public static IJsonData GetCurrentJsonData() { @@ -260,9 +257,8 @@ root.Append("</root>"); var xmlData = Encoding.UTF8.GetBytes(root.ToString()); return new JsonData { XmlStream = new MemoryStream(xmlData) }; - } catch (Exception e) { - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); return null; } } diff --git a/QtVsTools.Package/Common/NativeAPI.cs b/QtVsTools.Package/Common/NativeAPI.cs index 155db09..4cf3ba9 100644 --- a/QtVsTools.Package/Common/NativeAPI.cs +++ b/QtVsTools.Package/Common/NativeAPI.cs @@ -127,12 +127,12 @@ szTypeName = ""; } public IntPtr hIcon; - public int iIcon; - public uint dwAttributes; + private readonly int iIcon; + private readonly uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string szDisplayName; + private readonly string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_TYPE)] - public string szTypeName; + private readonly string szTypeName; }; [Flags] diff --git a/QtVsTools.Package/Common/PriorityQueue.cs b/QtVsTools.Package/Common/PriorityQueue.cs index cdc57e7..af8fffd 100644 --- a/QtVsTools.Package/Common/PriorityQueue.cs +++ b/QtVsTools.Package/Common/PriorityQueue.cs @@ -51,8 +51,8 @@ public abstract class BasePriorityQueue<T, TPriority> : Concurrent, IEnumerable<T> where TPriority : IComparable<TPriority> { - SortedDictionary<TPriority, T> ItemsByPriority { get; set; } - Dictionary<object, TPriority> ItemPriority { get; set; } + SortedDictionary<TPriority, T> ItemsByPriority { get; } + Dictionary<object, TPriority> ItemPriority { get; } T Head { get; set; } public int Count { get; private set; } public bool IsEmpty => (Count == 0); @@ -61,7 +61,7 @@ IEnumerator<T> IEnumerable<T>.GetEnumerator() => Items.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => Items.GetEnumerator(); - Func<T, object> GetItemKey { get; set; } + Func<T, object> GetItemKey { get; } public BasePriorityQueue() : this(x => x) { } @@ -102,11 +102,10 @@ if (item == null) throw new InvalidOperationException("Item cannot be null."); lock (CriticalSection) { - T oldItem; - if (ItemsByPriority.TryGetValue(priority, out oldItem) && !item.Equals(oldItem)) + if (ItemsByPriority.TryGetValue(priority, out T oldItem) && !item.Equals(oldItem)) throw new InvalidOperationException("An item with the same priority exists."); - TPriority oldPriority; - if (ItemPriority.TryGetValue(GetItemKey(item), out oldPriority)) { + + if (ItemPriority.TryGetValue(GetItemKey(item), out TPriority oldPriority)) { ItemsByPriority.Remove(oldPriority); --Count; } @@ -128,8 +127,7 @@ public T Peek() { lock (CriticalSection) { - T result; - if (!TryPeek(out result)) + if (!TryPeek(out T result)) throw new InvalidOperationException("Queue is empty."); return result; } @@ -167,8 +165,7 @@ public T Dequeue() { lock (CriticalSection) { - T result; - if (!TryDequeue(out result)) + if (!TryDequeue(out T result)) throw new InvalidOperationException("Queue is empty."); return result; } diff --git a/QtVsTools.Package/Common/Prototyped.cs b/QtVsTools.Package/Common/Prototyped.cs index cba7019..94bd14b 100644 --- a/QtVsTools.Package/Common/Prototyped.cs +++ b/QtVsTools.Package/Common/Prototyped.cs @@ -134,7 +134,7 @@ static readonly object classCriticalSection = new object(); - static Dictionary<Type, List<Type>> types = GetTypeHierarchy(typeof(TBase)); + static readonly Dictionary<Type, List<Type>> types = GetTypeHierarchy(typeof(TBase)); static Dictionary<Type, List<Type>> GetTypeHierarchy(Type baseType) { @@ -174,7 +174,7 @@ return subTypes; } - static Dictionary<Type, SubClass> classes = types + static readonly Dictionary<Type, SubClass> classes = types .ToDictionary(x => x.Key, x => Create(x.Key, x.Value)); static SubClass Create(Type type, IEnumerable<Type> subTypes) @@ -194,8 +194,7 @@ lock (classCriticalSection) { - SubClass subClass = null; - if (!classes.TryGetValue(type, out subClass)) { + if (!classes.TryGetValue(type, out SubClass subClass)) { var newTypes = GetTypeHierarchy(type) .Where(x => !classes.ContainsKey(x.Key)); @@ -213,7 +212,7 @@ } } - public static SubClass baseClass = Get(typeof(TBase)); + public static readonly SubClass baseClass = Get(typeof(TBase)); } #endregion //////////////////// SubClass ////////////////////////////////////////////////// diff --git a/QtVsTools.Package/Common/Timestamp.cs b/QtVsTools.Package/Common/Timestamp.cs index deaf18a..cf3155e 100644 --- a/QtVsTools.Package/Common/Timestamp.cs +++ b/QtVsTools.Package/Common/Timestamp.cs @@ -30,8 +30,12 @@ namespace QtVsTools { + using Common; + public class Timestamp : Concurrent<Timestamp> { + static LazyFactory StaticLazy { get; } = new LazyFactory(); + long LastTimestamp { get; set; } long GetStrictMonotonicTimestamp() { @@ -43,9 +47,8 @@ } } - static Timestamp _Instance; - static Timestamp Instance => - StaticThreadSafeInit(() => _Instance, () => _Instance = new Timestamp()); + static Timestamp Instance => StaticLazy.Get(() => + Instance, () => new Timestamp()); public static long Next() { diff --git a/QtVsTools.Package/Editors/Editor.QtDesigner.cs b/QtVsTools.Package/Editors/Editor.QtDesigner.cs index 518bd6c..73148b0 100644 --- a/QtVsTools.Package/Editors/Editor.QtDesigner.cs +++ b/QtVsTools.Package/Editors/Editor.QtDesigner.cs @@ -31,12 +31,15 @@ using System.IO; using System.Runtime.InteropServices; using System.Threading.Tasks; -using Microsoft.VisualStudio.Shell.Interop; -using QtVsTools.QtMsBuild; -using QtVsTools.VisualStudio; +using Microsoft.VisualStudio.Shell; + +using Task = System.Threading.Tasks.Task; namespace QtVsTools.Editors { + using QtMsBuild; + using VisualStudio; + [Guid(GuidString)] public class QtDesigner : Editor { @@ -58,27 +61,31 @@ protected override void OnStart(Process process) { + ThreadHelper.ThrowIfNotOnUIThread(); + base.OnStart(process); var document = VsShell.GetDocument(Context, ItemId); if (document == null) return; + var project = document.ProjectItem?.ContainingProject; - if (project == null || !QtProjectTracker.IsTracked(project)) + if (project == null || !QtProjectTracker.IsTracked(project.FullName)) return; + string projectPath = project.FullName; string filePath = document.FullName; string[] itemId = new[] { document.ProjectItem?.Name }; var lastWriteTime = File.GetLastWriteTime(filePath); - Task.Run(() => + _ = Task.Run(async () => { while (!process.WaitForExit(1000)) { var latestWriteTime = File.GetLastWriteTime(filePath); if (lastWriteTime != latestWriteTime) { lastWriteTime = latestWriteTime; - QtProjectIntellisense.Refresh(project, selectedFiles: itemId); + await QtProjectIntellisense.RefreshAsync(project, projectPath); } } if (lastWriteTime != File.GetLastWriteTime(filePath)) { - QtProjectIntellisense.Refresh(project, selectedFiles: itemId); + await QtProjectIntellisense.RefreshAsync(project, projectPath); } }); } diff --git a/QtVsTools.Package/Editors/Editor.QtResourceEditor.cs b/QtVsTools.Package/Editors/Editor.QtResourceEditor.cs index 6c159cd..0c38ad7 100644 --- a/QtVsTools.Package/Editors/Editor.QtResourceEditor.cs +++ b/QtVsTools.Package/Editors/Editor.QtResourceEditor.cs @@ -29,7 +29,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; -using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Shell; namespace QtVsTools.Editors { @@ -44,18 +44,13 @@ public override string ExecutableName => "QrcEditor.exe"; - protected override string GetToolsPath() - { - return QtVsToolsPackage.Instance?.PkgInstallPath; - } + protected override string GetToolsPath() => + QtVsToolsPackage.Instance?.PkgInstallPath; public override Func<string, bool> WindowFilter => caption => caption.StartsWith(Title); - protected override string GetTitle(Process editorProcess) - { - return Title; - } + protected override string GetTitle(Process editorProcess) => Title; protected override bool Detached => QtVsToolsPackage.Instance.Options.ResourceEditorDetached; } diff --git a/QtVsTools.Package/Editors/Editor.cs b/QtVsTools.Package/Editors/Editor.cs index 754f4ba..58db95a 100644 --- a/QtVsTools.Package/Editors/Editor.cs +++ b/QtVsTools.Package/Editors/Editor.cs @@ -40,11 +40,12 @@ using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.VCProjectEngine; -using QtVsTools.Core; -using QtVsTools.VisualStudio; namespace QtVsTools.Editors { + using Core; + using VisualStudio; + using static Core.HelperFunctions; public abstract class Editor : IVsEditorFactory @@ -61,6 +62,7 @@ protected virtual string GetToolsPath() { + ThreadHelper.ThrowIfNotOnUIThread(); return GetQtToolsPath() ?? GetDefaultQtToolsPath(); } @@ -69,33 +71,37 @@ string GetQtToolsPath() { - var project = VsShell.GetProject(Context); - if (project == null) - return null; + return ThreadHelper.JoinableTaskFactory.Run(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + var project = VsShell.GetProject(Context); + if (project == null) + return null; - var vcProject = project.Object as VCProject; - if (vcProject == null) - return null; + var vcProject = project.Object as VCProject; + if (vcProject == null) + return null; - var vcConfigs = vcProject.Configurations as IVCCollection; - if (vcConfigs == null) - return null; + var vcConfigs = vcProject.Configurations as IVCCollection; + if (vcConfigs == null) + return null; - var activeConfig = project.ConfigurationManager?.ActiveConfiguration; - if (activeConfig == null) - return null; + var activeConfig = project.ConfigurationManager?.ActiveConfiguration; + if (activeConfig == null) + return null; - var activeConfigId = string.Format("{0}|{1}", - activeConfig.ConfigurationName, activeConfig.PlatformName); - var vcConfig = vcConfigs.Item(activeConfigId) as VCConfiguration; - if (vcConfig == null) - return null; + var activeConfigId = string.Format("{0}|{1}", + activeConfig.ConfigurationName, activeConfig.PlatformName); + var vcConfig = vcConfigs.Item(activeConfigId) as VCConfiguration; + if (vcConfig == null) + return null; - var qtToolsPath = vcConfig.GetEvaluatedPropertyValue("QtToolsPath"); - if (string.IsNullOrEmpty(qtToolsPath)) - return null; + var qtToolsPath = vcConfig.GetEvaluatedPropertyValue("QtToolsPath"); + if (string.IsNullOrEmpty(qtToolsPath)) + return null; - return qtToolsPath; + return qtToolsPath; + }); } string GetDefaultQtToolsPath() @@ -126,6 +132,8 @@ out Guid pguidCmdUI, out int pgrfCDW) { + ThreadHelper.ThrowIfNotOnUIThread(); + // Initialize to null ppunkDocView = IntPtr.Zero; ppunkDocData = IntPtr.Zero; @@ -202,11 +210,15 @@ { if (string.IsNullOrEmpty(qtToolsPath)) qtToolsPath = GetDefaultQtToolsPath(); + var st = GetStartInfo(filePath, qtToolsPath, hideWindow); try { - return Process.Start(GetStartInfo(filePath, qtToolsPath, hideWindow)); - } catch (Exception e) { - Messages.Print( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + return Process.Start(st); + } catch (Exception exception) { + exception.Log(); + if (!File.Exists(st.Arguments)) + Messages.Print("The system cannot find the file: " + st.Arguments); + if (!File.Exists(st.FileName)) + Messages.Print("The system cannot find the file: " + st.FileName); return null; } } @@ -223,20 +235,20 @@ private class EditorPane : WindowPane, IVsPersistDocData { - public Editor Editor { get; private set; } - public string QtToolsPath { get; private set; } + private Editor Editor { get; } + private string QtToolsPath { get; } - public TableLayoutPanel EditorContainer { get; private set; } - public Label EditorTitle { get; private set; } - public LinkLabel EditorDetachButton { get; private set; } - public Panel EditorControl { get; private set; } + private TableLayoutPanel EditorContainer { get; set; } + private Label EditorTitle { get; } + private LinkLabel EditorDetachButton { get; } + private Panel EditorControl { get; } public override IWin32Window Window => EditorContainer; - public Process EditorProcess { get; private set; } - public IntPtr EditorWindow { get; private set; } - public int EditorWindowStyle { get; private set; } - public int EditorWindowStyleExt { get; private set; } - public IntPtr EditorIcon { get; private set; } + private Process EditorProcess { get; set; } + private IntPtr EditorWindow { get; set; } + private int EditorWindowStyle { get; set; } + private int EditorWindowStyleExt { get; set; } + private IntPtr EditorIcon { get; set; } public EditorPane(Editor editor, string qtToolsPath) { @@ -306,11 +318,11 @@ int IVsPersistDocData.LoadDocData(string pszMkDocument) { - var solution = GetService(typeof(SVsSolution)) as IVsSolution; EditorProcess = Editor.Start(pszMkDocument, QtToolsPath, hideWindow: !Editor.Detached); if (EditorProcess == null) return VSConstants.E_FAIL; + if (Editor.Detached) { Editor.OnStart(EditorProcess); CloseParentFrame(); @@ -395,8 +407,12 @@ { EditorProcess = null; EditorWindow = IntPtr.Zero; - var parentFrame = GetService(typeof(SVsWindowFrame)) as IVsWindowFrame; - parentFrame?.CloseFrame((uint)__FRAMECLOSE.FRAMECLOSE_NoSave); + ThreadHelper.JoinableTaskFactory.Run(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + var parentFrame = GetService(typeof(SVsWindowFrame)) as IVsWindowFrame; + parentFrame?.CloseFrame((uint)__FRAMECLOSE.FRAMECLOSE_NoSave); + }); } private void EditorProcess_Exited(object sender, EventArgs e) @@ -452,7 +468,7 @@ EditorWindow = IntPtr.Zero; // Close editor window - System.Threading.Tasks.Task.Run(() => + _ = System.Threading.Tasks.Task.Run(() => { NativeAPI.SendMessage(editorWindow, NativeAPI.WM_CLOSE, 0, 0); if (!editorProcess.WaitForExit(500)) { diff --git a/QtVsTools.Package/Icons/Monikers.imagemanifest b/QtVsTools.Package/Icons/Monikers.imagemanifest new file mode 100644 index 0000000..27e1e2b --- /dev/null +++ b/QtVsTools.Package/Icons/Monikers.imagemanifest @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<ImageManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://schemas.microsoft.com/VisualStudio/ImageManifestSchema/2014"> + <Symbols> + <String Name="Resources" Value="/QtVsTools;Component/Icons" /> + <Guid Name="QtMonikersGuid" Value="{0d2e443f-6dbb-4001-99dc-9cd7d5c924e7}" /> + <ID Name="prf" Value="0" /> + <ID Name="pri" Value="1" /> + <ID Name="pro" Value="2" /> + <ID Name="qml" Value="3" /> + <ID Name="qrc" Value="4" /> + <ID Name="ts" Value="5" /> + <ID Name="ui" Value="6" /> + </Symbols> + <Images> + <Image Guid="$(QtMonikersGuid)" ID="$(prf)"> + <Source Uri="$(Resources)/prf32.png"> + <Size Value="32" /> + </Source> + </Image> + <Image Guid="$(QtMonikersGuid)" ID="$(pri)"> + <Source Uri="$(Resources)/pri32.png"> + <Size Value="32" /> + </Source> + </Image> + <Image Guid="$(QtMonikersGuid)" ID="$(pro)"> + <Source Uri="$(Resources)/pro32.png"> + <Size Value="32" /> + </Source> + </Image> + <Image Guid="$(QtMonikersGuid)" ID="$(qml)"> + <Source Uri="$(Resources)/qml32.png"> + <Size Value="32" /> + </Source> + </Image> + <Image Guid="$(QtMonikersGuid)" ID="$(qrc)"> + <Source Uri="$(Resources)/qrc32.png"> + <Size Value="32" /> + </Source> + </Image> + <Image Guid="$(QtMonikersGuid)" ID="$(ts)"> + <Source Uri="$(Resources)/ts32.png"> + <Size Value="32" /> + </Source> + </Image> + <Image Guid="$(QtMonikersGuid)" ID="$(ui)"> + <Source Uri="$(Resources)/ui32.png"> + <Size Value="32" /> + </Source> + </Image> + </Images> + <ImageLists /> +</ImageManifest> diff --git a/QtVsTools.Package/Icons/prf32.png b/QtVsTools.Package/Icons/prf32.png new file mode 100644 index 0000000..359c5c8 --- /dev/null +++ b/QtVsTools.Package/Icons/prf32.png Binary files differ diff --git a/QtVsTools.Package/Icons/pri32.png b/QtVsTools.Package/Icons/pri32.png new file mode 100644 index 0000000..f82fea4 --- /dev/null +++ b/QtVsTools.Package/Icons/pri32.png Binary files differ diff --git a/QtVsTools.Package/Icons/pro32.png b/QtVsTools.Package/Icons/pro32.png new file mode 100644 index 0000000..13d8a84 --- /dev/null +++ b/QtVsTools.Package/Icons/pro32.png Binary files differ diff --git a/QtVsTools.Package/Icons/qml32.png b/QtVsTools.Package/Icons/qml32.png new file mode 100644 index 0000000..85ad155 --- /dev/null +++ b/QtVsTools.Package/Icons/qml32.png Binary files differ diff --git a/QtVsTools.Package/Icons/qrc32.png b/QtVsTools.Package/Icons/qrc32.png new file mode 100644 index 0000000..b4b70d8 --- /dev/null +++ b/QtVsTools.Package/Icons/qrc32.png Binary files differ diff --git a/QtVsTools.Package/Icons/ts32.png b/QtVsTools.Package/Icons/ts32.png new file mode 100644 index 0000000..9731b08 --- /dev/null +++ b/QtVsTools.Package/Icons/ts32.png Binary files differ diff --git a/QtVsTools.Package/Icons/ui32.png b/QtVsTools.Package/Icons/ui32.png new file mode 100644 index 0000000..5a40101 --- /dev/null +++ b/QtVsTools.Package/Icons/ui32.png Binary files differ diff --git a/QtVsTools.Package/Legacy/ChangeFor.cs b/QtVsTools.Package/Legacy/ChangeFor.cs new file mode 100644 index 0000000..8eb45fd --- /dev/null +++ b/QtVsTools.Package/Legacy/ChangeFor.cs @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +namespace QtVsTools.Legacy +{ + internal enum ChangeFor { Solution, Project } +} diff --git a/QtVsTools.Package/Legacy/FormChangeQtVersion.Designer.cs b/QtVsTools.Package/Legacy/FormChangeQtVersion.Designer.cs new file mode 100644 index 0000000..52fdac0 --- /dev/null +++ b/QtVsTools.Package/Legacy/FormChangeQtVersion.Designer.cs @@ -0,0 +1,87 @@ +namespace QtVsTools.Legacy +{ + partial class FormChangeQtVersion + { + + #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() + { + btnOK = new System.Windows.Forms.Button(); + btnCancel = new System.Windows.Forms.Button(); + lbQtVersions = new System.Windows.Forms.ListBox(); + lQtVersions = new System.Windows.Forms.Label(); + SuspendLayout(); + // + // btnOK + // + btnOK.DialogResult = System.Windows.Forms.DialogResult.OK; + btnOK.Location = new System.Drawing.Point(124, 231); + btnOK.Name = "btnOK"; + btnOK.Size = new System.Drawing.Size(75, 23); + btnOK.TabIndex = 1; + btnOK.Text = "&OK"; + btnOK.UseVisualStyleBackColor = true; + // + // btnCancel + // + btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + btnCancel.Location = new System.Drawing.Point(205, 231); + btnCancel.Name = "btnCancel"; + btnCancel.Size = new System.Drawing.Size(75, 23); + btnCancel.TabIndex = 2; + btnCancel.Text = "&Cancel"; + btnCancel.UseVisualStyleBackColor = true; + // + // lbQtVersions + // + lbQtVersions.FormattingEnabled = true; + lbQtVersions.Location = new System.Drawing.Point(13, 39); + lbQtVersions.Name = "lbQtVersions"; + lbQtVersions.Size = new System.Drawing.Size(267, 173); + lbQtVersions.TabIndex = 0; + // + // lQtVersions + // + lQtVersions.AutoSize = true; + lQtVersions.Location = new System.Drawing.Point(13, 20); + lQtVersions.Name = "lQtVersions"; + lQtVersions.Size = new System.Drawing.Size(103, 13); + lQtVersions.TabIndex = 3; + lQtVersions.Text = "Installed Qt Versions"; + // + // FormChangeQtVersion + // + AcceptButton = btnOK; + AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + CancelButton = btnCancel; + ClientSize = new System.Drawing.Size(292, 266); + Controls.Add(lQtVersions); + Controls.Add(lbQtVersions); + Controls.Add(btnCancel); + Controls.Add(btnOK); + FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + KeyPreview = true; + MaximizeBox = false; + MinimizeBox = false; + Name = "FormChangeQtVersion"; + ShowInTaskbar = false; + Text = "FormChangeQtVersion"; + ResumeLayout(false); + PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button btnOK; + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.ListBox lbQtVersions; + private System.Windows.Forms.Label lQtVersions; + } +} diff --git a/QtVsTools.Package/Legacy/FormChangeQtVersion.cs b/QtVsTools.Package/Legacy/FormChangeQtVersion.cs new file mode 100644 index 0000000..a001086 --- /dev/null +++ b/QtVsTools.Package/Legacy/FormChangeQtVersion.cs @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; + +namespace QtVsTools.Legacy +{ + using Core; + using Legacy = Core.Legacy; + + public partial class FormChangeQtVersion : Form + { + public FormChangeQtVersion() + { + InitializeComponent(); + btnOK.Text = "&OK"; + btnCancel.Text = "&Cancel"; + lQtVersions.Text = "Installed Qt Versions"; + lbQtVersions.DoubleClick += OnQtVersions_DoubleClick; + KeyPress += FormChangeQtVersion_KeyPress; + Shown += FormChangeQtVersion_Shown; + } + + private void FormChangeQtVersion_Shown(object sender, EventArgs e) + { + Text = "Set Solution's Qt Version"; + } + + void OnQtVersions_DoubleClick(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + void FormChangeQtVersion_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == 27) { + DialogResult = DialogResult.Cancel; + Close(); + } + } + + internal void UpdateContent(ChangeFor change) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + lbQtVersions.Items.Clear(); + var vm = QtVersionManager.The(); + foreach (var versionName in vm.GetVersions()) + lbQtVersions.Items.Add(versionName); + + lbQtVersions.Items.Add("$(DefaultQtVersion)"); + if (change == ChangeFor.Solution) { + var qtVer = Legacy.QtVersionManager + .GetSolutionQtVersion(QtVsToolsPackage.Instance.Dte.Solution); + if (qtVer == null) + qtVer = vm.GetDefaultVersion(); + if (qtVer != null) + lbQtVersions.SelectedItem = qtVer; + Text = "Set Solution's Qt Version"; + } else { + var pro = Core.HelperFunctions.GetSelectedProject(QtVsToolsPackage.Instance.Dte); + var qtVer = vm.GetProjectQtVersion(pro); + if (qtVer == null) + qtVer = vm.GetDefaultVersion(); + if (qtVer != null) + lbQtVersions.SelectedItem = qtVer; + Text = "Set Project's Qt Version"; + } + } + + public string GetSelectedQtVersion() + { + var idx = lbQtVersions.SelectedIndex; + if (idx < 0) + return null; + return lbQtVersions.Items[idx].ToString(); + } + } +} diff --git a/QtVsTools.Package/Legacy/FormChangeQtVersion.resx b/QtVsTools.Package/Legacy/FormChangeQtVersion.resx new file mode 100644 index 0000000..e0a4c98 --- /dev/null +++ b/QtVsTools.Package/Legacy/FormChangeQtVersion.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + 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">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <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" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </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>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/QtVsTools.Package/Legacy/FormProjectQtSettings.Designer.cs b/QtVsTools.Package/Legacy/FormProjectQtSettings.Designer.cs new file mode 100644 index 0000000..76265ea --- /dev/null +++ b/QtVsTools.Package/Legacy/FormProjectQtSettings.Designer.cs @@ -0,0 +1,159 @@ +using System.Windows.Forms; + +namespace QtVsTools.Legacy +{ + partial class FormProjectQtSettings + { + + #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() + { + this.OptionsPropertyGrid = new System.Windows.Forms.PropertyGrid(); + this.panel1 = new System.Windows.Forms.Panel(); + this.okButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + this.panel1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.SuspendLayout(); + // + // OptionsPropertyGrid + // + this.OptionsPropertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; + this.OptionsPropertyGrid.HelpVisible = false; + this.OptionsPropertyGrid.Location = new System.Drawing.Point(6, 6); + this.OptionsPropertyGrid.Margin = new System.Windows.Forms.Padding(6); + this.OptionsPropertyGrid.Name = "OptionsPropertyGrid"; + this.OptionsPropertyGrid.PropertySort = System.Windows.Forms.PropertySort.Alphabetical; + this.OptionsPropertyGrid.Size = new System.Drawing.Size(898, 603); + this.OptionsPropertyGrid.TabIndex = 8; + this.OptionsPropertyGrid.ToolbarVisible = false; + // + // panel1 + // + this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.panel1.Controls.Add(this.okButton); + this.panel1.Controls.Add(this.cancelButton); + this.panel1.Location = new System.Drawing.Point(620, 700); + this.panel1.Margin = new System.Windows.Forms.Padding(6); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(336, 73); + this.panel1.TabIndex = 9; + // + // okButton + // + this.okButton.Location = new System.Drawing.Point(16, 15); + this.okButton.Margin = new System.Windows.Forms.Padding(6); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(150, 44); + this.okButton.TabIndex = 0; + this.okButton.Click += new System.EventHandler(this.OkButton_Click); + this.okButton.Text = "&OK"; + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Location = new System.Drawing.Point(176, 15); + this.cancelButton.Margin = new System.Windows.Forms.Padding(6); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(150, 44); + this.cancelButton.TabIndex = 1; + this.cancelButton.Text = "Cancel"; + // + // tabControl1 + // + this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Location = new System.Drawing.Point(24, 23); + this.tabControl1.Margin = new System.Windows.Forms.Padding(6); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(926, 662); + this.tabControl1.TabIndex = 10; + // + // tabPage1 + // + this.tabPage1.BackColor = System.Drawing.SystemColors.Control; + this.tabPage1.Controls.Add(this.OptionsPropertyGrid); + this.tabPage1.Location = new System.Drawing.Point(8, 39); + this.tabPage1.Margin = new System.Windows.Forms.Padding(6); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(6); + this.tabPage1.Size = new System.Drawing.Size(910, 615); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Properties"; + // + // tabPage2 + // + this.tabPage2.BackColor = System.Drawing.SystemColors.Control; + this.tabPage2.Controls.Add(this.flowLayoutPanel1); + this.tabPage2.Location = new System.Drawing.Point(8, 39); + this.tabPage2.Margin = new System.Windows.Forms.Padding(6); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(6); + this.tabPage2.Size = new System.Drawing.Size(910, 615); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Qt Modules"; + // + // flowLayoutPanel1 + // + this.flowLayoutPanel1.AutoScroll = true; + this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this.flowLayoutPanel1.Location = new System.Drawing.Point(6, 6); + this.flowLayoutPanel1.Name = "flowLayoutPanel1"; + this.flowLayoutPanel1.Size = new System.Drawing.Size(898, 603); + this.flowLayoutPanel1.TabIndex = 66; + // + // FormProjectQtSettings + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.cancelButton; + this.ClientSize = new System.Drawing.Size(962, 801); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.panel1); + this.KeyPreview = true; + this.Margin = new System.Windows.Forms.Padding(6); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(988, 750); + this.Name = "FormProjectQtSettings"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show; + this.Text = "Qt Project Settings"; + this.panel1.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private PropertyGrid OptionsPropertyGrid; + private Panel panel1; + private Button okButton; + private Button cancelButton; + private TabControl tabControl1; + private TabPage tabPage1; + private TabPage tabPage2; + private FlowLayoutPanel flowLayoutPanel1; + } +} diff --git a/QtVsTools.Package/Legacy/FormProjectQtSettings.cs b/QtVsTools.Package/Legacy/FormProjectQtSettings.cs new file mode 100644 index 0000000..93a7be0 --- /dev/null +++ b/QtVsTools.Package/Legacy/FormProjectQtSettings.cs @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Windows.Forms; +using System.IO; +using EnvDTE; + +namespace QtVsTools.Legacy +{ + using Core; + using Legacy = Core.Legacy; + + public partial class FormProjectQtSettings : Form + { + private readonly Project project; + private readonly ProjectQtSettings qtSettings; + private readonly List<ModuleItem> moduleMap = new List<ModuleItem>(); + + private struct ModuleItem + { + public readonly CheckBox checkbox; + public readonly int moduleId; + public bool initialValue; + + public ModuleItem(CheckBox cb, int mid, bool init) + { + checkbox = cb; + moduleId = mid; + initialValue = init; + } + } + + public FormProjectQtSettings(Project pro) + { + InitializeComponent(); + + project = pro; + qtSettings = new ProjectQtSettings(project); + qtSettings.PropertyChanged += OnPropertyChanged; + OptionsPropertyGrid.SelectedObject = qtSettings; + + InitModules(QtVersionManager.The().GetProjectQtVersion(project)); + } + + protected override bool ProcessDialogKey(Keys keyData) + { + if (ModifierKeys == Keys.None && keyData == Keys.Escape) { + Close(); + return true; + } + return base.ProcessDialogKey(keyData); + } + + private void OkButton_Click(object sender, EventArgs e) + { + // Disable the buttons since some operations are quite expensive (e.g. changing + // the Qt version) and take some to finish. Keeping the buttons enabled allows to hit + // the buttons several times resulting in successive executions of these operations. + okButton.Enabled = false; + cancelButton.Enabled = false; + + qtSettings.SaveSettings(); + SaveModules(); + okButton.DialogResult = DialogResult.OK; + Close(); + } + + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName != "Version") + throw new ArgumentException(); + InitModules(qtSettings.Version); + } + + private void InitModules(string qtVersion) + { + moduleMap.Clear(); + flowLayoutPanel1.Controls.Clear(); + + var vm = QtVersionManager.The(); + var versionInfo = vm.GetVersionInfo(qtVersion); + if (string.IsNullOrEmpty(qtVersion) || versionInfo == null) { + flowLayoutPanel1.Controls.Add(new Label + { + Text = Environment.NewLine + + "Please set a valid Qt version first.", + AutoSize = true + }); + return; + } + + var installPath = vm.GetInstallPath(qtVersion) ?? string.Empty; + var modules = QtModules.Instance.GetAvailableModules(versionInfo.qtMajor) + .Where(x => x.Selectable) + .OrderBy(x => x.Name); + foreach (var module in modules) { + var checkBox = new CheckBox + { + Margin = new Padding(6), + Location = new System.Drawing.Point(150, 150), + Name = module.LibraryPrefix, + UseVisualStyleBackColor = true, + AutoSize = true, + Text = module.Name, + Checked = Legacy.QtProject.HasModule(project, module.Id, qtVersion) + }; + flowLayoutPanel1.Controls.Add(checkBox); + moduleMap.Add(new ModuleItem(checkBox, module.Id, checkBox.Checked)); + + var info = QtModules.Instance.Module(module.Id, versionInfo.qtMajor); + var libraryPrefix = info?.LibraryPrefix; + if (libraryPrefix.StartsWith("Qt", StringComparison.Ordinal)) + libraryPrefix = "Qt" + versionInfo.qtMajor + libraryPrefix.Substring(2); + checkBox.Enabled = new FileInfo( + Path.Combine(installPath, "lib", $"{libraryPrefix}{versionInfo.LibInfix()}.lib") + ).Exists; // Disable the check-box if the module is not installed. + if (!checkBox.Enabled) + checkBox.Checked = false; // Uncheck if the module is not installed. + } + } + + private void SaveModules() + { + for (var i = 0; i < moduleMap.Count; ++i) { + var item = moduleMap[i]; + var isModuleChecked = item.checkbox.Checked; + if (isModuleChecked != item.initialValue) { + if (isModuleChecked) + Legacy.QtProject.AddModule(project, item.moduleId); + else + Legacy.QtProject.RemoveModule(project, item.moduleId); + } + } + } + + } +} diff --git a/QtVsTools.Package/Legacy/FormProjectQtSettings.resx b/QtVsTools.Package/Legacy/FormProjectQtSettings.resx new file mode 100644 index 0000000..c7e0d4b --- /dev/null +++ b/QtVsTools.Package/Legacy/FormProjectQtSettings.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + 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">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <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" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </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>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/QtVsTools.Package/Legacy/ProjectQtSettings.cs b/QtVsTools.Package/Legacy/ProjectQtSettings.cs new file mode 100644 index 0000000..1cc4d53 --- /dev/null +++ b/QtVsTools.Package/Legacy/ProjectQtSettings.cs @@ -0,0 +1,336 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Text.RegularExpressions; + +namespace QtVsTools.Legacy +{ + using Core; + using Legacy = Core.Legacy; + + public class ProjectQtSettings : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + protected void OnPropertyChanged(string propertyName) + { + var eventHandler = PropertyChanged; + if (eventHandler != null) + eventHandler.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + public ProjectQtSettings(EnvDTE.Project proj) + { + versionManager = QtVersionManager.The(); + project = proj; + newMocDir = oldMocDir = Legacy.QtVSIPSettings.GetMocDirectory(project); + newMocOptions = oldMocOptions = Legacy.QtVSIPSettings.GetMocOptions(project); + newRccDir = oldRccDir = Legacy.QtVSIPSettings.GetRccDirectory(project); + newUicDir = oldUicDir = Legacy.QtVSIPSettings.GetUicDirectory(project); + newLUpdateOnBuild = oldLUpdateOnBuild = Legacy.QtVSIPSettings.GetLUpdateOnBuild(project); + newLUpdateOptions = oldLUpdateOptions = Legacy.QtVSIPSettings.GetLUpdateOptions(project); + newLReleaseOptions = oldLReleaseOptions = Legacy.QtVSIPSettings.GetLReleaseOptions(project); + newQtVersion = oldQtVersion = versionManager.GetProjectQtVersion(project); + QmlDebug = oldQmlDebug = Legacy.QtVSIPSettings.GetQmlDebug(project); + } + + private readonly QtVersionManager versionManager; + private EnvDTE.Project project; + + private readonly string oldMocDir; + private readonly string oldMocOptions; + private readonly string oldRccDir; + private readonly string oldUicDir; + private readonly string oldQtVersion; + private readonly bool oldLUpdateOnBuild; + private readonly string oldLUpdateOptions; + private readonly string oldLReleaseOptions; + private readonly bool oldQmlDebug; + + private string newMocDir; + private string newMocOptions; + private string newRccDir; + private string newUicDir; + private string newQtVersion; + private bool newLUpdateOnBuild; + private string newLUpdateOptions; + private string newLReleaseOptions; + + public void SaveSettings() + { + var updateMoc = false; + var qtPro = QtProject.Create(project); + + if (oldMocDir != newMocDir) { + Legacy.QtVSIPSettings.SaveMocDirectory(project, newMocDir); + updateMoc = true; + } + if (oldMocOptions != newMocOptions) { + Legacy.QtVSIPSettings.SaveMocOptions(project, newMocOptions); + updateMoc = true; + } + if (updateMoc) + qtPro.UpdateMocSteps(oldMocDir); + + if (oldUicDir != newUicDir) { + Legacy.QtVSIPSettings.SaveUicDirectory(project, newUicDir); + qtPro.UpdateUicSteps(oldUicDir, true); + } + + if (oldRccDir != newRccDir) { + Legacy.QtVSIPSettings.SaveRccDirectory(project, newRccDir); + qtPro.RefreshRccSteps(oldRccDir); + } + + if (oldLUpdateOnBuild != newLUpdateOnBuild) + Legacy.QtVSIPSettings.SaveLUpdateOnBuild(project, newLUpdateOnBuild); + + if (oldLUpdateOptions != newLUpdateOptions) + Legacy.QtVSIPSettings.SaveLUpdateOptions(project, newLUpdateOptions); + + if (oldLReleaseOptions != newLReleaseOptions) + Legacy.QtVSIPSettings.SaveLReleaseOptions(project, newLReleaseOptions); + + if (oldQmlDebug != QmlDebug) + Legacy.QtVSIPSettings.SaveQmlDebug(project, QmlDebug); + + if (oldQtVersion != newQtVersion) { + if (Legacy.QtProject.PromptChangeQtVersion(project, oldQtVersion, newQtVersion)) { + var newProjectCreated = false; + var versionChanged = qtPro.ChangeQtVersion( + oldQtVersion, newQtVersion, ref newProjectCreated); + if (versionChanged && newProjectCreated) + project = qtPro.Project; + } + } + } + + public string MocDirectory + { + get + { + return newMocDir; + } + set + { + var tmp = HelperFunctions.NormalizeRelativeFilePath(value); + if (tmp.Equals(oldMocDir, StringComparison.OrdinalIgnoreCase)) + return; + + string badMacros = IncompatibleMacros(tmp); + if (!string.IsNullOrEmpty(badMacros)) + Messages.DisplayErrorMessage(SR.GetString("IncompatibleMacros", badMacros)); + else + newMocDir = tmp; + } + } + + public string MocOptions + { + get + { + return newMocOptions; + } + + set + { + newMocOptions = value; + } + } + + public string UicDirectory + { + get + { + return newUicDir; + } + set + { + var tmp = HelperFunctions.NormalizeRelativeFilePath(value); + if (tmp.Equals(oldUicDir, StringComparison.OrdinalIgnoreCase)) + return; + + string badMacros = IncompatibleMacros(tmp); + if (!string.IsNullOrEmpty(badMacros)) + Messages.DisplayErrorMessage(SR.GetString("IncompatibleMacros", badMacros)); + else + newUicDir = tmp; + } + } + + public string RccDirectory + { + get + { + return newRccDir; + } + set + { + var tmp = HelperFunctions.NormalizeRelativeFilePath(value); + if (tmp.Equals(oldRccDir, StringComparison.OrdinalIgnoreCase)) + return; + + string badMacros = IncompatibleMacros(tmp); + if (!string.IsNullOrEmpty(badMacros)) + Messages.DisplayErrorMessage(SR.GetString("IncompatibleMacros", badMacros)); + else + newRccDir = tmp; + } + } + + public bool lupdateOnBuild + { + get + { + return newLUpdateOnBuild; + } + + set + { + newLUpdateOnBuild = value; + } + } + + public string LUpdateOptions + { + get + { + return newLUpdateOptions; + } + + set + { + newLUpdateOptions = value; + } + } + + public string LReleaseOptions + { + get + { + return newLReleaseOptions; + } + + set + { + newLReleaseOptions = value; + } + } + + [DisplayName("QML Debug")] + [TypeConverter(typeof(QmlDebugConverter))] + private bool QmlDebug { get; } + + private static string IncompatibleMacros(string stringToExpand) + { + string incompatibleMacros = ""; + foreach (Match metaNameMatch in Regex.Matches(stringToExpand, @"\%\(([^\)]+)\)")) { + string metaName = metaNameMatch.Groups[1].Value; + if (!incompatibleMacros.Contains(string.Format("%({0})", metaName))) { + switch (metaName) { + case "RecursiveDir": + case "ModifiedTime": + case "CreatedTime": + case "AccessedTime": + if (!string.IsNullOrEmpty(incompatibleMacros)) + incompatibleMacros += ", "; + incompatibleMacros += string.Format("%({0})", metaName); + break; + } + } + } + return incompatibleMacros; + } + + internal class QmlDebugConverter : BooleanConverter + { + public override object ConvertTo( + ITypeDescriptorContext context, + CultureInfo culture, + object value, + Type destinationType) + { + return (bool)value ? "Enabled" : "Disabled"; + } + + public override object ConvertFrom( + ITypeDescriptorContext context, + CultureInfo culture, + object value) + { + return (string)value == "Enabled"; + } + } + + [TypeConverter(typeof(VersionConverter))] + public string Version + { + get + { + return newQtVersion; + } + set + { + if (newQtVersion != value) { + newQtVersion = value; + OnPropertyChanged("Version"); + } + } + } + + internal class VersionConverter : StringConverter + { + private readonly QtVersionManager versionManager; + + public VersionConverter() + { + versionManager = QtVersionManager.The(); + } + + public override bool GetStandardValuesSupported(ITypeDescriptorContext context) + { + return true; + } + + public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) + { + var versions = versionManager.GetVersions(); + Array.Resize(ref versions, versions.Length + 1); + versions[versions.Length - 1] = "$(DefaultQtVersion)"; + return new StandardValuesCollection(versions); + } + + public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) + { + return true; + } + } + } +} diff --git a/QtVsTools.Package/Legacy/QtMenu.cs b/QtVsTools.Package/Legacy/QtMenu.cs new file mode 100644 index 0000000..bc38e6e --- /dev/null +++ b/QtVsTools.Package/Legacy/QtMenu.cs @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Windows.Forms; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.Shell; + +namespace QtVsTools.Legacy +{ + using Core; + using Legacy = Core.Legacy; + + internal static class QtMenu + { + internal static void ShowFormProjectQtSettings(Project project) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + using (var form = new FormProjectQtSettings(project)) { + form.StartPosition = FormStartPosition.CenterParent; + form.ShowDialog(new MainWinWrapper(QtVsToolsPackage.Instance.Dte)); + } + } + + internal static void ShowFormChangeProjectQtVersion() + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var pro = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte); + if (!HelperFunctions.IsQtProject(pro)) + return; + + using (var formChangeQtVersion = new FormChangeQtVersion()) { + formChangeQtVersion.UpdateContent(ChangeFor.Project); + var ww = new MainWinWrapper(QtVsToolsPackage.Instance.Dte); + if (formChangeQtVersion.ShowDialog(ww) == DialogResult.OK) { + var qtVersion = formChangeQtVersion.GetSelectedQtVersion(); + HelperFunctions.SetDebuggingEnvironment(pro, "PATH=" + QtVersionManager + .The().GetInstallPath(qtVersion) + @"\bin;$(PATH)", true); + } + } + } + + internal static void ShowFormChangeSolutionQtVersion() + { + ThreadHelper.ThrowIfNotOnUIThread(); + + string newQtVersion = null; + using (var formChangeQtVersion = new FormChangeQtVersion()) { + formChangeQtVersion.UpdateContent(ChangeFor.Solution); + if (formChangeQtVersion.ShowDialog() != DialogResult.OK) + return; + newQtVersion = formChangeQtVersion.GetSelectedQtVersion(); + } + if (newQtVersion == null) + return; + + string platform = null; + var dte = QtVsToolsPackage.Instance.Dte; + try { + platform = (dte.Solution.SolutionBuild.ActiveConfiguration as SolutionConfiguration2) + .PlatformName; + } catch { } + if (string.IsNullOrEmpty(platform)) + return; + + var vm = QtVersionManager.The(); + foreach (var project in HelperFunctions.ProjectsInSolution(dte)) { + if (HelperFunctions.IsVsToolsProject(project)) { + var OldQtVersion = vm.GetProjectQtVersion(project, platform); + if (OldQtVersion == null) + OldQtVersion = vm.GetDefaultVersion(); + + var created = false; + var qtProject = QtProject.Create(project); + if (Legacy.QtProject.PromptChangeQtVersion(project, OldQtVersion, newQtVersion)) + qtProject.ChangeQtVersion(OldQtVersion, newQtVersion, ref created); + } + } + Legacy.QtVersionManager.SaveSolutionQtVersion(dte.Solution, newQtVersion); + } + } +} diff --git a/QtVsTools.Package/Legacy/QtOptionsPage.cs b/QtVsTools.Package/Legacy/QtOptionsPage.cs new file mode 100644 index 0000000..c0783c6 --- /dev/null +++ b/QtVsTools.Package/Legacy/QtOptionsPage.cs @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.ComponentModel; +using Microsoft.Win32; +using Microsoft.VisualStudio.Shell; + +namespace QtVsTools.Legacy +{ + using Core; + + public class QtOptionsPage : DialogPage + { + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Source control: Ask before checking out files")] + public bool CheckoutPrompt { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Source control: Enable file check-out")] + public bool Checkout { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Linguist: Default lrelease options")] + public string DefaultLReleaseOptions { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Linguist: Default lupdate options")] + public string DefaultLUpdateOptions { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Linguist: Run lupdate during build")] + public bool EnableLUpdateOnBuild { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Meta-Object Compiler: Default moc generated files directory")] + public string DefaultMocDir { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Meta-Object Compiler: Default additional moc options ")] + public string AdditionalMocOptions { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Meta-Object Compiler: Enable automatic moc")] + public bool AutoMoc { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Resource Compiler: Default rcc generated files directory")] + public string DefaultRccDir { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("User Interface Compiler: Default uic generated files directory")] + public string DefaultUicDir { get; set; } + + [Category(@"Qt VS Project Format v2 (Qt tools integrated via custom-build steps)")] + [DisplayName("Build: Run pre-build setup")] + public bool PreBuildSetup { get; set; } + + const string VALUENAME_LegacyPreBuild = "LegacyPreBuild"; + + public override void ResetSettings() + { + CheckoutPrompt = true; + Checkout = true; + DefaultLReleaseOptions = ""; + DefaultLUpdateOptions = ""; + EnableLUpdateOnBuild = false; + DefaultMocDir = ""; + AdditionalMocOptions = ""; + AutoMoc = true; + DefaultRccDir = ""; + DefaultUicDir = ""; + PreBuildSetup = false; + } + + public override void LoadSettingsFromStorage() + { + ResetSettings(); + try { + using (var key = Registry.CurrentUser + .OpenSubKey(@"SOFTWARE\" + Resources.registryPackagePath, writable: false)) { + if (key == null) + return; + if (key.GetValue(Resources.askBeforeCheckoutFileKeyword) is int checkoutPrompt) + CheckoutPrompt = (checkoutPrompt != 0); + if (key.GetValue(Resources.disableCheckoutFilesKeyword) is int disableCheckout) + Checkout = (disableCheckout == 0); + if (key.GetValue(Resources.lreleaseOptionsKeyword) is string lreleaseOptions) + DefaultLReleaseOptions = lreleaseOptions; + if (key.GetValue(Resources.lupdateOptionsKeyword) is string lupdateOptions) + DefaultLUpdateOptions = lupdateOptions; + if (key.GetValue(Resources.lupdateKeyword) is int lupdateOnBuild) + EnableLUpdateOnBuild = (lupdateOnBuild != 0); + if (key.GetValue(Resources.mocDirKeyword) is string mocDir) + DefaultMocDir = mocDir; + if (key.GetValue(Resources.mocOptionsKeyword) is string mocOptions) + AdditionalMocOptions = mocOptions; + if (key.GetValue(Resources.disableAutoMocStepsUpdateKeyword) is int autoMocOff) + AutoMoc = (autoMocOff == 0); + if (key.GetValue(Resources.rccDirKeyword) is string rccDir) + DefaultRccDir = rccDir; + if (key.GetValue(Resources.uicDirKeyword) is string uicDir) + DefaultUicDir = uicDir; + if (key.GetValue(VALUENAME_LegacyPreBuild) is int preBuild) + PreBuildSetup = (preBuild != 0); + } + } catch (Exception exception) { + exception.Log(); + } + } + + public override void SaveSettingsToStorage() + { + try { + using (var key = Registry.CurrentUser + .CreateSubKey(@"SOFTWARE\" + Resources.registryPackagePath)) { + if (key == null) + return; + key.SetValue(Resources.askBeforeCheckoutFileKeyword, CheckoutPrompt ? 1 : 0); + key.SetValue(Resources.disableCheckoutFilesKeyword, Checkout ? 0 : 1); + key.SetValue(Resources.lreleaseOptionsKeyword, DefaultLReleaseOptions); + key.SetValue(Resources.lupdateOptionsKeyword, DefaultLUpdateOptions); + key.SetValue(Resources.lupdateKeyword, EnableLUpdateOnBuild ? 1 : 0); + key.SetValue(Resources.mocDirKeyword, DefaultMocDir); + key.SetValue(Resources.mocOptionsKeyword, AdditionalMocOptions); + key.SetValue(Resources.disableAutoMocStepsUpdateKeyword, AutoMoc ? 0 : 1); + key.SetValue(Resources.rccDirKeyword, DefaultRccDir); + key.SetValue(Resources.uicDirKeyword, DefaultUicDir); + key.SetValue(VALUENAME_LegacyPreBuild, PreBuildSetup ? 1 : 0); + } + } catch (Exception exception) { + exception.Log(); + } + } + } +} diff --git a/QtVsTools.Package/Legacy/Translation.cs b/QtVsTools.Package/Legacy/Translation.cs new file mode 100644 index 0000000..645d0ee --- /dev/null +++ b/QtVsTools.Package/Legacy/Translation.cs @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Microsoft.VisualStudio.VCProjectEngine; + +namespace QtVsTools.Legacy +{ + using Core; + using Legacy = Core.Legacy; + + using static Core.HelperFunctions; + using BuildAction = QtVsTools.Translation.BuildAction; + + internal static class Translation + { + internal static void Run(BuildAction buildAction, QtProject qtProject, + IEnumerable<string> tsFiles) + { + var qtInstallPath = QtVersionManager.The().GetInstallPath(qtProject.GetQtVersion()); + if (string.IsNullOrEmpty(qtInstallPath)) { + Messages.Print("translation: Error accessing Qt installation"); + return; + } + + if (tsFiles == null) { + tsFiles = (qtProject.VCProject + .GetFilesEndingWith(".ts") as IVCCollection) + .Cast<VCFile>() + .Select(vcFile => vcFile.RelativePath); + } + + if (tsFiles != null) { + var project = qtProject.Project; + var tempFile = Path.GetTempFileName(); + + File.WriteAllLines(tempFile, GetProjectFiles(project, FilesToList.FL_HFiles) + .Union(GetProjectFiles(project, FilesToList.FL_CppFiles)) + .Union(GetProjectFiles(project, FilesToList.FL_UiFiles)) + .Union(GetProjectFiles(project, FilesToList.FL_QmlFiles))); + + var procInfo = new ProcessStartInfo + { + WorkingDirectory = qtProject.ProjectDir, + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardError = true, + RedirectStandardOutput = true, + Arguments = "" + }; + procInfo.FileName = Path.Combine(qtInstallPath, "bin", + buildAction == BuildAction.Update ? "lupdate.exe" : "lrelease.exe"); + + foreach (var file in tsFiles.Where(file => file != null)) + Run(buildAction, file, tempFile, procInfo); + } else { + Messages.Print("translation: No translation files found"); + } + } + + private static void Run(BuildAction buildAction, string tsFile, string tempFile, + ProcessStartInfo procInfo) + { + switch (buildAction) { + case BuildAction.Update: + Messages.Print("\r\n--- (lupdate) file: " + tsFile); + var options = Legacy.QtVSIPSettings.GetLUpdateOptions(); + if (!string.IsNullOrEmpty(options)) + procInfo.Arguments += options + " "; + procInfo.Arguments += string.Format("\"@{0}\" -ts \"{1}\"", tempFile, tsFile); + break; + case BuildAction.Release: + Messages.Print("\r\n--- (lrelease) file: " + tsFile); + options = Legacy.QtVSIPSettings.GetLReleaseOptions(); + if (!string.IsNullOrEmpty(options)) + procInfo.Arguments += options + " "; + procInfo.Arguments += string.Format("\"{0}\"", tsFile); + break; + } + + using (var proc = Process.Start(procInfo)) { + proc.OutputDataReceived += (object sender, DataReceivedEventArgs e) => + { + if (!string.IsNullOrEmpty(e.Data)) + Messages.Print(e.Data); + }; + proc.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => + { + if (!string.IsNullOrEmpty(e.Data)) + Messages.Print(e.Data); + }; + proc.BeginOutputReadLine(); + proc.BeginErrorReadLine(); + proc.WaitForExit(); + switch (proc.ExitCode) { + case 0: + Messages.Print("translation: ok"); + break; + default: + Messages.Print(string.Format("translation: ERROR {0}", proc.ExitCode)); + break; + } + } + } + } +} diff --git a/QtVsTools.Package/Marketplace/Overview.html_TT b/QtVsTools.Package/Marketplace/Overview.html_TT index 7f83418..875bea6 100644 --- a/QtVsTools.Package/Marketplace/Overview.html_TT +++ b/QtVsTools.Package/Marketplace/Overview.html_TT @@ -94,7 +94,7 @@ <p><h3><span>The main features of Qt VS Tools are:</span></h3></p> <ul> <li> - Wizards for creating new Qt projects and classes. + Wizards for creating new Qt and Qt Quick projects and files. </li> <li> Automated build setup for the <a href="http://doc.qt.io/qt-5/moc.html"> @@ -122,6 +122,9 @@ <li> Debugging extensions for Qt data types. </li> + <li> + QML debug engine for debugging Qt Quick applications. + </li> </ul> <p><h3>How to set up F1 help</h3></p> <ol class="1" type="1"> @@ -140,13 +143,41 @@ Select <strong>Assign</strong>, and then select <strong>OK</strong>. </li> </ol> -<p><h3>How to report bugs and contribute code?</h3></p> +<p><h3>How to contribute via GitHub?</h3></p> <ul> <li> - <a title="Bug reports" href="https://bugreports.qt.io/browse/QTVSADDINBUG">Bug reports</a> + <a title="Source code on GitHub" + href="https://github.com/qt-labs/vstools">Source code on GitHub</a> </li> <li> - <a title="Source code" href="https://code.qt.io/cgit/qt-labs/vstools.git">Source code</a> + <a title="Pull requests on GitHub" + href="https://github.com/qt-labs/vstools/pulls">Pull requests on GitHub</a> + </li> +</ul> +<p><h3>How to contribute via Qt Labs?</h3></p> +<ul> + <li> + <a title="Source code on Qt Labs" + href="https://code.qt.io/cgit/qt-labs/vstools.git">Source code on Qt Labs</a> + </li> + <li> + <a title="Qt VS Tools Code Review" + href="https://codereview.qt-project.org/q/project:qt-labs/vstools">Qt VS Tools Code Review</a> + </li> +</ul> +For more information on how to contribute to the Qt Visual Tools via Qt Labs, please look at the + <a title="Qt contribution Guidelines" + href="https://wiki.qt.io/Qt_Contribution_Guidelines"> + Qt contribution Guidelines</a> first. +<p><h3>How to report bugs?</h3></p> +<ul> + <li> + <a title="Qt Bug Tracker" + href="https://bugreports.qt.io/browse/QTVSADDINBUG">Qt Bug Tracker</a> + </li> + <li> + <a title="GitHub Issue Tracker" + href="https://github.com/qt-labs/vstools/issues">GitHub Issue Tracker</a> </li> </ul> <p> diff --git a/QtVsTools.Package/Options/QtOptionsPage.cs b/QtVsTools.Package/Options/QtOptionsPage.cs index 5035285..7da27ae 100644 --- a/QtVsTools.Package/Options/QtOptionsPage.cs +++ b/QtVsTools.Package/Options/QtOptionsPage.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -30,20 +30,20 @@ using System.ComponentModel; using System.Globalization; using System.Linq; -using Microsoft.Win32; +using System.Linq.Expressions; +using System.Reflection; +using Microsoft.Build.Framework; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.Build.Framework; +using Microsoft.Win32; using EnvDTE; -using QtVsTools.Core; -using QtVsTools.Common; -using QtVsTools.VisualStudio; -using System.Reflection; -using System.Linq.Expressions; namespace QtVsTools.Options { - using static EnumExt; + using Core; + using VisualStudio; + + using static Common.EnumExt; public class QtOptionsPage : DialogPage, IQtVsToolsOptions { @@ -85,6 +85,16 @@ [String("BkgBuild_RunQtTools")] RunQtTools, [String("BkgBuild_DebugInfo")] DebugInfo, [String("BkgBuild_LoggerVerbosity")] LoggerVerbosity, + } + + public enum Notifications + { + [String("Notifications_Installed")] Installed, + } + + public enum Natvis + { + [String("LinkNatvis")] Link, } public enum Timeout : uint { Disabled = 0 } @@ -144,8 +154,8 @@ object value, Type destinationType) { - if (value.GetType() == typeof(bool) && destinationType == typeof(string)) - return ((bool)value) ? "Enable" : "Disable"; + if (value is bool b && destinationType == typeof(string)) + return b ? "Enable" : "Disable"; return base.ConvertTo(context, culture, value, destinationType); } } @@ -170,7 +180,7 @@ [DisplayName("Keyboard shortcut")] [Description("To change keyboard mapping, go to: Tools > Options > Keyboard")] [ReadOnly(true)] - public string QtHelpKeyBinding { get; set; } + private string QtHelpKeyBinding { get; set; } [Category("Help")] [DisplayName("Preferred source")] @@ -222,8 +232,25 @@ [Description("Configure verbosity level of background build log.")] public LoggerVerbosity BuildLoggerVerbosity { get; set; } + [Category("Notifications")] + [DisplayName("New version installed")] + [Description("Show notification when a new version was recently installed.")] + [TypeConverter(typeof(EnableDisableConverter))] + public bool NotifyInstalled { get; set; } + + [Category("Natvis")] + [DisplayName("Embed .natvis file into PDB")] + [Description("Embeds the debugger visualizations (.natvis file) into the PDB file" + + "generated by LINK. While setting this option, the embedded Natvis file will" + + "take precedence over user-specific Natvis files(for example the files" + + "located in %USERPROFILE%\\Documents\\Visual Studio 2022\\Visualizers).")] + [TypeConverter(typeof(EnableDisableConverter))] + public bool LinkNatvis { get; set; } + public override void ResetSettings() { + ThreadHelper.ThrowIfNotOnUIThread(); + QtMsBuildPath = ""; QmlDebuggerEnabled = true; QmlDebuggerTimeout = (Timeout)60000; @@ -234,6 +261,8 @@ BuildRunQtTools = ProjectTracking = true; BuildDebugInformation = false; BuildLoggerVerbosity = LoggerVerbosity.Quiet; + NotifyInstalled = true; + LinkNatvis = true; //////// // Get Qt Help keyboard shortcut @@ -252,6 +281,8 @@ public override void LoadSettingsFromStorage() { + ThreadHelper.ThrowIfNotOnUIThread(); + ResetSettings(); try { QtMsBuildPath = Environment.GetEnvironmentVariable("QTMSBUILD"); @@ -271,10 +302,11 @@ Load(() => BuildRunQtTools, key, BkgBuild.RunQtTools); Load(() => BuildDebugInformation, key, BkgBuild.DebugInfo); Load(() => BuildLoggerVerbosity, key, BkgBuild.LoggerVerbosity); + Load(() => NotifyInstalled, key, Notifications.Installed); + Load(() => LinkNatvis, key, Natvis.Link); } } catch (Exception exception) { - Messages.Print( - exception.Message + "\r\n\r\nStacktrace:\r\n" + exception.StackTrace); + exception.Log(); } } @@ -296,7 +328,7 @@ Save(QmlDebuggerEnabled, key, QmlDebug.Enable); Save(QmlDebuggerTimeout, key, QmlDebug.Timeout); Save(HelpPreference, key, Help.Preference); - Save(TryQtHelpOnF1Pressed, key, Help.Preference); + Save(TryQtHelpOnF1Pressed, key, Help.TryOnF1Pressed); Save(DesignerDetached, key, Designer.Detached); Save(LinguistDetached, key, Linguist.Detached); Save(ResourceEditorDetached, key, ResEditor.Detached); @@ -304,10 +336,11 @@ Save(BuildRunQtTools, key, BkgBuild.RunQtTools); Save(BuildDebugInformation, key, BkgBuild.DebugInfo); Save(BuildLoggerVerbosity, key, BkgBuild.LoggerVerbosity); + Save(NotifyInstalled, key, Notifications.Installed); + Save(LinkNatvis, key, Natvis.Link); } } catch (Exception exception) { - Messages.Print( - exception.Message + "\r\n\r\nStacktrace:\r\n" + exception.StackTrace); + exception.Log(); } } diff --git a/QtVsTools.Package/Options/QtVersionsPage.cs b/QtVsTools.Package/Options/QtVersionsPage.cs index f28e8ee..cffc4b7 100644 --- a/QtVsTools.Package/Options/QtVersionsPage.cs +++ b/QtVsTools.Package/Options/QtVersionsPage.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -28,29 +28,37 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Windows; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; -using QtVsTools.Core; namespace QtVsTools.Options { + using Common; + using Core; + using static QtVsTools.Options.QtVersionsTable; + public class QtVersionsPage : UIElementDialogPage { + static LazyFactory Lazy { get; } = new LazyFactory(); + QtVersionManager VersionManager => QtVersionManager.The(); - QtVersionsTable _VersionsTable; - QtVersionsTable VersionsTable => _VersionsTable - ?? (_VersionsTable = new QtVersionsTable()); + QtVersionsTable VersionsTable => Lazy.Get(() => + VersionsTable, () => new QtVersionsTable()); protected override UIElement Child => VersionsTable; public override void LoadSettingsFromStorage() { - var versions = new List<QtVersionsTable.Row>(); + var versions = new List<Row>(); foreach (var versionName in VersionManager.GetVersions()) { var versionPath = VersionManager.GetInstallPath(versionName); + if (string.IsNullOrEmpty(versionPath)) + continue; + BuildHost host = BuildHost.Windows; string compiler = "msvc"; if (versionPath.StartsWith("SSH:") || versionPath.StartsWith("WSL:")) { @@ -65,13 +73,15 @@ compiler = linuxPaths[2]; } var defaultVersion = VersionManager.GetDefaultVersion(); - versions.Add(new QtVersionsTable.Row() + versions.Add(new Row() { IsDefault = (versionName == defaultVersion), VersionName = versionName, + InitialVersionName = versionName, Path = versionPath, Host = host, Compiler = compiler, + State = State.Unknown }); } VersionsTable.UpdateVersions(versions); @@ -79,23 +89,40 @@ public override void SaveSettingsToStorage() { - foreach (var versionName in VersionManager.GetVersions()) { + void RemoveVersion(string versionName) + { try { VersionManager.RemoveVersion(versionName); } catch (Exception exception) { - Messages.Print( - exception.Message + "\r\n\r\nStacktrace:\r\n" + exception.StackTrace); + exception.Log(); } } - foreach (var version in VersionsTable.Versions) { + + var versions = VersionsTable.Versions; + foreach (var version in versions) { + if (version.State.HasFlag(State.Removed)) + RemoveVersion(version.VersionName); + + if (!version.State.HasFlag(State.Modified)) + continue; + try { if (version.Host == BuildHost.Windows) { - var versionInfo = VersionInformation.Get(version.Path); - var generator = versionInfo.GetQMakeConfEntry("MAKEFILE_GENERATOR"); - if (generator != "MSVC.NET" && generator != "MSBUILD") - throw new Exception(SR.GetString( - "AddQtVersionDialog_IncorrectMakefileGenerator", generator)); - VersionManager.SaveVersion(version.VersionName, version.Path); + if (version.State.HasFlag((State)Column.Path)) { + var versionPath = version.Path; + var ignoreCase = StringComparison.CurrentCultureIgnoreCase; + if (Path.GetFileName(versionPath).Equals("qmake.exe", ignoreCase)) + versionPath = Path.GetDirectoryName(versionPath); + if (Path.GetFileName(versionPath).Equals("bin", ignoreCase)) + versionPath = Path.GetDirectoryName(versionPath); + var versionInfo = VersionInformation.Get(versionPath); + var generator = versionInfo.GetQMakeConfEntry("MAKEFILE_GENERATOR"); + if (generator != "MSVC.NET" && generator != "MSBUILD") + throw new Exception(string.Format( + "This Qt version uses an unsupported makefile generator (used: " + + "{0}, supported: MSVC.NET, MSBUILD)", generator)); + VersionManager.SaveVersion(version.VersionName, versionPath); + } } else { string name = version.VersionName; string access = @@ -107,21 +134,34 @@ path = string.Format("{0}:{1}:{2}", access, path, compiler); VersionManager.SaveVersion(name, path, checkPath: false); } + + if (version.State.HasFlag((State)Column.VersionName)) { + try { + VersionManager.SaveVersion(version.VersionName, version.Path); + if (!string.IsNullOrEmpty(version.InitialVersionName)) + VersionManager.RemoveVersion(version.InitialVersionName); + } catch (Exception exception) { + exception.Log(); + } + } } catch (Exception exception) { - Messages.Print( - exception.Message + "\r\n\r\nStacktrace:\r\n" + exception.StackTrace); + exception.Log(); + version.State = State.Removed; + RemoveVersion(version.VersionName); } } + try { - var defaultVersion = VersionsTable.Versions - .Where(version => version.IsDefault) - .FirstOrDefault(); - if (defaultVersion != null) - VersionManager.SaveDefaultVersion(defaultVersion.VersionName); + var defaultVersion = + versions.FirstOrDefault(v => v.IsDefault && v.State != State.Removed) + ?? versions.FirstOrDefault(v => v.State != State.Removed); + VersionManager.SaveDefaultVersion(defaultVersion?.VersionName ?? ""); } catch (Exception exception) { - Messages.Print( - exception.Message + "\r\n\r\nStacktrace:\r\n" + exception.StackTrace); + exception.Log(); } + + if (Notifications.NoQtVersion.IsOpen && VersionManager.GetVersions()?.Any() == true) + Notifications.NoQtVersion.Close(); } protected override void OnApply(PageApplyEventArgs e) diff --git a/QtVsTools.Package/Options/QtVersionsTable.cs b/QtVsTools.Package/Options/QtVersionsTable.cs index dc6f9c5..cb09fff 100644 --- a/QtVsTools.Package/Options/QtVersionsTable.cs +++ b/QtVsTools.Package/Options/QtVersionsTable.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -37,11 +37,12 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using Microsoft.Win32; -using QtVsTools.Common; namespace QtVsTools.Options { - using static EnumExt; + using Common; + using QtVsTools.Core; + using static Common.EnumExt; public enum BuildHost { @@ -52,9 +53,28 @@ public partial class QtVersionsTable : UserControl { + LazyFactory Lazy { get; } = new LazyFactory(); + public QtVersionsTable() { InitializeComponent(); + } + + [Flags] public enum Column + { + IsDefault = 0x10, + VersionName = 0x20, + Host = 0x40, + Path = 0x80, + Compiler = 0x100 + } + + [Flags] public enum State + { + Unknown = 0x00, + Existing = 0x01, + Removed = 0x02, + Modified = 0x04 } public class Field @@ -62,57 +82,66 @@ public string Value { get; set; } public Control Control { get; set; } public DataGridCell Cell { get; set; } - public string ValidationError { get; set; } + private string error; + public string ValidationError { + set { + UpdateUi = value != error; + error = value; + } + get { return error; } + } public bool IsValid => string.IsNullOrEmpty(ValidationError); public ToolTip ToolTip => IsValid ? null : new ToolTip() { Content = ValidationError }; public int SelectionStart { get; set; } + public bool UpdateUi { get; private set; } = false; } public class Row { - public enum FieldNames { IsDefault, VersionName, Host, Path, Compiler } + static LazyFactory StaticLazy { get; } = new LazyFactory(); + LazyFactory Lazy { get; } = new LazyFactory(); - public Dictionary<FieldNames, Field> _Fields; - public Dictionary<FieldNames, Field> Fields => _Fields - ?? (_Fields = GetValues<FieldNames>() - .Select(field => new KeyValuePair<FieldNames, Field>(field, null)) + public Dictionary<Column, Field> Fields => Lazy.Get(() => + Fields, () => GetValues<Column>() + .Select(field => new KeyValuePair<Column, Field>(field, null)) .ToDictionary(keyValue => keyValue.Key, keyValue => keyValue.Value)); - public Field FieldDefault => Fields[FieldNames.IsDefault] - ?? (Fields[FieldNames.IsDefault] = new Field()); + public Field FieldDefault => Fields[Column.IsDefault] + ?? (Fields[Column.IsDefault] = new Field()); public bool IsDefault { get => (FieldDefault.Value == true.ToString()); set => FieldDefault.Value = value.ToString(); } - public Field FieldVersionName => Fields[FieldNames.VersionName] - ?? (Fields[FieldNames.VersionName] = new Field()); + public Field FieldVersionName => Fields[Column.VersionName] + ?? (Fields[Column.VersionName] = new Field()); public string VersionName { get => FieldVersionName.Value; set => FieldVersionName.Value = value; } + public string InitialVersionName { get; set; } - public Field FieldHost => Fields[FieldNames.Host] - ?? (Fields[FieldNames.Host] = new Field()); + public Field FieldHost => Fields[Column.Host] + ?? (Fields[Column.Host] = new Field()); public BuildHost Host { get => FieldHost.Value.Cast(defaultValue: BuildHost.Windows); set => FieldHost.Value = value.Cast<string>(); } - public Field FieldPath => Fields[FieldNames.Path] - ?? (Fields[FieldNames.Path] = new Field()); + public Field FieldPath => Fields[Column.Path] + ?? (Fields[Column.Path] = new Field()); public string Path { get => FieldPath.Value; set => FieldPath.Value = value; } - public Field FieldCompiler => Fields[FieldNames.Compiler] - ?? (Fields[FieldNames.Compiler] = new Field()); + public Field FieldCompiler => Fields[Column.Compiler] + ?? (Fields[Column.Compiler] = new Field()); public string Compiler { get => FieldCompiler.Value; @@ -124,7 +153,7 @@ public bool DefaultEnabled => !IsDefault && !LastRow; public bool NameEnabled => !LastRow; public bool CompilerEnabled => (Host != BuildHost.Windows); - public Visibility RowVisibility + public Visibility RowContentVisibility => LastRow ? Visibility.Hidden : Visibility.Visible; public Visibility ButtonAddVisibility => LastRow ? Visibility.Visible : Visibility.Hidden; @@ -135,17 +164,16 @@ public FontWeight FontWeight => IsDefault ? FontWeights.Bold : FontWeights.Normal; - public static ImageSource _ExplorerIcon; - public static ImageSource ExplorerIcon => _ExplorerIcon - ?? (_ExplorerIcon = GetExplorerIcon()); - } + public static ImageSource ExplorerIcon => StaticLazy.Get(() => + ExplorerIcon, () => GetExplorerIcon()); - public bool IsValid { get; private set; } + public State State { get; set; } = State.Unknown; + public bool RowVisible => State != State.Removed; + } Field FocusedField { get; set; } - List<Row> _Rows; - List<Row> Rows => _Rows ?? (_Rows = new List<Row>()); + List<Row> Rows => Lazy.Get(() => Rows, () => new List<Row>()); public IEnumerable<Row> Versions => Rows.TakeWhile(item => !item.LastRow); public void UpdateVersions(IEnumerable<Row> versions) @@ -154,15 +182,16 @@ Rows.AddRange(versions); Rows.Add(new Row { LastRow = true }); DataGrid.ItemsSource = Rows; - IsValid = true; FocusedField = null; Validate(true); + Rows.ForEach(item => item.State = State.Existing); } public IEnumerable<string> GetErrorMessages() { Validate(true); return Versions + .Where(v => v.State != State.Removed) .SelectMany(v => v.Fields.Values.Select(f => f.ValidationError)) .Where(s => !string.IsNullOrEmpty(s)) .Distinct(); @@ -170,95 +199,73 @@ void Validate(bool mustRefresh) { - ///////////////////////// - // Automatic cell values - foreach (var version in Versions) { - if (version.Host != BuildHost.Windows && version.Compiler == "msvc") { - version.Compiler = "g++"; - version.FieldCompiler.SelectionStart = version.Compiler.Length; - mustRefresh = true; - } else if (version.Host == BuildHost.Windows && version.Compiler != "msvc") { - version.Compiler = "msvc"; - version.FieldCompiler.SelectionStart = version.Compiler.Length; - mustRefresh = true; - } - } - //////////////////////// // Validate cell values - string previousValidation; - bool wasValid = IsValid; - IsValid = true; foreach (var version in Versions) { + if (!version.State.HasFlag(State.Modified)) + continue; ////////////////////// // Default validation - previousValidation = version.FieldDefault.ValidationError; - version.FieldDefault.ValidationError = null; - if (version.IsDefault && version.Host != BuildHost.Windows) { - version.FieldDefault.ValidationError = "Default version: host must be Windows"; - IsValid = false; + if (version.State.HasFlag((State)Column.IsDefault)) { + version.FieldDefault.ValidationError = null; + if (version.IsDefault && version.Host != BuildHost.Windows) + version.FieldDefault.ValidationError = "Default version: Host must be Windows"; + mustRefresh |= version.FieldDefault.UpdateUi; } - if (previousValidation != version.FieldDefault.ValidationError) - mustRefresh = true; /////////////////// // Name validation - previousValidation = version.FieldVersionName.ValidationError; - version.FieldVersionName.ValidationError = null; - if (string.IsNullOrEmpty(version.VersionName)) { - version.FieldVersionName.ValidationError = "Name cannot be empty"; - IsValid = false; - } else if (Versions - .Where(otherVersion => otherVersion != version - && otherVersion.VersionName == version.VersionName) - .Any()) { - version.FieldVersionName.ValidationError = "Duplicate version names"; - IsValid = false; + if (version.State.HasFlag((State)Column.VersionName)) { + version.FieldVersionName.ValidationError = null; + if (string.IsNullOrEmpty(version.VersionName)) { + version.FieldVersionName.ValidationError = "Name cannot be empty"; + } else if (Versions.Where(otherVersion => otherVersion != version + && otherVersion.VersionName == version.VersionName).Any()) { + version.FieldVersionName.ValidationError = "Duplicate version names"; + } + mustRefresh |= version.FieldVersionName.UpdateUi; } - if (previousValidation != version.FieldVersionName.ValidationError) - mustRefresh = true; /////////////////// // Host validation - previousValidation = version.FieldHost.ValidationError; - version.FieldHost.ValidationError = null; - if (version.IsDefault && version.Host != BuildHost.Windows) { - version.FieldHost.ValidationError = "Default version: host must be Windows"; - IsValid = false; + if (version.State.HasFlag((State)Column.Host)) { + version.FieldHost.ValidationError = null; + if (version.IsDefault && version.Host != BuildHost.Windows) + version.FieldHost.ValidationError = "Default version: Host must be Windows"; + mustRefresh |= version.FieldHost.UpdateUi; } - if (previousValidation != version.FieldHost.ValidationError) - mustRefresh = true; /////////////////// // Path validation - previousValidation = version.FieldPath.ValidationError; - version.FieldPath.ValidationError = null; - if (string.IsNullOrEmpty(version.Path)) { - version.FieldPath.ValidationError = "Path cannot be empty"; - IsValid = false; - } else if (version.Host == BuildHost.Windows && !Directory.Exists(version.Path)) { - version.FieldPath.ValidationError = "Path does not exist"; - IsValid = false; + if (version.State.HasFlag((State)Column.Path)) { + version.FieldPath.ValidationError = null; + if (string.IsNullOrEmpty(version.Path)) { + version.FieldPath.ValidationError = "Path cannot be empty"; + } else if (version.Host == BuildHost.Windows) { + string path = NormalizePath(version.Path); + if (path == null) { + version.FieldPath.ValidationError = "Invalid path format"; + } else { + if (!QMake.Exists(path)) + version.FieldPath.ValidationError = "Cannot find qmake.exe"; + } + } + mustRefresh |= version.FieldPath.UpdateUi; } - if (previousValidation != version.FieldPath.ValidationError) - mustRefresh = true; /////////////////////// // Compiler validation - previousValidation = version.FieldCompiler.ValidationError; - version.FieldCompiler.ValidationError = null; - if (string.IsNullOrEmpty(version.Compiler)) { - version.FieldCompiler.ValidationError = "Compiler cannot be empty"; - IsValid = false; + if (version.State.HasFlag((State)Column.Compiler)) { + version.FieldCompiler.ValidationError = null; + if (string.IsNullOrEmpty(version.Compiler)) + version.FieldCompiler.ValidationError = "Compiler cannot be empty"; + mustRefresh |= version.FieldCompiler.UpdateUi; } - if (previousValidation != version.FieldCompiler.ValidationError) - mustRefresh = true; } ////////////////////////////////////// // Refresh versions table if required - mustRefresh |= (wasValid != IsValid); if (mustRefresh) { // Reset bindings foreach (var version in Versions) { @@ -304,22 +311,20 @@ if (sender is Control control && GetBinding(control) is Row version) { if (version.LastRow) return; - - Row.FieldNames field; - if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out field)) + if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out Column column)) return; - var fieldBinding = version.Fields[field]; - fieldBinding.Control = control; - fieldBinding.Cell = FindContainingCell(control); - if (fieldBinding.Cell != null) { - fieldBinding.Cell.Background = - fieldBinding.IsValid ? Brushes.Transparent : InvalidCellBackground; + var field = version.Fields[column]; + field.Control = control; + field.Cell = FindContainingCell(control); + if (field.Cell != null) { + field.Cell.Background = + field.IsValid ? Brushes.Transparent : InvalidCellBackground; } - if (fieldBinding == FocusedField) + if (field == FocusedField) control.Focus(); - if (control is TextBox textBox && fieldBinding.SelectionStart >= 0) - textBox.Select(fieldBinding.SelectionStart, 0); + if (control is TextBox textBox && field.SelectionStart >= 0) + textBox.Select(field.SelectionStart, 0); } } @@ -339,24 +344,24 @@ void Control_GotFocus(object sender, RoutedEventArgs e) { if (sender is Control control && GetBinding(control) is Row version) { - Row.FieldNames field; - if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out field)) + if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out Column column)) return; - var fieldBinding = version.Fields[field]; - if (fieldBinding.Control != control) + + var field = version.Fields[column]; + if (field.Control != control) return; - FocusedField = fieldBinding; + FocusedField = field; } } void Control_LostFocus(object sender, RoutedEventArgs e) { if (sender is Control control && GetBinding(control) is Row version) { - Row.FieldNames field; - if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out field)) + if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out Column column)) return; - var fieldBinding = version.Fields[field]; - if (fieldBinding != FocusedField || fieldBinding.Control != control) + + var field = version.Fields[column]; + if (field != FocusedField || field.Control != control) return; FocusedField = null; } @@ -365,29 +370,32 @@ void TextBox_SelectionChanged(object sender, RoutedEventArgs e) { if (sender is TextBox textBox && GetBinding(textBox) is Row version) { - Row.FieldNames field; - if (string.IsNullOrEmpty(textBox.Name) || !textBox.Name.TryCast(out field)) + if (string.IsNullOrEmpty(textBox.Name) || !textBox.Name.TryCast(out Column column)) return; - var fieldBinding = version.Fields[field]; - if (fieldBinding.Control != textBox) + + var field = version.Fields[column]; + if (field.Control != textBox) return; - fieldBinding.SelectionStart = textBox.SelectionStart; + field.SelectionStart = textBox.SelectionStart; } } void TextBox_TextChanged(object sender, TextChangedEventArgs e) { if (sender is TextBox textBox && GetBinding(textBox) is Row version) { - Row.FieldNames field; - if (string.IsNullOrEmpty(textBox.Name) || !textBox.Name.TryCast(out field)) + if (string.IsNullOrEmpty(textBox.Name) || !textBox.Name.TryCast(out Column column)) return; - var fieldBinding = version.Fields[field]; - if (fieldBinding == null - || fieldBinding.Control != textBox - || fieldBinding.Value == textBox.Text) + + var field = version.Fields[column]; + if (field == null + || field.Control != textBox + || field.Value == textBox.Text) return; - fieldBinding.SelectionStart = textBox.SelectionStart; - fieldBinding.Value = textBox.Text; + + field.SelectionStart = textBox.SelectionStart; + field.Value = textBox.Text; + version.State |= State.Modified | (State)column; + Validate(false); } } @@ -397,28 +405,49 @@ if (sender is ComboBox comboBox && GetBinding(comboBox) is Row version) { if (!comboBox.IsEnabled || comboBox.SelectedIndex < 0) return; + if (string.IsNullOrEmpty(comboBox.Name) || !comboBox.Name.TryCast(out Column column)) + return; + string comboBoxValue = comboBox.Items[comboBox.SelectedIndex] as string; - string controlName = comboBox.Name; - Row.FieldNames field; - if (string.IsNullOrEmpty(controlName) || !controlName.TryCast(out field)) + var field = version.Fields[column]; + if (field == null + || field.Control != comboBox + || field.Value == comboBoxValue) return; - var fieldBinding = version.Fields[field]; - if (fieldBinding == null - || fieldBinding.Control != comboBox - || fieldBinding.Value == comboBoxValue) - return; - fieldBinding.Value = comboBoxValue; - Validate(false); + + field.Value = comboBoxValue; + version.State |= State.Modified | (State)Column.Host; + + bool mustRefresh = false; + if (version.Host != BuildHost.Windows && version.Compiler == "msvc") { + version.Compiler = "g++"; + version.FieldCompiler.SelectionStart = version.Compiler.Length; + version.State |= (State)Column.Compiler; + mustRefresh = true; + } else if (version.Host == BuildHost.Windows && version.Compiler != "msvc") { + version.Compiler = "msvc"; + version.FieldCompiler.SelectionStart = version.Compiler.Length; + version.State |= (State)Column.Compiler; + mustRefresh = true; + } + + Validate(mustRefresh); } + } + + static void SetDefaultState(ref Row version, bool value) + { + version.IsDefault = value; + version.State |= State.Modified | (State)Column.IsDefault; } void Default_Click(object sender, RoutedEventArgs e) { if (sender is CheckBox checkBox && GetBinding(checkBox) is Row version) { - var defaultVersion = Rows.Where(row => row.IsDefault).FirstOrDefault(); + var defaultVersion = Rows.FirstOrDefault(row => row.IsDefault); if (defaultVersion != null) - defaultVersion.IsDefault = false; - version.IsDefault = true; + SetDefaultState(ref defaultVersion, false); + SetDefaultState(ref version, true); Validate(true); } } @@ -427,12 +456,16 @@ { var version = new Row() { - IsDefault = !Versions.Any(), + IsDefault = !Versions.Any(x => x.State != State.Removed), Host = BuildHost.Windows, Path = "", Compiler = "msvc", - LastRow = false + LastRow = false, + State = State.Modified | (State)Column.VersionName | (State)Column.Host + | (State)Column.Path | (State)Column.Compiler }; + if (version.IsDefault) + version.State |= (State)Column.IsDefault; Rows.Insert(Rows.Count - 1, version); FocusedField = version.FieldVersionName; Validate(true); @@ -441,10 +474,26 @@ void Remove_Click(object sender, RoutedEventArgs e) { if (sender is Button button && GetBinding(button) is Row version) { - Rows.Remove(version); - if (version.IsDefault && Versions.Any()) - Versions.First().IsDefault = true; + version.State = State.Removed; + if (version.IsDefault) { + var first = Versions.FirstOrDefault(x => x.State != State.Removed); + if (first != null) + SetDefaultState(ref first, true); + } Validate(true); + } + } + + static string NormalizePath(string path) + { + if (string.IsNullOrEmpty(path)) + return path; + try { + return Path.GetFullPath(new Uri(path).LocalPath) + .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + .ToUpperInvariant(); + } catch (UriFormatException) { + return null; } } @@ -462,6 +511,7 @@ if (openFileDialog.ShowDialog() == true) { var qmakePath = openFileDialog.FileName; var qmakeDir = Path.GetDirectoryName(qmakePath); + var previousPath = NormalizePath(version.Path); if (Path.GetFileName(qmakeDir) .Equals("bin", StringComparison.InvariantCultureIgnoreCase)) { qmakeDir = Path.GetDirectoryName(qmakeDir); @@ -469,12 +519,18 @@ } else { version.Path = qmakePath; } + + if (previousPath != NormalizePath(version.Path)) + version.State |= State.Modified | (State)Column.Path; + if (string.IsNullOrEmpty(version.VersionName)) { version.VersionName = string.Format("{0}_{1}", Path.GetFileName(Path.GetDirectoryName(qmakeDir)), Path.GetFileName(qmakeDir)) .Replace(" ", "_"); + version.State |= State.Modified | (State)Column.VersionName; } + Validate(true); } } @@ -503,9 +559,9 @@ static object GetBinding(FrameworkElement control) { if (control == null - || control.BindingGroup == null - || control.BindingGroup.Items == null - || control.BindingGroup.Items.Count == 0) { + || control.BindingGroup == null + || control.BindingGroup.Items == null + || control.BindingGroup.Items.Count == 0) { return null; } return control.BindingGroup.Items[0]; @@ -515,7 +571,7 @@ { while (control != null) { if (control is ContentPresenter contentPresenter - && contentPresenter.Parent is DataGridCell cell) { + && contentPresenter.Parent is DataGridCell cell) { return cell; } control = VisualTreeHelper.GetParent(control); diff --git a/QtVsTools.Package/Options/QtVersionsTable.xaml b/QtVsTools.Package/Options/QtVersionsTable.xaml index 1b147ff..9f85dc3 100644 --- a/QtVsTools.Package/Options/QtVersionsTable.xaml +++ b/QtVsTools.Package/Options/QtVersionsTable.xaml @@ -1,7 +1,7 @@ <!-- /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -32,7 +32,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:local="clr-namespace:QtVsTools.Options" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> @@ -58,7 +57,13 @@ Color="Transparent" /> <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" /> + <BooleanToVisibilityConverter x:Key="b2v" /> </DataGrid.Resources> + <DataGrid.RowStyle> + <Style TargetType="{x:Type DataGridRow}"> + <Setter Property="Visibility" Value="{Binding RowVisible, Converter={StaticResource b2v}}"/> + </Style> + </DataGrid.RowStyle> <DataGrid.CellStyle> <Style TargetType="DataGridCell"> <Setter Property="BorderThickness" @@ -76,8 +81,7 @@ <CheckBox x:Name="IsDefault" IsChecked="{Binding IsDefault}" Focusable="{Binding DefaultEnabled}" - IsHitTestVisible="{Binding DefaultEnabled}" - Visibility="{Binding RowVisibility}" + Visibility="{Binding RowContentVisibility}" BorderThickness="1" Background="Transparent" VerticalAlignment="Center" @@ -94,7 +98,7 @@ <!--//// Name ////--> <Grid> <Button Cursor="Hand" - Visibility="{Binding RowVisibility}" + Visibility="{Binding RowContentVisibility}" HorizontalAlignment="Left" VerticalAlignment="Center" Click="Remove_Click"> @@ -153,7 +157,7 @@ </Button> <TextBox x:Name="VersionName" Text="{Binding VersionName}" - Visibility="{Binding RowVisibility}" + Visibility="{Binding RowContentVisibility}" IsEnabled="{Binding NameEnabled}" FontWeight="{Binding FontWeight}" Margin="20,4,2,4" @@ -166,7 +170,7 @@ LostFocus="Control_LostFocus" TextChanged="TextBox_TextChanged" SelectionChanged="TextBox_SelectionChanged" - ToolTip="{Binding FieldName.ToolTip}"> + ToolTip="{Binding FieldVersionName.ToolTip}"> <TextBox.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LimeGreen" /> @@ -181,7 +185,7 @@ <DataTemplate> <!--//// Host ////--> <ComboBox x:Name="Host" - Visibility="{Binding RowVisibility}" + Visibility="{Binding RowContentVisibility}" IsEditable="True" IsReadOnly="True" BorderThickness="0" @@ -233,7 +237,7 @@ </Button> <TextBox x:Name="Path" Text="{Binding Path}" - Visibility="{Binding RowVisibility}" + Visibility="{Binding RowContentVisibility}" BorderThickness="0" Background="Transparent" Margin="{Binding PathMargin}" @@ -260,7 +264,7 @@ <!--//// Compiler ////--> <TextBox x:Name="Compiler" Text="{Binding Compiler}" - Visibility="{Binding RowVisibility}" + Visibility="{Binding RowContentVisibility}" IsEnabled="{Binding CompilerEnabled}" BorderThickness="0" Background="Transparent" diff --git a/QtVsTools.Package/Package/DteEventsHandler.cs b/QtVsTools.Package/Package/DteEventsHandler.cs index c7304c0..df8bfc4 100644 --- a/QtVsTools.Package/Package/DteEventsHandler.cs +++ b/QtVsTools.Package/Package/DteEventsHandler.cs @@ -26,44 +26,45 @@ ** ****************************************************************************/ -using EnvDTE; -using EnvDTE80; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.VCProjectEngine; -using QtVsTools.Core; -using QtVsTools.Core.QtMsBuild; -using QtVsTools.QtMsBuild; using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text.RegularExpressions; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; +using EnvDTE; +using EnvDTE80; namespace QtVsTools { + using Core; + using QtMsBuild; + class DteEventsHandler { - private DTE dte; - private SolutionEvents solutionEvents; - private BuildEvents buildEvents; - private DocumentEvents documentEvents; - private ProjectItemsEvents projectItemsEvents; + private readonly DTE dte; + private readonly SolutionEvents solutionEvents; + private readonly BuildEvents buildEvents; + private readonly DocumentEvents documentEvents; + private readonly ProjectItemsEvents projectItemsEvents; private vsBuildAction currentBuildAction = vsBuildAction.vsBuildActionBuild; private VCProjectEngineEvents vcProjectEngineEvents; - private CommandEvents debugStartEvents; - private CommandEvents debugStartWithoutDebuggingEvents; - private CommandEvents f1HelpEvents; - private int dispId_VCFileConfiguration_ExcludedFromBuild; - private int dispId_VCCLCompilerTool_UsePrecompiledHeader; - private int dispId_VCCLCompilerTool_PrecompiledHeaderThrough; - private int dispId_VCCLCompilerTool_PreprocessorDefinitions; - private int dispId_VCCLCompilerTool_AdditionalIncludeDirectories; + private readonly CommandEvents debugStartEvents; + private readonly CommandEvents debugStartWithoutDebuggingEvents; + private readonly CommandEvents f1HelpEvents; + private WindowEvents windowEvents; + private readonly int dispId_VCFileConfiguration_ExcludedFromBuild; + private readonly int dispId_VCCLCompilerTool_UsePrecompiledHeader; + private readonly int dispId_VCCLCompilerTool_PrecompiledHeaderThrough; + private readonly int dispId_VCCLCompilerTool_PreprocessorDefinitions; + private readonly int dispId_VCCLCompilerTool_AdditionalIncludeDirectories; public DteEventsHandler(DTE _dte) { + ThreadHelper.ThrowIfNotOnUIThread(); + dte = _dte; var events = dte.Events as Events2; @@ -85,6 +86,9 @@ solutionEvents.Opened += SolutionEvents_Opened; solutionEvents.AfterClosing += SolutionEvents_AfterClosing; + windowEvents = events.WindowEvents; + windowEvents.WindowActivated += WindowEvents_WindowActivated; + var debugCommandsGUID = "{5EFC7975-14BC-11CF-9B2B-00AA00573819}"; debugStartEvents = events.get_CommandEvents(debugCommandsGUID, 295); debugStartEvents.BeforeExecute += debugStartEvents_BeforeExecute; @@ -105,15 +109,33 @@ InitializeVCProjects(); } + private void WindowEvents_WindowActivated(Window gotFocus, Window lostFocus) + { + ThreadHelper.ThrowIfNotOnUIThread(); + if (dte.MainWindow?.Visible == true) { + windowEvents.WindowActivated -= WindowEvents_WindowActivated; + windowEvents = null; + QtVsToolsPackage.Instance.VsMainWindowActivated(); + } + } + private void F1HelpEvents_BeforeExecute( string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault) { - if (QtVsToolsPackage.Instance.Options.TryQtHelpOnF1Pressed && QtHelp.QueryEditorContextHelp()) + ThreadHelper.ThrowIfNotOnUIThread(); + if (QtVsToolsPackage.Instance.Options.TryQtHelpOnF1Pressed) { + if (!QtHelp.ShowEditorContextHelp()) { + Messages.Print("No help match was found. You can still try to search online at " + + "https://doc.qt.io" + ".", false, true); + } CancelDefault = true; + } } void debugStartEvents_BeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault) { + ThreadHelper.ThrowIfNotOnUIThread(); + var debugger = dte.Debugger; if (debugger != null && debugger.CurrentMode != dbgDebugMode.dbgDesignMode) return; @@ -147,6 +169,8 @@ public void Disconnect() { + ThreadHelper.ThrowIfNotOnUIThread(); + if (buildEvents != null) { buildEvents.OnBuildBegin -= buildEvents_OnBuildBegin; buildEvents.OnBuildProjConfigBegin -= OnBuildProjConfigBegin; @@ -174,12 +198,19 @@ if (debugStartWithoutDebuggingEvents != null) debugStartWithoutDebuggingEvents.BeforeExecute -= debugStartWithoutDebuggingEvents_BeforeExecute; - if (vcProjectEngineEvents != null) + if (vcProjectEngineEvents != null) { vcProjectEngineEvents.ItemPropertyChange -= OnVCProjectEngineItemPropertyChange; + vcProjectEngineEvents.ItemPropertyChange2 -= OnVCProjectEngineItemPropertyChange2; + } + + if (windowEvents != null) + windowEvents.WindowActivated -= WindowEvents_WindowActivated; } public void OnBuildProjConfigBegin(string projectName, string projectConfig, string platform, string solutionConfig) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!QtVsToolsPackage.Instance.LegacyOptions.PreBuildSetup) return; @@ -195,7 +226,7 @@ break; } } - if (project == null || !HelperFunctions.IsQtProject(project)) + if (project == null || !HelperFunctions.IsVsToolsProject(project)) return; if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings) @@ -229,9 +260,11 @@ public void DocumentSaved(Document document) { + ThreadHelper.ThrowIfNotOnUIThread(); + var qtPro = QtProject.Create(document.ProjectItem.ContainingProject); - if (!HelperFunctions.IsQtProject(qtPro.VCProject)) + if (!HelperFunctions.IsVsToolsProject(qtPro.VCProject)) return; var file = (VCFile)((IVCCollection)qtPro.VCProject.Files).Item(document.FullName); @@ -323,10 +356,13 @@ public void ProjectItemsEvents_ItemAdded(ProjectItem projectItem) { + ThreadHelper.ThrowIfNotOnUIThread(); + var project = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte); var qtPro = QtProject.Create(project); - if (!HelperFunctions.IsQtProject(project)) + if (!HelperFunctions.IsVsToolsProject(project)) return; + var vcFile = GetVCFileFromProject(projectItem.Name, qtPro.VCProject); if (vcFile == null) return; @@ -373,12 +409,15 @@ HelperFunctions.EnsureCustomBuildToolAvailable(projectItem); qtPro.UpdateRccStep(vcFile, null); } else if (HelperFunctions.IsTranslationFile(vcFile.Name)) { + Translation.RunlUpdate(vcFile); } } catch { } } void ProjectItemsEvents_ItemRemoved(ProjectItem ProjectItem) { + ThreadHelper.ThrowIfNotOnUIThread(); + var pro = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte); if (pro == null) return; @@ -389,6 +428,8 @@ void ProjectItemsEvents_ItemRenamed(ProjectItem ProjectItem, string OldName) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (OldName == null) return; var pro = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte); @@ -397,12 +438,15 @@ var qtPro = QtProject.Create(pro); qtPro.RemoveGeneratedFiles(OldName); + ProjectItemsEvents_ItemAdded(ProjectItem); } void SolutionEvents_ProjectAdded(Project project) { - if (HelperFunctions.IsQMakeProject(project)) { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (HelperFunctions.IsQtProject(project)) { InitializeVCProject(project); QtProjectTracker.Add(project); var vcpro = project.Object as VCProject; @@ -446,9 +490,11 @@ public void SolutionEvents_Opened() { + ThreadHelper.ThrowIfNotOnUIThread(); + QtProjectTracker.SolutionPath = QtVsToolsPackage.Instance.Dte.Solution.FullName; foreach (var p in HelperFunctions.ProjectsInSolution(QtVsToolsPackage.Instance.Dte)) { - if (HelperFunctions.IsQtProject(p)) { + if (HelperFunctions.IsVsToolsProject(p)) { InitializeVCProject(p); QtProjectTracker.Add(p); } @@ -464,14 +510,18 @@ void InitializeVCProjects() { + ThreadHelper.ThrowIfNotOnUIThread(); + foreach (var project in HelperFunctions.ProjectsInSolution(dte)) { - if (project != null && HelperFunctions.IsQtProject(project)) + if (project != null && HelperFunctions.IsVsToolsProject(project)) InitializeVCProject(project); } } void InitializeVCProject(Project p) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (vcProjectEngineEvents != null) return; @@ -480,12 +530,12 @@ return; // Retrieves the VCProjectEngine from the given project and registers the handlers for VCProjectEngineEvents. - var prjEngine = vcPrj.VCProjectEngine as VCProjectEngine; - if (prjEngine != null) { + if (vcPrj.VCProjectEngine is VCProjectEngine prjEngine) { vcProjectEngineEvents = prjEngine.Events as VCProjectEngineEvents; if (vcProjectEngineEvents != null) { try { vcProjectEngineEvents.ItemPropertyChange += OnVCProjectEngineItemPropertyChange; + vcProjectEngineEvents.ItemPropertyChange2 += OnVCProjectEngineItemPropertyChange2; } catch { Messages.DisplayErrorMessage("VCProjectEngine events could not be registered."); } @@ -495,7 +545,6 @@ private void OnVCProjectEngineItemPropertyChange(object item, object tool, int dispid) { - //System.Diagnostics.Debug.WriteLine("OnVCProjectEngineItemPropertyChange " + dispid.ToString()); var vcFileCfg = item as VCFileConfiguration; if (vcFileCfg == null) { // A global or project specific property has changed. @@ -506,7 +555,7 @@ var vcPrj = vcCfg.project as VCProject; if (vcPrj == null) return; - if (!HelperFunctions.IsQtProject(vcPrj)) + if (!HelperFunctions.IsVsToolsProject(vcPrj)) return; // Ignore property events when using shared compiler properties if (QtProject.GetFormatVersion(vcPrj) >= Resources.qtMinFormatVersion_ClProperties) @@ -538,7 +587,7 @@ var vcPrj = vcFile.project as VCProject; if (vcPrj == null) return; - if (!HelperFunctions.IsQtProject(vcPrj)) + if (!HelperFunctions.IsVsToolsProject(vcPrj)) return; // Ignore property events when using shared compiler properties if (QtProject.GetFormatVersion(vcPrj) >= Resources.qtMinFormatVersion_ClProperties) @@ -557,10 +606,27 @@ } } + private void OnVCProjectEngineItemPropertyChange2( + object item, + string propertySheet, + string itemType, + string propertyName) + { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!propertyName.StartsWith("Qt") || propertyName == "QtLastBackgroundBuild") + return; + if (item is VCConfiguration vcConfig + && vcConfig.project is VCProject vcProject + && vcProject.Object is Project project) { + QtProjectIntellisense.Refresh( + QtProjectTracker.Get(project, project.FullName).Project, vcConfig.Name); + } + } + private static VCFile GetVCFileFromProject(string absFileName, VCProject project) { foreach (VCFile f in (IVCCollection)project.Files) { - if (f.Name.ToLower() == absFileName.ToLower()) + if (f.Name.Equals(absFileName, StringComparison.OrdinalIgnoreCase)) return f; } return null; @@ -574,8 +640,7 @@ var pi = type.GetProperty(propertyName); if (pi != null) { foreach (Attribute attribute in pi.GetCustomAttributes(true)) { - var dispIdAttribute = attribute as DispIdAttribute; - if (dispIdAttribute != null) + if (attribute is DispIdAttribute dispIdAttribute) return dispIdAttribute.Value; } } diff --git a/QtVsTools.Package/Package/ExtLoader.cs b/QtVsTools.Package/Package/ExtLoader.cs index 83885ac..76fc8bf 100644 --- a/QtVsTools.Package/Package/ExtLoader.cs +++ b/QtVsTools.Package/Package/ExtLoader.cs @@ -26,22 +26,27 @@ ** ****************************************************************************/ -using Microsoft.VisualStudio.VCProjectEngine; -using QtVsTools.Core; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; namespace QtVsTools { + using Core; + public static class ExtLoader { public static void ImportProFile() { + ThreadHelper.ThrowIfNotOnUIThread(); + var vm = QtVersionManager.The(); var qtVersion = vm.GetDefaultVersion(); var qtDir = vm.GetInstallPath(qtVersion); + if (qtDir == null) { Messages.DisplayErrorMessage(SR.GetString("CannotFindQMake")); return; @@ -59,11 +64,13 @@ public static void ImportPriFile(EnvDTE.Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project == null) return; VCProject vcproj; - if (!HelperFunctions.IsQtProject(project)) + if (!HelperFunctions.IsVsToolsProject(project)) return; vcproj = project.Object as VCProject; @@ -87,10 +94,12 @@ public static void ImportPriFile(EnvDTE.Project project, string fileName) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project == null) return; - if (!HelperFunctions.IsQtProject(project)) + if (!HelperFunctions.IsVsToolsProject(project)) return; var vcproj = project.Object as VCProject; @@ -134,6 +143,8 @@ private static List<string> ResolveFilesFromQMake(string[] files, EnvDTE.Project project, string path) { + ThreadHelper.ThrowIfNotOnUIThread(); + var lst = new List<string>(); foreach (var file in files) { var s = ResolveEnvironmentVariables(file, project); diff --git a/QtVsTools.Package/Package/Notifications.cs b/QtVsTools.Package/Package/Notifications.cs new file mode 100644 index 0000000..de0a639 --- /dev/null +++ b/QtVsTools.Package/Package/Notifications.cs @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using Microsoft.VisualStudio.Imaging; +using Microsoft.VisualStudio.Shell; + +namespace QtVsTools +{ + using Common; + using Microsoft.VisualStudio.Imaging.Interop; + using VisualStudio; + + public static class Notifications + { + static LazyFactory StaticLazy { get; } = new LazyFactory(); + + public static NoQtVersion NoQtVersion + => StaticLazy.Get(() => NoQtVersion, () => new NoQtVersion()); + + public static NotifyInstall NotifyInstall + => StaticLazy.Get(() => NotifyInstall, () => new NotifyInstall()); + } + + public class NoQtVersion : InfoBarMessage + { + protected override ImageMoniker Icon => KnownMonikers.StatusWarning; + + protected override TextSpan[] Text => new TextSpan[] + { + new TextSpan { Bold = true, Text = "Qt Visual Studio Tools" }, + new TextSpacer(2), + "\u2014", // Em dash + new TextSpacer(2), + "You must select a Qt version to use for development." + }; + + protected override Hyperlink[] Hyperlinks => new Hyperlink[] + { + new Hyperlink + { + Text = "Select Qt version...", + CloseInfoBar = false, + OnClicked = () => + QtVsToolsPackage.Instance.ShowOptionPage(typeof(Options.QtVersionsPage)) + } + }; + } + + public class NotifyInstall : InfoBarMessage + { + protected override ImageMoniker Icon => KnownMonikers.StatusInformation; + + protected override TextSpan[] Text => new TextSpan[] + { + new TextSpan { Bold = true, Text = "Qt Visual Studio Tools" }, + new TextSpacer(2), + "\u2014", // Em dash + new TextSpacer(2), + $"Version {Version.USER_VERSION} was recently installed." + }; + + protected override Hyperlink[] Hyperlinks => new Hyperlink[] + { + new Hyperlink + { + Text = "Release Notes", + CloseInfoBar = false, + OnClicked= () => + { + VsShellUtilities.OpenSystemBrowser( + "https://code.qt.io/cgit/qt-labs/vstools.git/tree/Changelog"); + } + }, + new Hyperlink + { + Text = "Don't show again", + CloseInfoBar = true, + OnClicked = () => + { + QtVsToolsPackage.Instance.Options.NotifyInstalled = false; + QtVsToolsPackage.Instance.Options.SaveSettingsToStorage(); + } + } + }; + } +} diff --git a/QtVsTools.Package/Package/QMakeWrapper.cs b/QtVsTools.Package/Package/QMakeWrapper.cs index 11b0614..61f7bcb 100644 --- a/QtVsTools.Package/Package/QMakeWrapper.cs +++ b/QtVsTools.Package/Package/QMakeWrapper.cs @@ -37,7 +37,7 @@ public string QtDir { get; set; } public bool IsFlat { get; private set; } - public bool IsValid { get; private set; } + private bool IsValid { get; set; } public string[] SourceFiles { get; private set; } public string[] HeaderFiles { get; private set; } diff --git a/QtVsTools.Package/Package/QtHelp.cs b/QtVsTools.Package/Package/QtHelp.cs index e36cb83..12e7b19 100644 --- a/QtVsTools.Package/Package/QtHelp.cs +++ b/QtVsTools.Package/Package/QtHelp.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,13 +26,6 @@ ** ****************************************************************************/ -using EnvDTE; -using Microsoft.VisualStudio.Settings; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.Shell.Settings; -using QtVsTools.Core; -using QtVsTools.VisualStudio; using System; using System.Collections.Generic; using System.ComponentModel.Design; @@ -40,37 +33,36 @@ using System.Data.SQLite; using System.IO; using System.Linq; -using System.Threading.Tasks; -using Task = System.Threading.Tasks.Task; +using EnvDTE; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; namespace QtVsTools { + using Core; + using VisualStudio; + public class QtHelp { public enum SourcePreference { Online, Offline } - public static QtHelp Instance + private static QtHelp Instance { get; - private set; + set; } - public static void Initialize(Package package) + public static void Initialize() { - Instance = new QtHelp(package); + Instance = new QtHelp(); } const int F1QtHelpId = 0x0502; - readonly Package package; - public static readonly Guid MainMenuGuid = new Guid("58f83fff-d39d-4c66-810b-2702e1f04e73"); + private static readonly Guid MainMenuGuid = new Guid("58f83fff-d39d-4c66-810b-2702e1f04e73"); - QtHelp(Package pkg) + private QtHelp() { - if (pkg == null) - throw new ArgumentNullException("package"); - package = pkg; - var commandService = VsServiceProvider .GetService<IMenuCommandService, OleMenuCommandService>(); if (commandService == null) @@ -79,12 +71,6 @@ var menuCommandID = new CommandID(MainMenuGuid, F1QtHelpId); commandService.AddCommand(new MenuCommand(F1QtHelpEventHandler, menuCommandID)); } - - IServiceProvider ServiceProvider - { - get { return package; } - } - static bool IsSuperfluousCharacter(string text) { switch (text) { @@ -131,11 +117,17 @@ void F1QtHelpEventHandler(object sender, EventArgs args) { - QueryEditorContextHelp(true); + ThreadHelper.ThrowIfNotOnUIThread(); + if (!ShowEditorContextHelp()) { + Messages.Print("No help match was found. You can still try to search online at " + + "https://doc.qt.io" + ".", false, true); + } } - public static bool QueryEditorContextHelp(bool defaultTryOnline = false) + public static bool ShowEditorContextHelp() { + ThreadHelper.ThrowIfNotOnUIThread(); + try { var dte = VsServiceProvider.GetService<SDTE, DTE>(); var objTextDocument = dte?.ActiveDocument?.Object() as TextDocument; @@ -173,7 +165,7 @@ var project = HelperFunctions.GetSelectedQtProject(dte); if (project == null) { project = HelperFunctions.GetSelectedProject(dte); - if (project != null && HelperFunctions.IsQMakeProject(project)) { + if (project != null && HelperFunctions.IsQtProject(project)) { var qmakeQtDir = HelperFunctions.GetQtDirFromQMakeProject(project); qtVersion = QtVersionManager.The().GetQtVersionFromInstallDir(qmakeQtDir); } @@ -188,7 +180,7 @@ var qchFiles = Directory.GetFiles(docPath, "*?.qch"); if (qchFiles.Length == 0) - return false; + return TryShowGenericSearchResultsOnline(keyword, info.qtMajor); var offline = QtVsToolsPackage.Instance.Options.HelpPreference == SourcePreference.Offline; @@ -207,8 +199,9 @@ using (var connection = new SQLiteConnection(builder.ToString())) { connection.Open(); using (var command = new SQLiteCommand(linksForKeyword, connection)) { - using (var reader = - Task.Run(async () => await command.ExecuteReaderAsync()).Result) { + var reader = QtVsToolsPackage.Instance.JoinableTaskFactory + .Run(async () => await command.ExecuteReaderAsync()); + using (reader) { while (reader.Read()) { var title = GetString(reader, 0); if (string.IsNullOrWhiteSpace(title)) @@ -233,15 +226,7 @@ var uri = string.Empty; switch (links.Values.Count) { case 0: - if (!offline && defaultTryOnline) { - uri = new UriBuilder($"https://doc.qt.io/qt-{info.qtMajor}/search-results.html") - { - Query = "q=" + keyword - }.ToString(); - } else { - return false; - } - break; + return TryShowGenericSearchResultsOnline(keyword, info.qtMajor); case 1: uri = links.First().Value; break; @@ -254,34 +239,40 @@ }; if (!dialog.ShowModal().GetValueOrDefault()) return false; - uri = dialog.Link - .Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + uri = dialog.Link; break; } - if (string.IsNullOrEmpty(uri)) { // offline mode without a single search hit - VsShellUtilities.ShowMessageBox(Instance.ServiceProvider, - "Your search - " + keyword + " - did not match any documents.", + uri = HelperFunctions.FromNativeSeparators(uri); + var helpUri = new Uri(uri); + if (helpUri.IsFile && !File.Exists(helpUri.LocalPath)) { + VsShellUtilities.ShowMessageBox(QtVsToolsPackage.Instance, + "Your search - " + keyword + " - did match a document, but it could " + + "not be found on disk. To use the online help, select: " + + "Tools | Options | Qt | Preferred source | Online", string.Empty, OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } else { - var helpUri = new Uri(uri.Replace('\\', '/')); - if (helpUri.IsFile && !File.Exists(helpUri.LocalPath)) { - VsShellUtilities.ShowMessageBox(Instance.ServiceProvider, - "Your search - " + keyword + " - did match a document, but it could " - + "not be found on disk. To use the online help, select: " - + "Help | Set Qt Help Preference | Use Online Documentation", - string.Empty, OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK, - OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); - } else { - VsShellUtilities.OpenSystemBrowser(HelperFunctions.ChangePathFormat(uri)); - } + VsShellUtilities.OpenSystemBrowser(uri); } - } catch (Exception e) { - Messages.Print( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); } return true; } + + private static bool TryShowGenericSearchResultsOnline(string keyword, uint version) + { + if (QtVsToolsPackage.Instance.Options.HelpPreference != SourcePreference.Online) + return false; + + VsShellUtilities.OpenSystemBrowser(HelperFunctions.FromNativeSeparators( + new UriBuilder($"https://doc.qt.io/qt-{version}/search-results.html") + { + Query = "q=" + keyword + }.ToString()) + ); + return true; + } } } diff --git a/QtVsTools.Package/Package/QtHelpLinkChooser.xaml b/QtVsTools.Package/Package/QtHelpLinkChooser.xaml index d901292..adfa3d6 100644 --- a/QtVsTools.Package/Package/QtHelpLinkChooser.xaml +++ b/QtVsTools.Package/Package/QtHelpLinkChooser.xaml @@ -1,7 +1,7 @@ <!-- ***************************************************************************** ** - ** Copyright (C) 2016 The Qt Company Ltd. + ** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -28,33 +28,31 @@ ***************************************************************************** --> -<local:VsToolsDialogWindow x:Class="QtVsTools.QtHelpLinkChooser" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:local="clr-namespace:QtVsTools" - Width="400" - Height="250" - MinWidth="400" - MinHeight="250" - mc:Ignorable="d" - Title="Choose Topic" - ShowInTaskbar="False" - HasHelpButton="False" - HasMinimizeButton="False" - ResizeMode="CanResizeWithGrip" - WindowStartupLocation="CenterOwner"> - <local:VsToolsDialogWindow.Resources> - <BooleanToVisibilityConverter x:Key="b2v" /> +<vsui:DialogWindow x:Class="QtVsTools.QtHelpLinkChooser" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:vsui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.15.0" + Width="400" + Height="250" + MinWidth="400" + MinHeight="250" + mc:Ignorable="d" + Title="Choose Topic" + ShowInTaskbar="False" + HasHelpButton="False" + HasMinimizeButton="False" + ResizeMode="CanResizeWithGrip" + WindowStartupLocation="CenterOwner"> + <vsui:DialogWindow.Resources> <Style x:Key="ListBoxDoubleClickStyle" TargetType="ListBoxItem"> <EventSetter Event="MouseDoubleClick" Handler="OnListBoxItem_DoubleClick" /> </Style> - </local:VsToolsDialogWindow.Resources> - <Grid Margin="10" - FocusManager.FocusedElement="{Binding ElementName=searchBox}"> + </vsui:DialogWindow.Resources> + <Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> @@ -68,18 +66,8 @@ Text="{Binding Path=Keyword}" /> <Run Text=":" /> </TextBlock> - <Grid Grid.Row="1" - MinHeight="22" - Background="White"> - <TextBlock Text=" Filter..." - Foreground="LightSteelBlue" - VerticalAlignment="Center" - Visibility="{Binding ElementName=searchBox, - Path=Text.IsEmpty, Converter={StaticResource b2v}}" /> - <TextBox Name="searchBox" - Background="Transparent" - TextChanged="OnSearchBox_TextChanged" - VerticalContentAlignment="Center" /> + <Grid Grid.Row="1"> + <Grid Name="searchControlHost" /> </Grid> <ListBox Grid.Row="2" Margin="0,10,0,0" @@ -104,4 +92,4 @@ Margin="0,10,0,0" /> </StackPanel> </Grid> -</local:VsToolsDialogWindow> +</vsui:DialogWindow> diff --git a/QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs b/QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs index 290f966..8d71431 100644 --- a/QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs +++ b/QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -32,10 +32,14 @@ using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; +using Microsoft.VisualStudio.PlatformUI; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using QtVsTools.VisualStudio; namespace QtVsTools { - partial class QtHelpLinkChooser : VsToolsDialogWindow + partial class QtHelpLinkChooser : DialogWindow { public QtHelpLinkChooser() { @@ -46,28 +50,32 @@ } public string Link { get; set; } + public string SearchText { get; set; } + public string Keyword { private get; set; } public Dictionary<string, string> Links { private get; set; } private void OnLoaded(object sender, RoutedEventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var view = CollectionViewSource.GetDefaultView(linkListBox.ItemsSource); view.Filter = obj => { - if (string.IsNullOrEmpty(searchBox.Text)) + if (string.IsNullOrEmpty(SearchText)) return true; var item = (KeyValuePair<string, string>)obj; - return item.Key.IndexOf(searchBox.Text, StringComparison.OrdinalIgnoreCase) >= 0; + return item.Key.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0; }; linkListBox.SelectedIndex = 0; - } - private void OnSearchBox_TextChanged(object sender, TextChangedEventArgs e) - { - CollectionViewSource.GetDefaultView(linkListBox.ItemsSource).Refresh(); - if (linkListBox.Items.Count == 1 || linkListBox.SelectedItem == null) - linkListBox.SelectedIndex = 0; + var factory = VsServiceProvider + .GetService<SVsWindowSearchHostFactory, IVsWindowSearchHostFactory>(); + var host = factory.CreateWindowSearchHost(searchControlHost); + + host.SetupSearch(new ListBoxSearch(linkListBox, value => SearchText = value)); + host.Activate(); // set focus } private void OnListBoxItem_DoubleClick(object sender, MouseButtonEventArgs e) diff --git a/QtVsTools.Package/Package/QtItemContextMenu.cs b/QtVsTools.Package/Package/QtItemContextMenu.cs index 19bc389..ce4f888 100644 --- a/QtVsTools.Package/Package/QtItemContextMenu.cs +++ b/QtVsTools.Package/Package/QtItemContextMenu.cs @@ -26,15 +26,16 @@ ** ****************************************************************************/ -using EnvDTE; -using Microsoft.VisualStudio.Shell; -using QtVsTools.Core; -using QtVsTools.VisualStudio; using System; using System.ComponentModel.Design; +using Microsoft.VisualStudio.Shell; +using EnvDTE; namespace QtVsTools { + using Core; + using VisualStudio; + /// <summary> /// Command handler /// </summary> @@ -43,30 +44,24 @@ /// <summary> /// Command menu group (command set GUID). /// </summary> - public static readonly Guid ItemContextMenuGuid = new Guid("9f67a0bd-ee0a-47e3-b656-5efb12e3c770"); + private static readonly Guid ItemContextMenuGuid = new Guid("9f67a0bd-ee0a-47e3-b656-5efb12e3c770"); /// <summary> /// Gets the instance of the command. /// </summary> - public static QtItemContextMenu Instance + private static QtItemContextMenu Instance { get; - private set; + set; } /// <summary> /// Initializes the singleton instance of the command. /// </summary> - /// <param name="package">Owner package, not null.</param> - public static void Initialize(Package package) + public static void Initialize() { - Instance = new QtItemContextMenu(package); + Instance = new QtItemContextMenu(); } - - /// <summary> - /// VS Package that provides this command, not null. - /// </summary> - private readonly Package m_package; /// <summary> /// Command ID. @@ -78,14 +73,8 @@ /// Initializes a new instance of the <see cref="QtMainMenu"/> class. /// Adds our command handlers for menu (commands must exist in the command table file) /// </summary> - /// <param name="package">Owner package, not null.</param> - private QtItemContextMenu(Package package) + private QtItemContextMenu() { - if (package == null) - throw new ArgumentNullException("package"); - - m_package = package; - var commandService = VsServiceProvider .GetService<IMenuCommandService, OleMenuCommandService>(); if (commandService == null) @@ -104,6 +93,8 @@ private void execHandler(object sender, EventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var command = sender as OleMenuCommand; if (command == null) return; @@ -120,6 +111,8 @@ private void beforeQueryStatus(object sender, EventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var command = sender as OleMenuCommand; if (command == null) return; @@ -128,7 +121,7 @@ command.Visible = false; var prj = HelperFunctions.GetSelectedProject(QtVsToolsPackage.Instance.Dte); - if (!HelperFunctions.IsQtProject(prj) || QtVsToolsPackage.Instance.Dte.SelectedItems.Count <= 0) + if (!HelperFunctions.IsVsToolsProject(prj) || QtVsToolsPackage.Instance.Dte.SelectedItems.Count <= 0) return; foreach (SelectedItem si in QtVsToolsPackage.Instance.Dte.SelectedItems) { @@ -136,7 +129,7 @@ return; // Don't display commands if one of the selected files is not a .ts file. } - command.Enabled = true; + command.Enabled = Translation.ToolsAvailable(prj); command.Visible = true; } } diff --git a/QtVsTools.Package/Package/QtMainMenu.cs b/QtVsTools.Package/Package/QtMainMenu.cs index 2c8e90d..7298333 100644 --- a/QtVsTools.Package/Package/QtMainMenu.cs +++ b/QtVsTools.Package/Package/QtMainMenu.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,16 +26,17 @@ ** ****************************************************************************/ -using EnvDTE; -using Microsoft.VisualStudio.Shell; -using QtVsTools.Core; -using QtVsTools.VisualStudio; using System; using System.ComponentModel.Design; using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; +using EnvDTE; namespace QtVsTools { + using Core; + using VisualStudio; + /// <summary> /// Command handler /// </summary> @@ -44,24 +45,23 @@ /// <summary> /// Command menu group (command set GUID). /// </summary> - public static readonly Guid MainMenuGuid = new Guid("58f83fff-d39d-4c66-810b-2702e1f04e73"); + private static readonly Guid MainMenuGuid = new Guid("58f83fff-d39d-4c66-810b-2702e1f04e73"); /// <summary> /// Gets the instance of the command. /// </summary> - public static QtMainMenu Instance + private static QtMainMenu Instance { get; - private set; + set; } /// <summary> /// Initializes the singleton instance of the command. /// </summary> - /// <param name="package">Owner package, not null.</param> - public static void Initialize(Package package) + public static void Initialize() { - Instance = new QtMainMenu(package); + Instance = new QtMainMenu(); } /// <summary> @@ -71,16 +71,14 @@ { QtVersionId = 0x0500, ViewQtHelpId = 0x0501, + ViewGettingStartedId = 0x0503, LaunchDesignerId = 0x0100, LaunchLinguistId = 0x0101, OpenProFileId = 0x0102, ImportPriFileId = 0x0103, ExportPriFileId = 0x0104, ExportProFileId = 0x0105, - CreateNewTsFileId = 0x0107, ConvertToQtMsBuild = 0x0130, - ConvertToQtId = 0x0124, - ConvertToQmakeId = 0x0108, QtProjectSettingsId = 0x0109, ChangeProjectQtVersionId = 0x0126, QtOptionsId = 0x0110, @@ -88,22 +86,12 @@ } /// <summary> - /// VS Package that provides this command, not null. - /// </summary> - private readonly Package m_package; - - /// <summary> /// Initializes a new instance of the <see cref="QtMainMenu"/> class. /// Adds our command handlers for menu (commands must exist in the command table file) /// </summary> /// <param name="package">Owner package, not null.</param> - private QtMainMenu(Package package) + private QtMainMenu() { - if (package == null) - throw new ArgumentNullException("package"); - - m_package = package; - var commandService = VsServiceProvider .GetService<IMenuCommandService, OleMenuCommandService>(); if (commandService == null) @@ -119,6 +107,8 @@ private void execHandler(object sender, EventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var command = sender as OleMenuCommand; if (command == null) return; @@ -126,6 +116,9 @@ switch ((CommandId)command.CommandID.ID) { case CommandId.ViewQtHelpId: VsShellUtilities.OpenSystemBrowser("https://www.qt.io/developers"); + break; + case CommandId.ViewGettingStartedId: + VsShellUtilities.OpenSystemBrowser("https://doc.qt.io/qtvstools/qtvstools-getting-started.html"); break; case CommandId.LaunchDesignerId: QtVsToolsPackage.Instance.QtDesigner.Start(hideWindow: false); @@ -145,23 +138,8 @@ case CommandId.ExportProFileId: ExtLoader.ExportProFile(); break; - case CommandId.CreateNewTsFileId: - Translation.CreateNewTranslationFile(HelperFunctions.GetSelectedQtProject(QtVsToolsPackage - .Instance.Dte)); - break; - case CommandId.ConvertToQtId: - case CommandId.ConvertToQmakeId: { - var caption = SR.GetString("ConvertTitle"); - var text = SR.GetString("ConvertConfirmation"); - if (MessageBox.Show(text, caption, MessageBoxButtons.YesNo) == DialogResult.Yes) { - HelperFunctions.ToggleProjectKind(HelperFunctions.GetSelectedProject(QtVsToolsPackage - .Instance.Dte)); - } - } - break; - case CommandId.ConvertToQtMsBuild: { - QtMsBuildConverter.SolutionToQtMsBuild(); - } + case CommandId.ConvertToQtMsBuild: + QtMsBuildConverter.SolutionToQtMsBuild(); break; case CommandId.QtProjectSettingsId: { var pro = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte); @@ -169,31 +147,14 @@ if (projectVersion >= Resources.qtMinFormatVersion_Settings) { QtVsToolsPackage.Instance.Dte.ExecuteCommand("Project.Properties"); } else if (pro != null) { - using (var formProjectQtSettings = new FormProjectQtSettings()) { - formProjectQtSettings.SetProject(pro); - formProjectQtSettings.StartPosition = FormStartPosition.CenterParent; - var ww = new MainWinWrapper(QtVsToolsPackage.Instance.Dte); - formProjectQtSettings.ShowDialog(ww); - } + Legacy.QtMenu.ShowFormProjectQtSettings(pro); } else { MessageBox.Show(SR.GetString("NoProjectOpened")); } } break; - case CommandId.ChangeProjectQtVersionId: { - var pro = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte); - if (HelperFunctions.IsQMakeProject(pro)) { - using (var formChangeQtVersion = new FormChangeQtVersion()) { - formChangeQtVersion.UpdateContent(ChangeFor.Project); - var ww = new MainWinWrapper(QtVsToolsPackage.Instance.Dte); - if (formChangeQtVersion.ShowDialog(ww) == DialogResult.OK) { - var qtVersion = formChangeQtVersion.GetSelectedQtVersion(); - HelperFunctions.SetDebuggingEnvironment(pro, "PATH=" + QtVersionManager - .The().GetInstallPath(qtVersion) + @"\bin;$(PATH)", true); - } - } - } - } + case CommandId.ChangeProjectQtVersionId: + Legacy.QtMenu.ShowFormChangeProjectQtVersion(); break; case CommandId.QtOptionsId: QtVsToolsPackage.Instance.ShowOptionPage(typeof(Options.QtOptionsPage)); @@ -206,12 +167,17 @@ private void beforeQueryStatus(object sender, EventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var command = sender as OleMenuCommand; if (command == null) return; + var project = HelperFunctions.GetSelectedProject(QtVsToolsPackage.Instance.Dte); + switch ((CommandId)command.CommandID.ID) { case CommandId.ViewQtHelpId: + case CommandId.ViewGettingStartedId: command.Visible = command.Enabled = true; break; case CommandId.QtVersionId: @@ -230,39 +196,26 @@ case CommandId.ImportPriFileId: case CommandId.ExportPriFileId: case CommandId.ExportProFileId: - case CommandId.CreateNewTsFileId: { - command.Visible = true; - command.Enabled = HelperFunctions.IsQtProject(HelperFunctions - .GetSelectedProject(QtVsToolsPackage.Instance.Dte)); - } + command.Visible = true; + command.Enabled = HelperFunctions.IsVsToolsProject(project); break; - // TODO: Fix these functionality and re-enable the menu items - case CommandId.ConvertToQtId: - case CommandId.ConvertToQmakeId: { - command.Visible = false; - } - break; - //case CommandId.ConvertToQmakeId: case CommandId.QtProjectSettingsId: { var status = vsCommandStatus.vsCommandStatusSupported; - var project = HelperFunctions.GetSelectedProject(QtVsToolsPackage.Instance.Dte); if (project != null) { - if (HelperFunctions.IsQtProject(project)) + if (HelperFunctions.IsVsToolsProject(project)) status |= vsCommandStatus.vsCommandStatusEnabled; - else if (HelperFunctions.IsQMakeProject(project)) + else if (HelperFunctions.IsQtProject(project)) status |= vsCommandStatus.vsCommandStatusInvisible; } command.Enabled = ((status & vsCommandStatus.vsCommandStatusEnabled) != 0); command.Visible = ((status & vsCommandStatus.vsCommandStatusInvisible) == 0); } break; - //case CommandId.ConvertToQtId: case CommandId.ChangeProjectQtVersionId: { var status = vsCommandStatus.vsCommandStatusSupported; - var project = HelperFunctions.GetSelectedProject(QtVsToolsPackage.Instance.Dte); - if ((project == null) || HelperFunctions.IsQtProject(project)) + if ((project == null) || HelperFunctions.IsVsToolsProject(project)) status |= vsCommandStatus.vsCommandStatusInvisible; - else if (HelperFunctions.IsQMakeProject(project)) + else if (HelperFunctions.IsQtProject(project)) status |= vsCommandStatus.vsCommandStatusEnabled; else status |= vsCommandStatus.vsCommandStatusInvisible; diff --git a/QtVsTools.Package/Package/QtMsBuildConverter.cs b/QtVsTools.Package/Package/QtMsBuildConverter.cs index eac783f..79d484d 100644 --- a/QtVsTools.Package/Package/QtMsBuildConverter.cs +++ b/QtVsTools.Package/Package/QtMsBuildConverter.cs @@ -32,17 +32,21 @@ using System.Linq; using System.Windows.Forms; using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.VCProjectEngine; -using QtVsTools.Core; -using QtVsTools.VisualStudio; namespace QtVsTools { + using Core; + using VisualStudio; + static class QtMsBuildConverter { public static bool SolutionToQtMsBuild() { + ThreadHelper.ThrowIfNotOnUIThread(); + var solution = QtVsToolsPackage.Instance.Dte.Solution; if (solution == null) return ErrorMessage(string.Format(SR.GetString("ErrorConvertingProject"), "")); @@ -53,8 +57,8 @@ return WarningMessage(SR.GetString("NoProjectsToConvert")); foreach (EnvDTE.Project project in allProjects) { - if ((HelperFunctions.IsQtProject(project) - || HelperFunctions.IsQMakeProject(project)) + if ((HelperFunctions.IsVsToolsProject(project) + || HelperFunctions.IsQtProject(project)) && !QtProject.IsQtMsBuildEnabled(project)) { projects.Add(project); } @@ -68,7 +72,14 @@ MessageBoxButtons.YesNo) != DialogResult.Yes) return WarningMessage(SR.GetString("CancelConvertingProject")); - if (projects.Where(project => project.IsDirty).Any()) { + bool hasDirtyProjects = projects + .Where(project => + { + ThreadHelper.ThrowIfNotOnUIThread(); + return project.IsDirty; + }) + .Any(); + if (hasDirtyProjects) { if (MessageBox.Show( SR.GetString("ConvertSaveConfirmation"), SR.GetString("ConvertTitle"), @@ -76,7 +87,13 @@ return WarningMessage(SR.GetString("CancelConvertingProject")); } - var projectPaths = projects.Select(x => x.FullName).ToList(); + var projectPaths = projects + .Select(x => + { + ThreadHelper.ThrowIfNotOnUIThread(); + return x.FullName; + }) + .ToList(); string solutionPath = solution.FileName; solution.Close(true); @@ -142,6 +159,8 @@ public static bool ProjectToQtMsBuild(EnvDTE.Project project, bool askConfirmation = true) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project == null) return ErrorMessage(string.Format(SR.GetString("ErrorConvertingProject"), "")); var pathToProject = project.FullName; @@ -178,7 +197,7 @@ try { if (solution.UnloadProject( ref projectGuid, - (uint)_VSProjectUnloadStatus.UNLOADSTATUS_LoadPendingIfNeeded) + (uint)_VSProjectUnloadStatus.UNLOADSTATUS_UnloadedByUser) != VSConstants.S_OK) return ErrorMessage( string.Format(SR.GetString("ErrorConvertingProject"), projectName)); diff --git a/QtVsTools.Package/Package/QtProjectContextMenu.cs b/QtVsTools.Package/Package/QtProjectContextMenu.cs index 2706ef5..3b08b13 100644 --- a/QtVsTools.Package/Package/QtProjectContextMenu.cs +++ b/QtVsTools.Package/Package/QtProjectContextMenu.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,20 +26,17 @@ ** ****************************************************************************/ -using EnvDTE; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.VCProjectEngine; -using QtVsTools.Core; -using QtVsTools.VisualStudio; using System; using System.ComponentModel.Design; using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; +using EnvDTE; namespace QtVsTools { + using Core; using QtMsBuild; + using VisualStudio; /// <summary> /// Command handler @@ -49,24 +46,23 @@ /// <summary> /// Command menu group (command set GUID). /// </summary> - public static readonly Guid ProjectContextMenuGuid = new Guid("5732faa9-6074-4e07-b035-2816e809f50e"); + private static readonly Guid ProjectContextMenuGuid = new Guid("5732faa9-6074-4e07-b035-2816e809f50e"); /// <summary> /// Gets the instance of the command. /// </summary> - public static QtProjectContextMenu Instance + private static QtProjectContextMenu Instance { get; - private set; + set; } /// <summary> /// Initializes the singleton instance of the command. /// </summary> - /// <param name="package">Owner package, not null.</param> - public static void Initialize(Package package) + public static void Initialize() { - Instance = new QtProjectContextMenu(package); + Instance = new QtProjectContextMenu(); } /// <summary> @@ -77,35 +73,20 @@ ImportPriFileProjectId = 0x0114, ExportPriFileProjectId = 0x0115, ExportProFileProjectId = 0x0116, - CreateNewTsFileProjectId = 0x0117, lUpdateOnProjectId = 0x0118, lReleaseOnProjectId = 0x0119, ProjectConvertToQtMsBuild = 0x0130, ProjectRefreshIntelliSense = 0x0131, - ConvertToQtProjectId = 0x0120, - ConvertToQmakeProjectId = 0x0121, QtProjectSettingsProjectId = 0x0122, - ChangeProjectQtVersionProjectId = 0x0123, - ProjectAddNewQtClassProjectId = 0x200 + ChangeProjectQtVersionProjectId = 0x0123 } - - /// <summary> - /// VS Package that provides this command, not null. - /// </summary> - private readonly Package m_package; /// <summary> /// Initializes a new instance of the <see cref="QtMainMenu"/> class. /// Adds our command handlers for menu (commands must exist in the command table file) /// </summary> - /// <param name="package">Owner package, not null.</param> - private QtProjectContextMenu(Package package) + private QtProjectContextMenu() { - if (package == null) - throw new ArgumentNullException("package"); - - m_package = package; - var commandService = VsServiceProvider .GetService<IMenuCommandService, OleMenuCommandService>(); if (commandService == null) @@ -121,6 +102,8 @@ private void execHandler(object sender, EventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var command = sender as OleMenuCommand; if (command == null) return; @@ -135,25 +118,11 @@ case CommandId.ExportProFileProjectId: ExtLoader.ExportProFile(); break; - case CommandId.CreateNewTsFileProjectId: - Translation.CreateNewTranslationFile(HelperFunctions.GetSelectedQtProject(QtVsToolsPackage - .Instance.Dte)); - break; case CommandId.lUpdateOnProjectId: Translation.RunlUpdate(HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte)); break; case CommandId.lReleaseOnProjectId: Translation.RunlRelease(HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte)); - break; - case CommandId.ConvertToQtProjectId: - case CommandId.ConvertToQmakeProjectId: { - var caption = SR.GetString("ConvertTitle"); - var text = SR.GetString("ConvertConfirmation"); - if (MessageBox.Show(text, caption, MessageBoxButtons.YesNo) == DialogResult.Yes) { - HelperFunctions.ToggleProjectKind(HelperFunctions.GetSelectedProject(QtVsToolsPackage - .Instance.Dte)); - } - } break; case CommandId.QtProjectSettingsProjectId: { var pro = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte); @@ -161,31 +130,14 @@ if (projectVersion >= Resources.qtMinFormatVersion_Settings) { QtVsToolsPackage.Instance.Dte.ExecuteCommand("Project.Properties"); } else if (pro != null) { - using (var formProjectQtSettings = new FormProjectQtSettings()) { - formProjectQtSettings.SetProject(pro); - formProjectQtSettings.StartPosition = FormStartPosition.CenterParent; - var ww = new MainWinWrapper(QtVsToolsPackage.Instance.Dte); - formProjectQtSettings.ShowDialog(ww); - } + Legacy.QtMenu.ShowFormProjectQtSettings(pro); } else { MessageBox.Show(SR.GetString("NoProjectOpened")); } } break; - case CommandId.ChangeProjectQtVersionProjectId: { - var pro = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte); - if (HelperFunctions.IsQMakeProject(pro)) { - using (var formChangeQtVersion = new FormChangeQtVersion()) { - formChangeQtVersion.UpdateContent(ChangeFor.Project); - var ww = new MainWinWrapper(QtVsToolsPackage.Instance.Dte); - if (formChangeQtVersion.ShowDialog(ww) == DialogResult.OK) { - var qtVersion = formChangeQtVersion.GetSelectedQtVersion(); - HelperFunctions.SetDebuggingEnvironment(pro, "PATH=" + QtVersionManager - .The().GetInstallPath(qtVersion) + @"\bin;$(PATH)", true); - } - } - } - } + case CommandId.ChangeProjectQtVersionProjectId: + Legacy.QtMenu.ShowFormChangeProjectQtVersion(); break; case CommandId.ProjectConvertToQtMsBuild: { QtMsBuildConverter.ProjectToQtMsBuild( @@ -194,29 +146,8 @@ break; case CommandId.ProjectRefreshIntelliSense: { var selectedProject = HelperFunctions.GetSelectedProject(QtVsToolsPackage.Instance.Dte); - var tracker = QtProjectTracker.Get(selectedProject); + var tracker = QtProjectTracker.Get(selectedProject, selectedProject.FullName); QtProjectIntellisense.Refresh(tracker.Project); - } - break; - case CommandId.ProjectAddNewQtClassProjectId: { - try { - var project = HelperFunctions.GetSelectedProject(QtVsToolsPackage.Instance.Dte); - if (!HelperFunctions.IsQtProject(project)) - return; - - var vcProject = project.Object as VCProject; - if (vcProject == null) - return; - - var loop = true; - do { - var classWizard = new Wizards.ClassWizard.AddClassWizard(); - loop = classWizard.Run(QtVsToolsPackage.Instance.Dte, vcProject.Name, - vcProject.ProjectDirectory) == Wizards.WizardResult.Exception; - } while (loop); - } catch { - // Deliberately ignore any kind of exception but close the dialog. - } } break; } @@ -229,8 +160,8 @@ return; var project = HelperFunctions.GetSelectedProject(QtVsToolsPackage.Instance.Dte); - var isQtProject = HelperFunctions.IsQtProject(project); - var isQMakeProject = HelperFunctions.IsQMakeProject(project); + var isQtProject = HelperFunctions.IsVsToolsProject(project); + var isQMakeProject = HelperFunctions.IsQtProject(project); var isQtMsBuildEnabled = QtProject.IsQtMsBuildEnabled(project); if (!isQtProject && !isQMakeProject) { @@ -239,25 +170,19 @@ } switch ((CommandId)command.CommandID.ID) { - // TODO: Fix these functionality and re-enable the menu items - case CommandId.ConvertToQtProjectId: - case CommandId.ConvertToQmakeProjectId: { - command.Visible = false; - } - break; case CommandId.ImportPriFileProjectId: case CommandId.ExportPriFileProjectId: case CommandId.ExportProFileProjectId: - case CommandId.CreateNewTsFileProjectId: + command.Visible = true; + command.Enabled = HelperFunctions.IsVsToolsProject(HelperFunctions + .GetSelectedProject(QtVsToolsPackage.Instance.Dte)); + break; case CommandId.lUpdateOnProjectId: case CommandId.lReleaseOnProjectId: command.Visible = true; - command.Enabled = HelperFunctions.IsQtProject(HelperFunctions - .GetSelectedProject(QtVsToolsPackage.Instance.Dte)); + command.Enabled = Translation.ToolsAvailable(project); break; - //case CommandId.ConvertToQmakeProjectId: - case CommandId.QtProjectSettingsProjectId: - case CommandId.ProjectAddNewQtClassProjectId: { + case CommandId.QtProjectSettingsProjectId: { var status = vsCommandStatus.vsCommandStatusSupported; if (project != null) { if (isQtProject) @@ -269,7 +194,6 @@ command.Visible = ((status & vsCommandStatus.vsCommandStatusInvisible) == 0); } break; - //case CommandId.ConvertToQtProjectId: case CommandId.ChangeProjectQtVersionProjectId: { var status = vsCommandStatus.vsCommandStatusSupported; if ((project == null) || isQtProject) diff --git a/QtVsTools.Package/Package/QtSolutionContextMenu.cs b/QtVsTools.Package/Package/QtSolutionContextMenu.cs index d680fe7..67f2a8c 100644 --- a/QtVsTools.Package/Package/QtSolutionContextMenu.cs +++ b/QtVsTools.Package/Package/QtSolutionContextMenu.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,17 +26,15 @@ ** ****************************************************************************/ -using EnvDTE80; -using Microsoft.VisualStudio.Shell; -using QtVsTools.Core; -using QtVsTools.VisualStudio; using System; using System.ComponentModel.Design; -using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; namespace QtVsTools { + using Core; using QtMsBuild; + using VisualStudio; /// <summary> /// Command handler @@ -46,30 +44,24 @@ /// <summary> /// Command menu group (command set GUID). /// </summary> - public static readonly Guid SolutionContextMenuGuid = new Guid("6dcda34f-4d22-4d6a-a176-5507069c5a3e"); + private static readonly Guid SolutionContextMenuGuid = new Guid("6dcda34f-4d22-4d6a-a176-5507069c5a3e"); /// <summary> /// Gets the instance of the command. /// </summary> - public static QtSolutionContextMenu Instance + private static QtSolutionContextMenu Instance { get; - private set; + set; } /// <summary> /// Initializes the singleton instance of the command. /// </summary> - /// <param name="package">Owner package, not null.</param> - public static void Initialize(Package package) + public static void Initialize() { - Instance = new QtSolutionContextMenu(package); + Instance = new QtSolutionContextMenu(); } - - /// <summary> - /// VS Package that provides this command, not null. - /// </summary> - private readonly Package m_package; /// <summary> /// Command ID. @@ -87,14 +79,8 @@ /// Initializes a new instance of the <see cref="QtMainMenu"/> class. /// Adds our command handlers for menu (commands must exist in the command table file) /// </summary> - /// <param name="package">Owner package, not null.</param> - private QtSolutionContextMenu(Package package) + private QtSolutionContextMenu() { - if (package == null) - throw new ArgumentNullException("package"); - - m_package = package; - var commandService = VsServiceProvider .GetService<IMenuCommandService, OleMenuCommandService>(); if (commandService == null) @@ -113,66 +99,51 @@ var command = sender as OleMenuCommand; if (command == null) return; - command.Enabled = command.Visible = true; + + switch (command.CommandID.ID) { + case (int)CommandId.ChangeSolutionQtVersionId: + var projects = HelperFunctions.ProjectsInSolution(QtVsToolsPackage.Instance.Dte); + foreach (var project in projects) { + if (!HelperFunctions.IsVsToolsProject(project) + && HelperFunctions.IsQtProject(project)) { + command.Enabled = command.Visible = true; + return; + } + } + command.Enabled = command.Visible = false; + break; + default: + command.Enabled = command.Visible = true; + break; + } } private void execHandler(object sender, EventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var command = sender as OleMenuCommand; if (command == null) return; var dte = QtVsToolsPackage.Instance.Dte; - switch (command.CommandID.ID) { - case (int)CommandId.lUpdateOnSolutionId: + switch ((CommandId)command.CommandID.ID) { + case CommandId.lUpdateOnSolutionId: Translation.RunlUpdate(QtVsToolsPackage.Instance.Dte.Solution); break; - case (int)CommandId.lReleaseOnSolutionId: + case CommandId.lReleaseOnSolutionId: Translation.RunlRelease(QtVsToolsPackage.Instance.Dte.Solution); break; - case (int)CommandId.ChangeSolutionQtVersionId: - string newQtVersion = null; - using (var formChangeQtVersion = new FormChangeQtVersion()) { - formChangeQtVersion.UpdateContent(ChangeFor.Solution); - if (formChangeQtVersion.ShowDialog() != DialogResult.OK) - return; - newQtVersion = formChangeQtVersion.GetSelectedQtVersion(); - } - if (newQtVersion == null) - return; - - string currentPlatform = null; - try { - var config2 = QtVsToolsPackage.Instance.Dte.Solution.SolutionBuild - .ActiveConfiguration as SolutionConfiguration2; - currentPlatform = config2.PlatformName; - } catch { } - if (string.IsNullOrEmpty(currentPlatform)) - return; - - foreach (var project in HelperFunctions.ProjectsInSolution(dte)) { - if (HelperFunctions.IsQtProject(project)) { - var OldQtVersion = QtVersionManager.The().GetProjectQtVersion(project, - currentPlatform); - if (OldQtVersion == null) - OldQtVersion = QtVersionManager.The().GetDefaultVersion(); - - var created = false; - var qtProject = QtProject.Create(project); - if (qtProject.PromptChangeQtVersion(OldQtVersion, newQtVersion)) - qtProject.ChangeQtVersion(OldQtVersion, newQtVersion, ref created); - } - } - QtVersionManager.The().SaveSolutionQtVersion(dte.Solution, newQtVersion); + case CommandId.ChangeSolutionQtVersionId: + Legacy.QtMenu.ShowFormChangeSolutionQtVersion(); break; - case (int)CommandId.SolutionConvertToQtMsBuild: { - QtMsBuildConverter.SolutionToQtMsBuild(); - } + case CommandId.SolutionConvertToQtMsBuild: + QtMsBuildConverter.SolutionToQtMsBuild(); break; - case (int)CommandId.SolutionEnableProjectTracking: { + case CommandId.SolutionEnableProjectTracking: { foreach (var project in HelperFunctions.ProjectsInSolution(dte)) { - if (HelperFunctions.IsQtProject(project)) - QtProjectTracker.Get(project); + if (HelperFunctions.IsVsToolsProject(project)) + QtProjectTracker.Get(project, project.FullName); } } break; diff --git a/QtVsTools.Package/Package/SR.cs b/QtVsTools.Package/Package/SR.cs index 8dd6c57..6bf9f44 100644 --- a/QtVsTools.Package/Package/SR.cs +++ b/QtVsTools.Package/Package/SR.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,8 +26,6 @@ ** ****************************************************************************/ -using System; -using System.Globalization; using System.Resources; namespace QtVsTools @@ -36,66 +34,39 @@ { static SR loader; readonly ResourceManager resources; - static readonly Object obj = new Object(); + static readonly object obj = new object(); - internal const string OK = "OK"; - internal const string Cancel = "Cancel"; - - internal static CultureInfo appCultureInfo; - internal static CultureInfo defaultCultureInfo; - - internal SR(int localeId) + internal SR() { - defaultCultureInfo = CultureInfo.GetCultureInfo("en"); - appCultureInfo = CultureInfo.GetCultureInfo(localeId); - if (appCultureInfo.Name.StartsWith("en", StringComparison.Ordinal)) - appCultureInfo = null; resources = new ResourceManager("QtVsTools.Package.Resources", GetType().Assembly); } - private static SR GetLoader(int localeId) + private static SR GetLoader() { if (loader == null) { lock (obj) { if (loader == null) - loader = new SR(localeId); + loader = new SR(); } } return loader; } - private static CultureInfo Culture - { - get { return appCultureInfo; } - } - public static string GetString(string name, params object[] args) { - var res = GetString(name); - if (!string.IsNullOrEmpty(res) && args != null && args.Length > 0) + var sys = GetLoader(); + if (sys == null) + return null; + + var res = sys.resources.GetString(name, null); + if (args != null && args.Length > 0 && !string.IsNullOrEmpty(res)) return string.Format(res, args); return res; } public static string GetString(string name) { - return GetString(name, QtVsToolsPackage.Instance); - } - - public static string GetString(string name, QtVsToolsPackage vsixInstance) - { - var sys = GetLoader(vsixInstance.Dte.LocaleID); - if (sys == null) - return null; - - string result; - try { - result = sys.resources.GetString(name, Culture); - } catch (Exception) { - result = sys.resources.GetString(name, defaultCultureInfo); - } - - return result; + return GetString(name, null); } } } diff --git a/QtVsTools.Package/Package/Translation.cs b/QtVsTools.Package/Package/Translation.cs index 3c7e9f2..d47e525 100644 --- a/QtVsTools.Package/Package/Translation.cs +++ b/QtVsTools.Package/Package/Translation.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -26,24 +26,16 @@ ** ****************************************************************************/ -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.VCProjectEngine; -using QtVsTools.Core; -using QtVsTools.VisualStudio; using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; namespace QtVsTools { - using static Core.HelperFunctions; + using Core; using QtMsBuild; /// <summary> @@ -51,16 +43,10 @@ /// </summary> public static class Translation { - public static void RunlRelease(VCFile vcFile) - { - var vcProj = vcFile.project as VCProject; - var project = vcProj?.Object as EnvDTE.Project; - RunTranslationTarget(BuildAction.Release, - project, new[] { vcFile.RelativePath }); - } - public static void RunlRelease(VCFile[] vcFiles) { + ThreadHelper.ThrowIfNotOnUIThread(); + var vcProj = vcFiles.FirstOrDefault()?.project as VCProject; var project = vcProj?.Object as EnvDTE.Project; RunTranslationTarget(BuildAction.Release, @@ -69,11 +55,14 @@ public static void RunlRelease(EnvDTE.Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); RunTranslationTarget(BuildAction.Release, project); } public static void RunlRelease(EnvDTE.Solution solution) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (solution == null) return; @@ -83,6 +72,8 @@ public static void RunlUpdate(VCFile vcFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + var vcProj = vcFile.project as VCProject; var project = vcProj?.Object as EnvDTE.Project; RunTranslationTarget(BuildAction.Update, @@ -91,6 +82,8 @@ public static void RunlUpdate(VCFile[] vcFiles) { + ThreadHelper.ThrowIfNotOnUIThread(); + var vcProj = vcFiles.FirstOrDefault()?.project as VCProject; var project = vcProj?.Object as EnvDTE.Project; RunTranslationTarget(BuildAction.Update, @@ -99,16 +92,19 @@ public static void RunlUpdate(EnvDTE.Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); RunTranslationTarget(BuildAction.Update, project); } - enum BuildAction { Update, Release } + internal enum BuildAction { Update, Release } static void RunTranslationTarget( BuildAction buildAction, EnvDTE.Project project, IEnumerable<string> selectedFiles = null) { + ThreadHelper.ThrowIfNotOnUIThread(); + using (WaitDialog.Start( "Qt Visual Studio Tools", "Running translation tool...")) { @@ -122,10 +118,9 @@ if (qtPro.FormatVersion < Resources.qtMinFormatVersion_Settings) { Messages.Print("translation: Legacy project format"); try { - Legacy_RunTranslation(buildAction, qtPro, selectedFiles); - } catch (Exception e) { - Messages.Print( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + Legacy.Translation.Run(buildAction, qtPro, selectedFiles); + } catch (Exception exception) { + exception.Log(); } return; } @@ -152,12 +147,15 @@ if (selectedFiles != null) properties["SelectedFiles"] = string.Join(";", selectedFiles); - QtProjectBuild.StartBuild(project, activeConfigId, properties, new[] { target }); + QtProjectBuild.StartBuild( + project, project.FullName, activeConfigId, properties, new[] { target }); } } public static void RunlUpdate(EnvDTE.Solution solution) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (solution == null) return; @@ -165,118 +163,23 @@ RunlUpdate(project); } - static void Legacy_RunTranslation( - BuildAction buildAction, - QtProject qtProject, - IEnumerable<string> tsFiles) - { - if (tsFiles == null) { - tsFiles = (qtProject.VCProject - .GetFilesEndingWith(".ts") as IVCCollection) - .Cast<VCFile>() - .Select(vcFile => vcFile.RelativePath); - if (tsFiles == null) { - Messages.Print("translation: no translation files found"); - return; - } - } - string tempFile = null; - foreach (var file in tsFiles.Where(file => file != null)) - Legacy_RunTranslation(buildAction, qtProject, file, ref tempFile); - } - - static void Legacy_RunTranslation( - BuildAction buildAction, - QtProject qtProject, - string tsFile, - ref string tempFile) - { - var qtVersion = qtProject.GetQtVersion(); - var qtInstallPath = QtVersionManager.The().GetInstallPath(qtVersion); - if (string.IsNullOrEmpty(qtInstallPath)) { - Messages.Print("translation: Error accessing Qt installation"); - return; - } - - var procInfo = new ProcessStartInfo - { - WorkingDirectory = qtProject.ProjectDir, - CreateNoWindow = true, - UseShellExecute = false, - RedirectStandardError = true, - RedirectStandardOutput = true, - Arguments = "" - }; - switch (buildAction) { - case BuildAction.Update: - Messages.Print("\r\n--- (lupdate) file: " + tsFile); - procInfo.FileName = Path.Combine(qtInstallPath, "bin", "lupdate.exe"); - var options = QtVSIPSettings.GetLUpdateOptions(); - if (!string.IsNullOrEmpty(options)) - procInfo.Arguments += options + " "; - if (tempFile == null) { - var inputFiles = GetProjectFiles(qtProject.Project, FilesToList.FL_HFiles) - .Union(GetProjectFiles(qtProject.Project, FilesToList.FL_CppFiles)) - .Union(GetProjectFiles(qtProject.Project, FilesToList.FL_UiFiles)) - .Union(GetProjectFiles(qtProject.Project, FilesToList.FL_QmlFiles)); - tempFile = Path.GetTempFileName(); - File.WriteAllLines(tempFile, inputFiles); - } - procInfo.Arguments += string.Format("\"@{0}\" -ts \"{1}\"", tempFile, tsFile); - break; - case BuildAction.Release: - Messages.Print("\r\n--- (lrelease) file: " + tsFile); - procInfo.FileName = Path.Combine(qtInstallPath, "bin", "lrelease.exe"); - options = QtVSIPSettings.GetLReleaseOptions(); - if (!string.IsNullOrEmpty(options)) - procInfo.Arguments += options + " "; - procInfo.Arguments += string.Format("\"{0}\"", tsFile); - break; - } - using (var proc = Process.Start(procInfo)) { - proc.OutputDataReceived += (object sender, DataReceivedEventArgs e) => - { - if (!string.IsNullOrEmpty(e.Data)) - Messages.Print(e.Data); - }; - proc.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => - { - if (!string.IsNullOrEmpty(e.Data)) - Messages.Print(e.Data); - }; - proc.BeginOutputReadLine(); - proc.BeginErrorReadLine(); - proc.WaitForExit(); - switch (proc.ExitCode) { - case 0: - Messages.Print("translation: ok"); - break; - default: - Messages.Print(string.Format("translation: ERROR {0}", proc.ExitCode)); - break; - } - } - } - - public static void CreateNewTranslationFile(EnvDTE.Project project) + public static bool ToolsAvailable(EnvDTE.Project project) { if (project == null) - return; + return false; + if (QtProject.GetPropertyValue(project, "ApplicationType") == "Linux") + return true; - using (var transDlg = new AddTranslationDialog(project)) { - if (transDlg.ShowDialog() == DialogResult.OK) { - try { - var qtPro = QtProject.Create(project); - var file = qtPro.AddFileInFilter(Filters.TranslationFiles(), - transDlg.TranslationFile, true); - RunlUpdate(file); - } catch (QtVSException e) { - Messages.DisplayErrorMessage(e.Message); - } catch (System.Exception ex) { - Messages.DisplayErrorMessage(ex.Message); - } - } + var qtToolsPath = QtProject.GetPropertyValue(project, "QtToolsPath"); + if (string.IsNullOrEmpty(qtToolsPath)) { + var qtVersion = QtVersionManager.The().GetProjectQtVersion(project); + var qtInstallPath = QtVersionManager.The().GetInstallPath(qtVersion); + if (string.IsNullOrEmpty(qtInstallPath)) + return false; + qtToolsPath = Path.Combine(qtInstallPath, "bin"); } + return File.Exists(Path.Combine(qtToolsPath, "lupdate.exe")) + && File.Exists(Path.Combine(qtToolsPath, "lrelease.exe")); } } } diff --git a/QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs b/QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs index d8698b4..b69d9b6 100644 --- a/QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs +++ b/QtVsTools.Package/QML/Classification/QmlAsyncClassifier.cs @@ -33,7 +33,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; using System.Windows.Threading; using Microsoft.VisualStudio.Text; @@ -52,7 +51,7 @@ /// </summary> class SharedTagList : Concurrent { - SortedList<int, TrackingTag> data = new SortedList<int, TrackingTag>(); + readonly SortedList<int, TrackingTag> data = new SortedList<int, TrackingTag>(); object owner; public bool Ready { get; private set; } @@ -97,7 +96,7 @@ class TrackingTagComparer : Comparer<TrackingTag> { - ITextSnapshot snapshot; + readonly ITextSnapshot snapshot; public TrackingTagComparer(ITextSnapshot snapshot) { this.snapshot = snapshot; @@ -232,17 +231,16 @@ /// <returns>Instance of T corresponding to the given TrackingTag</returns> protected abstract T GetClassification(TrackingTag tag); - protected ITextView TextView { get; private set; } - protected ITextBuffer Buffer { get; private set; } + private ITextView TextView { get; } + private ITextBuffer Buffer { get; } readonly object criticalSection = new object(); - - string classificationType; + readonly string classificationType; ParserKey currentParserKey; TagListKey currentTagListKey; SharedTagList currentTagList; - Dispatcher dispatcher; - DispatcherTimer timer; + readonly Dispatcher dispatcher; + readonly DispatcherTimer timer; bool flag = false; protected QmlAsyncClassifier( @@ -267,7 +265,7 @@ currentTagList = null; this.classificationType = classificationType; - AsyncParse(buffer.CurrentSnapshot); + Parse(buffer.CurrentSnapshot); } private void TextView_Closed(object sender, EventArgs e) @@ -286,16 +284,16 @@ private void Buffer_Changed(object sender, TextContentChangedEventArgs e) { timer.Stop(); - AsyncParse(e.After); + Parse(e.After); } private void Timer_Tick(object sender, EventArgs e) { timer.Stop(); - AsyncParse(Buffer.CurrentSnapshot); + Parse(Buffer.CurrentSnapshot); } - private async void AsyncParse(ITextSnapshot snapshot) + private void Parse(ITextSnapshot snapshot) { lock (criticalSection) { if (flag) @@ -311,7 +309,7 @@ ParserKey oldParserKey = null; TagListKey oldTagListKey = null; - await Task.Run(() => + _ = Task.Run(() => { var parser = ParserStore.Instance.Get(this, newParserKey); @@ -344,7 +342,7 @@ flag = false; } - await Task.Run(() => + _ = Task.Run(() => { if (oldParserKey != null) ParserStore.Instance.Release(this, oldParserKey); @@ -511,7 +509,7 @@ public TValue Value { get; set; } public HashSet<object> ClientObjects { get; set; } } - Dictionary<TKey, ValueRef> data = new Dictionary<TKey, ValueRef>(); + readonly Dictionary<TKey, ValueRef> data = new Dictionary<TKey, ValueRef>(); static readonly object staticCriticalSection = new object(); readonly object criticalSection = new object(); @@ -524,8 +522,7 @@ public TValue Get(object client, TKey key) { lock (criticalSection) { - ValueRef valueRef; - if (!data.TryGetValue(key, out valueRef)) { + if (!data.TryGetValue(key, out ValueRef valueRef)) { valueRef = new ValueRef { Value = GetDefaultValue(key), @@ -543,8 +540,7 @@ { IDisposable disposable = null; lock (criticalSection) { - ValueRef valueRef; - if (data.TryGetValue(key, out valueRef)) { + if (data.TryGetValue(key, out ValueRef valueRef)) { valueRef.ClientObjects.Remove(client); if (valueRef.ClientObjects.Count == 0) { data.Remove(key); @@ -573,8 +569,8 @@ class TagListKey { - public string Classification { get; private set; } - public ITextSnapshot Snapshot { get; private set; } + private string Classification { get; } + private ITextSnapshot Snapshot { get; } public TagListKey(string classification, ITextSnapshot snapshot) { Classification = classification; @@ -614,7 +610,7 @@ class ParserKey { - public ITextSnapshot Snapshot { get; private set; } + public ITextSnapshot Snapshot { get; } public ParserKey(ITextSnapshot snapshot) { Snapshot = snapshot; diff --git a/QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs b/QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs index 85c216d..1878c56 100644 --- a/QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs +++ b/QtVsTools.Package/QML/Classification/QmlErrorClassifier.cs @@ -28,11 +28,7 @@ /// Highlighting of syntax errors -using System; -using System.Collections.Generic; using System.ComponentModel.Composition; -using System.Threading.Tasks; -using System.Windows.Threading; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Text.Editor; diff --git a/QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs b/QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs index dd0528e..9cb30eb 100644 --- a/QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs +++ b/QtVsTools.Package/QML/Classification/QmlExpressionEvalClassifier.cs @@ -41,11 +41,12 @@ using Microsoft.VisualStudio.Text.Tagging; using Microsoft.VisualStudio.TextManager.Interop; using Microsoft.VisualStudio.Utilities; -using QtVsTools.Qml.Syntax; -using QtVsTools.VisualStudio; namespace QtVsTools.Qml.Classification { + using QtVsTools.VisualStudio; + using Syntax; + [Export(typeof(IViewTaggerProvider))] [ContentType("qml")] [TagType(typeof(ClassificationTag))] @@ -169,6 +170,8 @@ int IVsTextViewFilter.GetDataTipText(TextSpan[] pSpan, out string pbstrText) { + ThreadHelper.ThrowIfNotOnUIThread(); + pbstrText = ""; var dbgMode = new DBGMODE[1]; if (debugger.GetMode(dbgMode) != VSConstants.S_OK @@ -215,6 +218,7 @@ OLECMD[] prgCmds, IntPtr pCmdText) { + ThreadHelper.ThrowIfNotOnUIThread(); return nextTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText); } @@ -225,12 +229,13 @@ IntPtr pvaIn, IntPtr pvaOut) { + ThreadHelper.ThrowIfNotOnUIThread(); return nextTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); } class ExprTrackingTag : TrackingTag { - public IOrderedEnumerable<AstNode> Exprs { get; private set; } + public IOrderedEnumerable<AstNode> Exprs { get; } public ExprTrackingTag( ITextSnapshot snapshot, @@ -245,7 +250,7 @@ class ExprTag : ClassificationTag { - public IOrderedEnumerable<AstNode> Exprs { get; private set; } + public IOrderedEnumerable<AstNode> Exprs { get; } public ExprTag(IOrderedEnumerable<AstNode> exprs, IClassificationType type) : base(type) diff --git a/QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs b/QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs index 4675637..4035a67 100644 --- a/QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs +++ b/QtVsTools.Package/QML/Classification/QmlSyntaxClassifier.cs @@ -29,11 +29,7 @@ /// This file implements the actual highlighting of the text according to the /// classification of the syntax elements recognized by the QML parser. -using System; -using System.Collections.Generic; using System.ComponentModel.Composition; -using System.Threading.Tasks; -using System.Windows.Threading; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Text.Editor; diff --git a/QtVsTools.Package/QML/Classification/QmlTag.cs b/QtVsTools.Package/QML/Classification/QmlTag.cs index 5d92dcd..8cd0ba1 100644 --- a/QtVsTools.Package/QML/Classification/QmlTag.cs +++ b/QtVsTools.Package/QML/Classification/QmlTag.cs @@ -47,10 +47,10 @@ /// </summary> public class TrackingTag : ITag { - public ITextSnapshot Snapshot { get; private set; } - public int Start { get; private set; } - public int Length { get; private set; } - public ITrackingSpan Span { get; private set; } + public ITextSnapshot Snapshot { get; } + public int Start { get; } + private int Length { get; } + public ITrackingSpan Span { get; } public TrackingTag(ITextSnapshot snapshot, int start, int length) { Snapshot = snapshot; @@ -76,9 +76,9 @@ public const string TypeName = "typename.qml"; public const string Binding = "binding.qml"; - public SyntaxElement SyntaxElement { get; private set; } - public SourceLocation SourceLocation { get; private set; } - public IClassificationType ClassificationType { get; private set; } + private SyntaxElement SyntaxElement { get; } + private SourceLocation SourceLocation { get; } + public IClassificationType ClassificationType { get; } private QmlSyntaxTag(ITextSnapshot snapshot, SourceLocation location) : base(snapshot, location.Offset, location.Length) @@ -118,7 +118,7 @@ return new QmlSyntaxTag(snapshot, parentNode, classificationType, fullNameLocation); } - public static readonly HashSet<string> QmlBasicTypes = new HashSet<string> { + private static readonly HashSet<string> QmlBasicTypes = new HashSet<string> { "bool", "double", "enumeration", "int", "list", "real", "string", "url", "var", "date", "point", "rect", "size", "alias" @@ -223,7 +223,7 @@ public class QmlDiagnosticsTag : TrackingTag { - public DiagnosticMessage DiagnosticMessage { get; private set; } + private DiagnosticMessage DiagnosticMessage { get; } public QmlDiagnosticsTag(ITextSnapshot snapshot, DiagnosticMessage diagnosticMessage) : base(snapshot, diagnosticMessage.Location.Offset, diagnosticMessage.Location.Length) { diff --git a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Breakpoint.cs b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Breakpoint.cs index fad795d..13838bc 100644 --- a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Breakpoint.cs +++ b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Breakpoint.cs @@ -44,12 +44,12 @@ static readonly string[] ValidExtensions = new string[] { ".qml", ".js" }; public QmlEngine Engine { get; private set; } - public IDebugBreakpointRequest2 Request { get; private set; } - public enum_BP_LOCATION_TYPE LocationType { get; private set; } - public BP_REQUEST_INFO RequestInfo { get; private set; } + private IDebugBreakpointRequest2 Request { get; set; } + private enum_BP_LOCATION_TYPE LocationType { get; set; } + private BP_REQUEST_INFO RequestInfo { get; set; } public string FileName { get; private set; } public TEXT_POSITION BeginPosition { get; private set; } - public TEXT_POSITION EndPosition { get; private set; } + private TEXT_POSITION EndPosition { get; set; } public bool Enabled { get; private set; } HashSet<Breakpoint> breakpoints; @@ -85,8 +85,7 @@ if (docPosition == null) return false; - string fileName; - if (docPosition.GetFileName(out fileName) != VSConstants.S_OK) + if (docPosition.GetFileName(out string fileName) != VSConstants.S_OK) return false; if (!ValidExtensions.Where(x => string.Equals(x, Path.GetExtension(fileName))).Any()) @@ -186,12 +185,12 @@ IDebugBreakpointResolution2 // "This interface represents the information that describes a // bound breakpoint." { - public QmlDebugger Debugger { get; private set; } - public QmlEngine Engine { get; private set; } + private QmlDebugger Debugger { get; set; } + private QmlEngine Engine { get; set; } public Program Program { get; private set; } public PendingBreakpoint Parent { get; private set; } - public CodeContext CodeContext { get; private set; } - public bool Enabled { get; set; } + private CodeContext CodeContext { get; set; } + private bool Enabled { get; set; } bool supressNotify; diff --git a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Engine.cs b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Engine.cs index 8da6eb9..5dc4bdb 100644 --- a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Engine.cs +++ b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Engine.cs @@ -78,13 +78,13 @@ FileSystem = FileSystem.Create(); } - Dictionary<Guid, Program> programs = new Dictionary<Guid, Program>(); + readonly Dictionary<Guid, Program> programs = new Dictionary<Guid, Program>(); public IEnumerable<Program> Programs { get { return ThreadSafe(() => programs.Values.ToList()); } } - HashSet<PendingBreakpoint> pendingBreakpoints = new HashSet<PendingBreakpoint>(); + readonly HashSet<PendingBreakpoint> pendingBreakpoints = new HashSet<PendingBreakpoint>(); public IEnumerable<PendingBreakpoint> PendingBreakpoints { get { return ThreadSafe(() => pendingBreakpoints.ToList()); } @@ -106,8 +106,7 @@ if (string.IsNullOrEmpty(pszOptions)) return VSConstants.E_FAIL; - uint procId; - if (!uint.TryParse(pszOptions, out procId)) + if (!uint.TryParse(pszOptions, out uint procId)) return VSConstants.E_FAIL; var env = bstrEnv.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) @@ -120,13 +119,12 @@ FileSystem.RegisterRccFile(rccFile); } - IDebugProcess2 nativeProc; var nativeProcId = new AD_PROCESS_ID { ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM, dwProcessId = procId }; - if (pPort.GetProcess(nativeProcId, out nativeProc) != VSConstants.S_OK) + if (pPort.GetProcess(nativeProcId, out IDebugProcess2 nativeProc) != VSConstants.S_OK) return VSConstants.E_FAIL; var program = Program.Create(this, nativeProc, pszExe, pszArgs); @@ -144,20 +142,11 @@ if (program == null) return VSConstants.E_FAIL; - IDebugPort2 port; - if (process.GetPort(out port) != VSConstants.S_OK) + if (process.GetPort(out IDebugPort2 port) != VSConstants.S_OK) return VSConstants.E_FAIL; - string portName; - port.GetPortName(out portName); - - Guid guidPort; - port.GetPortId(out guidPort); - IDebugDefaultPort2 defaultPort = (IDebugDefaultPort2)port; - - IDebugPortNotify2 portNotify; - if (defaultPort.GetPortNotify(out portNotify) != VSConstants.S_OK) + if (defaultPort.GetPortNotify(out IDebugPortNotify2 portNotify) != VSConstants.S_OK) return VSConstants.E_FAIL; if (portNotify.AddProgramNode(program) != VSConstants.S_OK) @@ -181,8 +170,7 @@ DebugEvent.Send(new EngineCreateEvent(this)); - Guid pguidProgramId; - if (rgpPrograms[0].GetProgramId(out pguidProgramId) != VSConstants.S_OK) + if (rgpPrograms[0].GetProgramId(out Guid pguidProgramId) != VSConstants.S_OK) return VSConstants.E_FAIL; program.ProgramId = pguidProgramId; @@ -199,15 +187,10 @@ int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 pProcess) { - Guid procId; - if (pProcess.GetProcessId(out procId) != VSConstants.S_OK) + if (pProcess.GetProcessId(out Guid procId) != VSConstants.S_OK) return VSConstants.E_FAIL; - Program program; - if (!programs.TryGetValue(procId, out program)) - return VSConstants.S_FALSE; - - return VSConstants.S_OK; + return programs.TryGetValue(procId, out _) ? VSConstants.S_OK : VSConstants.S_FALSE; } public bool ProgramIsRunning(Program program) @@ -217,12 +200,10 @@ int IDebugEngineLaunch2.TerminateProcess(IDebugProcess2 pProcess) { - Guid procId; - if (pProcess.GetProcessId(out procId) != VSConstants.S_OK) + if (pProcess.GetProcessId(out Guid procId) != VSConstants.S_OK) return VSConstants.E_FAIL; - Program program; - if (!programs.TryGetValue(procId, out program)) + if (!programs.TryGetValue(procId, out Program program)) return VSConstants.S_FALSE; programs.Remove(procId); @@ -235,8 +216,7 @@ int IDebugEngine2.ContinueFromSynchronousEvent(IDebugEvent2 pEvent) { - var evtProgramDestroy = pEvent as ProgramDestroyEvent; - if (evtProgramDestroy != null) + if (pEvent is ProgramDestroyEvent evtProgramDestroy) evtProgramDestroy.Program.Dispose(); return VSConstants.S_OK; @@ -271,7 +251,7 @@ #region //////////////////// Concurrent /////////////////////////////////////////////////// - LocalConcurrent concurrent = new LocalConcurrent(); + readonly LocalConcurrent concurrent = new LocalConcurrent(); class LocalConcurrent : Concurrent { public void LocalThreadSafe(Action action) diff --git a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Events.cs b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Events.cs index 9c75bc5..6ea40cf 100644 --- a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Events.cs +++ b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Events.cs @@ -38,8 +38,8 @@ // such as stopping at a breakpoint, and non-critical information, such as a // debugging message." { - public Guid InterfaceId { get; protected set; } - public uint Attributes { get; protected set; } + private Guid InterfaceId { get; } + private uint Attributes { get; } protected const uint ASYNCHRONOUS = (uint)enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS; protected const uint STOPPING = (uint)enum_EVENTATTRIBUTES.EVENT_ASYNC_STOP; @@ -48,10 +48,10 @@ (uint)enum_EVENTATTRIBUTES.EVENT_STOPPING | (uint)enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS; - protected QmlEngine Engine { get; set; } - protected IDebugProgram2 Program { get; set; } - protected IDebugThread2 Thread { get; set; } - protected IDebugEventCallback2 Callback { get; set; } + protected QmlEngine Engine { get; } + private IDebugProgram2 Program { get; } + private IDebugThread2 Thread { get; } + private IDebugEventCallback2 Callback { get; } protected DebugEvent( QmlEngine engine, @@ -114,8 +114,8 @@ class ProgramDestroyEvent : DebugEvent, IDebugProgramDestroyEvent2 { - uint exitCode; - public new Program Program { get; private set; } + readonly uint exitCode; + public Program Program { get; } public ProgramDestroyEvent(Program program, uint exitCode) : base(program.Engine, typeof(IDebugProgramDestroyEvent2).GUID, @@ -142,7 +142,7 @@ class ThreadDestroyEvent : DebugEvent, IDebugThreadDestroyEvent2 { - uint exitCode; + readonly uint exitCode; public ThreadDestroyEvent(Program program, uint exitCode) : base(program.Engine, typeof(IDebugThreadDestroyEvent2).GUID, @@ -176,7 +176,7 @@ class BreakpointBoundEvent : DebugEvent, IDebugBreakpointBoundEvent2 { - public Breakpoint Breakpoint { get; private set; } + private Breakpoint Breakpoint { get; } public BreakpointBoundEvent(Breakpoint breakpoint) : base(breakpoint.Program.Engine, typeof(IDebugBreakpointBoundEvent2).GUID, ASYNCHRONOUS, breakpoint.Program, breakpoint.Program) @@ -201,7 +201,7 @@ class BreakpointEvent : DebugEvent, IDebugBreakpointEvent2 { - IEnumDebugBoundBreakpoints2 boundBreakpoints; + readonly IEnumDebugBoundBreakpoints2 boundBreakpoints; public BreakpointEvent(Program program, IEnumDebugBoundBreakpoints2 boundBreakpoints) @@ -228,8 +228,8 @@ class ExpressionEvaluationCompleteEvent : DebugEvent, IDebugExpressionEvaluationCompleteEvent2 { - public Expression Expression { get; private set; } - public Property Property { get; private set; } + private Expression Expression { get; } + private Property Property { get; } public ExpressionEvaluationCompleteEvent( IDebugEventCallback2 callback, @@ -257,7 +257,7 @@ class OutputStringEvent : DebugEvent, IDebugOutputStringEvent2 { - string outputString; + readonly string outputString; public OutputStringEvent(QmlEngine engine, string outputString) : base(engine, typeof(IDebugOutputStringEvent2).GUID, ASYNCHRONOUS) diff --git a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Expression.cs b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Expression.cs index 57f2e8b..f705c84 100644 --- a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Expression.cs +++ b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Expression.cs @@ -26,7 +26,6 @@ ** ****************************************************************************/ -using System; using System.Threading.Tasks; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Debugger.Interop; @@ -40,13 +39,13 @@ IDebugExpression2 // "This interface represents a parsed expression ready for binding // and evaluating." { - public string ExpressionString { get; private set; } + private string ExpressionString { get; set; } - public StackFrame StackFrame { get; private set; } + private StackFrame StackFrame { get; set; } public QmlEngine Engine { get; private set; } public Program Program { get; private set; } - public QmlDebugger Debugger { get; private set; } - public CodeContext CodeContext { get; private set; } + private QmlDebugger Debugger { get; set; } + private CodeContext CodeContext { get; set; } public static Expression Create(StackFrame frame, string expr) { @@ -86,7 +85,7 @@ enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback) { - Task.Run(() => + _ = Task.Run(() => { var value = Debugger.Evaluate(StackFrame.FrameNumber, ExpressionString); if (value != null) diff --git a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7InfoHelpers.cs b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7InfoHelpers.cs index 312aa39..dfd2af2 100644 --- a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7InfoHelpers.cs +++ b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7InfoHelpers.cs @@ -26,12 +26,9 @@ ** ****************************************************************************/ -using Microsoft.VisualStudio.Debugger.Interop; using System; using System.Collections; using System.Collections.Generic; -using System.Linq; -using System.Reflection; namespace QtVsTools.Qml.Debug.AD7 { @@ -76,9 +73,9 @@ public class Mapping<TStruct, TFieldMask> : Mapping, IEnumerable<MapField<TStruct, TFieldMask>> { - List<MapField<TStruct, TFieldMask>> fieldMaps; + readonly List<MapField<TStruct, TFieldMask>> fieldMaps; - protected static Action<Ref<TStruct>, TFieldMask> UpdateMask { get; set; } + private static Action<Ref<TStruct>, TFieldMask> UpdateMask { get; set; } public Mapping(Action<Ref<TStruct>, TFieldMask> updateMask) { @@ -188,8 +185,7 @@ TFieldMask fieldMask, out TStruct infoStruct) { - var mappingToStruct = mapping as Mapping<TStruct, TFieldMask>; - if (mappingToStruct != null) + if (mapping is Mapping<TStruct, TFieldMask> mappingToStruct) mappingToStruct.Map(this as TDerived, fieldMask, out infoStruct); else infoStruct = default(TStruct); diff --git a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Program.cs b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Program.cs index 6a7cee4..0111f31 100644 --- a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Program.cs +++ b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Program.cs @@ -29,18 +29,16 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading; using System.Windows.Threading; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Debugger.Interop; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; -using QtVsTools.VisualStudio; namespace QtVsTools.Qml.Debug.AD7 { + using VisualStudio; + sealed partial class Program : Disposable, IDebuggerEventSink, IDebugProgramNode2, // "This interface represents a program that can be debugged." @@ -64,21 +62,21 @@ public QmlEngine Engine { get; private set; } - public List<StackFrame> CurrentFrames { get; private set; } + private List<StackFrame> CurrentFrames { get; set; } - public const string Name = "QML Debugger"; - public Guid ProcessId { get; private set; } + private const string Name = "QML Debugger"; + public Guid ProcessId { get; set; } public Guid ProgramId { get; set; } - public IDebugProcess2 NativeProc { get; private set; } - public uint NativeProcId { get; private set; } - public string ExecPath { get; private set; } - public string ExecArgs { get; private set; } - public IVsDebugger VsDebugger { get; private set; } - Dispatcher vsDebuggerThreadDispatcher; + private IDebugProcess2 NativeProc { get; set; } + private uint NativeProcId { get; set; } + private string ExecPath { get; set; } + private string ExecArgs { get; set; } + private IVsDebugger VsDebugger { get; set; } + private Dispatcher vsDebuggerThreadDispatcher; - private readonly static object criticalSectionGlobal = new object(); - static bool originalBreakAllProcesses = BreakAllProcesses; - static int runningPrograms = 0; + private static readonly object criticalSectionGlobal = new object(); + private static bool originalBreakAllProcesses = BreakAllProcesses; + private static int runningPrograms = 0; public static Program Create( QmlEngine engine, @@ -114,8 +112,13 @@ return false; VsDebugger = VsServiceProvider.GetService<IVsDebugger>(); - if (VsDebugger != null) - VsDebugger.AdviseDebugEventCallback(this as IDebugEventCallback2); + if (VsDebugger != null) { + ThreadHelper.JoinableTaskFactory.Run(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + VsDebugger.AdviseDebugEventCallback(this); + }); + } vsDebuggerThreadDispatcher = Dispatcher.CurrentDispatcher; ProcessId = Guid.NewGuid(); @@ -141,8 +144,13 @@ protected override void DisposeManaged() { Debugger.Dispose(); - if (VsDebugger != null) - VsDebugger.UnadviseDebugEventCallback(this as IDebugEventCallback2); + if (VsDebugger != null) { + ThreadHelper.JoinableTaskFactory.Run(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + VsDebugger.UnadviseDebugEventCallback(this as IDebugEventCallback2); + }); + } lock (criticalSectionGlobal) { runningPrograms--; @@ -161,9 +169,12 @@ { var debugMode = new DBGMODE[1]; int res = VSConstants.S_FALSE; - vsDebuggerThreadDispatcher - .BeginInvoke(new Action(() => res = VsDebugger.GetMode(debugMode)), new object[0]) - .Wait(); + + QtVsToolsPackage.Instance.JoinableTaskFactory.Run(async () => + { + await QtVsToolsPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync(); + res = VsDebugger.GetMode(debugMode); + }); if (res != VSConstants.S_OK) return false; @@ -295,17 +306,24 @@ { get { - return ((bool)QtVsToolsPackage.Instance.Dte - .Properties["Debugging", "General"] - .Item("BreakAllProcesses") - .Value); + return ThreadHelper.JoinableTaskFactory.Run(async () => { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + return ((bool)QtVsToolsPackage.Instance.Dte + .Properties["Debugging", "General"] + .Item("BreakAllProcesses") + .Value); + }); } set { - QtVsToolsPackage.Instance.Dte - .Properties["Debugging", "General"] - .Item("BreakAllProcesses") - .let_Value(value ? "True" : "False"); + ThreadHelper.JoinableTaskFactory.Run(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + QtVsToolsPackage.Instance.Dte + .Properties["Debugging", "General"] + .Item("BreakAllProcesses") + .let_Value(value ? "True" : "False"); + }); } } diff --git a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Property.cs b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Property.cs index c1e7c1f..eba56a8 100644 --- a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Property.cs +++ b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7Property.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Debugger.Interop; @@ -43,23 +42,23 @@ // property, or some other property. The property is usually the result of // an expression evaluation." { - public QmlDebugger Debugger { get; private set; } + private QmlDebugger Debugger { get; set; } - public QmlEngine Engine { get; private set; } - public Program Program { get; private set; } - public StackFrame StackFrame { get; private set; } - public CodeContext CodeContext { get; private set; } + private QmlEngine Engine { get; set; } + private Program Program { get; set; } + private StackFrame StackFrame { get; set; } + private CodeContext CodeContext { get; set; } - public Property Parent { get; private set; } - public SortedDictionary<string, Property> Children { get; private set; } + private Property Parent { get; set; } + private SortedDictionary<string, Property> Children { get; set; } - public int FrameNumber { get; private set; } - public int ScopeNumber { get; private set; } - public JsValue JsValue { get; private set; } - public string Name { get; private set; } - public string FullName { get; private set; } - public string Type { get; private set; } - public string Value { get; private set; } + private int FrameNumber { get; set; } + private int ScopeNumber { get; set; } + private JsValue JsValue { get; set; } + private string Name { get; set; } + private string FullName { get; set; } + private string Type { get; set; } + private string Value { get; set; } public static Property Create( StackFrame frame, @@ -120,11 +119,9 @@ static string GetChildKey(string childName) { - int childIndex; - if (int.TryParse(childName, out childIndex)) + if (int.TryParse(childName, out int childIndex)) return string.Format("{0:D9}", childIndex); - else - return childName; + return childName; } int IDebugProperty2.SetValueAsString(string pszValue, uint dwRadix, uint dwTimeout) @@ -242,8 +239,7 @@ public DEBUG_PROPERTY_INFO GetInfo(enum_DEBUGPROP_INFO_FLAGS dwFields) { - DEBUG_PROPERTY_INFO info; - Info.Map(MappingToDEBUG_PROPERTY_INFO, dwFields, out info); + Info.Map(MappingToDEBUG_PROPERTY_INFO, dwFields, out DEBUG_PROPERTY_INFO info); return info; } @@ -275,19 +271,19 @@ public static readonly Guid Registers = new Guid("223ae797-bd09-4f28-8241-2763bdc5f713"); - public static readonly Guid Locals + private static readonly Guid Locals = new Guid("b200f725-e725-4c53-b36a-1ec27aef12ef"); - public static readonly Guid AllLocals + private static readonly Guid AllLocals = new Guid("196db21f-5f22-45a9-b5a3-32cddb30db06"); public static readonly Guid Args = new Guid("804bccea-0475-4ae7-8a46-1862688ab863"); - public static readonly Guid LocalsPlusArgs + private static readonly Guid LocalsPlusArgs = new Guid("e74721bb-10c0-40f5-807f-920d37f95419"); - public static readonly Guid AllLocalsPlusArgs + private static readonly Guid AllLocalsPlusArgs = new Guid("939729a8-4cb0-4647-9831-7ff465240d5f"); public static bool LocalsSelected(ref Guid guidFilter) diff --git a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7StackFrame.cs b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7StackFrame.cs index 8578f60..cc80a67 100644 --- a/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7StackFrame.cs +++ b/QtVsTools.Package/QML/Debugging/AD7/QmlDebugAD7StackFrame.cs @@ -32,6 +32,7 @@ using System.Threading.Tasks; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Debugger.Interop; +using Microsoft.VisualStudio.Threading; namespace QtVsTools.Qml.Debug.AD7 { @@ -52,14 +53,14 @@ public Program Program { get; private set; } public CodeContext Context { get; private set; } - public Dictionary<int, Dictionary<string, Property>> Properties { get; private set; } + private Dictionary<int, Dictionary<string, Property>> Properties { get; set; } - public string Name { get; private set; } - public int FrameNumber { get; private set; } - public IEnumerable<int> Scopes { get; private set; } - public Task InitThread { get; private set; } + private string Name { get; set; } + public int FrameNumber { get; set; } + private IEnumerable<int> Scopes { get; set; } + private JoinableTask InitThread { get; set; } - static public StackFrame Create( + public static StackFrame Create( string name, int number, IEnumerable<int> scopes, @@ -85,7 +86,11 @@ Name = string.Format("{0}@{1}:{2}", name, context.FilePath, context.FileLine + 1); FrameNumber = number; Scopes = scopes; - InitThread = Task.Run(() => InitializeProperties()); + InitThread = QtVsToolsPackage.Instance.JoinableTaskFactory.RunAsync(async () => + { + InitializeProperties(); + await Task.Yield(); + }); return true; } @@ -134,7 +139,7 @@ if (guidFilter != Guid.Empty && !Property.Filter.LocalsSelected(ref guidFilter)) return VSConstants.S_OK; - InitThread.Wait(); + InitThread.Join(); pcelt = 0; ppEnum = PropertyEnum.Create(Properties .SelectMany(x => x.Value @@ -152,9 +157,8 @@ uint dwTimeout, out IEnumDebugPropertyInfo2 ppEnum) { - uint pcelt; return ((IDebugStackFrame2)this) - .EnumProperties(dwFields, dwRadix, guidFilter, dwTimeout, out pcelt, out ppEnum); + .EnumProperties(dwFields, dwRadix, guidFilter, dwTimeout, out _, out ppEnum); } #region //////////////////// Info ///////////////////////////////////////////////////////// diff --git a/QtVsTools.Package/QML/Debugging/QmlDebugLauncher.cs b/QtVsTools.Package/QML/Debugging/QmlDebugLauncher.cs index 025ee42..02fd242 100644 --- a/QtVsTools.Package/QML/Debugging/QmlDebugLauncher.cs +++ b/QtVsTools.Package/QML/Debugging/QmlDebugLauncher.cs @@ -35,39 +35,50 @@ using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.VCProjectEngine; -using QtVsTools.Core; -using QtVsTools.Core.QtMsBuild; -using QtVsTools.SyntaxAnalysis; -using static QtVsTools.SyntaxAnalysis.RegExpr; namespace QtVsTools.Qml.Debug { using AD7; + using Common; + using Core; + using Core.QtMsBuild; + using SyntaxAnalysis; using VisualStudio; + + using static SyntaxAnalysis.RegExpr; class Launcher : Disposable, IDebugEventCallback2 { - public static Launcher Instance { get; private set; } + LazyFactory Lazy { get; } = new LazyFactory(); + + private static Launcher Instance { get; set; } IVsDebugger debugger; IVsDebugger4 debugger4; - HashSet<Guid> _ExcludedProcesses; - HashSet<Guid> ExcludedProcesses => _ExcludedProcesses - ?? (_ExcludedProcesses = new HashSet<Guid>()); + HashSet<Guid> ExcludedProcesses => Lazy.Get(() => + ExcludedProcesses, () => new HashSet<Guid>()); public static void Initialize() { + ThreadHelper.ThrowIfNotOnUIThread(); + Instance = new Launcher(); Instance.debugger = VsServiceProvider.GetService<IVsDebugger>(); Instance.debugger4 = VsServiceProvider.GetService<IVsDebugger, IVsDebugger4>(); + if (Instance.debugger != null && Instance.debugger4 != null) Instance.debugger.AdviseDebugEventCallback(Instance); } protected override void DisposeManaged() { - if (debugger != null) - debugger.UnadviseDebugEventCallback(this); + if (debugger != null) { + ThreadHelper.JoinableTaskFactory.Run(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + debugger.UnadviseDebugEventCallback(this); + }); + } } int IDebugEventCallback2.Event( @@ -79,6 +90,8 @@ ref Guid riidEvent, uint dwAttrib) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!QtVsToolsPackage.Instance.Options.QmlDebuggerEnabled) return VSConstants.S_OK; @@ -90,8 +103,7 @@ if (pProcess == null && pProgram.GetProcess(out pProcess) != VSConstants.S_OK) return VSConstants.S_OK; - Guid procGuid; - if (pProcess.GetProcessId(out procGuid) != VSConstants.S_OK) + if (pProcess.GetProcessId(out Guid procGuid) != VSConstants.S_OK) return VSConstants.S_OK; // Run only once per process @@ -119,14 +131,10 @@ else return VSConstants.S_OK; - string execPath; - uint procId; - if (!GetProcessInfo(pProcess, native, out execPath, out procId)) + if (!GetProcessInfo(pProcess, native, out string execPath, out uint procId)) return VSConstants.S_OK; - string execCmd; - IEnumerable<string> rccItems; - if (!GetProjectInfo(execPath, native, out execCmd, out rccItems)) + if (!GetProjectInfo(execPath, native, out string execCmd, out IEnumerable<string> rccItems)) return VSConstants.S_OK; LaunchDebug(execPath, execCmd, procId, rccItems); @@ -135,9 +143,7 @@ Guid GetEngineId(IDebugProgram2 pProgram) { - string engineName; - Guid engineGuid; - if (pProgram.GetEngineInfo(out engineName, out engineGuid) != VSConstants.S_OK) + if (pProgram.GetEngineInfo(out _, out Guid engineGuid) != VSConstants.S_OK) return Guid.Empty; return engineGuid; } @@ -152,7 +158,7 @@ } } - static RegExpr wslPathRegex = new Token("WSLPATH", SkipWs_Disable, StartOfFile + static readonly RegExpr wslPathRegex = new Token("WSLPATH", SkipWs_Disable, StartOfFile & "/mnt/" & new Token("DRIVE", CharWord) & "/" & new Token("PATH", AnyChar.Repeat())) { new Rule<WslPath> @@ -161,15 +167,14 @@ Update("PATH", (WslPath wslPath, string path) => wslPath.Path = path), } }; - static RegExpr.Parser wslPathParser = wslPathRegex.Render(); + static readonly RegExpr.Parser wslPathParser = wslPathRegex.Render(); bool GetProcessInfo(IDebugProcess2 pProcess, bool native, out string execPath, out uint procId) { execPath = ""; procId = 0; - string fileName; - if (pProcess.GetName(enum_GETNAME_TYPE.GN_FILENAME, out fileName) != VSConstants.S_OK) + if (pProcess.GetName(enum_GETNAME_TYPE.GN_FILENAME, out string fileName) != VSConstants.S_OK) return false; var pProcessId = new AD_PROCESS_ID[1]; @@ -193,6 +198,8 @@ bool GetProjectInfo(string execPath, bool native, out string execCmd, out IEnumerable<string> rccItems) { + ThreadHelper.ThrowIfNotOnUIThread(); + execCmd = ""; rccItems = null; @@ -290,6 +297,8 @@ uint procId, IEnumerable<string> rccItems) { + ThreadHelper.ThrowIfNotOnUIThread(); + var targets = new[] { new VsDebugTargetInfo4 { dlo = (uint)DEBUG_LAUNCH_OPERATION.DLO_CreateProcess, @@ -305,8 +314,8 @@ try { debugger4.LaunchDebugTargets4((uint)targets.Length, targets, processInfo); - } catch (System.Exception e) { - OutputWriteLine(e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); } } } diff --git a/QtVsTools.Package/QML/Debugging/QmlDebugger.cs b/QtVsTools.Package/QML/Debugging/QmlDebugger.cs index 892a17d..b877956 100644 --- a/QtVsTools.Package/QML/Debugging/QmlDebugger.cs +++ b/QtVsTools.Package/QML/Debugging/QmlDebugger.cs @@ -26,18 +26,19 @@ ** ****************************************************************************/ -using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; -using QtVsTools.SyntaxAnalysis; -using static QtVsTools.SyntaxAnalysis.RegExpr; -using RegExprParser = QtVsTools.SyntaxAnalysis.RegExpr.Parser; namespace QtVsTools.Qml.Debug { + using Common; + using SyntaxAnalysis; using V4; + + using RegExprParser = SyntaxAnalysis.RegExpr.Parser; + + using static SyntaxAnalysis.RegExpr; struct FrameInfo { @@ -69,6 +70,8 @@ class QmlDebugger : Disposable, IMessageEventSink { + static LazyFactory StaticLazy { get; } = new LazyFactory(); + IDebuggerEventSink sink; ProtocolDriver driver; string connectionHostName; @@ -80,11 +83,11 @@ List<Request> outbox; Dictionary<int, IBreakpoint> breakpoints; - public bool Started { get; private set; } + private bool Started { get; set; } - public bool Running { get; private set; } + private bool Running { get; set; } - public string Version { get; private set; } + private string Version { get; set; } public uint? ThreadId { get { return driver.ThreadId; } } @@ -160,7 +163,7 @@ if (!Started) { Running = Started = true; LeaveCriticalSection(); - Task.Run(() => ConnectToDebugger()); + _ = Task.Run(() => ConnectToDebugger()); } else if (!Running) { Running = true; @@ -201,7 +204,7 @@ setBreakpoint.Arguments.Line = (int)breakpoint.Line; setBreakpoint.Tag = breakpoint; if (driver.ConnectionState == DebugClientState.Connected) - setBreakpoint.SendAsync(); + setBreakpoint.SendRequest(); else ThreadSafe(() => outbox.Add(setBreakpoint)); } @@ -231,7 +234,7 @@ var reqClearBreak = Message.Create<ClearBreakpointRequest>(driver); reqClearBreak.Arguments.Breakpoint = breakpointNum[breakpoint]; - reqClearBreak.SendAsync(); + reqClearBreak.SendRequest(); } void RefreshFrames() @@ -286,8 +289,7 @@ } else { foreach (int breakpointId in evtBreak.Body.Breakpoints) { - IBreakpoint breakpoint; - if (!breakpoints.TryGetValue(breakpointId, out breakpoint)) + if (!breakpoints.TryGetValue(breakpointId, out IBreakpoint breakpoint)) continue; breakpoint.NotifyBreak(); } @@ -406,20 +408,20 @@ { if (oldState != DebugClientState.Unavailable && newState == DebugClientState.Disconnected) { - Task.Run(() => sink.NotifyClientDisconnected()); + _ = Task.Run(() => sink.NotifyClientDisconnected()); } } void IMessageEventSink.NotifyRequestResponded(Request msgRequest) { if (msgRequest is SetBreakpointRequest) - Task.Run(() => SetBreakpointResponded(msgRequest as SetBreakpointRequest)); + _ = Task.Run(() => SetBreakpointResponded(msgRequest as SetBreakpointRequest)); } void IMessageEventSink.NotifyEvent(Event msgEvent) { if (msgEvent is BreakEvent) - Task.Run(() => BreakNotified(msgEvent as BreakEvent)); + _ = Task.Run(() => BreakNotified(msgEvent as BreakEvent)); } void IMessageEventSink.NotifyMessage(Message msg) @@ -430,13 +432,7 @@ public static bool CheckCommandLine(string execPath, string args) { - ushort portFrom; - ushort portTo; - string hostName; - string fileName; - bool block; - return ParseCommandLine( - execPath, args, out portFrom, out portTo, out hostName, out fileName, out block); + return ParseCommandLine(execPath, args, out _, out _, out _, out _, out _); } /// <summary> @@ -456,8 +452,8 @@ /// <summary> /// Regex-based parser for QML debug connection parameters /// </summary> - static RegExprParser ConnectParamsParser => _ConnectParamsParser ?? ( - _ConnectParamsParser = new Token(TokenId.ConnectParams, RxConnectParams) + static RegExprParser ConnectParamsParser => StaticLazy.Get(() => + ConnectParamsParser, () => new Token(TokenId.ConnectParams, RxConnectParams) { new Rule<ConnectParams> { @@ -469,7 +465,6 @@ } } .Render()); - static RegExprParser _ConnectParamsParser; /// <summary> /// Regular expression for parsing connection parameters string in the form: diff --git a/QtVsTools.Package/QML/Debugging/QmlFileSystem.cs b/QtVsTools.Package/QML/Debugging/QmlFileSystem.cs index 4b33faf..20af63b 100644 --- a/QtVsTools.Package/QML/Debugging/QmlFileSystem.cs +++ b/QtVsTools.Package/QML/Debugging/QmlFileSystem.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -36,6 +36,8 @@ namespace QtVsTools.Qml.Debug { + using QtVsTools.Core; + struct QmlFile { public string QrcPath; @@ -92,9 +94,8 @@ using (var reader = XmlReader.Create(new StringReader(xmlText), settings)) { rccXml = XDocument.Load(reader); } - } catch (Exception e) { - System.Diagnostics.Debug.WriteLine( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); return; } @@ -156,8 +157,7 @@ qrcPath = string.Format("qrc:///{0}", qrcPath); - QmlFile file; - if (!files.TryGetValue(qrcPath, out file)) + if (!files.TryGetValue(qrcPath, out QmlFile file)) return default(QmlFile); return file; @@ -190,8 +190,7 @@ return default(QmlFile); } - QmlFile file; - if (files.TryGetValue(fullPath, out file)) + if (files.TryGetValue(fullPath, out QmlFile file)) return file; return new QmlFile diff --git a/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Continue.cs b/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Continue.cs index 905adff..febf0d7 100644 --- a/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Continue.cs +++ b/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Continue.cs @@ -26,10 +26,7 @@ ** ****************************************************************************/ -using System.Collections.Generic; -using System.ComponentModel; using System.Runtime.Serialization; -using System.Threading; namespace QtVsTools.Qml.Debug.V4 { diff --git a/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4JsObject.cs b/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4JsObject.cs index a5a9272..eb5b243 100644 --- a/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4JsObject.cs +++ b/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4JsObject.cs @@ -26,7 +26,6 @@ ** ****************************************************************************/ -using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; diff --git a/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Message.cs b/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Message.cs index ad1a5b9..f1c3739 100644 --- a/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Message.cs +++ b/QtVsTools.Package/QML/Debugging/V4/Messages/QmlDebugV4Message.cs @@ -143,14 +143,14 @@ set { Atomic(() => tag == null, () => tag = value); } } - public virtual ProtocolDriver.PendingRequest SendAsync() + public virtual ProtocolDriver.PendingRequest SendRequest() { return Driver.SendRequest(this); } public new Response Send() { - return SendAsync().WaitForResponse(); + return SendRequest().WaitForResponse(); } public static new Response Send<T>(ProtocolDriver driver, Action<T> initMsg = null) @@ -173,7 +173,7 @@ public new virtual TResponse Send() { - var pendingRequest = SendAsync(); + var pendingRequest = SendRequest(); if (!pendingRequest.RequestSent) return null; diff --git a/QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Client.cs b/QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Client.cs index abbf6de..19f88f2 100644 --- a/QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Client.cs +++ b/QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Client.cs @@ -26,14 +26,9 @@ ** ****************************************************************************/ -using QtVsTools.Options; using System; -using System.Collections.Concurrent; -using System.IO; using System.Net.Sockets; using System.Runtime.InteropServices; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Json; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -62,7 +57,7 @@ IConnectionEventSink sink; IntPtr client; Task clientThread; - EventWaitHandle clientCreated = new EventWaitHandle(false, EventResetMode.ManualReset); + readonly EventWaitHandle clientCreated = new EventWaitHandle(false, EventResetMode.ManualReset); EventWaitHandle clientConnected; public uint? ThreadId { get; private set; } @@ -82,7 +77,7 @@ if (state != value) { var oldState = state; state = value; - Task.Run(() => sink.NotifyStateTransition(this, oldState, value)); + _ = Task.Run(() => sink.NotifyStateTransition(this, oldState, value)); } } } @@ -100,14 +95,17 @@ { this.sink = sink; - Task.WaitAny(new[] + QtVsToolsPackage.Instance.JoinableTaskFactory.Run(async () => { - // Try to start client thread - // Unblock if thread was abruptly terminated (e.g. DLL not found) - clientThread = Task.Run(() => ClientThread()), + await Task.WhenAny(new[] + { + // Try to start client thread + // Unblock if thread was abruptly terminated (e.g. DLL not found) + clientThread = Task.Run(() => ClientThread()), - // Unblock if client was created (i.e. client thread is running) - Task.Run(() => clientCreated.WaitOne()) + // Unblock if client was created (i.e. client thread is running) + Task.Run(() => clientCreated.WaitOne()) + }); }); if (State == DebugClientState.Unavailable) { @@ -135,7 +133,9 @@ { if (State != DebugClientState.Unavailable) { NativeMethods.DebugClientShutdown(client); - clientThread.Wait(); + + QtVsToolsPackage.Instance.JoinableTaskFactory.Run( + async () => await Task.WhenAll(new[] { clientThread })); } } @@ -180,7 +180,7 @@ var hostNameData = Encoding.UTF8.GetBytes(hostName); uint timeout = (uint)QtVsToolsPackage.Instance.Options.QmlDebuggerTimeout; - Task.Run(() => + _ = Task.Run(() => { var connectTimer = new System.Diagnostics.Stopwatch(); connectTimer.Start(); @@ -246,7 +246,7 @@ uint timeout = (uint)QtVsToolsPackage.Instance.Options.QmlDebuggerTimeout; if (timeout != 0) { - Task.Run(() => + _ = Task.Run(() => { var connectTimer = new System.Diagnostics.Stopwatch(); connectTimer.Start(); diff --git a/QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Protocol.cs b/QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Protocol.cs index 07315df..a6bc303 100644 --- a/QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Protocol.cs +++ b/QtVsTools.Package/QML/Debugging/V4/QmlDebugV4Protocol.cs @@ -53,10 +53,10 @@ IMessageEventSink sink; DebugClient client; int nextRequestSeq = 0; - Dictionary<int, PendingRequest> pendingRequests = new Dictionary<int, PendingRequest>(); + readonly Dictionary<int, PendingRequest> pendingRequests = new Dictionary<int, PendingRequest>(); Task eventHandlingThread; - EventWaitHandle eventReceived = new EventWaitHandle(false, EventResetMode.AutoReset); - ConcurrentQueue<Event> eventQueue = new ConcurrentQueue<Event>(); + readonly EventWaitHandle eventReceived = new EventWaitHandle(false, EventResetMode.AutoReset); + readonly ConcurrentQueue<Event> eventQueue = new ConcurrentQueue<Event>(); public uint? ThreadId { get { return client.ThreadId; } } @@ -92,7 +92,8 @@ protected override void DisposeFinally() { eventReceived.Set(); - eventHandlingThread.Wait(); + QtVsToolsPackage.Instance.JoinableTaskFactory.Run( + async () => await Task.WhenAll(new[] { eventHandlingThread })); eventReceived.Dispose(); } @@ -100,8 +101,7 @@ { while (!Disposing) { eventReceived.WaitOne(); - Event evt; - while (!Disposing && eventQueue.TryDequeue(out evt)) + while (!Disposing && eventQueue.TryDequeue(out Event evt)) sink.NotifyEvent(evt); } } @@ -209,8 +209,8 @@ public class PendingRequest : Finalizable { - public Request Request { get; private set; } - EventWaitHandle responded; + public Request Request { get; } + readonly EventWaitHandle responded; public PendingRequest() { diff --git a/QtVsTools.Package/QML/Parser/QmlParserDiagnostics.cs b/QtVsTools.Package/QML/Parser/QmlParserDiagnostics.cs index 484dc03..929bb80 100644 --- a/QtVsTools.Package/QML/Parser/QmlParserDiagnostics.cs +++ b/QtVsTools.Package/QML/Parser/QmlParserDiagnostics.cs @@ -37,8 +37,8 @@ /// </summary> public class DiagnosticMessage { - public DiagnosticMessageKind Kind { get; set; } - public SourceLocation Location { get; set; } + private DiagnosticMessageKind Kind { get; } + public SourceLocation Location { get; } public DiagnosticMessage(DiagnosticMessageKind kind, int offset, int length) { Kind = kind; diff --git a/QtVsTools.Package/QML/Parser/QmlParserInterop.cs b/QtVsTools.Package/QML/Parser/QmlParserInterop.cs index 8ff5d87..d9965f2 100644 --- a/QtVsTools.Package/QML/Parser/QmlParserInterop.cs +++ b/QtVsTools.Package/QML/Parser/QmlParserInterop.cs @@ -148,28 +148,27 @@ IntPtr qmlTextPtr = IntPtr.Zero; IntPtr qmlParserPtr = IntPtr.Zero; - - List<Token> tokens; + readonly List<Token> tokens; public IEnumerable<Token> Tokens { get { return tokens; } } - List<DiagnosticMessage> diagnosticMessages; + readonly List<DiagnosticMessage> diagnosticMessages; public IEnumerable<DiagnosticMessage> DiagnosticMessages { get { return diagnosticMessages; } } - public int FirstErrorOffset { get; private set; } + private int FirstErrorOffset { get; set; } - List<AstNode> visitedNodes; + readonly List<AstNode> visitedNodes; public IEnumerable<AstNode> AstNodes { get { return visitedNodes; } } public bool ParsedCorrectly { get; private set; } - Dictionary<IntPtr, AstNode> nodesBytPtr; - Dictionary<IntPtr, List<KeyValuePair<AstNode, PropertyInfo>>> pendingDereferences; + readonly Dictionary<IntPtr, AstNode> nodesBytPtr; + readonly Dictionary<IntPtr, List<KeyValuePair<AstNode, PropertyInfo>>> pendingDereferences; Parser() { @@ -315,8 +314,7 @@ if (ptrRef == IntPtr.Zero) return; - AstNode nodeRef; - if (nodesBytPtr.TryGetValue(ptrRef, out nodeRef)) { + if (nodesBytPtr.TryGetValue(ptrRef, out AstNode nodeRef)) { nodeProperty.SetValue(node, nodeRef); } else { List<KeyValuePair<AstNode, PropertyInfo>> pendingRefList; diff --git a/QtVsTools.Package/QML/Syntax/QmlAst.cs b/QtVsTools.Package/QML/Syntax/QmlAst.cs index 1b3b1d1..a5e5ff4 100644 --- a/QtVsTools.Package/QML/Syntax/QmlAst.cs +++ b/QtVsTools.Package/QML/Syntax/QmlAst.cs @@ -156,7 +156,7 @@ public class AstNode : SyntaxElement { - public AstNodeKind Kind { get; private set; } + public AstNodeKind Kind { get; } public AstNode(AstNodeKind kind) { Kind = kind; } public SourceLocation FirstSourceLocation { get; set; } public SourceLocation LastSourceLocation { get; set; } diff --git a/QtVsTools.Package/QML/Syntax/QmlSyntax.cs b/QtVsTools.Package/QML/Syntax/QmlSyntax.cs index 1035815..0e5ac06 100644 --- a/QtVsTools.Package/QML/Syntax/QmlSyntax.cs +++ b/QtVsTools.Package/QML/Syntax/QmlSyntax.cs @@ -192,7 +192,7 @@ /// </summary> public class Token : SyntaxElement { - public TokenKind Kind { get; private set; } + private TokenKind Kind { get; set; } public SourceLocation Location { get; private set; } protected Token() { } public static Token Create(TokenKind kind, int offset, int length) diff --git a/QtVsTools.Package/QtMenus.vsct_TT b/QtVsTools.Package/QtMenus.vsct_TT index 76d066f..2f7f7d8 100644 --- a/QtVsTools.Package/QtMenus.vsct_TT +++ b/QtVsTools.Package/QtMenus.vsct_TT @@ -2,7 +2,7 @@ <!-- ***************************************************************************** ** - ** Copyright (C) 2016 The Qt Company Ltd. + ** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -152,15 +152,8 @@ <Group guid="ProjectContextMenuGuid" id="ProjectContextOthersMenuGroup" priority="0x0600"> <Parent guid="ProjectContextMenuGuid" id="QtProjectSubMenu"/> </Group> - <Group guid="ProjectContextMenuGuid" id="ProjectContextAddNewQtClassMenuGroup" priority="0x0600"> - <Parent guid="guidSHLMainMenu" id="cmdidShellWindowNavigate7"/> - </Group> <!-- Endregion Project context menu groups --> - - <Group guid="ProjectContextMenuGuid" id="ProjectContextAddNewQtClassMenuGroup" priority="0x0600"> - <Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_PROJECT" /> - </Group> <Group guid="ItemContextMenuGuid" id="ItemContextTsMenuGroup" priority="0x0600"> <Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_ITEMNODE" /> @@ -209,6 +202,15 @@ <ButtonText>qt.io</ButtonText> </Strings> </Button> + <Button guid="MainMenuGuid" id="ViewGettingStartedId" priority="0x0100" type="Button"> + <Parent guid="MainMenuGuid" id="VersionMenuGroup" /> + <Icon guid="MenuImages" id="QtLogoBitmap" /> + <CommandFlag>DynamicVisibility</CommandFlag> + <CommandFlag>DefaultInvisible</CommandFlag> + <Strings> + <ButtonText>Getting Started</ButtonText> + </Strings> + </Button> <Button guid="MainMenuGuid" id="F1QtHelpId" priority="0x0100" type="Button"> <Parent guid="MainMenuGuid" id="VersionMenuGroup" /> @@ -285,16 +287,6 @@ </Strings> </Button> - <Button guid="MainMenuGuid" id="CreateNewTsFileId" priority="0x0100" type="Button"> - <Parent guid="MainMenuGuid" id="OthersMenuGroup" /> - <CommandFlag>DefaultDisabled</CommandFlag> - <CommandFlag>DynamicVisibility</CommandFlag> - <CommandFlag>DefaultInvisible</CommandFlag> - <Strings> - <ButtonText>Create New Translation File</ButtonText> - <ToolTipText>Create a new translation file that you can open in Qt Linguist</ToolTipText> - </Strings> - </Button> <Button guid="MainMenuGuid" id="ConvertToQtMsBuild" priority="0x0100" type="Button"> <Parent guid="MainMenuGuid" id="OthersMenuGroup" /> <CommandFlag>DefaultDisabled</CommandFlag> @@ -302,24 +294,6 @@ <CommandFlag>DynamicVisibility</CommandFlag> <Strings> <ButtonText>Convert custom build steps to Qt/MSBuild</ButtonText> - </Strings> - </Button> - <Button guid="MainMenuGuid" id="ConvertToQtId" priority="0x0100" type="Button"> - <Parent guid="MainMenuGuid" id="OthersMenuGroup" /> - <CommandFlag>DefaultDisabled</CommandFlag> - <CommandFlag>DefaultInvisible</CommandFlag> - <CommandFlag>DynamicVisibility</CommandFlag> - <Strings> - <ButtonText>Convert Project to Qt VS Tools Project</ButtonText> - </Strings> - </Button> - <Button guid="MainMenuGuid" id="ConvertToQmakeId" priority="0x0100" type="Button"> - <Parent guid="MainMenuGuid" id="OthersMenuGroup" /> - <CommandFlag>DefaultDisabled</CommandFlag> - <CommandFlag>DynamicVisibility</CommandFlag> - <CommandFlag>DefaultInvisible</CommandFlag> - <Strings> - <ButtonText>Convert Project to QMake Generated Project</ButtonText> </Strings> </Button> <Button guid="MainMenuGuid" id="QtProjectSettingsId" priority="0x0100" type="Button"> @@ -451,15 +425,6 @@ </Strings> </Button> - <Button guid="ProjectContextMenuGuid" id="CreateNewTsFileProjectId" priority="0x0100" type="Button"> - <Parent guid="ProjectContextMenuGuid" id="ProjectContextTsMenuGroup" /> - <CommandFlag>DefaultDisabled</CommandFlag> - <CommandFlag>DynamicVisibility</CommandFlag> - <Strings> - <ButtonText>Create New Translation File</ButtonText> - <ToolTipText>Create a new translation file that you can open in Qt Linguist</ToolTipText> - </Strings> - </Button> <Button guid="ProjectContextMenuGuid" id="lUpdateOnProjectId" priority="0x0100" type="Button"> <Parent guid="ProjectContextMenuGuid" id="ProjectContextTsMenuGroup" /> <Icon guid="MenuImages" id="LaunchLinguistBitmap" /> @@ -499,23 +464,6 @@ <ButtonText>Refresh IntelliSense</ButtonText> </Strings> </Button> - <Button guid="ProjectContextMenuGuid" id="ConvertToQtProjectId" priority="0x0100" type="Button"> - <Parent guid="ProjectContextMenuGuid" id="ProjectContextOthersMenuGroup" /> - <CommandFlag>DefaultDisabled</CommandFlag> - <CommandFlag>DefaultInvisible</CommandFlag> - <CommandFlag>DynamicVisibility</CommandFlag> - <Strings> - <ButtonText>Convert Project to Qt VS Tools Project</ButtonText> - </Strings> - </Button> - <Button guid="ProjectContextMenuGuid" id="ConvertToQmakeProjectId" priority="0x0100" type="Button"> - <Parent guid="ProjectContextMenuGuid" id="ProjectContextOthersMenuGroup" /> - <CommandFlag>DefaultDisabled</CommandFlag> - <CommandFlag>DynamicVisibility</CommandFlag> - <Strings> - <ButtonText>Convert Project to QMake Generated Project</ButtonText> - </Strings> - </Button> <Button guid="ProjectContextMenuGuid" id="QtProjectSettingsProjectId" priority="0x0100" type="Button"> <Parent guid="ProjectContextMenuGuid" id="ProjectContextOthersMenuGroup" /> <CommandFlag>DefaultDisabled</CommandFlag> @@ -532,16 +480,6 @@ <CommandFlag>DynamicVisibility</CommandFlag> <Strings> <ButtonText>Change Project's Qt Version</ButtonText> - </Strings> - </Button> - <Button guid="ProjectContextMenuGuid" id="ProjectAddNewQtClassProjectId" priority="0x0100" type="Button"> - <Parent guid="ProjectContextMenuGuid" id="ProjectContextAddNewQtClassMenuGroup" /> - <Icon guid="MenuImages" id="AddNewQtClassBitmap" /> - <CommandFlag>DefaultDisabled</CommandFlag> - <CommandFlag>DefaultInvisible</CommandFlag> - <CommandFlag>DynamicVisibility</CommandFlag> - <Strings> - <ButtonText>Add Qt Class...</ButtonText> </Strings> </Button> @@ -586,7 +524,7 @@ --> <Bitmap guid="MenuImages" href="Resources\menuimages.png" usedList="LaunchDesignerBitmap, LaunchLinguistBitmap, OpenProFileBitmap, ImportPriFileBitmap, ExportProFileBitmap, - CreateProFileBitmap, QtLogoBitmap, AddNewQtClassBitmap" /> + CreateProFileBitmap, QtLogoBitmap" /> </Bitmaps> </Commands> @@ -605,6 +543,7 @@ <IDSymbol name="QtVersionId" value="0x0500" /> <IDSymbol name="ViewQtHelpId" value="0x0501" /> <IDSymbol name="F1QtHelpId" value="0x0502" /> + <IDSymbol name="ViewGettingStartedId" value="0x0503" /> <IDSymbol name="LaunchMenuGroup" value="0x1021" /> <IDSymbol name="LaunchDesignerId" value="0x0100" /> @@ -617,10 +556,7 @@ <IDSymbol name="ExportProFileId" value="0x0105" /> <IDSymbol name="OthersMenuGroup" value="0x1023" /> - <IDSymbol name="CreateNewTsFileId" value="0x0107" /> <IDSymbol name="ConvertToQtMsBuild" value="0x0130" /> - <IDSymbol name="ConvertToQtId" value="0x0124" /> - <IDSymbol name="ConvertToQmakeId" value="0x0108" /> <IDSymbol name="QtProjectSettingsId" value="0x0109" /> <IDSymbol name="ChangeProjectQtVersionId" value="0x0126" /> @@ -665,20 +601,16 @@ <IDSymbol name="ExportProFileProjectId" value="0x0116" /> <IDSymbol name="ProjectContextTsMenuGroup" value="0x1028" /> - <IDSymbol name="CreateNewTsFileProjectId" value="0x0117" /> <IDSymbol name="lUpdateOnProjectId" value="0x0118" /> <IDSymbol name="lReleaseOnProjectId" value="0x0119" /> <IDSymbol name="ProjectContextOthersMenuGroup" value="0x1029" /> <IDSymbol name="ProjectConvertToQtMsBuild" value="0x0130" /> <IDSymbol name="ProjectRefreshIntelliSense" value="0x0131" /> - <IDSymbol name="ConvertToQtProjectId" value="0x0120" /> - <IDSymbol name="ConvertToQmakeProjectId" value="0x0121" /> <IDSymbol name="QtProjectSettingsProjectId" value="0x0122" /> <IDSymbol name="ChangeProjectQtVersionProjectId" value="0x0123" /> <IDSymbol name="ProjectContextAddNewQtClassMenuGroup" value="0x1031" /> - <IDSymbol name="ProjectAddNewQtClassProjectId" value="0x0200" /> <!-- Endregion Project context menu button Ids --> @@ -700,7 +632,6 @@ <IDSymbol name="ExportProFileBitmap" value="5" /> <IDSymbol name="CreateProFileBitmap" value="6" /> <IDSymbol name="QtLogoBitmap" value="7" /> - <IDSymbol name="AddNewQtClassBitmap" value="8" /> </GuidSymbol> </Symbols> diff --git a/QtVsTools.Package/QtMsBuild/QtModulesEditor.cs b/QtVsTools.Package/QtMsBuild/QtModulesEditor.cs index 8fbd145..e05e4ce 100644 --- a/QtVsTools.Package/QtMsBuild/QtModulesEditor.cs +++ b/QtVsTools.Package/QtMsBuild/QtModulesEditor.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -28,15 +28,15 @@ using Microsoft.VisualStudio.ProjectSystem; using Microsoft.VisualStudio.ProjectSystem.Properties; -using Microsoft.Internal.VisualStudio.PlatformUI; using System; +using System.Collections.Generic; using System.ComponentModel.Composition; using System.Linq; using System.Threading.Tasks; namespace QtVsTools.QtMsBuild { - using QtVsTools.Core; + using Core; [Export(typeof(IPropertyPageUIValueEditor))] [ExportMetadata("Name", "QtModulesEditor")] @@ -50,7 +50,15 @@ { await Task.Yield(); - var modules = QtModules.Instance.GetAvailableModules() + var qtSettings = ruleProperty.ContainingRule; + var qtVersion = await qtSettings.GetPropertyValueAsync("QtInstall"); + + var vm = QtVersionManager.The(); + var versionInfo = vm.GetVersionInfo(qtVersion); + if (versionInfo == null) + versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); + + var modules = QtModules.Instance.GetAvailableModules(versionInfo.qtMajor) .Where(x => !string.IsNullOrEmpty(x.proVarQT)) .Select(x => new QtModulesPopup.Module { @@ -61,24 +69,28 @@ }) .ToList(); - var allQT = modules.SelectMany(x => x.QT).ToHashSet(); - var selectedQT = currentValue.ToString().Split(';').ToHashSet(); - var extraQT = selectedQT.Except(allQT); + HashSet<string> selectedQt = null; + IEnumerable<string> extraQt = null; + if (currentValue != null) { + var allQt = modules.SelectMany(x => x.QT).ToHashSet(); + selectedQt = currentValue.ToString().Split(';').ToHashSet(); + extraQt = selectedQt.Except(allQt); - foreach (var module in modules) - module.IsSelected = module.QT.Intersect(selectedQT).Count() == module.QT.Count; + foreach (var module in modules) + module.IsSelected = module.QT.Intersect(selectedQt).Count() == module.QT.Count; + } var popup = new QtModulesPopup(); - popup.SetModules(modules); + popup.SetModules(modules.OrderBy(module => module.Name)); if (popup.ShowModal().GetValueOrDefault()) { - selectedQT = modules + selectedQt = modules .Where(x => x.IsSelected) .SelectMany(x => x.QT) - .Union(extraQT) + .Union(extraQt ?? Enumerable.Empty<string>()) .ToHashSet(); } - return string.Join(";", selectedQT); + return selectedQt == null ? "" : string.Join(";", selectedQt); } } } diff --git a/QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml b/QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml index 54e13a7..fd22f7b 100644 --- a/QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml +++ b/QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml @@ -1,7 +1,7 @@ <!-- ***************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -27,10 +27,10 @@ ** ***************************************************************************** --> -<local:VsToolsDialogWindow x:Class="QtVsTools.QtMsBuild.QtModulesPopup" +<vsui:DialogWindow x:Class="QtVsTools.QtMsBuild.QtModulesPopup" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:local="clr-namespace:QtVsTools" + xmlns:vsui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.15.0" ResizeMode="CanResize" Width="800" MaxHeight="550" MouseDown="Window_MouseDown" @@ -108,4 +108,4 @@ <Button IsCancel="True" MinHeight="23" MinWidth="74">_Cancel</Button> </WrapPanel> </Grid> -</local:VsToolsDialogWindow> +</vsui:DialogWindow> diff --git a/QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml.cs b/QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml.cs index 19d045b..ba20831 100644 --- a/QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml.cs +++ b/QtVsTools.Package/QtMsBuild/QtModulesPopup.xaml.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -30,10 +30,11 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Input; +using Microsoft.VisualStudio.PlatformUI; namespace QtVsTools.QtMsBuild { - public partial class QtModulesPopup : VsToolsDialogWindow + public partial class QtModulesPopup : DialogWindow { public class Module { @@ -81,8 +82,7 @@ private void PopupListBox_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter || e.Key == Key.Space) { - var module = PopupListBox.SelectedItem as Module; - if (module != null && module.IsEnabled) + if (PopupListBox.SelectedItem is Module module && module.IsEnabled) module.CheckBox.IsChecked = (module.CheckBox.IsChecked != true); } } diff --git a/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs b/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs index f2fea0b..44023ee 100644 --- a/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs +++ b/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs @@ -40,36 +40,42 @@ using Microsoft.VisualStudio.TaskStatusCenter; using Microsoft.VisualStudio.Threading; using Microsoft.VisualStudio.VCProjectEngine; -using EnvDTE; + +using Thread = System.Threading.Thread; namespace QtVsTools.QtMsBuild { + using Common; using Core; using VisualStudio; - using Thread = System.Threading.Thread; + using static Common.EnumExt; class QtProjectBuild : Concurrent<QtProjectBuild> { - static PunisherQueue<QtProjectBuild> _BuildQueue; - static PunisherQueue<QtProjectBuild> BuildQueue => - StaticThreadSafeInit(() => _BuildQueue, - () => _BuildQueue = new PunisherQueue<QtProjectBuild>( - getItemKey: (QtProjectBuild build) => - { - return build.ConfiguredProject; - }) - ); + static LazyFactory StaticLazy { get; } = new LazyFactory(); - static ConcurrentStopwatch _RequestTimer; - static ConcurrentStopwatch RequestTimer => - StaticThreadSafeInit(() => _RequestTimer, () => _RequestTimer = new ConcurrentStopwatch()); + public enum Target + { + // Mark project as dirty, but do not request a build + [String("QtVsTools.QtMsBuild.QtProjectBuild.Target.SetOutdated")] SetOutdated + } - static IVsTaskStatusCenterService _StatusCenter; - static IVsTaskStatusCenterService StatusCenter => StaticThreadSafeInit(() => _StatusCenter, - () => _StatusCenter = VsServiceProvider - .GetService<SVsTaskStatusCenterService, IVsTaskStatusCenterService>()); + static PunisherQueue<QtProjectBuild> BuildQueue => StaticLazy.Get(() => + BuildQueue, () => new PunisherQueue<QtProjectBuild>( + getItemKey: (QtProjectBuild build) => + { + return build.ConfiguredProject; + })); + + static ConcurrentStopwatch RequestTimer => StaticLazy.Get(() => + RequestTimer, () => new ConcurrentStopwatch()); + + static IVsTaskStatusCenterService StatusCenter => StaticLazy.Get(() => + StatusCenter, () => VsServiceProvider + .GetService<SVsTaskStatusCenterService, IVsTaskStatusCenterService>()); EnvDTE.Project Project { get; set; } + VCProject VcProject { get; set; } UnconfiguredProject UnconfiguredProject { get; set; } ConfiguredProject ConfiguredProject { get; set; } Dictionary<string, string> Properties { get; set; } @@ -80,6 +86,7 @@ public static void StartBuild( EnvDTE.Project project, + string projectPath, string configName, Dictionary<string, string> properties, IEnumerable<string> targets, @@ -90,11 +97,13 @@ if (configName == null) throw new ArgumentException("Configuration name cannot be null."); - Task.Run(() => StartBuildAsync(project, configName, properties, targets, verbosity)); + _ = Task.Run(() => StartBuildAsync( + project, projectPath, configName, properties, targets, verbosity)); } public static async Task StartBuildAsync( EnvDTE.Project project, + string projectPath, string configName, Dictionary<string, string> properties, IEnumerable<string> targets, @@ -106,15 +115,15 @@ throw new ArgumentException("Configuration name cannot be null."); RequestTimer.Restart(); + var tracker = QtProjectTracker.Get(project, projectPath); + await tracker.Initialized; + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { Messages.Print(string.Format( "{0:HH:mm:ss.FFF} QtProjectBuild({1}): Request [{2}] {3}", DateTime.Now, Thread.CurrentThread.ManagedThreadId, - configName, project.FullName)); + configName, tracker.UnconfiguredProject.FullPath)); } - - var tracker = QtProjectTracker.Get(project); - await tracker.Initialized; var knownConfigs = await tracker.UnconfiguredProject.Services .ProjectConfigurationsService.GetKnownProjectConfigurationsAsync(); @@ -134,6 +143,7 @@ BuildQueue.Enqueue(new QtProjectBuild() { Project = project, + VcProject = tracker.VcProject, UnconfiguredProject = tracker.UnconfiguredProject, ConfiguredProject = configuredProject, Properties = properties?.ToDictionary(x => x.Key, x => x.Value), @@ -143,6 +153,35 @@ StaticThreadSafeInit(() => BuildDispatcher, () => BuildDispatcher = Task.Run(BuildDispatcherLoopAsync)) .Forget(); + } + + public static void SetOutdated( + EnvDTE.Project project, + string projectPath, + string configName, + LoggerVerbosity verbosity = LoggerVerbosity.Quiet) + { + if (project == null) + throw new ArgumentException("Project cannot be null."); + if (configName == null) + throw new ArgumentException("Configuration name cannot be null."); + + _ = Task.Run(() => SetOutdatedAsync(project, projectPath, configName, verbosity)); + } + + public static async Task SetOutdatedAsync( + EnvDTE.Project project, + string projectPath, + string configName, + LoggerVerbosity verbosity = LoggerVerbosity.Quiet) + { + await StartBuildAsync( + project, + projectPath, + configName, + null, + new[] { Target.SetOutdated.Cast<string>() }, + verbosity); } public static void Reset() @@ -161,8 +200,7 @@ } await Task.Delay(100); } - QtProjectBuild buildRequest; - if (BuildQueue.TryDequeue(out buildRequest)) { + if (BuildQueue.TryDequeue(out QtProjectBuild buildRequest)) { if (dispatchStatus == null) { dispatchStatus = StatusCenter.PreRegister( new TaskHandlerOptions @@ -202,6 +240,140 @@ } } + async Task<bool> BuildProjectAsync(ProjectWriteLockReleaser writeAccess) + { + var msBuildProject = await writeAccess.GetProjectAsync(ConfiguredProject); + + if (Targets.Any(t => t == Target.SetOutdated.Cast<string>())) { + msBuildProject.MarkDirty(); + await writeAccess.ReleaseAsync(); + return true; + } + + var solutionPath = QtProjectTracker.SolutionPath; + var configProps = new Dictionary<string, string>( + ConfiguredProject.ProjectConfiguration.Dimensions.ToImmutableDictionary()) + { + { "SolutionPath", solutionPath }, + { "SolutionFileName", Path.GetFileName(solutionPath) }, + { "SolutionName", Path.GetFileNameWithoutExtension(solutionPath) }, + { "SolutionExt", Path.GetExtension(solutionPath) }, + { "SolutionDir", Path.GetDirectoryName(solutionPath).TrimEnd('\\') + '\\' } + }; + + foreach (var property in Properties) + configProps[property.Key] = property.Value; + + var projectInstance = new ProjectInstance(msBuildProject.Xml, + configProps, null, new ProjectCollection()); + + var loggerVerbosity = LoggerVerbosity; + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) + loggerVerbosity = QtVsToolsPackage.Instance.Options.BuildLoggerVerbosity; + var buildParams = new BuildParameters() + { + Loggers = (loggerVerbosity != LoggerVerbosity.Quiet) + ? new[] { new QtProjectLogger() { Verbosity = loggerVerbosity } } + : null + }; + + var buildRequest = new BuildRequestData(projectInstance, + Targets.ToArray(), + hostServices: null, + flags: BuildRequestDataFlags.ProvideProjectStateAfterBuild); + + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { + Messages.Print(string.Format( + "{0:HH:mm:ss.FFF} QtProjectBuild({1}): Build [{2}] {3}", + DateTime.Now, Thread.CurrentThread.ManagedThreadId, + ConfiguredProject.ProjectConfiguration.Name, + UnconfiguredProject.FullPath)); + Messages.Print("=== Targets"); + foreach (var target in buildRequest.TargetNames) + Messages.Print(string.Format(" {0}", target)); + Messages.Print("=== Properties"); + foreach (var property in Properties) { + Messages.Print(string.Format(" {0}={1}", + property.Key, property.Value)); + } + } + + BuildResult result = null; + while (result == null) { + try { + result = BuildManager.DefaultBuildManager.Build( + buildParams, buildRequest); + } catch (InvalidOperationException) { + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { + Messages.Print(string.Format( + "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] " + + "Warning: Another build is in progress; waiting...", + DateTime.Now, + Thread.CurrentThread.ManagedThreadId, + ConfiguredProject.ProjectConfiguration.Name)); + } + await Task.Delay(3000); + } + } + + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { + string resMsg; + StringBuilder resInfo = new StringBuilder(); + if (result?.OverallResult == BuildResultCode.Success) { + resMsg = "Build ok"; + } else { + resMsg = "Build FAIL"; + if (result == null) { + resInfo.AppendLine("####### Build returned 'null'"); + } else { + resInfo.AppendLine("####### Build returned 'Failure' code"); + if (result.ResultsByTarget != null) { + foreach (var tr in result.ResultsByTarget) { + var res = tr.Value; + if (res.ResultCode != TargetResultCode.Failure) + continue; + resInfo.AppendFormat("### Target '{0}' FAIL\r\n", tr.Key); + if (res.Items != null && res.Items.Length > 0) { + resInfo.AppendFormat( + "Items: {0}\r\n", string.Join(", ", res.Items + .Select(it => it.ItemSpec))); + } + var e = tr.Value?.Exception; + if (e != null) { + resInfo.AppendFormat( + "Exception: {0}\r\nStacktrace:\r\n{1}\r\n", + e.Message, e.StackTrace); + } + } + } + } + } + Messages.Print(string.Format( + "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] {3}\r\n{4}", + DateTime.Now, Thread.CurrentThread.ManagedThreadId, + ConfiguredProject.ProjectConfiguration.Name, + resMsg, resInfo.ToString())); + } + + bool ok = false; + if (result == null + || result.ResultsByTarget == null + || result.OverallResult != BuildResultCode.Success) { + Messages.Print(string.Format("{0}: background build FAILED!", + Path.GetFileName(UnconfiguredProject.FullPath))); + } else { + var checkResults = result.ResultsByTarget + .Where(x => Targets.Contains(x.Key)) + .Select(x => x.Value); + ok = checkResults.Any() + && checkResults.All(x => x.ResultCode == TargetResultCode.Success); + if (ok) + msBuildProject.MarkDirty(); + } + await writeAccess.ReleaseAsync(); + return ok; + } + async Task BuildAsync() { if (LoggerVerbosity != LoggerVerbosity.Quiet) { @@ -211,7 +383,7 @@ * Properties: {1} * Targets: {2} ", - /*{0}*/ Project.Name, + /*{0}*/ Path.GetFileNameWithoutExtension(UnconfiguredProject.FullPath), /*{1}*/ string.Join("", Properties .Select(property => string.Format(@" {0} = {1}", /*{0}*/ property.Key, /*{1}*/ property.Value))), @@ -222,151 +394,41 @@ bool ok = false; try { - ProjectWriteLockReleaser writeAccess; var timer = ConcurrentStopwatch.StartNew(); while (timer.IsRunning) { try { - writeAccess = await lockService.WriteLockAsync(); +#if VS2017 + using (var writeAccess = await lockService.WriteLockAsync()) + ok = await BuildProjectAsync(writeAccess); +#else + await lockService.WriteLockAsync( + async (ProjectWriteLockReleaser writeAccess) => + { + ok = await BuildProjectAsync(writeAccess); + }); +#endif timer.Stop(); } catch (InvalidOperationException) { if (timer.ElapsedMilliseconds >= 5000) throw; +#if VS2017 using (var readAccess = await lockService.ReadLockAsync()) await readAccess.ReleaseAsync(); +#else + await lockService.ReadLockAsync( + async (ProjectLockReleaser readAccess) => + { + await readAccess.ReleaseAsync(); + }); +#endif } - } - - using (writeAccess) { - var msBuildProject = await writeAccess.GetProjectAsync(ConfiguredProject); - - var solutionPath = QtProjectTracker.SolutionPath; - var configProps = new Dictionary<string, string>( - ConfiguredProject.ProjectConfiguration.Dimensions.ToImmutableDictionary()) - { - { "SolutionPath", solutionPath }, - { "SolutionFileName", Path.GetFileName(solutionPath) }, - { "SolutionName", Path.GetFileNameWithoutExtension(solutionPath) }, - { "SolutionExt", Path.GetExtension(solutionPath) }, - { "SolutionDir", Path.GetDirectoryName(solutionPath).TrimEnd('\\') + '\\' } - }; - - foreach (var property in Properties) - configProps[property.Key] = property.Value; - - var projectInstance = new ProjectInstance(msBuildProject.Xml, - configProps, null, new ProjectCollection()); - - var loggerVerbosity = LoggerVerbosity; - if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) - loggerVerbosity = QtVsToolsPackage.Instance.Options.BuildLoggerVerbosity; - var buildParams = new BuildParameters() - { - Loggers = (loggerVerbosity != LoggerVerbosity.Quiet) - ? new[] { new QtProjectLogger() { Verbosity = loggerVerbosity } } - : null - }; - - var buildRequest = new BuildRequestData(projectInstance, - Targets.ToArray(), - hostServices: null, - flags: BuildRequestDataFlags.ProvideProjectStateAfterBuild); - - if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { - Messages.Print(string.Format( - "{0:HH:mm:ss.FFF} QtProjectBuild({1}): Build [{2}] {3}", - DateTime.Now, Thread.CurrentThread.ManagedThreadId, - ConfiguredProject.ProjectConfiguration.Name, - UnconfiguredProject.FullPath)); - Messages.Print("=== Targets"); - foreach (var target in buildRequest.TargetNames) - Messages.Print(string.Format(" {0}", target)); - Messages.Print("=== Properties"); - foreach (var property in Properties) { - Messages.Print(string.Format(" {0}={1}", - property.Key, property.Value)); - } - } - - BuildResult result = null; - while (result == null) { - try { - result = BuildManager.DefaultBuildManager.Build( - buildParams, buildRequest); - } catch (InvalidOperationException) { - if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { - Messages.Print(string.Format( - "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] " - + "Warning: Another build is in progress; waiting...", - DateTime.Now, - Thread.CurrentThread.ManagedThreadId, - ConfiguredProject.ProjectConfiguration.Name)); - } - await Task.Delay(3000); - } - } - - if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { - string resMsg; - StringBuilder resInfo = new StringBuilder(); - if (result?.OverallResult == BuildResultCode.Success) { - resMsg = "Build ok"; - } else { - resMsg = "Build FAIL"; - if (result == null) { - resInfo.AppendLine("####### Build returned 'null'"); - } else { - resInfo.AppendLine("####### Build returned 'Failure' code"); - if (result.ResultsByTarget != null) { - foreach (var tr in result.ResultsByTarget) { - var res = tr.Value; - if (res.ResultCode != TargetResultCode.Failure) - continue; - resInfo.AppendFormat("### Target '{0}' FAIL\r\n", tr.Key); - if (res.Items != null && res.Items.Length > 0) { - resInfo.AppendFormat( - "Items: {0}\r\n", string.Join(", ", res.Items - .Select(it => it.ItemSpec))); - } - var e = tr.Value?.Exception; - if (e != null) { - resInfo.AppendFormat( - "Exception: {0}\r\nStacktrace:\r\n{1}\r\n", - e.Message, e.StackTrace); - } - } - } - } - } - Messages.Print(string.Format( - "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] {3}\r\n{4}", - DateTime.Now, Thread.CurrentThread.ManagedThreadId, - ConfiguredProject.ProjectConfiguration.Name, - resMsg, resInfo.ToString())); - } - - if (result == null - || result.ResultsByTarget == null - || result.OverallResult != BuildResultCode.Success) { - Messages.Print(string.Format("{0}: background build FAILED!", - Path.GetFileName(UnconfiguredProject.FullPath))); - } else { - var checkResults = result.ResultsByTarget - .Where(x => Targets.Contains(x.Key)) - .Select(x => x.Value); - ok = checkResults.Any() - && checkResults.All(x => x.ResultCode == TargetResultCode.Success); - if (ok) - msBuildProject.MarkDirty(); - } - await writeAccess.ReleaseAsync(); } if (ok) { - var vcProject = Project.Object as VCProject; - var vcConfigs = vcProject.Configurations as IVCCollection; + var vcConfigs = VcProject.Configurations as IVCCollection; var vcConfig = vcConfigs.Item(ConfiguredProject.ProjectConfiguration.Name) as VCConfiguration; var props = vcConfig.Rules.Item("QtRule10_Settings") as IVCRulePropertyStorage; - props.SetPropertyValue("QtLastBackgroundBuild", DateTime.UtcNow.ToString("o")); + props?.SetPropertyValue("QtLastBackgroundBuild", DateTime.UtcNow.ToString("o")); } } catch (Exception e) { Messages.Print(string.Format("{0}: background build ERROR: {1}", @@ -377,7 +439,8 @@ Messages.Print(string.Format( @" == {0}: build {1}", - Project.Name, ok ? "successful" : "ERROR")); + Path.GetFileNameWithoutExtension(UnconfiguredProject.FullPath), + ok ? "successful" : "ERROR")); } } } diff --git a/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs b/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs index 605763f..46ff9d4 100644 --- a/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs +++ b/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs @@ -31,12 +31,15 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.Build.Framework; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Threading; + +using Task = System.Threading.Tasks.Task; +using Thread = System.Threading.Thread; namespace QtVsTools.QtMsBuild { using Core; - using Thread = System.Threading.Thread; static class QtProjectIntellisense { @@ -45,25 +48,31 @@ string configId = null, IEnumerable<string> selectedFiles = null) { - if (project == null || !QtProjectTracker.IsTracked(project)) + ThreadHelper.ThrowIfNotOnUIThread(); + + if (project == null || !QtProjectTracker.IsTracked(project.FullName)) return; + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { Messages.Print(string.Format( "{0:HH:mm:ss.FFF} QtProjectIntellisense({1}): Refreshing: [{2}] {3}", DateTime.Now, Thread.CurrentThread.ManagedThreadId, (configId != null) ? configId : "(all configs)", project.FullName)); } - Task.Run(() => RefreshAsync(project, configId, selectedFiles)); + string projectPath = project.FullName; + _ = Task.Run(() => RefreshAsync(project, projectPath, configId, selectedFiles, false)); } public static async Task RefreshAsync( EnvDTE.Project project, + string projectPath, string configId = null, - IEnumerable<string> selectedFiles = null) + IEnumerable<string> selectedFiles = null, + bool refreshQtVars = false) { - if (project == null || !QtProjectTracker.IsTracked(project)) + if (project == null || !QtProjectTracker.IsTracked(projectPath)) return; - var tracker = QtProjectTracker.Get(project); + var tracker = QtProjectTracker.Get(project, projectPath); await tracker.Initialized; var properties = new Dictionary<string, string>(); @@ -84,9 +93,14 @@ } foreach (var config in configs) { - await QtProjectBuild.StartBuildAsync( - project, config, properties, targets, - LoggerVerbosity.Quiet); + if (refreshQtVars) { + await QtProjectBuild.StartBuildAsync( + project, projectPath, config, properties, targets, + LoggerVerbosity.Quiet); + } else { + await QtProjectBuild.SetOutdatedAsync( + project, projectPath, config, LoggerVerbosity.Quiet); + } } } } diff --git a/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs b/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs index 66db5c7..1d8e719 100644 --- a/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs +++ b/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs @@ -29,41 +29,41 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; -using Microsoft.Build.Evaluation; -using Microsoft.Build.Framework; using Microsoft.VisualStudio.ProjectSystem; using Microsoft.VisualStudio.ProjectSystem.Properties; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.TaskStatusCenter; using Microsoft.VisualStudio.Threading; -using EnvDTE; +using Microsoft.VisualStudio.VCProjectEngine; + +using Task = System.Threading.Tasks.Task; namespace QtVsTools.QtMsBuild { + using Common; using Core; using VisualStudio; - using Thread = System.Threading.Thread; + using SubscriberAction = ActionBlock<IProjectVersionedValue<IProjectSubscriptionUpdate>>; class QtProjectTracker : Concurrent<QtProjectTracker> { - static ConcurrentDictionary<string, QtProjectTracker> _Instances; - static ConcurrentDictionary<string, QtProjectTracker> Instances => - StaticThreadSafeInit(() => _Instances, () => - _Instances = new ConcurrentDictionary<string, QtProjectTracker>()); + static LazyFactory StaticLazy { get; } = new LazyFactory(); - static PunisherQueue<QtProjectTracker> _InitQueue; - static PunisherQueue<QtProjectTracker> InitQueue => - StaticThreadSafeInit(() => _InitQueue, () => - _InitQueue = new PunisherQueue<QtProjectTracker>()); + static ConcurrentDictionary<string, QtProjectTracker> Instances => StaticLazy.Get(() => + Instances, () => new ConcurrentDictionary<string, QtProjectTracker>()); - static IVsTaskStatusCenterService _StatusCenter; - static IVsTaskStatusCenterService StatusCenter => StaticThreadSafeInit(() => _StatusCenter, - () => _StatusCenter = VsServiceProvider - .GetService<SVsTaskStatusCenterService, IVsTaskStatusCenterService>()); + static PunisherQueue<QtProjectTracker> InitQueue => StaticLazy.Get(() => + InitQueue, () => new PunisherQueue<QtProjectTracker>()); + + static IVsTaskStatusCenterService StatusCenter => StaticLazy.Get(() => + StatusCenter, () => VsServiceProvider + .GetService<SVsTaskStatusCenterService, IVsTaskStatusCenterService>()); static Task InitDispatcher { get; set; } static ITaskHandler2 InitStatus { get; set; } @@ -75,73 +75,37 @@ Initialized = new EventWaitHandle(false, EventResetMode.ManualReset); } - class Subscriber : IDisposable - { - public Subscriber(QtProjectTracker tracker, ConfiguredProject config) - { - Tracker = tracker; - Config = config; - Subscription = Config.Services.ProjectSubscription.JointRuleSource.SourceBlock - .LinkTo(new SubscriberAction(ProjectUpdateAsync), - ruleNames: new[] - { - "ClCompile", - "QtRule10_Settings", - "QtRule30_Moc", - "QtRule40_Rcc", - "QtRule60_Repc", - "QtRule50_Uic", - "QtRule_Translation", - "QtRule70_Deploy", - }, - initialDataAsNew: false - ); - } - - QtProjectTracker Tracker { get; set; } - ConfiguredProject Config { get; set; } - IDisposable Subscription { get; set; } - - public void Dispose() - { - Subscription?.Dispose(); - Subscription = null; - } - - async Task ProjectUpdateAsync(IProjectVersionedValue<IProjectSubscriptionUpdate> update) - { - await Tracker.OnProjectUpdateAsync(Config, update.Value); - } - } - public EnvDTE.Project Project { get; private set; } + public string ProjectPath { get; private set; } + public VCProject VcProject { get; private set; } public UnconfiguredProject UnconfiguredProject { get; private set; } - public EventWaitHandle Initialized { get; private set; } - List<Subscriber> Subscribers { get; set; } + public EventWaitHandle Initialized { get; } - public static bool IsTracked(EnvDTE.Project project) + public static bool IsTracked(string projectPath) { - return Instances.ContainsKey(project.FullName); + return Instances.ContainsKey(projectPath); } public static void Add(EnvDTE.Project project) { if (!QtVsToolsPackage.Instance.Options.ProjectTracking) return; - Get(project); + + ThreadHelper.ThrowIfNotOnUIThread(); + Get(project, project.FullName); } - public static QtProjectTracker Get(EnvDTE.Project project) + public static QtProjectTracker Get(EnvDTE.Project project, string projectPath) { lock (StaticCriticalSection) { - QtProjectTracker tracker = null; - if (Instances.TryGetValue(project.FullName, out tracker)) + if (Instances.TryGetValue(projectPath, out QtProjectTracker tracker)) return tracker; tracker = new QtProjectTracker { Project = project, + ProjectPath = projectPath }; - Instances[project.FullName] = tracker; + Instances[projectPath] = tracker; InitQueue.Enqueue(tracker); if (InitDispatcher == null) InitDispatcher = Task.Run(InitDispatcherLoopAsync); @@ -162,14 +126,17 @@ while (!QtVsToolsPackage.Instance.Zombied) { while (InitQueue.IsEmpty) await Task.Delay(100); - QtProjectTracker tracker; - if (InitQueue.TryDequeue(out tracker)) { + if (InitQueue.TryDequeue(out QtProjectTracker tracker)) { if (InitStatus == null) { - await QtVsToolsPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync(); + await QtVsToolsPackage.Instance.JoinableTaskFactory + .SwitchToMainThreadAsync(); tracker.BeginInitStatus(); await TaskScheduler.Default; } else { + await QtVsToolsPackage.Instance.JoinableTaskFactory + .SwitchToMainThreadAsync(); tracker.UpdateInitStatus(0); + await TaskScheduler.Default; } await tracker.InitializeAsync(); } @@ -187,9 +154,12 @@ async Task InitializeAsync() { int p = 0; + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); UpdateInitStatus(p += 10); - await QtVsToolsPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync(); + VcProject = Project.Object as VCProject; + if (VcProject == null) + return; UpdateInitStatus(p += 10); var context = Project.Object as IVsBrowseObjectContext; @@ -211,57 +181,23 @@ Initialized.Set(); - Subscribers = new List<Subscriber>(); int n = configs.Count; int d = (100 - p) / (n * 2); foreach (var config in configs) { var configProject = await UnconfiguredProject.LoadConfiguredProjectAsync(config); UpdateInitStatus(p += d); - Subscribers.Add(new Subscriber(this, configProject)); - configProject.ProjectUnloading += OnProjectUnloading; + configProject.ProjectUnloading += OnProjectUnloadingAsync; if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { Messages.Print(string.Format( "{0:HH:mm:ss.FFF} QtProjectTracker({1}): Started tracking [{2}] {3}", DateTime.Now, Thread.CurrentThread.ManagedThreadId, - config.Name, - UnconfiguredProject.FullPath)); + config.Name, ProjectPath)); } UpdateInitStatus(p += d); } } - - async Task OnProjectUpdateAsync(ConfiguredProject config, IProjectSubscriptionUpdate update) - { - var changes = update.ProjectChanges.Values - .Where(x => x.Difference.AnyChanges) - .Select(x => x.Difference); - var changesCount = changes - .Select(x => x.AddedItems.Count - + x.ChangedItems.Count - + x.ChangedProperties.Count - + x.RemovedItems.Count - + x.RenamedItems.Count) - .Sum(); - var changedProps = changes.SelectMany(x => x.ChangedProperties); - if (changesCount == 0 - || (changesCount == 1 - && changedProps.Count() == 1 - && changedProps.First() == "QtLastBackgroundBuild")) { - return; - } - - if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { - Messages.Print(string.Format( - "{0:HH:mm:ss.FFF} QtProjectTracker({1}): Changed [{2}] {3}", - DateTime.Now, Thread.CurrentThread.ManagedThreadId, - config.ProjectConfiguration.Name, - config.UnconfiguredProject.FullPath)); - } - await QtProjectIntellisense.RefreshAsync(Project, config.ProjectConfiguration.Name); - } - - async Task OnProjectUnloading(object sender, EventArgs args) + async Task OnProjectUnloadingAsync(object sender, EventArgs args) { var project = sender as ConfiguredProject; if (project == null || project.Services == null) @@ -274,18 +210,16 @@ project.UnconfiguredProject.FullPath)); } lock (CriticalSection) { - if (Subscribers != null) { - Subscribers.ForEach(s => s.Dispose()); - Subscribers.Clear(); - Subscribers = null; - } - project.ProjectUnloading -= OnProjectUnloading; - Instances.TryRemove(Project.FullName, out QtProjectTracker tracker); + project.ProjectUnloading -= OnProjectUnloadingAsync; + Instances.TryRemove(project.UnconfiguredProject.FullPath, out QtProjectTracker _); } + await Task.Yield(); } void BeginInitStatus() { + ThreadHelper.ThrowIfNotOnUIThread(); + lock (StaticCriticalSection) { if (InitStatus != null) return; @@ -303,9 +237,8 @@ PercentComplete = 0 }) as ITaskHandler2; - } catch (Exception e) { - Messages.Print( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); } InitStatus.RegisterTask(new Task(() => throw new InvalidOperationException())); } @@ -320,13 +253,12 @@ InitStatus.Progress.Report(new TaskProgressData { ProgressText = string.Format("{0} ({1} project(s) remaining)", - Project.Name, InitQueue.Count), + Path.GetFileNameWithoutExtension(ProjectPath), InitQueue.Count), CanBeCanceled = true, PercentComplete = percentComplete }); - } catch (Exception e) { - Messages.Print( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); } } } diff --git a/QtVsTools.Package/QtMsBuild/QtVersionProvider.cs b/QtVsTools.Package/QtMsBuild/QtVersionProvider.cs index f9626ca..4fd6db9 100644 --- a/QtVsTools.Package/QtMsBuild/QtVersionProvider.cs +++ b/QtVsTools.Package/QtMsBuild/QtVersionProvider.cs @@ -57,7 +57,6 @@ public async Task<ICollection<IEnumValue>> GetListedValuesAsync() { - List<IEnumValue> values = new List<IEnumValue>(); using (var qtVersions = Registry.CurrentUser.OpenSubKey(@"Software\Digia\Versions")) { return await Task.FromResult( diff --git a/QtVsTools.Package/QtVsTools.Icons.pkgdef b/QtVsTools.Package/QtVsTools.Icons.pkgdef new file mode 100644 index 0000000..5bc4660 --- /dev/null +++ b/QtVsTools.Package/QtVsTools.Icons.pkgdef @@ -0,0 +1,20 @@ +[$RootKey$\ShellFileAssociations\.prf] +"DefaultIconMoniker"="0d2e443f-6dbb-4001-99dc-9cd7d5c924e7:0" + +[$RootKey$\ShellFileAssociations\.pri] +"DefaultIconMoniker"="0d2e443f-6dbb-4001-99dc-9cd7d5c924e7:1" + +[$RootKey$\ShellFileAssociations\.pro] +"DefaultIconMoniker"="0d2e443f-6dbb-4001-99dc-9cd7d5c924e7:2" + +[$RootKey$\ShellFileAssociations\.qml] +"DefaultIconMoniker"="0d2e443f-6dbb-4001-99dc-9cd7d5c924e7:3" + +[$RootKey$\ShellFileAssociations\.qrc] +"DefaultIconMoniker"="0d2e443f-6dbb-4001-99dc-9cd7d5c924e7:4" + +[$RootKey$\ShellFileAssociations\.ts] +"DefaultIconMoniker"="0d2e443f-6dbb-4001-99dc-9cd7d5c924e7:5" + +[$RootKey$\ShellFileAssociations\.ui] +"DefaultIconMoniker"="0d2e443f-6dbb-4001-99dc-9cd7d5c924e7:6" diff --git a/QtVsTools.Package/QtVsTools.Package.csproj b/QtVsTools.Package/QtVsTools.Package.csproj index 270b6c9..e57b845 100644 --- a/QtVsTools.Package/QtVsTools.Package.csproj +++ b/QtVsTools.Package/QtVsTools.Package.csproj @@ -90,59 +90,45 @@ <Reference Include="System.Data" /> <Reference Include="System.Design" /> <Reference Include="System.Drawing" /> + <Reference Include="System.ComponentModel.Composition" /> + <Reference Include="System.Xaml" /> <Reference Include="PresentationCore" /> <Reference Include="PresentationFramework" /> <Reference Include="WindowsBase" /> - <Reference Include="Microsoft.VisualStudio.ProjectSystem"> - <HintPath>$(VsInstallRoot)\Common7\IDE\CommonExtensions\Microsoft\Project\Microsoft.VisualStudio.ProjectSystem.dll</HintPath> - </Reference> - <Reference Include="Microsoft.VisualStudio.Composition"> - <HintPath>$(VsInstallRoot)\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.Composition.dll</HintPath> - </Reference> </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - // Version specific references + // General package references // --> <Import Project="$(SolutionDir)\references.props" /> <ItemGroup> - <PackageReference Include="System.ComponentModel.Composition" - Version="$(Version_System_ComponentModel_Composition)" /> - <PackageReference Include="Stub.System.Data.SQLite.Core.NetFramework" - Version="$(Version_Stub_System_Data_SQLite_Core_NetFramework)" - GeneratePathProperty="true" /> - <PackageReference Include="Newtonsoft.Json" - Version="$(Version_Newtonsoft_Json)" /> - <PackageReference Include="Microsoft.Build" - Version="$(Version_Microsoft_Build)" /> - <PackageReference Include="Microsoft.Build.Framework" - Version="$(Version_Microsoft_Build_Framework)" /> - <PackageReference Include="Microsoft.Build.Tasks.Core" - Version="$(Version_Microsoft_Build_Tasks_Core)" /> - <PackageReference Include="Microsoft.VisualStudio.SDK" - Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> - <PackageReference Include="Microsoft.VSSDK.BuildTools" - Version="$(Version_Microsoft_VSSDK_BuildTools)" /> - <PackageReference Include="Microsoft.VisualStudio.Shell.Framework" - Version="$(Version_Microsoft_VisualStudio_Shell_Framework)" /> - <PackageReference Include="Microsoft.VisualStudio.Validation" - Version="$(Version_Microsoft_VisualStudio_Validation)" /> - <PackageReference Include="$(Name_Microsoft_VisualStudio_Threading)" - Version="$(Version_Microsoft_VisualStudio_Threading)" /> - <PackageReference Include="System.Collections.Immutable" - Version="$(Version_System_Collections_Immutable)" /> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_ProjectSystem)" Version="$(Version_Microsoft_VisualStudio_ProjectSystem)" /> + <PackageReference Include="$(Name_Newtonsoft_Json)" Version="$(Version_Newtonsoft_Json)" /> + <PackageReference Include="$(Name_Stub_System_Data_SQLite_Core_NetFramework)" Version="$(Version_Stub_System_Data_SQLite_Core_NetFramework)" GeneratePathProperty="true" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Shell_15)" Version="$(Version_Microsoft_VisualStudio_Shell_15)" /> </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='17.0'"> - <PackageReference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" - Version="$(Version_Microsoft_VisualStudio_VCProjectEngine)" /> - </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='16.0'"> - <PackageReference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" - Version="$(Version_Microsoft_VisualStudio_VCProjectEngine)" /> - </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='15.0'"> - <Reference Include="Microsoft.VisualStudio.VCProjectEngine" /> - </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + <Reference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Shell_Framework)" Version="$(Version_Microsoft_VisualStudio_Shell_Framework)" /> + </ItemGroup> + </When> + </Choose> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// // Solution project references @@ -173,6 +159,27 @@ <Project>{4cee73c9-fcfa-3a72-a0a3-036bdbb3240f}</Project> <Name>qrceditor</Name> <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> + <ProjectReference Include="..\Templates\qtclass\QtTemplate.Item.QtClass.csproj"> + <Project>{4981AAE8-9AC7-4758-87EA-FB2397D6C404}</Project> + <Name>QtTemplate.Item.QtClass</Name> + <VSIXSubPath>ItemTemplates</VSIXSubPath> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + <IncludeOutputGroupsInVSIX>TemplateProjectOutputGroup%3b</IncludeOutputGroupsInVSIX> + </ProjectReference> + <ProjectReference Include="..\Templates\translation\QtTemplate.Item.Translation.csproj"> + <Project>{202F4A6D-77CD-4992-AA53-01B585463287}</Project> + <Name>QtTemplate.Item.Translation</Name> + <VSIXSubPath>ItemTemplates</VSIXSubPath> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + <IncludeOutputGroupsInVSIX>TemplateProjectOutputGroup%3b</IncludeOutputGroupsInVSIX> + </ProjectReference> + <ProjectReference Include="..\Templates\widgetsclass\QtTemplate.Item.WidgetsClass.csproj"> + <Project>{020422DA-33AB-4495-A439-7DAC2690795C}</Project> + <Name>QtTemplate.Item.WidgetsClass</Name> + <VSIXSubPath>ItemTemplates</VSIXSubPath> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + <IncludeOutputGroupsInVSIX>TemplateProjectOutputGroup%3b</IncludeOutputGroupsInVSIX> </ProjectReference> <ProjectReference Include="..\vsqml\vsqml.vcxproj"> <Project>{b12702ad-abfb-343a-a199-8e24837244a3}</Project> @@ -303,6 +310,12 @@ <DependsOn>$(SolutionDir)\version.targets;$(SolutionDir)\version.tt;$(SolutionDir)\common.tt</DependsOn> <LastGenOutput>AssemblyInfo.tt.cs</LastGenOutput> </T4Template> + <Compile Include="Legacy\ProjectQtSettings.cs" /> + <Compile Include="Legacy\QtMenu.cs" /> + <Compile Include="Legacy\QtOptionsPage.cs"> + <SubType>Component</SubType> + </Compile> + <Compile Include="Legacy\Translation.cs" /> <Compile Include="Properties\AssemblyInfo.tt.cs"> <AutoGen>True</AutoGen> <DesignTime>True</DesignTime> @@ -321,15 +334,11 @@ <DesignTime>True</DesignTime> <DependentUpon>QtMenus.vsct_TT</DependentUpon> </VSCTCompile> - <Content Include="Resources\Vsix.ico" /> <EmbeddedResource Include="VSPackage.resx"> <MergeWithCTO>true</MergeWithCTO> <ManifestResourceName>VSPackage</ManifestResourceName> </EmbeddedResource> - <Compile Include="Package\AddTranslationDialog.cs"> - <SubType>Form</SubType> - </Compile> - <Compile Include="Package\ChangeFor.cs" /> + <Compile Include="Legacy\ChangeFor.cs" /> <Compile Include="Common\Concurrent.cs" /> <Compile Include="Common\ConcurrentStopwatch.cs" /> <Compile Include="Common\Disposable.cs" /> @@ -348,20 +357,17 @@ <Compile Include="Editors\Editor.QtLinguist.cs" /> <Compile Include="Editors\Editor.QtResourceEditor.cs" /> <Compile Include="Package\ExtLoader.cs" /> - <Compile Include="Package\FormChangeQtVersion.cs"> + <Compile Include="Legacy\FormChangeQtVersion.cs"> <SubType>Form</SubType> </Compile> - <Compile Include="Package\FormChangeQtVersion.Designer.cs"> + <Compile Include="Legacy\FormChangeQtVersion.Designer.cs"> <DependentUpon>FormChangeQtVersion.cs</DependentUpon> </Compile> - <Compile Include="Package\FormProjectQtSettings.cs"> + <Compile Include="Legacy\FormProjectQtSettings.cs"> <SubType>Form</SubType> </Compile> - <Compile Include="Package\FormProjectQtSettings.Designer.cs"> + <Compile Include="Legacy\FormProjectQtSettings.Designer.cs"> <DependentUpon>FormProjectQtSettings.cs</DependentUpon> - </Compile> - <Compile Include="Options\QtLegacyOptionsPage.cs"> - <SubType>Component</SubType> </Compile> <Compile Include="Options\QtOptionsPage.cs"> <SubType>Component</SubType> @@ -372,7 +378,6 @@ <Compile Include="Options\QtVersionsPage.cs"> <SubType>Component</SubType> </Compile> - <Compile Include="Package\ProjectQtSettings.cs" /> <Compile Include="Package\QMakeWrapper.cs" /> <Compile Include="QML\Classification\QmlAsyncClassifier.cs" /> <Compile Include="QML\Classification\QmlClassificationFormat.cs" /> @@ -437,9 +442,7 @@ <Compile Include="Package\QtSolutionContextMenu.cs" /> <Compile Include="Package\SR.cs" /> <Compile Include="Package\Translation.cs" /> - <Compile Include="Package\TranslationItem.cs" /> - <Compile Include="VisualStudio\VsShell.cs" /> - <Compile Include="Common\VsToolsDialogWindow.cs" /> + <Compile Include="Package\Notifications.cs" /> <Content Include="..\Changelog"> <Link>Changelog</Link> <CopyToOutputDirectory>Always</CopyToOutputDirectory> @@ -456,6 +459,9 @@ <DependsOn>$(SolutionDir)\version.targets;$(SolutionDir)\version.tt;$(SolutionDir)\common.tt</DependsOn> <LastGenOutput>source.extension.vsixmanifest</LastGenOutput> </T4Template> + <Content Include="Icons\Monikers.imagemanifest"> + <IncludeInVSIX>true</IncludeInVSIX> + </Content> <None Include="source.extension.vsixmanifest"> <DependentUpon>source.extension.vsixmanifest_TT</DependentUpon> <SubType>Designer</SubType> @@ -473,6 +479,16 @@ <DependsOn>$(SolutionDir)\version.targets;$(SolutionDir)\version.tt;$(SolutionDir)\common.tt</DependsOn> <LastGenOutput>Overview.html</LastGenOutput> </T4Template> + <Content Include="QtVsTools.Icons.pkgdef"> + <IncludeInVSIX>true</IncludeInVSIX> + </Content> + <Resource Include="Icons\prf32.png" /> + <Resource Include="Icons\pri32.png" /> + <Resource Include="Icons\pro32.png" /> + <Resource Include="Icons\qml32.png" /> + <Resource Include="Icons\qrc32.png" /> + <Resource Include="Icons\ts32.png" /> + <Resource Include="Icons\ui32.png" /> <Content Include="Marketplace\Overview.html"> <AutoGen>True</AutoGen> <DesignTime>True</DesignTime> @@ -499,6 +515,10 @@ <IncludeInVSIX>true</IncludeInVSIX> <SubType>Designer</SubType> </Content> + <Content Include="qt6modules.xml"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + <IncludeInVSIX>true</IncludeInVSIX> + </Content> <Content Include="QtVsTools.ico" /> <Content Include="QtVsTools.Qml.Debug.pkgdef"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> @@ -509,14 +529,12 @@ <CopyToOutputDirectory>Always</CopyToOutputDirectory> <IncludeInVSIX>true</IncludeInVSIX> </Content> - <EmbeddedResource Include="Package\AddTranslationDialog.resx"> - <DependentUpon>AddTranslationDialog.cs</DependentUpon> - </EmbeddedResource> - <EmbeddedResource Include="Package\FormChangeQtVersion.resx"> + <EmbeddedResource Include="Legacy\FormChangeQtVersion.resx"> <DependentUpon>FormChangeQtVersion.cs</DependentUpon> </EmbeddedResource> - <EmbeddedResource Include="Package\FormProjectQtSettings.resx"> + <EmbeddedResource Include="Legacy\FormProjectQtSettings.resx"> <DependentUpon>FormProjectQtSettings.cs</DependentUpon> + <SubType>Designer</SubType> </EmbeddedResource> <EmbeddedResource Include="Resources.resx"> <SubType>Designer</SubType> @@ -546,8 +564,8 @@ </Page> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(SolutionDir)\transform.targets" /> + <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> <Target Name="QtVsTools_PostBuild" AfterTargets="Build"> <Error Condition="!Exists('$(TargetPath)')" Text="Build failed." /> <PropertyGroup> @@ -602,19 +620,13 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// // NuGet native libs // --> - <PropertyGroup - Condition="'$(PkgStub_System_Data_SQLite_Core_NetFramework)' != ''"> - <SQLitePkgDir Condition="'$(SQLitePkgDir)' == ''" - >$(PkgStub_System_Data_SQLite_Core_NetFramework)</SQLitePkgDir> + <PropertyGroup Condition="'$(PkgStub_System_Data_SQLite_Core_NetFramework)' != ''"> + <SQLitePkgDir Condition="'$(SQLitePkgDir)' == ''">$(PkgStub_System_Data_SQLite_Core_NetFramework)</SQLitePkgDir> </PropertyGroup> - <PropertyGroup - Condition="'$(PkgStub_System_Data_SQLite_Core_NetFramework)' == ''"> - <NuGetGlobalPkgDir Condition="'$(NuGetGlobalPkgDir)' == ''" - >$(USERPROFILE)\.nuget\packages</NuGetGlobalPkgDir> - <SQLitePkgRoot - >$(NuGetGlobalPkgDir)\Stub.System.Data.SQLite.Core.NetFramework</SQLitePkgRoot> - <SQLitePkgDir Condition="'$(SQLitePkgDir)' == ''" - >$(SQLitePkgRoot)\$(Version_Stub_System_Data_SQLite_Core_NetFramework)</SQLitePkgDir> + <PropertyGroup Condition="'$(PkgStub_System_Data_SQLite_Core_NetFramework)' == ''"> + <NuGetGlobalPkgDir Condition="'$(NuGetGlobalPkgDir)' == ''">$(USERPROFILE)\.nuget\packages</NuGetGlobalPkgDir> + <SQLitePkgRoot>$(NuGetGlobalPkgDir)\Stub.System.Data.SQLite.Core.NetFramework</SQLitePkgRoot> + <SQLitePkgDir Condition="'$(SQLitePkgDir)' == ''">$(SQLitePkgRoot)\$(Version_Stub_System_Data_SQLite_Core_NetFramework)</SQLitePkgDir> </PropertyGroup> <ItemGroup> <Content Include="$(SQLitePkgDir)\build\net46\x64\SQLite.Interop.dll"> diff --git a/QtVsTools.Package/QtVsToolsPackage.cs b/QtVsTools.Package/QtVsToolsPackage.cs index aad01be..93325f3 100644 --- a/QtVsTools.Package/QtVsToolsPackage.cs +++ b/QtVsTools.Package/QtVsToolsPackage.cs @@ -27,20 +27,14 @@ ****************************************************************************/ using System; -using System.ComponentModel.Design; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using Task = System.Threading.Tasks.Task; -using System.Windows.Forms; using Microsoft.VisualStudio; -using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Settings; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; @@ -49,13 +43,15 @@ using Microsoft.Win32; using EnvDTE; +using Task = System.Threading.Tasks.Task; + namespace QtVsTools { using Core; using QtMsBuild; - using SyntaxAnalysis; - using static SyntaxAnalysis.RegExpr; using VisualStudio; + + using static SyntaxAnalysis.RegExpr; [Guid(QtVsToolsPackage.PackageGuidString)] [InstalledProductRegistration("#110", "#112", Version.PRODUCT_VERSION, IconResourceID = 400)] @@ -97,7 +93,7 @@ "Qt", "Versions", 0, 0, true, Sort = 1)] // Legacy options page - [ProvideOptionPage(typeof(Options.QtLegacyOptionsPage), + [ProvideOptionPage(typeof(Legacy.QtOptionsPage), "Qt", "Legacy Project Format", 0, 0, true, Sort = 2)] public sealed class QtVsToolsPackage : AsyncPackage, IVsServiceProvider, IProjectTracker @@ -109,13 +105,13 @@ public string PkgInstallPath { get; private set; } public Options.QtOptionsPage Options => GetDialogPage(typeof(Options.QtOptionsPage)) as Options.QtOptionsPage; - public Options.QtLegacyOptionsPage LegacyOptions - => GetDialogPage(typeof(Options.QtLegacyOptionsPage)) as Options.QtLegacyOptionsPage; + public Legacy.QtOptionsPage LegacyOptions + => GetDialogPage(typeof(Legacy.QtOptionsPage)) as Legacy.QtOptionsPage; public Editors.QtDesigner QtDesigner { get; private set; } public Editors.QtLinguist QtLinguist { get; private set; } - public Editors.QtResourceEditor QtResourceEditor { get; private set; } + private Editors.QtResourceEditor QtResourceEditor { get; set; } - static EventWaitHandle initDone = new EventWaitHandle(false, EventResetMode.ManualReset); + static readonly EventWaitHandle initDone = new EventWaitHandle(false, EventResetMode.ManualReset); static QtVsToolsPackage instance = null; public static QtVsToolsPackage Instance @@ -167,7 +163,6 @@ var timeInitBegin = initTimer.Elapsed; VsServiceProvider.Instance = instance = this; QtProject.ProjectTracker = this; - Messages.JoinableTaskFactory = JoinableTaskFactory; // determine the package installation directory var uri = new Uri(System.Reflection.Assembly @@ -180,7 +175,7 @@ await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); var timeUiThreadBegin = initTimer.Elapsed; - if ((Dte = VsServiceProvider.GetService<DTE>()) == null) + if ((Dte = await VsServiceProvider.GetServiceAsync<DTE>()) == null) throw new Exception("Unable to get service: DTE"); QtVSIPSettings.Options = Options; @@ -188,14 +183,14 @@ eventHandler = new DteEventsHandler(Dte); Qml.Debug.Launcher.Initialize(); - QtMainMenu.Initialize(this); - QtSolutionContextMenu.Initialize(this); - QtProjectContextMenu.Initialize(this); - QtItemContextMenu.Initialize(this); + QtMainMenu.Initialize(); + QtSolutionContextMenu.Initialize(); + QtProjectContextMenu.Initialize(); + QtItemContextMenu.Initialize(); RegisterEditorFactory(QtDesigner = new Editors.QtDesigner()); RegisterEditorFactory(QtLinguist = new Editors.QtLinguist()); RegisterEditorFactory(QtResourceEditor = new Editors.QtResourceEditor()); - QtHelp.Initialize(this); + QtHelp.Initialize(); if (!string.IsNullOrEmpty(VsShell.InstallRootDir)) HelperFunctions.VCPath = Path.Combine(VsShell.InstallRootDir, "VC"); @@ -209,9 +204,11 @@ var timeUiThreadEnd = initTimer.Elapsed; var vm = QtVersionManager.The(initDone); - var error = string.Empty; - if (vm.HasInvalidVersions(out error)) + if (vm.HasInvalidVersions(out string error, out bool defaultInvalid)) { + if (defaultInvalid) + vm.SetLatestQtVersionAsDefault(); Messages.Print(error); + } /////////// // Install Qt/MSBuild files from package folder to standard location @@ -306,9 +303,8 @@ ================================================================", urlDownloadQtIo, devRelease)); } - } catch (Exception e) { - Messages.Print( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); } finally { initDone.Set(); initTimer.Stop(); @@ -326,11 +322,35 @@ eventHandler.SolutionEvents_Opened(); } + bool TestVersionInstalled() + { + bool newVersion = false; + string versionFile = Path.Combine(PkgInstallPath, "lastversion.txt"); + if (File.Exists(versionFile)) { + string lastVersion = File.ReadAllText(versionFile); + newVersion = (lastVersion!= Version.PRODUCT_VERSION); + } else { + newVersion = true; + } + if (newVersion) + File.WriteAllText(versionFile, Version.PRODUCT_VERSION); + return newVersion; + } + + public void VsMainWindowActivated() + { + if (QtVersionManager.The().GetVersions()?.Length == 0) + Notifications.NoQtVersion.Show(); + if (Options.NotifyInstalled && TestVersionInstalled()) + Notifications.NotifyInstall.Show(); + } + protected override int QueryClose(out bool canClose) { - if (eventHandler != null) { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (eventHandler != null) eventHandler.Disconnect(); - } return base.QueryClose(out canClose); } @@ -381,14 +401,15 @@ File.WriteAllText(Path.Combine(visualizersPath, natvisFile), natvis, System.Text.Encoding.UTF8); - } catch (Exception e) { - Messages.Print( - e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace); + } catch (Exception exception) { + exception.Log(); } } public string GetNatvisPath() { + ThreadHelper.ThrowIfNotOnUIThread(); + try { using (var vsRootKey = Registry.CurrentUser.OpenSubKey(Dte.RegistryRoot)) { if (vsRootKey.GetValue("VisualStudioLocation") is string vsLocation) @@ -433,6 +454,7 @@ void IProjectTracker.AddProject(Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); QtProjectTracker.Add(project); } diff --git a/QtVsTools.Package/Resources.resx b/QtVsTools.Package/Resources.resx index 4c63e0b..cee5e85 100644 --- a/QtVsTools.Package/Resources.resx +++ b/QtVsTools.Package/Resources.resx @@ -117,24 +117,6 @@ <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> - <data name="ActionDialog_Properties" xml:space="preserve"> - <value>Properties</value> - </data> - <data name="AddQtVersionDialog_IncorrectMakefileGenerator" xml:space="preserve"> - <value>This Qt version uses an unsupported makefile generator (used: {0}, supported: MSVC.NET, MSBUILD)</value> - </data> - <data name="AddTranslationDialog_FileName" xml:space="preserve"> - <value>Filename:</value> - </data> - <data name="AddTranslationDialog_Language" xml:space="preserve"> - <value>Language:</value> - </data> - <data name="AddTranslationDialog_Title" xml:space="preserve"> - <value>Add Translation</value> - </data> - <data name="Cancel" xml:space="preserve"> - <value>&Cancel</value> - </data> <data name="CannotFindQMake" xml:space="preserve"> <value>Cannot find qmake. Make sure you have specified a Qt version.</value> </data> @@ -175,32 +157,11 @@ <data name="ImportPriFileNotResolved" xml:space="preserve"> <value>--- (importing .pri file) file: {0} cannot be resolved. Skipping file.</value> </data> - <data name="InstalledQtVersions" xml:space="preserve"> - <value>Installed Qt Versions</value> - </data> <data name="NoProjectOpened" xml:space="preserve"> <value>No Project Opened</value> </data> - <data name="OK" xml:space="preserve"> - <value>&OK</value> - </data> - <data name="IncompatibleMacros" xml:space="preserve"> - <value>The following macros are not compatible: {0}</value> - </data> - <data name="ProjectQtSettingsButtonText" xml:space="preserve"> - <value>Qt Project Settings</value> - </data> - <data name="ProjectQtVersion" xml:space="preserve"> - <value>Set Project's Qt Version</value> - </data> <data name="ProjectQtVersionNotFoundError" xml:space="preserve"> <value>There's no Qt version assigned to project {0} for configuration {1}/{2}. Please use the 'Qt Project Settings' editor to change the 'Version' to a valid Qt version for this platform.</value> - </data> - <data name="QtModules" xml:space="preserve"> - <value>Qt Modules</value> - </data> - <data name="SolutionQtVersion" xml:space="preserve"> - <value>Set Solution's Qt Version</value> </data> <data name="ExportProject_ImportPriFile" xml:space="preserve"> <value>Import from .pri File</value> diff --git a/QtVsTools.Package/qt5.natvis.xml b/QtVsTools.Package/qt5.natvis.xml index 237fbd9..fc3e557 100644 --- a/QtVsTools.Package/qt5.natvis.xml +++ b/QtVsTools.Package/qt5.natvis.xml @@ -224,14 +224,41 @@ </Type> <Type Name="##NAMESPACE##::QString"> - <DisplayString>{((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub}</DisplayString> - <StringView>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub</StringView> + <DisplayString>{((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub}</DisplayString> + <StringView>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub</StringView> <Expand> <Item Name="[size]">d->size</Item> <Item Name="[referenced]">d->ref.atomic._q_value</Item> <ArrayItems> <Size>d->size</Size> - <ValuePointer>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),c</ValuePointer> + <ValuePointer>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),c</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QStringRef"> + <Intrinsic Name="offset" Expression="(reinterpret_cast<char16_t*>(m_string->d)) + + m_string->d->offset / 2" /> + <DisplayString Condition="m_string == nullptr">{m_string,[m_size]} u""</DisplayString> + <DisplayString Condition="m_string != nullptr">{offset() + m_position,[m_size]}</DisplayString> + <Expand> + <Item Name="[position]" ExcludeView="simple">m_position</Item> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems Condition="m_string != nullptr"> + <Size>m_size</Size> + <ValuePointer>offset()+m_position</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QStringView"> + <DisplayString>{m_data,[m_size]}</DisplayString> + <StringView>m_data,[m_size]</StringView> + <Expand> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems> + <Size>m_size</Size> + <ValuePointer>m_data</ValuePointer> </ArrayItems> </Expand> </Type> @@ -264,8 +291,8 @@ <Intrinsic Name="query" Expression="*((QString*)(((char*)(d) + memberOffset(5))))" /> <Intrinsic Name="fragment" Expression="*((QString*)(((char*)(d) + memberOffset(6))))" /> - <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> - <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> + <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> + <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> <Expand> <Item Name="[scheme]">scheme()</Item> <Item Name="[username]">username()</Item> @@ -424,8 +451,8 @@ <IndexListItems> <Size>d->end - d->begin</Size> <ValueNode>*reinterpret_cast<$T1*>((sizeof($T1) > sizeof(void*)) - ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v - : reinterpret_cast<$T1*>(d->array + d->begin + $i)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<$T1*>(d->array + d->begin + $i)) </ValueNode> </IndexListItems> </Expand> @@ -439,8 +466,8 @@ <Size>d->end - d->begin</Size> <ValueNode> *reinterpret_cast<QString*>((sizeof(QString) > sizeof(void*)) - ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v - : reinterpret_cast<QString*>(d->array + d->begin + $i)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QString*>(d->array + d->begin + $i)) </ValueNode> </IndexListItems> </Expand> @@ -454,8 +481,8 @@ <Size>d->end - d->begin</Size> <ValueNode> *reinterpret_cast<QVariant*>((sizeof(QVariant) > sizeof(void*)) - ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v - : reinterpret_cast<QVariant*>(d->array + d->begin + $i)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QVariant*>(d->array + d->begin + $i)) </ValueNode> </IndexListItems> </Expand> @@ -526,7 +553,7 @@ <Exec>node = *(bucket++)</Exec> <Exec>--n</Exec> <Loop> - <Break Condition="!node || !node->next"/> + <Break Condition="!node || !node->next"/> <Exec>keyValuePair = reinterpret_cast<Node *>(node)</Exec> <Item Name="[{keyValuePair->key}]">keyValuePair->value</Item> <Exec>node = node->next</Exec> diff --git a/QtVsTools.Package/qt6.natvis.xml b/QtVsTools.Package/qt6.natvis.xml index 5274053..18c7adf 100644 --- a/QtVsTools.Package/qt6.natvis.xml +++ b/QtVsTools.Package/qt6.natvis.xml @@ -259,7 +259,34 @@ </Expand> </Type> - <Type Name="##NAMESPACE##::QByteArray"> + <Type Name="##NAMESPACE##::QStringRef"> + <DisplayString Condition="m_string == nullptr">{m_string,[m_size]} u""</DisplayString> + <DisplayString Condition="m_string != nullptr">{m_string->d.ptr+m_position,[m_size]}</DisplayString> + <StringView Condition="m_string == nullptr">""</StringView> + <StringView Condition="m_string != nullptr">m_string,[m_position+m_size]</StringView> + <Expand> + <Item Name="[position]" ExcludeView="simple">m_position</Item> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems Condition="m_string != nullptr"> + <Size>m_size</Size> + <ValuePointer>m_string->d.ptr+m_position</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QStringView"> + <DisplayString>{m_data,[m_size]}</DisplayString> + <StringView>m_data,[m_size]</StringView> + <Expand> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems> + <Size>m_size</Size> + <ValuePointer>m_data</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="##NAMESPACE##::QByteArray"> <DisplayString>"{((reinterpret_cast<char*>(d.ptr))),sb}"</DisplayString> <StringView>((reinterpret_cast<char*>(d.ptr))),sb</StringView> <Expand> @@ -286,8 +313,8 @@ <Intrinsic Name="query" Expression="*((QString*)(((char*)(d) + memberOffset(5))))" /> <Intrinsic Name="fragment" Expression="*((QString*)(((char*)(d) + memberOffset(6))))" /> - <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> - <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> + <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> + <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> <Expand> <Item Name="[scheme]">scheme()</Item> <Item Name="[username]">username()</Item> diff --git a/QtVsTools.Package/qt6modules.xml b/QtVsTools.Package/qt6modules.xml new file mode 100644 index 0000000..1754d1a --- /dev/null +++ b/QtVsTools.Package/qt6modules.xml @@ -0,0 +1,510 @@ +<?xml version="1.0" encoding="utf-8"?> +<QtVsTools> + + <!-- Qt Essentials --> + + <Module Id="1"> + <Name>Qt Core</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtCore</LibraryPrefix> + <proVarQT>core</proVarQT> + <IncludePath>$(QTDIR)\include\QtCore</IncludePath> + <Defines>QT_CORE_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="2"> + <Name>Qt D-Bus</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtDBus</LibraryPrefix> + <proVarQT>dbus</proVarQT> + <IncludePath>$(QTDIR)\include\QtDBus</IncludePath> + <Defines>QT_DBUS_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="3"> + <Name>Qt GUI</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtGui</LibraryPrefix> + <proVarQT>gui</proVarQT> + <IncludePath>$(QTDIR)\include\QtGui</IncludePath> + <Defines>QT_GUI_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="4"> + <Name>Qt Network</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtNetwork</LibraryPrefix> + <proVarQT>network</proVarQT> + <IncludePath>$(QTDIR)\include\QtNetwork</IncludePath> + <Defines>QT_NETWORK_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="5"> + <Name>Qt QML</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtQml</LibraryPrefix> + <proVarQT>qml</proVarQT> + <IncludePath>$(QTDIR)\include\QtQml</IncludePath> + <Defines>QT_QML_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="6"> + <Name>Qt Quick</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtQuick</LibraryPrefix> + <proVarQT>quick</proVarQT> + <IncludePath>$(QTDIR)\include\QtQuick</IncludePath> + <Defines>QT_QUICK_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="7"> + <Name>Qt Quick Controls</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtQuickControls2</LibraryPrefix> + <proVarQT>quickcontrols2</proVarQT> + <IncludePath>$(QTDIR)\include\QtQuickControls2</IncludePath> + <Defines>QT_QUICKCONTROLS2_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="8"> + <Name>Qt Quick Dialogs</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtQuickDialogs2</LibraryPrefix> + <proVarQT>quickdialogs2</proVarQT> + <IncludePath>$(QTDIR)\include\QtQuickDialogs2</IncludePath> + <Defines>QT_QUICKDIALOGS2_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="9"> + <Name>Qt Quick Layouts</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtQuickLayouts</LibraryPrefix> + <proVarQT>quicklayouts</proVarQT> + <IncludePath>$(QTDIR)\include\QtQuickLayouts</IncludePath> + <Defines>QT_QUICKLAYOUTS_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="10"> + <Name>Qt Quick Test</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtQuickTest</LibraryPrefix> + <proVarQT>qmltest</proVarQT> + <IncludePath>$(QTDIR)\include\QtQuickTest</IncludePath> + <Defines>QT_QMLTEST_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="11"> + <Name>Qt Test</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtTest</LibraryPrefix> + <proVarQT>testlib</proVarQT> + <IncludePath>$(QTDIR)\include\QtTest</IncludePath> + <Defines>QT_TESTLIB_LIB</Defines> + <Tag>Essential</Tag> + </Module> + <Module Id="12"> + <Name>Qt Widgets</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtWidgets</LibraryPrefix> + <proVarQT>widgets</proVarQT> + <IncludePath>$(QTDIR)\include\QtWidgets</IncludePath> + <Defines>QT_WIDGETS_LIB</Defines> + <Tag>Essential</Tag> + </Module> + + <!-- Qt Add-Ons--> + + <Module Id="13"> + <Name>Active Qt (Server)</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtAxServer</LibraryPrefix> + <proVarQT>axserver</proVarQT> + <IncludePath>$(QTDIR)\include\ActiveQt</IncludePath> + <Defines>QAXSERVER</Defines> + <Defines>QT_AXSERVER_LIB</Defines> + <AdditionalLibraries>Qt6AxBase.lib</AdditionalLibraries> + <AdditionalLibrariesDebug>Qt6AxBased.lib</AdditionalLibrariesDebug> + </Module> + <Module Id="14"> + <Name>Active Qt (Container)</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtAxContainer</LibraryPrefix> + <proVarQT>axcontainer</proVarQT> + <IncludePath>$(QTDIR)\include\ActiveQt</IncludePath> + <Defines>QT_AXCONTAINER_LIB</Defines> + <AdditionalLibraries>Qt6AxBase.lib</AdditionalLibraries> + <AdditionalLibrariesDebug>Qt6AxBased.lib</AdditionalLibrariesDebug> + </Module> + <Module Id="15"> + <Name>Qt Bluetooth</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtBluetooth</LibraryPrefix> + <proVarQT>bluetooth</proVarQT> + <IncludePath>$(QTDIR)\include\QtBluetooth</IncludePath> + <Defines>QT_BLUETOOTH_LIB</Defines> + </Module> + <Module Id="16"> + <Name>Qt 3D</Name> + <Selectable>true</Selectable> + <LibraryPrefix>Qt3DCore</LibraryPrefix> + <proVarQT>3dcore 3danimation 3dextras 3dinput 3dlogic 3drender</proVarQT> + <IncludePath>$(QTDIR)\include\Qt3DCore</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DAnimation</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DExtras</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DInput</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DLogic</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DRender</IncludePath> + <Defines>QT_3DCORE_LIB</Defines> + <Defines>QT_3DANIMATION_LIB</Defines> + <Defines>QT_3DEXTRAS_LIB</Defines> + <Defines>QT_3DINPUT_LIB</Defines> + <Defines>QT_3DLOGIC_LIB</Defines> + <Defines>QT_3DRENDER_LIB</Defines> + <AdditionalLibraries>Qt63DCore.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DAnimation.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DExtras.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DInput.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DLogic.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DRender.lib</AdditionalLibraries> + <AdditionalLibrariesDebug>Qt63DCored.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DAnimationd.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DExtrasd.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DInputd.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DLogicd.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DRenderd.lib</AdditionalLibrariesDebug> + </Module> + <Module Id="17"> + <Name>Qt 5 Core Compatibility APIs</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtCore5Compat</LibraryPrefix> + <proVarQT>core5compat</proVarQT> + <IncludePath>$(QTDIR)\include\QtCore5Compat</IncludePath> + <Defines>QT_CORE5COMPAT_LIB</Defines> + </Module> + <Module Id="18"> <!-- TODO: Split? --> + <Name>Qt for Automation</Name> + <proVarQT>coap mqtt opcua</proVarQT> + <Selectable>true</Selectable> + <LibraryPrefix>QtCoap</LibraryPrefix> + <AdditionalLibraries>Qt6Coap.lib</AdditionalLibraries> + <AdditionalLibraries>Qt6Coapd.lib</AdditionalLibraries> + <AdditionalLibraries>Qt6Mqtt.lib</AdditionalLibraries> + <AdditionalLibraries>Qt6Mqttd.lib</AdditionalLibraries> + <AdditionalLibraries>Qt6OpcUa.lib</AdditionalLibraries> + <AdditionalLibraries>Qt6OpcUad.lib</AdditionalLibraries> + </Module> + <Module Id="19"> + <Name>Qt Concurrent</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtConcurrent</LibraryPrefix> + <proVarQT>concurrent</proVarQT> + <IncludePath>$(QTDIR)\include\QtConcurrent</IncludePath> + <Defines>QT_CONCURRENT_LIB</Defines> + </Module> + <Module Id="20"> + <Name>Qt Help</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtHelp</LibraryPrefix> + <proVarQT>help</proVarQT> + <IncludePath>$(QTDIR)\include\QtHelp</IncludePath> + <Defines>QT_HELP_LIB</Defines> + </Module> + <!-- + Image formats + --> + <Module Id="21"> + <Name>Qt OpenGL</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtOpenGL</LibraryPrefix> + <proVarQT>opengl</proVarQT> + <IncludePath>$(QTDIR)\include\QtOpenGL</IncludePath> + <Defines>QT_OPENGL_LIB</Defines> + </Module> + <Module Id="22"> + <Name>Qt Multimedia</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtMultimedia</LibraryPrefix> + <proVarQT>multimedia</proVarQT> + <IncludePath>$(QTDIR)\include\QtMultimedia</IncludePath> + <Defines>QT_MULTIMEDIA_LIB</Defines> + </Module> + <Module Id="23"> + <Name>Qt Print Support</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtPrintSupport</LibraryPrefix> + <proVarQT>printsupport</proVarQT> + <IncludePath>$(QTDIR)\include\QtPrintSupport</IncludePath> + <Defines>QT_PRINTSUPPORT_LIB</Defines> + </Module> + <Module Id="24"> + <Name>Qt Quick Widgets</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtQuickWidgets</LibraryPrefix> + <proVarQT>quickwidgets</proVarQT> + <IncludePath>$(QTDIR)\include\QtQuickWidgets</IncludePath> + <Defines>QT_QUICKWIDGETS_LIB</Defines> + </Module> + <Module Id="25"> + <Name>Qt Remote Objects</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtRemoteObjects</LibraryPrefix> + <proVarQT>remoteobjects</proVarQT> + <IncludePath>$(QTDIR)\include\QtRemoteObjects</IncludePath> + <Defines>QT_REMOTEOBJECTS_LIB</Defines> + </Module> + <Module Id="26"> + <Name>Qt SCXML</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtScxml</LibraryPrefix> + <proVarQT>scxml</proVarQT> + <IncludePath>$(QTDIR)\include\QtScxml</IncludePath> + <Defines>QT_SCXML_LIB</Defines> + </Module> + <Module Id="27"> + <Name>Qt Sensors</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtSensors</LibraryPrefix> + <proVarQT>sensors</proVarQT> + <IncludePath>$(QTDIR)\include\QtSensors</IncludePath> + <Defines>QT_SENSORS_LIB</Defines> + </Module> + <Module Id="28"> + <Name>Qt Serial Bus</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtSerialBus</LibraryPrefix> + <proVarQT>serialbus</proVarQT> + <IncludePath>$(QTDIR)\include\QtSerialBus</IncludePath> + <Defines>QT_SERIALBUS_LIB</Defines> + </Module> + <Module Id="29"> + <Name>Qt Serial Port</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtSerialPort</LibraryPrefix> + <proVarQT>serialport</proVarQT> + <IncludePath>$(QTDIR)\include\QtSerialPort</IncludePath> + <Defines>QT_SERIALPORT_LIB</Defines> + </Module> + <Module Id="30"> + <Name>Qt SQL</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtSql</LibraryPrefix> + <proVarQT>sql</proVarQT> + <IncludePath>$(QTDIR)\include\QtSql</IncludePath> + <Defines>QT_SQL_LIB</Defines> + </Module> + <Module Id="31"> + <Name>Qt State Machine</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtStateMachine</LibraryPrefix> + <proVarQT>statemachine</proVarQT> + <IncludePath>$(QTDIR)\include\QtStateMachine</IncludePath> + <Defines>QT_STATEMACHINE_LIB</Defines> + </Module> + <Module Id="32"> + <Name>Qt SVG</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtSvg</LibraryPrefix> + <proVarQT>svg</proVarQT> + <IncludePath>$(QTDIR)\include\QtSvg</IncludePath> + <Defines>QT_SVG_LIB</Defines> + </Module> + <Module Id="34"> + <Name>Qt WebChannel</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtWebChannel</LibraryPrefix> + <proVarQT>webchannel</proVarQT> + <IncludePath>$(QTDIR)\include\QtWebChannel</IncludePath> + <Defines>QT_WEBCHANNEL_LIB</Defines> + </Module> + <Module Id="35"> + <Name>Qt WebEngine</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtWebEngine</LibraryPrefix> + <proVarQT>webenginecore</proVarQT> + <IncludePath>$(QTDIR)\include\QtWebEngineCore</IncludePath> + <Defines>QT_WEBENGINECORE_LIB</Defines> + <AdditionalLibraries>Qt6WebEngine.lib</AdditionalLibraries> + <AdditionalLibraries>Qt6WebEngineCore.lib</AdditionalLibraries> + <AdditionalLibrariesDebug>Qt6WebEngined.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt6WebEngineCored.lib</AdditionalLibrariesDebug> + </Module> + <Module Id="36"> + <Name>Qt WebSockets</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtWebSockets</LibraryPrefix> + <proVarQT>websockets</proVarQT> + <IncludePath>$(QTDIR)\include\QtWebSockets</IncludePath> + <Defines>QT_WEBSOCKETS_LIB</Defines> + </Module> + <Module Id="37"> + <Name>WebView</Name> + <proVarQT>webview</proVarQT> + <Selectable>true</Selectable> + <LibraryPrefix>QtWebView</LibraryPrefix> + </Module> + <Module Id="38"> + <Name>Qt XML</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtXml</LibraryPrefix> + <proVarQT>xml</proVarQT> + <IncludePath>$(QTDIR)\include\QtXml</IncludePath> + <Defines>QT_XML_LIB</Defines> + </Module> + <Module Id="39"> + <Name>Qt Positioning</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtPositioning</LibraryPrefix> + <proVarQT>positioning</proVarQT> + <IncludePath>$(QTDIR)\include\QtPositioning</IncludePath> + <Defines>QT_POSITIONING_LIB</Defines> + </Module> + <Module Id="40"> + <Name>Qt NFC</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtNfc</LibraryPrefix> + <proVarQT>nfc</proVarQT> + <IncludePath>$(QTDIR)\include\QtNfc</IncludePath> + <Defines>QT_NFC_LIB</Defines> + </Module> + <Module Id="41"> + <Name>Qt Charts</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtCharts</LibraryPrefix> + <proVarQT>charts</proVarQT> + <IncludePath>$(QTDIR)\include\QtCharts</IncludePath> + <Defines>QT_CHARTS_LIB</Defines> + </Module> + <Module Id="42"> + <Name>Qt Data Visualization</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtDataVisualization</LibraryPrefix> + <proVarQT>datavisualization</proVarQT> + <IncludePath>$(QTDIR)\include\QtDataVisualization</IncludePath> + <Defines>QT_DATAVISUALIZATION_LIB</Defines> + </Module> + <!-- + lottie + --> + <Module Id="44"> + <Name>Qt Network Authorization</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtNetworkAuth</LibraryPrefix> + <proVarQT>networkauth</proVarQT> + <IncludePath>$(QTDIR)\include\QtNetworkAuth</IncludePath> + <Defines>QT_NETWORKAUTH_LIB</Defines> + </Module> + <Module Id="45"> + <Name>Qt Virtual Keyboard</Name> + <proVarQT>virtualkeyboard</proVarQT> + <Selectable>true</Selectable> + <LibraryPrefix>QtVirtualKeyboard</LibraryPrefix> + </Module> + <Module Id="46"> + <Name>Qt Quick 3D</Name> + <Selectable>true</Selectable> + <LibraryPrefix>Qt3DQuick</LibraryPrefix> + <proVarQT>3dquick</proVarQT> + <IncludePath>$(QTDIR)\include\Qt3DQuick</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DQuickAnimation</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DQuickExtras</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DQuickInput</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DQuickRender</IncludePath> + <IncludePath>$(QTDIR)\include\Qt3DQuickScene2D</IncludePath> + <Defines>QT_3DQUICK_LIB</Defines> + <Defines>QT_3DQUICKANIMATION_LIB</Defines> + <Defines>QT_3DQUICKEXTRAS_LIB</Defines> + <Defines>QT_3DQUICKINPUT_LIB</Defines> + <Defines>QT_3DQUICKRENDER_LIB</Defines> + <Defines>QT_3DQUICKSCENE2D_LIB</Defines> + <AdditionalLibraries>Qt63DQuick.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DQuickAnimation.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DQuickExtras.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DQuickInput.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DQuickRender.lib</AdditionalLibraries> + <AdditionalLibraries>Qt63DQuickScene2D.lib</AdditionalLibraries> + <AdditionalLibrariesDebug>Qt63DQuickd.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DQuickAnimationd.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DQuickExtrasd.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DQuickInputd.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DQuickRenderd.lib</AdditionalLibrariesDebug> + <AdditionalLibrariesDebug>Qt63DQuickScene2Dd.lib</AdditionalLibrariesDebug> + </Module> + <Module Id="47"> + <Name>Qt Quick Timeline</Name> + <proVarQT>quicktimeline</proVarQT> + <Selectable>true</Selectable> + <LibraryPrefix>QtQuickTimeline</LibraryPrefix> + </Module> + <Module Id="48"> + <Name>Qt Shader Tools</Name> + <proVarQT>shadertools</proVarQT> + <Selectable>true</Selectable> + <LibraryPrefix>QtShaderTools</LibraryPrefix> + </Module> + <Module Id="49"> + <Name>Qt Wayland Compositor</Name> + <proVarQT>waylandcompositor</proVarQT> + <Selectable>true</Selectable> + <LibraryPrefix>QtWaylandCompositor</LibraryPrefix> + </Module> + <Module Id="50"> + <Name>Qt WebEngine Widgets</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtWebEngineWidgets</LibraryPrefix> + <proVarQT>webenginewidgets</proVarQT> + <IncludePath>$(QTDIR)\include\QtWebEngineCore</IncludePath> + <IncludePath>$(QTDIR)\include\QtWebEngineWidgets</IncludePath> + <Defines>QT_WEBENGINECORE_LIB</Defines> + <Defines>QT_WEBENGINEWIDGETS_LIB</Defines> + <AdditionalLibraries>Qt6WebEngineCore.lib</AdditionalLibraries> + <AdditionalLibrariesDebug>Qt6WebEngineCored.lib</AdditionalLibrariesDebug> + <AdditionalLibraries>Qt6WebEngineWidgets.lib</AdditionalLibraries> + <AdditionalLibrariesDebug>Qt6WebEngineWidgetsd.lib</AdditionalLibrariesDebug> + </Module> + <Module Id="51"> + <Name>Qt WebEngine Quick</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtWebEngineQuick</LibraryPrefix> + <proVarQT>webenginequick</proVarQT> + <IncludePath>$(QTDIR)\include\QtWebEngineCore</IncludePath> + <IncludePath>$(QTDIR)\include\QtWebEngineQuick</IncludePath> + <Defines>QT_WEBENGINECORE_LIB</Defines> + <Defines>QT_WEBENGINEQUICK_LIB</Defines> + <AdditionalLibraries>Qt6WebEngineCore.lib</AdditionalLibraries> + <AdditionalLibrariesDebug>Qt6WebEngineCored.lib</AdditionalLibrariesDebug> + <AdditionalLibraries>Qt6WebEngineQuick.lib</AdditionalLibraries> + <AdditionalLibrariesDebug>Qt6WebEngineQuickd.lib</AdditionalLibrariesDebug> + </Module> + + <!-- Designer --> + <Module Id="52"> + <Name>Designer</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtDesigner</LibraryPrefix> + <HasDLL>true</HasDLL> + <proVarQT>designer</proVarQT> + <IncludePath>$(QTDIR)\include\QtDesigner</IncludePath> + <Defines>QT_DESIGNER_LIB</Defines> + </Module> + <Module Id="53"> + <Name>Qt UI Tools</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtUiTools</LibraryPrefix> + <HasDLL>true</HasDLL> + <proVarQT>uitools</proVarQT> + <IncludePath>$(QTDIR)\include\QtUiTools</IncludePath> + <Defines>QT_UITOOLS_LIB</Defines> + </Module> + <Module Id="54"> + <Name>Qt UI Plugin</Name> + <Selectable>true</Selectable> + <LibraryPrefix>QtUiPlugin</LibraryPrefix> + <HasDLL>false</HasDLL> + <proVarQT>uiplugin</proVarQT> + <IncludePath>$(QTDIR)\include\QtUiPlugin</IncludePath> + <Defines>QT_UIPLUGIN_LIB</Defines> + <Defines>QDESIGNER_EXPORT_WIDGETS</Defines> + </Module> + <!-- Designer --> + +</QtVsTools> diff --git a/QtVsTools.Package/qtmodules.xml b/QtVsTools.Package/qtmodules.xml index 1a56520..364a84a 100644 --- a/QtVsTools.Package/qtmodules.xml +++ b/QtVsTools.Package/qtmodules.xml @@ -4,7 +4,6 @@ <Name>Core</Name> <Selectable>true</Selectable> <LibraryPrefix>QtCore</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>core</proVarQT> <IncludePath>$(QTDIR)\include\QtCore</IncludePath> <Defines>QT_CORE_LIB</Defines> @@ -13,7 +12,6 @@ <Name>Xml</Name> <Selectable>true</Selectable> <LibraryPrefix>QtXml</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>xml</proVarQT> <IncludePath>$(QTDIR)\include\QtXml</IncludePath> <Defines>QT_XML_LIB</Defines> @@ -22,7 +20,6 @@ <Name>Sql</Name> <Selectable>true</Selectable> <LibraryPrefix>QtSql</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>sql</proVarQT> <IncludePath>$(QTDIR)\include\QtSql</IncludePath> <Defines>QT_SQL_LIB</Defines> @@ -31,7 +28,6 @@ <Name>OpenGL</Name> <Selectable>true</Selectable> <LibraryPrefix>QtOpenGL</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>opengl</proVarQT> <IncludePath>$(QTDIR)\include\QtOpenGL</IncludePath> <Defines>QT_OPENGL_LIB</Defines> @@ -40,7 +36,6 @@ <Name>Network</Name> <Selectable>true</Selectable> <LibraryPrefix>QtNetwork</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>network</proVarQT> <IncludePath>$(QTDIR)\include\QtNetwork</IncludePath> <Defines>QT_NETWORK_LIB</Defines> @@ -49,7 +44,6 @@ <Name>Gui</Name> <Selectable>true</Selectable> <LibraryPrefix>QtGui</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>gui</proVarQT> <IncludePath>$(QTDIR)\include\QtGui</IncludePath> <IncludePath>$(QTDIR)\include\QtANGLE</IncludePath> @@ -59,7 +53,6 @@ <Name>ActiveQtS</Name> <Selectable>true</Selectable> <LibraryPrefix>QtAxServer</LibraryPrefix> - <HasDLL>false</HasDLL> <proVarQT>axserver</proVarQT> <IncludePath>$(QTDIR)\include\ActiveQt</IncludePath> <Defines>QAXSERVER</Defines> @@ -70,7 +63,6 @@ <Name>ActiveQtC</Name> <Selectable>true</Selectable> <LibraryPrefix>QtAxContainer</LibraryPrefix> - <HasDLL>false</HasDLL> <proVarQT>axcontainer</proVarQT> <IncludePath>$(QTDIR)\include\ActiveQt</IncludePath> <AdditionalLibraries>Qt5AxBase.lib</AdditionalLibraries> @@ -80,13 +72,11 @@ <Name>Main</Name> <Selectable>false</Selectable> <LibraryPrefix>qtmain</LibraryPrefix> - <HasDLL>false</HasDLL> </Module> <Module Id="13"> <Name>Svg</Name> <Selectable>true</Selectable> <LibraryPrefix>QtSvg</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>svg</proVarQT> <IncludePath>$(QTDIR)\include\QtSvg</IncludePath> <Defines>QT_SVG_LIB</Defines> @@ -95,17 +85,14 @@ <Name>Designer</Name> <Selectable>false</Selectable> <LibraryPrefix>QtDesigner</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>designer</proVarQT> <IncludePath>$(QTDIR)\include\QtDesigner</IncludePath> - <Defines>QDESIGNER_EXPORT_WIDGETS</Defines> <Defines>QT_DESIGNER_LIB</Defines> </Module> <Module Id="15"> <Name>Test</Name> <Selectable>true</Selectable> <LibraryPrefix>QtTest</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>testlib</proVarQT> <IncludePath>$(QTDIR)\include\QtTest</IncludePath> <Defines>QT_TESTLIB_LIB</Defines> @@ -114,7 +101,6 @@ <Name>Script</Name> <Selectable>false</Selectable> <LibraryPrefix>QtScript</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>script</proVarQT> <IncludePath>$(QTDIR)\include\QtScript</IncludePath> <Defines>QT_SCRIPT_LIB</Defines> @@ -123,7 +109,6 @@ <Name>Help</Name> <Selectable>true</Selectable> <LibraryPrefix>QtHelp</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>help</proVarQT> <IncludePath>$(QTDIR)\include\QtHelp</IncludePath> <Defines>QT_HELP_LIB</Defines> @@ -132,7 +117,6 @@ <Name>WebKit</Name> <Selectable>false</Selectable> <LibraryPrefix>QtWebKit</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>webkit</proVarQT> <IncludePath>$(QTDIR)\include\QtWebKit</IncludePath> </Module> @@ -140,7 +124,6 @@ <Name>XmlPatterns</Name> <Selectable>true</Selectable> <LibraryPrefix>QtXmlPatterns</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>xmlpatterns</proVarQT> <IncludePath>$(QTDIR)\include\QtXmlPatterns</IncludePath> <Defines>QT_XMLPATTERNS_LIB</Defines> @@ -149,7 +132,6 @@ <Name>Enginio</Name> <Selectable>false</Selectable> <LibraryPrefix>Enginio</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>enginio</proVarQT> <IncludePath>$(QTDIR)\include\Enginio</IncludePath> <Defines>QT_ENGINIO_LIB</Defines> @@ -158,7 +140,6 @@ <Name>Multimedia</Name> <Selectable>true</Selectable> <LibraryPrefix>QtMultimedia</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>multimedia</proVarQT> <IncludePath>$(QTDIR)\include\QtMultimedia</IncludePath> <Defines>QT_MULTIMEDIA_LIB</Defines> @@ -167,7 +148,6 @@ <Name>ScriptTools</Name> <Selectable>false</Selectable> <LibraryPrefix>QtScriptTools</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>scripttools</proVarQT> <IncludePath>$(QTDIR)\include\QtScriptTools</IncludePath> <Defines>QT_SCRIPTTOOLS_LIB</Defines> @@ -176,7 +156,6 @@ <Name>UiTools</Name> <Selectable>true</Selectable> <LibraryPrefix>QtUiTools</LibraryPrefix> - <HasDLL>false</HasDLL> <proVarQT>uitools</proVarQT> <IncludePath>$(QTDIR)\include\QtUiTools</IncludePath> <Defines>QT_UITOOLS_LIB</Defines> @@ -185,7 +164,6 @@ <Name>Widgets</Name> <Selectable>true</Selectable> <LibraryPrefix>QtWidgets</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>widgets</proVarQT> <IncludePath>$(QTDIR)\include\QtWidgets</IncludePath> <Defines>QT_WIDGETS_LIB</Defines> @@ -194,7 +172,6 @@ <Name>Location</Name> <Selectable>true</Selectable> <LibraryPrefix>QtLocation</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>location</proVarQT> <IncludePath>$(QTDIR)\include\QtLocation</IncludePath> <Defines>QT_LOCATION_LIB</Defines> @@ -203,7 +180,6 @@ <Name>Nfc</Name> <Selectable>true</Selectable> <LibraryPrefix>QtNfc</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>nfc</proVarQT> <IncludePath>$(QTDIR)\include\QtNfc</IncludePath> <Defines>QT_NFC_LIB</Defines> @@ -212,7 +188,6 @@ <Name>Qml</Name> <Selectable>true</Selectable> <LibraryPrefix>QtQml</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>qml</proVarQT> <IncludePath>$(QTDIR)\include\QtQml</IncludePath> <Defines>QT_QML_LIB</Defines> @@ -221,7 +196,6 @@ <Name>Bluetooth</Name> <Selectable>true</Selectable> <LibraryPrefix>QtBluetooth</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>bluetooth</proVarQT> <IncludePath>$(QTDIR)\include\QtBluetooth</IncludePath> <Defines>QT_BLUETOOTH_LIB</Defines> @@ -230,7 +204,6 @@ <Name>Positioning</Name> <Selectable>true</Selectable> <LibraryPrefix>QtPositioning</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>positioning</proVarQT> <IncludePath>$(QTDIR)\include\QtPositioning</IncludePath> <Defines>QT_POSITIONING_LIB</Defines> @@ -239,7 +212,6 @@ <Name>SerialPort</Name> <Selectable>true</Selectable> <LibraryPrefix>QtSerialPort</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>serialport</proVarQT> <IncludePath>$(QTDIR)\include\QtSerialPort</IncludePath> <Defines>QT_SERIALPORT_LIB</Defines> @@ -248,7 +220,6 @@ <Name>PrintSupport</Name> <Selectable>true</Selectable> <LibraryPrefix>QtPrintSupport</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>printsupport</proVarQT> <IncludePath>$(QTDIR)\include\QtPrintSupport</IncludePath> <Defines>QT_PRINTSUPPORT_LIB</Defines> @@ -257,7 +228,6 @@ <Name>WebChannel</Name> <Selectable>true</Selectable> <LibraryPrefix>QtWebChannel</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>webchannel</proVarQT> <IncludePath>$(QTDIR)\include\QtWebChannel</IncludePath> <Defines>QT_WEBCHANNEL_LIB</Defines> @@ -266,7 +236,6 @@ <Name>WebSockets</Name> <Selectable>true</Selectable> <LibraryPrefix>QtWebSockets</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>websockets</proVarQT> <IncludePath>$(QTDIR)\include\QtWebSockets</IncludePath> <Defines>QT_WEBSOCKETS_LIB</Defines> @@ -275,7 +244,6 @@ <Name>Sensors</Name> <Selectable>true</Selectable> <LibraryPrefix>QtSensors</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>sensors</proVarQT> <IncludePath>$(QTDIR)\include\QtSensors</IncludePath> <Defines>QT_SENSORS_LIB</Defines> @@ -284,7 +252,6 @@ <Name>WindowsExtras</Name> <Selectable>true</Selectable> <LibraryPrefix>QtWinExtras</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>winextras</proVarQT> <IncludePath>$(QTDIR)\include\QtWinExtras</IncludePath> <Defines>QT_WINEXTRAS_LIB</Defines> @@ -293,7 +260,6 @@ <Name>QuickWidgets</Name> <Selectable>true</Selectable> <LibraryPrefix>QtQuickWidgets</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>quickwidgets</proVarQT> <IncludePath>$(QTDIR)\include\QtQuickWidgets</IncludePath> <Defines>QT_QUICKWIDGETS_LIB</Defines> @@ -302,7 +268,6 @@ <Name>Quick</Name> <Selectable>true</Selectable> <LibraryPrefix>QtQuick</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>quick</proVarQT> <IncludePath>$(QTDIR)\include\QtQuick</IncludePath> <Defines>QT_QUICK_LIB</Defines> @@ -311,7 +276,6 @@ <Name>WebkitWidgets</Name> <Selectable>false</Selectable> <LibraryPrefix>QtWebkitWidgets</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>webkitwidgets</proVarQT> <IncludePath>$(QTDIR)\include\QtWebkitWidgets</IncludePath> <Defines>QT_WEBKITWIDGETS_LIB</Defines> @@ -320,7 +284,6 @@ <Name>Concurrent</Name> <Selectable>true</Selectable> <LibraryPrefix>QtConcurrent</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>concurrent</proVarQT> <IncludePath>$(QTDIR)\include\QtConcurrent</IncludePath> <Defines>QT_CONCURRENT_LIB</Defines> @@ -329,7 +292,6 @@ <Name>MultimediaWidgets</Name> <Selectable>true</Selectable> <LibraryPrefix>QtMultimediaWidgets</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>multimediawidgets</proVarQT> <IncludePath>$(QTDIR)\include\QtMultimediaWidgets</IncludePath> <Defines>QT_MULTIMEDIAWIDGETS_LIB</Defines> @@ -338,7 +300,6 @@ <Name>3D</Name> <Selectable>true</Selectable> <LibraryPrefix>Qt3DCore</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>3dcore 3danimation 3dextras 3dinput 3dlogic 3drender</proVarQT> <IncludePath>$(QTDIR)\include\Qt3DCore</IncludePath> <IncludePath>$(QTDIR)\include\Qt3DAnimation</IncludePath> @@ -369,7 +330,6 @@ <Name>3D Quick</Name> <Selectable>true</Selectable> <LibraryPrefix>Qt3DQuick</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>3dquick</proVarQT> <IncludePath>$(QTDIR)\include\Qt3DQuick</IncludePath> <IncludePath>$(QTDIR)\include\Qt3DQuickAnimation</IncludePath> @@ -400,7 +360,6 @@ <Name>DBus</Name> <Selectable>true</Selectable> <LibraryPrefix>QtDBus</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>dbus</proVarQT> <IncludePath>$(QTDIR)\include\QtDBus</IncludePath> <Defines>QT_DBUS_LIB</Defines> @@ -409,7 +368,6 @@ <Name>Gamepad</Name> <Selectable>true</Selectable> <LibraryPrefix>QtGamepad</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>gamepad</proVarQT> <IncludePath>$(QTDIR)\include\QtGamepad</IncludePath> <Defines>QT_GAMEPAD_LIB</Defines> @@ -418,7 +376,6 @@ <Name>OpenGL Extensions</Name> <Selectable>true</Selectable> <LibraryPrefix>QtOpenGLExtensions</LibraryPrefix> - <HasDLL>false</HasDLL> <proVarQT>openglextensions</proVarQT> <IncludePath>$(QTDIR)\include\QtOpenGLExtensions</IncludePath> <Defines>QT_OPENGLEXTENSIONS_LIB</Defines> @@ -427,7 +384,6 @@ <Name>QuickTest</Name> <Selectable>true</Selectable> <LibraryPrefix>QtQuickTest</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>qmltest</proVarQT> <IncludePath>$(QTDIR)\include\QtQuickTest</IncludePath> <Defines>QT_QMLTEST_LIB</Defines> @@ -436,7 +392,6 @@ <Name>Quick Controls2</Name> <Selectable>true</Selectable> <LibraryPrefix>QtQuickControls2</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>quickcontrols2</proVarQT> <IncludePath>$(QTDIR)\include\QtQuickControls2</IncludePath> <Defines>QT_QUICKCONTROLS2_LIB</Defines> @@ -445,7 +400,6 @@ <Name>Scxml</Name> <Selectable>true</Selectable> <LibraryPrefix>QtScxml</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>scxml</proVarQT> <IncludePath>$(QTDIR)\include\QtScxml</IncludePath> <Defines>QT_SCXML_LIB</Defines> @@ -454,7 +408,6 @@ <Name>Serial Bus</Name> <Selectable>true</Selectable> <LibraryPrefix>QtSerialBus</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>serialbus</proVarQT> <IncludePath>$(QTDIR)\include\QtSerialBus</IncludePath> <Defines>QT_SERIALBUS_LIB</Defines> @@ -463,16 +416,15 @@ <Name>UI Plugin</Name> <Selectable>false</Selectable> <LibraryPrefix>QtUiPlugin</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>uiplugin</proVarQT> <IncludePath>$(QTDIR)\include\QtUiPlugin</IncludePath> <Defines>QT_UIPLUGIN_LIB</Defines> + <Defines>QDESIGNER_EXPORT_WIDGETS</Defines> </Module> <Module Id="111"> <Name>WebEngine</Name> <Selectable>true</Selectable> <LibraryPrefix>QtWebEngine</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>webengine</proVarQT> <IncludePath>$(QTDIR)\include\QtWebEngine</IncludePath> <IncludePath>$(QTDIR)\include\QtWebEngineCore</IncludePath> @@ -487,7 +439,6 @@ <Name>WebEngine Widgets</Name> <Selectable>true</Selectable> <LibraryPrefix>QtWebEngineWidgets</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>webenginewidgets</proVarQT> <IncludePath>$(QTDIR)\include\QtWebEngineWidgets</IncludePath> <IncludePath>$(QTDIR)\include\QtWebEngineCore</IncludePath> @@ -502,7 +453,6 @@ <Name>Charts</Name> <Selectable>true</Selectable> <LibraryPrefix>QtCharts</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>charts</proVarQT> <IncludePath>$(QTDIR)\include\QtCharts</IncludePath> <Defines>QT_CHARTS_LIB</Defines> @@ -511,7 +461,6 @@ <Name>Data Visualization</Name> <Selectable>true</Selectable> <LibraryPrefix>QtDataVisualization</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>datavisualization</proVarQT> <IncludePath>$(QTDIR)\include\QtDataVisualization</IncludePath> <Defines>QT_DATAVISUALIZATION_LIB</Defines> @@ -520,7 +469,6 @@ <Name>Network Authorization</Name> <Selectable>true</Selectable> <LibraryPrefix>QtNetworkAuth</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>networkauth</proVarQT> <IncludePath>$(QTDIR)\include\QtNetworkAuth</IncludePath> <Defines>QT_NETWORKAUTH_LIB</Defines> @@ -529,7 +477,6 @@ <Name>Speech</Name> <Selectable>true</Selectable> <LibraryPrefix>QtTextToSpeech</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>texttospeech</proVarQT> <IncludePath>$(QTDIR)\include\QtTextToSpeech</IncludePath> <Defines>QT_TEXTTOSPEECH_LIB</Defines> @@ -538,7 +485,6 @@ <Name>Remote Objects</Name> <Selectable>true</Selectable> <LibraryPrefix>QtRemoteObjects</LibraryPrefix> - <HasDLL>true</HasDLL> <proVarQT>remoteobjects</proVarQT> <IncludePath>$(QTDIR)\include\QtRemoteObjects</IncludePath> <Defines>QT_REMOTEOBJECTS_LIB</Defines> diff --git a/QtVsTools.Package/source.extension.vsixmanifest_TT b/QtVsTools.Package/source.extension.vsixmanifest_TT index 7321b70..1aa4a5d 100644 --- a/QtVsTools.Package/source.extension.vsixmanifest_TT +++ b/QtVsTools.Package/source.extension.vsixmanifest_TT @@ -88,9 +88,9 @@ <DisplayName>Qt Visual Studio Tools</DisplayName> <Description xml:space="preserve">The Qt VS Tools for Visual Studio <#=VS_NAME#> allow developers to use the standard development environment without having to worry about any Qt-related build steps or tools.</Description> <#=XML_COMMENT_BEGIN#> END Generated Text --> - <MoreInfo>http://www.qt.io</MoreInfo> + <MoreInfo>https://doc.qt.io/qtvstools/index.html</MoreInfo> <License>LICENSE.GPL3-EXCEPT</License> - <ReleaseNotes>Changelog</ReleaseNotes> + <ReleaseNotes>https://code.qt.io/cgit/qt-labs/vstools.git/tree/Changelog</ReleaseNotes> <Icon>qt.ico</Icon> <PreviewImage>preview.png</PreviewImage> </Metadata> @@ -195,6 +195,20 @@ d:TargetPath="|QtTemplate.Item.Widget;TemplateProjectOutputGroup|" Path="ItemTemplates" d:VsixSubPath="ItemTemplates" /> <Asset + Type="Microsoft.VisualStudio.ItemTemplate" d:Source="Project" d:ProjectName="WidgetsClass" + d:TargetPath="|QtTemplate.Item.WidgetsClass;TemplateProjectOutputGroup|" Path="ItemTemplates" + d:VsixSubPath="ItemTemplates" /> + <Asset + Type="Microsoft.VisualStudio.ItemTemplate" d:Source="Project" d:ProjectName="QtClass" + d:TargetPath="|QtTemplate.Item.QtClass;TemplateProjectOutputGroup|" Path="ItemTemplates" + d:VsixSubPath="ItemTemplates" /> + <Asset + Type="Microsoft.VisualStudio.ItemTemplate" d:Source="Project" d:ProjectName="Translation" + d:TargetPath="|QtTemplate.Item.Translation;TemplateProjectOutputGroup|" Path="ItemTemplates" + d:VsixSubPath="ItemTemplates" /> + <Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="File" Path="QtVsTools.Qml.Debug.pkgdef" /> + <Asset + Type="Microsoft.VisualStudio.VsPackage" d:Source="File" Path="QtVsTools.Icons.pkgdef" /> </Assets> </PackageManifest> diff --git a/QtVsTools.RegExpr/Properties/AssemblyInfo.cs b/QtVsTools.RegExpr/Properties/AssemblyInfo.cs index 87d3c5e..4753562 100644 --- a/QtVsTools.RegExpr/Properties/AssemblyInfo.cs +++ b/QtVsTools.RegExpr/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/QtVsTools.RegExpr/QtVsTools.RegExpr.csproj b/QtVsTools.RegExpr/QtVsTools.RegExpr.csproj index 92577c4..b309bab 100644 --- a/QtVsTools.RegExpr/QtVsTools.RegExpr.csproj +++ b/QtVsTools.RegExpr/QtVsTools.RegExpr.csproj @@ -66,21 +66,18 @@ // --> <ItemGroup> <Reference Include="System" /> - <Reference Include="System.Xml.Linq" /> </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// // Version specific references // --> + <!--<Import Project="$(SolutionDir)\references.props" />--> <!-- // Visual Studio 2022 --> - <ItemGroup Condition="'$(VisualStudioVersion)'=='17.0'"> - </ItemGroup> + <ItemGroup Condition="'$(VisualStudioVersion)'=='17.0'" /> <!-- // Visual Studio 2019 --> - <ItemGroup Condition="'$(VisualStudioVersion)'=='16.0'"> - </ItemGroup> + <ItemGroup Condition="'$(VisualStudioVersion)'=='16.0'" /> <!-- // Visual Studio 2017 --> - <ItemGroup Condition="'$(VisualStudioVersion)'=='15.0'"> - </ItemGroup> + <ItemGroup Condition="'$(VisualStudioVersion)'=='15.0'" /> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// // Solution project references diff --git a/QtVsTools.RegExpr/expression/CharClassSet.cs b/QtVsTools.RegExpr/expression/CharClassSet.cs index 36e1fa6..16cc9ba 100644 --- a/QtVsTools.RegExpr/expression/CharClassSet.cs +++ b/QtVsTools.RegExpr/expression/CharClassSet.cs @@ -26,7 +26,6 @@ ** ****************************************************************************/ -using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -48,8 +47,8 @@ /// public partial class CharClassSet : CharClass, IEnumerable<IEnumerable<Element>> { - public IEnumerable<Element> Positives { get; set; } - public IEnumerable<Element> Negatives { get; set; } + private IEnumerable<Element> Positives { get; set; } + private IEnumerable<Element> Negatives { get; set; } bool IsSubSet { get; set; } bool HasPositive { get { return Positives != null && Positives.Any(); } } @@ -210,13 +209,13 @@ public class Expr { - public Op Operator { get; private set; } + public Op Operator { get; } - public List<Expr> Factors { get; private set; } + public List<Expr> Factors { get; } public Expr(Op op, List<Expr> factors) { Operator = op; Factors = factors; } public Expr(Op op, params Expr[] factors) : this(op, factors.ToList()) { } - public CharClass Term { get; private set; } + public CharClass Term { get; } public Expr(CharClass c) { Operator = Op.Term; Term = c; } public static implicit operator Expr(CharClass c) { return new Expr(c); } public static implicit operator Expr(string s) { return Char[s]; } @@ -325,7 +324,7 @@ { public Expr Expr { get; set; } public Queue<Expr> Children { get; set; } - public List<CharClassSet> SubSets { get; set; } + public List<CharClassSet> SubSets { get; } public StackFrame() { Expr = null; diff --git a/QtVsTools.RegExpr/expression/RegExprAssert.cs b/QtVsTools.RegExpr/expression/RegExprAssert.cs index 09172c0..82c6721 100644 --- a/QtVsTools.RegExpr/expression/RegExprAssert.cs +++ b/QtVsTools.RegExpr/expression/RegExprAssert.cs @@ -26,9 +26,7 @@ ** ****************************************************************************/ -using System; using System.Collections.Generic; -using System.Collections.Concurrent; using System.Text; namespace QtVsTools.SyntaxAnalysis @@ -140,7 +138,7 @@ public class AssertExprBuilder { - AssertTemplate Template { get; set; } + AssertTemplate Template { get; } public AssertExprBuilder(AssertTemplate template) { diff --git a/QtVsTools.RegExpr/expression/RegExprRepeat.cs b/QtVsTools.RegExpr/expression/RegExprRepeat.cs index a6ee1fa..d49b9ba 100644 --- a/QtVsTools.RegExpr/expression/RegExprRepeat.cs +++ b/QtVsTools.RegExpr/expression/RegExprRepeat.cs @@ -26,7 +26,6 @@ ** ****************************************************************************/ -using System; using System.Collections.Generic; using System.Text; diff --git a/QtVsTools.RegExpr/expression/RegExprToken.cs b/QtVsTools.RegExpr/expression/RegExprToken.cs index 08152b1..47dce8e 100644 --- a/QtVsTools.RegExpr/expression/RegExprToken.cs +++ b/QtVsTools.RegExpr/expression/RegExprToken.cs @@ -57,13 +57,13 @@ { public string Id { get; set; } - public bool SkipLeadingWhitespace { get; set; } - public RegExpr LeadingWhitespace { get; set; } + private bool SkipLeadingWhitespace { get; } + private RegExpr LeadingWhitespace { get; } - public RegExpr Expr { get; set; } + private RegExpr Expr { get; } - public HashSet<Token> Children { get; set; } - public Dictionary<string, Token> Parents { get; set; } + private HashSet<Token> Children { get; } + public Dictionary<string, Token> Parents { get; } public IEnumerable<string> CaptureIds => Parents.Keys; public Token(string id, RegExpr skipWs, RegExpr expr) @@ -170,7 +170,7 @@ /// <summary> /// Set of rules that can be applied to the token. /// </summary> - TokenRules Rules { get; set; } + TokenRules Rules { get; } public void Add(IProductionRule rule) { @@ -221,7 +221,7 @@ public class TokenGroup : IEnumerable<string> { - HashSet<string> TokenIds { get; set; } + HashSet<string> TokenIds { get; } public TokenGroup(params string[] tokenIds) { @@ -261,7 +261,7 @@ public class TokenRules : IEnumerable<IProductionRule> { - Dictionary<RuleCallback.Selector, IProductionRule> Rules { get; set; } + Dictionary<RuleCallback.Selector, IProductionRule> Rules { get; } IProductionRule DefaultRule { get; set; } public TokenRules() @@ -383,6 +383,6 @@ public object Production { get; } } - static TokenEndOfList EndOfList = new TokenEndOfList(); + static readonly TokenEndOfList EndOfList = new TokenEndOfList(); } } diff --git a/QtVsTools.RegExpr/expression/Renderer.cs b/QtVsTools.RegExpr/expression/Renderer.cs index c79da8c..3f8b334 100644 --- a/QtVsTools.RegExpr/expression/Renderer.cs +++ b/QtVsTools.RegExpr/expression/Renderer.cs @@ -26,7 +26,6 @@ ** ****************************************************************************/ -using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/QtVsTools.RegExpr/parser/ParseTree.cs b/QtVsTools.RegExpr/parser/ParseTree.cs index 1ee054c..4ff56d0 100644 --- a/QtVsTools.RegExpr/parser/ParseTree.cs +++ b/QtVsTools.RegExpr/parser/ParseTree.cs @@ -26,11 +26,8 @@ ** ****************************************************************************/ -using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Text.RegularExpressions; namespace QtVsTools.SyntaxAnalysis { @@ -70,7 +67,7 @@ } } - static NodeComparer _Comparer = new NodeComparer(); + static readonly NodeComparer _Comparer = new NodeComparer(); public static IComparer<Node> Comparer { get { return _Comparer; } } public Token Token { get; set; } @@ -80,11 +77,9 @@ public Node Parent { get; set; } - SortedList<int, Node> _ChildNodes = new SortedList<int, Node>(); - public SortedList<int, Node> ChildNodes { get { return _ChildNodes; } } + public SortedList<int, Node> ChildNodes { get; } = new SortedList<int, Node>(); - ProductionObjects _ChildProductions = new ProductionObjects(); - public ProductionObjects ChildProductions { get { return _ChildProductions; } } + public ProductionObjects ChildProductions { get; } = new ProductionObjects(); public Queue<Node> TokenStream { get; set; } public Stack<Node> OperatorStack { get; set; } diff --git a/QtVsTools.RegExpr/parser/Parser.cs b/QtVsTools.RegExpr/parser/Parser.cs index f69cae4..e2b9f36 100644 --- a/QtVsTools.RegExpr/parser/Parser.cs +++ b/QtVsTools.RegExpr/parser/Parser.cs @@ -27,8 +27,6 @@ ****************************************************************************/ using System; -using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Text.RegularExpressions; @@ -46,7 +44,7 @@ /// </summary> public partial class Parser { - Renderer Renderer { get; set; } + Renderer Renderer { get; } Pattern Pattern { get; set; } public Regex Regex { get; private set; } @@ -118,11 +116,9 @@ foreach (var node in nodes.Where(n => n.Token != Pattern.Root)) { // Get nodes captured by parent token - Token parentToken; - if (!node.Token.Parents.TryGetValue(node.CaptureId, out parentToken)) + if (!node.Token.Parents.TryGetValue(node.CaptureId, out Token parentToken)) throw new ParseErrorException("Unknown capture ID"); - ParseTree.Node[] parentNodes; - if (!nodesByToken.TryGetValue(parentToken, out parentNodes)) + if (!nodesByToken.TryGetValue(parentToken, out ParseTree.Node[] parentNodes)) throw new ParseErrorException("Missing parent nodes"); // Find parent node int idx = Array.BinarySearch(parentNodes, node, ParseTree.Node.Comparer); diff --git a/QtVsTools.RegExpr/production/Production.cs b/QtVsTools.RegExpr/production/Production.cs index 8dc30cc..39d770b 100644 --- a/QtVsTools.RegExpr/production/Production.cs +++ b/QtVsTools.RegExpr/production/Production.cs @@ -30,11 +30,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using System.Text; namespace QtVsTools.SyntaxAnalysis { @@ -215,8 +211,8 @@ /// </summary> public partial class ProductionObjects : IEnumerable<KeyValuePair<string, object>> { - List<KeyValuePair<string, object>> Productions { get; set; } - Dictionary<string, List<object>> ProductionsByTokenId { get; set; } + List<KeyValuePair<string, object>> Productions { get; } + Dictionary<string, List<object>> ProductionsByTokenId { get; } public ProductionObjects() { @@ -227,8 +223,7 @@ public void Add(string tokenId, object prodObj) { Productions.Add(new KeyValuePair<string, object>(tokenId, prodObj)); - List<object> prodObjs; - if (!ProductionsByTokenId.TryGetValue(tokenId, out prodObjs)) + if (!ProductionsByTokenId.TryGetValue(tokenId, out List<object> prodObjs)) ProductionsByTokenId.Add(tokenId, prodObjs = new List<object>()); prodObjs.Add(prodObj); } @@ -238,8 +233,7 @@ if (string.IsNullOrEmpty(tokenId)) return Empty<T>(); - List<object> tokenProds; - if (!ProductionsByTokenId.TryGetValue(tokenId, out tokenProds)) + if (!ProductionsByTokenId.TryGetValue(tokenId, out List<object> tokenProds)) return Empty<T>(); return tokenProds diff --git a/QtVsTools.RegExpr/production/ProductionRule.cs b/QtVsTools.RegExpr/production/ProductionRule.cs index 8884aae..2299177 100644 --- a/QtVsTools.RegExpr/production/ProductionRule.cs +++ b/QtVsTools.RegExpr/production/ProductionRule.cs @@ -29,11 +29,8 @@ using System; using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Linq.Expressions; using System.Reflection; -using System.Text; namespace QtVsTools.SyntaxAnalysis { @@ -66,7 +63,7 @@ public virtual Delimiter Delimiters { get { return Delimiter.None; } } public virtual Operand Operands { get { return Operand.None; } } - protected List<IRuleAction<T>> Actions = new List<IRuleAction<T>>(); + private readonly List<IRuleAction<T>> Actions = new List<IRuleAction<T>>(); protected void Init( int priority, RuleCallback.Selector select, RuleCallback.PreCondition pre) diff --git a/QtVsTools.RegExpr/production/ProductionRuleAction.cs b/QtVsTools.RegExpr/production/ProductionRuleAction.cs index 71662d8..7d7a2e0 100644 --- a/QtVsTools.RegExpr/production/ProductionRuleAction.cs +++ b/QtVsTools.RegExpr/production/ProductionRuleAction.cs @@ -135,11 +135,9 @@ public bool Execute(ref T prod, string value, params object[] operands) { int idx = 0; - T1 x; - T2 y; - if (!GetOperand(out x, operands, ref idx)) + if (!GetOperand(out T1 x, operands, ref idx)) return false; - if (!GetOperand(out y, operands, ref idx)) + if (!GetOperand(out T2 y, operands, ref idx)) return false; if (!TestAssert(prod, value, x, y)) diff --git a/QtVsTools.RegExpr/utils/Consts.cs b/QtVsTools.RegExpr/utils/Consts.cs index 4835958..ec1e394 100644 --- a/QtVsTools.RegExpr/utils/Consts.cs +++ b/QtVsTools.RegExpr/utils/Consts.cs @@ -26,11 +26,6 @@ ** ****************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace QtVsTools.SyntaxAnalysis { using static CharClass; @@ -82,7 +77,7 @@ /// <summary><![CDATA[ /// Equivalent to: [\S] /// ]]></summary> - public static CharClassLiteral CharNonSpace + private static CharClassLiteral CharNonSpace { get { return new CharClassLiteral { LiteralChars = @"\S" }; } } /// <summary><![CDATA[ @@ -181,21 +176,17 @@ public static RegExpr SkipWs { get { return new Token(); } } - static CharExprBuilder _Char = new CharExprBuilder(); + static readonly CharExprBuilder _Char = new CharExprBuilder(); public static CharExprBuilder Char { get { return _Char; } } public static CharExprBuilder Chars { get { return _Char; } } - static CharSetExprBuilder _CharSet = new CharSetExprBuilder(); - public static CharSetExprBuilder CharSet { get { return _CharSet; } } + public static CharSetExprBuilder CharSet { get; } = new CharSetExprBuilder(); - static CharSetRawExprBuilder _CharSetRaw = new CharSetRawExprBuilder(); - public static CharSetRawExprBuilder CharSetRaw { get { return _CharSetRaw; } } + public static CharSetRawExprBuilder CharSetRaw { get; } = new CharSetRawExprBuilder(); - static AssertExprBuilder _LookAhead = new AssertExprBuilder(AssertLookAhead); - public static AssertExprBuilder LookAhead { get { return _LookAhead; } } + public static AssertExprBuilder LookAhead { get; } = new AssertExprBuilder(AssertLookAhead); - static AssertExprBuilder _LookBehind = new AssertExprBuilder(AssertLookBehind); - public static AssertExprBuilder LookBehind { get { return _LookBehind; } } + public static AssertExprBuilder LookBehind { get; } = new AssertExprBuilder(AssertLookBehind); public const SkipWhitespace SkipWs_Disable = SkipWhitespace.Disable; } diff --git a/QtVsTools.Wizards/Common/GuiPage.xaml b/QtVsTools.Wizards/Common/GuiPage.xaml new file mode 100644 index 0000000..cdbc560 --- /dev/null +++ b/QtVsTools.Wizards/Common/GuiPage.xaml @@ -0,0 +1,307 @@ +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + +<common:WizardPage x:Class="QtVsTools.Wizards.Common.GuiPage" + xmlns:common="clr-namespace:QtVsTools.Wizards.Common" + xmlns:util="clr-namespace:QtVsTools.Wizards.Util" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + KeepAlive="True" + mc:Ignorable="d" + d:DesignHeight="445" + d:DesignWidth="585"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Image Grid.Column="0" + HorizontalAlignment="Center" + Source="/QtVsTools.Wizards;component/Resources/Qt-logo-small.png" + VerticalAlignment="Top" + Margin="0,25,0,0" + RenderTransformOrigin="1,0"> + <Image.RenderTransform> + <TransformGroup> + <ScaleTransform ScaleY="0.86" + ScaleX="0.86" /> + </TransformGroup> + </Image.RenderTransform> + </Image> + <Grid Grid.Column="1" + Margin="25,25,10,0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock TextWrapping="Wrap" + Grid.Row="0"> + <Run FontWeight="Bold" + Text="{Binding Path=Header}" /> + <LineBreak /> + <LineBreak /> + <Run Text="{Binding Path=Message}" /> + <LineBreak /> + </TextBlock> + <Grid Grid.Row="1"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid.Resources> + <Style TargetType="TextBox"> + <Style.Triggers> + <Trigger Property="Validation.HasError" + Value="true"> + <Setter Property="ToolTip" + Value="{Binding RelativeSource={RelativeSource Self}, + Path=(Validation.Errors)[0].ErrorContent}" /> + </Trigger> + </Style.Triggers> + </Style> + </Grid.Resources> + <StackPanel Grid.Column="0"> + <TextBlock Text="Class Name:" + Margin="0,0,10,0" /> + <TextBox Margin="0,0,10,15" + Name="ClassName" + TextChanged="OnClassNameChanged" + TabIndex="0"> + <TextBox.Text> + <Binding Path="Data.ClassName" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:ClassNameValidationRule SupportNamespaces="True"/> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Text="User Interface (.ui) file:" + Margin="0,0,10,0" /> + <TextBox Name="UiFile" + Margin="0,0,10,52" + TabIndex="2"> + <TextBox.Text> + <Binding Path="Data.UiFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".ui" /> + <util:FileExistsinFilterValidationRule Filter="FL_UiFiles" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Text="Header (.h) file:" + Margin="0,0,10,0" /> + <TextBox Name="ClassHeaderFile" + Margin="0,0,10,5" + TabIndex="6"> + <TextBox.Text> + <Binding Path="Data.ClassHeaderFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".h" /> + <util:FileExistsinFilterValidationRule Filter="FL_HFiles" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Text="Source (.cpp) file:" + Margin="0,0,0,0" /> + <TextBox Name="ClassSourceFile" + Margin="0,0,10,15" + TabIndex="8"> + <TextBox.Text> + <Binding Path="Data.ClassSourceFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".cpp" /> + <util:FileExistsinFilterValidationRule Filter="FL_CppFiles" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + + </StackPanel> + <StackPanel Grid.Column="1"> + <TextBlock Text="Base class:" /> + <ComboBox Margin="0,0,0,11" + IsEditable="{Binding Path=IsClassWizardPage}" + SelectedIndex="0" + Text="{Binding Path=Data.BaseClass}" + IsSynchronizedWithCurrentItem="True" + TabIndex="1"> + <ComboBoxItem Content="QMainWindow" + IsSelected="True" /> + <ComboBoxItem Content="QWidget" /> + <ComboBoxItem Content="QDialog" /> + </ComboBox> + <TextBlock TextWrapping="Wrap" + Text="Ui Class Inclusion as:" + Margin="0,0,0,5" + VerticalAlignment="Top"/> + <StackPanel Grid.Column="1" + Margin="10,0,0,10"> + <StackPanel.Resources> + <util:UiClassInclusionConverter x:Key="UiClassInclusionConverter" /> + </StackPanel.Resources> + <RadioButton Content="Member" + Margin="0,0,0,5" + IsChecked="{ + Binding Path=Data.UiClassInclusion, + Converter={StaticResource UiClassInclusionConverter}, + ConverterParameter={x:Static common:UiClassInclusion.Member} + }" + TabIndex="3" /> + <RadioButton Content="Member Pointer" + Margin="0,0,0,5" + IsChecked="{ + Binding Path=Data.UiClassInclusion, + Converter={StaticResource UiClassInclusionConverter}, + ConverterParameter={x:Static common:UiClassInclusion.MemberPointer} + }" + TabIndex="4" /> + <RadioButton Content="Multiple Inheritance" + IsChecked="{ + Binding Path=Data.UiClassInclusion, + Converter={StaticResource UiClassInclusionConverter}, + ConverterParameter={x:Static common:UiClassInclusion.MultipleInheritance} + }" + TabIndex="5" /> + </StackPanel> + <CheckBox Content="Insert Q_OBJECT macro" + TabIndex="7" + Margin="0,0,0,-17" + Name="InsertQObjectMacro" + Visibility="{Binding Path=QObjectMacro}" + IsChecked="{Binding Path=Data.InsertQObjectMacro}" /> + <TextBlock Margin="0,0,10,0" + Text="Resource (.qrc) file:" + Visibility="{Binding Path=ClassPageVisible}" /> + <TextBox Name="QrcFile" + Margin="0,0,0,23" + TabIndex="7" + Visibility="{Binding Path=ClassPageVisible}" > + <TextBox.Text> + <Binding Path="Data.QrcFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".qrc" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <CheckBox Content="Lower case file names" + Margin="0,0,0,5" + Name="LowerCaseFileNames" + TabIndex="9" + Click="OnLowerCaseFileNamesClick" /> + <CheckBox Content="Precompiled header" + Margin="0,0,0,5" + IsChecked="{Binding Path=Data.UsePrecompiledHeader}" + TabIndex="10" + Visibility="{Binding Path=ClassPageVisible}"/> + <CheckBox Content="Add default application icon" + Margin="0,0,0,0" + IsChecked="{Binding Path=Data.AddDefaultAppIcon}" + TabIndex="11" + Visibility="{Binding Path=ClassPageVisible}" /> + </StackPanel> + </Grid> + <StackPanel HorizontalAlignment="Right" + Orientation="Horizontal" + Grid.Row="2" + Margin="0,0,0,10"> + <Button Click="OnPreviousButtonClick" + Name="PreviousButton" + IsEnabled="{Binding Path=PreviousButtonEnabled}" + MinWidth="75">< _Previous</Button> + <Button MinWidth="75" + Name="NextButton" + Click="OnNextButtonClick" + IsEnabled="{Binding Path=NextButtonEnabled}" + Margin="10,0,0,0">_Next ></Button> + <Button MinWidth="75" + Click="OnFinishButtonClick" + Margin="10,0,0,0" + IsDefault="True" + Name="FinishButton" + Content="_Finish" + VerticalAlignment="Bottom"> + <Button.Style> + <Style TargetType="Button"> + <Setter Property="IsEnabled" + Value="false" /> + <Style.Triggers> + <MultiDataTrigger> + <MultiDataTrigger.Conditions> + <Condition Binding="{Binding Path=FinishButtonEnabled}" + Value="true" /> + <Condition Binding="{Binding ElementName=ClassName, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassHeaderFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassSourceFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=UiFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=QrcFile, + Path=(Validation.HasError)}" + Value="false" /> + </MultiDataTrigger.Conditions> + <Setter Property="IsEnabled" + Value="true" /> + </MultiDataTrigger> + </Style.Triggers> + </Style> + </Button.Style> + </Button> + <Button Click="OnCancelButtonClick" + MinWidth="75" + Margin="10,0,0,0" + Name="CancelButton" + IsEnabled="{Binding Path=CancelButtonEnabled}" + IsCancel="True">_Cancel</Button> + </StackPanel> + </Grid> + </Grid> +</common:WizardPage> diff --git a/QtVsTools.Wizards/Common/GuiPage.xaml.cs b/QtVsTools.Wizards/Common/GuiPage.xaml.cs new file mode 100644 index 0000000..764ca09 --- /dev/null +++ b/QtVsTools.Wizards/Common/GuiPage.xaml.cs @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Windows; +using System.Windows.Controls; + +namespace QtVsTools.Wizards.Common +{ + public partial class GuiPage : WizardPage + { + public bool IsClassWizardPage { get; set; } = false; + public Visibility ClassPageVisible => IsClassWizardPage ? Visibility.Hidden : Visibility.Visible; + public Visibility QObjectMacro => IsClassWizardPage ? Visibility.Visible : Visibility.Collapsed; + + public GuiPage() + { + InitializeComponent(); + DataContext = this; + UpdateFileNames(); + } + + private void OnClassNameChanged(object sender, TextChangedEventArgs e) + { + UpdateFileNames(); + } + + private void OnLowerCaseFileNamesClick(object sender, RoutedEventArgs e) + { + UpdateFileNames(); + } + + private void UpdateFileNames() + { + var filename = ClassName.Text; + if (LowerCaseFileNames.IsChecked.GetValueOrDefault()) + filename = filename.ToLower(); + + // support namespaces in class name + var index = filename.LastIndexOf(@":", System.StringComparison.Ordinal); + if (index >= 0) + filename = filename.Substring(index + 1); + + ClassHeaderFile.Text = filename + @".h"; + ClassSourceFile.Text = filename + @".cpp"; + UiFile.Text = filename + @".ui"; + QrcFile.Text = filename + @".qrc"; + } + } +} diff --git a/QtVsTools.Wizards/Common/UiClassInclusion.cs b/QtVsTools.Wizards/Common/UiClassInclusion.cs new file mode 100644 index 0000000..b99c71f --- /dev/null +++ b/QtVsTools.Wizards/Common/UiClassInclusion.cs @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +namespace QtVsTools.Wizards.Common +{ + public enum UiClassInclusion + { + Member, + MemberPointer, + MultipleInheritance + } +} diff --git a/QtVsTools.Wizards/Common/WizardData.cs b/QtVsTools.Wizards/Common/WizardData.cs new file mode 100644 index 0000000..8424f5e --- /dev/null +++ b/QtVsTools.Wizards/Common/WizardData.cs @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; + +namespace QtVsTools.Wizards.Common +{ + using ProjectWizard; + + public class WizardData + { + public WizardData() + { + Modules = new List<string>(); + DefaultModules = new List<string>(); + } + + public string ClassName { get; set; } + public string BaseClass { get; set; } + public string PluginClass { get; set; } + public string ConstructorSignature { get; set; } + + public string ClassHeaderFile { get; set; } + public string ClassSourceFile { get; set; } + public string PluginHeaderFile { get; set; } + public string PluginSourceFile { get; set; } + + public string UiFile { get; set; } + public string QrcFile { get; set; } + + private List<string> Modules { get; } + public List<string> DefaultModules { get; set; } + + public bool AddDefaultAppIcon { get; set; } + public bool CreateStaticLibrary { get; set; } + public bool UsePrecompiledHeader { get; set; } + public bool InsertQObjectMacro { get; set; } + public bool LowerCaseFileNames { get; set; } + public UiClassInclusion UiClassInclusion { get; set; } + + public IEnumerable<IWizardConfiguration> Configs { get; set; } + } +} diff --git a/QtVsTools.Wizards/Common/WizardIntroPage.xaml b/QtVsTools.Wizards/Common/WizardIntroPage.xaml new file mode 100644 index 0000000..5db4608 --- /dev/null +++ b/QtVsTools.Wizards/Common/WizardIntroPage.xaml @@ -0,0 +1,102 @@ +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2016 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + +<common:WizardPage x:Class="QtVsTools.Wizards.Common.WizardIntroPage" + xmlns:common="clr-namespace:QtVsTools.Wizards.Common" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + KeepAlive="True" + mc:Ignorable="d" + d:DesignHeight="445" + d:DesignWidth="585"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Image Grid.Column="0" + HorizontalAlignment="Center" + Source="/QtVsTools.Wizards;component/Resources/Qt-logo-small.png" + VerticalAlignment="Top" + Margin="0,25,0,0" + RenderTransformOrigin="1,0"> + <Image.RenderTransform> + <TransformGroup> + <ScaleTransform ScaleY="0.86" + ScaleX="0.86" /> + </TransformGroup> + </Image.RenderTransform> + </Image> + <Grid Grid.Column="1" + Margin="25,25,10,0"> + <Grid.RowDefinitions> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock TextWrapping="Wrap" + Grid.Row="0"> + <Run FontWeight="Bold" + Text="{Binding Path=Header}" /> + <LineBreak /> + <LineBreak /> + <Run Text="{Binding Path=Message}" /> + </TextBlock> + <StackPanel HorizontalAlignment="Right" + Orientation="Horizontal" + Grid.Row="1" + Margin="0,0,0,10"> + <Button Click="OnPreviousButtonClick" + Name="PreviousButton" + IsEnabled="{Binding Path=PreviousButtonEnabled}" + MinWidth="75">< _Previous</Button> + <Button MinWidth="75" + Name="NextButton" + Click="OnNextButtonClick" + IsEnabled="{Binding Path=NextButtonEnabled}" + Margin="10,0,0,0">_Next ></Button> + <Button MinWidth="75" + Click="OnFinishButtonClick" + Margin="10,0,0,0" + IsDefault="True" + IsEnabled="{Binding Path=FinishButtonEnabled}" + Name="FinishButton" + VerticalAlignment="Bottom">_Finish</Button> + <Button Click="OnCancelButtonClick" + MinWidth="75" + Margin="10,0,0,0" + Name="CancelButton" + IsEnabled="{Binding Path=CancelButtonEnabled}" + IsCancel="True">_Cancel</Button> + </StackPanel> + </Grid> + </Grid> +</common:WizardPage> diff --git a/QtVsTools.Wizards/Common/WizardIntroPage.xaml.cs b/QtVsTools.Wizards/Common/WizardIntroPage.xaml.cs new file mode 100644 index 0000000..5bee6ff --- /dev/null +++ b/QtVsTools.Wizards/Common/WizardIntroPage.xaml.cs @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +namespace QtVsTools.Wizards.Common +{ + public partial class WizardIntroPage : WizardPage + { + public WizardIntroPage() + { + InitializeComponent(); + DataContext = this; + } + } +} diff --git a/QtVsTools.Wizards/Common/WizardPage.cs b/QtVsTools.Wizards/Common/WizardPage.cs new file mode 100644 index 0000000..e3959ae --- /dev/null +++ b/QtVsTools.Wizards/Common/WizardPage.cs @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Windows; +using System.Windows.Navigation; + +namespace QtVsTools.Wizards.Common +{ + public class WizardPage : PageFunction<WizardResult> + { + public string Header { get; set; } + public string Message { get; set; } + + public WizardData Data { get; set; } + public WizardWindow Wizard { get; set; } + + public bool PreviousButtonEnabled { get; set; } + public bool NextButtonEnabled { get; set; } + public bool FinishButtonEnabled { get; set; } + public bool CancelButtonEnabled { get; set; } + + public event EventHandler NavigateForward; + public event EventHandler NavigatedBackward; + + public event ReturnEventHandler<WizardResult> ReturnEx; + public void OnReturnEx(ReturnEventArgs<WizardResult> e) + { + if (ReturnEx != null) + ReturnEx.Invoke(this, e); + } + + protected virtual void OnPreviousButtonClick(object sender, RoutedEventArgs e) + { + if (NavigationService == null || !NavigationService.CanGoBack) + return; + + NavigationService.GoBack(); + OnNavigatedBackward(new EventArgs()); + } + + protected virtual void OnNextButtonClick(object sender, RoutedEventArgs e) + { + if (NavigationService == null || Wizard == null) + return; + + try { + OnNavigateForward(new EventArgs()); + } catch (InvalidOperationException) { + return; // we can't navigate any further + } + + if (!NavigationService.CanGoForward) { + Wizard.NextPage.ReturnEx += OnPageReturn; + NavigationService.Navigate(Wizard.NextPage); + } else { + NavigationService.GoForward(); + } + } + + protected virtual void OnFinishButtonClick(object sender, RoutedEventArgs e) + { + OnReturnEx(new ReturnEventArgs<WizardResult>(WizardResult.Finished)); + } + + protected virtual void OnCancelButtonClick(object sender, RoutedEventArgs e) + { + OnReturnEx(new ReturnEventArgs<WizardResult>(WizardResult.Canceled)); + OnReturn(null); + } + + protected virtual void OnNavigateForward(EventArgs e) + { + if (NavigateForward != null) + NavigateForward.Invoke(this, e); + } + + protected virtual void OnNavigatedBackward(EventArgs e) + { + if (NavigatedBackward != null) + NavigatedBackward.Invoke(this, e); + } + + private void OnPageReturn(object sender, ReturnEventArgs<WizardResult> e) + { + OnReturnEx(e); + OnReturn(null); + } + } +} diff --git a/QtVsTools.Wizards/Common/WizardResult.cs b/QtVsTools.Wizards/Common/WizardResult.cs new file mode 100644 index 0000000..96bc3f4 --- /dev/null +++ b/QtVsTools.Wizards/Common/WizardResult.cs @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +namespace QtVsTools.Wizards.Common +{ + public enum WizardResult + { + Canceled, + Finished, + Exception + } +} diff --git a/QtVsTools.Wizards/Common/WizardWindow.xaml b/QtVsTools.Wizards/Common/WizardWindow.xaml new file mode 100644 index 0000000..9b461e7 --- /dev/null +++ b/QtVsTools.Wizards/Common/WizardWindow.xaml @@ -0,0 +1,44 @@ +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2016 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + +<NavigationWindow x:Class="QtVsTools.Wizards.Common.WizardWindow" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + WindowStartupLocation="CenterOwner" + ShowInTaskbar="False" + ShowsNavigationUI="False" + Title="Wizard Window" + ResizeMode="CanResizeWithGrip" + MinHeight="480" + MinWidth="640" + Height="480" + Width="640" + MaxHeight="768" + MaxWidth="1024" /> diff --git a/QtVsTools.Wizards/Common/WizardWindow.xaml.cs b/QtVsTools.Wizards/Common/WizardWindow.xaml.cs new file mode 100644 index 0000000..95028a3 --- /dev/null +++ b/QtVsTools.Wizards/Common/WizardWindow.xaml.cs @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Windows.Navigation; + +namespace QtVsTools.Wizards.Common +{ + using Wizards.Util; + + public partial class WizardWindow : NavigationWindow, IEnumerable<WizardPage> + { + + public WizardWindow(IEnumerable<WizardPage> pages = null, string title = null) + { + InitializeComponent(); + SourceInitialized += OnSourceInitialized; + + if (title != null) + Title = title; + + Pages = new List<WizardPage>(); + + if (pages != null) { + foreach (var page in pages) + Add(page); + } + } + + public void Add(WizardPage page) + { + bool isFirstPage = (Pages.Count == 0); + page.Wizard = this; + page.NavigateForward += OnNavigateForward; + page.NavigatedBackward += OnNavigatedBackwards; + Pages.Add(page); + + if (isFirstPage) { + NextPage.ReturnEx += OnPageReturn; + Navigate(NextPage); // put on navigation stack + } + } + + public WizardPage NextPage + { + get + { + return Pages[currentPage]; + } + } + + private List<WizardPage> Pages + { + get; + } + + public IEnumerator<WizardPage> GetEnumerator() + { + return ((IEnumerable<WizardPage>)Pages).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable<WizardPage>)Pages).GetEnumerator(); + } + + private int currentPage; + + private void OnSourceInitialized(object sender, EventArgs e) + { + try { + var STYLE = -16; // see winuser.h + var hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle; + UnsafeNativeMethods.SetWindowLong(hwnd, STYLE, + NativeMethods.GetWindowLong(hwnd, STYLE) & ~(0x10000 | 0x20000)); + } catch { + // Ignore if we can't remove the buttons. + SourceInitialized -= OnSourceInitialized; + } + } + + private void OnNavigateForward(object sender, EventArgs e) + { + var tmp = currentPage + 1; + if (tmp >= Pages.Count) { + throw new InvalidOperationException(@"Current wizard page " + + @"cannot be equal or greater than pages count."); + } + currentPage++; + } + + private void OnPageReturn(object sender, ReturnEventArgs<WizardResult> e) + { + if (DialogResult == null) + DialogResult = (e.Result == WizardResult.Finished); + } + + private void OnNavigatedBackwards(object sender, EventArgs e) + { + var tmp = currentPage - 1; + if (tmp < 0) + throw new InvalidOperationException(@"Current wizard page cannot be less then 0."); + currentPage--; + } + } +} diff --git a/QtVsTools.Wizards/ItemWizard/QtClass/QtClassPage.xaml b/QtVsTools.Wizards/ItemWizard/QtClass/QtClassPage.xaml new file mode 100644 index 0000000..fe00ef0 --- /dev/null +++ b/QtVsTools.Wizards/ItemWizard/QtClass/QtClassPage.xaml @@ -0,0 +1,298 @@ +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + +<common:WizardPage x:Class="QtVsTools.Wizards.ItemWizard.QtClassPage" + xmlns:common="clr-namespace:QtVsTools.Wizards.Common" + xmlns:util="clr-namespace:QtVsTools.Wizards.Util" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + KeepAlive="True" + mc:Ignorable="d" + d:DesignHeight="445" + d:DesignWidth="585"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Image Grid.Column="0" + HorizontalAlignment="Center" + Source="/QtVsTools.Wizards;component/Resources/Qt-logo-small.png" + VerticalAlignment="Top" + Margin="0,25,0,0" + RenderTransformOrigin="1,0"> + <Image.RenderTransform> + <TransformGroup> + <ScaleTransform ScaleY="0.86" + ScaleX="0.86" /> + </TransformGroup> + </Image.RenderTransform> + </Image> + <Grid Grid.Column="1" + Margin="25,25,10,0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock TextWrapping="Wrap" + Grid.Row="0"> + <Run FontWeight="Bold" + Text="{Binding Path=Header}" /> + <LineBreak /> + <LineBreak /> + <Run Text="{Binding Path=Message}" /> + <LineBreak /> + </TextBlock> + <Grid Grid.Row="1"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid.Resources> + <Style TargetType="TextBox"> + <Style.Triggers> + <Trigger Property="Validation.HasError" + Value="true"> + <Setter Property="ToolTip" + Value="{Binding RelativeSource={RelativeSource Self}, + Path=(Validation.Errors)[0].ErrorContent}" /> + </Trigger> + </Style.Triggers> + </Style> + </Grid.Resources> + <TextBlock Grid.Row="0" + Text="Class Name:" + Margin="0,0,10,0" /> + <TextBox Grid.Row="1" + Margin="0,0,10,10" + Name="ClassName" + TextChanged="OnClassNameChanged" + TabIndex="0"> + <TextBox.Text> + <Binding Path="Data.ClassName" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:ClassNameValidationRule SupportNamespaces="True" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock TextWrapping="Wrap" + Text="Constructor signature:" + Grid.Row="2" + Margin="0,0,10,5" /> + <ComboBox Grid.Row="3" + VerticalAlignment="Top" + TabIndex="2" + IsSynchronizedWithCurrentItem="True" + Margin="0,0,10,30" + SelectedIndex="0" + Text="{Binding Path=Data.ConstructorSignature}"> + <ComboBoxItem Content="QObject *parent" + IsSelected="True" /> + <ComboBoxItem Content="QWidget *parent" /> + <ComboBoxItem Content="" /> + <ComboBox.Style> + <Style TargetType="ComboBox"> + <Style.Triggers> + <DataTrigger Binding="{Binding ElementName=BaseClass, Path=Text}" + Value=""> + <Setter Property="IsEnabled" + Value="false" /> + </DataTrigger> + </Style.Triggers> + </Style> + </ComboBox.Style> + </ComboBox> + <TextBlock TextWrapping="Wrap" + Text="Base class:" + Margin="0,0,10,0" + Grid.Column="1" /> + <TextBox Margin="0,0,0,10" + TabIndex="1" + Grid.Column="1" + Grid.Row="1" + Name="BaseClass"> + <TextBox.Text> + <Binding Path="Data.BaseClass" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:ClassNameValidationRule AllowEmptyIdentifier="True"/> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <Grid Grid.Row="4" + Grid.ColumnSpan="2"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <TextBlock Grid.Row="0" + Margin="0,0,10,5" + Text="Header (.h) file:" /> + <TextBox Grid.Row="1" + Margin="0,0,10,0" + Name="ClassHeaderFile" + TabIndex="4"> + <TextBox.Text> + <Binding Path="Data.ClassHeaderFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".h" /> + <util:FileExistsinFilterValidationRule Filter="FL_HFiles" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Row="0" + Grid.Column="1" + Margin="0,0,0,5" + Text="Source (.cpp) file:" /> + <TextBox Grid.Row="1" + Grid.Column="1" + Margin="0,0,0,00" + Name="ClassSourceFile" + TabIndex="5"> + <TextBox.Text> + <Binding Path="Data.ClassSourceFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".cpp" /> + <util:FileExistsinFilterValidationRule Filter="FL_CppFiles" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + </Grid> + <CheckBox Grid.Row="5" + Content="Lower case file names" + Name="LowerCaseFileNames" + Click="OnLowerCaseFileNamesClick" + Margin="0,20,10,5" + TabIndex="6" /> + <CheckBox Content="Insert Q_OBJECT macro" + Grid.Column="1" + Grid.Row="3" + VerticalAlignment="Center" + Margin="0,0,0,30" + TabIndex="3" + IsChecked="{Binding Path=Data.InsertQObjectMacro}"> + <CheckBox.Style> + <Style TargetType="CheckBox"> + <Style.Triggers> + <DataTrigger Binding="{Binding ElementName=BaseClass, Path=Text}" + Value=""> + <Setter Property="IsEnabled" + Value="false" /> + </DataTrigger> + </Style.Triggers> + </Style> + </CheckBox.Style> + </CheckBox> + </Grid> + <StackPanel HorizontalAlignment="Right" + Orientation="Horizontal" + Grid.Row="2" + Margin="0,0,0,10"> + <Button Click="OnPreviousButtonClick" + Name="PreviousButton" + IsEnabled="{Binding Path=PreviousButtonEnabled}" + MinWidth="75">< _Previous</Button> + <Button MinWidth="75" + Name="NextButton" + Click="OnNextButtonClick" + IsEnabled="{Binding Path=NextButtonEnabled}" + Margin="10,0,0,0">_Next ></Button> + <Button MinWidth="75" + Click="OnFinishButtonClick" + Margin="10,0,0,0" + IsDefault="True" + Name="FinishButton" + Content="_Finish" + VerticalAlignment="Bottom"> + <Button.Style> + <Style TargetType="Button"> + <Setter Property="IsEnabled" + Value="false" /> + <Style.Triggers> + <MultiDataTrigger> + <MultiDataTrigger.Conditions> + <Condition Binding="{Binding Path=FinishButtonEnabled}" + Value="true" /> + <Condition Binding="{Binding ElementName=ClassName, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=BaseClass, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassHeaderFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassSourceFile, + Path=(Validation.HasError)}" + Value="false" /> + </MultiDataTrigger.Conditions> + <Setter Property="IsEnabled" + Value="true" /> + </MultiDataTrigger> + </Style.Triggers> + </Style> + </Button.Style> + </Button> + <Button Click="OnCancelButtonClick" + MinWidth="75" + Margin="10,0,0,0" + Name="CancelButton" + IsEnabled="{Binding Path=CancelButtonEnabled}" + IsCancel="True">_Cancel</Button> + </StackPanel> + </Grid> + </Grid> +</common:WizardPage> diff --git a/QtVsTools.Wizards/ItemWizard/QtClass/QtClassPage.xaml.cs b/QtVsTools.Wizards/ItemWizard/QtClass/QtClassPage.xaml.cs new file mode 100644 index 0000000..fcc4960 --- /dev/null +++ b/QtVsTools.Wizards/ItemWizard/QtClass/QtClassPage.xaml.cs @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Windows; +using System.Windows.Controls; + +namespace QtVsTools.Wizards.ItemWizard +{ + using Wizards.Common; + + public partial class QtClassPage : WizardPage + { + public QtClassPage() + { + InitializeComponent(); + DataContext = this; + } + + private void OnClassNameChanged(object sender, TextChangedEventArgs e) + { + UpdateFileNames(); + } + + private void OnLowerCaseFileNamesClick(object sender, RoutedEventArgs e) + { + UpdateFileNames(); + } + + private void UpdateFileNames() + { + var filename = ClassName.Text; + if (LowerCaseFileNames.IsChecked.GetValueOrDefault()) + filename = filename.ToLower(); + + var index = filename.LastIndexOf(@":", System.StringComparison.Ordinal); + if (index >= 0) + filename = filename.Substring(index + 1); + + ClassHeaderFile.Text = filename + @".h"; + ClassSourceFile.Text = filename + @".cpp"; + } + } +} diff --git a/QtVsTools.Wizards/ItemWizard/QtClass/QtClassWizard.cs b/QtVsTools.Wizards/ItemWizard/QtClass/QtClassWizard.cs new file mode 100644 index 0000000..970c585 --- /dev/null +++ b/QtVsTools.Wizards/ItemWizard/QtClass/QtClassWizard.cs @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Controls; +using Microsoft.VisualStudio.Shell; +using EnvDTE; + +namespace QtVsTools.Wizards.ItemWizard +{ + using QtVsTools.Common; + using Core; + using Wizards.Common; + using Wizards.ProjectWizard; + using Wizards.Util; + + using static QtVsTools.Common.EnumExt; + + public sealed class QtClassWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => Options.ConsoleSystem; + + enum NewClass + { + [String("safeitemname")] SafeItemName, + [String("sourcefilename")] SourceFileName, + [String("headerfilename")] HeaderFileName + } + + enum NewQtItem + { + [String("classname")] ClassName, + [String("baseclass")] BaseClass, + [String("include")] Include, + [String("qobject")] QObject, + [String("baseclassdecl")] BaseClassDecl, + [String("signature")] Signature, + [String("baseclassinclude")] BaseClassInclude, + [String("baseclasswithparent")] BaseClassWithParent + } + + enum Meta + { + [String("namespacebegin")] NamespaceBegin, + [String("namespaceend")] NamespaceEnd + } + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new WizardData + { + InsertQObjectMacro = true, + LowerCaseFileNames = false, + UsePrecompiledHeader = false, + DefaultModules = new List<string> { "core" } + }); + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt Class Wizard") + { + new WizardIntroPage + { + Data = WizardData, + Header = @"Welcome to the Qt Class Wizard", + Message = @"This wizard will add a new Qt class to your project. The " + + @"wizard creates a .h and .cpp file." + System.Environment.NewLine + + System.Environment.NewLine + "To continue, click Next.", + PreviousButtonEnabled = false, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new QtClassPage { + Data = WizardData, + Header = @"Welcome to the Qt Class Wizard", + Message = @"This wizard will add a new Qt class to your project. The " + + @"wizard creates a .h and .cpp file.", + PreviousButtonEnabled = true, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true + } + }); + + protected override void BeforeWizardRun() + { + var className = Parameter[NewClass.SafeItemName]; + className = Regex.Replace(className, @"[^a-zA-Z0-9_]", string.Empty); + className = Regex.Replace(className, @"^[\d-]*\s*", string.Empty); + var result = new Util.ClassNameValidationRule().Validate(className, null); + if (result != ValidationResult.ValidResult) + className = @"QtClass"; + + WizardData.ClassName = className; + WizardData.BaseClass = @"QObject"; + WizardData.ClassHeaderFile = className + @".h"; + WizardData.ClassSourceFile = className + @".cpp"; + WizardData.ConstructorSignature = "QObject *parent"; + + Parameter[NewQtItem.QObject] = ""; + Parameter[NewQtItem.BaseClassDecl] = ""; + Parameter[NewQtItem.Signature] = ""; + Parameter[NewQtItem.BaseClassInclude] = ""; + Parameter[NewQtItem.BaseClassWithParent] = ""; + } + + protected override void BeforeTemplateExpansion() + { + Parameter[NewClass.SourceFileName] = WizardData.ClassSourceFile; + Parameter[NewClass.HeaderFileName] = WizardData.ClassHeaderFile; + + var array = WizardData.ClassName.Split(new[] { "::" }, + StringSplitOptions.RemoveEmptyEntries); + var className = array.LastOrDefault(); + var baseClass = WizardData.BaseClass; + + Parameter[NewQtItem.ClassName] = className; + Parameter[NewQtItem.BaseClass] = baseClass; + + var include = new StringBuilder(); + var pro = HelperFunctions.GetSelectedQtProject(Dte); + if (pro != null) { + var qtProject = QtProject.Create(pro); + if (qtProject != null && qtProject.UsesPrecompiledHeaders()) { + include.AppendLine(string.Format("#include \"{0}\"", qtProject + .GetPrecompiledHeaderThrough())); + } + } + include.AppendLine(string.Format("#include \"{0}\"", WizardData.ClassHeaderFile)); + Parameter[NewQtItem.Include] = FormatParam(include); + + if (!string.IsNullOrEmpty(baseClass)) { + Parameter[NewQtItem.QObject] = WizardData.InsertQObjectMacro + ? "\r\n Q_OBJECT\r\n" : ""; + Parameter[NewQtItem.BaseClassDecl] = " : public " + baseClass; + Parameter[NewQtItem.Signature] = WizardData.ConstructorSignature; + Parameter[NewQtItem.BaseClassInclude] = "#include <" + baseClass + ">\r\n\r\n"; + Parameter[NewQtItem.BaseClassWithParent] = string.IsNullOrEmpty(WizardData + .ConstructorSignature) ? "" : "\r\n : " + baseClass + "(parent)"; + } + + string nsBegin = string.Empty, nsEnd = string.Empty; + for (var i = 0; i < array.Length - 1; ++i) { + nsBegin += "namespace " + array[i] + " {\r\n"; + nsEnd = "} // namespace " + array[i] + "\r\n" + nsEnd; + } + Parameter[Meta.NamespaceBegin] = nsBegin; + Parameter[Meta.NamespaceEnd] = nsEnd; + } + + protected override void Expand() + { + ThreadHelper.ThrowIfNotOnUIThread(); + VCRulePropertyStorageHelper.SetQtModules(Dte, WizardData.DefaultModules); + } + + public override void ProjectItemFinishedGenerating(ProjectItem projectItem) + { + ThreadHelper.ThrowIfNotOnUIThread(); + QtProject.AdjustWhitespace(Dte, projectItem.Properties.Item("FullPath").Value.ToString()); + } + } +} diff --git a/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml b/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml new file mode 100644 index 0000000..2f707b2 --- /dev/null +++ b/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml @@ -0,0 +1,149 @@ +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + +<common:WizardPage x:Class="QtVsTools.Wizards.ItemWizard.TranslationPage" + xmlns:common="clr-namespace:QtVsTools.Wizards.Common" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + KeepAlive="True" + mc:Ignorable="d" + d:DesignHeight="445" + d:DesignWidth="585" > + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + + <Image Grid.Column="0" + HorizontalAlignment="Center" + Source="/QtVsTools.Wizards;component/Resources/Qt-logo-small.png" + VerticalAlignment="Top" + Margin="0,25,0,0" + RenderTransformOrigin="1,0"> + <Image.RenderTransform> + <TransformGroup> + <ScaleTransform ScaleY="0.86" + ScaleX="0.86" /> + </TransformGroup> + </Image.RenderTransform> + </Image> + + <Grid Grid.Column="1" + Margin="25,25,25,0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock TextWrapping="Wrap" + Grid.Row="0"> + <Run FontWeight="Bold" + Text="{Binding Path=Header}" /> + <LineBreak /> + <LineBreak /> + <Run Text="{Binding Path=Message}" /> + <LineBreak /> + </TextBlock> + + <Grid Grid.Row="1" + Margin="0,20,0,20"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock Grid.Row="0" + Margin="0,0,0,5" + Text="Select a Language:" /> + <Grid Grid.Row="1"> + <Grid Name="searchControlHost" /> + </Grid> + <ListBox Grid.Row="2" + Margin="0,10,0,8" + Name="LanguageListBox" + DisplayMemberPath="Value" + SelectedValuePath="Key" + ItemsSource="{Binding Path=Data.CultureInfos}" + SelectedValue="{Binding Path=Data.CultureInfoName}" + SelectionChanged="OnLanguageBoxSelectionChanged" /> + <TextBlock Grid.Row="3" + Margin="0,0,0,5" + Text="Save as:"/> + <Grid Grid.Row="4"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="Auto" /> + </Grid.ColumnDefinitions> + <TextBox Text="{Binding Path=Data.TsFile}"/> + <TextBlock Grid.Column="1" + Margin="5,0,0,0" + VerticalAlignment="Center"> + <Run FontWeight="Bold" + Text="{Binding Path=Data.CultureInfoName}" /> + <Run Text=".ts" /> + </TextBlock> + </Grid> + </Grid> + + <StackPanel Grid.Row="2" + HorizontalAlignment="Right" + Orientation="Horizontal" + Margin="0,0,0,10"> + <Button Click="OnPreviousButtonClick" + Name="PreviousButton" + IsEnabled="{Binding Path=PreviousButtonEnabled}" + MinWidth="75">< _Previous</Button> + <Button MinWidth="75" + Name="NextButton" + Click="OnNextButtonClick" + IsEnabled="{Binding Path=NextButtonEnabled}" + Margin="10,0,0,0">_Next ></Button> + <Button MinWidth="75" + Click="OnFinishButtonClick" + Margin="10,0,0,0" + IsDefault="True" + IsEnabled="{Binding Path=FinishButtonEnabled}" + Name="FinishButton" + VerticalAlignment="Bottom">_Finish</Button> + <Button Click="OnCancelButtonClick" + MinWidth="75" + Margin="10,0,0,0" + Name="CancelButton" + IsEnabled="{Binding Path=CancelButtonEnabled}" + IsCancel="True">_Cancel</Button> + </StackPanel> + </Grid> + </Grid> +</common:WizardPage> diff --git a/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml.cs b/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml.cs new file mode 100644 index 0000000..adcc38b --- /dev/null +++ b/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml.cs @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace QtVsTools.Wizards.ItemWizard +{ + using QtVsTools.VisualStudio; + using Wizards.Common; + + public partial class TranslationPage : WizardPage + { + private string SearchText { get; set; } + + public TranslationPage() + { + InitializeComponent(); + DataContext = this; + Loaded += OnTranslationPageLoaded; + } + + private void OnTranslationPageLoaded(object sender, RoutedEventArgs e) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var view = CollectionViewSource.GetDefaultView(LanguageListBox.ItemsSource); + view.Filter = obj => + { + if (string.IsNullOrEmpty(SearchText)) + return true; + + var item = (KeyValuePair<string, string>)obj; + return item.Value.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0; + }; + LanguageListBox.SelectedIndex = 0; + + var factory = VsServiceProvider + .GetService<SVsWindowSearchHostFactory, IVsWindowSearchHostFactory>(); + var host = factory.CreateWindowSearchHost(searchControlHost); + + host.SetupSearch(new ListBoxSearch(LanguageListBox, value => SearchText = value)); + host.Activate(); // set focus + } + + private void OnSearchBoxTextChanged(object sender, TextChangedEventArgs e) + { + CollectionViewSource.GetDefaultView(LanguageListBox.ItemsSource).Refresh(); + if (LanguageListBox.Items.Count == 1 || LanguageListBox.SelectedItem == null) + LanguageListBox.SelectedIndex = 0; + } + + private void OnLanguageBoxSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (e.RemovedItems != null && (e.AddedItems == null || e.AddedItems.Count == 0)) { + if (LanguageListBox.Items.Count != 0) + LanguageListBox.SelectedIndex = 0; + } + } + } +} diff --git a/QtVsTools.Wizards/ItemWizard/Translation/TranslationWizard.cs b/QtVsTools.Wizards/ItemWizard/Translation/TranslationWizard.cs new file mode 100644 index 0000000..0c6c8c5 --- /dev/null +++ b/QtVsTools.Wizards/ItemWizard/Translation/TranslationWizard.cs @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Microsoft.VisualStudio.Shell; +using EnvDTE; + +namespace QtVsTools.Wizards.ItemWizard +{ + using QtVsTools.Common; + using Core; + using Wizards.Common; + using Wizards.ProjectWizard; + using Wizards.Util; + + using static QtVsTools.Common.EnumExt; + + public sealed class TsWizardData : WizardData + { + public string TsFile { get; set; } + public string CultureInfoName { get; set; } + public List<KeyValuePair<string, string>> CultureInfos { get; set; } + } + + public sealed class TranslationWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => Options.ConsoleSystem | Options.GUISystem; + + enum NewTranslationItem + { + [String("safeitemname")] SafeItemName, + [String("tsfilename")] TsFileName, + [String("cultureinfoname")] CultureInfoName + } + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new TsWizardData + { + DefaultModules = new List<string> { "core"} + }); + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt Translation File Wizard") + { + new TranslationPage + { + Data = WizardData, + Header = @"Welcome to the Qt Translation File Wizard", + Message = @"This wizard will add a new Qt empty translation file to your " + + @"project. The wizard creates a .ts for the selected language.", + PreviousButtonEnabled = false, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true + }, + }); + + protected override void BeforeWizardRun() + { + var tmp = WizardData as TsWizardData; + tmp.TsFile = Parameter[NewTranslationItem.SafeItemName]; + tmp.CultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures) + .ToDictionary( + mc => mc.Name.Replace("-", "_"), + mc => mc.EnglishName, + StringComparer.OrdinalIgnoreCase + ).OrderBy(item => item.Value).ToList(); + } + + protected override void BeforeTemplateExpansion() + { + var tmp = WizardData as TsWizardData; + Parameter[NewTranslationItem.CultureInfoName] = tmp.CultureInfoName; + Parameter[NewTranslationItem.TsFileName] = tmp.TsFile + "_" + tmp.CultureInfoName + ".ts"; + } + + protected override void Expand() + { + ThreadHelper.ThrowIfNotOnUIThread(); + VCRulePropertyStorageHelper.SetQtModules(Dte, WizardData.DefaultModules); + } + + public override void ProjectItemFinishedGenerating(ProjectItem projectItem) + { + ThreadHelper.ThrowIfNotOnUIThread(); + QtProject.AdjustWhitespace(Dte, projectItem.Properties.Item("FullPath").Value.ToString()); + } + } +} diff --git a/QtVsTools.Wizards/ItemWizard/WidgetsClass/WidgetsClassWizard.cs b/QtVsTools.Wizards/ItemWizard/WidgetsClass/WidgetsClassWizard.cs new file mode 100644 index 0000000..8fc0d97 --- /dev/null +++ b/QtVsTools.Wizards/ItemWizard/WidgetsClass/WidgetsClassWizard.cs @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Controls; +using Microsoft.VisualStudio.Shell; +using EnvDTE; + +namespace QtVsTools.Wizards.ItemWizard +{ + using QtVsTools.Common; + using Core; + using Wizards.Common; + using Wizards.ProjectWizard; + using Wizards.Util; + + using static QtVsTools.Common.EnumExt; + + public sealed class WidgetsClassWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => Options.GUISystem; + + enum NewClass + { + [String("safeitemname")] SafeItemName, + [String("sourcefilename")] SourceFileName, + [String("headerfilename")] HeaderFileName, + [String("uifilename")] UiFileName + } + + enum NewWidgetsItem + { + [String("classname")] ClassName, + [String("baseclass")] BaseClass, + [String("include")] Include, + [String("qobject")] QObject, + [String("ui_hdr")] UiHeaderName, + [String("centralwidget")] CentralWidget, + [String("forward_declare_class")] ForwardDeclClass, + [String("multiple_inheritance")] MultipleInheritance, + [String("ui_classname")] UiClassName, + [String("member")] Member + } + + enum Meta + { + [String("namespacebegin")] NamespaceBegin, + [String("operator")] Operator, + [String("asterisk")] Asterisk, + [String("semicolon")] Semicolon, + [String("new")] New, + [String("delete")] Delete, + [String("namespaceend")] NamespaceEnd + } + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new WizardData + { + InsertQObjectMacro = true, + LowerCaseFileNames = false, + UsePrecompiledHeader = false, + DefaultModules = new List<string> { "core", "gui", "widgets" } + }); + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt Widgets Class Wizard") + { + new WizardIntroPage + { + Data = WizardData, + Header = @"Welcome to the Qt Widgets Class Wizard", + Message = @"This wizard will add a new Qt Widgets class to your project. " + + @"The wizard creates a .h and .cpp file. It also creates a new " + + @"empty form." + System.Environment.NewLine + + System.Environment.NewLine + "To continue, click Next.", + PreviousButtonEnabled = false, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new GuiPage + { + Data = WizardData, + IsClassWizardPage = true, + Header = @"Welcome to the Qt Widgets Class Wizard", + Message = @"This wizard will add a new Qt Widgets class to your project. " + + @"The wizard creates a .h and .cpp file. It also creates a new " + + @"empty form.", + PreviousButtonEnabled = true, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true + } + }); + + protected override void BeforeWizardRun() + { + var className = Parameter[NewClass.SafeItemName]; + className = Regex.Replace(className, @"[^a-zA-Z0-9_]", string.Empty); + className = Regex.Replace(className, @"^[\d-]*\s*", string.Empty); + var result = new Util.ClassNameValidationRule().Validate(className, null); + if (result != ValidationResult.ValidResult) + className = @"QtWidgetsClass"; + + WizardData.ClassName = className; + WizardData.BaseClass = @"QMainWindow"; + WizardData.ClassHeaderFile = className + @".h"; + WizardData.ClassSourceFile = className + @".cpp"; + WizardData.UiFile = WizardData.ClassName + @".ui"; + WizardData.QrcFile = WizardData.ClassName + @".qrc"; + WizardData.UiClassInclusion = UiClassInclusion.Member; + + Parameter[NewWidgetsItem.ForwardDeclClass] = ""; + Parameter[NewWidgetsItem.MultipleInheritance] = ""; + Parameter[NewWidgetsItem.UiClassName] = ""; + Parameter[NewWidgetsItem.Member] = "ui"; + + Parameter[Meta.Asterisk] =""; + Parameter[Meta.Operator] = "."; + Parameter[Meta.Semicolon] = ";"; + Parameter[Meta.New] = ""; + Parameter[Meta.Delete] = ""; + } + + protected override void BeforeTemplateExpansion() + { + Parameter[NewClass.SourceFileName] = WizardData.ClassSourceFile; + Parameter[NewClass.HeaderFileName] = WizardData.ClassHeaderFile; + Parameter[NewClass.UiFileName] = WizardData.UiFile; + + var array = WizardData.ClassName.Split(new[] { "::" }, + StringSplitOptions.RemoveEmptyEntries); + var className = array.LastOrDefault(); + + Parameter[NewWidgetsItem.ClassName] = className; + Parameter[NewWidgetsItem.BaseClass] = WizardData.BaseClass; + + var include = new StringBuilder(); + var pro = HelperFunctions.GetSelectedQtProject(Dte); + if (pro != null) { + var qtProject = QtProject.Create(pro); + if (qtProject != null && qtProject.UsesPrecompiledHeaders()) { + include.AppendLine(string.Format("#include \"{0}\"", qtProject + .GetPrecompiledHeaderThrough())); + } + } + include.AppendLine(string.Format("#include \"{0}\"", WizardData.ClassHeaderFile)); + Parameter[NewWidgetsItem.Include] = FormatParam(include); + + Parameter[NewWidgetsItem.QObject] = WizardData.InsertQObjectMacro + ? "\r\n Q_OBJECT\r\n" : ""; + + Parameter[NewWidgetsItem.UiHeaderName] = string.Format("ui_{0}.h", + Path.GetFileNameWithoutExtension(WizardData.UiFile)); + + if (WizardData.BaseClass == "QMainWindow") { + Parameter[NewWidgetsItem.CentralWidget] = FormatParam( + @" <widget class=""QMenuBar"" name=""menuBar"" />" + + @" <widget class=""QToolBar"" name=""mainToolBar"" />" + + @" <widget class=""QWidget"" name=""centralWidget"" />" + + @" <widget class=""QStatusBar"" name=""statusBar"" />" + ); + } + + switch (WizardData.UiClassInclusion) { + case UiClassInclusion.MemberPointer: + Parameter[NewWidgetsItem.ForwardDeclClass] = + string.Format( + "\r\nQT_BEGIN_NAMESPACE\r\n" + + "namespace Ui {{ class {0}Class; }};\r\n" + + "QT_END_NAMESPACE\r\n", className + ); + Parameter[Meta.Asterisk] = "*"; + Parameter[Meta.Operator] = "->"; + Parameter[Meta.New] = string.Format("\r\n , {0}(new Ui::{1}Class())", + Parameter[NewWidgetsItem.Member], className); + Parameter[Meta.Delete] = string.Format("\r\n delete {0};\r\n", + Parameter[NewWidgetsItem.Member]); + goto case UiClassInclusion.Member; + case UiClassInclusion.Member: + Parameter[NewWidgetsItem.UiClassName] = string.Format("Ui::{0}Class", className); + break; + case UiClassInclusion.MultipleInheritance: + Parameter[NewWidgetsItem.MultipleInheritance] = + string.Format(", public Ui::{0}Class", className); + Parameter[NewWidgetsItem.Member] = ""; + Parameter[Meta.Operator] = ""; + Parameter[Meta.Semicolon] = ""; + break; + } + + string nsBegin = string.Empty, nsEnd = string.Empty; + for (var i = 0; i < array.Length - 1; ++i) { + nsBegin += "namespace " + array[i] + " {\r\n"; + nsEnd = "} // namespace " + array[i] + "\r\n" + nsEnd; + } + Parameter[Meta.NamespaceBegin] = nsBegin; + Parameter[Meta.NamespaceEnd] = nsEnd; + } + + protected override void Expand() + { + ThreadHelper.ThrowIfNotOnUIThread(); + VCRulePropertyStorageHelper.SetQtModules(Dte, WizardData.DefaultModules); + } + + public override void ProjectItemFinishedGenerating(ProjectItem projectItem) + { + ThreadHelper.ThrowIfNotOnUIThread(); + QtProject.AdjustWhitespace(Dte, projectItem.Properties.Item("FullPath").Value.ToString()); + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/ConfigPage.xaml b/QtVsTools.Wizards/ProjectWizard/ConfigPage.xaml new file mode 100644 index 0000000..034113e --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/ConfigPage.xaml @@ -0,0 +1,298 @@ +<!-- +***************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +***************************************************************************** +--> +<common:WizardPage x:Class="QtVsTools.Wizards.ProjectWizard.ConfigPage" + xmlns:common="clr-namespace:QtVsTools.Wizards.Common" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" KeepAlive="True" + mc:Ignorable="d" d:DesignHeight="445" d:DesignWidth="585"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Image Grid.Column="0" HorizontalAlignment="Center" + Source="/QtVsTools.Wizards;component/Resources/Qt-logo-small.png" VerticalAlignment="Top" + Margin="0,25,0,0" RenderTransformOrigin="1,0"> + <Image.RenderTransform> + <TransformGroup> + <ScaleTransform ScaleY="0.86" ScaleX="0.86" /> + </TransformGroup> + </Image.RenderTransform> + </Image> + <Grid Grid.Column="1" Margin="25,25,10,0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock TextWrapping="Wrap" Grid.Row="0"> + <Run FontWeight="Bold" Text="{Binding Path=Header}" /> + <LineBreak /> + <LineBreak /> + <Run Text="{Binding Path=Message}" /> + <LineBreak /> + </TextBlock> + <Grid Grid.Row="1" Name="ModuleGrid"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid.Resources> + <Style TargetType="ListBox"> + <Setter Property="Background" Value="Transparent" /> + </Style> + </Grid.Resources> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <DataGrid Margin="0,20,0,0" Name="ConfigTable" AutoGenerateColumns="False" + IsReadOnly="True" BorderThickness="1" BorderBrush="LightGray" + GridLinesVisibility="All" HorizontalGridLinesBrush="LightGray" + VerticalGridLinesBrush="LightGray" CanUserReorderColumns="False" + CanUserSortColumns="False" CanUserResizeRows="False" RowHeaderWidth="0" + FrozenColumnCount="1" Grid.Row="0"> + <DataGrid.Resources> + <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" /> + <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" /> + </DataGrid.Resources> + <DataGrid.CellStyle> + <Style TargetType="DataGridCell"> + <Setter Property="BorderThickness" Value="0" /> + <Setter Property="FocusVisualStyle" Value="{x:Null}" /> + </Style> + </DataGrid.CellStyle> + <DataGrid.Columns> + <DataGridTemplateColumn Header="Configuration"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <Button Cursor="Hand" ButtonBase.Click="RemoveConfig_Click"> + <Button.Template> + <ControlTemplate TargetType="Button"> + <Grid HorizontalAlignment="Center" VerticalAlignment="Center" + Margin="2,0"> + <Ellipse Fill="Red" Width="13" Height="13" /> + <Rectangle Width="8" Height="2" Fill="White" /> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <Button Cursor="Hand" ButtonBase.Click="DuplicateConfig_Click"> + <Button.Template> + <ControlTemplate TargetType="Button"> + <Grid HorizontalAlignment="Center" VerticalAlignment="Center" + Margin="2,0"> + <Ellipse Fill="#FF36B31A" Width="13" Height="13" /> + <Rectangle Width="8" Height="2" Fill="White" /> + <Rectangle Width="2" Height="8" Fill="White" /> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <TextBox Text="{Binding Name}" Margin="2,8" BorderThickness="0" + Background="Transparent" TextBoxBase.TextChanged="Name_TextChanged"> + <TextBox.Resources> + <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" + Color="LimeGreen" /> + </TextBox.Resources> + </TextBox> + </StackPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="Qt Version"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <ComboBox Text="{Binding QtVersionName}" IsEditable="True" Height="22" + SelectedIndex="0" BorderThickness="0" Background="Transparent" + FrameworkElement.Loaded="QtVersion_ComboBox_Loaded" + TextBoxBase.TextChanged="QtVersion_TextChanged"> + <ComboBox.Resources> + <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" + Color="LimeGreen" /> + </ComboBox.Resources> + </ComboBox> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="Target"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <ComboBox Text="{Binding Target}" IsEditable="True" Height="22" + SelectedIndex="0" BorderThickness="0" Background="Transparent" + FrameworkElement.Loaded="Target_ComboBox_Loaded" + TextBoxBase.TextChanged="Target_TextChanged"> + <ComboBox.Resources> + <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" + Color="LimeGreen" /> + </ComboBox.Resources> + </ComboBox> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="Platform"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <ComboBox Text="{Binding Platform}" IsEditable="True" Height="22" + SelectedIndex="0" BorderThickness="0" Background="Transparent" + FrameworkElement.Loaded="Platform_ComboBox_Loaded" + TextBoxBase.TextChanged="Platform_TextChanged"> + <ComboBox.Resources> + <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" + Color="LimeGreen" /> + </ComboBox.Resources> + </ComboBox> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="Debug"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" + IsChecked="{Binding IsDebug}" Click="Debug_Click" /> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="Qt Modules" Width="*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <ComboBox Name="Modules"> + <ComboBox.Template> + <ControlTemplate TargetType="ComboBox"> + <Grid> + <ListView Name="SelectedModules" ItemsSource="{Binding SelectedModules}" + ScrollViewer.HorizontalScrollBarVisibility="Disabled" + BorderThickness="0" IsEnabled="False"> + <ListView.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel /> + </ItemsPanelTemplate> + </ListView.ItemsPanel> + <ListView.ItemTemplate> + <DataTemplate> + <Grid> + <Rectangle Fill="#FF36B31A" RadiusX="4" RadiusY="4" Height="20" /> + <Label Content="{Binding Name}" Foreground="White" /> + </Grid> + </DataTemplate> + </ListView.ItemTemplate> + </ListView> + <ToggleButton Opacity="0" Name="ToggleButton" Focusable="false" + IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" + ClickMode="Press" Cursor="Hand" /> + <Popup Name="Popup" Placement="Bottom" + IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" + Focusable="False" PopupAnimation="Slide"> + <Grid Name="DropDown" SnapsToDevicePixels="True" + MinWidth="{TemplateBinding ActualWidth}" + MaxHeight="{TemplateBinding MaxDropDownHeight}"> + <Border x:Name="DropDownBorder" Background="White" + BorderThickness="2" BorderBrush="Gray" /> + <ListView Name="PopupListBox" BorderThickness="0" + ScrollViewer.VerticalScrollBarVisibility="Disabled" + ScrollViewer.HorizontalScrollBarVisibility="Auto" + Margin="10,10,10,10" ItemsSource="{Binding AllModules}"> + <ListView.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Vertical" /> + </ItemsPanelTemplate> + </ListView.ItemsPanel> + <ListView.ItemTemplate> + <DataTemplate> + <CheckBox Content="{Binding Name}" + IsChecked="{Binding IsSelected}" + IsEnabled="{Binding IsEnabled}" VerticalAlignment="Center" + VerticalContentAlignment="Center" Click="Module_Click" + Margin="4"> + <CheckBox.ContentTemplate> + <DataTemplate> + <Grid> + <Rectangle Fill="#FF36B31A" RadiusX="4" RadiusY="4" + Height="20" /> + <Label Content="{Binding}" Foreground="White" /> + </Grid> + </DataTemplate> + </CheckBox.ContentTemplate> + </CheckBox> + </DataTemplate> + </ListView.ItemTemplate> + <ListView.ItemContainerStyle> + <Style TargetType="ListViewItem"> + <Style.Setters> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="ListViewItem"> + <ContentPresenter + HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" + VerticalAlignment="{TemplateBinding VerticalContentAlignment}" + SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style.Setters> + </Style> + </ListView.ItemContainerStyle> + </ListView> + </Grid> + </Popup> + </Grid> + </ControlTemplate> + </ComboBox.Template> + </ComboBox> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + </DataGrid.Columns> + </DataGrid> + <StackPanel Name="ErrorPanel" Orientation="Horizontal" Grid.Row="1" Margin="0,10" + Visibility="Hidden"> + <Image Name="ErrorIcon" Height="16" Width="16" Margin="5,0" /> + <Label Name="ErrorMsg" Foreground="Red" /> + </StackPanel> + </Grid> + </Grid> + <StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Grid.Row="2" + Margin="0,0,0,10"> + <Button Click="OnPreviousButtonClick" Name="PreviousButton" + IsEnabled="{Binding Path=PreviousButtonEnabled}" MinWidth="75">< _Previous</Button> + <Button MinWidth="75" Name="NextButton" Click="OnNextButtonClick" + IsEnabled="{Binding Path=NextButtonEnabled}" Margin="10,0,0,0">_Next ></Button> + <Button MinWidth="75" Click="OnFinishButtonClick" Margin="10,0,0,0" IsDefault="True" + IsEnabled="{Binding Path=FinishButtonEnabled}" Name="FinishButton" + VerticalAlignment="Bottom">_Finish</Button> + <Button Click="OnCancelButtonClick" MinWidth="75" Margin="10,0,0,0" Name="CancelButton" + IsEnabled="{Binding Path=CancelButtonEnabled}" IsCancel="True">_Cancel</Button> + </StackPanel> + </Grid> + </Grid> +</common:WizardPage> diff --git a/QtVsTools.Wizards/ProjectWizard/ConfigPage.xaml.cs b/QtVsTools.Wizards/ProjectWizard/ConfigPage.xaml.cs new file mode 100644 index 0000000..408cc45 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/ConfigPage.xaml.cs @@ -0,0 +1,489 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Microsoft.Win32; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using Core; + using QtVsTools.Common; + using Wizards.Common; + + public partial class ConfigPage : WizardPage + { + interface ICloneable<T> where T : ICloneable<T> + { + T Clone(); + } + + class Module : ICloneable<Module> + { + public string Name { get; set; } + public string Id { get; set; } + public bool IsSelected { get; set; } + public bool IsReadOnly { get; set; } + public bool IsEnabled => !IsReadOnly; + + public Module Clone() + { + return new Module + { + Name = Name, + Id = Id, + IsSelected = IsSelected, + IsReadOnly = IsReadOnly + }; + } + } + + class Config : ICloneable<Config>, IWizardConfiguration + { + public string Name { get; set; } + public VersionInformation QtVersion { get; set; } + public string QtVersionName { get; set; } + public string QtVersionPath { get; set; } + public string Target { get; set; } + public string Platform { get; set; } + public bool IsDebug { get; set; } + + public Dictionary<string, Module> Modules { get; set; } + + public IEnumerable<Module> AllModules + => Modules.Values.OrderBy(module => module.Name); + public IEnumerable<Module> SelectedModules + => Modules.Values.Where((Module m) => m.IsSelected); + + IEnumerable<string> IWizardConfiguration.Modules + => SelectedModules.SelectMany((Module m) => m.Id.Split(' ')); + + public Config Clone() + { + return new Config + { + Name = Name, + QtVersion = QtVersion, + QtVersionName = QtVersionName, + Target = Target, + Platform = Platform, + IsDebug = IsDebug, + Modules = AllModules + .Select((Module m) => m.Clone()) + .ToDictionary((Module m) => m.Name) + }; + } + } + + class CloneableList<T> : List<T> where T : ICloneable<T> + { + public CloneableList() : base() + { } + + public CloneableList(IEnumerable<T> collection) : base(collection) + { } + + public CloneableList<T> Clone() + { + return new CloneableList<T>(this.Select(x => x.Clone())); + } + } + + const string QT_VERSION_DEFAULT = "<Default>"; + const string QT_VERSION_BROWSE = "<Browse...>"; + + IEnumerable<string> qtVersionList = new[] { QT_VERSION_DEFAULT, QT_VERSION_BROWSE } + .Union(QtVersionManager.The().GetVersions()); + + readonly QtVersionManager qtVersionManager = QtVersionManager.The(); + readonly VersionInformation defaultQtVersionInfo; + + CloneableList<Config> defaultConfigs; + List<Config> currentConfigs; + bool initialNextButtonIsEnabled; + bool initialFinishButtonIsEnabled; + + public ConfigPage() + { + InitializeComponent(); + + string defaultQtVersionName = qtVersionManager.GetDefaultVersion(); + defaultQtVersionInfo = qtVersionManager.GetVersionInfo(defaultQtVersionName); + + ErrorIcon.Source = Imaging.CreateBitmapSourceFromHIcon( + SystemIcons.Exclamation.Handle, Int32Rect.Empty, + BitmapSizeOptions.FromEmptyOptions()); + + DataContext = this; + Loaded += OnLoaded; + } + + void OnLoaded(object sender, RoutedEventArgs e) + { + Loaded -= OnLoaded; + + qtVersionList = new[] { QT_VERSION_DEFAULT, QT_VERSION_BROWSE } + .Union(QtVersionManager.The().GetVersions()); + + if (defaultQtVersionInfo == null) { + Validate(); + return; + } + + var qtModules = QtModules.Instance.GetAvailableModules(defaultQtVersionInfo.qtMajor) + .Where((QtModule mi) => mi.Selectable) + .Select((QtModule mi) => new Module() + { + Name = mi.Name, + Id = mi.proVarQT, + IsSelected = Data.DefaultModules.Contains(mi.LibraryPrefix), + IsReadOnly = Data.DefaultModules.Contains(mi.LibraryPrefix), + }); + + defaultConfigs = new CloneableList<Config> { + new Config { + Name = "Debug", + IsDebug = true, + QtVersion = defaultQtVersionInfo, + QtVersionName = defaultQtVersionInfo.name, + Target = defaultQtVersionInfo.isWinRT() + ? ProjectTargets.WindowsStore.Cast<string>() + : ProjectTargets.Windows.Cast<string>(), + Platform = defaultQtVersionInfo.is64Bit() + ? ProjectPlatforms.X64.Cast<string>() + : ProjectPlatforms.Win32.Cast<string>(), + Modules = qtModules.ToDictionary((Module m) => m.Name), + }, + new Config { + Name = "Release", + IsDebug = false, + QtVersion = defaultQtVersionInfo, + QtVersionName = defaultQtVersionInfo.name, + Target = defaultQtVersionInfo.isWinRT() + ? ProjectTargets.WindowsStore.Cast<string>() + : ProjectTargets.Windows.Cast<string>(), + Platform = defaultQtVersionInfo.is64Bit() + ? ProjectPlatforms.X64.Cast<string>() + : ProjectPlatforms.Win32.Cast<string>(), + Modules = qtModules.ToDictionary((Module m) => m.Name), + } + }; + currentConfigs = defaultConfigs.Clone(); + ConfigTable.ItemsSource = currentConfigs; + + initialNextButtonIsEnabled = NextButton.IsEnabled; + initialFinishButtonIsEnabled = FinishButton.IsEnabled; + + Validate(); + } + + /// <summary> + /// Callback to validate selected configurations. + /// Must return an error message in case of failed validation. + /// Otherwise, return empty string or null. + /// </summary> + public Func<IEnumerable<IWizardConfiguration>, string> ValidateConfigs { get; set; } + + void Validate() + { + if (currentConfigs == null) { + ErrorMsg.Content = "Register at least one Qt version using \"Qt VS Tools\"" + + " -> \"Qt Options\"."; + ErrorPanel.Visibility = Visibility.Visible; + NextButton.IsEnabled = false; + FinishButton.IsEnabled = false; + } else if (currentConfigs // "$(Configuration)|$(Platform)" must be unique + .GroupBy((Config c) => string.Format("{0}|{1}", c.Name, c.Platform)) + .Where((IGrouping<string, Config> g) => g.Count() > 1) + .Any()) { + ErrorMsg.Content = "(Configuration, Platform) must be unique"; + ErrorPanel.Visibility = Visibility.Visible; + NextButton.IsEnabled = false; + FinishButton.IsEnabled = false; + } else if (ValidateConfigs != null + && ValidateConfigs(currentConfigs) is string errorMsg + && !string.IsNullOrEmpty(errorMsg)) { + ErrorMsg.Content = errorMsg; + ErrorPanel.Visibility = Visibility.Visible; + NextButton.IsEnabled = false; + FinishButton.IsEnabled = false; + } else { + ErrorMsg.Content = string.Empty; + ErrorPanel.Visibility = Visibility.Hidden; + NextButton.IsEnabled = initialNextButtonIsEnabled; + FinishButton.IsEnabled = initialFinishButtonIsEnabled; + } + } + + void RemoveConfig_Click(object sender, RoutedEventArgs e) + { + if (sender is Button buttonRemove + && GetBinding(buttonRemove) is Config config) { + currentConfigs.Remove(config); + if (!currentConfigs.Any()) { + currentConfigs = defaultConfigs.Clone(); + ConfigTable.ItemsSource = currentConfigs; + } + ConfigTable.Items.Refresh(); + Validate(); + } + } + + void DuplicateConfig_Click(object sender, RoutedEventArgs e) + { + if (sender is Button buttonDuplicate + && GetBinding(buttonDuplicate) is Config config) { + currentConfigs.Add(config.Clone()); + ConfigTable.Items.Refresh(); + Validate(); + } + } + + void Name_TextChanged(object sender, TextChangedEventArgs e) + { + if (sender is TextBox txt && GetBinding(txt) is Config cfg) + cfg.Name = txt.Text; + Validate(); + } + + void QtVersion_ComboBox_Loaded(object sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBoxQtVersion + && GetBinding(comboBoxQtVersion) is Config config) { + comboBoxQtVersion.IsEnabled = false; + comboBoxQtVersion.ItemsSource = qtVersionList; + comboBoxQtVersion.Text = config.QtVersionName; + comboBoxQtVersion.IsEnabled = true; + } + } + + void QtVersion_TextChanged(object sender, TextChangedEventArgs e) + { + if (sender is ComboBox comboBoxQtVersion + && comboBoxQtVersion.IsEnabled + && GetBinding(comboBoxQtVersion) is Config config + && config.QtVersionName != comboBoxQtVersion.Text) { + var oldQtVersion = config.QtVersion; + if (comboBoxQtVersion.Text == QT_VERSION_DEFAULT) { + config.QtVersion = defaultQtVersionInfo; + config.QtVersionName = defaultQtVersionInfo.name; + config.QtVersionPath = defaultQtVersionInfo.qtDir; + comboBoxQtVersion.Text = defaultQtVersionInfo.name; + } else if (comboBoxQtVersion.Text == QT_VERSION_BROWSE) { + var openFileDialog = new OpenFileDialog + { + Filter = "qmake (qmake.exe)|qmake.exe" + }; + if (openFileDialog.ShowDialog() == true) { + IEnumerable<string> binPath = Path.GetDirectoryName(openFileDialog.FileName) + .Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + string lastDirName = binPath.LastOrDefault(); + if ("bin".Equals(lastDirName, StringComparison.InvariantCultureIgnoreCase)) + binPath = binPath.Take(binPath.Count() - 1); + + var qtVersion = string.Join( + Path.DirectorySeparatorChar.ToString(), binPath); + var versionInfo = VersionInformation.Get(qtVersion); + if (versionInfo != null) { + versionInfo.name = qtVersion; + config.QtVersion = versionInfo; + config.QtVersionName = versionInfo.name; + config.QtVersionPath = config.QtVersion.qtDir; + } + } + comboBoxQtVersion.Text = config.QtVersionName; + } else if (qtVersionManager.GetVersions().Contains(comboBoxQtVersion.Text)) { + config.QtVersion = qtVersionManager.GetVersionInfo(comboBoxQtVersion.Text); + config.QtVersionName = comboBoxQtVersion.Text; + config.QtVersionPath = qtVersionManager.GetInstallPath(comboBoxQtVersion.Text); + } else { + config.QtVersion = null; + config.QtVersionName = config.QtVersionPath = comboBoxQtVersion.Text; + } + + if (oldQtVersion != config.QtVersion) { + if (config.QtVersion != null) { + config.Target = config.QtVersion.isWinRT() + ? ProjectTargets.WindowsStore.Cast<string>() + : ProjectTargets.Windows.Cast<string>(); + config.Platform = config.QtVersion.is64Bit() + ? ProjectPlatforms.X64.Cast<string>() + : ProjectPlatforms.Win32.Cast<string>(); + config.Modules = + QtModules.Instance.GetAvailableModules(config.QtVersion.qtMajor) + .Where((QtModule mi) => mi.Selectable) + .Select((QtModule mi) => new Module() + { + Name = mi.Name, + Id = mi.proVarQT, + IsSelected = Data.DefaultModules.Contains(mi.LibraryPrefix), + IsReadOnly = Data.DefaultModules.Contains(mi.LibraryPrefix), + }).ToDictionary((Module m) => m.Name); + } else if (config.QtVersionPath.StartsWith("SSH:")) { + config.Target = ProjectTargets.LinuxSSH.Cast<string>(); + } else if (config.QtVersionPath.StartsWith("WSL:")) { + config.Target = ProjectTargets.LinuxWSL.Cast<string>(); + } + ConfigTable.Items.Refresh(); + } + Validate(); + } + } + + void Target_ComboBox_Loaded(object sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBoxTarget + && GetBinding(comboBoxTarget) is Config config) { + comboBoxTarget.IsEnabled = false; + comboBoxTarget.ItemsSource = EnumExt.GetValues<string>(typeof(ProjectTargets)); + comboBoxTarget.Text = config.Target; + comboBoxTarget.IsEnabled = true; + } + } + + void Target_TextChanged(object sender, TextChangedEventArgs e) + { + if (sender is ComboBox comboBoxTarget + && comboBoxTarget.IsEnabled + && GetBinding(comboBoxTarget) is Config config + && config.Target != comboBoxTarget.Text) { + config.Target = comboBoxTarget.Text; + ConfigTable.Items.Refresh(); + Validate(); + } + } + + void Platform_ComboBox_Loaded(object sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBoxPlatform + && GetBinding(comboBoxPlatform) is Config config) { + comboBoxPlatform.IsEnabled = false; + comboBoxPlatform.ItemsSource = EnumExt.GetValues<string>(typeof(ProjectPlatforms)); + comboBoxPlatform.Text = config.Platform; + comboBoxPlatform.IsEnabled = true; + } + } + + void Platform_TextChanged(object sender, TextChangedEventArgs e) + { + if (sender is ComboBox comboBoxPlatform + && comboBoxPlatform.IsEnabled + && GetBinding(comboBoxPlatform) is Config config + && config.Platform != comboBoxPlatform.Text) { + config.Platform = comboBoxPlatform.Text; + ConfigTable.Items.Refresh(); + Validate(); + } + } + + void Debug_Click(object sender, RoutedEventArgs e) + { + if (sender is CheckBox checkBox && GetBinding(checkBox) is Config config) { + config.IsDebug = checkBox.IsChecked ?? false; + if (config.IsDebug && config.Name.EndsWith("Release")) { + config.Name = string.Format("{0}Debug", + config.Name.Substring(0, config.Name.Length - "Release".Length)); + ConfigTable.Items.Refresh(); + } else if (!config.IsDebug && config.Name.EndsWith("Debug")) { + config.Name = string.Format("{0}Release", + config.Name.Substring(0, config.Name.Length - "Debug".Length)); + ConfigTable.Items.Refresh(); + } + Validate(); + } + } + + void Module_Click(object sender, RoutedEventArgs e) + { + if (sender is CheckBox checkBoxModule + && (checkBoxModule.TemplatedParent as ContentPresenter)?.Content is Module + && GetBinding(checkBoxModule) is Config config + && FindAncestor(checkBoxModule, "Modules") is ComboBox comboBoxModules + && FindDescendant(comboBoxModules, "SelectedModules") is ListView selectedModules) { + selectedModules.ItemsSource = config.SelectedModules; + Validate(); + } + } + + protected override void OnNextButtonClick(object sender, RoutedEventArgs e) + { + Data.Configs = currentConfigs.Cast<IWizardConfiguration>(); + base.OnNextButtonClick(sender, e); + } + + protected override void OnFinishButtonClick(object sender, RoutedEventArgs e) + { + Data.Configs = currentConfigs.Cast<IWizardConfiguration>(); + base.OnFinishButtonClick(sender, e); + } + + static object GetBinding(FrameworkElement control) + { + if (control.BindingGroup == null + || control.BindingGroup.Items == null + || control.BindingGroup.Items.Count == 0) { + return null; + } + return control.BindingGroup.Items[0]; + } + + static FrameworkElement FindAncestor(FrameworkElement control, string name) + { + while (control != null && control.Name != name) { + object parent = control.Parent + ?? control.TemplatedParent + ?? VisualTreeHelper.GetParent(control); + control = parent as FrameworkElement; + } + return control; + } + + static FrameworkElement FindDescendant(FrameworkElement control, string name) + { + var stack = new Stack<FrameworkElement>(new[] { control }); + while (stack.Any()) { + control = stack.Pop(); + if (control?.Name == name && control is FrameworkElement result) + return result; + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(control); ++i) { + if (VisualTreeHelper.GetChild(control, i) is FrameworkElement child) + stack.Push(child); + } + } + return null; + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Console/ConsoleWizard.cs b/QtVsTools.Wizards/ProjectWizard/Console/ConsoleWizard.cs new file mode 100644 index 0000000..76c8365 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Console/ConsoleWizard.cs @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using QtVsTools.Common; + using Wizards.Common; + + public class ConsoleWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => Options.Application | Options.ConsoleSystem; + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new WizardData + { + DefaultModules = new List<string> { "QtCore" } + }); + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt Console Application Wizard") + { + new WizardIntroPage { + Data = WizardData, + Header = @"Welcome to the Qt Console Application Wizard", + Message = @"This wizard generates a Qt console application " + + @"project. The application derives from QCoreApplication " + + @"and does not present a GUI." + System.Environment.NewLine + + System.Environment.NewLine + "To continue, click Next.", + PreviousButtonEnabled = false, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new ConfigPage { + Data = WizardData, + Header = @"Welcome to the Qt Console Application Wizard", + Message = + @"Setup the configurations you want to include in your project. " + + @"The recommended settings for this project are selected by default.", + PreviousButtonEnabled = true, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true, + ValidateConfigs = ValidateConfigsForConsoleApp + } + }); + + string ValidateConfigsForConsoleApp(IEnumerable<IWizardConfiguration> configs) + { + foreach (var config in configs) { + if (config.Target.EqualTo(ProjectTargets.WindowsStore)) { + return string.Format( + "Console Application project not available for the '{0}' target.", + config.Target); + } + } + return string.Empty; + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Designer/DesignerPage.xaml b/QtVsTools.Wizards/ProjectWizard/Designer/DesignerPage.xaml new file mode 100644 index 0000000..1a7b71f --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Designer/DesignerPage.xaml @@ -0,0 +1,310 @@ +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2016 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + +<common:WizardPage x:Class="QtVsTools.Wizards.ProjectWizard.DesignerPage" + xmlns:common="clr-namespace:QtVsTools.Wizards.Common" + xmlns:util="clr-namespace:QtVsTools.Wizards.Util" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + KeepAlive="True" + mc:Ignorable="d" + d:DesignHeight="445" + d:DesignWidth="585"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Image Grid.Column="0" + HorizontalAlignment="Center" + Source="/QtVsTools.Wizards;component/Resources/Qt-logo-small.png" + VerticalAlignment="Top" + Margin="0,25,0,0" + RenderTransformOrigin="1,0"> + <Image.RenderTransform> + <TransformGroup> + <ScaleTransform ScaleY="0.86" + ScaleX="0.86" /> + </TransformGroup> + </Image.RenderTransform> + </Image> + <Grid Grid.Column="1" + Margin="25,25,10,0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock TextWrapping="Wrap" + Grid.Row="0"> + <Run FontWeight="Bold" + Text="{Binding Path=Header}" /> + <LineBreak /> + <LineBreak /> + <Run Text="{Binding Path=Message}" /> + <LineBreak /> + </TextBlock> + <Grid Grid.Row="1"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid.Resources> + <Style TargetType="TextBox"> + <Style.Triggers> + <Trigger Property="Validation.HasError" + Value="true"> + <Setter Property="ToolTip" + Value="{Binding RelativeSource={RelativeSource Self}, + Path=(Validation.Errors)[0].ErrorContent}" /> + </Trigger> + </Style.Triggers> + </Style> + </Grid.Resources> + <TextBlock Grid.Row="0" + Margin="0,0,10,5"> + <Run FontWeight="Bold" + Text="Custom Widget "/> + <Run Text="- Class Name:"/> + </TextBlock> + <TextBox Grid.Row="1" + Margin="0,0,10,10" + x:Name="ClassName" + TextChanged="OnClassNameChanged"> + <TextBox.Text> + <Binding Path="Data.ClassName" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:ClassNameValidationRule /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Column="1" + Grid.Row="0" + Text="Base class:" + Margin="0,0,0,5" /> + <TextBox Grid.Column="1" + Grid.Row="1" + Name="BaseClass" + Margin="0,0,0,10"> + <TextBox.Text> + <Binding Path="Data.BaseClass" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:ClassNameValidationRule AllowEmptyIdentifier="True"/> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Row="2" + Margin="0,0,10,5" + Text="Header (.h) file:" /> + <TextBox Grid.Row="3" + Margin="0,0,10,30" + Name="ClassHeaderFile"> + <TextBox.Text> + <Binding Path="Data.ClassHeaderFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".h" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Column="1" + Grid.Row="2" + Margin="0,0,0,5" + Text="Source (.cpp) file:" /> + <TextBox Grid.Column="1" + Grid.Row="3" + Margin="0,0,0,30" + Name="ClassSourceFile"> + <TextBox.Text> + <Binding Path="Data.ClassSourceFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".cpp" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Column="0" + Grid.Row="4" + Margin="0,0,0,5" + > + <Run FontWeight="Bold" + Text="Plugin"/> + <Run Text=" - Class Name:"/> + </TextBlock> + <TextBox Grid.Column="0" + Grid.Row="5" + Margin="0,0,0,10" + Name="PluginClass"> + <TextBox.Text> + <Binding Path="Data.PluginClass" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:ClassNameValidationRule /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Row="6" + Margin="0,0,10,5" + Text="Header (.h) file:" /> + <TextBox Grid.Row="7" + Margin="0,0,10,0" + Name="PluginHeaderFile"> + <TextBox.Text> + <Binding Path="Data.PluginHeaderFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".h" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Column="1" + Grid.Row="6" + Margin="0,0,0,5" + Text="Source (.cpp) file:" /> + <TextBox Grid.Column="1" + Grid.Row="7" + Margin="0" + Name="PluginSourceFile"> + <TextBox.Text> + <Binding Path="Data.PluginSourceFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".cpp" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <CheckBox Grid.Row="8" + Content="Lower case file names" + Margin="0,20,0,5" + Name="LowerCaseFileNames" + Click="OnLowerCaseFileNamesClick" /> + <CheckBox Grid.Row="9" + Content="Precompiled header" + Margin="0,10,0,0" + IsChecked="{Binding Path=Data.UsePrecompiledHeader}" /> + </Grid> + <StackPanel HorizontalAlignment="Right" + Orientation="Horizontal" + Grid.Row="2" + Margin="0,0,0,10"> + <Button Click="OnPreviousButtonClick" + Name="PreviousButton" + IsEnabled="{Binding Path=PreviousButtonEnabled}" + MinWidth="75">< _Previous</Button> + <Button MinWidth="75" + Name="NextButton" + Click="OnNextButtonClick" + IsEnabled="{Binding Path=NextButtonEnabled}" + Margin="10,0,0,0">_Next ></Button> + <Button MinWidth="75" + Click="OnFinishButtonClick" + Margin="10,0,0,0" + IsDefault="True" + Name="FinishButton" + Content="_Finish" + VerticalAlignment="Bottom"> + <Button.Style> + <Style TargetType="Button"> + <Setter Property="IsEnabled" + Value="false" /> + <Style.Triggers> + <MultiDataTrigger> + <MultiDataTrigger.Conditions> + <Condition Binding="{Binding Path=FinishButtonEnabled}" + Value="true" /> + <Condition Binding="{Binding ElementName=ClassName, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=BaseClass, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassHeaderFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassSourceFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=PluginClass, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=PluginHeaderFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=PluginSourceFile, + Path=(Validation.HasError)}" + Value="false" /> + </MultiDataTrigger.Conditions> + <Setter Property="IsEnabled" + Value="true" /> + </MultiDataTrigger> + </Style.Triggers> + </Style> + </Button.Style> + </Button> + <Button Click="OnCancelButtonClick" + MinWidth="75" + Margin="10,0,0,0" + Name="CancelButton" + IsEnabled="{Binding Path=CancelButtonEnabled}" + IsCancel="True">_Cancel</Button> + </StackPanel> + </Grid> + </Grid> +</common:WizardPage> diff --git a/QtVsTools.Wizards/ProjectWizard/Designer/DesignerPage.xaml.cs b/QtVsTools.Wizards/ProjectWizard/Designer/DesignerPage.xaml.cs new file mode 100644 index 0000000..fb1f10e --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Designer/DesignerPage.xaml.cs @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Windows; +using System.Windows.Controls; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using Wizards.Common; + + public partial class DesignerPage : WizardPage + { + public DesignerPage() + { + InitializeComponent(); + DataContext = this; + } + + private void OnClassNameChanged(object sender, TextChangedEventArgs e) + { + UpdateFileNames(); + } + + private void OnLowerCaseFileNamesClick(object sender, RoutedEventArgs e) + { + UpdateFileNames(); + } + + private void UpdateFileNames() + { + var filename = ClassName.Text; + var pluginFilename = PluginClass.Text; + if (LowerCaseFileNames.IsChecked.GetValueOrDefault()) { + filename = filename.ToLower(); + pluginFilename = pluginFilename.ToLower(); + } + + ClassHeaderFile.Text = filename + @".h"; + ClassSourceFile.Text = filename + @".cpp"; + + PluginHeaderFile.Text = pluginFilename + @".h"; + PluginSourceFile.Text = pluginFilename + @".cpp"; + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Designer/DesignerWizard.cs b/QtVsTools.Wizards/ProjectWizard/Designer/DesignerWizard.cs new file mode 100644 index 0000000..f93f677 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Designer/DesignerWizard.cs @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Controls; +using EnvDTE; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using Core; + using Legacy = Core.Legacy; + using QtVsTools.Common; + using Wizards.Common; + + using static QtVsTools.Common.EnumExt; + + public class DesignerWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => + Options.PluginProject | Options.DynamicLibrary | Options.GUISystem; + + enum NewClass + { + [String("classname")] ClassName, + [String("baseclass")] BaseClass, + [String("sourcefilename")] SourceFileName, + [String("headerfilename")] HeaderFileName, + [String("include")] Include, + } + + enum NewDesignerPlugin + { + [String("plugin_class")] ClassName, + [String("objname")] ObjectName, + [String("pluginsourcefilename")] SourceFileName, + [String("pluginheaderfilename")] HeaderFileName, + [String("plugin_json")] JsonFileName, + } + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new WizardData + { + DefaultModules = new List<string> { + "QtCore", "QtGui", "QtWidgets", "QtDesigner" + } + }); + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt Custom Designer Widget") + { + new WizardIntroPage { + Data = WizardData, + Header = @"Welcome to the Qt Custom Designer Widget", + Message = @"This wizard generates a custom designer widget which can be " + + @"used in Qt Designer or Visual Studio." + + System.Environment.NewLine + System.Environment.NewLine + + "To continue, click Next.", + PreviousButtonEnabled = false, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new ConfigPage { + Data = WizardData, + Header = @"Welcome to the Qt Custom Designer Widget", + Message = + @"Setup the configurations you want to include in your project. " + + @"The recommended settings for this project are selected by default.", + PreviousButtonEnabled = true, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true, + ValidateConfigs = ValidateConfigsForDesignerWidget + }, + new DesignerPage { + Data = WizardData, + Header = @"Welcome to the Qt Custom Designer Widget", + Message = @"This wizard generates a custom designer widget which can be " + + @"used in Qt Designer or Visual Studio.", + PreviousButtonEnabled = true, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true + } + } + ); + + string ValidateConfigsForDesignerWidget(IEnumerable<IWizardConfiguration> configs) + { + foreach (var config in configs) { + if (config.Target.EqualTo(ProjectTargets.WindowsStore)) { + return string.Format( + "Custom Designer Widget project not available for the '{0}' target.", + config.Target); + } + } + return string.Empty; + } + + protected override void BeforeWizardRun() + { + var className = Parameter[NewProject.SafeName]; + className = Regex.Replace(className, @"[^a-zA-Z0-9_]", string.Empty); + className = Regex.Replace(className, @"^[\d-]*\s*", string.Empty); + var result = new Util.ClassNameValidationRule().Validate(className, null); + if (result != ValidationResult.ValidResult) + className = @"MyDesignerWidget"; + + WizardData.ClassName = className; + WizardData.BaseClass = @"QWidget"; + WizardData.ClassHeaderFile = className + @".h"; + WizardData.ClassSourceFile = className + @".cpp"; + + WizardData.PluginClass = className + @"Plugin"; + WizardData.PluginHeaderFile = WizardData.PluginClass + @".h"; + WizardData.PluginSourceFile = WizardData.PluginClass + @".cpp"; + } + + protected override void BeforeTemplateExpansion() + { + Parameter[NewClass.ClassName] = WizardData.ClassName; + Parameter[NewClass.BaseClass] = WizardData.BaseClass; + Parameter[NewClass.HeaderFileName] = WizardData.ClassHeaderFile; + Parameter[NewClass.SourceFileName] = WizardData.ClassSourceFile; + + var include = new StringBuilder(); + if (UsePrecompiledHeaders) + include.AppendLine(string.Format("#include \"{0}\"", PrecompiledHeader.Include)); + include.AppendLine(string.Format("#include \"{0}\"", WizardData.ClassHeaderFile)); + Parameter[NewClass.Include] = FormatParam(include); + + Parameter[NewDesignerPlugin.ClassName] = WizardData.PluginClass; + Parameter[NewDesignerPlugin.HeaderFileName] = WizardData.PluginHeaderFile; + Parameter[NewDesignerPlugin.SourceFileName] = WizardData.PluginSourceFile; + Parameter[NewDesignerPlugin.JsonFileName] = WizardData.PluginClass.ToLower() + ".json"; + Parameter[NewDesignerPlugin.ObjectName] = string.Format("{0}{1}", + WizardData.ClassName[0], + WizardData.ClassName.Substring(1)); + } + + protected override void OnProjectGenerated(Project project) + { + var qtPro = Core.QtProject.Create(project); + if (qtPro != null) { + QtProject.MarkAsQtPlugin(qtPro); + Legacy.QtProject.MarkAsDesignerPluginProject(qtPro); + } + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Empty/EmptyWizard.cs b/QtVsTools.Wizards/ProjectWizard/Empty/EmptyWizard.cs new file mode 100644 index 0000000..b223170 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Empty/EmptyWizard.cs @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using QtVsTools.Common; + using Wizards.Common; + + public class EmptyWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => Options.Application | Options.GUISystem; + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new WizardData + { + DefaultModules = new List<string> { } + }); + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt Empty Application Wizard") + { + new WizardIntroPage { + Data = WizardData, + Header = @"Welcome to the Qt Empty Application Wizard", + Message = @"This wizard generates an empty Qt application project." + + System.Environment.NewLine + + "Click Finish to create the project.", + PreviousButtonEnabled = false, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new ConfigPage { + Data = WizardData, + Header = @"Welcome to the Qt Empty Application Wizard", + Message = + @"Setup the configurations you want to include in your project. " + + @"The recommended settings for this project are selected by default.", + PreviousButtonEnabled = true, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true, + } + }); + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Gui/GuiWizard.cs b/QtVsTools.Wizards/ProjectWizard/Gui/GuiWizard.cs new file mode 100644 index 0000000..a4f6f21 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Gui/GuiWizard.cs @@ -0,0 +1,365 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Controls; +using EnvDTE; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using QtVsTools.Common; + using Core; + using Wizards.Common; + + using static QtVsTools.Common.EnumExt; + + public class GuiWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => Options.Application | Options.GUISystem; + + readonly Func<IWizardConfiguration, bool> whereConfigTargetIsWindowsStore + = (IWizardConfiguration config) => config.Target.EqualTo(ProjectTargets.WindowsStore); + + enum NewClass + { + [String("classname")] ClassName, + [String("baseclass")] BaseClass, + [String("sourcefilename")] SourceFileName, + [String("headerfilename")] HeaderFileName, + [String("include")] Include, + } + + enum NewGuiProject + { + [String("centralwidget")] CentralWidget, + [String("qrcfilename")] QrcFileName, + [String("uifilename")] UiFileName, + [String("ui_hdr")] UiHeaderName, + [String("forward_declare_class")] ForwardDeclClass, + [String("multiple_inheritance")] MultipleInheritance, + [String("ui_classname")] UiClassName, + [String("member")] Member, + } + + enum Meta + { + [String("namespace")] Namespace, + [String("namespacebegin")] NamespaceBegin, + [String("operator")] Operator, + [String("asterisk")] Asterisk, + [String("semicolon")] Semicolon, + [String("new")] New, + [String("delete")] Delete, + [String("namespaceend")] NamespaceEnd + } + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new WizardData + { + DefaultModules = new List<string> { "QtCore", "QtGui", "QtWidgets" } + }); + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt Widgets Application Wizard") + { + new WizardIntroPage + { + Data = WizardData, + Header = @"Welcome to the Qt Widgets Application Wizard", + Message = @"This wizard generates a Qt Widgets application project. The " + + @"application derives from QApplication and includes an empty " + + @"widget." + System.Environment.NewLine + + System.Environment.NewLine + "To continue, click Next.", + PreviousButtonEnabled = false, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new ConfigPage + { + Data = WizardData, + Header = @"Welcome to the Qt Widgets Application Wizard", + Message = + @"Setup the configurations you want to include in your project. " + + @"The recommended settings for this project are selected by default.", + PreviousButtonEnabled = true, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new GuiPage + { + Data = WizardData, + Header = @"Welcome to the Qt Widgets Application Wizard", + Message = @"This wizard generates a Qt Widgets application project. The " + + @"application derives from QApplication and includes an empty " + + @"widget.", + PreviousButtonEnabled = true, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true + } + }); + + readonly List<ItemDef> GuiExtraItems; + protected override IEnumerable<ItemDef> ExtraItems => GuiExtraItems; + + public GuiWizard() + { + GuiExtraItems = new List<ItemDef> + { + new ItemDef + { + ItemType = "AppxManifest", + Include = "Package.appxmanifest", + Filter = "Resource Files", + WhereConfig = whereConfigTargetIsWindowsStore + }, + new ItemDef + { + ItemType = "Image", + Include = "assets/logo_store.png", + Filter = "Resource Files", + WhereConfig = whereConfigTargetIsWindowsStore + }, + new ItemDef + { + ItemType = "Image", + Include = "assets/logo_620x300.png", + Filter = "Resource Files", + WhereConfig = whereConfigTargetIsWindowsStore + }, + new ItemDef + { + ItemType = "Image", + Include = "assets/logo_150x150.png", + Filter = "Resource Files", + WhereConfig = whereConfigTargetIsWindowsStore + }, + new ItemDef + { + ItemType = "Image", + Include = "assets/logo_44x44.png", + Filter = "Resource Files", + WhereConfig = whereConfigTargetIsWindowsStore + }, + }; + } + + protected override void BeforeWizardRun() + { + var className = Parameter[NewProject.SafeName]; + className = Regex.Replace(className, @"[^a-zA-Z0-9_]", string.Empty); + className = Regex.Replace(className, @"^[\d-]*\s*", string.Empty); + var result = new Util.ClassNameValidationRule().Validate(className, null); + if (result != ValidationResult.ValidResult) + className = @"QtWidgetsApplication"; + + WizardData.ClassName = className; + WizardData.BaseClass = @"QMainWindow"; + WizardData.ClassHeaderFile = className + @".h"; + WizardData.ClassSourceFile = className + @".cpp"; + WizardData.UiFile = WizardData.ClassName + @".ui"; + WizardData.QrcFile = WizardData.ClassName + @".qrc"; + WizardData.UiClassInclusion = UiClassInclusion.Member; + + Parameter[NewGuiProject.ForwardDeclClass] = ""; + Parameter[NewGuiProject.MultipleInheritance] = ""; + Parameter[NewGuiProject.UiClassName] = ""; + Parameter[NewGuiProject.Member] = "ui"; + + Parameter[Meta.Asterisk] =""; + Parameter[Meta.Operator] = "."; + Parameter[Meta.Semicolon] = ";"; + Parameter[Meta.New] = ""; + Parameter[Meta.Delete] = ""; + } + + protected override void BeforeTemplateExpansion() + { + var array = WizardData.ClassName.Split(new[] { "::" }, + StringSplitOptions.RemoveEmptyEntries); + var className = array.LastOrDefault(); + + Parameter[NewClass.ClassName] = className; + Parameter[NewClass.BaseClass] = WizardData.BaseClass; + Parameter[NewClass.HeaderFileName] = WizardData.ClassHeaderFile; + Parameter[NewClass.SourceFileName] = WizardData.ClassSourceFile; + Parameter[NewGuiProject.UiFileName] = WizardData.UiFile; + + var include = new StringBuilder(); + if (UsePrecompiledHeaders) + include.AppendLine(string.Format("#include \"{0}\"", PrecompiledHeader.Include)); + include.AppendLine(string.Format("#include \"{0}\"", WizardData.ClassHeaderFile)); + Parameter[NewClass.Include] = FormatParam(include); + + Parameter[NewGuiProject.UiHeaderName] = string.Format("ui_{0}.h", + Path.GetFileNameWithoutExtension(WizardData.UiFile)); + Parameter[NewGuiProject.QrcFileName] = WizardData.QrcFile; + + if (WizardData.BaseClass == "QMainWindow") { + Parameter[NewGuiProject.CentralWidget] = FormatParam(@" + <widget class=""QMenuBar"" name=""menuBar"" /> + <widget class=""QToolBar"" name=""mainToolBar"" /> + <widget class=""QWidget"" name=""centralWidget"" /> + <widget class=""QStatusBar"" name=""statusBar"" />"); + } + + StringBuilder winRcFile = new StringBuilder(); + + if (WizardData.AddDefaultAppIcon) { + var projectIcon = Path.Combine( + Parameter[NewProject.DestinationDirectory], + Parameter[NewProject.SafeName] + ".ico"); + var iconExists = File.Exists(projectIcon); + if (!iconExists) { + try { + var uri = + new Uri(System.Reflection.Assembly.GetExecutingAssembly().EscapedCodeBase); + var pkgInstallPath + = Path.GetDirectoryName(Uri.UnescapeDataString(uri.AbsolutePath)) + @"\"; + var templateIcon + = Path.Combine(pkgInstallPath, @"ProjectTemplates\VC\Qt\1033\gui\gui.ico"); + File.Copy(templateIcon, projectIcon); + File.SetAttributes(projectIcon, + File.GetAttributes(projectIcon) & (~FileAttributes.ReadOnly)); + iconExists = true; + } catch (Exception /*ex*/) { + // Silently ignore any error, the project is working + // without icon too. + } + } + + if (iconExists) { + GuiExtraItems.Add(new ItemDef + { + ItemType = "None", + Include = Parameter[NewProject.SafeName] + ".ico", + Filter = "Resource Files" + }); + winRcFile.AppendLine( + string.Format("IDI_ICON1\t\tICON\t\tDISCARDABLE\t\"{0}.ico\"", + /*{0}*/ Parameter[NewProject.SafeName])); + } + } + + if (winRcFile.Length > 0) { + GuiExtraItems.Add(new ItemDef + { + ItemType = "ResourceCompile", + Include = Parameter[NewProject.SafeName] + ".rc", + Filter = "Resource Files" + }); + File.WriteAllText( + Path.Combine( + Parameter[NewProject.DestinationDirectory], + Parameter[NewProject.SafeName] + ".rc"), + winRcFile.ToString()); + } + + switch (WizardData.UiClassInclusion) { + case UiClassInclusion.MemberPointer: + Parameter[NewGuiProject.ForwardDeclClass] = + string.Format( + "\r\nQT_BEGIN_NAMESPACE\r\n" + + "namespace Ui {{ class {0}Class; }};\r\n" + + "QT_END_NAMESPACE\r\n", className + ); + Parameter[Meta.Asterisk] = "*"; + Parameter[Meta.Operator] = "->"; + Parameter[Meta.New] = string.Format("\r\n , {0}(new Ui::{1}Class())", + Parameter[NewGuiProject.Member], className); + Parameter[Meta.Delete] = string.Format("\r\n delete {0};\r\n", + Parameter[NewGuiProject.Member]); + goto case UiClassInclusion.Member; + case UiClassInclusion.Member: + Parameter[NewGuiProject.UiClassName] = string.Format("Ui::{0}Class", className); + break; + case UiClassInclusion.MultipleInheritance: + Parameter[NewGuiProject.MultipleInheritance] = + string.Format(", public Ui::{0}Class", className); + Parameter[NewGuiProject.Member] = ""; + Parameter[Meta.Operator] = ""; + Parameter[Meta.Semicolon] = ""; + break; + } + + string ns = "", nsBegin = "", nsEnd = ""; + for (var i = 0; i < array.Length - 1; ++i) { + ns += array[i] + "::"; + nsBegin += "namespace " + array[i] + " {\r\n"; + nsEnd = "} // namespace " + array[i] + "\r\n" + nsEnd; + } + Parameter[Meta.Namespace] = ns; + Parameter[Meta.NamespaceBegin] = nsBegin; + Parameter[Meta.NamespaceEnd] = nsEnd; + } + + protected override void OnProjectGenerated(Project project) + { + IWizardConfiguration configWinRT = Configurations + .Where(whereConfigTargetIsWindowsStore) + .FirstOrDefault(); + + if (configWinRT != null) { + var projDir = Parameter[NewProject.DestinationDirectory]; + var qmakeTmpDir = Path.Combine(projDir, "qmake_tmp"); + Directory.CreateDirectory(qmakeTmpDir); + + var dummyPro = Path.Combine(qmakeTmpDir, + string.Format("{0}.pro", Parameter[NewProject.SafeName])); + File.WriteAllText(dummyPro, "SOURCES = main.cpp\r\n"); + + var qmake = new QMakeImport(configWinRT.QtVersion, dummyPro); + qmake.Run(setVCVars: true); + + var qmakeAssetsDir = Path.Combine(qmakeTmpDir, "assets"); + var projAssetsDir = Path.Combine(projDir, "assets"); + if (Directory.Exists(qmakeAssetsDir)) { + if (Directory.Exists(projAssetsDir)) + Directory.Delete(projAssetsDir, recursive: true); + Directory.Move(qmakeAssetsDir, projAssetsDir); + } + + var manifestFile = Path.Combine(qmakeTmpDir, "Package.appxmanifest"); + if (File.Exists(manifestFile)) { + File.Move(manifestFile, Path.Combine(projDir, "Package.appxmanifest")); + } + + Directory.Delete(qmakeTmpDir, recursive: true); + } + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Library/LibraryClassPage.xaml b/QtVsTools.Wizards/ProjectWizard/Library/LibraryClassPage.xaml new file mode 100644 index 0000000..aebfe6f --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Library/LibraryClassPage.xaml @@ -0,0 +1,238 @@ +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2016 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + +<common:WizardPage x:Class="QtVsTools.Wizards.ProjectWizard.LibraryClassPage" + xmlns:common="clr-namespace:QtVsTools.Wizards.Common" + xmlns:util="clr-namespace:QtVsTools.Wizards.Util" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + KeepAlive="True" + mc:Ignorable="d" + d:DesignHeight="445" + d:DesignWidth="585"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Image Grid.Column="0" + HorizontalAlignment="Center" + Source="/QtVsTools.Wizards;component/Resources/Qt-logo-small.png" + VerticalAlignment="Top" + Margin="0,25,0,0" + RenderTransformOrigin="1,0"> + <Image.RenderTransform> + <TransformGroup> + <ScaleTransform ScaleY="0.86" + ScaleX="0.86" /> + </TransformGroup> + </Image.RenderTransform> + </Image> + <Grid Grid.Column="1" + Margin="25,25,10,0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock TextWrapping="Wrap" + Grid.Row="0"> + <Run FontWeight="Bold" + Text="{Binding Path=Header}" /> + <LineBreak /> + <LineBreak /> + <Run Text="{Binding Path=Message}" /> + <LineBreak /> + </TextBlock> + <Grid Grid.Row="1"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid.Resources> + <Style TargetType="TextBox"> + <Style.Triggers> + <Trigger Property="Validation.HasError" + Value="true"> + <Setter Property="ToolTip" + Value="{Binding RelativeSource={RelativeSource Self}, + Path=(Validation.Errors)[0].ErrorContent}" /> + </Trigger> + </Style.Triggers> + </Style> + </Grid.Resources> + <TextBlock Grid.Row="0" + Text="Class Name:" + Margin="0,0,10,0" /> + <TextBox Grid.Row="1" + Margin="0,0,10,30" + Name="ClassName" + TextChanged="OnClassNameChanged" + TabIndex="0"> + <TextBox.Text> + <Binding Path="Data.ClassName" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:ClassNameValidationRule /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <Grid Grid.Row="2" + Grid.ColumnSpan="2"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <TextBlock Grid.Row="0" + Margin="0,0,10,5" + Text="Header (.h) file:" /> + <TextBox Grid.Row="1" + Margin="0,0,10,0" + Name="ClassHeaderFile" + TabIndex="1"> + <TextBox.Text> + <Binding Path="Data.ClassHeaderFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".h" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Row="0" + Grid.Column="1" + Margin="0,0,0,5" + Text="Source (.cpp) file:" /> + <TextBox Grid.Row="1" + Grid.Column="1" + Margin="0,0,0,00" + Name="ClassSourceFile" + TabIndex="2"> + <TextBox.Text> + <Binding Path="Data.ClassSourceFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".cpp" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + </Grid> + <CheckBox Grid.Row="3" + Content="Lower case file names" + Name="LowerCaseFileNames" + Click="OnLowerCaseFileNamesClick" + Margin="0,20,10,5" + TabIndex="3" /> + <CheckBox Grid.Row="4" + Content="Precompiled header" + IsChecked="{Binding Path=Data.UsePrecompiledHeader}" + Margin="0,10,10,5" + TabIndex="4" /> + <CheckBox Grid.Row="5" + Content="Create Static Library (.lib)" + IsChecked="{Binding Path=Data.CreateStaticLibrary}" + Margin="0,0,10,0" + TabIndex="5" /> + </Grid> + <StackPanel HorizontalAlignment="Right" + Orientation="Horizontal" + Grid.Row="2" + Margin="0,0,0,10"> + <Button Click="OnPreviousButtonClick" + Name="PreviousButton" + IsEnabled="{Binding Path=PreviousButtonEnabled}" + MinWidth="75">< _Previous</Button> + <Button MinWidth="75" + Name="NextButton" + Click="OnNextButtonClick" + IsEnabled="{Binding Path=NextButtonEnabled}" + Margin="10,0,0,0">_Next ></Button> + <Button MinWidth="75" + Click="OnFinishButtonClick" + Margin="10,0,0,0" + IsDefault="True" + Name="FinishButton" + Content="_Finish" + VerticalAlignment="Bottom"> + <Button.Style> + <Style TargetType="Button"> + <Setter Property="IsEnabled" + Value="false" /> + <Style.Triggers> + <MultiDataTrigger> + <MultiDataTrigger.Conditions> + <Condition Binding="{Binding Path=FinishButtonEnabled}" + Value="true" /> + <Condition Binding="{Binding ElementName=ClassName, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassHeaderFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassSourceFile, + Path=(Validation.HasError)}" + Value="false" /> + </MultiDataTrigger.Conditions> + <Setter Property="IsEnabled" + Value="true" /> + </MultiDataTrigger> + </Style.Triggers> + </Style> + </Button.Style> + </Button> + <Button Click="OnCancelButtonClick" + MinWidth="75" + Margin="10,0,0,0" + Name="CancelButton" + IsEnabled="{Binding Path=CancelButtonEnabled}" + IsCancel="True">_Cancel</Button> + </StackPanel> + </Grid> + </Grid> +</common:WizardPage> diff --git a/QtVsTools.Wizards/ProjectWizard/Library/LibraryClassPage.xaml.cs b/QtVsTools.Wizards/ProjectWizard/Library/LibraryClassPage.xaml.cs new file mode 100644 index 0000000..93f8fd0 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Library/LibraryClassPage.xaml.cs @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Windows; +using System.Windows.Controls; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using Wizards.Common; + + public partial class LibraryClassPage : WizardPage + { + public LibraryClassPage() + { + InitializeComponent(); + DataContext = this; + } + + private void OnClassNameChanged(object sender, TextChangedEventArgs e) + { + UpdateFileNames(); + } + + private void OnLowerCaseFileNamesClick(object sender, RoutedEventArgs e) + { + UpdateFileNames(); + } + + private void UpdateFileNames() + { + var filename = ClassName.Text; + if (LowerCaseFileNames.IsChecked.GetValueOrDefault()) + filename = filename.ToLower(); + + ClassHeaderFile.Text = filename + @".h"; + ClassSourceFile.Text = filename + @".cpp"; + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Library/LibraryWizard.cs b/QtVsTools.Wizards/ProjectWizard/Library/LibraryWizard.cs new file mode 100644 index 0000000..0968343 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Library/LibraryWizard.cs @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Controls; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using QtVsTools.Common; + using Wizards.Common; + + using static QtVsTools.Common.EnumExt; + + public class LibraryWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => Options.GUISystem + | (WizardData.CreateStaticLibrary ? Options.StaticLibrary : Options.DynamicLibrary); + + enum NewLibClass + { + [String("classname")] ClassName, + [String("sourcefilename")] SourceFileName, + [String("headerfilename")] HeaderFileName, + [String("include")] Include, + [String("saveglobal")] GlobalHeader, + [String("pro_lib_define")] LibDefine, + [String("pro_lib_export")] LibExport, + } + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new WizardData + { + DefaultModules = new List<string> { "QtCore" } + }); + + readonly List<string> LibExtraDefines = new List<string>(); + protected override IEnumerable<string> ExtraDefines => LibExtraDefines; + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt Class Library Wizard") + { + new WizardIntroPage { + Data = WizardData, + Header = @"Welcome to the Qt Class Library Wizard", + Message = @"This wizard generates a Qt Class Library project. The " + + @"resulting library is linked dynamically with Qt." + + System.Environment.NewLine + System.Environment.NewLine + + @"To continue, click Next.", + PreviousButtonEnabled = false, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new ConfigPage { + Data = WizardData, + Header = @"Welcome to the Qt Class Library Wizard", + Message = + @"Setup the configurations you want to include in your project. " + + @"The recommended settings for this project are selected by default.", + PreviousButtonEnabled = true, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new LibraryClassPage { + Data = WizardData, + Header = @"Welcome to the Qt Class Library Wizard", + Message = @"This wizard generates a Qt Class Library project. The " + + @"resulting library is linked dynamically with Qt.", + PreviousButtonEnabled = true, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true + } + }); + + protected override void BeforeWizardRun() + { + var safeprojectname = Parameter[NewProject.SafeName]; + safeprojectname = Regex.Replace(safeprojectname, @"[^a-zA-Z0-9_]", string.Empty); + safeprojectname = Regex.Replace(safeprojectname, @"^[\d-]*\s*", string.Empty); + var result = new Util.ClassNameValidationRule().Validate(safeprojectname, null); + if (result != ValidationResult.ValidResult) + safeprojectname = @"QtClassLibrary"; + + WizardData.ClassName = safeprojectname; + WizardData.ClassHeaderFile = safeprojectname + @".h"; + WizardData.ClassSourceFile = safeprojectname + @".cpp"; + } + + protected override void BeforeTemplateExpansion() + { + Parameter[NewLibClass.ClassName] = WizardData.ClassName; + Parameter[NewLibClass.HeaderFileName] = WizardData.ClassHeaderFile; + Parameter[NewLibClass.SourceFileName] = WizardData.ClassSourceFile; + + var include = new StringBuilder(); + if (UsePrecompiledHeaders) + include.AppendLine(string.Format("#include \"{0}\"", PrecompiledHeader.Include)); + include.AppendLine(string.Format("#include \"{0}\"", WizardData.ClassHeaderFile)); + Parameter[NewLibClass.Include] = FormatParam(include); + + var safeprojectname = Parameter[NewProject.SafeName]; + Parameter[NewLibClass.GlobalHeader] = safeprojectname.ToLower(); + Parameter[NewLibClass.LibDefine] = safeprojectname.ToUpper() + "_LIB"; + Parameter[NewLibClass.LibExport] = safeprojectname.ToUpper() + "_EXPORT"; + + LibExtraDefines.Add(Parameter[NewLibClass.LibDefine]); + if (WizardData.CreateStaticLibrary) + LibExtraDefines.Add("BUILD_STATIC"); + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/ProjectTemplateWizard.cs b/QtVsTools.Wizards/ProjectWizard/ProjectTemplateWizard.cs new file mode 100644 index 0000000..9ae6ae8 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/ProjectTemplateWizard.cs @@ -0,0 +1,722 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Microsoft.Internal.VisualStudio.PlatformUI; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.TemplateWizard; +using EnvDTE; + + +namespace QtVsTools.Wizards.ProjectWizard +{ + using QtVsTools.Common; + using Core; + using Core.QtMsBuild; + using VisualStudio; + using Wizards.Common; + + using WhereConfig = Func<IWizardConfiguration, bool>; + + using static QtVsTools.Common.EnumExt; + + public interface IWizardConfiguration + { + string Name { get; } + VersionInformation QtVersion { get; } + string QtVersionName { get; } + string QtVersionPath { get; } + string Target { get; } + string Platform { get; } + bool IsDebug { get; } + IEnumerable<string> Modules { get; } + } + + public enum ProjectTargets + { + Windows, + [String("Windows Store")] WindowsStore, + [String("Linux (SSH)")] LinuxSSH, + [String("Linux (WSL)")] LinuxWSL + } + + public enum ProjectPlatforms + { + [String("x64")] X64, + Win32, + ARM64, + ARM, + } + + public abstract class ProjectTemplateWizard : IWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + private readonly WhereConfig WhereConfig_SelectAll = (x => true); + + protected struct ItemProperty + { + public string Key { get; } + public string Value { get; } + public WhereConfig WhereConfig { get; } + + public ItemProperty(string key, string value, WhereConfig whereConfig = null) + { + Key = key; + Value = value; + WhereConfig = whereConfig; + } + + public static implicit operator ItemProperty[](ItemProperty that) + { + return new[] { that }; + } + } + + protected class ItemGlobalDef + { + public string ItemType { get; set; } + public ItemProperty[] Properties { get; set; } + } + + protected class ItemDef + { + public string ItemType { get; set; } + public string Include { get; set; } + public ItemProperty[] Properties { get; set; } + public string Filter { get; set; } + public WhereConfig WhereConfig { get; set; } + } + + [Flags] + protected enum Options : uint + { + Application = 0x000, + DynamicLibrary = 0x001, + StaticLibrary = 0x002, + GUISystem = 0x004, + ConsoleSystem = 0x008, + PluginProject = 0x100 + } + + protected abstract Options TemplateType { get; } + protected abstract WizardData WizardData { get; } + protected abstract WizardWindow WizardWindow { get; } + + protected virtual IDictionary<string, ItemGlobalDef> ItemGlobals => null; + protected virtual IEnumerable<ItemDef> ExtraItems => Enumerable.Empty<ItemDef>(); + protected virtual IEnumerable<string> ExtraModules => Enumerable.Empty<string>(); + protected virtual IEnumerable<string> ExtraDefines => Enumerable.Empty<string>(); + + protected virtual IEnumerable<IWizardConfiguration> Configurations => WizardData.Configs; + protected virtual bool UsePrecompiledHeaders => WizardData.UsePrecompiledHeader; + + private Dictionary<string, string> ParameterValues { get; set; } + protected EnvDTE.DTE Dte { get; private set; } + + protected virtual ItemDef PrecompiledHeader => Lazy.Get(() => + PrecompiledHeader, () => new ItemDef + { + ItemType = "ClInclude", + Include = "stdafx.h", + Filter = "Header Files" + }); + + protected virtual ItemDef PrecompiledHeaderSource => Lazy.Get(() => + PrecompiledHeaderSource, () => new ItemDef + { + ItemType = "ClCompile", + Include = "stdafx.cpp", + Properties = new ItemProperty("PrecompiledHeader", "Create"), + Filter = "Source Files", + }); + + protected class TemplateParameters + { + public ProjectTemplateWizard Template { get; set; } + + string ParamKey(Enum param) + { + return string.Format("${0}$", param.Cast<string>()); + } + + public string this[Enum param] + { + get => Template.ParameterValues[ParamKey(param)]; + set => Template.ParameterValues[ParamKey(param)] = value; + } + } + + protected enum NewProject + { + // Read-only parameters + [String("projectname")] Name, + [String("safeprojectname")] SafeName, + [String("destinationdirectory")] DestinationDirectory, + [String("solutiondirectory")] SolutionDirectory, + + // Custom parameters + ToolsVersion, + ProjectConfigurations, + Properties, + ProjectGuid, + Keyword, + Globals, + Configurations, + PropertySheets, + QtSettings, + BuildSettings, + ProjectItems, + FilterItems, + } + + protected TemplateParameters Parameter => Lazy.Get(() => + Parameter, () => new TemplateParameters { Template = this }); + + protected QtVersionManager VersionManager => QtVersionManager.The(); + + public virtual void ProjectItemFinishedGenerating(ProjectItem projectItem) { } + public virtual void BeforeOpeningFile(ProjectItem projectItem) { } + public virtual void RunFinished() { } + public virtual bool ShouldAddProjectItem(string filePath) => true; + + protected virtual void BeforeWizardRun() { } + protected virtual void BeforeTemplateExpansion() { } + protected virtual void OnProjectGenerated(Project project) { } + + public virtual void RunStarted( + object automationObject, + Dictionary<string, string> parameterValues, + WizardRunKind runKind, + object[] customParams) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + Dte = automationObject as DTE; + ParameterValues = parameterValues; + + Debug.Assert(WizardWindow != null); + + BeforeWizardRun(); + + var iVsUIShell = VsServiceProvider.GetService<SVsUIShell, IVsUIShell>(); + if (iVsUIShell == null) + throw new NullReferenceException("IVsUIShell"); + + try { + iVsUIShell.EnableModeless(0); + iVsUIShell.GetDialogOwnerHwnd(out IntPtr hwnd); + WindowHelper.ShowModal(WizardWindow, hwnd); + } catch (QtVSException exception) { + exception.Log(false, true); + throw; + } finally { + iVsUIShell.EnableModeless(1); + } + if (!WizardWindow.DialogResult ?? false) { + try { + Directory.Delete(Parameter[NewProject.DestinationDirectory]); + Directory.Delete(Parameter[NewProject.SolutionDirectory]); + } catch { } + throw new WizardBackoutException(); + } + + BeforeTemplateExpansion(); + Expand(); + } + + public virtual void ProjectFinishedGenerating(Project project) + { + OnProjectGenerated(project); + } + + protected static bool IsLinux(IWizardConfiguration wizConfig) + { + return wizConfig.Target.EqualTo(ProjectTargets.LinuxSSH) + || wizConfig.Target.EqualTo(ProjectTargets.LinuxWSL); + } + + protected static string GetLinuxCompilerPath(IWizardConfiguration wizConfig) + { + if (!IsLinux(wizConfig)) + return string.Empty; + if (string.IsNullOrEmpty(wizConfig.QtVersionPath)) + return string.Empty; + string[] linuxPaths = wizConfig.QtVersionPath.Split(':'); + if (linuxPaths == null || linuxPaths.Length <= 2) + return string.Empty; + return linuxPaths[2]; + } + + protected virtual void Expand() + { + ThreadHelper.ThrowIfNotOnUIThread(); + + Debug.Assert(ParameterValues != null); + Debug.Assert(Dte != null); + Debug.Assert(Configurations != null); + Debug.Assert(ExtraItems != null); + + StringBuilder xml; + + /////////////////////////////////////////////////////////////////////////////////////// + // Tools version = VS version + // + Parameter[NewProject.ToolsVersion] = Dte.Version; + + /////////////////////////////////////////////////////////////////////////////////////// + // Configurations + // + xml = new StringBuilder(); + foreach (IWizardConfiguration c in Configurations) { + xml.AppendLine(string.Format(@" + <ProjectConfiguration Include=""{0}|{1}""> + <Configuration>{0}</Configuration> + <Platform>{1}</Platform> + </ProjectConfiguration>", + /*{0}*/ c.Name, + /*{1}*/ c.Platform)); + } + Parameter[NewProject.ProjectConfigurations] = FormatParam(xml); + + /////////////////////////////////////////////////////////////////////////////////////// + // Properties + // + xml = new StringBuilder(); + foreach (IWizardConfiguration c in Configurations) { + xml.AppendLine(string.Format(@" + <PropertyGroup Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">", + /*{0}*/ c.Name, + /*{1}*/ c.Platform)); + if (IsLinux(c)) { + var compilerPath = GetLinuxCompilerPath(c); + if (!string.IsNullOrEmpty(compilerPath)) + xml.AppendLine(string.Format(@" + <RemoteCCompileToolExe>{0}</RemoteCCompileToolExe> + <RemoteCppCompileToolExe>{0}</RemoteCppCompileToolExe> + <RemoteLdToolExe>{0}</RemoteLdToolExe>", + /*{0}*/ compilerPath)); + } + xml.AppendLine(@" + </PropertyGroup>"); + } + Parameter[NewProject.Properties] = FormatParam(xml); + + /////////////////////////////////////////////////////////////////////////////////////// + // Globals + // + xml = new StringBuilder(); + Parameter[NewProject.ProjectGuid] = HelperFunctions.NewProjectGuid(); + Parameter[NewProject.Keyword] = Resources.QtVSVersionTag; + + /////////////////////////////////////////////////////////////////////////////////////// + // Globals: Windows + // + foreach (IWizardConfiguration c in Configurations + .Where(c => c.Target.EqualTo(ProjectTargets.Windows))) { + if (!string.IsNullOrEmpty(c.QtVersion.VC_WindowsTargetPlatformVersion)) { + xml.AppendLine(string.Format(@" + <WindowsTargetPlatformVersion Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">{2}</WindowsTargetPlatformVersion>", + /*{0}*/ c.Name, + /*{1}*/ c.Platform, + /*{2}*/ c.QtVersion.VC_WindowsTargetPlatformVersion)); + } + } + + /////////////////////////////////////////////////////////////////////////////////////// + // Globals: Windows Store + // + foreach (IWizardConfiguration c in Configurations + .Where(c => c.Target.EqualTo(ProjectTargets.WindowsStore))) { + xml.AppendLine(string.Format(@" + <ApplicationType Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">Windows Store</ApplicationType> + <WindowsTargetPlatformVersion Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">{2}</WindowsTargetPlatformVersion> + <WindowsTargetPlatformMinVersion Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">{3}</WindowsTargetPlatformMinVersion> + <MinimumVisualStudioVersion Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">{4}</MinimumVisualStudioVersion> + <ApplicationTypeRevision Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">{5}</ApplicationTypeRevision> + <DefaultLanguage Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">en</DefaultLanguage> + <AppContainerApplication Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">true</AppContainerApplication>", + /*{0}*/ c.Name, + /*{1}*/ c.Platform, + /*{2}*/ c.QtVersion.VC_WindowsTargetPlatformVersion, + /*{3}*/ c.QtVersion.VC_WindowsTargetPlatformMinVersion, + /*{4}*/ c.QtVersion.VC_MinimumVisualStudioVersion, + /*{5}*/ c.QtVersion.VC_ApplicationTypeRevision)); + } + + /////////////////////////////////////////////////////////////////////////////////////// + // Globals: Linux + // + foreach (IWizardConfiguration c in Configurations.Where(c => IsLinux(c))) { + xml.AppendLine(string.Format(@" + <ApplicationType Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">Linux</ApplicationType> + <ApplicationTypeRevision Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">1.0</ApplicationTypeRevision> + <TargetLinuxPlatform Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">Generic</TargetLinuxPlatform> + <LinuxProjectType Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">{{D51BCBC9-82E9-4017-911E-C93873C4EA2B}}</LinuxProjectType>", + /*{0}*/ c.Name, + /*{1}*/ c.Platform)); + } + + Parameter[NewProject.Globals] = FormatParam(xml); + + /////////////////////////////////////////////////////////////////////////////////////// + // VC Configurations + // + xml = new StringBuilder(); + foreach (IWizardConfiguration c in Configurations) { + if (!c.Target.TryCast(out ProjectTargets target)) + continue; + xml.AppendLine(string.Format(@" + <PropertyGroup Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"" Label=""Configuration"">", + /*{0}*/ c.Name, + /*{1}*/ c.Platform)); + if (TemplateType.HasFlag(Options.DynamicLibrary)) { + xml.AppendLine(@" + <ConfigurationType>DynamicLibrary</ConfigurationType>"); + } else if (TemplateType.HasFlag(Options.StaticLibrary)) { + xml.AppendLine(@" + <ConfigurationType>StaticLibrary</ConfigurationType>"); + } else { + xml.AppendLine(@" + <ConfigurationType>Application</ConfigurationType>"); + } + switch (target) { + case ProjectTargets.Windows: + case ProjectTargets.WindowsStore: + xml.AppendLine(string.Format(@" + <PlatformToolset>v{0}</PlatformToolset>", + /*{0}*/ BuildConfig.PlatformToolset)); + break; + case ProjectTargets.LinuxSSH: + xml.AppendLine(@" + <PlatformToolset>Remote_GCC_1_0</PlatformToolset>"); + break; + case ProjectTargets.LinuxWSL: + xml.AppendLine(@" + <PlatformToolset>WSL_1_0</PlatformToolset>"); + break; + } + if (IsLinux(c)) { + xml.AppendLine(string.Format(@" + <UseDebugLibraries>{0}</UseDebugLibraries>", + /*{0}*/ c.IsDebug ? "true" : "false")); + } else if (target == ProjectTargets.WindowsStore) { + xml.AppendLine(@" + <GenerateManifest>false</GenerateManifest> + <EmbedManifest>false</EmbedManifest>"); + } + xml.AppendLine(@" + </PropertyGroup>"); + } + Parameter[NewProject.Configurations] = FormatParam(xml); + + /////////////////////////////////////////////////////////////////////////////////////// + // Property sheets + // + xml = new StringBuilder(); + foreach (IWizardConfiguration c in Configurations) { + xml.AppendLine(string.Format(@" + <ImportGroup Label=""PropertySheets"" Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'""> + <Import Project=""$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"" Condition=""exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"" Label=""LocalAppDataPlatform"" /> + <Import Project=""$(QtMsBuild)\Qt.props"" /> + </ImportGroup>", + /*{0}*/ c.Name, + /*{1}*/ c.Platform)); + } + Parameter[NewProject.PropertySheets] = FormatParam(xml); + + /////////////////////////////////////////////////////////////////////////////////////// + // Qt settings + // + xml = new StringBuilder(); + foreach (IWizardConfiguration c in Configurations) { + xml.AppendLine(string.Format(@" + <PropertyGroup Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"" Label=""QtSettings""> + <QtInstall>{2}</QtInstall> + <QtModules>{3}</QtModules> + <QtBuildConfig>{4}</QtBuildConfig>", + /*{0}*/ c.Name, + /*{1}*/ c.Platform, + /*{2}*/ c.QtVersionName, + /*{3}*/ string.Join(";", c.Modules.Union(ExtraModules)), + /*{4}*/ c.IsDebug ? "debug" : "release")); + if (c.Target.EqualTo(ProjectTargets.WindowsStore)) { + xml.AppendLine(@" + <QtDeploy>true</QtDeploy> + <QtDeployToProjectDir>true</QtDeployToProjectDir> + <QtDeployVsContent>true</QtDeployVsContent>"); + } + xml.AppendLine(@" + </PropertyGroup>"); + } + Parameter[NewProject.QtSettings] = FormatParam(xml); + + /////////////////////////////////////////////////////////////////////////////////////// + // Build settings + // + IEnumerable<ItemProperty> mocProperties + = ItemGlobals?[QtMoc.ItemTypeName]?.Properties ?? Enumerable.Empty<ItemProperty>(); + IEnumerable<ItemProperty> clProperties + = ItemGlobals?["ClCompile"]?.Properties ?? Enumerable.Empty<ItemProperty>(); + IEnumerable<ItemProperty> linkProperties + = ItemGlobals?["Link"]?.Properties ?? Enumerable.Empty<ItemProperty>(); + + xml = new StringBuilder(); + foreach (IWizardConfiguration c in Configurations) { + xml.AppendLine(string.Format(@" + <ItemDefinitionGroup Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"" Label=""Configuration"">", + /*{0}*/ c.Name, + /*{1}*/ c.Platform)); + + + /////////////////////////////////////////////////////////////////////////////////// + // Build settings: C++ compiler + // + if (!IsLinux(c)) { + // Windows + xml.AppendLine(@" + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation>"); + if (c.IsDebug) { + xml.AppendLine(@" + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization>"); + } else { + xml.AppendLine(@" + <DebugInformationFormat>None</DebugInformationFormat> + <Optimization>MaxSpeed</Optimization>"); + } + if (c.Target.EqualTo(ProjectTargets.WindowsStore)) { + xml.AppendLine(@" + <CompileAsWinRT>false</CompileAsWinRT> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <RuntimeTypeInfo>true</RuntimeTypeInfo>"); + } + if (UsePrecompiledHeaders) { + xml.AppendLine(string.Format(@" + <PrecompiledHeader>Use</PrecompiledHeader> + <PrecompiledHeaderFile>{0}</PrecompiledHeaderFile>", + /*{0}*/ PrecompiledHeader.Include)); + } + if (ExtraDefines?.Any() == true) { + xml.AppendLine(string.Format(@" + <PreprocessorDefinitions>{0};%(PreprocessorDefinitions)</PreprocessorDefinitions>", + /*{0}*/ string.Join(";", ExtraDefines))); + } + foreach (ItemProperty p in clProperties) { + xml.AppendLine(string.Format(@" + <{0}>{1}</{0}>", + /*{0}*/ p.Key, + /*{1}*/ p.Value)); + } + xml.AppendLine(@" + </ClCompile>"); + } else { + // Linux + xml.AppendLine(@" + <ClCompile> + <PositionIndependentCode>true</PositionIndependentCode> + </ClCompile>"); + } + + /////////////////////////////////////////////////////////////////////////////////// + // Build settings: Linker + // + if (!IsLinux(c)) { + // Windows + xml.AppendLine(string.Format(@" + <Link> + <SubSystem>{0}</SubSystem> + <GenerateDebugInformation>{1}</GenerateDebugInformation>", + /*{0}*/ TemplateType.HasFlag(Options.ConsoleSystem) ? "Console" : "Windows", + /*{1}*/ c.IsDebug ? "true" : "false")); + if (c.Target.EqualTo(ProjectTargets.WindowsStore)) { + xml.AppendLine(string.Format(@" + <AdditionalOptions>/APPCONTAINER %(AdditionalOptions)</AdditionalOptions> + <GenerateManifest>false</GenerateManifest> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + <TargetMachine>{0}</TargetMachine>", + /*{0}*/ c.QtVersion.VC_Link_TargetMachine)); + } + foreach (ItemProperty p in linkProperties) { + xml.AppendLine(string.Format(@" + <{0}>{1}</{0}>", + /*{0}*/ p.Key, + /*{1}*/ p.Value)); + } + xml.AppendLine(@" + </Link>"); + } + + /////////////////////////////////////////////////////////////////////////////////// + // Build settings: moc + // + if (UsePrecompiledHeaders || mocProperties.Any()) { + xml.AppendLine(string.Format(@" + <{0}>", QtMoc.ItemTypeName)); + foreach (ItemProperty p in mocProperties) { + xml.AppendLine(string.Format(@" + <{0}>{1}</{0}>", + /*{0}*/ p.Key, + /*{1}*/ p.Value)); + } + if (UsePrecompiledHeaders) { + xml.AppendLine(string.Format(@" + <{0}>{1};%({0})</{0}>", + /*{0}*/ QtMoc.Property.PrependInclude, + /*{1}*/ PrecompiledHeader.Include)); + } + xml.AppendLine(string.Format(@" + </{0}>", QtMoc.ItemTypeName)); + } + + /////////////////////////////////////////////////////////////////////////////////// + // Build settings: remaining item types + // + if (ItemGlobals != null) { + foreach (string itemType in ItemGlobals.Keys + .Except(new[] { "ClCompile", "Link", QtMoc.ItemTypeName })) { + xml.AppendLine(string.Format(@" + <{0}>", + /*{0}*/ itemType)); + foreach (ItemProperty p in ItemGlobals[itemType].Properties) { + xml.AppendLine(string.Format(@" + <{0}>{1}</{0}>", + /*{0}*/ p.Key, + /*{1}*/ p.Value)); + } + xml.AppendLine(string.Format(@" + </{0}>", + /*{0}*/ itemType)); + } + } + xml.AppendLine(@" + </ItemDefinitionGroup>"); + } + + Parameter[NewProject.BuildSettings] = FormatParam(xml); + + /////////////////////////////////////////////////////////////////////////////////////// + // Project items + // + IEnumerable<ItemDef> projectItems = ExtraItems + .Where((ItemDef item) => item.WhereConfig == null + || Configurations.Where(item.WhereConfig).Any()) + .Union(UsePrecompiledHeaders + ? new[] { PrecompiledHeader, PrecompiledHeaderSource } + : Enumerable.Empty<ItemDef>()); + + xml = new StringBuilder(); + foreach (ItemDef item in projectItems) { + bool itemHasProperties = (item.WhereConfig != null || item.Properties != null); + xml.Append(string.Format(@" + <{0} Include=""{1}""{2}", + /*{0}*/ item.ItemType, + /*{1}*/ item.Include, + /*{2}*/ itemHasProperties ? ">" : " />")); + + if (item.Properties != null) { + foreach (ItemProperty property in item.Properties) { + IEnumerable<IWizardConfiguration> configs = Configurations + .Where(property.WhereConfig ?? WhereConfig_SelectAll); + foreach (IWizardConfiguration config in configs) { + xml.AppendLine(string.Format(@" + <{0} Condition=""'$(Configuration)|$(Platform)' == '{1}|{2}'"">{3}</{0}>", + /*{0}*/ property.Key, + /*{1}*/ config.Name, + /*{2}*/ config.Platform, + /*{3}*/ property.Value)); + } + } + } + + if (item.WhereConfig != null) { + IEnumerable<IWizardConfiguration> excludedConfigs = Configurations + .Where(config => !item.WhereConfig(config)); + foreach (var excludedConfig in excludedConfigs) { + xml.AppendLine(string.Format(@" + <ExcludedFromBuild Condition=""'$(Configuration)|$(Platform)' == '{0}|{1}'"">true</ExcludedFromBuild>", + /*{0}*/ excludedConfig.Name, + /*{1}*/ excludedConfig.Platform)); + } + } + + if (itemHasProperties) { + xml.AppendLine(string.Format(@" + </{0}>", + /*{0}*/ item.ItemType)); + } + } + Parameter[NewProject.ProjectItems] = FormatParam(xml); + + /////////////////////////////////////////////////////////////////////////////////////// + // Project items: filters + // + xml = new StringBuilder(); + foreach (ItemDef item in projectItems) { + xml.Append(string.Format(@" + <{0} Include=""{1}"">", + /*{0}*/ item.ItemType, + /*{1}*/ item.Include)); + xml.AppendLine(string.Format(@" + <Filter>{0}</Filter>", + /*{0}*/ item.Filter)); + xml.AppendLine(string.Format(@" + </{0}>", + /*{0}*/ item.ItemType)); + } + Parameter[NewProject.FilterItems] = FormatParam(xml); + } + + // Matches empty lines; captures first newline + static readonly Regex patternEmptyLines + = new Regex(@"(?:^|(?<FIRST_NL>\r\n))(?:\r\n)+(?![\r\n]|$)|(?:\r\n)+$"); + + protected static string FormatParam(StringBuilder paramValue) + { + return FormatParam(paramValue.ToString()); + } + + protected static string FormatParam(string paramValue) + { + // Remove empty lines; replace with first newline (if any) + paramValue = patternEmptyLines.Replace(paramValue, + (Match m) => m.Groups["FIRST_NL"].Value); + + return paramValue; + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Quick/QuickWizard.cs b/QtVsTools.Wizards/ProjectWizard/Quick/QuickWizard.cs new file mode 100644 index 0000000..87a0cc2 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Quick/QuickWizard.cs @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using QtVsTools.Common; + using Wizards.Common; + + public class QuickWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => Options.Application | Options.GUISystem; + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new WizardData + { + DefaultModules = new List<string> { "QtQuick" } + }); + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt Quick Application Wizard") + { + new WizardIntroPage { + Data = WizardData, + Header = @"Welcome to the Qt Quick Application Wizard", + Message = @"This wizard generates a Qt Quick application project." + + System.Environment.NewLine + + "Click Finish to create the project.", + PreviousButtonEnabled = false, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new ConfigPage { + Data = WizardData, + Header = @"Welcome to the Qt Quick Application Wizard", + Message = + @"Setup the configurations you want to include in your project. " + + @"The recommended settings for this project are selected by default.", + PreviousButtonEnabled = true, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true, + } + }); + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Server/ServerPage.xaml b/QtVsTools.Wizards/ProjectWizard/Server/ServerPage.xaml new file mode 100644 index 0000000..8d7e946 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Server/ServerPage.xaml @@ -0,0 +1,259 @@ +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2016 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + +<common:WizardPage x:Class="QtVsTools.Wizards.ProjectWizard.ServerPage" + xmlns:common="clr-namespace:QtVsTools.Wizards.Common" + xmlns:util="clr-namespace:QtVsTools.Wizards.Util" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + KeepAlive="True" + mc:Ignorable="d" + d:DesignHeight="445" + d:DesignWidth="585"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Image Grid.Column="0" + HorizontalAlignment="Center" + Source="/QtVsTools.Wizards;component/Resources/Qt-logo-small.png" + VerticalAlignment="Top" + Margin="0,25,0,0" + RenderTransformOrigin="1,0"> + <Image.RenderTransform> + <TransformGroup> + <ScaleTransform ScaleY="0.86" + ScaleX="0.86" /> + </TransformGroup> + </Image.RenderTransform> + </Image> + <Grid Grid.Column="1" + Margin="25,25,10,0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock TextWrapping="Wrap" + Grid.Row="0"> + <Run FontWeight="Bold" + Text="{Binding Path=Header}" /> + <LineBreak /> + <LineBreak /> + <Run Text="{Binding Path=Message}" /> + <LineBreak /> + </TextBlock> + <Grid Grid.Row="1"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid.Resources> + <Style TargetType="TextBox"> + <Style.Triggers> + <Trigger Property="Validation.HasError" + Value="true"> + <Setter Property="ToolTip" + Value="{Binding RelativeSource={RelativeSource Self}, + Path=(Validation.Errors)[0].ErrorContent}" /> + </Trigger> + </Style.Triggers> + </Style> + </Grid.Resources> + <TextBlock Grid.Row="0" + Text="Class Name:" + Margin="0,0,10,0" /> + <TextBox Grid.Row="1" + Margin="0,0,10,30" + Name="ClassName" + TextChanged="OnClassNameChanged" + TabIndex="0"> + <TextBox.Text> + <Binding Path="Data.ClassName" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:ClassNameValidationRule /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <Grid Grid.Row="2" + Grid.ColumnSpan="2"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <TextBlock Grid.Row="0" + Grid.Column="0" + Margin="0,0,10,5" + Text="Header (.h) file:" /> + <TextBox Grid.Row="1" + Grid.Column="0" + Margin="0,0,10,10" + Name="ClassHeaderFile" + TabIndex="1"> + <TextBox.Text> + <Binding Path="Data.ClassHeaderFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".h" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Row="2" + Grid.Column="0" + Margin="0,0,10,5" + Text="User Interface (.ui) file:" /> + <TextBox Grid.Row="3" + Grid.Column="0" + Margin="0,0,10,0" + Name="UiFile" + TabIndex="3"> + <TextBox.Text> + <Binding Path="Data.UiFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".ui" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + <TextBlock Grid.Row="0" + Grid.Column="1" + Margin="0,0,0,5" + Text="Source (.cpp) file:" /> + <TextBox Grid.Row="1" + Grid.Column="1" + Margin="0,0,0,10" + Name="ClassSourceFile" + TabIndex="2"> + <TextBox.Text> + <Binding Path="Data.ClassSourceFile" + NotifyOnValidationError="True" + UpdateSourceTrigger="PropertyChanged"> + <Binding.ValidationRules> + <util:FileNameValidationRule FileExt=".cpp" /> + </Binding.ValidationRules> + </Binding> + </TextBox.Text> + </TextBox> + </Grid> + <CheckBox Grid.Row="3" + Content="Lower case file names" + Name="LowerCaseFileNames" + Click="OnLowerCaseFileNamesClick" + Margin="0,20,10,5" + TabIndex="4" /> + <CheckBox Grid.Row="4" + Content="Precompiled header" + IsChecked="{Binding Path=Data.UsePrecompiledHeader}" + Margin="0,10,10,5" + TabIndex="5" /> + </Grid> + <StackPanel HorizontalAlignment="Right" + Orientation="Horizontal" + Grid.Row="2" + Margin="0,0,0,10"> + <Button Click="OnPreviousButtonClick" + Name="PreviousButton" + IsEnabled="{Binding Path=PreviousButtonEnabled}" + MinWidth="75">< _Previous</Button> + <Button MinWidth="75" + Name="NextButton" + Click="OnNextButtonClick" + IsEnabled="{Binding Path=NextButtonEnabled}" + Margin="10,0,0,0">_Next ></Button> + <Button MinWidth="75" + Click="OnFinishButtonClick" + Margin="10,0,0,0" + IsDefault="True" + Name="FinishButton" + Content="_Finish" + VerticalAlignment="Bottom"> + <Button.Style> + <Style TargetType="Button"> + <Setter Property="IsEnabled" + Value="false" /> + <Style.Triggers> + <MultiDataTrigger> + <MultiDataTrigger.Conditions> + <Condition Binding="{Binding Path=FinishButtonEnabled}" + Value="true" /> + <Condition Binding="{Binding ElementName=ClassName, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassHeaderFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=ClassSourceFile, + Path=(Validation.HasError)}" + Value="false" /> + <Condition Binding="{Binding ElementName=UiFile, + Path=(Validation.HasError)}" + Value="false" /> + </MultiDataTrigger.Conditions> + <Setter Property="IsEnabled" + Value="true" /> + </MultiDataTrigger> + </Style.Triggers> + </Style> + </Button.Style> + </Button> + <Button Click="OnCancelButtonClick" + MinWidth="75" + Margin="10,0,0,0" + Name="CancelButton" + IsEnabled="{Binding Path=CancelButtonEnabled}" + IsCancel="True">_Cancel</Button> + </StackPanel> + </Grid> + </Grid> +</common:WizardPage> diff --git a/QtVsTools.Wizards/ProjectWizard/Server/ServerPage.xaml.cs b/QtVsTools.Wizards/ProjectWizard/Server/ServerPage.xaml.cs new file mode 100644 index 0000000..f0681b8 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Server/ServerPage.xaml.cs @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Windows; +using System.Windows.Controls; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using Wizards.Common; + + public partial class ServerPage : WizardPage + { + public ServerPage() + { + InitializeComponent(); + DataContext = this; + } + + private void OnClassNameChanged(object sender, TextChangedEventArgs e) + { + UpdateFileNames(); + } + + private void OnLowerCaseFileNamesClick(object sender, RoutedEventArgs e) + { + UpdateFileNames(); + } + + private void UpdateFileNames() + { + Data.LowerCaseFileNames = LowerCaseFileNames.IsChecked.GetValueOrDefault(); + var filename = Data.LowerCaseFileNames ? ClassName.Text.ToLower() : ClassName.Text; + + ClassHeaderFile.Text = filename + @".h"; + ClassSourceFile.Text = filename + @".cpp"; + UiFile.Text = filename + @".ui"; + } + } +} diff --git a/QtVsTools.Wizards/ProjectWizard/Server/ServerWizard.cs b/QtVsTools.Wizards/ProjectWizard/Server/ServerWizard.cs new file mode 100644 index 0000000..2f77f13 --- /dev/null +++ b/QtVsTools.Wizards/ProjectWizard/Server/ServerWizard.cs @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Controls; +using Microsoft.VisualStudio.Shell; +using EnvDTE; + +namespace QtVsTools.Wizards.ProjectWizard +{ + using QtVsTools.Common; + using Core; + using Wizards.Common; + + using static QtVsTools.Common.EnumExt; + + public class ServerWizard : ProjectTemplateWizard + { + LazyFactory Lazy { get; } = new LazyFactory(); + + protected override Options TemplateType => Options.DynamicLibrary | Options.GUISystem; + + enum NewClass + { + [String("classname")] ClassName, + [String("sourcefilename")] SourceFileName, + [String("headerfilename")] HeaderFileName, + [String("include")] Include, + } + + enum NewActiveQtProject + { + [String("pro_name")] Name, + [String("uifilename")] UiFileName, + [String("ui_hdr")] UiHeaderName, + } + + protected override WizardData WizardData => Lazy.Get(() => + WizardData, () => new WizardData + { + DefaultModules = new List<string> { "QtCore", "QtGui", "QtWidgets", "QtAxServer" } + }); + + protected override WizardWindow WizardWindow => Lazy.Get(() => + WizardWindow, () => new WizardWindow(title: "Qt ActiveQt Server Wizard") + { + new WizardIntroPage { + Data = WizardData, + Header = @"Welcome to the Qt ActiveQt Server Wizard", + Message = @"This wizard generates a Qt ActiveQt server project. It " + + @"creates a simple ActiveQt widget with the required files." + + System.Environment.NewLine + System.Environment.NewLine + + "To continue, click Next.", + PreviousButtonEnabled = false, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true + }, + new ConfigPage { + Data = WizardData, + Header = @"Welcome to the Qt ActiveQt Server Wizard", + Message = + @"Setup the configurations you want to include in your project. " + + @"The recommended settings for this project are selected by default.", + PreviousButtonEnabled = true, + NextButtonEnabled = true, + FinishButtonEnabled = false, + CancelButtonEnabled = true, + ValidateConfigs = ValidateConfigsForActiveQtServer + }, + new ServerPage { + Data = WizardData, + Header = @"Welcome to the Qt ActiveQt Server Wizard", + Message = @"This wizard generates a Qt ActiveQt server project. It " + + @"creates a simple ActiveQt widget with the required files.", + PreviousButtonEnabled = true, + NextButtonEnabled = false, + FinishButtonEnabled = true, + CancelButtonEnabled = true + } + }); + + string ValidateConfigsForActiveQtServer(IEnumerable<IWizardConfiguration> configs) + { + foreach (var config in configs) { + if (config.Target.EqualTo(ProjectTargets.WindowsStore)) { + return string.Format( + "ActiveQt Server project not available for the '{0}' target.", + config.Target); + } + } + return string.Empty; + } + + protected override void BeforeWizardRun() + { + // midl.exe does not support spaces in project name. Fails while generating the + // IDL file (library attribute), e.g. 'library Active QtServer1Lib' is illegal. + if (Parameter[NewProject.SafeName].Contains(" ")) + throw new QtVSException("Project name shall not contain spaces."); + + var className = Parameter[NewProject.SafeName]; + className = Regex.Replace(className, @"[^a-zA-Z0-9_]", string.Empty); + className = Regex.Replace(className, @"^[\d-]*\s*", string.Empty); + var result = new Util.ClassNameValidationRule().Validate(className, null); + if (result != ValidationResult.ValidResult) + className = @"ActiveQtServer"; + + WizardData.ClassName = className; + WizardData.ClassHeaderFile = className + @".h"; + WizardData.ClassSourceFile = className + @".cpp"; + WizardData.UiFile = WizardData.ClassName + @".ui"; + } + + protected override void BeforeTemplateExpansion() + { + Parameter[NewClass.ClassName] = WizardData.ClassName; + Parameter[NewClass.HeaderFileName] = WizardData.ClassHeaderFile; + Parameter[NewClass.SourceFileName] = WizardData.ClassSourceFile; + Parameter[NewActiveQtProject.UiFileName] = WizardData.UiFile; + + var include = new StringBuilder(); + if (UsePrecompiledHeaders) + include.AppendLine(string.Format("#include \"{0}\"", PrecompiledHeader.Include)); + include.AppendLine(string.Format("#include \"{0}\"", WizardData.ClassHeaderFile)); + Parameter[NewClass.Include] = FormatParam(include); + + Parameter[NewActiveQtProject.UiHeaderName] = string.Format("ui_{0}.h", + Path.GetFileNameWithoutExtension(WizardData.UiFile)); + + Parameter[NewActiveQtProject.Name] = WizardData.LowerCaseFileNames + ? Parameter[NewProject.SafeName].ToLower() + : Parameter[NewProject.SafeName]; + } + + protected override void OnProjectGenerated(Project project) + { + var qtProject = QtProject.Create(project); + qtProject.AddActiveQtBuildStep("1.0", Parameter[NewProject.SafeName] + ".def"); + } + } +} diff --git a/QtVsTools.Wizards/QtVsTools.Wizards.csproj b/QtVsTools.Wizards/QtVsTools.Wizards.csproj index 0b333de..34aa9ff 100644 --- a/QtVsTools.Wizards/QtVsTools.Wizards.csproj +++ b/QtVsTools.Wizards/QtVsTools.Wizards.csproj @@ -71,42 +71,43 @@ <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> <Reference Include="System" /> <Reference Include="System.Drawing" /> - <Reference Include="System.Xml.Linq" /> <Reference Include="PresentationCore" /> <Reference Include="PresentationFramework" /> + <Reference Include="System.Xaml" /> <Reference Include="WindowsBase" /> <Reference Include="Microsoft.VisualStudio.VCCodeModel" /> - <Reference Include="Microsoft.VisualStudio.ExtensionsExplorer.UI, Version=$(VisualStudioVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>$(DevEnvDir)PrivateAssemblies\Microsoft.VisualStudio.ExtensionsExplorer.UI.dll</HintPath> - </Reference> </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - // Version specific references + // General package references // --> <Import Project="$(SolutionDir)\references.props" /> <ItemGroup> - <PackageReference Include="Microsoft.VisualStudio.SDK" - Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> - <PackageReference Include="Microsoft.VSSDK.BuildTools" - Version="$(Version_Microsoft_VSSDK_BuildTools)" /> - <PackageReference Include="Newtonsoft.Json" - Version="$(Version_Newtonsoft_Json)" /> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='17.0'"> - <PackageReference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" - Version="$(Version_Microsoft_VisualStudio_VCProjectEngine)" /> - <PackageReference Include="$(Name_Microsoft_VisualStudio_TemplateWizardInterface)" - Version="$(Version_Microsoft_VisualStudio_TemplateWizardInterface)" /> - </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='16.0'"> - <Reference Include="Microsoft.VisualStudio.TemplateWizardInterface" /> - </ItemGroup> - <ItemGroup Condition="'$(VisualStudioVersion)'=='15.0'"> - <Reference Include="Microsoft.VisualStudio.VCProjectEngine" /> - <Reference Include="Microsoft.VisualStudio.TemplateWizardInterface" /> - </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_TemplateWizardInterface)" Version="$(Version_Microsoft_VisualStudio_TemplateWizardInterface)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_TemplateWizardInterface)" Version="$(Version_Microsoft_VisualStudio_TemplateWizardInterface)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + <Reference Include="$(Name_Microsoft_VisualStudio_VCProjectEngine)" /> + <Reference Include="$(Name_Microsoft_VisualStudio_TemplateWizardInterface)" /> + </ItemGroup> + </When> + </Choose> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// // Solution project references @@ -123,58 +124,47 @@ // --> <ItemGroup> <Content Include="Resources\QtProjectWizard.ico" /> - <Resource Include="Resources\medium.png"> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Resource> <Resource Include="Resources\Qt-logo-small.png"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Resource> - <Resource Include="Resources\small.png"> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Resource> </ItemGroup> <ItemGroup> - <Compile Include="Wizards\ClassWizard\AddClassPage.xaml.cs"> - <DependentUpon>AddClassPage.xaml</DependentUpon> + <Compile Include="ItemWizard\Translation\TranslationPage.xaml.cs"> + <DependentUpon>TranslationPage.xaml</DependentUpon> </Compile> - <Compile Include="Wizards\ClassWizard\AddClassWizard.cs" /> - <Compile Include="Wizards\ClassWizard\Class.cs" /> - <Compile Include="Wizards\ClassWizard\ClassKind.cs" /> - <Compile Include="Wizards\ProjectWizard\ConfigPage.xaml.cs"> + <Compile Include="ItemWizard\Translation\TranslationWizard.cs" /> + <Compile Include="ProjectWizard\ConfigPage.xaml.cs"> <DependentUpon>ConfigPage.xaml</DependentUpon> </Compile> - <Compile Include="Wizards\ProjectWizard\ProjectTemplateWizard.cs" /> - <Compile Include="Wizards\ProjectWizard\Quick\QuickWizard.cs" /> - <Compile Include="Wizards\Util\ClassNameValidationRule.cs" /> - <Compile Include="Wizards\ProjectWizard\Console\ConsoleWizard.cs" /> - <Compile Include="Wizards\ClassWizard\Core\CoreClassPage.xaml.cs"> - <DependentUpon>CoreClassPage.xaml</DependentUpon> + <Compile Include="ProjectWizard\ProjectTemplateWizard.cs" /> + <Compile Include="ProjectWizard\Quick\QuickWizard.cs" /> + <Compile Include="Util\ClassNameValidationRule.cs" /> + <Compile Include="ProjectWizard\Console\ConsoleWizard.cs" /> + <Compile Include="ItemWizard\QtClass\QtClassPage.xaml.cs"> + <DependentUpon>QtClassPage.xaml</DependentUpon> </Compile> - <Compile Include="Wizards\ClassWizard\Core\CoreClassWizard.cs" /> - <Compile Include="Wizards\ProjectWizard\Designer\DesignerPage.xaml.cs"> + <Compile Include="ProjectWizard\Designer\DesignerPage.xaml.cs"> <DependentUpon>DesignerPage.xaml</DependentUpon> </Compile> - <Compile Include="Wizards\ProjectWizard\Designer\DesignerWizard.cs" /> - <Compile Include="Wizards\Util\FileExistsInFilterValidationRule.cs" /> - <Compile Include="Wizards\Util\FileNameValidationRule.cs" /> - <Compile Include="Wizards\ClassWizard\Gui\GuiClassPage.xaml.cs"> - <DependentUpon>GuiClassPage.xaml</DependentUpon> - </Compile> - <Compile Include="Wizards\ClassWizard\Gui\GuiClassWizard.cs" /> - <Compile Include="Wizards\ProjectWizard\Gui\GuiPage.xaml.cs"> + <Compile Include="ProjectWizard\Designer\DesignerWizard.cs" /> + <Compile Include="Util\FileExistsInFilterValidationRule.cs" /> + <Compile Include="Util\FileNameValidationRule.cs" /> + <Compile Include="Common\GuiPage.xaml.cs"> <DependentUpon>GuiPage.xaml</DependentUpon> </Compile> - <Compile Include="Wizards\ProjectWizard\Gui\GuiWizard.cs" /> - <Compile Include="Wizards\ProjectWizard\Empty\EmptyWizard.cs" /> - <Compile Include="Wizards\ClassWizard\IClassWizard.cs" /> - <Compile Include="Wizards\WizardIntroPage.xaml.cs"> + <Compile Include="ProjectWizard\Gui\GuiWizard.cs" /> + <Compile Include="ProjectWizard\Empty\EmptyWizard.cs" /> + <Compile Include="Common\WizardIntroPage.xaml.cs"> <DependentUpon>WizardIntroPage.xaml</DependentUpon> </Compile> - <Compile Include="Wizards\ProjectWizard\Library\LibraryClassPage.xaml.cs"> + <Compile Include="ProjectWizard\Library\LibraryClassPage.xaml.cs"> <DependentUpon>LibraryClassPage.xaml</DependentUpon> </Compile> - <Compile Include="Wizards\ProjectWizard\Library\LibraryWizard.cs" /> - <Compile Include="Wizards\Util\NativeMethods.cs" /> + <Compile Include="ProjectWizard\Library\LibraryWizard.cs" /> + <Compile Include="Util\NativeMethods.cs" /> + <Compile Include="ItemWizard\QtClass\QtClassWizard.cs" /> + <Compile Include="ItemWizard\WidgetsClass\WidgetsClassWizard.cs" /> + <Compile Include="Util\VCRulePropertyStorageHelper.cs" /> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> <OutputFile>Properties\AssemblyInfo.tt.cs</OutputFile> @@ -186,65 +176,58 @@ <DesignTime>True</DesignTime> <DependentUpon>AssemblyInfo.cs</DependentUpon> </Compile> - <Compile Include="Wizards\ProjectWizard\Server\ServerPage.xaml.cs"> + <Compile Include="ProjectWizard\Server\ServerPage.xaml.cs"> <DependentUpon>ServerPage.xaml</DependentUpon> </Compile> - <Compile Include="Wizards\ProjectWizard\Server\ServerWizard.cs" /> - <Compile Include="Wizards\Util\SortComboBoxItem.cs" /> - <Compile Include="Wizards\ClassWizard\UiClassInclusion.cs" /> - <Compile Include="Wizards\Util\UnsafeNativeMethods.cs" /> - <Compile Include="Wizards\Util\VCLanguageManagerValidationRule.cs" /> - <Compile Include="Wizards\WizardData.cs" /> - <Compile Include="Wizards\WizardPage.cs" /> - <Compile Include="Wizards\WizardResult.cs" /> - <Compile Include="Wizards\WizardWindow.xaml.cs"> + <Compile Include="ProjectWizard\Server\ServerWizard.cs" /> + <Compile Include="Util\UiClassInclusionConverter.cs" /> + <Compile Include="Common\UiClassInclusion.cs" /> + <Compile Include="Util\UnsafeNativeMethods.cs" /> + <Compile Include="Util\VCLanguageManagerValidationRule.cs" /> + <Compile Include="Common\WizardData.cs" /> + <Compile Include="Common\WizardPage.cs" /> + <Compile Include="Common\WizardResult.cs" /> + <Compile Include="Common\WizardWindow.xaml.cs"> <DependentUpon>WizardWindow.xaml</DependentUpon> </Compile> - <Page Include="Wizards\ClassWizard\AddClassPage.xaml"> + <Page Include="ItemWizard\QtClass\QtClassPage.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> - <Page Include="Wizards\ClassWizard\Core\CoreClassPage.xaml"> + <Page Include="ItemWizard\Translation\TranslationPage.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> - <Page Include="Wizards\ProjectWizard\Designer\DesignerPage.xaml"> + <Page Include="ProjectWizard\Designer\DesignerPage.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> - <Page Include="Wizards\ClassWizard\Gui\GuiClassPage.xaml"> + <Page Include="Common\GuiPage.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> - <Page Include="Wizards\ProjectWizard\Gui\GuiPage.xaml"> - <SubType>Designer</SubType> - <Generator>MSBuild:Compile</Generator> - </Page> - <Page Include="Wizards\ProjectWizard\ConfigPage.xaml"> + <Page Include="ProjectWizard\ConfigPage.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </Page> - <Page Include="Wizards\WizardIntroPage.xaml"> + <Page Include="Common\WizardIntroPage.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> - <Page Include="Wizards\ProjectWizard\Library\LibraryClassPage.xaml"> + <Page Include="ProjectWizard\Library\LibraryClassPage.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> - <Page Include="Resources\ExpanderStyle.xaml"> + <Page Include="ProjectWizard\Server\ServerPage.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> - <Page Include="Wizards\ProjectWizard\Server\ServerPage.xaml"> - <SubType>Designer</SubType> - <Generator>MSBuild:Compile</Generator> - </Page> - <Page Include="Wizards\WizardWindow.xaml"> + <Page Include="Common\WizardWindow.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> </ItemGroup> + <ItemGroup /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> </Project> \ No newline at end of file diff --git a/QtVsTools.Wizards/Util/ClassNameValidationRule.cs b/QtVsTools.Wizards/Util/ClassNameValidationRule.cs new file mode 100644 index 0000000..a9304a8 --- /dev/null +++ b/QtVsTools.Wizards/Util/ClassNameValidationRule.cs @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Globalization; +using System.Text.RegularExpressions; +using System.Windows.Controls; + +namespace QtVsTools.Wizards.Util +{ + internal class ClassNameValidationRule : VCLanguageManagerValidationRule + { + public ClassNameValidationRule() + { + SupportNamespaces = false; + AllowEmptyIdentifier = false; + } + + public override ValidationResult Validate(object value, CultureInfo cultureInfo) + { + if (value is string) { + var identifier = value as string; + if (AllowEmptyIdentifier && string.IsNullOrEmpty(identifier)) + return ValidationResult.ValidResult; + + if (SupportNamespaces) { + var index = identifier.LastIndexOf(@"::", System.StringComparison.Ordinal); + if (index >= 0) + identifier = identifier.Substring(index + 2); + } + + if (Regex.IsMatch(identifier, pattern) && !Vclm.IsReservedName(identifier)) + return ValidationResult.ValidResult; + } + return new ValidationResult(false, @"Invalid identifier."); + } + + public bool SupportNamespaces { get; set; } + public bool AllowEmptyIdentifier { get; set; } + + const string pattern = @"^[a-zA-Z_][a-zA-Z0-9_]*$"; + } +} diff --git a/QtVsTools.Wizards/Util/FileExistsInFilterValidationRule.cs b/QtVsTools.Wizards/Util/FileExistsInFilterValidationRule.cs new file mode 100644 index 0000000..036c824 --- /dev/null +++ b/QtVsTools.Wizards/Util/FileExistsInFilterValidationRule.cs @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Globalization; +using System.Linq; +using System.Windows.Controls; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using EnvDTE; + +namespace QtVsTools.Wizards.Util +{ + using Core; + using VisualStudio; + + internal class FileExistsinFilterValidationRule : VCLanguageManagerValidationRule + { + public override ValidationResult Validate(object value, CultureInfo cultureInfo) + { + if (value is string) { + var dte = VsServiceProvider.GetService<SDTE, DTE>(); + if (dte == null) + return ValidationResult.ValidResult; + + var project = HelperFunctions.GetSelectedProject(dte); + if (project == null) + return ValidationResult.ValidResult; + + var files = HelperFunctions.GetProjectFiles(project, Filter); + if (files.Count == 0) + return ValidationResult.ValidResult; + + var fileName = (value as string).ToUpperInvariant(); + if (files.FirstOrDefault(x => x.ToUpperInvariant() == fileName) != null) + return new ValidationResult(false, @"File already exists."); + return ValidationResult.ValidResult; + } + return new ValidationResult(false, @"Invalid file name."); + } + + public FilesToList Filter { get; set; } + } +} diff --git a/QtVsTools.Wizards/Util/FileNameValidationRule.cs b/QtVsTools.Wizards/Util/FileNameValidationRule.cs new file mode 100644 index 0000000..e3ea756 --- /dev/null +++ b/QtVsTools.Wizards/Util/FileNameValidationRule.cs @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Globalization; +using System.IO; +using System.Linq; +using System.Windows.Controls; + +namespace QtVsTools.Wizards.Util +{ + internal class FileNameValidationRule : VCLanguageManagerValidationRule + { + public override ValidationResult Validate(object value, CultureInfo cultureInfo) + { + if (value is string) { + var filename = value as string; + if (FileExt == @".ui" || FileExt == @".qrc") { + filename = filename.ToLower().Replace(@".h", @".x"); + filename = filename.Replace(FileExt, @".h"); + } + + if (Vclm.ValidateFileName(filename) + && !Path.GetInvalidFileNameChars().Any(filename.Contains)) { + return ValidationResult.ValidResult; + } + } + return new ValidationResult(false, @"Invalid file name."); + } + } +} diff --git a/QtVsTools.Wizards/Util/NativeMethods.cs b/QtVsTools.Wizards/Util/NativeMethods.cs new file mode 100644 index 0000000..00edfea --- /dev/null +++ b/QtVsTools.Wizards/Util/NativeMethods.cs @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace QtVsTools.Wizards.Util +{ + internal static class NativeMethods + { + [ResourceExposure(ResourceScope.None)] + [DllImport("user32.dll", CharSet = CharSet.Auto)] + internal static extern int GetWindowLong(IntPtr hwnd, int index); + } +} diff --git a/QtVsTools.Wizards/Util/UiClassInclusionConverter.cs b/QtVsTools.Wizards/Util/UiClassInclusionConverter.cs new file mode 100644 index 0000000..64ee165 --- /dev/null +++ b/QtVsTools.Wizards/Util/UiClassInclusionConverter.cs @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Globalization; +using System.Windows.Data; + +namespace QtVsTools.Wizards.Util +{ + public class UiClassInclusionConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + => value?.Equals(parameter); + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + => value?.Equals(true) == true ? parameter : Binding.DoNothing; + } +} diff --git a/QtVsTools.Wizards/Util/UnsafeNativeMethods.cs b/QtVsTools.Wizards/Util/UnsafeNativeMethods.cs new file mode 100644 index 0000000..8fc5f27 --- /dev/null +++ b/QtVsTools.Wizards/Util/UnsafeNativeMethods.cs @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace QtVsTools.Wizards.Util +{ + internal static class UnsafeNativeMethods + { + [ResourceExposure(ResourceScope.None)] + [DllImport("user32.dll", CharSet = CharSet.Auto)] + internal static extern int SetWindowLong(IntPtr hwnd, int index, int value); + } +} diff --git a/QtVsTools.Wizards/Util/VCLanguageManagerValidationRule.cs b/QtVsTools.Wizards/Util/VCLanguageManagerValidationRule.cs new file mode 100644 index 0000000..996e91c --- /dev/null +++ b/QtVsTools.Wizards/Util/VCLanguageManagerValidationRule.cs @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Windows.Controls; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCCodeModel; +using EnvDTE; + +namespace QtVsTools.Wizards.Util +{ + using VisualStudio; + + internal abstract class VCLanguageManagerValidationRule : ValidationRule + { + protected VCLanguageManagerValidationRule() + { + ThreadHelper.ThrowIfNotOnUIThread(); + + ValidatesOnTargetUpdated = true; + + var dte = VsServiceProvider.GetService<DTE>(); + Vclm = dte.GetObject("VCLanguageManager") as VCLanguageManager; + } + + public string FileExt { get; set; } + public VCLanguageManager Vclm { get; } + } +} diff --git a/QtVsTools.Wizards/Util/VCRulePropertyStorageHelper.cs b/QtVsTools.Wizards/Util/VCRulePropertyStorageHelper.cs new file mode 100644 index 0000000..e183a82 --- /dev/null +++ b/QtVsTools.Wizards/Util/VCRulePropertyStorageHelper.cs @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; +using EnvDTE; + +namespace QtVsTools.Wizards.Util +{ + using Core; + + static class VCRulePropertyStorageHelper + { + public static void SetQtModules(DTE dte, List<string> modules) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var newModules = modules.ToHashSet(); + if (modules.Count == 0) + return; + + var project = HelperFunctions.GetSelectedQtProject(dte); + if (project == null) + return; + + var vcproject = project.Object as VCProject; + if (vcproject == null) + return; + + // TODO: There is already code providing such functionality, though it seems overly + // complicated to use compared to this simple for loop (see VCPropertyStorageProvider). + foreach (VCConfiguration config in vcproject.Configurations as IVCCollection) { + var props = config.Rules.Item("QtRule10_Settings") as IVCRulePropertyStorage; + var updatedModules = props.GetUnevaluatedPropertyValue("QtModules") + .Split(new char[] { ';' }, System.StringSplitOptions.RemoveEmptyEntries) + .ToHashSet() + .Union(newModules); + props.SetPropertyValue("QtModules", string.Join(";", updatedModules)); + } + } + } +} diff --git a/README.md b/README.md index fa5df16..cc2dbdd 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ The following is required in order to build the Qt Visual Studio solution: -- Visual Studio 2017, 2019 or 2022, with the following workloads: +- Visual Studio 2017, 2019 or 2022, with the following workloads (A .vsconfig file per VS version can be found in the source tree): - Desktop development with C++ - .NET desktop development - [Visual Studio extension development](https://docs.microsoft.com/en-us/visualstudio/extensibility/installing-the-visual-studio-sdk) diff --git a/Templates/console/QtTemplate.Project.Console.csproj b/Templates/console/QtTemplate.Project.Console.csproj index d4bbdfe..c4d6e31 100644 --- a/Templates/console/QtTemplate.Project.Console.csproj +++ b/Templates/console/QtTemplate.Project.Console.csproj @@ -76,16 +76,45 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> <ItemGroup> - <Reference Include="Microsoft.VisualStudio.CoreUtility"> - <Private>False</Private> - </Reference> - <Reference Include="System" /> - <Reference Include="System.Core" /> - <Reference Include="System.Data" /> - <Reference Include="System.Xml" /> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -126,6 +155,6 @@ </VSTemplate> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(SolutionDir)\transform.targets" /> -</Project> + <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> +</Project> \ No newline at end of file diff --git a/Templates/console/console.vcxproj.filters b/Templates/console/console.vcxproj.filters index df883a8..64ad4dd 100644 --- a/Templates/console/console.vcxproj.filters +++ b/Templates/console/console.vcxproj.filters @@ -3,7 +3,7 @@ <ItemGroup> <Filter Include="Source Files"> <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + <Extensions>qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> </Filter> <Filter Include="Header Files"> <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> @@ -13,6 +13,10 @@ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> <Filter Include="Translation Files"> <UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier> <Extensions>ts</Extensions> diff --git a/Templates/designer/QtTemplate.Project.Designer.csproj b/Templates/designer/QtTemplate.Project.Designer.csproj index 0e19350..6e2e3b1 100644 --- a/Templates/designer/QtTemplate.Project.Designer.csproj +++ b/Templates/designer/QtTemplate.Project.Designer.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -122,17 +161,7 @@ <Content Include="widget.cpp" /> <Content Include="widget.h" /> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/Templates/designer/designer.vcxproj.filters b/Templates/designer/designer.vcxproj.filters index 7b7bab4..c2f3f8d 100644 --- a/Templates/designer/designer.vcxproj.filters +++ b/Templates/designer/designer.vcxproj.filters @@ -3,7 +3,7 @@ <ItemGroup> <Filter Include="Source Files"> <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + <Extensions>qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> </Filter> <Filter Include="Header Files"> <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> @@ -13,6 +13,10 @@ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> <Filter Include="Translation Files"> <UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier> <Extensions>ts</Extensions> diff --git a/Templates/designer/plugin.h b/Templates/designer/plugin.h index 1f88121..dfdacaa 100644 --- a/Templates/designer/plugin.h +++ b/Templates/designer/plugin.h @@ -9,7 +9,7 @@ Q_INTERFACES(QDesignerCustomWidgetInterface) public: - $plugin_class$(QObject *parent = Q_NULLPTR); + $plugin_class$(QObject *parent = nullptr); bool isContainer() const; bool isInitialized() const; diff --git a/Templates/designer/widget.h b/Templates/designer/widget.h index abf56e1..8c3d96b 100644 --- a/Templates/designer/widget.h +++ b/Templates/designer/widget.h @@ -7,5 +7,5 @@ Q_OBJECT public: - $classname$(QWidget *parent = Q_NULLPTR); + $classname$(QWidget *parent = nullptr); }; diff --git a/Templates/dialogbuttonbottom/QtTemplate.Item.DialogButtonBottom.csproj b/Templates/dialogbuttonbottom/QtTemplate.Item.DialogButtonBottom.csproj index 5c6cf84..decad55 100644 --- a/Templates/dialogbuttonbottom/QtTemplate.Item.DialogButtonBottom.csproj +++ b/Templates/dialogbuttonbottom/QtTemplate.Item.DialogButtonBottom.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -99,17 +138,7 @@ <SubType>Designer</SubType> </VSTemplate> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/Templates/dialogbuttonright/QtTemplate.Item.DialogButtonRight.csproj b/Templates/dialogbuttonright/QtTemplate.Item.DialogButtonRight.csproj index ad22581..aec8882 100644 --- a/Templates/dialogbuttonright/QtTemplate.Item.DialogButtonRight.csproj +++ b/Templates/dialogbuttonright/QtTemplate.Item.DialogButtonRight.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -98,17 +137,7 @@ <OutputSubPath>Qt</OutputSubPath> </VSTemplate> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/Templates/empty/QtTemplate.Project.Empty.csproj b/Templates/empty/QtTemplate.Project.Empty.csproj index 536168f..1e7bd4e 100644 --- a/Templates/empty/QtTemplate.Project.Empty.csproj +++ b/Templates/empty/QtTemplate.Project.Empty.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -113,17 +152,7 @@ <DependentUpon>empty.vstemplate_TT</DependentUpon> </VSTemplate> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/Templates/gui/QtTemplate.Project.Gui.csproj b/Templates/gui/QtTemplate.Project.Gui.csproj index 1b373ae..09a9d4f 100644 --- a/Templates/gui/QtTemplate.Project.Gui.csproj +++ b/Templates/gui/QtTemplate.Project.Gui.csproj @@ -76,16 +76,45 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> <ItemGroup> - <Reference Include="Microsoft.VisualStudio.CoreUtility"> - <Private>False</Private> - </Reference> - <Reference Include="System" /> - <Reference Include="System.Core" /> - <Reference Include="System.Data" /> - <Reference Include="System.Xml" /> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -108,6 +137,7 @@ <SubType>Designer</SubType> </None> <None Include="main.cpp" /> + <None Include="widget.qrc" /> <None Include="stdafx.cpp" /> <None Include="stdafx.h" /> <None Include="widget.cpp" /> @@ -130,13 +160,6 @@ </VSTemplate> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(SolutionDir)\transform.targets" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> -</Project> + <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> +</Project> \ No newline at end of file diff --git a/Templates/gui/gui.vcxproj.filters b/Templates/gui/gui.vcxproj.filters index 90f5b7a..b6e7201 100644 --- a/Templates/gui/gui.vcxproj.filters +++ b/Templates/gui/gui.vcxproj.filters @@ -3,7 +3,7 @@ <ItemGroup> <Filter Include="Source Files"> <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + <Extensions>qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> </Filter> <Filter Include="Header Files"> <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> diff --git a/Templates/gui/gui.vstemplate_TT b/Templates/gui/gui.vstemplate_TT index 7a09db3..33fdd42 100644 --- a/Templates/gui/gui.vstemplate_TT +++ b/Templates/gui/gui.vstemplate_TT @@ -71,6 +71,8 @@ <ProjectItem ReplaceParameters="true" TargetFileName="$safeprojectname$.vcxproj.filters">gui.vcxproj.filters</ProjectItem> <ProjectItem ReplaceParameters="false">gui.ico</ProjectItem> + <ProjectItem ReplaceParameters="true" + TargetFileName="$qrcfilename$">widget.qrc</ProjectItem> </Project> </TemplateContent> <WizardExtension> diff --git a/Templates/gui/main.cpp b/Templates/gui/main.cpp index 6478e3f..d3f5898 100644 --- a/Templates/gui/main.cpp +++ b/Templates/gui/main.cpp @@ -4,7 +4,7 @@ int main(int argc, char *argv[]) { QApplication a(argc, argv); - $classname$ w; + $namespace$$classname$ w; w.show(); return a.exec(); } diff --git a/Templates/gui/widget.cpp b/Templates/gui/widget.cpp index 28c285b..7718d6f 100644 --- a/Templates/gui/widget.cpp +++ b/Templates/gui/widget.cpp @@ -1,7 +1,11 @@ $include$ -$classname$::$classname$(QWidget *parent) - : $baseclass$(parent) +$namespacebegin$$classname$::$classname$(QWidget *parent) + : $baseclass$(parent)$new$ { - ui.setupUi(this); + $member$$operator$setupUi(this); } + +$classname$::~$classname$() +{$delete$} +$namespaceend$ \ No newline at end of file diff --git a/Templates/gui/widget.h b/Templates/gui/widget.h index 578cb5e..68646a0 100644 --- a/Templates/gui/widget.h +++ b/Templates/gui/widget.h @@ -2,14 +2,16 @@ #include <QtWidgets/$baseclass$> #include "$ui_hdr$" - -class $classname$ : public $baseclass$ +$forward_declare_class$ +$namespacebegin$class $classname$ : public $baseclass$$multiple_inheritance$ { Q_OBJECT public: - $classname$(QWidget *parent = Q_NULLPTR); + $classname$(QWidget *parent = nullptr); + ~$classname$(); private: - Ui::$classname$Class ui; + $ui_classname$ $asterisk$$member$$semicolon$ }; +$namespaceend$ \ No newline at end of file diff --git a/Templates/gui/widget.qrc b/Templates/gui/widget.qrc new file mode 100644 index 0000000..f0fb159 --- /dev/null +++ b/Templates/gui/widget.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="$classname$"> + </qresource> +</RCC> diff --git a/Templates/lib/QtTemplate.Project.Lib.csproj b/Templates/lib/QtTemplate.Project.Lib.csproj index 1b7c02e..4065393 100644 --- a/Templates/lib/QtTemplate.Project.Lib.csproj +++ b/Templates/lib/QtTemplate.Project.Lib.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -120,17 +159,7 @@ <Content Include="stdafx.cpp" /> <Content Include="stdafx.h" /> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/Templates/lib/lib.vcxproj.filters b/Templates/lib/lib.vcxproj.filters index 1630278..af524ae 100644 --- a/Templates/lib/lib.vcxproj.filters +++ b/Templates/lib/lib.vcxproj.filters @@ -3,7 +3,7 @@ <ItemGroup> <Filter Include="Source Files"> <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + <Extensions>qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> </Filter> <Filter Include="Header Files"> <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> @@ -13,6 +13,10 @@ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> <Filter Include="Translation Files"> <UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier> <Extensions>ts</Extensions> diff --git a/Templates/mainwindow/QtTemplate.Item.MainWindow.csproj b/Templates/mainwindow/QtTemplate.Item.MainWindow.csproj index 9683ca1..c2b6ea5 100644 --- a/Templates/mainwindow/QtTemplate.Item.MainWindow.csproj +++ b/Templates/mainwindow/QtTemplate.Item.MainWindow.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -99,17 +138,7 @@ <SubType>Designer</SubType> </VSTemplate> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/Templates/qml/QtTemplate.Item.QMLFile.csproj b/Templates/qml/QtTemplate.Item.QMLFile.csproj index 1d26bac..f65cecb 100644 --- a/Templates/qml/QtTemplate.Item.QMLFile.csproj +++ b/Templates/qml/QtTemplate.Item.QMLFile.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -103,17 +142,7 @@ <ItemGroup> <Content Include="qml.ico" /> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> \ No newline at end of file diff --git a/Templates/qmldir/QtTemplate.Item.QMLDir.csproj b/Templates/qmldir/QtTemplate.Item.QMLDir.csproj index a3cdb07..d6f9d48 100644 --- a/Templates/qmldir/QtTemplate.Item.QMLDir.csproj +++ b/Templates/qmldir/QtTemplate.Item.QMLDir.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -103,17 +142,7 @@ <ItemGroup> <Content Include="qml.ico" /> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> \ No newline at end of file diff --git a/Templates/qtclass/Properties/AssemblyInfo.cs b/Templates/qtclass/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..127025e --- /dev/null +++ b/Templates/qtclass/Properties/AssemblyInfo.cs @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +**************************************************************************** +<#@output extension="tt.cs" #> +<#@include file="$(SolutionDir)\version.tt" #> +** <#=WARNING_GENERATED_FILE#> +****************************************************************************/ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("QtClass")] +[assembly: AssemblyDescription("The Qt Visual Studio Tools allow developers to use the standard development environment without having to worry about any Qt-related build steps or tools.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Qt Company Ltd.")] +[assembly: AssemblyProduct("Qt Visual Studio Tools")] +[assembly: AssemblyCopyright("Copyright (C) 2016-22 The Qt Company Ltd.")] +[assembly: AssemblyTrademark("The Qt Company Ltd. Qt and their respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f375c22e-8c6d-4800-ad3a-ff301113dac6")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("<#=QT_VS_TOOLS_VERSION_ASSEMBLY#>")] +[assembly: AssemblyFileVersion("<#=QT_VS_TOOLS_VERSION_ASSEMBLY_FILE#>")] diff --git a/Templates/qtclass/QtTemplate.Item.QtClass.csproj b/Templates/qtclass/QtTemplate.Item.QtClass.csproj new file mode 100644 index 0000000..24cf073 --- /dev/null +++ b/Templates/qtclass/QtTemplate.Item.QtClass.csproj @@ -0,0 +1,157 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +--> +<Project ToolsVersion="$(VisualStudioVersion)" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <MinimumVisualStudioVersion>$(VisualStudioVersion)</MinimumVisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + </PropertyGroup> + <PropertyGroup> + <ApplicationIcon>qtclass.ico</ApplicationIcon> + </PropertyGroup> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <ProjectGuid>{4981AAE8-9AC7-4758-87EA-FB2397D6C404}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>QtClass</RootNamespace> + <AssemblyName>QtClass</AssemblyName> + <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <GeneratePkgDefFile>false</GeneratePkgDefFile> + <IncludeAssemblyInVSIXContainer>false</IncludeAssemblyInVSIXContainer> + <IncludeDebugSymbolsInVSIXContainer>false</IncludeDebugSymbolsInVSIXContainer> + <IncludeDebugSymbolsInLocalVSIXDeployment>false</IncludeDebugSymbolsInLocalVSIXDeployment> + <CreateVsixContainer>false</CreateVsixContainer> + <DeployExtension>false</DeployExtension> + <DeployVSTemplates>false</DeployVSTemplates> + <CopyVsixManifestToOutput>false</CopyVsixManifestToOutput> + <CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory> + <CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> + <ItemGroup> + <T4Template Include="Properties\AssemblyInfo.cs"> + <Generator>TextTemplatingFileGenerator</Generator> + <OutputFile>Properties\AssemblyInfo.tt.cs</OutputFile> + <DependsOn>$(SolutionDir)\version.tt;$(SolutionDir)\common.tt</DependsOn> + <LastGenOutput>AssemblyInfo.tt.cs</LastGenOutput> + </T4Template> + <Compile Include="Properties\AssemblyInfo.tt.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>AssemblyInfo.cs</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <None Include="header.h" /> + <None Include="source.cpp" /> + </ItemGroup> + <ItemGroup> + <T4Template Include="qtclass.vstemplate_TT"> + <Generator>TextTemplatingFileGenerator</Generator> + <OutputFile>qtclass.vstemplate</OutputFile> + <DependsOn>$(SolutionDir)\version.tt;$(SolutionDir)\common.tt</DependsOn> + <LastGenOutput>qtclass.vstemplate</LastGenOutput> + <SubType>Designer</SubType> + </T4Template> + <VSTemplate Include="qtclass.vstemplate"> + <SubType>Designer</SubType> + <OutputSubPath>Qt</OutputSubPath> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>qtclass.vstemplate_TT</DependentUpon> + </VSTemplate> + </ItemGroup> + <ItemGroup> + <Content Include="qtclass.ico" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(SolutionDir)\transform.targets" /> + <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> +</Project> \ No newline at end of file diff --git a/Templates/qtclass/header.h b/Templates/qtclass/header.h new file mode 100644 index 0000000..8495cfc --- /dev/null +++ b/Templates/qtclass/header.h @@ -0,0 +1,9 @@ +#pragma once + +$baseclassinclude$$namespacebegin$class $classname$ $baseclassdecl$ +{$qobject$ +public: + $classname$($signature$); + ~$classname$(); +}; +$namespaceend$ \ No newline at end of file diff --git a/Templates/qtclass/qtclass.ico b/Templates/qtclass/qtclass.ico new file mode 100644 index 0000000..1c4fb80 --- /dev/null +++ b/Templates/qtclass/qtclass.ico Binary files differ diff --git a/Templates/qtclass/qtclass.vstemplate_TT b/Templates/qtclass/qtclass.vstemplate_TT new file mode 100644 index 0000000..b0ab4d8 --- /dev/null +++ b/Templates/qtclass/qtclass.vstemplate_TT @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +<#@output extension="vstemplate" #> +<#@include file="$(SolutionDir)\version.tt" #> + ** <#=WARNING_GENERATED_FILE#> + ***************************************************************************** +--> + +<VSTemplate Version="3.0.0" + xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" + xmlns:sdk="http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010" + Type="Item" > + <TemplateData> + <Name>Qt Class</Name> + <Description>Adds a Qt class to the project.</Description> + <ProjectType>VC</ProjectType> + <CreateNewFolder>true</CreateNewFolder> + <DefaultName>QtClass</DefaultName> + <ProvideDefaultName>true</ProvideDefaultName> + <LocationField>Enabled</LocationField> + <EnableLocationBrowseButton>true</EnableLocationBrowseButton> + <Icon>qtclass.ico</Icon> + <LanguageTag>Cpp</LanguageTag> + <PlatformTag>Windows</PlatformTag> + <PlatformTag>Linux</PlatformTag> + <ProjectTypeTag>Qt</ProjectTypeTag> + <ProjectTypeTag>IoT</ProjectTypeTag> + <ProjectTypeTag>Desktop</ProjectTypeTag> + <ProjectTypeTag>Console</ProjectTypeTag> + </TemplateData> + <TemplateContent> + <ProjectItem OpenInEditor="true" + ReplaceParameters="true" + TargetFileName="$sourcefilename$">source.cpp</ProjectItem> + <ProjectItem ReplaceParameters="true" + TargetFileName="$headerfilename$">header.h</ProjectItem> + </TemplateContent> + <WizardExtension> + <!-- BEGIN Generated Text <#=XML_COMMENT_END#> + <Assembly>QtVsTools.Wizards, Version=<#=QT_VS_TOOLS_VERSION_ASSEMBLY#>, Culture=neutral, PublicKeyToken=null</Assembly> + <#=XML_COMMENT_BEGIN#> END Generated Text --> + <FullClassName>QtVsTools.Wizards.ItemWizard.QtClassWizard</FullClassName> + </WizardExtension> +</VSTemplate> diff --git a/Templates/qtclass/source.cpp b/Templates/qtclass/source.cpp new file mode 100644 index 0000000..7bdcd06 --- /dev/null +++ b/Templates/qtclass/source.cpp @@ -0,0 +1,8 @@ +$include$ + +$namespacebegin$$classname$::$classname$($signature$)$baseclasswithparent$ +{} + +$classname$::~$classname$() +{} +$namespaceend$ \ No newline at end of file diff --git a/Templates/quick/QtTemplate.Project.Quick.csproj b/Templates/quick/QtTemplate.Project.Quick.csproj index 3137fb0..1fa7f47 100644 --- a/Templates/quick/QtTemplate.Project.Quick.csproj +++ b/Templates/quick/QtTemplate.Project.Quick.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -114,9 +153,6 @@ <DesignTime>True</DesignTime> <DependentUpon>quick.vstemplate_TT</DependentUpon> </VSTemplate> - </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> </ItemGroup> <ItemGroup> <Content Include="main.cpp" /> diff --git a/Templates/quick/quick.vcxproj.filters b/Templates/quick/quick.vcxproj.filters index 1ed1ade..a26deb6 100644 --- a/Templates/quick/quick.vcxproj.filters +++ b/Templates/quick/quick.vcxproj.filters @@ -13,6 +13,10 @@ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> <Filter Include="Translation Files"> <UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier> <Extensions>ts</Extensions> diff --git a/Templates/resource/QtTemplate.Item.Resource.csproj b/Templates/resource/QtTemplate.Item.Resource.csproj index 6881f8a..7e22911 100644 --- a/Templates/resource/QtTemplate.Item.Resource.csproj +++ b/Templates/resource/QtTemplate.Item.Resource.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -103,17 +142,7 @@ <ItemGroup> <Content Include="resource.ico" /> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/Templates/server/QtTemplate.Project.Server.csproj b/Templates/server/QtTemplate.Project.Server.csproj index b30bb48..4c24a53 100644 --- a/Templates/server/QtTemplate.Project.Server.csproj +++ b/Templates/server/QtTemplate.Project.Server.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -122,17 +161,7 @@ <Content Include="stdafx.h" /> <Content Include="widget.ui" /> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/Templates/server/header.h b/Templates/server/header.h index b3a1e6e..f404141 100644 --- a/Templates/server/header.h +++ b/Templates/server/header.h @@ -10,7 +10,7 @@ Q_OBJECT public: - $classname$(QWidget *parent = Q_NULLPTR); + $classname$(QWidget *parent = nullptr); private: Ui::$classname$Class ui; diff --git a/Templates/server/server.vcxproj.filters b/Templates/server/server.vcxproj.filters index 1dca9ac..eb9be8d 100644 --- a/Templates/server/server.vcxproj.filters +++ b/Templates/server/server.vcxproj.filters @@ -3,7 +3,7 @@ <ItemGroup> <Filter Include="Source Files"> <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + <Extensions>qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> </Filter> <Filter Include="Header Files"> <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> diff --git a/Templates/translation/Properties/AssemblyInfo.cs b/Templates/translation/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7fcd1b7 --- /dev/null +++ b/Templates/translation/Properties/AssemblyInfo.cs @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +**************************************************************************** +<#@output extension="tt.cs" #> +<#@include file="$(SolutionDir)\version.tt" #> +** <#=WARNING_GENERATED_FILE#> +****************************************************************************/ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Translation")] +[assembly: AssemblyDescription("The Qt Visual Studio Tools allow developers to use the standard development environment without having to worry about any Qt-related build steps or tools.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Qt Company Ltd.")] +[assembly: AssemblyProduct("Qt Visual Studio Tools")] +[assembly: AssemblyCopyright("Copyright (C) 2016-2022 The Qt Company Ltd.")] +[assembly: AssemblyTrademark("The Qt Company Ltd. Qt and their respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("131278ae-99ef-45c0-8455-423ee8f123dc")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("<#=QT_VS_TOOLS_VERSION_ASSEMBLY#>")] +[assembly: AssemblyFileVersion("<#=QT_VS_TOOLS_VERSION_ASSEMBLY_FILE#>")] diff --git a/Templates/translation/QtTemplate.Item.Translation.csproj b/Templates/translation/QtTemplate.Item.Translation.csproj new file mode 100644 index 0000000..3b9a576 --- /dev/null +++ b/Templates/translation/QtTemplate.Item.Translation.csproj @@ -0,0 +1,155 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +--> +<Project ToolsVersion="$(VisualStudioVersion)" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <MinimumVisualStudioVersion>$(VisualStudioVersion)</MinimumVisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + </PropertyGroup> + <PropertyGroup> + <ApplicationIcon>translation.ico</ApplicationIcon> + </PropertyGroup> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <ProjectGuid>{202F4A6D-77CD-4992-AA53-01B585463287}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Translation</RootNamespace> + <AssemblyName>Translation</AssemblyName> + <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <GeneratePkgDefFile>false</GeneratePkgDefFile> + <IncludeAssemblyInVSIXContainer>false</IncludeAssemblyInVSIXContainer> + <IncludeDebugSymbolsInVSIXContainer>false</IncludeDebugSymbolsInVSIXContainer> + <IncludeDebugSymbolsInLocalVSIXDeployment>false</IncludeDebugSymbolsInLocalVSIXDeployment> + <CreateVsixContainer>false</CreateVsixContainer> + <DeployExtension>false</DeployExtension> + <DeployVSTemplates>false</DeployVSTemplates> + <CopyVsixManifestToOutput>false</CopyVsixManifestToOutput> + <CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory> + <CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> + <ItemGroup> + <T4Template Include="Properties\AssemblyInfo.cs"> + <Generator>TextTemplatingFileGenerator</Generator> + <OutputFile>Properties\AssemblyInfo.tt.cs</OutputFile> + <DependsOn>$(SolutionDir)\version.tt;$(SolutionDir)\common.tt</DependsOn> + <LastGenOutput>AssemblyInfo.tt.cs</LastGenOutput> + </T4Template> + <Compile Include="Properties\AssemblyInfo.tt.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>AssemblyInfo.cs</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <None Include="translation.ts" /> + </ItemGroup> + <ItemGroup> + <T4Template Include="translation.vstemplate_TT"> + <Generator>TextTemplatingFileGenerator</Generator> + <OutputFile>translation.vstemplate</OutputFile> + <DependsOn>$(SolutionDir)\version.tt;$(SolutionDir)\common.tt</DependsOn> + <LastGenOutput>translation.vstemplate</LastGenOutput> + </T4Template> + <VSTemplate Include="translation.vstemplate"> + <SubType>Designer</SubType> + <OutputSubPath>Qt</OutputSubPath> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>translation.vstemplate_TT</DependentUpon> + </VSTemplate> + </ItemGroup> + <ItemGroup> + <Content Include="translation.ico" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(SolutionDir)\transform.targets" /> + <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> +</Project> \ No newline at end of file diff --git a/Templates/translation/translation.ico b/Templates/translation/translation.ico new file mode 100644 index 0000000..1c4fb80 --- /dev/null +++ b/Templates/translation/translation.ico Binary files differ diff --git a/Templates/translation/translation.ts b/Templates/translation/translation.ts new file mode 100644 index 0000000..fda00e7 --- /dev/null +++ b/Templates/translation/translation.ts @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS > +<TS version="2.1" language="$cultureinfoname$"> +</TS> diff --git a/Templates/translation/translation.vstemplate_TT b/Templates/translation/translation.vstemplate_TT new file mode 100644 index 0000000..6ec4f47 --- /dev/null +++ b/Templates/translation/translation.vstemplate_TT @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +<#@output extension="vstemplate" #> +<#@include file="$(SolutionDir)\version.tt" #> + ** <#=WARNING_GENERATED_FILE#> + ***************************************************************************** +--> + +<VSTemplate Version="3.0.0" + xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" + xmlns:sdk="http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010" + Type="Item"> + <TemplateData> + <Name>Qt Translation File</Name> + <Description>Qt Translation File (.ts)</Description> + <ProjectType>VC</ProjectType> + <DefaultName>Translation.ts</DefaultName> + <ProvideDefaultName>true</ProvideDefaultName> + <LocationField>Enabled</LocationField> + <EnableLocationBrowseButton>true</EnableLocationBrowseButton> + <Icon>translation.ico</Icon> + <LanguageTag>Cpp</LanguageTag> + <PlatformTag>Windows</PlatformTag> + <PlatformTag>Linux</PlatformTag> + <ProjectTypeTag>Qt</ProjectTypeTag> + <ProjectTypeTag>Desktop</ProjectTypeTag> + <AppliesTo>VisualC</AppliesTo> + <TemplateGroupID>QtVsTools</TemplateGroupID> + <TemplateID>QtVsTools-QTranslation</TemplateID> + </TemplateData> + <TemplateContent> + <ProjectItem OpenInEditor="false" + ReplaceParameters="true" + TargetFileName="$tsfilename$">translation.ts</ProjectItem> + </TemplateContent> + <WizardExtension> + <!-- BEGIN Generated Text <#=XML_COMMENT_END#> + <Assembly>QtVsTools.Wizards, Version=<#=QT_VS_TOOLS_VERSION_ASSEMBLY#>, Culture=neutral, PublicKeyToken=null</Assembly> + <#=XML_COMMENT_BEGIN#> END Generated Text --> + <FullClassName>QtVsTools.Wizards.ItemWizard.TranslationWizard</FullClassName> + </WizardExtension> +</VSTemplate> diff --git a/Templates/widget/QtTemplate.Item.Widget.csproj b/Templates/widget/QtTemplate.Item.Widget.csproj index c31a8ea..b843926 100644 --- a/Templates/widget/QtTemplate.Item.Widget.csproj +++ b/Templates/widget/QtTemplate.Item.Widget.csproj @@ -78,6 +78,45 @@ <WarningLevel>4</WarningLevel> <UseVSHostingProcess>false</UseVSHostingProcess> </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> <ItemGroup> <T4Template Include="Properties\AssemblyInfo.cs"> <Generator>TextTemplatingFileGenerator</Generator> @@ -98,17 +137,7 @@ <OutputSubPath>Qt</OutputSubPath> </VSTemplate> </ItemGroup> - <ItemGroup> - <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\transform.targets" /> <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/Templates/widgetsclass/Properties/AssemblyInfo.cs b/Templates/widgetsclass/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e8d8a9c --- /dev/null +++ b/Templates/widgetsclass/Properties/AssemblyInfo.cs @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +**************************************************************************** +<#@output extension="tt.cs" #> +<#@include file="$(SolutionDir)\version.tt" #> +** <#=WARNING_GENERATED_FILE#> +****************************************************************************/ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WidgetsClass")] +[assembly: AssemblyDescription("The Qt Visual Studio Tools allow developers to use the standard development environment without having to worry about any Qt-related build steps or tools.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Qt Company Ltd.")] +[assembly: AssemblyProduct("Qt Visual Studio Tools")] +[assembly: AssemblyCopyright("Copyright (C) 2016-2022 The Qt Company Ltd.")] +[assembly: AssemblyTrademark("The Qt Company Ltd. Qt and their respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("665d1b79-1498-4d1a-8376-58394e150276")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("<#=QT_VS_TOOLS_VERSION_ASSEMBLY#>")] +[assembly: AssemblyFileVersion("<#=QT_VS_TOOLS_VERSION_ASSEMBLY_FILE#>")] diff --git a/Templates/widgetsclass/QtTemplate.Item.WidgetsClass.csproj b/Templates/widgetsclass/QtTemplate.Item.WidgetsClass.csproj new file mode 100644 index 0000000..5dbb07f --- /dev/null +++ b/Templates/widgetsclass/QtTemplate.Item.WidgetsClass.csproj @@ -0,0 +1,157 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +--> +<Project ToolsVersion="$(VisualStudioVersion)" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <MinimumVisualStudioVersion>$(VisualStudioVersion)</MinimumVisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + </PropertyGroup> + <PropertyGroup> + <ApplicationIcon>widgetsclass.ico</ApplicationIcon> + </PropertyGroup> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <ProjectGuid>{020422DA-33AB-4495-A439-7DAC2690795C}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>WidgetsClass</RootNamespace> + <AssemblyName>WidgetsClass</AssemblyName> + <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <GeneratePkgDefFile>false</GeneratePkgDefFile> + <IncludeAssemblyInVSIXContainer>false</IncludeAssemblyInVSIXContainer> + <IncludeDebugSymbolsInVSIXContainer>false</IncludeDebugSymbolsInVSIXContainer> + <IncludeDebugSymbolsInLocalVSIXDeployment>false</IncludeDebugSymbolsInLocalVSIXDeployment> + <CreateVsixContainer>false</CreateVsixContainer> + <DeployExtension>false</DeployExtension> + <DeployVSTemplates>false</DeployVSTemplates> + <CopyVsixManifestToOutput>false</CopyVsixManifestToOutput> + <CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory> + <CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VisualStudio_Validation)" Version="$(Version_Microsoft_VisualStudio_Validation)" /> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> + <ItemGroup> + <T4Template Include="Properties\AssemblyInfo.cs"> + <Generator>TextTemplatingFileGenerator</Generator> + <OutputFile>Properties\AssemblyInfo.tt.cs</OutputFile> + <DependsOn>$(SolutionDir)\version.tt;$(SolutionDir)\common.tt</DependsOn> + <LastGenOutput>AssemblyInfo.tt.cs</LastGenOutput> + </T4Template> + <Compile Include="Properties\AssemblyInfo.tt.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>AssemblyInfo.cs</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <None Include="widget.cpp" /> + <None Include="widget.h" /> + <None Include="widget.ui" /> + </ItemGroup> + <ItemGroup> + <T4Template Include="widgetsclass.vstemplate_TT"> + <Generator>TextTemplatingFileGenerator</Generator> + <OutputFile>widgetsclass.vstemplate</OutputFile> + <DependsOn>$(SolutionDir)\version.tt;$(SolutionDir)\common.tt</DependsOn> + <LastGenOutput>widgetsclass.vstemplate</LastGenOutput> + </T4Template> + <VSTemplate Include="widgetsclass.vstemplate"> + <SubType>Designer</SubType> + <OutputSubPath>Qt</OutputSubPath> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>widgetsclass.vstemplate_TT</DependentUpon> + </VSTemplate> + </ItemGroup> + <ItemGroup> + <Content Include="widgetsclass.ico" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(SolutionDir)\transform.targets" /> + <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> +</Project> \ No newline at end of file diff --git a/Templates/widgetsclass/widget.cpp b/Templates/widgetsclass/widget.cpp new file mode 100644 index 0000000..7718d6f --- /dev/null +++ b/Templates/widgetsclass/widget.cpp @@ -0,0 +1,11 @@ +$include$ + +$namespacebegin$$classname$::$classname$(QWidget *parent) + : $baseclass$(parent)$new$ +{ + $member$$operator$setupUi(this); +} + +$classname$::~$classname$() +{$delete$} +$namespaceend$ \ No newline at end of file diff --git a/Templates/widgetsclass/widget.h b/Templates/widgetsclass/widget.h new file mode 100644 index 0000000..e0cb40e --- /dev/null +++ b/Templates/widgetsclass/widget.h @@ -0,0 +1,15 @@ +#pragma once + +#include <$baseclass$> +#include "$ui_hdr$" +$forward_declare_class$ +$namespacebegin$class $classname$ : public $baseclass$$multiple_inheritance$ +{$qobject$ +public: + $classname$(QWidget *parent = nullptr); + ~$classname$(); + +private: + $ui_classname$ $asterisk$$member$$semicolon$ +}; +$namespaceend$ \ No newline at end of file diff --git a/Templates/widgetsclass/widget.ui b/Templates/widgetsclass/widget.ui new file mode 100644 index 0000000..74c429e --- /dev/null +++ b/Templates/widgetsclass/widget.ui @@ -0,0 +1,22 @@ +<UI version="4.0" > + <class>$classname$Class</class> + <widget class="$baseclass$" name="$classname$Class" > + <property name="objectName" > + <string notr="true">$classname$Class</string> + </property> + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle" > + <string>$classname$</string> + </property>$centralwidget$ + </widget> + <layoutDefault spacing="6" margin="11" /> + <pixmapfunction></pixmapfunction> + <connections/> +</UI> diff --git a/Templates/widgetsclass/widgetsclass.ico b/Templates/widgetsclass/widgetsclass.ico new file mode 100644 index 0000000..1c4fb80 --- /dev/null +++ b/Templates/widgetsclass/widgetsclass.ico Binary files differ diff --git a/Templates/widgetsclass/widgetsclass.vstemplate_TT b/Templates/widgetsclass/widgetsclass.vstemplate_TT new file mode 100644 index 0000000..89c5e79 --- /dev/null +++ b/Templates/widgetsclass/widgetsclass.vstemplate_TT @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ***************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +<#@output extension="vstemplate" #> +<#@include file="$(SolutionDir)\version.tt" #> + ** <#=WARNING_GENERATED_FILE#> + ***************************************************************************** +--> + +<VSTemplate Version="3.0.0" + xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" + xmlns:sdk="http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010" + Type="Item" > + <TemplateData> + <Name>Qt Widgets Class</Name> + <Description>Adds a Qt Widgets class to the project.</Description> + <ProjectType>VC</ProjectType> + <DefaultName>QtWidgetsClass</DefaultName> + <ProvideDefaultName>true</ProvideDefaultName> + <LocationField>Enabled</LocationField> + <EnableLocationBrowseButton>true</EnableLocationBrowseButton> + <Icon>widgetsclass.ico</Icon> + <LanguageTag>Cpp</LanguageTag> + <PlatformTag>Windows</PlatformTag> + <PlatformTag>Linux</PlatformTag> + <ProjectTypeTag>Qt</ProjectTypeTag> + <ProjectTypeTag>Desktop</ProjectTypeTag> + </TemplateData> + <TemplateContent> + <ProjectItem OpenInEditor="true" + ReplaceParameters="true" + TargetFileName="$sourcefilename$">widget.cpp</ProjectItem> + <ProjectItem ReplaceParameters="true" + TargetFileName="$headerfilename$">widget.h</ProjectItem> + <ProjectItem ReplaceParameters="true" + TargetFileName="$uifilename$">widget.ui</ProjectItem> + </TemplateContent> + <WizardExtension> + <!-- BEGIN Generated Text <#=XML_COMMENT_END#> + <Assembly>QtVsTools.Wizards, Version=<#=QT_VS_TOOLS_VERSION_ASSEMBLY#>, Culture=neutral, PublicKeyToken=null</Assembly> + <#=XML_COMMENT_BEGIN#> END Generated Text --> + <FullClassName>QtVsTools.Wizards.ItemWizard.WidgetsClassWizard</FullClassName> + </WizardExtension> +</VSTemplate> diff --git a/Tests/BigSolution/generator/Program.cs b/Tests/BigSolution/generator/Program.cs index 6100ac6..5624762 100644 --- a/Tests/BigSolution/generator/Program.cs +++ b/Tests/BigSolution/generator/Program.cs @@ -38,51 +38,27 @@ { internal class Program { - static void Main(string[] args) + static void GenerateProject( + StringBuilder genSolutionProjectRef, + StringBuilder genSolutionProjectConfigs, + string pathToTemplateDir, + string pathToGeneratedDir, + int projectCount, + string projectGuid, + string projectName, + string projectRef, + IEnumerable<string> projectConfigsList) { - var projectCount = args.Length > 0 ? Convert.ToInt32(args[0]) : 400; - var pathToTemplateDir = Path.GetFullPath(@"..\..\..\template"); - var pathToGeneratedDir = Path.GetFullPath(@"..\..\..\generated"); - var templateFiles = Directory.GetFiles( - pathToTemplateDir, "*", SearchOption.AllDirectories); - var solutionFilePath = templateFiles - .Where(x => Path.GetExtension(x) == ".sln") - .First(); - var solutionName = Path.GetFileName(solutionFilePath); - var solutionText = File.ReadAllText(solutionFilePath); - var projectFilePath = templateFiles - .Where(x => Path.GetExtension(x) == ".vcxproj") - .First(); - var projectText = File.ReadAllText(projectFilePath); - var projectName = Path.GetFileNameWithoutExtension(projectFilePath); - var projectGuidMatch = Regex.Match(projectText, @"<ProjectGuid>({[^}]+})<"); - var projectGuid = projectGuidMatch.Groups[1].Value; - - var projectRef = Regex - .Match(solutionText, - @"^Project.*" + projectGuid + @"""\r\nEndProject\r\n", RegexOptions.Multiline) - .Value; - - var projectConfigsList = Regex - .Matches(solutionText, - @"^\s+" + projectGuid + @".*\r\n", RegexOptions.Multiline) - .Cast<Match>() - .Select(x => x.Value); - var projectConfigs = string.Join("", projectConfigsList); - var projectFiles = Directory.GetFiles( Path.Combine(pathToTemplateDir, projectName), "*", SearchOption.TopDirectoryOnly); - if (Directory.Exists(pathToGeneratedDir)) - Directory.Delete(pathToGeneratedDir, true); - - var genSolutionProjectRef = new StringBuilder(); - var genSolutionProjectConfigs = new StringBuilder(); - - for (int i = 1; i <= projectCount; i++) { + bool singleProject = false; + for (int i = 1; !singleProject && i <= projectCount; i++) { var idxStr = string.Format("{0:D3}", i); var genProjectName = projectName.Replace("NNN", idxStr); + if (genProjectName == projectName) + singleProject = true; var genProjectDirPath = Path.Combine(pathToGeneratedDir, genProjectName); var genProjectGuid = projectGuid.Replace("000", idxStr); @@ -110,9 +86,66 @@ genSolutionProjectConfigs.Append(genProjectConfig); } } - var genSolutionText = solutionText - .Replace(projectRef, genSolutionProjectRef.ToString()) - .Replace(projectConfigs, genSolutionProjectConfigs.ToString()); + } + + static void Main(string[] args) + { + int projectCount; + if (args.Length == 0 || !int.TryParse(args[0], out projectCount)) { + string userProjectCount; + do { + Console.Write("Project count: "); + userProjectCount = Console.ReadLine(); + } while (!int.TryParse(userProjectCount, out projectCount)); + } + var pathToTemplateDir = Path.GetFullPath(@"..\..\..\template"); + var pathToGeneratedDir = Path.GetFullPath( + $@"..\..\..\generated_{DateTime.Now.ToString("yyyyMMddhhmmssfff")}"); + var templateFiles = Directory.GetFiles( + pathToTemplateDir, "*", SearchOption.AllDirectories); + var solutionFilePath = templateFiles + .Where(x => Path.GetExtension(x) == ".sln") + .First(); + var solutionName = Path.GetFileName(solutionFilePath); + var solutionText = File.ReadAllText(solutionFilePath); + var projectFilePaths = templateFiles + .Where(x => Path.GetExtension(x) == ".vcxproj"); + var genSolutionText = solutionText; + if (Directory.Exists(pathToGeneratedDir)) + Directory.Delete(pathToGeneratedDir, true); + foreach (var projectFilePath in projectFilePaths) { + var genSolutionProjectRef = new StringBuilder(); + var genSolutionProjectConfigs = new StringBuilder(); + var projectText = File.ReadAllText(projectFilePath); + var projectName = Path.GetFileNameWithoutExtension(projectFilePath); + var projectGuidMatch = Regex.Match(projectText, @"<ProjectGuid>({[^}]+})<"); + var projectGuid = projectGuidMatch.Groups[1].Value; + var projectRef = Regex + .Match(solutionText, + @"^Project.*" + projectGuid + @"""\r\nEndProject\r\n", + RegexOptions.Multiline | RegexOptions.IgnoreCase) + .Value; + var projectConfigsList = Regex + .Matches(solutionText, + @"^\s+" + projectGuid + @".*\r\n", + RegexOptions.Multiline | RegexOptions.IgnoreCase) + .Cast<Match>() + .Select(x => x.Value); + var projectConfigs = string.Join("", projectConfigsList); + GenerateProject( + genSolutionProjectRef, + genSolutionProjectConfigs, + pathToTemplateDir, + pathToGeneratedDir, + projectCount, + projectGuid, + projectName, + projectRef, + projectConfigsList); + genSolutionText = genSolutionText + .Replace(projectRef, genSolutionProjectRef.ToString()) + .Replace(projectConfigs, genSolutionProjectConfigs.ToString()); + } var genSolutionFilePath = Path.Combine(pathToGeneratedDir, solutionName); File.WriteAllText(genSolutionFilePath, genSolutionText); } diff --git a/Tests/BigSolution/template/BigProjectNNN/BigProjectNNN.vcxproj b/Tests/BigSolution/template/BigProjectNNN/BigProjectNNN.vcxproj index 2ec9d1f..886f40a 100644 --- a/Tests/BigSolution/template/BigProjectNNN/BigProjectNNN.vcxproj +++ b/Tests/BigSolution/template/BigProjectNNN/BigProjectNNN.vcxproj @@ -95,6 +95,14 @@ <QtUic Include="BigProjectNNN.ui" /> <QtRcc Include="BigProjectNNN.qrc" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\QtClassLibrary\QtClassLibrary.vcxproj"> + <Project>{ce78ec51-c4a0-465b-a161-21c257bd057b}</Project> + </ProjectReference> + <ProjectReference Include="..\StaticLib\StaticLib.vcxproj"> + <Project>{8463051a-b32c-43f0-9a77-9f223598aac9}</Project> + </ProjectReference> + </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> <Import Project="$(QtMsBuild)\qt.targets" /> diff --git a/Tests/BigSolution/template/BigProjectNNN/BigProjectQtClassNNN.h b/Tests/BigSolution/template/BigProjectNNN/BigProjectQtClassNNN.h index 66561fb..cb4d382 100644 --- a/Tests/BigSolution/template/BigProjectNNN/BigProjectQtClassNNN.h +++ b/Tests/BigSolution/template/BigProjectNNN/BigProjectQtClassNNN.h @@ -36,7 +36,7 @@ Q_OBJECT public: - BigProjectQtClassNNN(QWidget *parent = Q_NULLPTR); + BigProjectQtClassNNN(QWidget *parent = nullptr); private: Ui::BigProjectNNNUi ui; diff --git a/Tests/BigSolution/template/BigSolution.sln b/Tests/BigSolution/template/BigSolution.sln index 66a56f1..ee2c8e6 100644 --- a/Tests/BigSolution/template/BigSolution.sln +++ b/Tests/BigSolution/template/BigSolution.sln @@ -3,6 +3,10 @@ # Visual Studio Version 16 VisualStudioVersion = 16.0.31229.387 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtClassLibrary", "QtClassLibrary\QtClassLibrary.vcxproj", "{CE78EC51-C4A0-465B-A161-21C257BD057B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StaticLib", "StaticLib\StaticLib.vcxproj", "{8463051A-B32C-43F0-9A77-9F223598AAC9}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BigProjectNNN", "BigProjectNNN\BigProjectNNN.vcxproj", "{C032BE4B-48F7-465F-BA2A-44962223E000}" EndProject Global @@ -11,6 +15,14 @@ Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CE78EC51-C4A0-465B-A161-21C257BD057B}.Debug|x64.ActiveCfg = Debug|x64 + {CE78EC51-C4A0-465B-A161-21C257BD057B}.Debug|x64.Build.0 = Debug|x64 + {CE78EC51-C4A0-465B-A161-21C257BD057B}.Release|x64.ActiveCfg = Release|x64 + {CE78EC51-C4A0-465B-A161-21C257BD057B}.Release|x64.Build.0 = Release|x64 + {8463051A-B32C-43F0-9A77-9F223598AAC9}.Debug|x64.ActiveCfg = Debug|x64 + {8463051A-B32C-43F0-9A77-9F223598AAC9}.Debug|x64.Build.0 = Debug|x64 + {8463051A-B32C-43F0-9A77-9F223598AAC9}.Release|x64.ActiveCfg = Release|x64 + {8463051A-B32C-43F0-9A77-9F223598AAC9}.Release|x64.Build.0 = Release|x64 {C032BE4B-48F7-465F-BA2A-44962223E000}.Debug|x64.ActiveCfg = Debug|x64 {C032BE4B-48F7-465F-BA2A-44962223E000}.Debug|x64.Build.0 = Debug|x64 {C032BE4B-48F7-465F-BA2A-44962223E000}.Release|x64.ActiveCfg = Release|x64 diff --git a/Tests/BigSolution/template/QtClassLibrary/QtClass.cpp b/Tests/BigSolution/template/QtClassLibrary/QtClass.cpp new file mode 100644 index 0000000..e0be39f --- /dev/null +++ b/Tests/BigSolution/template/QtClassLibrary/QtClass.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "QtClass.h" + +QtClass::QtClass(QObject *parent) + : QObject(parent) +{ +} + +QtClass::~QtClass() +{ +} diff --git a/Tests/BigSolution/template/QtClassLibrary/QtClass.h b/Tests/BigSolution/template/QtClassLibrary/QtClass.h new file mode 100644 index 0000000..25117bf --- /dev/null +++ b/Tests/BigSolution/template/QtClassLibrary/QtClass.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once +#include "qtclasslibrary_global.h" + +#include <QObject> + +class QTCLASSLIBRARY_EXPORT QtClass : public QObject +{ + Q_OBJECT + +public: + QtClass(QObject *parent); + ~QtClass(); +}; diff --git a/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.cpp b/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.cpp new file mode 100644 index 0000000..2aea7ec --- /dev/null +++ b/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.cpp @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "QtClassLibrary.h" + +QtClassLibrary::QtClassLibrary() +{ +} diff --git a/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.h b/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.h new file mode 100644 index 0000000..076f26a --- /dev/null +++ b/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include "qtclasslibrary_global.h" + +class QTCLASSLIBRARY_EXPORT QtClassLibrary +{ +public: + QtClassLibrary(); +}; diff --git a/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.vcxproj b/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.vcxproj new file mode 100644 index 0000000..54fd6da --- /dev/null +++ b/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.vcxproj @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="$(VisualStudioVersion)" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{CE78EC51-C4A0-465B-A161-21C257BD057B}</ProjectGuid> + <Keyword>QtVS_v304</Keyword> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">10.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">10.0</WindowsTargetPlatformVersion> + <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings"> + <QtInstall>$(DefaultQtVersion)</QtInstall> + <QtModules>core</QtModules> + <QtBuildConfig>debug</QtBuildConfig> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings"> + <QtInstall>$(DefaultQtVersion)</QtInstall> + <QtModules>core</QtModules> + <QtBuildConfig>release</QtBuildConfig> + </PropertyGroup> + <Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(QtMsBuild)\Qt.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(QtMsBuild)\Qt.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <AllProjectIncludesArePublic>true</AllProjectIncludesArePublic> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <AllProjectIncludesArePublic>true</AllProjectIncludesArePublic> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ProjectReference> + <UseLibraryDependencyInputs>true</UseLibraryDependencyInputs> + </ProjectReference> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ProjectReference> + <UseLibraryDependencyInputs>true</UseLibraryDependencyInputs> + </ProjectReference> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <PreprocessorDefinitions>QTCLASSLIBRARY_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>None</DebugInformationFormat> + <Optimization>MaxSpeed</Optimization> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <PreprocessorDefinitions>QTCLASSLIBRARY_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <QtMoc Include="QtClass.h" /> + <ClInclude Include="qtclasslibrary_global.h" /> + <ClInclude Include="QtClassLibrary.h" /> + <ClCompile Include="QtClass.cpp" /> + <ClCompile Include="QtClassLibrary.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.vcxproj.filters b/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.vcxproj.filters new file mode 100644 index 0000000..5797d00 --- /dev/null +++ b/Tests/BigSolution/template/QtClassLibrary/QtClassLibrary.vcxproj.filters @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Translation Files"> + <UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier> + <Extensions>ts</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="qtclasslibrary_global.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClCompile Include="QtClassLibrary.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClInclude Include="QtClassLibrary.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <QtMoc Include="QtClass.h"> + <Filter>Header Files</Filter> + </QtMoc> + </ItemGroup> + <ItemGroup> + <ClCompile Include="QtClass.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/Tests/BigSolution/template/QtClassLibrary/qtclasslibrary_global.h b/Tests/BigSolution/template/QtClassLibrary/qtclasslibrary_global.h new file mode 100644 index 0000000..30029ba --- /dev/null +++ b/Tests/BigSolution/template/QtClassLibrary/qtclasslibrary_global.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include <QtCore/qglobal.h> + +#ifndef BUILD_STATIC +# if defined(QTCLASSLIBRARY_LIB) +# define QTCLASSLIBRARY_EXPORT Q_DECL_EXPORT +# else +# define QTCLASSLIBRARY_EXPORT Q_DECL_IMPORT +# endif +#else +# define QTCLASSLIBRARY_EXPORT +#endif diff --git a/Tests/BigSolution/template/StaticLib/Header.h b/Tests/BigSolution/template/StaticLib/Header.h new file mode 100644 index 0000000..69b048e --- /dev/null +++ b/Tests/BigSolution/template/StaticLib/Header.h @@ -0,0 +1,4 @@ +#pragma once + +void foobar(); + diff --git a/Tests/BigSolution/template/StaticLib/StaticLib.cpp b/Tests/BigSolution/template/StaticLib/StaticLib.cpp new file mode 100644 index 0000000..85cd0de --- /dev/null +++ b/Tests/BigSolution/template/StaticLib/StaticLib.cpp @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +void foobar() +{ +} diff --git a/Tests/BigSolution/template/StaticLib/StaticLib.vcxproj b/Tests/BigSolution/template/StaticLib/StaticLib.vcxproj new file mode 100644 index 0000000..e250860 --- /dev/null +++ b/Tests/BigSolution/template/StaticLib/StaticLib.vcxproj @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>16.0</VCProjectVersion> + <Keyword>Win32Proj</Keyword> + <ProjectGuid>{8463051a-b32c-43f0-9a77-9f223598aac9}</ProjectGuid> + <RootNamespace>StaticLib</RootNamespace> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <AllProjectIncludesArePublic>true</AllProjectIncludesArePublic> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <AllProjectIncludesArePublic>true</AllProjectIncludesArePublic> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <SubSystem> + </SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <SubSystem> + </SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="StaticLib.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Header.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Tests/BigSolution/template/StaticLib/StaticLib.vcxproj.filters b/Tests/BigSolution/template/StaticLib/StaticLib.vcxproj.filters new file mode 100644 index 0000000..55c2e2a --- /dev/null +++ b/Tests/BigSolution/template/StaticLib/StaticLib.vcxproj.filters @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="StaticLib.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Header.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/Tests/BigSolution/template/loop_msbuild.bat b/Tests/BigSolution/template/loop_msbuild.bat new file mode 100644 index 0000000..24854c0 --- /dev/null +++ b/Tests/BigSolution/template/loop_msbuild.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +SET TOTAL=0 +SET FAIL=0 +SET RATE=0 +SET USER_QUIT=0 +SET PAD=..00 + +:loop + CLS + SET RATE=%PAD%%RATE% + ECHO ################################################################################ + ECHO # Total: %TOTAL%, Failed: %FAIL%...%RATE:~-4,-2%,%RATE:~-2%%% + ECHO ################################################################################ + IF %USER_QUIT% EQU 1 GOTO quit + SET /A "TOTAL+=1" + msbuild %* ^ + /m /bl /v:m /nologo ^ + && ( + DEL last_build_ok.binlog 2> NUL + COPY msbuild.binlog last_build_ok.binlog > NUL + ) || ( + SET /A "FAIL+=1" + COPY msbuild.binlog error_build_%TOTAL%.binlog > NUL + ) + SET /A "RATE=(FAIL*100*100)/(TOTAL)" + ECHO ################################################################################ + CHOICE /C QNOP /N /T 1 /D N /M "# [N]ext / [O]pen Log / [P]ause / [Q]uit ?" + IF %ERRORLEVEL% EQU 3 ( + START "" msbuild.binlog + PAUSE + ) + IF %ERRORLEVEL% EQU 4 PAUSE + SET USER_QUIT=%ERRORLEVEL% + GOTO :loop +:quit diff --git a/Tests/ProjectFormats/100/QtProjectV100.cpp b/Tests/ProjectFormats/100/QtProjectV100.cpp new file mode 100644 index 0000000..19581ed --- /dev/null +++ b/Tests/ProjectFormats/100/QtProjectV100.cpp @@ -0,0 +1,10 @@ +#include "QtProjectV100.h" + +QtProjectV100::QtProjectV100(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} + +QtProjectV100::~QtProjectV100() +{} diff --git a/Tests/ProjectFormats/100/QtProjectV100.h b/Tests/ProjectFormats/100/QtProjectV100.h new file mode 100644 index 0000000..17c9eff --- /dev/null +++ b/Tests/ProjectFormats/100/QtProjectV100.h @@ -0,0 +1,16 @@ +#pragma once + +#include <QtWidgets/QMainWindow> +#include "ui_QtProjectV100.h" + +class QtProjectV100 : public QMainWindow +{ + Q_OBJECT + +public: + QtProjectV100(QWidget *parent = nullptr); + ~QtProjectV100(); + +private: + Ui::QtProjectV100Class ui; +}; diff --git a/Tests/ProjectFormats/100/QtProjectV100.pro b/Tests/ProjectFormats/100/QtProjectV100.pro new file mode 100644 index 0000000..bcf1b07 --- /dev/null +++ b/Tests/ProjectFormats/100/QtProjectV100.pro @@ -0,0 +1,6 @@ +QT += widgets +HEADERS = QtProjectV100.h +FORMS = QtProjectV100.ui +RESOURCES = QtProjectV100.qrc +SOURCES = QtProjectV100.cpp \ + main.cpp diff --git a/Tests/ProjectFormats/100/QtProjectV100.qrc b/Tests/ProjectFormats/100/QtProjectV100.qrc new file mode 100644 index 0000000..c2c4dd0 --- /dev/null +++ b/Tests/ProjectFormats/100/QtProjectV100.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="QtProjectV100"> + </qresource> +</RCC> diff --git a/Tests/ProjectFormats/100/QtProjectV100.ui b/Tests/ProjectFormats/100/QtProjectV100.ui new file mode 100644 index 0000000..4fe7f33 --- /dev/null +++ b/Tests/ProjectFormats/100/QtProjectV100.ui @@ -0,0 +1,28 @@ +<UI version="4.0" > + <class>QtProjectV100Class</class> + <widget class="QMainWindow" name="QtProjectV100Class" > + <property name="objectName" > + <string notr="true">QtProjectV100Class</string> + </property> + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle" > + <string>QtProjectV100</string> + </property> <widget class="QMenuBar" name="menuBar" /> + <widget class="QToolBar" name="mainToolBar" /> + <widget class="QWidget" name="centralWidget" /> + <widget class="QStatusBar" name="statusBar" /> + </widget> + <layoutDefault spacing="6" margin="11" /> + <pixmapfunction></pixmapfunction> + <resources> + <include location="QtProjectV100.qrc"/> + </resources> + <connections/> +</UI> diff --git a/Tests/ProjectFormats/100/QtProjectV100.vcxproj b/Tests/ProjectFormats/100/QtProjectV100.vcxproj new file mode 100644 index 0000000..347aa54 --- /dev/null +++ b/Tests/ProjectFormats/100/QtProjectV100.vcxproj @@ -0,0 +1,215 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{E5EA0EEF-BDC2-3484-A4F0-BA6C71E224CF}</ProjectGuid> + <RootNamespace>QtProjectV100</RootNamespace> + <Keyword>Qt4VSv1.0</Keyword> + <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <PlatformToolset>v142</PlatformToolset> + <OutputDirectory>release\</OutputDirectory> + <ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage> + <CharacterSet>NotSet</CharacterSet> + <ConfigurationType>Application</ConfigurationType> + <IntermediateDirectory>release\</IntermediateDirectory> + <PrimaryOutput>QtProjectV100</PrimaryOutput> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <PlatformToolset>v142</PlatformToolset> + <OutputDirectory>debug\</OutputDirectory> + <ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage> + <CharacterSet>NotSet</CharacterSet> + <ConfigurationType>Application</ConfigurationType> + <IntermediateDirectory>debug\</IntermediateDirectory> + <PrimaryOutput>QtProjectV100</PrimaryOutput> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\</IntDir> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">QtProjectV100</TargetName> + <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\</IntDir> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">QtProjectV100</TargetName> + <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <AdditionalIncludeDirectories>.;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtWidgets;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtGui;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtANGLE;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtCore;release;.;/include;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\win32-msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions> + <AssemblerListingLocation>release\</AssemblerListingLocation> + <BrowseInformation>false</BrowseInformation> + <DebugInformationFormat>None</DebugInformationFormat> + <DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ExceptionHandling>Sync</ExceptionHandling> + <ObjectFileName>release\</ObjectFileName> + <Optimization>MaxSpeed</Optimization> + <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;NDEBUG;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessToFile>false</PreprocessToFile> + <ProgramDataBaseFileName></ProgramDataBaseFileName> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <SuppressStartupBanner>true</SuppressStartupBanner> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <WarningLevel>Level3</WarningLevel> + </ClCompile> + <Link> + <AdditionalDependencies>C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Widgets.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Gui.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Core.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\qtmain.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>C:\openssl\lib;C:\Utils\my_sql\mysql-5.7.25-winx64\lib;C:\Utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions> + <DataExecutionPrevention>true</DataExecutionPrevention> + <GenerateDebugInformation>false</GenerateDebugInformation> + <IgnoreImportLibrary>true</IgnoreImportLibrary> + <LinkIncremental>false</LinkIncremental> + <OptimizeReferences>true</OptimizeReferences> + <OutputFile>$(OutDir)\QtProjectV100.exe</OutputFile> + <RandomizedBaseAddress>true</RandomizedBaseAddress> + <SubSystem>Windows</SubSystem> + <SuppressStartupBanner>true</SuppressStartupBanner> + </Link> + <Midl> + <DefaultCharType>Unsigned</DefaultCharType> + <EnableErrorChecks>None</EnableErrorChecks> + <WarningLevel>0</WarningLevel> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;NDEBUG;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <AdditionalIncludeDirectories>.;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtWidgets;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtGui;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtANGLE;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtCore;debug;.;/include;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\win32-msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions> + <AssemblerListingLocation>debug\</AssemblerListingLocation> + <BrowseInformation>false</BrowseInformation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ExceptionHandling>Sync</ExceptionHandling> + <ObjectFileName>debug\</ObjectFileName> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessToFile>false</PreprocessToFile> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <SuppressStartupBanner>true</SuppressStartupBanner> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <WarningLevel>Level3</WarningLevel> + </ClCompile> + <Link> + <AdditionalDependencies>C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Widgetsd.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Guid.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Cored.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\qtmaind.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>C:\openssl\lib;C:\Utils\my_sql\mysql-5.7.25-winx64\lib;C:\Utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions> + <DataExecutionPrevention>true</DataExecutionPrevention> + <GenerateDebugInformation>true</GenerateDebugInformation> + <IgnoreImportLibrary>true</IgnoreImportLibrary> + <OutputFile>$(OutDir)\QtProjectV100.exe</OutputFile> + <RandomizedBaseAddress>true</RandomizedBaseAddress> + <SubSystem>Windows</SubSystem> + <SuppressStartupBanner>true</SuppressStartupBanner> + </Link> + <Midl> + <DefaultCharType>Unsigned</DefaultCharType> + <EnableErrorChecks>None</EnableErrorChecks> + <WarningLevel>0</WarningLevel> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="QtProjectV100.cpp" /> + <ClCompile Include="main.cpp" /> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV100.h"> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">QtProjectV100.h;release\moc_predefs.h;C:\lib\Qt\5.15.10\msvc2019_64\bin\moc.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\moc.exe -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DNDEBUG -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB --compiler-flavor=msvc --include C:/dev/tests/formats/100/release/moc_predefs.h -IC:/lib/Qt/5.15.10/msvc2019_64/mkspecs/win32-msvc -IC:/dev/tests/formats/100 -IC:/lib/Qt/5.15.10/msvc2019_64/include -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtWidgets -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtGui -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtANGLE -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtCore -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\ATLMFC\include" -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\winrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\cppwinrt" QtProjectV100.h -o release\moc_QtProjectV100.cpp</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MOC QtProjectV100.h</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\moc_QtProjectV100.cpp;%(Outputs)</Outputs> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">QtProjectV100.h;debug\moc_predefs.h;C:\lib\Qt\5.15.10\msvc2019_64\bin\moc.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\moc.exe -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB --compiler-flavor=msvc --include C:/dev/tests/formats/100/debug/moc_predefs.h -IC:/lib/Qt/5.15.10/msvc2019_64/mkspecs/win32-msvc -IC:/dev/tests/formats/100 -IC:/lib/Qt/5.15.10/msvc2019_64/include -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtWidgets -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtGui -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtANGLE -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtCore -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\ATLMFC\include" -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\winrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\cppwinrt" QtProjectV100.h -o debug\moc_QtProjectV100.cpp</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">MOC QtProjectV100.h</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\moc_QtProjectV100.cpp;%(Outputs)</Outputs> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <ClCompile Include="debug\moc_QtProjectV100.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="release\moc_QtProjectV100.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + </ClCompile> + <CustomBuild Include="debug\moc_predefs.h.cbt"> + <FileType>Document</FileType> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -BxC:\lib\Qt\5.15.10\msvc2019_64\bin\qmake.exe -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E ..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\features\data\dummy.cpp 2>NUL >debug\moc_predefs.h</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Generate moc_predefs.h</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\moc_predefs.h;%(Outputs)</Outputs> + </CustomBuild> + <CustomBuild Include="release\moc_predefs.h.cbt"> + <FileType>Document</FileType> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -BxC:\lib\Qt\5.15.10\msvc2019_64\bin\qmake.exe -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E ..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\features\data\dummy.cpp 2>NUL >release\moc_predefs.h</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Generate moc_predefs.h</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\moc_predefs.h;%(Outputs)</Outputs> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + </CustomBuild> + <ClCompile Include="debug\qrc_QtProjectV100.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="release\qrc_QtProjectV100.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClInclude Include="ui_QtProjectV100.h" /> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV100.ui"> + <FileType>Document</FileType> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">QtProjectV100.ui;C:\lib\Qt\5.15.10\msvc2019_64\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\uic.exe QtProjectV100.ui -o ui_QtProjectV100.h</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">UIC QtProjectV100.ui</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">ui_QtProjectV100.h;%(Outputs)</Outputs> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">QtProjectV100.ui;C:\lib\Qt\5.15.10\msvc2019_64\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\uic.exe QtProjectV100.ui -o ui_QtProjectV100.h</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">UIC QtProjectV100.ui</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">ui_QtProjectV100.h;%(Outputs)</Outputs> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV100.qrc"> + <FileType>Document</FileType> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">QtProjectV100.qrc;C:\lib\Qt\5.15.10\msvc2019_64\bin\rcc.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\rcc.exe -name QtProjectV100 QtProjectV100.qrc -o release\qrc_QtProjectV100.cpp</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">RCC QtProjectV100.qrc</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\qrc_QtProjectV100.cpp;%(Outputs)</Outputs> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">QtProjectV100.qrc;C:\lib\Qt\5.15.10\msvc2019_64\bin\rcc.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\rcc.exe -name QtProjectV100 QtProjectV100.qrc -o debug\qrc_QtProjectV100.cpp</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">RCC QtProjectV100.qrc</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\qrc_QtProjectV100.cpp;%(Outputs)</Outputs> + </CustomBuild> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets" /> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/100/QtProjectV100.vcxproj.filters b/Tests/ProjectFormats/100/QtProjectV100.vcxproj.filters new file mode 100644 index 0000000..0c6827d --- /dev/null +++ b/Tests/ProjectFormats/100/QtProjectV100.vcxproj.filters @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + <Filter Include="Generated Files"> + <UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier> + <Extensions>cpp;c;cxx;moc;h;def;odl;idl;res;</Extensions> + </Filter> + <Filter Include="Generated Files"> + <UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier> + <Extensions>cpp;c;cxx;moc;h;def;odl;idl;res;</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="QtProjectV100.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV100.h"> + <Filter>Header Files</Filter> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <ClCompile Include="debug\moc_QtProjectV100.cpp"> + <Filter>Generated Files</Filter> + </ClCompile> + <ClCompile Include="release\moc_QtProjectV100.cpp"> + <Filter>Generated Files</Filter> + </ClCompile> + <CustomBuild Include="debug\moc_predefs.h.cbt"> + <Filter>Generated Files</Filter> + </CustomBuild> + <CustomBuild Include="release\moc_predefs.h.cbt"> + <Filter>Generated Files</Filter> + </CustomBuild> + <ClCompile Include="debug\qrc_QtProjectV100.cpp"> + <Filter>Generated Files</Filter> + </ClCompile> + <ClCompile Include="release\qrc_QtProjectV100.cpp"> + <Filter>Generated Files</Filter> + </ClCompile> + <ClInclude Include="ui_QtProjectV100.h"> + <Filter>Generated Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV100.ui"> + <Filter>Form Files</Filter> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV100.qrc"> + <Filter>Resource Files</Filter> + </CustomBuild> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/100/main.cpp b/Tests/ProjectFormats/100/main.cpp new file mode 100644 index 0000000..1c6e872 --- /dev/null +++ b/Tests/ProjectFormats/100/main.cpp @@ -0,0 +1,10 @@ +#include "QtProjectV100.h" +#include <QtWidgets/QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QtProjectV100 w; + w.show(); + return a.exec(); +} diff --git a/Tests/ProjectFormats/200/QtProjectV200.cpp b/Tests/ProjectFormats/200/QtProjectV200.cpp new file mode 100644 index 0000000..9247eb2 --- /dev/null +++ b/Tests/ProjectFormats/200/QtProjectV200.cpp @@ -0,0 +1,7 @@ +#include "QtProjectV200.h" + +QtProjectV200::QtProjectV200(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} diff --git a/Tests/ProjectFormats/200/QtProjectV200.h b/Tests/ProjectFormats/200/QtProjectV200.h new file mode 100644 index 0000000..dc1b953 --- /dev/null +++ b/Tests/ProjectFormats/200/QtProjectV200.h @@ -0,0 +1,15 @@ +#pragma once + +#include <QtWidgets/QMainWindow> +#include "ui_QtProjectV200.h" + +class QtProjectV200 : public QMainWindow +{ + Q_OBJECT + +public: + QtProjectV200(QWidget *parent = Q_NULLPTR); + +private: + Ui::QtProjectV200Class ui; +}; diff --git a/Tests/ProjectFormats/200/QtProjectV200.qrc b/Tests/ProjectFormats/200/QtProjectV200.qrc new file mode 100644 index 0000000..f5921b2 --- /dev/null +++ b/Tests/ProjectFormats/200/QtProjectV200.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="QtProjectV200"> + </qresource> +</RCC> diff --git a/Tests/ProjectFormats/200/QtProjectV200.sln b/Tests/ProjectFormats/200/QtProjectV200.sln new file mode 100644 index 0000000..32e1cd1 --- /dev/null +++ b/Tests/ProjectFormats/200/QtProjectV200.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtProjectV200", "QtProjectV200.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.ActiveCfg = Debug|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.Build.0 = Debug|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Tests/ProjectFormats/200/QtProjectV200.ui b/Tests/ProjectFormats/200/QtProjectV200.ui new file mode 100644 index 0000000..8eed476 --- /dev/null +++ b/Tests/ProjectFormats/200/QtProjectV200.ui @@ -0,0 +1,29 @@ +<UI version="4.0" > + <class>QtProjectV200Class</class> + <widget class="QMainWindow" name="QtProjectV200Class" > + <property name="objectName" > + <string notr="true">QtProjectV200Class</string> + </property> + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle" > + <string>QtProjectV200</string> + </property> + <widget class="QMenuBar" name="menuBar" /> + <widget class="QToolBar" name="mainToolBar" /> + <widget class="QWidget" name="centralWidget" /> + <widget class="QStatusBar" name="statusBar" /> + </widget> + <layoutDefault spacing="6" margin="11" /> + <pixmapfunction></pixmapfunction> + <resources> + <include location="QtProjectV200.qrc"/> + </resources> + <connections/> +</UI> diff --git a/Tests/ProjectFormats/200/QtProjectV200.vcxproj b/Tests/ProjectFormats/200/QtProjectV200.vcxproj new file mode 100644 index 0000000..1b4d671 --- /dev/null +++ b/Tests/ProjectFormats/200/QtProjectV200.vcxproj @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B12702AD-ABFB-343A-A199-8E24837244A3}</ProjectGuid> + <Keyword>Qt4VSv1.0</Keyword> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" /> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PreprocessorDefinitions>UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <Optimization>Disabled</Optimization> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <AdditionalLibraryDirectories>$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PreprocessorDefinitions>UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DebugInformationFormat /> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <AdditionalLibraryDirectories>$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <GenerateDebugInformation>false</GenerateDebugInformation> + <AdditionalDependencies>qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="GeneratedFiles\Debug\moc_QtProjectV200.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="GeneratedFiles\qrc_QtProjectV200.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + </PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + </PrecompiledHeader> + </ClCompile> + <ClCompile Include="GeneratedFiles\Release\moc_QtProjectV200.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="main.cpp" /> + <ClCompile Include="QtProjectV200.cpp" /> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV200.h"> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing QtProjectV200.h...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing QtProjectV200.h...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV200.ui"> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Uic%27ing %(Identity)...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Uic%27ing %(Identity)...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <ClInclude Include="GeneratedFiles\ui_QtProjectV200.h" /> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV200.qrc"> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(FullPath);%(AdditionalInputs)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Rcc%27ing %(Identity)...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs)</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp</Command> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(FullPath);%(AdditionalInputs)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Rcc%27ing %(Identity)...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs)</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp</Command> + </CustomBuild> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> + <ProjectExtensions> + <VisualStudio> + <UserProperties MocDir=".\GeneratedFiles\$(ConfigurationName)" UicDir=".\GeneratedFiles" RccDir=".\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" Qt5Version_x0020_x64="msvc2019_64" MocOptions="" /> + </VisualStudio> + </ProjectExtensions> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/200/QtProjectV200.vcxproj.filters b/Tests/ProjectFormats/200/QtProjectV200.vcxproj.filters new file mode 100644 index 0000000..81ea645 --- /dev/null +++ b/Tests/ProjectFormats/200/QtProjectV200.vcxproj.filters @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + <Filter Include="Generated Files"> + <UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier> + <Extensions>moc;h;cpp</Extensions> + <SourceControlFiles>False</SourceControlFiles> + </Filter> + <Filter Include="Generated Files\Debug"> + <UniqueIdentifier>{61dba4ef-747b-4196-a5ef-706b88f740b6}</UniqueIdentifier> + <Extensions>cpp;moc</Extensions> + <SourceControlFiles>False</SourceControlFiles> + </Filter> + <Filter Include="Generated Files\Release"> + <UniqueIdentifier>{52c84570-5db2-40f2-bcf4-841a0b66e6ee}</UniqueIdentifier> + <Extensions>cpp;moc</Extensions> + <SourceControlFiles>False</SourceControlFiles> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="QtProjectV200.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="GeneratedFiles\Debug\moc_QtProjectV200.cpp"> + <Filter>Generated Files\Debug</Filter> + </ClCompile> + <ClCompile Include="GeneratedFiles\Release\moc_QtProjectV200.cpp"> + <Filter>Generated Files\Release</Filter> + </ClCompile> + <ClCompile Include="GeneratedFiles\qrc_QtProjectV200.cpp"> + <Filter>Generated Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV200.h"> + <Filter>Header Files</Filter> + </CustomBuild> + <CustomBuild Include="QtProjectV200.ui"> + <Filter>Form Files</Filter> + </CustomBuild> + <CustomBuild Include="QtProjectV200.qrc"> + <Filter>Resource Files</Filter> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <ClInclude Include="GeneratedFiles\ui_QtProjectV200.h"> + <Filter>Generated Files</Filter> + </ClInclude> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/200/main.cpp b/Tests/ProjectFormats/200/main.cpp new file mode 100644 index 0000000..a033029 --- /dev/null +++ b/Tests/ProjectFormats/200/main.cpp @@ -0,0 +1,10 @@ +#include "QtProjectV200.h" +#include <QtWidgets/QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QtProjectV200 w; + w.show(); + return a.exec(); +} diff --git a/Tests/ProjectFormats/300/QtProjectV300.cpp b/Tests/ProjectFormats/300/QtProjectV300.cpp new file mode 100644 index 0000000..f896a7a --- /dev/null +++ b/Tests/ProjectFormats/300/QtProjectV300.cpp @@ -0,0 +1,7 @@ +#include "QtProjectV300.h" + +QtProjectV300::QtProjectV300(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} diff --git a/Tests/ProjectFormats/300/QtProjectV300.h b/Tests/ProjectFormats/300/QtProjectV300.h new file mode 100644 index 0000000..ceb967c --- /dev/null +++ b/Tests/ProjectFormats/300/QtProjectV300.h @@ -0,0 +1,15 @@ +#pragma once + +#include <QtWidgets/QMainWindow> +#include "ui_QtProjectV300.h" + +class QtProjectV300 : public QMainWindow +{ + Q_OBJECT + +public: + QtProjectV300(QWidget *parent = Q_NULLPTR); + +private: + Ui::QtProjectV300Class ui; +}; diff --git a/Tests/ProjectFormats/300/QtProjectV300.qrc b/Tests/ProjectFormats/300/QtProjectV300.qrc new file mode 100644 index 0000000..505a26b --- /dev/null +++ b/Tests/ProjectFormats/300/QtProjectV300.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="QtProjectV300"> + </qresource> +</RCC> diff --git a/Tests/ProjectFormats/300/QtProjectV300.sln b/Tests/ProjectFormats/300/QtProjectV300.sln new file mode 100644 index 0000000..d48f3dd --- /dev/null +++ b/Tests/ProjectFormats/300/QtProjectV300.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32106.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtProjectV300", "QtProjectV300.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.ActiveCfg = Debug|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.Build.0 = Debug|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {862404ED-03D5-41D1-B5BB-72FD8BD05038} + EndGlobalSection +EndGlobal diff --git a/Tests/ProjectFormats/300/QtProjectV300.ui b/Tests/ProjectFormats/300/QtProjectV300.ui new file mode 100644 index 0000000..74ffe53 --- /dev/null +++ b/Tests/ProjectFormats/300/QtProjectV300.ui @@ -0,0 +1,29 @@ +<UI version="4.0" > + <class>QtProjectV300Class</class> + <widget class="QMainWindow" name="QtProjectV300Class" > + <property name="objectName" > + <string notr="true">QtProjectV300Class</string> + </property> + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle" > + <string>QtProjectV300</string> + </property> + <widget class="QMenuBar" name="menuBar" /> + <widget class="QToolBar" name="mainToolBar" /> + <widget class="QWidget" name="centralWidget" /> + <widget class="QStatusBar" name="statusBar" /> + </widget> + <layoutDefault spacing="6" margin="11" /> + <pixmapfunction></pixmapfunction> + <resources> + <include location="QtProjectV300.qrc"/> + </resources> + <connections/> +</UI> diff --git a/Tests/ProjectFormats/300/QtProjectV300.vcxproj b/Tests/ProjectFormats/300/QtProjectV300.vcxproj new file mode 100644 index 0000000..276f090 --- /dev/null +++ b/Tests/ProjectFormats/300/QtProjectV300.vcxproj @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B12702AD-ABFB-343A-A199-8E24837244A3}</ProjectGuid> + <Keyword>QtVS_v300</Keyword> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <QtInstall>msvc2019_64</QtInstall> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <QtInstall>msvc2019_64</QtInstall> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup Condition="'$(QtMsBuild)'=='' or !Exists('$(QtMsBuild)\qt.targets')"> + <QtMsBuild>$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')"> + <Import Project="$(QtMsBuild)\qt.props" /> + </ImportGroup> + <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <QtModules>core;gui;widgets</QtModules> + </PropertyGroup> + <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <QtModules>core;gui;widgets</QtModules> + </PropertyGroup> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <Optimization>Disabled</Optimization> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat /> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="main.cpp" /> + <ClCompile Include="QtProjectV300.cpp" /> + </ItemGroup> + <ItemGroup> + <QtMoc Include="QtProjectV300.h" /> + </ItemGroup> + <ItemGroup> + <QtUic Include="QtProjectV300.ui" /> + </ItemGroup> + <ItemGroup> + <QtRcc Include="QtProjectV300.qrc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/300/QtProjectV300.vcxproj.filters b/Tests/ProjectFormats/300/QtProjectV300.vcxproj.filters new file mode 100644 index 0000000..8c77244 --- /dev/null +++ b/Tests/ProjectFormats/300/QtProjectV300.vcxproj.filters @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="QtProjectV300.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <QtMoc Include="QtProjectV300.h"> + <Filter>Header Files</Filter> + </QtMoc> + </ItemGroup> + <ItemGroup> + <QtUic Include="QtProjectV300.ui"> + <Filter>Form Files</Filter> + </QtUic> + </ItemGroup> + <ItemGroup> + <QtRcc Include="QtProjectV300.qrc"> + <Filter>Resource Files</Filter> + </QtRcc> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/300/main.cpp b/Tests/ProjectFormats/300/main.cpp new file mode 100644 index 0000000..48ff587 --- /dev/null +++ b/Tests/ProjectFormats/300/main.cpp @@ -0,0 +1,10 @@ +#include "QtProjectV300.h" +#include <QtWidgets/QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QtProjectV300 w; + w.show(); + return a.exec(); +} diff --git a/Tests/ProjectFormats/301/QtProjectV301.cpp b/Tests/ProjectFormats/301/QtProjectV301.cpp new file mode 100644 index 0000000..7a1e8ea --- /dev/null +++ b/Tests/ProjectFormats/301/QtProjectV301.cpp @@ -0,0 +1,7 @@ +#include "QtProjectV301.h" + +QtProjectV301::QtProjectV301(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} diff --git a/Tests/ProjectFormats/301/QtProjectV301.h b/Tests/ProjectFormats/301/QtProjectV301.h new file mode 100644 index 0000000..bfe8d95 --- /dev/null +++ b/Tests/ProjectFormats/301/QtProjectV301.h @@ -0,0 +1,15 @@ +#pragma once + +#include <QtWidgets/QMainWindow> +#include "ui_QtProjectV301.h" + +class QtProjectV301 : public QMainWindow +{ + Q_OBJECT + +public: + QtProjectV301(QWidget *parent = Q_NULLPTR); + +private: + Ui::QtProjectV301Class ui; +}; diff --git a/Tests/ProjectFormats/301/QtProjectV301.qrc b/Tests/ProjectFormats/301/QtProjectV301.qrc new file mode 100644 index 0000000..3c3a0f3 --- /dev/null +++ b/Tests/ProjectFormats/301/QtProjectV301.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="QtProjectV301"> + </qresource> +</RCC> diff --git a/Tests/ProjectFormats/301/QtProjectV301.sln b/Tests/ProjectFormats/301/QtProjectV301.sln new file mode 100644 index 0000000..909bab4 --- /dev/null +++ b/Tests/ProjectFormats/301/QtProjectV301.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32106.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtProjectV301", "QtProjectV301.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.ActiveCfg = Debug|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.Build.0 = Debug|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AD220BEA-2E4C-4346-9387-E61F9D9E6181} + EndGlobalSection +EndGlobal diff --git a/Tests/ProjectFormats/301/QtProjectV301.ui b/Tests/ProjectFormats/301/QtProjectV301.ui new file mode 100644 index 0000000..c25f457 --- /dev/null +++ b/Tests/ProjectFormats/301/QtProjectV301.ui @@ -0,0 +1,29 @@ +<UI version="4.0" > + <class>QtProjectV301Class</class> + <widget class="QMainWindow" name="QtProjectV301Class" > + <property name="objectName" > + <string notr="true">QtProjectV301Class</string> + </property> + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle" > + <string>QtProjectV301</string> + </property> + <widget class="QMenuBar" name="menuBar" /> + <widget class="QToolBar" name="mainToolBar" /> + <widget class="QWidget" name="centralWidget" /> + <widget class="QStatusBar" name="statusBar" /> + </widget> + <layoutDefault spacing="6" margin="11" /> + <pixmapfunction></pixmapfunction> + <resources> + <include location="QtProjectV301.qrc"/> + </resources> + <connections/> +</UI> diff --git a/Tests/ProjectFormats/301/QtProjectV301.vcxproj b/Tests/ProjectFormats/301/QtProjectV301.vcxproj new file mode 100644 index 0000000..78b4aa7 --- /dev/null +++ b/Tests/ProjectFormats/301/QtProjectV301.vcxproj @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B12702AD-ABFB-343A-A199-8E24837244A3}</ProjectGuid> + <Keyword>QtVS_v301</Keyword> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup Condition="'$(QtMsBuild)'=='' or !Exists('$(QtMsBuild)\qt.targets')"> + <QtMsBuild>$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + </PropertyGroup> + <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + </PropertyGroup> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')"> + <Import Project="$(QtMsBuild)\qt.props" /> + </ImportGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <Optimization>Disabled</Optimization> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat /> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="main.cpp" /> + <ClCompile Include="QtProjectV301.cpp" /> + </ItemGroup> + <ItemGroup> + <QtMoc Include="QtProjectV301.h" /> + </ItemGroup> + <ItemGroup> + <QtUic Include="QtProjectV301.ui" /> + </ItemGroup> + <ItemGroup> + <QtRcc Include="QtProjectV301.qrc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/301/QtProjectV301.vcxproj.filters b/Tests/ProjectFormats/301/QtProjectV301.vcxproj.filters new file mode 100644 index 0000000..62f11c2 --- /dev/null +++ b/Tests/ProjectFormats/301/QtProjectV301.vcxproj.filters @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="QtProjectV301.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <QtMoc Include="QtProjectV301.h"> + <Filter>Header Files</Filter> + </QtMoc> + </ItemGroup> + <ItemGroup> + <QtUic Include="QtProjectV301.ui"> + <Filter>Form Files</Filter> + </QtUic> + </ItemGroup> + <ItemGroup> + <QtRcc Include="QtProjectV301.qrc"> + <Filter>Resource Files</Filter> + </QtRcc> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/301/main.cpp b/Tests/ProjectFormats/301/main.cpp new file mode 100644 index 0000000..f12d171 --- /dev/null +++ b/Tests/ProjectFormats/301/main.cpp @@ -0,0 +1,10 @@ +#include "QtProjectV301.h" +#include <QtWidgets/QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QtProjectV301 w; + w.show(); + return a.exec(); +} diff --git a/Tests/ProjectFormats/302/QtProjectV302.cpp b/Tests/ProjectFormats/302/QtProjectV302.cpp new file mode 100644 index 0000000..a7d523a --- /dev/null +++ b/Tests/ProjectFormats/302/QtProjectV302.cpp @@ -0,0 +1,7 @@ +#include "QtProjectV302.h" + +QtProjectV302::QtProjectV302(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} diff --git a/Tests/ProjectFormats/302/QtProjectV302.h b/Tests/ProjectFormats/302/QtProjectV302.h new file mode 100644 index 0000000..3cef345 --- /dev/null +++ b/Tests/ProjectFormats/302/QtProjectV302.h @@ -0,0 +1,15 @@ +#pragma once + +#include <QtWidgets/QMainWindow> +#include "ui_QtProjectV302.h" + +class QtProjectV302 : public QMainWindow +{ + Q_OBJECT + +public: + QtProjectV302(QWidget *parent = Q_NULLPTR); + +private: + Ui::QtProjectV302Class ui; +}; diff --git a/Tests/ProjectFormats/302/QtProjectV302.qrc b/Tests/ProjectFormats/302/QtProjectV302.qrc new file mode 100644 index 0000000..de388f6 --- /dev/null +++ b/Tests/ProjectFormats/302/QtProjectV302.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="QtProjectV302"> + </qresource> +</RCC> diff --git a/Tests/ProjectFormats/302/QtProjectV302.sln b/Tests/ProjectFormats/302/QtProjectV302.sln new file mode 100644 index 0000000..5cc4823 --- /dev/null +++ b/Tests/ProjectFormats/302/QtProjectV302.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32106.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtProjectV302", "QtProjectV302.vcxproj", "{10A7CC05-6663-4C63-906F-E56EDF8218CA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {10A7CC05-6663-4C63-906F-E56EDF8218CA}.Debug|x64.ActiveCfg = Debug|x64 + {10A7CC05-6663-4C63-906F-E56EDF8218CA}.Debug|x64.Build.0 = Debug|x64 + {10A7CC05-6663-4C63-906F-E56EDF8218CA}.Release|x64.ActiveCfg = Release|x64 + {10A7CC05-6663-4C63-906F-E56EDF8218CA}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4FB5DF86-4C19-4C53-B0CC-EAA09A44D321} + EndGlobalSection +EndGlobal diff --git a/Tests/ProjectFormats/302/QtProjectV302.ui b/Tests/ProjectFormats/302/QtProjectV302.ui new file mode 100644 index 0000000..4e0ff07 --- /dev/null +++ b/Tests/ProjectFormats/302/QtProjectV302.ui @@ -0,0 +1,28 @@ +<UI version="4.0" > + <class>QtProjectV302Class</class> + <widget class="QMainWindow" name="QtProjectV302Class" > + <property name="objectName" > + <string notr="true">QtProjectV302Class</string> + </property> + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle" > + <string>QtProjectV302</string> + </property> <widget class="QMenuBar" name="menuBar" /> + <widget class="QToolBar" name="mainToolBar" /> + <widget class="QWidget" name="centralWidget" /> + <widget class="QStatusBar" name="statusBar" /> + </widget> + <layoutDefault spacing="6" margin="11" /> + <pixmapfunction></pixmapfunction> + <resources> + <include location="QtProjectV302.qrc"/> + </resources> + <connections/> +</UI> diff --git a/Tests/ProjectFormats/302/QtProjectV302.vcxproj b/Tests/ProjectFormats/302/QtProjectV302.vcxproj new file mode 100644 index 0000000..05b8241 --- /dev/null +++ b/Tests/ProjectFormats/302/QtProjectV302.vcxproj @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{10A7CC05-6663-4C63-906F-E56EDF8218CA}</ProjectGuid> + <Keyword>QtVS_v302</Keyword> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')" + >$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Target Name="QtMsBuildNotFound" + BeforeTargets="CustomBuild;ClCompile" + Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" + Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>debug</QtBuildConfig> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>release</QtBuildConfig> + </PropertyGroup> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')"> + <Import Project="$(QtMsBuild)\qt.props" /> + </ImportGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>None</DebugInformationFormat> + <Optimization>MaxSpeed</Optimization> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <QtRcc Include="QtProjectV302.qrc"/> + <QtUic Include="QtProjectV302.ui"/> + <QtMoc Include="QtProjectV302.h"/> + <ClCompile Include="QtProjectV302.cpp"/> + <ClCompile Include="main.cpp"/> + + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/302/QtProjectV302.vcxproj.filters b/Tests/ProjectFormats/302/QtProjectV302.vcxproj.filters new file mode 100644 index 0000000..c68f29a --- /dev/null +++ b/Tests/ProjectFormats/302/QtProjectV302.vcxproj.filters @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + </ItemGroup> + <ItemGroup> + <QtUic Include="QtProjectV302.ui"> + <Filter>Resource Files</Filter> + </QtUic> + <QtMoc Include="QtProjectV302.h"> + <Filter>Header Files</Filter> + </QtMoc> + <ClCompile Include="QtProjectV302.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ResourceCompile Include="$pro_name$.rc"> + </ResourceCompile> + <None Include="$pro_name$.ico"> + <Filter>Resource Files</Filter> + </None> + <None Include="$pro_name$.def"> + <Filter>Resource Files</Filter> + </None> + + </ItemGroup> +</Project> diff --git a/Tests/ProjectFormats/302/main.cpp b/Tests/ProjectFormats/302/main.cpp new file mode 100644 index 0000000..aa6a9e2 --- /dev/null +++ b/Tests/ProjectFormats/302/main.cpp @@ -0,0 +1,10 @@ +#include "QtProjectV302.h" +#include <QtWidgets/QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QtProjectV302 w; + w.show(); + return a.exec(); +} diff --git a/Tests/ProjectFormats/303/QtProjectV303.cpp b/Tests/ProjectFormats/303/QtProjectV303.cpp new file mode 100644 index 0000000..9c2b3ff --- /dev/null +++ b/Tests/ProjectFormats/303/QtProjectV303.cpp @@ -0,0 +1,7 @@ +#include "QtProjectV303.h" + +QtProjectV303::QtProjectV303(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} diff --git a/Tests/ProjectFormats/303/QtProjectV303.h b/Tests/ProjectFormats/303/QtProjectV303.h new file mode 100644 index 0000000..777c5fd --- /dev/null +++ b/Tests/ProjectFormats/303/QtProjectV303.h @@ -0,0 +1,15 @@ +#pragma once + +#include <QtWidgets/QMainWindow> +#include "ui_QtProjectV303.h" + +class QtProjectV303 : public QMainWindow +{ + Q_OBJECT + +public: + QtProjectV303(QWidget *parent = Q_NULLPTR); + +private: + Ui::QtProjectV303Class ui; +}; diff --git a/Tests/ProjectFormats/303/QtProjectV303.qrc b/Tests/ProjectFormats/303/QtProjectV303.qrc new file mode 100644 index 0000000..7af7692 --- /dev/null +++ b/Tests/ProjectFormats/303/QtProjectV303.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="QtProjectV303"> + </qresource> +</RCC> diff --git a/Tests/ProjectFormats/303/QtProjectV303.sln b/Tests/ProjectFormats/303/QtProjectV303.sln new file mode 100644 index 0000000..641c2a5 --- /dev/null +++ b/Tests/ProjectFormats/303/QtProjectV303.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32106.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtProjectV303", "QtProjectV303.vcxproj", "{812E4050-B861-4918-A0DC-53053B848372}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {812E4050-B861-4918-A0DC-53053B848372}.Debug|x64.ActiveCfg = Debug|x64 + {812E4050-B861-4918-A0DC-53053B848372}.Debug|x64.Build.0 = Debug|x64 + {812E4050-B861-4918-A0DC-53053B848372}.Release|x64.ActiveCfg = Release|x64 + {812E4050-B861-4918-A0DC-53053B848372}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7F50220B-20CF-415F-80A5-DA078F8F82BF} + EndGlobalSection +EndGlobal diff --git a/Tests/ProjectFormats/303/QtProjectV303.ui b/Tests/ProjectFormats/303/QtProjectV303.ui new file mode 100644 index 0000000..8295da9 --- /dev/null +++ b/Tests/ProjectFormats/303/QtProjectV303.ui @@ -0,0 +1,28 @@ +<UI version="4.0" > + <class>QtProjectV303Class</class> + <widget class="QMainWindow" name="QtProjectV303Class" > + <property name="objectName" > + <string notr="true">QtProjectV303Class</string> + </property> + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle" > + <string>QtProjectV303</string> + </property> <widget class="QMenuBar" name="menuBar" /> + <widget class="QToolBar" name="mainToolBar" /> + <widget class="QWidget" name="centralWidget" /> + <widget class="QStatusBar" name="statusBar" /> + </widget> + <layoutDefault spacing="6" margin="11" /> + <pixmapfunction></pixmapfunction> + <resources> + <include location="QtProjectV303.qrc"/> + </resources> + <connections/> +</UI> diff --git a/Tests/ProjectFormats/303/QtProjectV303.vcxproj b/Tests/ProjectFormats/303/QtProjectV303.vcxproj new file mode 100644 index 0000000..9c3febf --- /dev/null +++ b/Tests/ProjectFormats/303/QtProjectV303.vcxproj @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{812E4050-B861-4918-A0DC-53053B848372}</ProjectGuid> + <Keyword>QtVS_v303</Keyword> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')" + >$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Target Name="QtMsBuildNotFound" + BeforeTargets="CustomBuild;ClCompile" + Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" + Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>debug</QtBuildConfig> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>release</QtBuildConfig> + </PropertyGroup> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')"> + <Import Project="$(QtMsBuild)\qt.props" /> + </ImportGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>None</DebugInformationFormat> + <Optimization>MaxSpeed</Optimization> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <QtRcc Include="QtProjectV303.qrc"/> + <QtUic Include="QtProjectV303.ui"/> + <QtMoc Include="QtProjectV303.h"/> + <ClCompile Include="QtProjectV303.cpp"/> + <ClCompile Include="main.cpp"/> + + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/303/QtProjectV303.vcxproj.filters b/Tests/ProjectFormats/303/QtProjectV303.vcxproj.filters new file mode 100644 index 0000000..ebb32d8 --- /dev/null +++ b/Tests/ProjectFormats/303/QtProjectV303.vcxproj.filters @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + </ItemGroup> + <ItemGroup> + <QtRcc Include="QtProjectV303.qrc"> + <Filter>Resource Files</Filter> + </QtRcc> + <QtUic Include="QtProjectV303.ui"> + <Filter>Resource Files</Filter> + </QtUic> + <QtMoc Include="QtProjectV303.h"> + <Filter>Header Files</Filter> + </QtMoc> + <ClCompile Include="QtProjectV303.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ResourceCompile Include="$pro_name$.rc"> + </ResourceCompile> + <None Include="$pro_name$.ico"> + <Filter>Resource Files</Filter> + </None> + <None Include="$pro_name$.def"> + <Filter>Resource Files</Filter> + </None> + + </ItemGroup> +</Project> diff --git a/Tests/ProjectFormats/303/main.cpp b/Tests/ProjectFormats/303/main.cpp new file mode 100644 index 0000000..7d8e068 --- /dev/null +++ b/Tests/ProjectFormats/303/main.cpp @@ -0,0 +1,10 @@ +#include "QtProjectV303.h" +#include <QtWidgets/QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QtProjectV303 w; + w.show(); + return a.exec(); +} diff --git a/Tests/ProjectFormats/304/QtProjectV304.cpp b/Tests/ProjectFormats/304/QtProjectV304.cpp new file mode 100644 index 0000000..5f32d67 --- /dev/null +++ b/Tests/ProjectFormats/304/QtProjectV304.cpp @@ -0,0 +1,10 @@ +#include "QtProjectV304.h" + +QtProjectV304::QtProjectV304(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} + +QtProjectV304::~QtProjectV304() +{} diff --git a/Tests/ProjectFormats/304/QtProjectV304.h b/Tests/ProjectFormats/304/QtProjectV304.h new file mode 100644 index 0000000..ecd09cd --- /dev/null +++ b/Tests/ProjectFormats/304/QtProjectV304.h @@ -0,0 +1,16 @@ +#pragma once + +#include <QtWidgets/QMainWindow> +#include "ui_QtProjectV304.h" + +class QtProjectV304 : public QMainWindow +{ + Q_OBJECT + +public: + QtProjectV304(QWidget *parent = nullptr); + ~QtProjectV304(); + +private: + Ui::QtProjectV304Class ui; +}; diff --git a/Tests/ProjectFormats/304/QtProjectV304.qrc b/Tests/ProjectFormats/304/QtProjectV304.qrc new file mode 100644 index 0000000..3466c73 --- /dev/null +++ b/Tests/ProjectFormats/304/QtProjectV304.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="QtProjectV304"> + </qresource> +</RCC> diff --git a/Tests/ProjectFormats/304/QtProjectV304.sln b/Tests/ProjectFormats/304/QtProjectV304.sln new file mode 100644 index 0000000..3ebf58a --- /dev/null +++ b/Tests/ProjectFormats/304/QtProjectV304.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31919.166 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtProjectV304", "QtProjectV304.vcxproj", "{923588D5-2AA5-4B0F-8110-56BEEBB531D5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {923588D5-2AA5-4B0F-8110-56BEEBB531D5}.Debug|x64.ActiveCfg = Debug|x64 + {923588D5-2AA5-4B0F-8110-56BEEBB531D5}.Debug|x64.Build.0 = Debug|x64 + {923588D5-2AA5-4B0F-8110-56BEEBB531D5}.Release|x64.ActiveCfg = Release|x64 + {923588D5-2AA5-4B0F-8110-56BEEBB531D5}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AE3F49BF-2193-402A-AA0C-E77FF9B63160} + EndGlobalSection +EndGlobal diff --git a/Tests/ProjectFormats/304/QtProjectV304.ui b/Tests/ProjectFormats/304/QtProjectV304.ui new file mode 100644 index 0000000..73f83d6 --- /dev/null +++ b/Tests/ProjectFormats/304/QtProjectV304.ui @@ -0,0 +1,28 @@ +<UI version="4.0" > + <class>QtProjectV304Class</class> + <widget class="QMainWindow" name="QtProjectV304Class" > + <property name="objectName" > + <string notr="true">QtProjectV304Class</string> + </property> + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle" > + <string>QtProjectV304</string> + </property> <widget class="QMenuBar" name="menuBar" /> + <widget class="QToolBar" name="mainToolBar" /> + <widget class="QWidget" name="centralWidget" /> + <widget class="QStatusBar" name="statusBar" /> + </widget> + <layoutDefault spacing="6" margin="11" /> + <pixmapfunction></pixmapfunction> + <resources> + <include location="QtProjectV304.qrc"/> + </resources> + <connections/> +</UI> diff --git a/Tests/ProjectFormats/304/QtProjectV304.vcxproj b/Tests/ProjectFormats/304/QtProjectV304.vcxproj new file mode 100644 index 0000000..9c43ee5 --- /dev/null +++ b/Tests/ProjectFormats/304/QtProjectV304.vcxproj @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{923588D5-2AA5-4B0F-8110-56BEEBB531D5}</ProjectGuid> + <Keyword>QtVS_v304</Keyword> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')" + >$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v143</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v143</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings"> + <QtInstall>5.15.10_msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>debug</QtBuildConfig> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings"> + <QtInstall>5.15.10_msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>release</QtBuildConfig> + </PropertyGroup> + <Target Name="QtMsBuildNotFound" + BeforeTargets="CustomBuild;ClCompile" + Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" + Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(QtMsBuild)\Qt.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(QtMsBuild)\Qt.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>None</DebugInformationFormat> + <Optimization>MaxSpeed</Optimization> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <QtRcc Include="QtProjectV304.qrc"/> + <QtUic Include="QtProjectV304.ui"/> + <QtMoc Include="QtProjectV304.h"/> + <ClCompile Include="QtProjectV304.cpp"/> + <ClCompile Include="main.cpp"/> + + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Tests/ProjectFormats/304/QtProjectV304.vcxproj.filters b/Tests/ProjectFormats/304/QtProjectV304.vcxproj.filters new file mode 100644 index 0000000..a001b10 --- /dev/null +++ b/Tests/ProjectFormats/304/QtProjectV304.vcxproj.filters @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Form Files"> + <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier> + <Extensions>ui</Extensions> + </Filter> + <Filter Include="Translation Files"> + <UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier> + <Extensions>ts</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <QtRcc Include="QtProjectV304.qrc"> + <Filter>Resource Files</Filter> + </QtRcc> + <QtUic Include="QtProjectV304.ui"> + <Filter>Form Files</Filter> + </QtUic> + <QtMoc Include="QtProjectV304.h"> + <Filter>Header Files</Filter> + </QtMoc> + <ClCompile Include="QtProjectV304.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ResourceCompile Include="$pro_name$.rc"> + </ResourceCompile> + <None Include="$pro_name$.ico"> + <Filter>Resource Files</Filter> + </None> + <None Include="$pro_name$.def"> + <Filter>Resource Files</Filter> + </None> + + </ItemGroup> +</Project> diff --git a/Tests/ProjectFormats/304/main.cpp b/Tests/ProjectFormats/304/main.cpp new file mode 100644 index 0000000..d448992 --- /dev/null +++ b/Tests/ProjectFormats/304/main.cpp @@ -0,0 +1,10 @@ +#include "QtProjectV304.h" +#include <QtWidgets/QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QtProjectV304 w; + w.show(); + return a.exec(); +} diff --git a/Tests/ProjectFormats/ProjectFormats.md b/Tests/ProjectFormats/ProjectFormats.md new file mode 100644 index 0000000..5702dc4 --- /dev/null +++ b/Tests/ProjectFormats/ProjectFormats.md @@ -0,0 +1,1324 @@ +# Qt VS Tools - Project format versions + +## Contents + +* [Project format v1.0](#project-format-v1.0) +* [Project format v2.0](#project-format-v2.0) +* [Project format v3.0](#project-format-v3.0) +* [Project format v3.1](#project-format-v3.1) +* [Project format v3.2](#project-format-v3.2) +* [Project format v3.3](#project-format-v3.3) +* [Project format v3.4](#project-format-v3.4) +* [Example projects](#example-projects) + * [v1.0](#v1.0) + * [v2.0](#v2.0) + * [v3.0](#v3.0) + * [v3.1](#v3.1) + * [v3.2](#v3.2) + * [v3.3](#v3.3) + * [v3.4](#v3.4) + +## Project format v1.0 + +Output of `qmake` using the VC template: + + qmake -tp vc + +### Project file outline + +- ItemGroup **ProjectConfiguration** +- PropertyGroup **Globals** + - Keyword **Qt4VSv1.0** +- Import **Microsoft.Cpp.Default.props** +- PropertyGroup **Configuration** +- Import **Microsoft.Cpp.props** +- ImportGroup **ExtensionSettings** +- ImportGroup **PropertySheets** +- PropertyGroup **UserMacros** +- PropertyGroup + - Property **OutDir** + - Property **IntDir** + - ... +- ItemDefinitionGroup + - **ClCompile** + - **Link** + - ... +- ItemGroup + - **CustomBuild** (*MOC header*) + - *N* x **ClCompile** (*MOC-generated CPP source*), where N = number of configurations + - (*N* - 1) x **ExcludedFromBuild** (*configuration*) + - **CustomBuild** (*QRC resources*) + - *N* x **ClCompile** (*RCC-generated CPP source*), where N = number of configurations + - (*N* - 1) x **ExcludedFromBuild** (*configuration*) + - **CustomBuild** (*UI form*) + - **ClInclude** (*UIC-generated header*) + - **ClInclude** (*other headers*) + - **ClCompile** (*other CPP sources*) + - ... +- Import **Microsoft.Cpp.targets** +- ImportGroup **ExtensionTargets** + +## Project format v2.0 +**[Qt Visual Studio Tools v2.1.1](https://download.qt.io/official_releases/vsaddin/2.1.1/)** + +### Project file outline + +- ItemGroup **ProjectConfiguration** +- PropertyGroup **Globals** + - Keyword **Qt4VSv1.0** +- Import **Microsoft.Cpp.Default.props** +- PropertyGroup **Configuration** +- Import **Microsoft.Cpp.props** +- ImportGroup **ExtensionSettings** +- ImportGroup **Shared** +- ImportGroup **PropertySheets** +- PropertyGroup **UserMacros** +- PropertyGroup + - Property **OutDir** + - Property **IntDir** + - ... +- ItemDefinitionGroup + - **ClCompile** + - **Link** + - ... +- ItemGroup + - **CustomBuild** (*MOC header*) + - *N* x **ClCompile** (*MOC-generated CPP source*), where N = number of configurations + - (*N* - 1) x **ExcludedFromBuild** (*configuration*) + - **CustomBuild** (*QRC resources*) + - *N* x **ClCompile** (*RCC-generated CPP source*), where N = number of configurations + - (*N* - 1) x **ExcludedFromBuild** (*configuration*) + - **CustomBuild** (*UI form*) + - **ClInclude** (*UIC-generated header*) + - **ClInclude** (*other headers*) + - **ClCompile** (*other CPP sources*) + - ... +- Import **Microsoft.Cpp.targets** +- ImportGroup **ExtensionTargets** +- ProjectExtensions / VisualStudio + - UserProperties + - **MocDir** + - **UicDir** + - **RccDir** + - **lupdateOptions** + - **lupdateOnBuild** + - **lreleaseOptions** + - **Qt5Version_x0020_x64** + - **MocOptions** + +## Project format v3.0 +**[Qt Visual Studio Tools v2.4.0](https://download.qt.io/official_releases/vsaddin/2.4.0/)** + +**`Edit Qt settings in property pages (V3 format)`** +`commit 805e9ed6f14fb0a4d9dd8ce6a23631ca215b304a` +`Author: Miguel Costa <miguel.costa@qt.io>` +`Date: Thu Jun 20 13:54:49 2019 +0200` + + Qt settings are now configured in the project property pages. This + includes the possibility to have different versions of the Qt settings + per project configuration. Previously, the Qt settings were edited in a + custom dialog, allowing only a single version of the settings that + would apply to all project configurations. + + This change breaks the current version of the support for Qt VS Tools + projects. A new version (V3) of the project format is introduced. This + new format allows Qt settings to be stored in the same way as other + project properties. Previous versions will still work and a later change + will introduce the possibility to convert from previous versions to V3. + +### Project file outline + +- ItemGroup **ProjectConfiguration** +- PropertyGroup **Globals** + - Keyword **QtVS_v300** +- Import **Microsoft.Cpp.Default.props** +- PropertyGroup **Configuration** +- Import **Microsoft.Cpp.props** +- PropertyGroup **if %QTMSBUILD% undefined** + - Property **QtMsBuild** = $(MSBuildProjectDirectory)\QtMsBuild +- PropertyGroup + - Property **OutDir** + - Property **IntDir** + - ... +- Target **QtMsBuildNotFound** +- Import **qt.props** +- PropertyGroup **QtSettings** +- ImportGroup **ExtensionSettings** +- ImportGroup **Shared** +- ImportGroup **PropertySheets** +- PropertyGroup **UserMacros** +- ItemDefinitionGroup + - **ClCompile** + - **Link** + - **QtMoc** + - **QtRcc** + - **QtUic** + - ... +- ItemGroup + - **QtMoc** (*MOC header*) + - **QtRcc** (*QRC resources*) + - **QtUic** (*UI form*) + - **ClInclude** (*other headers*) + - **ClCompile** (*other CPP sources*) + - ... +- Import **Microsoft.Cpp.targets** +- Import **qt.targets** +- ImportGroup **ExtensionTargets** + +## Project format v3.1 +**[Qt Visual Studio Tools v2.4.2](https://download.qt.io/official_releases/vsaddin/2.4.2/)** + +**`Implement project format v3.1`** +`commit fdbec35c590f524f6f9ce8f2e6a7328f2f3df508` +`Author: Miguel Costa <miguel.costa@qt.io>` +`Date: Wed Sep 18 18:47:30 2019 +0200` + + This change introduces a revision of the v3 project format, which will + now allow Qt settings to reference user macros defined in imported + property sheets. This includes the following changes to the order of + property evaluation: + - "QtSettings" property group moved to after the import of user + property sheets; + - QtInstall property moved from the "Configuration" property group + to the "QtSettings" property group; + - Import of qt.props moved to after the "QtSettings" property group. + +### Project file outline + +- ItemGroup **ProjectConfiguration** +- PropertyGroup **Globals** + - Keyword **QtVS_v301** +- Import **Microsoft.Cpp.Default.props** +- PropertyGroup **Configuration** + - Property **QtInstall** +- Import **Microsoft.Cpp.props** +- PropertyGroup (*if `%QTMSBUILD%` undefined*) + - Property **QtMsBuild** = $(MSBuildProjectDirectory)\QtMsBuild +- PropertyGroup + - Property **OutDir** + - Property **IntDir** + - ... +- Target **QtMsBuildNotFound** +- ImportGroup **ExtensionSettings** +- ImportGroup **Shared** +- ImportGroup **PropertySheets** +- PropertyGroup **UserMacros** +- Import **qt.props** +- PropertyGroup **QtSettings** +- ItemDefinitionGroup + - **ClCompile** + - **Link** + - **QtMoc** + - **QtRcc** + - **QtUic** + - ... +- ItemGroup + - **QtMoc** (*MOC header*) + - **QtRcc** (*QRC resources*) + - **QtUic** (*UI form*) + - **ClInclude** (*other headers*) + - **ClCompile** (*other CPP sources*) + - ... +- Import **Microsoft.Cpp.targets** +- Import **qt.targets** +- ImportGroup **ExtensionTargets** + +## Project format v3.2 +**[Qt Visual Studio Tools v2.5.1](https://download.qt.io/official_releases/vsaddin/2.5.1/)** + +**`Fix incompatibilities with property sheets`** +`commit 1a93741cadaa26b49cc4dc02d09ea7249cbea6fe` +`Author: Miguel Costa <miguel.costa@qt.io>` +`Date: Thu Nov 21 16:21:35 2019 +0100` + + Updated the format of Qt projects to better match the requirements for + Visual Studio C++ projects (*) that enable integrating with the IDE, in + particular, that allow external property sheets to be referenced. +(*) https://docs.microsoft.com/en-us/cpp/build/reference/cxproj-file-structure#per-configuration-propertygroup-elements + +### Project file outline + +- ItemGroup **ProjectConfiguration** +- PropertyGroup **Globals** + - Keyword **QtVS_v302** + - Property (*if `%QTMSBUILD%` undefined*) **QtMsBuild** = $(MSBuildProjectDirectory)\QtMsBuild +- Import **Microsoft.Cpp.Default.props** +- PropertyGroup **Configuration** + - Property **QtInstall** +- Import **Microsoft.Cpp.props** +- Target **QtMsBuildNotFound** +- ImportGroup **ExtensionSettings** +- ImportGroup **Shared** +- ImportGroup **PropertySheets** +- PropertyGroup **UserMacros** +- Import **qt_defaults.props** +- PropertyGroup **QtSettings** +- Import **qt.props** +- ItemDefinitionGroup + - **ClCompile** + - **Link** + - **QtMoc** + - **QtRcc** + - **QtUic** + - ... +- ItemGroup + - **QtMoc** (*MOC header*) + - **QtRcc** (*QRC resources*) + - **QtUic** (*UI form*) + - **ClInclude** (*other headers*) + - **ClCompile** (*other CPP sources*) + - ... +- Import **Microsoft.Cpp.targets** +- Import **qt.targets** +- ImportGroup **ExtensionTargets** + +## Project format v3.3 +**[Qt Visual Studio Tools v2.6.0](https://download.qt.io/official_releases/vsaddin/2.6.0/)** + +**`Fix ignoring VC property changes (project format v3.3)`** +`commit 621efbcc92be6e1a9869a15a850b9bd8cccf2e97` +`Author: Miguel Costa <miguel.costa@qt.io>` +`Date: Tue Jun 9 10:24:54 2020 +0200` + + This change introduces project format version 3.3, which fixes issues + related to modified values of VC properties (e.g. $(IntDir)) being + ignored when evaluating Qt build settings. + + MSBuild evaluates properties by order of definition; dependencies are + resolved by using the latest evaluation of referred properties. As such, + any subsequent changes to the value of dependencies will not be + reflected in previously evaluated properties. + + Redefinitions of VC properties are stored in uncategorized property + groups (i.e. <PropertyGroup> elements without a Label attrib) inside the + MSBuild project file; if no available group is found, Visual Studio will + create a new one. The incorrect evaluation of Qt properties happens when + new property groups are created after the definition of Qt properties, + such that the evaluation of Qt properties will be using outdated values + of VC properties. + + Project format version 3.3 addresses this issue by adding property + groups for VC property storage in a correct location, with respect to + Qt build settings definitions. + +### Project file outline + +- ItemGroup **ProjectConfiguration** +- PropertyGroup **Globals** + - Keyword **QtVS_v303** + - Property (*if `%QTMSBUILD%` undefined*) **QtMsBuild** = $(MSBuildProjectDirectory)\QtMsBuild +- Import **Microsoft.Cpp.Default.props** +- PropertyGroup **Configuration** + - Property **QtInstall** +- Import **Microsoft.Cpp.props** +- Target **QtMsBuildNotFound** +- ImportGroup **ExtensionSettings** +- ImportGroup **Shared** +- ImportGroup **PropertySheets** +- PropertyGroup **UserMacros** +- Import **qt_defaults.props** +- PropertyGroup + - Property **OutDir** + - Property **IntDir** + - ... +- PropertyGroup **QtSettings** +- Import **qt.props** +- ItemDefinitionGroup + - **ClCompile** + - **Link** + - **QtMoc** + - **QtRcc** + - **QtUic** + - ... +- ItemGroup + - **QtMoc** (*MOC header*) + - **QtRcc** (*QRC resources*) + - **QtUic** (*UI form*) + - **ClInclude** (*other headers*) + - **ClCompile** (*other CPP sources*) + - ... +- Import **Microsoft.Cpp.targets** +- Import **qt.targets** +- ImportGroup **ExtensionTargets** + +## Project format v3.4 +**>= [Qt Visual Studio Tools v2.7.1](https://download.qt.io/official_releases/vsaddin/2.7.1/)** + +**`Integrate Qt.props in the VS Property Manager`** +`commit cb9ec156845a9efc163a9c67d7a54c8ca790e805` +`Author: Miguel Costa <miguel.costa@qt.io>` +`Date: Fri Dec 11 16:58:06 2020 +0100` + + The Qt property definitions file (Qt.props) will now be shown in the + evaluation list of the Property Manager window. This allows the user to + customize the order of evaluation of Qt.props in relation to other + property files loaded during the build, thereby defining the correct + dependency between Qt properties and other build settings. Previously, + the order of evaluation of Qt.props was fixed and could only be changed + by manually editing the project file's XML. + + Allowing Qt.props to be manipulated in the Property Manager window will + enable the user to define properties and default metadata within the + Qt.props itself. To ensure these custom definitions are not lost when + installing Qt/MSBuild files, the Qt.props file will no longer be + replaced during start-up. + +### Project file outline + +- ItemGroup **ProjectConfiguration** +- PropertyGroup **Globals** + - Keyword **QtVS_v304** + - Property (*if `%QTMSBUILD%` undefined*) **QtMsBuild** = $(MSBuildProjectDirectory)\QtMsBuild +- Import **Microsoft.Cpp.Default.props** +- PropertyGroup **Configuration** + - Property **QtInstall** +- Import **Microsoft.Cpp.props** +- Import **qt_defaults.props** +- PropertyGroup **QtSettings** +- Target **QtMsBuildNotFound** +- ImportGroup **ExtensionSettings** +- ImportGroup **Shared** +- ImportGroup **PropertySheets** + - Import **Qt.props** +- PropertyGroup **UserMacros** +- PropertyGroup + - Property **OutDir** + - Property **IntDir** + - ... +- ItemDefinitionGroup + - **ClCompile** + - **Link** + - **QtMoc** + - **QtRcc** + - **QtUic** + - ... +- ItemGroup + - **QtMoc** (*MOC header*) + - **QtRcc** (*QRC resources*) + - **QtUic** (*UI form*) + - **ClInclude** (*other headers*) + - **ClCompile** (*other CPP sources*) + - ... +- Import **Microsoft.Cpp.targets** +- Import **qt.targets** +- ImportGroup **ExtensionTargets** + +## Example projects + +### v1.0 + +#### `.vcxproj` +```xml +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{E5EA0EEF-BDC2-3484-A4F0-BA6C71E224CF}</ProjectGuid> + <RootNamespace>QtProjectV100</RootNamespace> + <Keyword>Qt4VSv1.0</Keyword> + <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <PlatformToolset>v142</PlatformToolset> + <OutputDirectory>release\</OutputDirectory> + <ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage> + <CharacterSet>NotSet</CharacterSet> + <ConfigurationType>Application</ConfigurationType> + <IntermediateDirectory>release\</IntermediateDirectory> + <PrimaryOutput>QtProjectV100</PrimaryOutput> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <PlatformToolset>v142</PlatformToolset> + <OutputDirectory>debug\</OutputDirectory> + <ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage> + <CharacterSet>NotSet</CharacterSet> + <ConfigurationType>Application</ConfigurationType> + <IntermediateDirectory>debug\</IntermediateDirectory> + <PrimaryOutput>QtProjectV100</PrimaryOutput> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\</IntDir> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">QtProjectV100</TargetName> + <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\</IntDir> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">QtProjectV100</TargetName> + <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <AdditionalIncludeDirectories>.;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtWidgets;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtGui;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtANGLE;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtCore;release;.;/include;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\win32-msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions> + <AssemblerListingLocation>release\</AssemblerListingLocation> + <BrowseInformation>false</BrowseInformation> + <DebugInformationFormat>None</DebugInformationFormat> + <DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ExceptionHandling>Sync</ExceptionHandling> + <ObjectFileName>release\</ObjectFileName> + <Optimization>MaxSpeed</Optimization> + <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;NDEBUG;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessToFile>false</PreprocessToFile> + <ProgramDataBaseFileName></ProgramDataBaseFileName> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <SuppressStartupBanner>true</SuppressStartupBanner> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <WarningLevel>Level3</WarningLevel> + </ClCompile> + <Link> + <AdditionalDependencies>C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Widgets.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Gui.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Core.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\qtmain.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>C:\openssl\lib;C:\Utils\my_sql\mysql-5.7.25-winx64\lib;C:\Utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions> + <DataExecutionPrevention>true</DataExecutionPrevention> + <GenerateDebugInformation>false</GenerateDebugInformation> + <IgnoreImportLibrary>true</IgnoreImportLibrary> + <LinkIncremental>false</LinkIncremental> + <OptimizeReferences>true</OptimizeReferences> + <OutputFile>$(OutDir)\QtProjectV100.exe</OutputFile> + <RandomizedBaseAddress>true</RandomizedBaseAddress> + <SubSystem>Windows</SubSystem> + <SuppressStartupBanner>true</SuppressStartupBanner> + </Link> + <Midl> + <DefaultCharType>Unsigned</DefaultCharType> + <EnableErrorChecks>None</EnableErrorChecks> + <WarningLevel>0</WarningLevel> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;NDEBUG;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <AdditionalIncludeDirectories>.;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtWidgets;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtGui;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtANGLE;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\include\QtCore;debug;.;/include;..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\win32-msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions> + <AssemblerListingLocation>debug\</AssemblerListingLocation> + <BrowseInformation>false</BrowseInformation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ExceptionHandling>Sync</ExceptionHandling> + <ObjectFileName>debug\</ObjectFileName> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessToFile>false</PreprocessToFile> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <SuppressStartupBanner>true</SuppressStartupBanner> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <WarningLevel>Level3</WarningLevel> + </ClCompile> + <Link> + <AdditionalDependencies>C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Widgetsd.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Guid.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\Qt5Cored.lib;C:\lib\Qt\5.15.10\msvc2019_64\lib\qtmaind.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>C:\openssl\lib;C:\Utils\my_sql\mysql-5.7.25-winx64\lib;C:\Utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions> + <DataExecutionPrevention>true</DataExecutionPrevention> + <GenerateDebugInformation>true</GenerateDebugInformation> + <IgnoreImportLibrary>true</IgnoreImportLibrary> + <OutputFile>$(OutDir)\QtProjectV100.exe</OutputFile> + <RandomizedBaseAddress>true</RandomizedBaseAddress> + <SubSystem>Windows</SubSystem> + <SuppressStartupBanner>true</SuppressStartupBanner> + </Link> + <Midl> + <DefaultCharType>Unsigned</DefaultCharType> + <EnableErrorChecks>None</EnableErrorChecks> + <WarningLevel>0</WarningLevel> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="QtProjectV100.cpp" /> + <ClCompile Include="main.cpp" /> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV100.h"> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">QtProjectV100.h;release\moc_predefs.h;C:\lib\Qt\5.15.10\msvc2019_64\bin\moc.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\moc.exe -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DNDEBUG -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB --compiler-flavor=msvc --include C:/dev/tests/formats/100/release/moc_predefs.h -IC:/lib/Qt/5.15.10/msvc2019_64/mkspecs/win32-msvc -IC:/dev/tests/formats/100 -IC:/lib/Qt/5.15.10/msvc2019_64/include -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtWidgets -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtGui -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtANGLE -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtCore -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\ATLMFC\include" -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\winrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\cppwinrt" QtProjectV100.h -o release\moc_QtProjectV100.cpp</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MOC QtProjectV100.h</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\moc_QtProjectV100.cpp;%(Outputs)</Outputs> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">QtProjectV100.h;debug\moc_predefs.h;C:\lib\Qt\5.15.10\msvc2019_64\bin\moc.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\moc.exe -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB --compiler-flavor=msvc --include C:/dev/tests/formats/100/debug/moc_predefs.h -IC:/lib/Qt/5.15.10/msvc2019_64/mkspecs/win32-msvc -IC:/dev/tests/formats/100 -IC:/lib/Qt/5.15.10/msvc2019_64/include -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtWidgets -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtGui -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtANGLE -IC:/lib/Qt/5.15.10/msvc2019_64/include/QtCore -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\ATLMFC\include" -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\winrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\cppwinrt" QtProjectV100.h -o debug\moc_QtProjectV100.cpp</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">MOC QtProjectV100.h</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\moc_QtProjectV100.cpp;%(Outputs)</Outputs> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <ClCompile Include="debug\moc_QtProjectV100.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="release\moc_QtProjectV100.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + </ClCompile> + <CustomBuild Include="debug\moc_predefs.h.cbt"> + <FileType>Document</FileType> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -BxC:\lib\Qt\5.15.10\msvc2019_64\bin\qmake.exe -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E ..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\features\data\dummy.cpp 2>NUL >debug\moc_predefs.h</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Generate moc_predefs.h</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\moc_predefs.h;%(Outputs)</Outputs> + </CustomBuild> + <CustomBuild Include="release\moc_predefs.h.cbt"> + <FileType>Document</FileType> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -BxC:\lib\Qt\5.15.10\msvc2019_64\bin\qmake.exe -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E ..\..\..\..\lib\Qt\5.15.10\msvc2019_64\mkspecs\features\data\dummy.cpp 2>NUL >release\moc_predefs.h</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Generate moc_predefs.h</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\moc_predefs.h;%(Outputs)</Outputs> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + </CustomBuild> + <ClCompile Include="debug\qrc_QtProjectV100.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="release\qrc_QtProjectV100.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClInclude Include="ui_QtProjectV100.h" /> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV100.ui"> + <FileType>Document</FileType> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">QtProjectV100.ui;C:\lib\Qt\5.15.10\msvc2019_64\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\uic.exe QtProjectV100.ui -o ui_QtProjectV100.h</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">UIC QtProjectV100.ui</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">ui_QtProjectV100.h;%(Outputs)</Outputs> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">QtProjectV100.ui;C:\lib\Qt\5.15.10\msvc2019_64\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\uic.exe QtProjectV100.ui -o ui_QtProjectV100.h</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">UIC QtProjectV100.ui</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">ui_QtProjectV100.h;%(Outputs)</Outputs> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV100.qrc"> + <FileType>Document</FileType> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">QtProjectV100.qrc;C:\lib\Qt\5.15.10\msvc2019_64\bin\rcc.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\rcc.exe -name QtProjectV100 QtProjectV100.qrc -o release\qrc_QtProjectV100.cpp</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">RCC QtProjectV100.qrc</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\qrc_QtProjectV100.cpp;%(Outputs)</Outputs> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">QtProjectV100.qrc;C:\lib\Qt\5.15.10\msvc2019_64\bin\rcc.exe;%(AdditionalInputs)</AdditionalInputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\lib\Qt\5.15.10\msvc2019_64\bin\rcc.exe -name QtProjectV100 QtProjectV100.qrc -o debug\qrc_QtProjectV100.cpp</Command> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">RCC QtProjectV100.qrc</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\qrc_QtProjectV100.cpp;%(Outputs)</Outputs> + </CustomBuild> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets" /> +</Project> +``` + +### v2.0 + +#### `.vcxproj` +```xml +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B12702AD-ABFB-343A-A199-8E24837244A3}</ProjectGuid> + <Keyword>Qt4VSv1.0</Keyword> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" /> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PreprocessorDefinitions>UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <Optimization>Disabled</Optimization> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <AdditionalLibraryDirectories>$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PreprocessorDefinitions>UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DebugInformationFormat /> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <AdditionalLibraryDirectories>$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <GenerateDebugInformation>false</GenerateDebugInformation> + <AdditionalDependencies>qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="GeneratedFiles\Debug\moc_QtProjectV200.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="GeneratedFiles\qrc_QtProjectV200.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + </PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + </PrecompiledHeader> + </ClCompile> + <ClCompile Include="GeneratedFiles\Release\moc_QtProjectV200.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="main.cpp" /> + <ClCompile Include="QtProjectV200.cpp" /> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV200.h"> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing QtProjectV200.h...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing QtProjectV200.h...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV200.ui"> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Uic%27ing %(Identity)...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Uic%27ing %(Identity)...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command> + </CustomBuild> + </ItemGroup> + <ItemGroup> + <ClInclude Include="GeneratedFiles\ui_QtProjectV200.h" /> + </ItemGroup> + <ItemGroup> + <CustomBuild Include="QtProjectV200.qrc"> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(FullPath);%(AdditionalInputs)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Rcc%27ing %(Identity)...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs)</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp</Command> + <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(FullPath);%(AdditionalInputs)</AdditionalInputs> + <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Rcc%27ing %(Identity)...</Message> + <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs)</Outputs> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp</Command> + </CustomBuild> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> + <ProjectExtensions> + <VisualStudio> + <UserProperties MocDir=".\GeneratedFiles\$(ConfigurationName)" UicDir=".\GeneratedFiles" RccDir=".\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" Qt5Version_x0020_x64="msvc2019_64" MocOptions="" /> + </VisualStudio> + </ProjectExtensions> +</Project> +``` + +### v3.0 + +#### `.vcxproj` +```xml +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B12702AD-ABFB-343A-A199-8E24837244A3}</ProjectGuid> + <Keyword>QtVS_v300</Keyword> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <QtInstall>msvc2019_64</QtInstall> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <QtInstall>msvc2019_64</QtInstall> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup Condition="'$(QtMsBuild)'=='' or !Exists('$(QtMsBuild)\qt.targets')"> + <QtMsBuild>$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')"> + <Import Project="$(QtMsBuild)\qt.props" /> + </ImportGroup> + <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <QtModules>core;gui;widgets</QtModules> + </PropertyGroup> + <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <QtModules>core;gui;widgets</QtModules> + </PropertyGroup> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <Optimization>Disabled</Optimization> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat /> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="main.cpp" /> + <ClCompile Include="QtProjectV300.cpp" /> + </ItemGroup> + <ItemGroup> + <QtMoc Include="QtProjectV300.h" /> + </ItemGroup> + <ItemGroup> + <QtUic Include="QtProjectV300.ui" /> + </ItemGroup> + <ItemGroup> + <QtRcc Include="QtProjectV300.qrc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> +``` + +### v3.1 + +#### `.vcxproj` +```xml +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B12702AD-ABFB-343A-A199-8E24837244A3}</ProjectGuid> + <Keyword>QtVS_v301</Keyword> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup Condition="'$(QtMsBuild)'=='' or !Exists('$(QtMsBuild)\qt.targets')"> + <QtMsBuild>$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + </PropertyGroup> + <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + </PropertyGroup> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')"> + <Import Project="$(QtMsBuild)\qt.props" /> + </ImportGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <Optimization>Disabled</Optimization> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat /> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="main.cpp" /> + <ClCompile Include="QtProjectV301.cpp" /> + </ItemGroup> + <ItemGroup> + <QtMoc Include="QtProjectV301.h" /> + </ItemGroup> + <ItemGroup> + <QtUic Include="QtProjectV301.ui" /> + </ItemGroup> + <ItemGroup> + <QtRcc Include="QtProjectV301.qrc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> +``` + +### v3.2 + +#### `.vcxproj` +```xml +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{10A7CC05-6663-4C63-906F-E56EDF8218CA}</ProjectGuid> + <Keyword>QtVS_v302</Keyword> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')" + >$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Target Name="QtMsBuildNotFound" + BeforeTargets="CustomBuild;ClCompile" + Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" + Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>debug</QtBuildConfig> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>release</QtBuildConfig> + </PropertyGroup> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')"> + <Import Project="$(QtMsBuild)\qt.props" /> + </ImportGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>None</DebugInformationFormat> + <Optimization>MaxSpeed</Optimization> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <QtRcc Include="QtProjectV302.qrc"/> + <QtUic Include="QtProjectV302.ui"/> + <QtMoc Include="QtProjectV302.h"/> + <ClCompile Include="QtProjectV302.cpp"/> + <ClCompile Include="main.cpp"/> + + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> +``` + +### v3.3 + +#### `.vcxproj` +```xml +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{812E4050-B861-4918-A0DC-53053B848372}</ProjectGuid> + <Keyword>QtVS_v303</Keyword> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')" + >$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Target Name="QtMsBuildNotFound" + BeforeTargets="CustomBuild;ClCompile" + Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" + Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>debug</QtBuildConfig> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings"> + <QtInstall>msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>release</QtBuildConfig> + </PropertyGroup> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')"> + <Import Project="$(QtMsBuild)\qt.props" /> + </ImportGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>None</DebugInformationFormat> + <Optimization>MaxSpeed</Optimization> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <QtRcc Include="QtProjectV303.qrc"/> + <QtUic Include="QtProjectV303.ui"/> + <QtMoc Include="QtProjectV303.h"/> + <ClCompile Include="QtProjectV303.cpp"/> + <ClCompile Include="main.cpp"/> + + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> +``` + +### v3.4 + +#### `.vcxproj` +```xml +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{923588D5-2AA5-4B0F-8110-56BEEBB531D5}</ProjectGuid> + <Keyword>QtVS_v304</Keyword> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">10.0.19041.0</WindowsTargetPlatformVersion> + <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')" + >$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v143</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v143</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings"> + <QtInstall>5.15.10_msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>debug</QtBuildConfig> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings"> + <QtInstall>5.15.10_msvc2019_64</QtInstall> + <QtModules>core;gui;widgets</QtModules> + <QtBuildConfig>release</QtBuildConfig> + </PropertyGroup> + <Target Name="QtMsBuildNotFound" + BeforeTargets="CustomBuild;ClCompile" + Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" + Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(QtMsBuild)\Qt.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(QtMsBuild)\Qt.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>None</DebugInformationFormat> + <Optimization>MaxSpeed</Optimization> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <QtRcc Include="QtProjectV304.qrc"/> + <QtUic Include="QtProjectV304.ui"/> + <QtMoc Include="QtProjectV304.h"/> + <ClCompile Include="QtProjectV304.cpp"/> + <ClCompile Include="main.cpp"/> + + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> +``` diff --git a/Tests/Test_QtMsBuild.Tasks/Properties/AssemblyInfo.cs b/Tests/Test_QtMsBuild.Tasks/Properties/AssemblyInfo.cs index d2a7f58..2b3b56c 100644 --- a/Tests/Test_QtMsBuild.Tasks/Properties/AssemblyInfo.cs +++ b/Tests/Test_QtMsBuild.Tasks/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTitle("Test_QtMsBuild.Tasks")] diff --git a/Tests/Test_QtMsBuild.Tasks/TestTaskLoggingHelper.cs b/Tests/Test_QtMsBuild.Tasks/TestTaskLoggingHelper.cs index b4c1272..0c5d72a 100644 --- a/Tests/Test_QtMsBuild.Tasks/TestTaskLoggingHelper.cs +++ b/Tests/Test_QtMsBuild.Tasks/TestTaskLoggingHelper.cs @@ -26,11 +26,11 @@ ** ****************************************************************************/ -using Microsoft.Build.Framework; using System; using System.Collections.Generic; -using System.IO; using System.Diagnostics; +using System.IO; +using Microsoft.Build.Framework; namespace QtVsTools.Test.QtMsBuild.Tasks { diff --git a/Tests/Test_QtMsBuild.Tasks/Test_Join.cs b/Tests/Test_QtMsBuild.Tasks/Test_Join.cs index 0ae7973..3743125 100644 --- a/Tests/Test_QtMsBuild.Tasks/Test_Join.cs +++ b/Tests/Test_QtMsBuild.Tasks/Test_Join.cs @@ -26,19 +26,20 @@ ** ****************************************************************************/ -using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Linq; using System.Collections.Generic; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; -using QtVsTools.QtMsBuild.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; namespace QtVsTools.Test.QtMsBuild.Tasks { + using QtVsTools.QtMsBuild.Tasks; + [TestClass] public class Test_Join { - ITaskItem[] LeftItems = new TaskItem[] + readonly ITaskItem[] LeftItems = new TaskItem[] { new TaskItem("A", new Dictionary<string, string> { { "X", "foo" }, @@ -53,8 +54,7 @@ { "Y", "3.14159" }, }), }; - - ITaskItem[] RightItems = new TaskItem[] + readonly ITaskItem[] RightItems = new TaskItem[] { new TaskItem("A", new Dictionary<string, string> { { "Z", "foo" }, @@ -90,9 +90,8 @@ // --------------- var criteria = new string[] { "Y" }; - ITaskItem[] result; Assert.IsTrue( - Join.Execute(LeftItems, RightItems, out result, criteria)); + Join.Execute(LeftItems, RightItems, out ITaskItem[] result, criteria)); Assert.IsTrue(result != null && result.Length == 3); Assert.IsTrue(result[0].GetMetadata("X") == "foo"); @@ -124,9 +123,8 @@ // ------------------- var criteria = new string[] { "ROW_NUMBER" }; - ITaskItem[] result; Assert.IsTrue( - Join.Execute(LeftItems, RightItems, out result, criteria)); + Join.Execute(LeftItems, RightItems, out ITaskItem[] result, criteria)); Assert.IsTrue(result != null && result.Length == 3); Assert.IsTrue(result[0].GetMetadata("X") == "foo"); @@ -158,9 +156,8 @@ // ------------------- var criteria = new string[] { "ROW_NUMBER", "Y" }; - ITaskItem[] result; Assert.IsTrue( - Join.Execute(LeftItems, RightItems, out result, criteria)); + Join.Execute(LeftItems, RightItems, out ITaskItem[] result, criteria)); Assert.IsTrue(result != null && result.Length == 0); } @@ -187,9 +184,8 @@ .ToArray(); var criteria = new string[] { "ROW_NUMBER", "Y" }; - ITaskItem[] result; Assert.IsTrue( - Join.Execute(newLeftItems, RightItems, out result, criteria)); + Join.Execute(newLeftItems, RightItems, out ITaskItem[] result, criteria)); Assert.IsTrue(result != null && result.Length == 1); Assert.IsTrue(result[0].GetMetadata("X") == "zzz"); @@ -212,9 +208,8 @@ // --------------------- A | bar | 99 B | bar | 99 | bar // --------------------- ---------------------- - ITaskItem[] result; Assert.IsTrue( - Join.Execute(LeftItems, RightItems, out result)); + Join.Execute(LeftItems, RightItems, out ITaskItem[] result)); Assert.IsTrue(result != null && result.Length == 4); Assert.IsTrue(result[0].GetMetadata("X") == "foo"); diff --git a/Tests/Test_QtMsBuild.Tasks/Test_QtMsBuild.Tasks.csproj b/Tests/Test_QtMsBuild.Tasks/Test_QtMsBuild.Tasks.csproj index 77bbb75..b4ae05a 100644 --- a/Tests/Test_QtMsBuild.Tasks/Test_QtMsBuild.Tasks.csproj +++ b/Tests/Test_QtMsBuild.Tasks/Test_QtMsBuild.Tasks.csproj @@ -76,17 +76,35 @@ </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - // Version specific references + // General package references // --> <Import Project="$(SolutionDir)\references.props" /> <ItemGroup> - <PackageReference Include="Microsoft.Build" Version="$(Version_Microsoft_Build)" /> - <PackageReference Include="Microsoft.Build.Framework" Version="$(Version_Microsoft_Build_Framework)" /> - <PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(Version_Microsoft_Build_Tasks_Core)" /> - <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="$(Version_Microsoft_Bcl_AsyncInterfaces)" /> - <PackageReference Include="MSTest.TestAdapter" Version="$(Version_MSTest_TestAdapter)" /> - <PackageReference Include="MSTest.TestFramework" Version="$(Version_MSTest_TestFramework)" /> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + <PackageReference Include="$(Name_Microsoft_Build)" Version="$(Version_Microsoft_Build)" /> + <PackageReference Include="$(Name_Microsoft_Build_Tasks_Core)" Version="$(Version_Microsoft_Build_Tasks_Core)" /> + <PackageReference Include="$(Name_MSTest_TestAdapter)" Version="$(Version_MSTest_TestAdapter)" /> + <PackageReference Include="$(Name_MSTest_TestFramework)" Version="$(Version_MSTest_TestFramework)" /> </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// // Solution project references @@ -105,6 +123,7 @@ <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="TestTaskLoggingHelper.cs" /> <Compile Include="Test_Join.cs" /> + <Compile Include="Test_QtRunTask.cs" /> </ItemGroup> <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> diff --git a/Tests/Test_QtMsBuild.Tasks/Test_QtRunTask.cs b/Tests/Test_QtMsBuild.Tasks/Test_QtRunTask.cs new file mode 100644 index 0000000..969e582 --- /dev/null +++ b/Tests/Test_QtMsBuild.Tasks/Test_QtRunTask.cs @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace QtVsTools.Test.QtMsBuild.Tasks +{ + using QtVsTools.QtMsBuild.Tasks; + + [TestClass] + public class Test_QtRunTask + { + [TestMethod] + public void CLCommandLine() + { + var argv = Environment.GetCommandLineArgs(); + var path = argv[0]; + if (string.IsNullOrEmpty(Path.GetPathRoot(path))) + Assert.Inconclusive("Executable path is not rooted."); + + do + path = Path.GetFullPath(Path.GetDirectoryName(path)); + while (path != Path.GetPathRoot(path) + && !File.Exists(Path.Combine(path, "devenv.exe"))); + + if (!File.Exists(Path.Combine(path, "devenv.exe"))) + Assert.Inconclusive("devenv.exe not found"); + + string vsPath = Path.GetDirectoryName(Path.GetDirectoryName(path)); + string vcTargetsPath = Path.Combine(vsPath, "MSBuild", "Microsoft", "VC"); + if (Directory.Exists(Path.Combine(vcTargetsPath, "v170"))) + vcTargetsPath = Path.Combine(vcTargetsPath, "v170"); + else if (Directory.Exists(Path.Combine(vcTargetsPath, "v160"))) + vcTargetsPath = Path.Combine(vcTargetsPath, "v160"); + else if (Directory.Exists(Path.Combine(vcTargetsPath, "v150"))) + vcTargetsPath = Path.Combine(vcTargetsPath, "v150"); + else + Assert.Inconclusive("MSBuild VC targets directory not found"); + + ITaskItem[] sourceItems = new TaskItem[] + { + new TaskItem("main.cpp", new Dictionary<string, string> { + { "EnforceTypeConversionRules", "false" }, + }) + }; + + Assert.IsTrue( + QtRunTask.Execute( + sourceItems, + $@"{vcTargetsPath}\Microsoft.Build.CPPTasks.Common.dll", + "Microsoft.Build.CPPTasks.CLCommandLine", + "Sources", + out ITaskItem[] result, + "CommandLines", + "CommandLine")); + Assert.IsTrue(result != null && result.Length == 1); + Assert.IsTrue(result[0].GetMetadata("CommandLine").Contains("/Zc:rvalueCast-")); + } + } +} diff --git a/Tests/Test_QtVsTools.Core/Properties/AssemblyInfo.cs b/Tests/Test_QtVsTools.Core/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4c2fa40 --- /dev/null +++ b/Tests/Test_QtVsTools.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Test_QtVsTools.Core")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Test_QtVsTools.Core")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("4b8fc08c-4901-45d4-bc00-c0c461292ff2")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Tests/Test_QtVsTools.Core/Test_LazyFactory.cs b/Tests/Test_QtVsTools.Core/Test_LazyFactory.cs new file mode 100644 index 0000000..953f024 --- /dev/null +++ b/Tests/Test_QtVsTools.Core/Test_LazyFactory.cs @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace QtVsTools.Test.Core +{ + using Common; + + [TestClass] + public class Test_LazyFactory + { + class LazyClass + { + LazyFactory Lazy { get; } = new LazyFactory(); + + public ConcurrentBag<int> InitThread { get; } = new ConcurrentBag<int>(); + public string LazyProperty => Lazy.Get(() => + LazyProperty, () => + { + InitThread.Add(Thread.CurrentThread.ManagedThreadId); + return "LAZYVALUE"; + }); + } + + [TestMethod] + public void Test_ThreadSafety() + { + var lazyObject = new LazyClass(); + var task = Task.Run(async () => + { + var tasks = new Task[3000]; + for (int i = 0; i < tasks.Length; i++) { + var n = i; + tasks[i] = Task.Run(() => + { + Debug.WriteLine($"Lazy value #{n} is {lazyObject.LazyProperty}"); + }); + } + await Task.WhenAll(tasks); + }); + while (!task.IsCompleted) + Thread.Sleep(100); + + Assert.IsTrue(lazyObject.InitThread.Count == 1); + } + } +} diff --git a/Tests/Test_QtVsTools.Core/Test_QtVsTools.Core.csproj b/Tests/Test_QtVsTools.Core/Test_QtVsTools.Core.csproj new file mode 100644 index 0000000..b6ab30a --- /dev/null +++ b/Tests/Test_QtVsTools.Core/Test_QtVsTools.Core.csproj @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="$(VisualStudioVersion)" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <!-- + ***************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{4B8FC08C-4901-45D4-BC00-C0C461292FF2}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>QtVsTools.Test.Core</RootNamespace> + <AssemblyName>Test_QtVsTools.Core</AssemblyName> + <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath> + <IsCodedUITest>False</IsCodedUITest> + <TestProjectType>UnitTest</TestProjectType> + <NuGetPackageImportStamp> + </NuGetPackageImportStamp> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + <PackageReference Include="$(Name_Microsoft_Build)" Version="$(Version_Microsoft_Build)" /> + <PackageReference Include="$(Name_Microsoft_Build_Tasks_Core)" Version="$(Version_Microsoft_Build_Tasks_Core)" /> + <PackageReference Include="$(Name_MSTest_TestAdapter)" Version="$(Version_MSTest_TestAdapter)" /> + <PackageReference Include="$(Name_MSTest_TestFramework)" Version="$(Version_MSTest_TestFramework)" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Solution project references + // --> + <ItemGroup> + <ProjectReference Include="$(SolutionDir)\QtVsTools.Core\QtVsTools.Core.csproj"> + <Project>{2621ad55-c4e9-4884-81e9-da0d00b4c6e5}</Project> + <Name>QtVsTools.Core</Name> + </ProjectReference> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> + <ItemGroup> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Test_LazyFactory.cs" /> + </ItemGroup> + <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(SolutionDir)\transform.targets" /> +</Project> \ No newline at end of file diff --git a/Tests/Test_QtVsTools.Package/Properties/AssemblyInfo.cs b/Tests/Test_QtVsTools.Package/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e33cba0 --- /dev/null +++ b/Tests/Test_QtVsTools.Package/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Test_QtVsTools.Package")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Test_QtVsTools.Package")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("afd33401-2f15-4e72-ab35-42c3ee12e897")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Tests/Test_QtVsTools.Package/QtVsTestClient.cs b/Tests/Test_QtVsTools.Package/QtVsTestClient.cs new file mode 100644 index 0000000..a98f68b --- /dev/null +++ b/Tests/Test_QtVsTools.Package/QtVsTestClient.cs @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Diagnostics; +using System.IO; +using System.IO.Pipes; +using System.Linq; +using System.Text; + +namespace QtVsTools.Test +{ + public class QtVsTestClient : IDisposable + { + public NamedPipeClientStream Stream { get; } + + public QtVsTestClient(int vsProcId) + { + Stream = new NamedPipeClientStream(".", $"QtVSTest_{vsProcId}", PipeDirection.InOut); + } + + public static QtVsTestClient Attach(int? vsProcId = null) + { + if (vsProcId == null) { + var procs = Process.GetProcessesByName("devenv"); + var vsProc = procs + .Where(p => p.Id != Process.GetCurrentProcess().Id + && !p.MainWindowTitle.StartsWith("vstools")) + .FirstOrDefault(); + if (vsProc == null) + throw new InvalidOperationException("VS process not found"); + vsProcId = vsProc.Id; + } + var client = new QtVsTestClient(vsProcId.Value); + client.Connect(); + return client; + } + + public void Connect() => Stream.Connect(); + + public void Dispose() => Stream?.Dispose(); + + public string RunMacro(string macroCode) + { + if (!Stream.IsConnected) + Connect(); + + var macroData = Encoding.UTF8.GetBytes(macroCode); + int macroDataSize = macroData.Length; + byte[] sizeData = BitConverter.GetBytes(macroDataSize); + + Stream.Write(sizeData, 0, sizeof(int)); + Stream.Write(macroData, 0, macroData.Length); + Stream.Flush(); + if (!Stream.IsConnected) + return Error("Disconnected"); + + Stream.WaitForPipeDrain(); + if (!Stream.IsConnected) + return Error("Disconnected"); + + for (int i = 0; i < sizeof(int); i++) { + int c = Stream.ReadByte(); + if (c == -1) + return Error("Disconnected"); + if (c < Byte.MinValue || c > Byte.MaxValue) + return Error("Pipe error"); + sizeData[i] = (byte)c; + } + + int replyDataSize = BitConverter.ToInt32(sizeData, 0); + byte[] replyData = new byte[replyDataSize]; + int bytesRead = 0; + while (bytesRead < replyDataSize) { + if (!Stream.IsConnected) + return Error("Disconnected"); + bytesRead += Stream.Read(replyData, bytesRead, replyDataSize - bytesRead); + } + + return Encoding.UTF8.GetString(replyData); + } + + public string RunMacroFile(string macroPath) + { + return LoadAndRunMacro(macroPath); + } + + public string StoreMacro(string macroName, string macroCode) + { + if (string.IsNullOrEmpty(macroName)) + return Error("Invalid macro name"); + return RunMacro($"//# macro {macroName}\r\n{macroCode}"); + } + + public string StoreMacroFile(string macroName, string macroPath) + { + if (string.IsNullOrEmpty(macroName)) + return Error("Invalid macro name"); + return LoadAndRunMacro(macroPath, $"//# macro {macroName}"); + } + + string LoadAndRunMacro(string macroPath, string macroHeader = null) + { + var macroCode = File.ReadAllText(macroPath, Encoding.UTF8); + if (string.IsNullOrEmpty(macroCode)) + return Error("Macro load failed"); + if (!string.IsNullOrEmpty(macroHeader)) + return RunMacro($"{macroHeader}\r\n{macroCode}"); + else + return RunMacro(macroCode); + } + + public const string MacroOk = "(ok)"; + public const string MacroWarn = "(warn)"; + public const string MacroError = "(error)"; + + static string Error(string msg) => $"{MacroError}\r\n{msg}"; + } +} diff --git a/Tests/Test_QtVsTools.Package/Test_QtVersionsPage.cs b/Tests/Test_QtVsTools.Package/Test_QtVersionsPage.cs new file mode 100644 index 0000000..7e57e2e --- /dev/null +++ b/Tests/Test_QtVsTools.Package/Test_QtVersionsPage.cs @@ -0,0 +1,247 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.Win32; + +namespace QtVsTools.Test.Package +{ + [TestClass] + public class Test_QtVersionsPage + { + // UI automation property conditions + string SetGlobals => @" +//# using System.IO +var elementSubtree = (TreeScope.Element | TreeScope.Subtree); +var isButton = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button); +var isDataGrid = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataGrid); +var isEdit = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit); +var isText = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Text); +var isWindow = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window);"; + + // Open menu: Tools > Options... + string OpenVsOptions => @" +//# ui context VSROOT => ""MenuBar"", ""Tools"" +//# ui pattern Invoke +//# ui context => ""Options..."" +//# ui pattern Invoke"; + + // Select options: page Qt > Versions + string SelectQtVersionsPage => @" +//# ui context VSROOT => ""Options"", ""Qt"" +//# ui pattern ExpandCollapse qtOptions +qtOptions.Expand(); +//# ui context => ""Versions"" +//# ui pattern SelectionItem qtVersions +qtVersions.Select();"; + + // Get reference to data grid with Qt versions + string GetQtVersionsTable => @" +//# ui context VSROOT => ""Options"" +//# ui find => elementSubtree, isDataGrid +//# ui pattern Grid qtVersionsTable"; + + // Add new row to versions table + string AddNewRow => @" +var lastRow = qtVersionsTable.Current.RowCount - 1; +UiContext = qtVersionsTable.GetItem(lastRow, 1); +//# ui find => elementSubtree, isButton +//# ui pattern Invoke +{ + //# ui context VSROOT => ""Options"" + //# ui find => elementSubtree, isDataGrid + //# ui pattern Grid qtVersionsTableAux + qtVersionsTable = qtVersionsTableAux; +} +UiContext = qtVersionsTable.GetItem(lastRow, 1); +//# ui find => elementSubtree, isEdit +//# ui pattern Value newVersionName +newVersionName.SetValue(""TEST_"" + Path.GetRandomFileName());"; + + // Set UI context to the path field of the new row + string SelectNewRowPath => @" +UiContext = qtVersionsTable.GetItem(lastRow, 3); +//# ui find => elementSubtree, isEdit"; + + // Save changes to the versions table and close the VS options dialog + // * Any error message will be copied to 'Result' + string SaveChanges => @" +//# ui context VSROOT => ""Options"", ""OK"" +//# ui pattern Invoke +//# thread ui +try { + //# ui context VSROOT 100 => ""Options"" + //# ui find => elementSubtree, isWindow +} catch (TimeoutException) { + return; +} +if (UiContext == null) + return; +//# ui find => elementSubtree, isText +Result = UiContext.Current.Name; +//# ui context VSROOT => ""Options"" +//# ui find => elementSubtree, isWindow +//# ui context => ""OK"" +//# ui pattern Invoke +//# ui context VSROOT => ""Options"", ""Cancel"" +//# ui pattern Invoke"; + + // Add new variable 'qtPath' with the path to the Qt version in the top row + // * This is assumed to be a valid path to an existing Qt version + string GetFirstRowPath => @" +if (qtVersionsTable.Current.RowCount <= 1) { + Result = MACRO_ERROR_MSG(""No Qt version registered.""); + return; +} +UiContext = qtVersionsTable.GetItem(0, 3); +//# ui find => elementSubtree, isEdit +//# ui pattern Value path +string qtPath = path.Current.Value; +if (Path.GetFileName(qtPath).Equals(""qmake.exe"", StringComparison.InvariantCultureIgnoreCase)) + qtPath = Path.GetDirectoryName(qtPath); +if (Path.GetFileName(qtPath).Equals(""bin"", StringComparison.InvariantCultureIgnoreCase)) + qtPath = Path.GetDirectoryName(qtPath);"; + + [TestMethod] + // Add new (empty) row => error + public void Test_EmptyVersion() + { + string result; + using (var vs = QtVsTestClient.Attach()) { + result = vs.RunMacro($@" + {SetGlobals} + {OpenVsOptions} + {SelectQtVersionsPage} + {GetQtVersionsTable} + {AddNewRow} + {SaveChanges}"); + } + Assert.IsTrue(result.Contains("Invalid Qt versions"), result); + } + + [TestMethod] + // Add new row and copy the path from the top row => OK + public void Test_AddNewVersion() + { + string result; + using (var vs = QtVsTestClient.Attach()) { + result = vs.RunMacro($@" + {SetGlobals} + {OpenVsOptions} + {SelectQtVersionsPage} + {GetQtVersionsTable} + {GetFirstRowPath} + {AddNewRow} + {SelectNewRowPath} + //# ui pattern Value newVersionPath + newVersionPath.SetValue(qtPath); + {SaveChanges}"); + } + Assert.IsTrue(result.StartsWith(QtVsTestClient.MacroOk), result); + } + + [TestMethod] + // Add new row, copy the path from the top row, and append "qmake.exe" => OK + public void Test_AddBinToPath() + { + string result; + using (var vs = QtVsTestClient.Attach()) { + result = vs.RunMacro($@" + {SetGlobals} + {OpenVsOptions} + {SelectQtVersionsPage} + {GetQtVersionsTable} + {GetFirstRowPath} + {AddNewRow} + {SelectNewRowPath} + //# ui pattern Value newVersionPath + newVersionPath.SetValue(Path.Combine(qtPath, ""bin"")); + {SaveChanges}"); + } + Assert.IsTrue(result.StartsWith(QtVsTestClient.MacroOk), result); + } + + [TestMethod] + // Add new row, copy the path from the top row, and append "bin\qmake.exe" => OK + public void Test_AddBinQMakeToPath() + { + string result; + using (var vs = QtVsTestClient.Attach()) { + result = vs.RunMacro($@" + {SetGlobals} + {OpenVsOptions} + {SelectQtVersionsPage} + {GetQtVersionsTable} + {GetFirstRowPath} + {AddNewRow} + {SelectNewRowPath} + //# ui pattern Value newVersionPath + newVersionPath.SetValue(Path.Combine(qtPath, ""bin"", ""qmake.exe"")); + {SaveChanges}"); + } + Assert.IsTrue(result.StartsWith(QtVsTestClient.MacroOk), result); + } + + [TestMethod] + // Add new row, copy the path from the top row, and append "include" => ERROR + public void Test_AddIncludeToPath() + { + string result; + using (var vs = QtVsTestClient.Attach()) { + result = vs.RunMacro($@" + {SetGlobals} + {OpenVsOptions} + {SelectQtVersionsPage} + {GetQtVersionsTable} + {GetFirstRowPath} + {AddNewRow} + {SelectNewRowPath} + //# ui pattern Value newVersionPath + newVersionPath.SetValue(Path.Combine(qtPath, ""include"")); + {SaveChanges}"); + } + Assert.IsTrue(result.Contains("Invalid Qt versions"), result); + } + + [ClassCleanup] + // Remove registry keys created during tests + public static void RemoveTestKeys() + { + var qtVersions = Registry.CurrentUser + .OpenSubKey(@"Software\Digia\Versions", writable: true); + using (qtVersions) { + var allVersions = qtVersions.GetSubKeyNames(); + var testVersions = allVersions.Where(k => k.StartsWith("TEST")); + foreach (var testVersion in testVersions) + qtVersions.DeleteSubKey(testVersion); + qtVersions.Close(); + } + } + } +} diff --git a/Tests/Test_QtVsTools.Package/Test_QtVsTools.Package.csproj b/Tests/Test_QtVsTools.Package/Test_QtVsTools.Package.csproj new file mode 100644 index 0000000..e2c41f0 --- /dev/null +++ b/Tests/Test_QtVsTools.Package/Test_QtVsTools.Package.csproj @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="$(VisualStudioVersion)" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <!-- + ***************************************************************************** + ** + ** Copyright (C) 2022 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the Qt VS Tools. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ***************************************************************************** +--> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{AFD33401-2F15-4E72-AB35-42C3EE12E897}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Test_QtVsTools.Package</RootNamespace> + <AssemblyName>Test_QtVsTools.Package</AssemblyName> + <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath> + <IsCodedUITest>False</IsCodedUITest> + <TestProjectType>UnitTest</TestProjectType> + <NuGetPackageImportStamp> + </NuGetPackageImportStamp> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Global references + // --> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // General package references + // --> + <Import Project="$(SolutionDir)\references.props" /> + <ItemGroup> + <PackageReference Include="$(Name_Microsoft_VSSDK_BuildTools)" Version="$(Version_Microsoft_VSSDK_BuildTools)" /> + <PackageReference Include="$(Name_Microsoft_VisualStudio_SDK)" Version="$(Version_Microsoft_VisualStudio_SDK)" ExcludeAssets="runtime" /> + <PackageReference Include="$(Name_Microsoft_Build)" Version="$(Version_Microsoft_Build)" /> + <PackageReference Include="$(Name_Microsoft_Build_Tasks_Core)" Version="$(Version_Microsoft_Build_Tasks_Core)" /> + <PackageReference Include="$(Name_MSTest_TestAdapter)" Version="$(Version_MSTest_TestAdapter)" /> + <PackageReference Include="$(Name_MSTest_TestFramework)" Version="$(Version_MSTest_TestFramework)" /> + </ItemGroup> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Version specific package references + // --> + <Choose> + <When Condition="'$(VisualStudioVersion)'=='17.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='16.0'"> + <ItemGroup> + </ItemGroup> + </When> + <When Condition="'$(VisualStudioVersion)'=='15.0'"> + <ItemGroup> + </ItemGroup> + </When> + </Choose> + <!-- + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Project items + // --> + <ItemGroup> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Test_QtVersionsPage.cs" /> + <Compile Include="QtVsTestClient.cs" /> + </ItemGroup> + <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(SolutionDir)\transform.targets" /> +</Project> \ No newline at end of file diff --git a/Tests/Test_QtVsTools.PriorityQueue/Properties/AssemblyInfo.cs b/Tests/Test_QtVsTools.PriorityQueue/Properties/AssemblyInfo.cs index 8561057..91ed9f8 100644 --- a/Tests/Test_QtVsTools.PriorityQueue/Properties/AssemblyInfo.cs +++ b/Tests/Test_QtVsTools.PriorityQueue/Properties/AssemblyInfo.cs @@ -27,7 +27,6 @@ ****************************************************************************/ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTitle("Test_QtVsTools.PriorityQueue")] diff --git a/Tests/Test_QtVsTools.PriorityQueue/Test_PriorityQueue.cs b/Tests/Test_QtVsTools.PriorityQueue/Test_PriorityQueue.cs index b5a2a4b..51f8213 100644 --- a/Tests/Test_QtVsTools.PriorityQueue/Test_PriorityQueue.cs +++ b/Tests/Test_QtVsTools.PriorityQueue/Test_PriorityQueue.cs @@ -89,12 +89,11 @@ public void TestTryPeek() { var q = new PunisherQueue<string>(); - string s; - Assert.IsTrue(!q.TryPeek(out s)); + Assert.IsTrue(!q.TryPeek(out _)); q.Enqueue("a"); q.Enqueue("b"); q.Enqueue("c"); - Assert.IsTrue(q.TryPeek(out s) && s == "a"); + Assert.IsTrue(q.TryPeek(out string s) && s == "a"); Assert.IsTrue(string.Join("", q) == "abc"); } @@ -121,12 +120,11 @@ public void TestTryDequeue() { var q = new PunisherQueue<string>(); - string s; - Assert.IsTrue(!q.TryDequeue(out s)); + Assert.IsTrue(!q.TryDequeue(out _)); q.Enqueue("a"); q.Enqueue("b"); q.Enqueue("c"); - Assert.IsTrue(q.TryDequeue(out s) && s == "a"); + Assert.IsTrue(q.TryDequeue(out string s) && s == "a"); Assert.IsTrue(string.Join("", q) == "bc"); } @@ -168,7 +166,7 @@ { var q = new PunisherQueue<string>(); int n = 0; - Task.Run(() => + _ = Task.Run(() => { for (int i = 0; i < 10000; ++i) { q.Enqueue(Path.GetRandomFileName()); @@ -177,8 +175,7 @@ } }); for (int i = 0; i < 10000; ++i) { - string s; - if (!q.TryDequeue(out s)) + if (!q.TryDequeue(out _)) --i; --n; Thread.Yield(); diff --git a/Tests/Test_QtVsTools.PriorityQueue/Test_QtVsTools.PriorityQueue.csproj b/Tests/Test_QtVsTools.PriorityQueue/Test_QtVsTools.PriorityQueue.csproj index 7cc709b..94ebaeb 100644 --- a/Tests/Test_QtVsTools.PriorityQueue/Test_QtVsTools.PriorityQueue.csproj +++ b/Tests/Test_QtVsTools.PriorityQueue/Test_QtVsTools.PriorityQueue.csproj @@ -76,12 +76,12 @@ </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - // Version specific references + // General package references // --> <Import Project="$(SolutionDir)\references.props" /> <ItemGroup> - <PackageReference Include="MSTest.TestAdapter" Version="$(Version_MSTest_TestAdapter)" /> - <PackageReference Include="MSTest.TestFramework" Version="$(Version_MSTest_TestFramework)" /> + <PackageReference Include="$(Name_MSTest_TestAdapter)" Version="$(Version_MSTest_TestAdapter)" /> + <PackageReference Include="$(Name_MSTest_TestFramework)" Version="$(Version_MSTest_TestFramework)" /> </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Tests/Test_QtVsTools.RegExpr/Properties/AssemblyInfo.cs b/Tests/Test_QtVsTools.RegExpr/Properties/AssemblyInfo.cs index 68ec694..2ab45a1 100644 --- a/Tests/Test_QtVsTools.RegExpr/Properties/AssemblyInfo.cs +++ b/Tests/Test_QtVsTools.RegExpr/Properties/AssemblyInfo.cs @@ -27,7 +27,6 @@ ****************************************************************************/ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTitle("Test_QtVsTools.RegExpr")] diff --git a/Tests/Test_QtVsTools.RegExpr/Test_MacroParser.cs b/Tests/Test_QtVsTools.RegExpr/Test_MacroParser.cs index 5f29dc4..f8d8ad5 100644 --- a/Tests/Test_QtVsTools.RegExpr/Test_MacroParser.cs +++ b/Tests/Test_QtVsTools.RegExpr/Test_MacroParser.cs @@ -26,7 +26,6 @@ ** ****************************************************************************/ -using System; using System.Diagnostics; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -38,7 +37,7 @@ [TestClass] public class Test_MacroParser { - MacroParser Parser = MacroParser.Get(); + readonly MacroParser Parser = MacroParser.Get(); [TestMethod] public void TestMacro() diff --git a/Tests/Test_QtVsTools.RegExpr/Test_QtVsTools.RegExpr.csproj b/Tests/Test_QtVsTools.RegExpr/Test_QtVsTools.RegExpr.csproj index 5622e2d..7a257c8 100644 --- a/Tests/Test_QtVsTools.RegExpr/Test_QtVsTools.RegExpr.csproj +++ b/Tests/Test_QtVsTools.RegExpr/Test_QtVsTools.RegExpr.csproj @@ -76,12 +76,12 @@ </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - // Version specific references + // General package references // --> <Import Project="$(SolutionDir)\references.props" /> <ItemGroup> - <PackageReference Include="MSTest.TestAdapter" Version="$(Version_MSTest_TestAdapter)" /> - <PackageReference Include="MSTest.TestFramework" Version="$(Version_MSTest_TestFramework)" /> + <PackageReference Include="$(Name_MSTest_TestAdapter)" Version="$(Version_MSTest_TestAdapter)" /> + <PackageReference Include="$(Name_MSTest_TestFramework)" Version="$(Version_MSTest_TestFramework)" /> </ItemGroup> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Tests/Test_QtVsTools.RegExpr/Test_SubTokens.cs b/Tests/Test_QtVsTools.RegExpr/Test_SubTokens.cs index 8118ea7..847557a 100644 --- a/Tests/Test_QtVsTools.RegExpr/Test_SubTokens.cs +++ b/Tests/Test_QtVsTools.RegExpr/Test_SubTokens.cs @@ -26,7 +26,6 @@ ** ****************************************************************************/ -using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace QtVsTools.Test.RegExpr diff --git a/Tests/Test_QtVsTools.RegExpr/Test_XmlIntParser.cs b/Tests/Test_QtVsTools.RegExpr/Test_XmlIntParser.cs index bca023e..85aa5f6 100644 --- a/Tests/Test_QtVsTools.RegExpr/Test_XmlIntParser.cs +++ b/Tests/Test_QtVsTools.RegExpr/Test_XmlIntParser.cs @@ -26,7 +26,6 @@ ** ****************************************************************************/ -using System; using System.Diagnostics; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -224,7 +223,7 @@ return xmlInt.Render(CharSpace.Repeat()); } - Parser Parser = GetParser(); + readonly Parser Parser = GetParser(); [TestMethod] public void TestConst() diff --git a/doc/config/qtvstools-project.qdocconf b/doc/config/qtvstools-project.qdocconf index 845c88c..a5fe990 100644 --- a/doc/config/qtvstools-project.qdocconf +++ b/doc/config/qtvstools-project.qdocconf @@ -6,6 +6,9 @@ project = "QtVSTools" description = "Qt VS Tools Manual" +#Words to ignore for auto-linking +ignorewords += MainWindow + sourcedirs += .. imagedirs += ../images outputdir = $OUTDIR @@ -22,7 +25,7 @@ qhp.QtVSTools.indexRoot = qhp.QtVSTools.subprojects = manual -qhp.QtVSTools.subprojects.manual.indexTitle = Qt VS Tools Manual +qhp.QtVSTools.subprojects.manual.indexTitle = All Topics qhp.QtVSTools.subprojects.manual.title = Qt VS Tools Manual qhp.QtVSTools.subprojects.manual.type = manual @@ -33,7 +36,10 @@ $QDOC_INDEX_DIR/qtgui/qtgui.index \ $QDOC_INDEX_DIR/qthelp/qthelp.index \ $QDOC_INDEX_DIR/qtlinguist/qtlinguist.index \ + $QDOC_INDEX_DIR/qtqml/qtqml.index \ $QDOC_INDEX_DIR/qtquick/qtquick.index \ + $QDOC_INDEX_DIR/qtqmlmodels/qtqmlmodels.index \ + $QDOC_INDEX_DIR/qtquickcontrols/qtquickcontrols.index \ $QDOC_INDEX_DIR/qtwidgets/qtwidgets.index # Doxygen compatibility commands diff --git a/doc/config/style/qt5-sidebar.html b/doc/config/style/qt5-sidebar.html index 60760ac..1b0e0ec 100644 --- a/doc/config/style/qt5-sidebar.html +++ b/doc/config/style/qt5-sidebar.html @@ -1,15 +1,50 @@ <div class="sectionlist normallist"> <div class="heading"> - <a name="reference"></a> - <h2 id="reference">Qt VS Tools Manual</h2> + <h2>Getting Started</h2> </div> <div class="indexboxcont indexboxbar"> <ul> - <li><a href="qtvstools-getting-started.html">Getting Started</a></li> - <li><a href="qtvstools-managing-projects.html">Managing Projects</a></li> - <li><a href="qtvstools-form-files.html">Adding Form Files to Projects</a></li> - <li><a href="qtvstools-managing-resources.html">Managing Resources</a></li> - <li><a href="qtvstools-translation-files.html">Creating Qt Translation Files for Projects</a></li> - <li><a href="qtvstools-faq.html">FAQ</a></li> + <li><a href="qtvstools-qt-widgets-application.html">Tutorial: Qt Widgets Application</a></li> + <li><a href="qtvstools-qt-quick-application.html">Tutorial: Qt Quick Application</a></li> </ul> </div> +</div> +<div class="sectionlist normallist"> + <div class="heading"> + <h2>Configuring Builds</h2> + </div> + <ul> + <li><a href="qtvstools-managing-qt-versions.html">Managing Qt Versions</a></li> + <li><a href="qtvstools-building.html">Building</a></li> + <li><a href="qtvstools-cross-compiling.html">Cross-Compiling</a></li> + <li><a href="qtvstools-importing-and-exporting-projects.html">Importing and Exporting Projects</a></li> + </ul> +</div> +<div class="sectionlist normallist"> + <div class="heading"> + <h2>Managing Projects</h2> + </div> + <ul> + <li><a href="qtvstools-creating-projects.html">Creating Projects</a></li> + <li><a href="qtvstools-creating-files.html">Creating Files</a></li> + </ul> +</div> +<div class="sectionlist normallist"> + <ul> + <li><a href="qtvstools-intellisense-info.html">Updating IntelliSense Info</a></li> + </ul> +</div> +<div class="sectionlist normallist"> + <div class="heading"> + <h2>Debugging</h2> + </div> + <ul> + <li><a href="qtvstools-debugging-qt-quick.html">Debugging Qt Quick Applications</a></li> + <li><a href="qtvstools-debugging-linux.html">Debugging on Linux</a></li> + </ul> +</div> +<div class="sectionlist normallist"> + <ul> + <li><a href="qtvstools-getting-help.html">Getting Help</a></li> + </ul> +</div> diff --git a/doc/images/front-advanced.png b/doc/images/front-advanced.png new file mode 100644 index 0000000..87780aa --- /dev/null +++ b/doc/images/front-advanced.png Binary files differ diff --git a/doc/images/front-coding.png b/doc/images/front-coding.png new file mode 100644 index 0000000..edfc550 --- /dev/null +++ b/doc/images/front-coding.png Binary files differ diff --git a/doc/images/front-gs.png b/doc/images/front-gs.png new file mode 100644 index 0000000..27706a8 --- /dev/null +++ b/doc/images/front-gs.png Binary files differ diff --git a/doc/images/front-help.png b/doc/images/front-help.png new file mode 100644 index 0000000..d2f9d42 --- /dev/null +++ b/doc/images/front-help.png Binary files differ diff --git a/doc/images/front-preview.png b/doc/images/front-preview.png new file mode 100644 index 0000000..fe7aab3 --- /dev/null +++ b/doc/images/front-preview.png Binary files differ diff --git a/doc/images/front-projects.png b/doc/images/front-projects.png new file mode 100644 index 0000000..69414f4 --- /dev/null +++ b/doc/images/front-projects.png Binary files differ diff --git a/doc/images/qtvstools-msbuild-diagram.png b/doc/images/qtvstools-msbuild-diagram.png new file mode 100644 index 0000000..e136170 --- /dev/null +++ b/doc/images/qtvstools-msbuild-diagram.png Binary files differ diff --git a/doc/images/qtvstools-options-qt-general.png b/doc/images/qtvstools-options-qt-general.png new file mode 100644 index 0000000..6d1e62a --- /dev/null +++ b/doc/images/qtvstools-options-qt-general.png Binary files differ diff --git a/doc/images/qtvstools-qt-project-settings.png b/doc/images/qtvstools-qt-project-settings.png index c7f7bc2..1367921 100644 --- a/doc/images/qtvstools-qt-project-settings.png +++ b/doc/images/qtvstools-qt-project-settings.png Binary files differ diff --git a/doc/images/qtvstools-qt-translation-file-wizard.png b/doc/images/qtvstools-qt-translation-file-wizard.png new file mode 100644 index 0000000..c39e3c5 --- /dev/null +++ b/doc/images/qtvstools-qt-translation-file-wizard.png Binary files differ diff --git a/doc/images/qtvstools-qt-widget-class-wizard.png b/doc/images/qtvstools-qt-widget-class-wizard.png index e6a30dd..37aba74 100644 --- a/doc/images/qtvstools-qt-widget-class-wizard.png +++ b/doc/images/qtvstools-qt-widget-class-wizard.png Binary files differ diff --git a/doc/images/qtvstools-qtquick-app-modules.png b/doc/images/qtvstools-qtquick-app-modules.png new file mode 100644 index 0000000..9c8054d --- /dev/null +++ b/doc/images/qtvstools-qtquick-app-modules.png Binary files differ diff --git a/doc/images/qtvstools-quick-addressbook-entries.png b/doc/images/qtvstools-quick-addressbook-entries.png new file mode 100644 index 0000000..e283e38 --- /dev/null +++ b/doc/images/qtvstools-quick-addressbook-entries.png Binary files differ diff --git a/doc/images/qtvstools-quick-addressbook-mainwindow.png b/doc/images/qtvstools-quick-addressbook-mainwindow.png new file mode 100644 index 0000000..94b5a82 --- /dev/null +++ b/doc/images/qtvstools-quick-addressbook-mainwindow.png Binary files differ diff --git a/doc/images/qtvstools-quick-addressbook-popup.png b/doc/images/qtvstools-quick-addressbook-popup.png new file mode 100644 index 0000000..d5de412 --- /dev/null +++ b/doc/images/qtvstools-quick-addressbook-popup.png Binary files differ diff --git a/doc/images/qtvstools-remote-debugging.png b/doc/images/qtvstools-remote-debugging.png new file mode 100644 index 0000000..2a083a7 --- /dev/null +++ b/doc/images/qtvstools-remote-debugging.png Binary files differ diff --git a/doc/qtvstools-online.qdocconf b/doc/qtvstools-online.qdocconf index 95d3f7c..6cb5590 100644 --- a/doc/qtvstools-online.qdocconf +++ b/doc/qtvstools-online.qdocconf @@ -3,7 +3,7 @@ HTML.footer = \ " </div>\n" \ " <p class=\"copy-notice\">\n" \ - " <acronym title=\"Copyright\">©</acronym> 2016 The Qt Company Ltd.\n" \ + " <acronym title=\"Copyright\">©</acronym> 2022 The Qt Company Ltd.\n" \ " Documentation contributions included herein are the copyrights of\n" \ " their respective owners. " \ " The documentation provided herein is licensed under the terms of the" \ diff --git a/doc/src/qtvstools.qdoc b/doc/src/qtvstools.qdoc index 1b0eda9..85ef0fa 100644 --- a/doc/src/qtvstools.qdoc +++ b/doc/src/qtvstools.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -36,10 +36,93 @@ or tools. You can install and update Qt VS Tools directly from Microsoft Visual Studio. + \table + \row + \li {4,1} \b {\l{All Topics}} + \row + \li \inlineimage front-gs.png + \li \inlineimage front-advanced.png + \li \inlineimage front-projects.png + \row + \li \b {\l{Getting Started}} + \list + \li \l {Tutorial: Qt Widgets Application} + \li \l {Tutorial: Qt Quick Application} + \endlist + \li \b {\l {Configuring Builds}} + \list + \li \l {Managing Qt Versions} + \li \l {Building} + \li \l {Cross-Compiling} + \li \l {Importing and Exporting Projects} + \endlist + \li \b {\l {Managing Projects}} + \list + \li \l {Creating Projects} + \li \l {Creating Files} + \endlist + \row + \li \inlineimage front-coding.png + \li \inlineimage front-preview.png + \li \inlineimage front-help.png + \row + \li \b {\l {Updating IntelliSense Info}} + \li \b {\l {Debugging}} + \list + \li \l {Debugging Qt Quick Applications} + \li \l {Debugging on Linux} + \endlist + \li \b {\l {Getting Help}} + \endtable +*/ + +/*! + \page qtvstools-toc.html + \title All Topics + + \list + \li \l {Getting Started} + \list + \li \l {Tutorial: Qt Widgets Application} + \li \l {Tutorial: Qt Quick Application} + \endlist + \li \l {Configuring Builds} + \list + \li \l {Managing Qt Versions} + \li \l {Building} + \li \l {Cross-Compiling} + \li \l {Importing and Exporting Projects} + \endlist + \li \l {Managing Projects} + \list + \li \l {Creating Projects} + \li \l {Creating Files} + \list + \li \l {Adding Form Files} + \li \l {Managing Resources} + \li \l {Creating Qt Translation Files} + \endlist + \endlist + \li \l {Updating IntelliSense Info} + \li \l {Debugging} + \list + \li \l {Debugging Qt Quick Applications} + \li \l {Debugging on Linux} + \endlist + \li \l {Getting Help} + \endlist +*/ + +/*! + \page qtvstools-getting-started.html + \previouspage Qt VS Tools Manual + \nextpage Tutorial: Qt Widgets Application + \title Getting Started + The main features of Qt VS Tools are: \list - \li Wizards for creating new Qt projects and classes. + \li Wizards for creating new Qt and Qt Quick projects and files. \li Automated build setup for the \l {Using the Meta-Object Compiler (moc)}{Meta-Object Compiler (moc)}, \l {User Interface Compiler (uic)}, and \l {Resource Compiler (rcc)}. @@ -55,36 +138,6 @@ \li Debugging extensions for Qt data types. \endlist - \section1 Table of Contents - - \list - \li \l {Getting Started} - \li \l {Managing Qt Versions} - \li \l {Building} - \li \l {Cross-Compiling} - \li \l {Creating Projects} - \li \l {Importing and Exporting Projects} - \li \l {Adding Form Files to Projects} - \li \l {Managing Resources} - \li \l {Creating Qt Translation Files for Projects} - \li \l {Updating IntelliSense Info} - \li \l {Getting Help} - \endlist -*/ - -/*! - \page qtvstools-getting-started.html - \previouspage Qt VS Tools Manual - \nextpage Managing Qt Versions - \title Getting Started - - This tutorial illustrates how to use Qt VS Tools to create a \l {Qt Widgets} - application. You will create a project using a project wizard and design a - widget-based UI using \QD. In addition, you will learn how to convert a - Microsoft Visual Studio project file into a qmake compatible \c .pro file. - - You can use Qt VS Tools to develop also \l{Qt Quick} applications. - \section1 Install Qt VS Tools In Microsoft Visual Studio, select \uicontrol Extensions > @@ -97,6 +150,40 @@ To create a Qt VS Tools project, you must add at least one \l{Managing Qt Versions}{Qt version}. + \section1 Create a Project + + Follow the tutorials to create your first applications: + + \list + \li \l {Tutorial: Qt Widgets Application} + \li \l {Tutorial: Qt Quick Application} + \endlist + + For all the options you have, see \l {Creating Projects}. +*/ + +/*! + \page qtvstools-qt-widgets-application.html + \previouspage Getting Started + \nextpage Tutorial: Qt Quick Application + \title Tutorial: Qt Widgets Application + + This tutorial illustrates how to use Qt VS Tools to create a \l {Qt Widgets} + application. You will create a project using a project wizard and design a + widget-based UI using \QD. In addition, you will learn how to convert a + Microsoft Visual Studio project file into a qmake compatible \c .pro file. + + You can use Qt VS Tools to develop also \l{Qt Quick} applications. + + \section1 Before You Start + + Before you start, you have to: + + \list + \li \l {Install Qt VS Tools} + \li \l {Add a Qt Version} + \endlist + \section1 Create a Qt Widgets Application Project To create a Qt Widgets application project in Visual Studio: @@ -104,8 +191,9 @@ \list 1 \li Select \uicontrol File > \uicontrol New > \uicontrol Project, and search for \uicontrol {Qt Widgets Application}. - \li In the \uicontrol Name field, enter \e AddressBook, and then select - \uicontrol OK. + \li Select the project wizard, and then select \uicontrol Next. + \li In the \uicontrol {Project name} field, enter \e AddressBook, + and then select \uicontrol OK. \li To acknowledge the \uicontrol Welcome dialog, select \uicontrol Next. \li Set up the \uicontrol Debug build configuration and select the @@ -407,9 +495,366 @@ */ /*! + \page qtvstools-qt-quick-application.html + \previouspage Tutorial: Qt Widgets Application + \nextpage Configuring Builds + \title Tutorial: Qt Quick Application + + This tutorial illustrates how to use Qt VS Tools to create a \l {Qt Quick} + application. You will create a project using a project wizard and design a + Qt Quick UI. In addition, you will learn how to add QML module definitions + and QML files to your projects. + + You can use Qt VS Tools to develop also \l{Qt Widgets} applications. + + \section1 Before You Start + + Before you start, you have to: + + \list + \li \l {Install Qt VS Tools} + \li \l {Add a Qt Version} + \endlist + + \section1 Create a Qt Quick Application Project + + To create a Qt Quick application project in Visual Studio: + + \list 1 + \li Select \uicontrol File > \uicontrol New > \uicontrol Project, and + search for \uicontrol {Qt Quick Application}. + \li Select the project wizard, and then select \uicontrol Next. + \li In the \uicontrol {Project name} field, enter \e QuickAddressBook, + and then select \uicontrol Create. + \li To acknowledge the \uicontrol Welcome dialog, select + \uicontrol Next. + \li To set up debug and release build configurations, click in + \uicontrol {Quick Modules}, and select the \uicontrol {Quick} and + \uicontrol {Quick Controls2} modules to include in the project: + \image qtvstools-qtquick-app-modules.png "Selecting Qt modules in Qt Quick Application Wizard" + \li Select \uicontrol Finish to create the project. + \endlist + + You now have a small working Qt Quick application. Select \uicontrol Build > + \uicontrol {Build Solution} to build it, and then select \uicontrol Debug > + \uicontrol {Start Debugging} to run it. For now, the result is an empty + window. + + \section1 Design the Main Window + + The wizard created a main QML file for you, which declares a root object of + the type \l Window. You can modify the file to design the application's main + window. + + Specify values for the Window \c color and \c title properties to set the + background color and title of the application main window: + + \quotefromfile QuickAddressBook/main.qml + \skipto Window { + \printuntil title + + \section2 Add a Button + + To create the \uicontrol Add button, declare an object of the \l Button type + from the \l {Qt Quick Controls} module. Set the value of the button \c text + property to \e Add and the value of the \c font.pointSize property to \e 24: + + \skipto Button { + \printuntil font.pointSize + + When you run the application, you should now see this: + + \image qtvstools-quick-addressbook-mainwindow.png QuickAddressBook's main window + + \section2 Connect the Button to an Action + + QML has a signal and handler mechanism, where the signal is the event and + the signal is responded to through a signal handler. When a signal is + emitted, the corresponding signal handler is invoked. Placing logic such + as a script or other operations in the handler allows the component to + respond to the event. + + To receive a notification when a particular signal is emitted for a + particular object, the object definition should declare a signal handler + named \c on<Signal>, where \c <Signal> is the name of the signal, with + the first letter capitalized. The signal handler should contain the + JavaScript code to be executed when the signal handler is invoked. + + The \l Button type has a \c clicked signal, which is emitted when the users + click the button. To invoke a popup for adding an address book entry when + the users select the \uicontrol Add button in the main window, you must + connect the \c onClicked signal handler of the button to the \c open() + method of the popup. You will add the popup as a separate QML type later. + + \printuntil } + + \section2 Add a List Model + + \image qtvstools-quick-addressbook-entries.png QuickAddressBook entries + + Within the Window, declare an object of the \l ListModel type with the + \c id \e addressList for storing the contact data. A list model defines + a free-form list data source: + + \quotefromfile QuickAddressBook/main.qml + \skipto ListModel { + \printuntil } + + \section2 Declare a Popup + + Declare an object of the custom \c NewAddressPopup type that + defines the popup where the users will add address book entries. + Use the \c onAddressAdded signal handler to determine that address + book entries are appended to the \e addressList model: + + \printuntil } + \printuntil } + + You will create the \c NewAddressPopup type later. + + \section2 Position the Button + + Declare an object of \l ColumnLayout type to position the \l Button object + and an instance of the \l Repeater type: + + \printuntil } + + Anchor the column layout to the left and right edges of its parent to make + the application scalable on different screen sizes. Set the \c spacing + between the rows in the column to \e 0. + + \section2 Add a Repeater + + The \l Repeater type is used to create a large number of similar items. It + has a model and a delegate: for each entry in the model, the delegate is + instantiated in a context seeded with data from the model. A repeater is + usually enclosed in an instance of a positioner type such as a + \l ColumnLayout to visually position the multiple delegate items created + by the repeater. + + Specify \e addressList as the \c model to use for the repeater: + + \printuntil anchors.right + + Declare an object of the custom \c AddressBookItem type that the + repeater will use to instantiate address book entries: + + \printuntil id: + + You will create the \c AddressBookItem type later. + + \section2 Connect the Remove Button to an Action + + Use the \c onRemoved signal handler to specify that an address book entry + is removed from the list when the users click the \uicontrol Remove button + for an address book entry. + + \printuntil } + + \section1 Add a Popup + + Now that the main window is ready, you can move on to create the popup + where users can add address book entries. The data that the + users enter is instantiated by the repeater in the main window, as + specified by the \c AddressBookItem type. + + \image qtvstools-quick-addressbook-popup.png QuickAddressBook's popup + + You can use a Qt file wizard in Visual Studio to create a custom type + that defines the popup. + + To create custom QML types, you must first add a QML Module Definition + (\c qmldir) file to the project. + + \section2 Add a QML Module Definition + + A QML module definition (\c qmldir) maps each custom QML type to its + corresponding source file. + + To add a QML module definition, select \uicontrol Project > + \uicontrol {Add New Item} > \uicontrol Qt > + \uicontrol {Qt QML Module Definition} > \uicontrol Add. + + In the \c qmldir file, add QML type definitions for \e AddressBookItem and + \e NewAddressPopup: + + \quotefile QuickAddressBook/qmldir + + Next, you will create the QML types. + + \section2 Create a Popup + + To add a custom QML type to the project: + + \list 1 + \li Select \uicontrol Project > \uicontrol {Add New File} > + \uicontrol Qt > \uicontrol {Qt QML File} > \uicontrol Add. + \li In the \uicontrol Name field, enter \e NewAddressPopup. + \li Select \uicontrol Finish to create a custom QML type. + \endlist + + \section2 Design the Popup + + In \e NewAddressPopup.qml, declare a root object of the type \l Popup to + create a popup that can be opened within a \l Window. A popup does not + provide a layout of its own, so you will use a \l ColumnLayout and a + \l RowLayout to position the \uicontrol Name and \uicontrol {E-Mail Address} + fields. + + \quotefromfile QuickAddressBook/QuickAddressBookTypes/NewAddressPopup.qml + \skipto Popup { + \printuntil id: + + Set the \c modal property to \c true to specify that the popup is modal. Set + the \c focus property to \c true to specify that the popup requests focus: + + \printuntil focus: + + Specify values for the \c width, \c x, and \c y properties to determine the + position and size of the popup on top of the main window: + + \printuntil y: + + \section2 Reset Popup Controls + + When the popup opens, the \uicontrol Name and \uicontrol {E-Mail Address} + fields should display placeholder text and any values entered previously + should be cleared. You use the \c onOpened signal handler to reset the + values of the fields and give focus to the \uicontrol Name field: + + \printuntil } + + \section2 Position Fields + + Use an instance of the \l ColumnLayout type to position the \l TextField + objects that specify the \uicontrol Name and \uicontrol {E-Mail Address} + fields of the popup: + + \skipto ColumnLayout { + \printuntil id: addrField + \printuntil } + \printuntil } + + \section2 Position Buttons + + Use an instance of a \l RowLayout type to position two \l Button objects + that specify the \uicontrol Add and \uicontrol Cancel buttons: + + \printuntil Layout.fillWidth: true + + \section2 Connect Buttons to Actions + + When the users click the \uicontrol Add button, the values they entered to + the \uicontrol Name and \uicontrol {E-Mail Address} fields are added to the + address list in the main window and the popup is closed. + + To enable this, add the \c {addressAdded(string newName, string newAddr)} + signal: + + \quotefromfile QuickAddressBook/QuickAddressBookTypes/NewAddressPopup.qml + \skipto addressAdded( + \printuntil ) + + Connect the \c onClicked signal handler of the \uicontrol Add button to + the \c addressAdded() signal and to the popup's \c close() method: + + \skipto Button { + \printuntil } + \printuntil } + + For the \uicontrol Cancel button, connect the \c onClicked signal handler to + the to the popup's \c close() method to close the popup without saving the + data: + + \printuntil } + + \section1 Define an Address Book Entry + + Address book entries are presented in the main window as specified by a + custom \c AddressBookItem type. + + Select \uicontrol Project > \uicontrol {Add New File} > \uicontrol Qt > + \uicontrol {Qt QML File} > \uicontrol Add, to create a new QML file + called \e AddressBookItem.qml. + + \section2 Design the Entry + + First, you will declare a root object of type \l Rectangle. It is one of the + basic building blocks you can use to create an application in QML. Give it + an \c id to be able to refer to it later. + + \quotefromfile QuickAddressBook/QuickAddressBookTypes/AddressBookItem.qml + \skipto Rectangle { + \printuntil id: + + To use alternating colors for rows, set the value of the \c color property: + + \printuntil color: + + Anchor the rectangle to the left and right edges of its parent to make + the application scalable on different screen sizes. Bind the rectangle + \c height property to the height of the text items it will contain: + + \printuntil height: + + \section2 Connect the Remove Button to an Action + + Add the \c removed() signal that you will connect to the \onClicked + signal handler of the remove button. This removes an address book entry + from the main window when users click the button: + + \printuntil signal removed() + + \section2 Position the Button and Text + + Use instances of the \l RoundButton and \l Text types within an instance of + a \l RowLayout type to define an address book entry: + + \printuntil } + + \section2 Format the Text + + Set the value of the \c text property to combine the values of the \c name + and \c addr fields from the popup and to use bold and italic formatting for + the values: + + \printuntil } + + Your application is now complete. + + \section1 Create Project Files + + To build the application on other platforms, you need to create a \c .pro + file for the project, as instructed in \l{Create Qt Project Files}. + +*/ + +/*! + \page qtvstools-managing-projects.html + \previouspage Importing and Exporting Projects + \nextpage Creating Projects + \title Managing Projects + + Qt VS Tools provides wizards for creating several types of Qt and Qt Quick + projects and files that you can add to the projects, such as classes, form + files, or custom QML types. + + You can use the integrated Qt Resource editor to manage the resources in + Qt projects. + + In addition, you can create a Qt translation source (TS) file and start + \QL from Visual Studio to translate the strings in your application. + + \list + \li \l {Creating Projects} + \li \l {Creating Files} + \endlist +*/ + +/*! \page qtvstools-creating-projects.html - \previouspage Cross-Compiling - \nextpage Importing and Exporting Projects + \previouspage Managing Projects + \nextpage Creating Files \title Creating Projects Once you have installed Qt VS Tools, you can search for and then select @@ -439,11 +884,158 @@ To start writing Qt code and building your projects, you must tell Visual Studio where to find the \l{Managing Qt Versions}{Qt version} that you want to use. + + The application tutorials contain examples of using the project templates: + + \list + \li \l {Tutorial: Qt Widgets Application} + \li \l {Tutorial: Qt Quick Application} + \endlist +*/ + +/*! + \page qtvstools-creating-files.html + \previouspage Creating Projects + \nextpage Adding Form Files + \title Creating Files + + You can use file templates to add the following types of files to projects + by selecting \uicontrol Project > \uicontrol {Add New Item} > + \uicontrol Installed > \uicontrol {Visual C++} > \uicontrol Qt: + + \list + \li \uicontrol {Qt Class} adds a Qt class to an Application project. + \li \uicontrol {Qt Dialog Form File (Button Bottom)} adds a dialog with + \uicontrol OK and \uicontrol Cancel buttons at its bottom to a + Qt Widgets Application project. + \li \uicontrol {Qt Dialog Form File (Button Right)} adds a dialog with + buttons at its right edge to a Qt Widgets Application project. + \li \uicontrol {Qt MainWindow Form File} adds a form file to a + Qt Widgets Application project. + \li \uicontrol {Qt QML File} adds a custom QML type to a Qt Quick + Application project. + \li \uicontrol {Qt QML Module Definition} adds a qmldir file that + specifies the custom QML types used in a Qt Quick Application + project. + \li \uicontrol {Qt Resource File} adds a Qt resource file (.qrc) to + an Application project. + \li \uicontrol {Qt Translation File} adds a Qt translation file (.ts) + to an Application project. + \li \uicontrol {Qt Widget Class} adds a Qt Widgets class to a + Qt Widgets Application project. + \li \uicontrol {Qt Widget Form File} adds a Qt Widgets form file (.ui) + to an Application project. + \endlist + + The following sections describe how to add different types of files to + projects: + + \list + \li \l {Adding Form Files} + \li \l {Managing Resources} + \li \l {Creating Qt Translation Files} + \endlist + + The application tutorials contain examples of using file templates to add + files to projects: + + \list + \li \l {Tutorial: Qt Widgets Application} + \li \l {Tutorial: Qt Quick Application} + \endlist +*/ + +/*! + \page qtvstools-configuring-builds.html + \previouspage Tutorial: Qt Quick Application + \nextpage Managing Qt Versions + \title Configuring Builds + + In Visual Studio, C++ projects are built using the Project System, + where MSBuild provides the project file format and build framework. + Qt VS Tools make use of the extensibility of MSBuild to provide + design-time and build-time integration of Qt in Visual Studio projects. + + Qt uses \c .pro files with \l {qmake Manual}{qmake} to build projects, + whereas Visual Studio uses \c .vcproj files. Qt VS Tools enables you to + import Qt project files into Visual Studio and export them back into + Qt build files. In addition, you can convert Qt VS Tools projects into + a qmake project, or the other way around. + + \list + \li \l {Managing Qt Versions} + \li \l {Building} + \li \l {Cross-Compiling} + \li \l {Importing and Exporting Projects} + \endlist + + \section1 MSBuild Configurations + + At very general level, MSBuild might be described as follows: + + \list + \li An MSBuild project consists of references to source files and + descriptions of actions to take in order to process those source + files that are called \e targets. + \li The build process runs in the context of a project configuration, + such as \e Debug or \e Release. A project may contain any number + of configurations. + \li Data associated to source files and the project itself is accessible + through \e properties. MSBuild properties are name-value definitions, + specified per configuration. That is, each configuration has its own + set of property definitions. + \endlist + + \image qtvstools-msbuild-diagram.png "Diagram showing Visual Studio Project and MSBuild" + + \section2 Properties + + Properties may apply to the project itself or to a specific file in the + project, and can be defined either globally or locally: + + \list + \li Project scope properties are always global. For example, the + project's output directory or target file name. + \li Properties applied to source files can be defined globally, in + which case the same value will apply to all files. For example, + the default compiler warning level could be defined globally at + level 3. + \li Such a global, file-scope definition may be overridden for a + specific file by a locally defined property with the same name. + For example, one of the source files needs to be compiled with + warning level 4. + \li Global definitions are stored in the project file or imported from + property sheet files. + \li Local property definitions are stored in the project file, within + the associated source file references. + \endlist + + \section2 Qt Settings + + Qt Visual Studio Tools integrate with the MSBuild project system by + providing a set of Qt-specific targets that describe how to process + files such as moc headers by using the appropriate Qt tools. + + \image qtvstools-qt-project-settings.png "Qt Project Settings" + + Qt settings are fully-fledged project properties, which ensures that: + + \list + \li Changes in Qt settings are synchronized with all the other + properties in the project. + \li You can specify Qt settings, such as Qt versions and modules, + separately for each build configuration. + \li You can override compiler properties for files generated by + Qt tools in project settings + \li You can share Qt settings within a team or organization by + exporting and importing them to and from shared \e {property sheet} + files (\c .props). + \endlist */ /*! \page qtvstools-managing-qt-versions.html - \previouspage Getting Started + \previouspage Configuring Builds \nextpage Building \title Managing Qt Versions @@ -529,7 +1121,7 @@ /*! \page qtvstools-cross-compiling.html \previouspage Building - \nextpage Creating Projects + \nextpage Importing and Exporting Projects \title Cross-Compiling Qt VS Tools supports cross-compilation of Qt projects by integrating @@ -589,8 +1181,8 @@ /*! \page qtvstools-importing-and-exporting-projects.html - \previouspage Creating Projects - \nextpage Adding Form Files to Projects + \previouspage Cross-Compiling + \nextpage Managing Projects \title Importing and Exporting Projects Qt and Visual Studio use different file formats to save projects. If you @@ -659,16 +1251,16 @@ /*! \page qtvstools-form-files.html - \previouspage Importing and Exporting Projects + \previouspage Creating Files \nextpage Managing Resources - \title Adding Form Files to Projects + \title Adding Form Files You can start \QD from Qt VS Tools by double-clicking a \c .ui file. For more information about using \QD, see the \l{Qt Designer Manual}. To add a new \c .ui file to the project, select \uicontrol Project > - \uicontrol {Add Qt Class} > \uicontrol Installed > \uicontrol {Visual C++} > - \uicontrol Qt > \uicontrol {Qt Widget Class}. + \uicontrol {Add New Item} > \uicontrol Installed > \uicontrol {Visual C++} > + \uicontrol Qt > \uicontrol {Qt Widgets Form File}. \image qtvstools-qt-widget-class-wizard.png @@ -679,8 +1271,8 @@ /*! \page qtvstools-managing-resources.html - \previouspage Adding Form Files to Projects - \nextpage Creating Qt Translation Files for Projects + \previouspage Adding Form Files + \nextpage Creating Qt Translation Files \title Managing Resources Adding new resources to a Qt project is similar to adding resources to a @@ -727,18 +1319,20 @@ \page qtvstools-translation-files.html \previouspage Managing Resources \nextpage Updating IntelliSense Info - \title Creating Qt Translation Files for Projects + \title Creating Qt Translation Files To add a new translation file to the project: + \image qtvstools-qt-translation-file-wizard.png + \list 1 - \li Select \uicontrol Extensions > \uicontrol {Qt VS Tools} > - \uicontrol {Create New Translation File}. - \li In the \uicontrol Language field, select a language from the list of - supported languages. - \li In the \uicontrol Filename field, enter a filename for the - translation file. - \li Select \uicontrol OK to create the file and have it listed in + \li Select \uicontrol Project > \uicontrol {Add New Item} > \uicontrol Installed > + \uicontrol {Visual C++} > \uicontrol Qt > \uicontrol {Qt Translation File}. + \li In \uicontrol {Select a Language}, you can choose a language from the list + of supported languages. You can use \uicontrol Search to filter for a specific + language. + \li In the \uicontrol {Save as} field, enter a filename for the translation file. + \li Select \uicontrol Finish to create the file and have it listed in \uicontrol {Translation Files} in Visual Studio's Solution Explorer. \li Right-click a translation file to open a context menu with options for running \c lupdate and \c lrelease. @@ -761,7 +1355,7 @@ /*! \page qtvstools-getting-help.html - \previouspage Updating IntelliSense Info + \previouspage Debugging on Linux \title Getting Help By default, Qt VS Tools tries to display Qt online documentation when you @@ -790,8 +1384,8 @@ /*! \page qtvstools-intellisense-info.html - \previouspage Creating Qt Translation Files for Projects - \nextpage Getting Help + \previouspage Creating Qt Translation Files + \nextpage Debugging \title Updating IntelliSense Info Visual Studio provides IntelliSense code editing features for C++ types @@ -822,6 +1416,164 @@ \li \uicontrol {Verbosity of background build log} determines the amount of info recorded in the background build log. \endlist - */ +/*! + \page qtvstools-debugging.html + \previouspage Updating IntelliSense Info + \nextpage Debugging Qt Quick Applications + \title Debugging + + Visual Studio supports debugging Qt C++ applications using the Visual Studio + debugger and Qt Quick applications using the \e {QML debug engine}. To debug + applications on Linux, you can use GDB. + + You can debug Qt and Qt Quick applications in Visual Studio by setting + breakpoints in C++ and QML files and stepping through the execution of code. + While in break mode, you can watch variables and change their values, as + well as evaluate arbitrary expressions. For Qt Quick applications, a QML + debugging session runs concurrently to a C++ debugging session, which + enables you to set breakpoints and watch variables in both C++ and QML + during the same debugging session. + + To start a debugging session, select \uicontrol Debug > + \uicontrol {Start Debugging} or press \key F5. + + \list + \li \l {Debugging Qt Quick Applications} + \li \l {Debugging on Linux} + \endlist +*/ + +/*! + \page qtvstools-debugging-qt-quick.html + \previouspage Debugging + \nextpage Debugging on Linux + \title Debugging Qt Quick Applications + + A \e {QML debug engine} extends the Visual Studio debugger with features of + the \l{QML Debugging Infrastructure}{QML debugging infrastructure}, which is + a part of the \l{Qt QML} module that provides services for debugging, + inspecting, and profiling applications via a TCP port. The debug engine + implements interfaces from the Active Debugging 7 (AD7) extensibility + framework for the Visual Studio debugger. + + If a Qt project contains QML resource files, starting a debugging session + (for example, by pressing \key F5) launches the native application and + connects to the QML debugging infrastructure of that application. This can + be seen in the Processes window of the Visual Studio debugger. Two processes + are listed: a native process that corresponds to the actual physical + process created for the C++ debugging session and a QML process that does + not correspond to any physical process that is running on the machine, but + rather represents the connection to the QML debugging runtime within the + native process. + + The presence of both a native process and a QML process enables setting + breakpoints both in C++ or QML code. The Visual Studio debugger forwards + breakpoint requests to the appropriate debug engine. A filled circular + breakpoint marker in QML code indicates a valid breakpoint. This means that + a breakpoint request for that file position was sent to the QML runtime + and was confirmed by it. + + When a breakpoint is hit, Visual Studio shows the current state of the call + stack. Unlike other scenarios of debugging applications that mix several + languages, such as .NET and native debugging, the QML debug engine does not + provide true mixed mode debugging. It runs concurrently with the native + debug engine and is not considered to be related to the native process by + the Visual Studio debugger. Therefore, even though you can debug both C++ + and QML in the same debugging session, the stack that is shown when a QML + breakpoint is hit includes only QML function calls. The C++ context of those + calls will not be available. + + As in the case of native debugging, while in break mode, it is possible to + view and modify the values of local variables in the context of the + currently active call stack frame, as well as to create watches for any + variable or expression. In the Immediate window, you can evaluate any + expression in the context of the current stack frame. + + Move the mouse over a QML expression to display an instant watch window. + The value of that expression in the current context is displayed and can + be modified. + + \section1 Enabling QML Debugging + + QML debugging is enabled by default. To disable processing of all QML + debug events by the QML debug engine, select \uicontrol Extensions > + \uicontrol {Qt VS Tools} > \uicontrol Options > \uicontrol Qt + \uicontrol General > \uicontrol {QML Debugging}, and set + \uicontrol {Process debug events} to \uicontrol False. + This effectively excludes the QML debug engine from the debugging + environment and disables debugging of QML code for all projects. + + \image qtvstools-options-qt-general.png "Qt General Options" + + To increase or decrease the timeout for debugging connections in + milliseconds, edit the value of \uicontrol {Runtime connection timeout}. + To remove the timeout, set the value to \uicontrol Disabled. + + For more information about debugging Qt Quick applications on Linux devices, + see \l {Remote QML Debugging}. +*/ + +/*! + \page qtvstools-debugging-linux.html + \previouspage Debugging Qt Quick Applications + \nextpage Getting Help + \title Debugging on Linux + + If you have set up Qt VS Tools for \l {Cross-Compiling}{cross-compilation} + on Linux, you can debug applications running on a Linux devices. First + launch the application using \c gdbserver and then configure GDB to connect + to the device and start a remote debugging session. + + \image qtvstools-remote-debugging.png + + For this to work, the GDB installed in the WSL must support the target + device architecture. A simple way to achieve this is to install + \c gdb-multiarch. To ensure the Visual Studio uses the correct debugger, + create a symbolic link from \c gdb to \c gdb-multiarch. + + To set up the remote debugging session in Visual Studio, you must + pass additional commands to GDB. Select \uicontrol Project > + \uicontrol Properties > \uicontrol Debugging, and then select + \uicontrol {GDB Debugger} in \uicontrol {Debugger to launch}. In + \uicontrol {Additional Debugger Commands}, add the following commands: + + \badcode + target extended-remote <IP_address>:<port> + set remote exec-file <path_to_executable> + \endcode + + Before starting the remote debugging session, set the required environment + variables and launch \c gdbserver on the device: + + \list + \li \l{https://man7.org/linux/man-pages/man8/ld.so.8.html} + {LD_LIBRARY_PATH} specifies the path to the directory + where Qt binaries are installed. + \li \l {Qt for Embedded Linux}{QT_QPA_PLATFORM} specifies the platform + plugin, such as EGLFS, LinuxFB, DirectFB, or Wayland. + \li \c QT_QPA_PLATFORM_PLUGIN_PATH specifies the path to the + directory where the platform plugin is installed. + \li For the \l {EGLFS} platform, \c QT_QPA_EGLFS_PHYSICAL_WIDTH and + \c QT_QPA_EGLFS_PHYSICAL_HEIGHT specify the screen width and + height in millimeters. + \li \l{QML Import Path}{QML2_IMPORT_PATH} specifies the path to the + directory where QML modules are installed. + \endlist + + Press \key F5 to start the remote debugging session. + + \section1 Remote QML Debugging + + To debug Qt Quick applications on Linux devices, \l{Enabling QML Debugging} + {enable QML debugging} and set up program arguments for starting a QML + debugging session. \uicontrol Project > \uicontrol Properties > + \uicontrol Debugging, and then select \uicontrol {GDB Debugger} in + \uicontrol {Debugger to launch}. In + \uicontrol {Additional Debugger Commands}, add the following command: + + \badcode + -qmljsdebugger=port:<port>,host:<IP_address>,block + \endcode +*/ diff --git a/doc/tutorial/AddressBook/adddialog.h b/doc/tutorial/AddressBook/adddialog.h index 68b312d..13d05f2 100644 --- a/doc/tutorial/AddressBook/adddialog.h +++ b/doc/tutorial/AddressBook/adddialog.h @@ -48,6 +48,6 @@ Q_OBJECT public: - AddDialog(QWidget *parent = Q_NULLPTR); + AddDialog(QWidget *parent = nullptr); ~AddDialog(); }; diff --git a/doc/tutorial/QuickAddressBook/QuickAddressBook.sln b/doc/tutorial/QuickAddressBook/QuickAddressBook.sln new file mode 100644 index 0000000..b774435 --- /dev/null +++ b/doc/tutorial/QuickAddressBook/QuickAddressBook.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31919.166 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QuickAddressBook", "QuickAddressBook.vcxproj", "{09DCDDDF-9469-4F20-84EF-7D8481C6FFE1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {09DCDDDF-9469-4F20-84EF-7D8481C6FFE1}.Debug|x64.ActiveCfg = Debug|x64 + {09DCDDDF-9469-4F20-84EF-7D8481C6FFE1}.Debug|x64.Build.0 = Debug|x64 + {09DCDDDF-9469-4F20-84EF-7D8481C6FFE1}.Release|x64.ActiveCfg = Release|x64 + {09DCDDDF-9469-4F20-84EF-7D8481C6FFE1}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7D002559-106F-4ED4-A8D0-DCF37C96FDA8} + EndGlobalSection +EndGlobal diff --git a/doc/tutorial/QuickAddressBook/QuickAddressBook.vcxproj b/doc/tutorial/QuickAddressBook/QuickAddressBook.vcxproj new file mode 100644 index 0000000..005fe3f --- /dev/null +++ b/doc/tutorial/QuickAddressBook/QuickAddressBook.vcxproj @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +--> +<Project ToolsVersion="$(VisualStudioVersion)" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{09DCDDDF-9469-4F20-84EF-7D8481C6FFE1}</ProjectGuid> + <Keyword>QtVS_v304</Keyword> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion Condition="'$(VisualStudioVersion)'=='15.0'">10.0.17763.0</WindowsTargetPlatformVersion> + <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup> + <PlatformToolset Condition="'$(VisualStudioVersion)'=='15.0'">v141</PlatformToolset> + <PlatformToolset Condition="'$(VisualStudioVersion)'=='16.0'">v142</PlatformToolset> + <PlatformToolset Condition="'$(VisualStudioVersion)'=='17.0'">v143</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')"> + <Import Project="$(QtMsBuild)\qt_defaults.props" /> + </ImportGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings"> + <QtInstall>$(DefaultQtVersion)</QtInstall> + <QtModules>quick</QtModules> + <QtBuildConfig>debug</QtBuildConfig> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings"> + <QtInstall>$(DefaultQtVersion)</QtInstall> + <QtModules>quick</QtModules> + <QtBuildConfig>release</QtBuildConfig> + </PropertyGroup> + <Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')"> + <Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." /> + </Target> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(QtMsBuild)\Qt.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(QtMsBuild)\Qt.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="Configuration"> + <ClCompile> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DebugInformationFormat>None</DebugInformationFormat> + <Optimization>MaxSpeed</Optimization> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="main.cpp" /> + <None Include="qmldir" /> + <None Include="QuickAddressBookTypes\AddressBookItem.qml" /> + <None Include="main.qml" /> + <None Include="QuickAddressBookTypes\NewAddressPopup.qml" /> + </ItemGroup> + <ItemGroup> + <QtRcc Include="qml.qrc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> + <Import Project="$(QtMsBuild)\qt.targets" /> + </ImportGroup> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> diff --git a/doc/tutorial/QuickAddressBook/QuickAddressBook.vcxproj.filters b/doc/tutorial/QuickAddressBook/QuickAddressBook.vcxproj.filters new file mode 100644 index 0000000..ae4de39 --- /dev/null +++ b/doc/tutorial/QuickAddressBook/QuickAddressBook.vcxproj.filters @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Translation Files"> + <UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier> + <Extensions>ts</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <None Include="main.qml"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> + <ItemGroup> + <None Include="QuickAddressBookTypes\AddressBookItem.qml"> + <Filter>Source Files</Filter> + </None> + <None Include="qmldir"> + <Filter>Source Files</Filter> + </None> + <None Include="QuickAddressBookTypes\NewAddressPopup.qml"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> + <ItemGroup> + <QtRcc Include="qml.qrc"> + <Filter>Resource Files</Filter> + </QtRcc> + </ItemGroup> +</Project> diff --git a/doc/tutorial/QuickAddressBook/QuickAddressBookTypes/AddressBookItem.qml b/doc/tutorial/QuickAddressBook/QuickAddressBookTypes/AddressBookItem.qml new file mode 100644 index 0000000..7374265 --- /dev/null +++ b/doc/tutorial/QuickAddressBook/QuickAddressBookTypes/AddressBookItem.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.5 +import QtQuick.Layouts 1.12 + +Rectangle { + id: addressBookItem + color: (index % 2) == 0 ? "dimgray" : "lightgray" + anchors.left: parent.left + anchors.right: parent.right + height: itemText.height + 12 + + signal removed() + + RowLayout { + spacing: 12 + anchors.left: parent.left + anchors.leftMargin: spacing + RoundButton { + id: deleteButton + text: "🗙" + font.pointSize: 12 + palette.buttonText: "red" + onClicked: addressBookItem.removed() + } + Text { + id: itemText + font.pointSize: 24 + text: "<b>" + name + "</b><br><i>" + addr + "</i>" + } + } +} diff --git a/doc/tutorial/QuickAddressBook/QuickAddressBookTypes/NewAddressPopup.qml b/doc/tutorial/QuickAddressBook/QuickAddressBookTypes/NewAddressPopup.qml new file mode 100644 index 0000000..6513ec3 --- /dev/null +++ b/doc/tutorial/QuickAddressBook/QuickAddressBookTypes/NewAddressPopup.qml @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.5 +import QtQuick.Layouts 1.12 + +Popup { + id: newAddressPopup + modal: true + focus: true + width: parent.width * 0.9 + x: (parent.width - width) / 2 + y: 35 + onOpened: { + nameField.text = ""; + addrField.text = ""; + nameField.focus = true; + } + + signal addressAdded(string newName, string newAddr) + + ColumnLayout { + anchors.fill: parent + TextField { + id: nameField + placeholderText: qsTr("Name") + font.pointSize: 24 + background: Rectangle { color: "lightgray" } + Layout.preferredWidth: newAddressPopup / 2 + Layout.fillWidth: true + } + TextField { + id: addrField + placeholderText: qsTr("E-Mail Address") + font.pointSize: 24 + background: Rectangle { color: "lightgray" } + Layout.preferredWidth: newAddressPopup / 2 + Layout.fillWidth: true + } + RowLayout { + anchors.left: parent.left; anchors.right: parent.right + Button { + text: "Add" + enabled: nameField.length > 0 && addrField.length > 0 + font.pointSize: 24 + Layout.preferredWidth: newAddressPopup / 2 + Layout.fillWidth: true + onClicked: { + newAddressPopup.addressAdded(nameField.text, addrField.text) + newAddressPopup.close() + } + } + Button { + text: "Cancel" + font.pointSize: 24 + Layout.preferredWidth: newAddressPopup / 2 + Layout.fillWidth: true + onClicked: newAddressPopup.close() + } + } + } +} diff --git a/doc/tutorial/QuickAddressBook/main.cpp b/doc/tutorial/QuickAddressBook/main.cpp new file mode 100644 index 0000000..a02a02f --- /dev/null +++ b/doc/tutorial/QuickAddressBook/main.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QGuiApplication> +#include <QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ +#if defined(Q_OS_WIN) + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif + + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + if (engine.rootObjects().isEmpty()) + return -1; + + return app.exec(); +} diff --git a/doc/tutorial/QuickAddressBook/main.qml b/doc/tutorial/QuickAddressBook/main.qml new file mode 100644 index 0000000..01e6e68 --- /dev/null +++ b/doc/tutorial/QuickAddressBook/main.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.5 +import QtQuick.Layouts 1.12 +import "QuickAddressBookTypes" + +Window { + id: mainWindow + visible: true + width: 480 + height: 640 + color: "darkgray" + title: qsTr("Address Book") + + ListModel { + id: addressList + } + + NewAddressPopup { + id: newAddressPopup + onAddressAdded: addressList.append({name: newName, addr: newAddr}) + } + + ColumnLayout { + id: mainWindowLayout + anchors.left: parent.left; anchors.right: parent.right + spacing: 0 + Button { + id: addButton + anchors.left: parent.left + anchors.right: parent.right + text: "Add..." + font.pointSize: 24 + onClicked: newAddressPopup.open() + } + Repeater { + id: addressListViewer + model: addressList + anchors.left: parent.left + anchors.right: parent.right + AddressBookItem { + id: addressBookItem + onRemoved: addressList.remove(index) + } + } + } +} diff --git a/doc/tutorial/QuickAddressBook/qml.qrc b/doc/tutorial/QuickAddressBook/qml.qrc new file mode 100644 index 0000000..f5a34f3 --- /dev/null +++ b/doc/tutorial/QuickAddressBook/qml.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>qmldir</file> + <file>QuickAddressBookTypes/AddressBookItem.qml</file> + <file>QuickAddressBookTypes/NewAddressPopup.qml</file> + </qresource> +</RCC> diff --git a/doc/tutorial/QuickAddressBook/qmldir b/doc/tutorial/QuickAddressBook/qmldir new file mode 100644 index 0000000..23d4e49 --- /dev/null +++ b/doc/tutorial/QuickAddressBook/qmldir @@ -0,0 +1,2 @@ +AddressBookItem 1.0 AddressBookItem.qml +NewAddressPopup 1.0 NewAddressPopup.qml diff --git a/references.props b/references.props index 0f4a231..b38e5f9 100644 --- a/references.props +++ b/references.props @@ -2,124 +2,73 @@ <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////// - // References versions + // Package References names/version // --> <!-- // Common --> <PropertyGroup> - <Version_Microsoft_Bcl_AsyncInterfaces - >5.0.0</Version_Microsoft_Bcl_AsyncInterfaces> - <Version_Stub_System_Data_SQLite_Core_NetFramework - >1.0.115</Version_Stub_System_Data_SQLite_Core_NetFramework> - <Version_System_Collections_Immutable - >5.0.0</Version_System_Collections_Immutable> - <Version_System_ComponentModel_Composition - >5.0.0</Version_System_ComponentModel_Composition> - <Version_Newtonsoft_Json - >13.0.1</Version_Newtonsoft_Json> - <Version_MSTest_TestAdapter - >2.2.8</Version_MSTest_TestAdapter> - <Version_MSTest_TestFramework - >2.2.8</Version_MSTest_TestFramework> + <Name_Microsoft_Build>Microsoft.Build</Name_Microsoft_Build> + <Name_Microsoft_Build_Tasks_Core>Microsoft.Build.Tasks.Core</Name_Microsoft_Build_Tasks_Core> + <Name_Microsoft_VSSDK_BuildTools>Microsoft.VSSDK.BuildTools</Name_Microsoft_VSSDK_BuildTools> + <Name_Microsoft_VisualStudio_SDK>Microsoft.VisualStudio.SDK</Name_Microsoft_VisualStudio_SDK> + <Name_Microsoft_Bcl_AsyncInterfaces>Microsoft.Bcl.AsyncInterfaces</Name_Microsoft_Bcl_AsyncInterfaces> + <Name_Microsoft_VisualStudio_Validation>Microsoft.VisualStudio.Validation</Name_Microsoft_VisualStudio_Validation> + <Name_Microsoft_VisualStudio_RpcContracts>Microsoft.VisualStudio.RpcContracts</Name_Microsoft_VisualStudio_RpcContracts> + <Name_Microsoft_VisualStudio_ProjectSystem>Microsoft.VisualStudio.ProjectSystem</Name_Microsoft_VisualStudio_ProjectSystem> + <Name_Microsoft_VisualStudio_VCProjectEngine>Microsoft.VisualStudio.VCProjectEngine</Name_Microsoft_VisualStudio_VCProjectEngine> + <Name_Microsoft_VisualStudio_Shell_15>Microsoft.VisualStudio.Shell.15.0</Name_Microsoft_VisualStudio_Shell_15> + <Name_Microsoft_VisualStudio_Shell_Framework>Microsoft.VisualStudio.Shell.Framework</Name_Microsoft_VisualStudio_Shell_Framework> + <Name_Microsoft_VisualStudio_TemplateWizardInterface>Microsoft.VisualStudio.TemplateWizardInterface</Name_Microsoft_VisualStudio_TemplateWizardInterface> + + <Name_MSTest_TestAdapter>MSTest.TestAdapter</Name_MSTest_TestAdapter> + <Version_MSTest_TestAdapter>2.2.8</Version_MSTest_TestAdapter> + + <Name_MSTest_TestFramework>MSTest.TestFramework</Name_MSTest_TestFramework> + <Version_MSTest_TestFramework>2.2.8</Version_MSTest_TestFramework> + + <Name_Newtonsoft_Json>Newtonsoft.Json</Name_Newtonsoft_Json> + <Version_Newtonsoft_Json>13.0.1</Version_Newtonsoft_Json> + + <Name_Stub_System_Data_SQLite_Core_NetFramework>Stub.System.Data.SQLite.Core.NetFramework</Name_Stub_System_Data_SQLite_Core_NetFramework> + <Version_Stub_System_Data_SQLite_Core_NetFramework>1.0.115.5</Version_Stub_System_Data_SQLite_Core_NetFramework> </PropertyGroup> - <PropertyGroup> - <Name_DummyPackage - >Stub.System.Data.SQLite.Core.NetFramework</Name_DummyPackage> - <Version_DummyPackage - >$(Version_Stub_System_Data_SQLite_Core_NetFramework)</Version_DummyPackage> - </PropertyGroup> + <!-- // Visual Studio 2022 --> <PropertyGroup Condition="'$(VisualStudioVersion)'=='17.0'"> - <Version_Microsoft_Build - >16.11.0</Version_Microsoft_Build> - <Version_Microsoft_Build_Framework - >16.11.0</Version_Microsoft_Build_Framework> - <Version_Microsoft_Build_Tasks_Core - >16.11.0</Version_Microsoft_Build_Tasks_Core> - <Version_Microsoft_VisualStudio_SDK - >17.0.0-previews-4-31709-430</Version_Microsoft_VisualStudio_SDK> - <Version_Microsoft_VSSDK_BuildTools - >17.0.5232</Version_Microsoft_VSSDK_BuildTools> - <Version_Microsoft_VisualStudio_ProjectSystem - >17.0.667-pre</Version_Microsoft_VisualStudio_ProjectSystem> - <Version_Microsoft_VisualStudio_Validation - >17.0.34</Version_Microsoft_VisualStudio_Validation> - <Version_Microsoft_VisualStudio_Shell_Framework - >17.0.0-previews-5-31722-452</Version_Microsoft_VisualStudio_Shell_Framework> - <Name_Microsoft_VisualStudio_VCProjectEngine - >Microsoft.VisualStudio.VCProjectEngine</Name_Microsoft_VisualStudio_VCProjectEngine> - <Version_Microsoft_VisualStudio_VCProjectEngine - >17.0.0-previews-4-31709-430</Version_Microsoft_VisualStudio_VCProjectEngine> - <Name_Microsoft_VisualStudio_TemplateWizardInterface - >Microsoft.VisualStudio.TemplateWizardInterface</Name_Microsoft_VisualStudio_TemplateWizardInterface> - <Version_Microsoft_VisualStudio_TemplateWizardInterface - >17.0.0-previews-1-31410-258</Version_Microsoft_VisualStudio_TemplateWizardInterface> - <Name_Microsoft_VisualStudio_Threading - >$(Name_DummyPackage)</Name_Microsoft_VisualStudio_Threading> - <Version_Microsoft_VisualStudio_Threading - >$(Version_DummyPackage)</Version_Microsoft_VisualStudio_Threading> - <Version_System_Collections_Immutable - >5.0.0</Version_System_Collections_Immutable> + <Version_Microsoft_Build>17.0.0</Version_Microsoft_Build> + <Version_Microsoft_Build_Tasks_Core>17.0.0</Version_Microsoft_Build_Tasks_Core> + <Version_Microsoft_VSSDK_BuildTools>17.0.5234</Version_Microsoft_VSSDK_BuildTools> + <Version_Microsoft_Bcl_AsyncInterfaces>6.0.0</Version_Microsoft_Bcl_AsyncInterfaces> + <Version_Microsoft_VisualStudio_SDK>17.0.32112.339</Version_Microsoft_VisualStudio_SDK> + <Version_Microsoft_VisualStudio_ProjectSystem>17.0.1313-pre</Version_Microsoft_VisualStudio_ProjectSystem> + <Version_Microsoft_VisualStudio_TemplateWizardInterface>17.0.31902.203</Version_Microsoft_VisualStudio_TemplateWizardInterface> + <Version_Microsoft_VisualStudio_Shell_15>17.0.32112.339</Version_Microsoft_VisualStudio_Shell_15> </PropertyGroup> + <!-- // Visual Studio 2019 --> <PropertyGroup Condition="'$(VisualStudioVersion)'=='16.0'"> - <Version_Microsoft_Build - >16.8.0</Version_Microsoft_Build> - <Version_Microsoft_Build_Framework - >16.8.0</Version_Microsoft_Build_Framework> - <Version_Microsoft_Build_Tasks_Core - >16.8.0</Version_Microsoft_Build_Tasks_Core> - <Version_Microsoft_VisualStudio_SDK - >16.0.206</Version_Microsoft_VisualStudio_SDK> - <Version_Microsoft_VSSDK_BuildTools - >16.4.1060</Version_Microsoft_VSSDK_BuildTools> - <Version_Microsoft_VisualStudio_ProjectSystem - >16.2.133-pre</Version_Microsoft_VisualStudio_ProjectSystem> - <Version_Microsoft_VisualStudio_Validation - >16.8.33</Version_Microsoft_VisualStudio_Validation> - <Version_Microsoft_VisualStudio_Shell_Framework - >16.4.29519.181</Version_Microsoft_VisualStudio_Shell_Framework> - <Name_Microsoft_VisualStudio_VCProjectEngine - >Microsoft.VisualStudio.VCProjectEngine</Name_Microsoft_VisualStudio_VCProjectEngine> - <Version_Microsoft_VisualStudio_VCProjectEngine - >16.7.30328.74</Version_Microsoft_VisualStudio_VCProjectEngine> - <Name_Microsoft_VisualStudio_TemplateWizardInterface - >$(Name_DummyPackage)</Name_Microsoft_VisualStudio_TemplateWizardInterface> - <Version_Microsoft_VisualStudio_TemplateWizardInterface - >$(Version_DummyPackage)</Version_Microsoft_VisualStudio_TemplateWizardInterface> - <Name_Microsoft_VisualStudio_Threading - >$(Name_DummyPackage)</Name_Microsoft_VisualStudio_Threading> - <Version_Microsoft_VisualStudio_Threading - >$(Version_DummyPackage)</Version_Microsoft_VisualStudio_Threading> - <Version_System_Collections_Immutable - >1.5.0</Version_System_Collections_Immutable> + <Version_Microsoft_Build>16.11.0</Version_Microsoft_Build> + <Version_Microsoft_Build_Tasks_Core>16.11.0</Version_Microsoft_Build_Tasks_Core> + <Version_Microsoft_VSSDK_BuildTools>16.11.35</Version_Microsoft_VSSDK_BuildTools> + <Version_Microsoft_Bcl_AsyncInterfaces>5.0.0</Version_Microsoft_Bcl_AsyncInterfaces> + <Version_Microsoft_VisualStudio_SDK>16.10.31321.278</Version_Microsoft_VisualStudio_SDK> + <Version_Microsoft_VisualStudio_Validation>16.10.35</Version_Microsoft_VisualStudio_Validation> + <Version_Microsoft_VisualStudio_RpcContracts>17.0.51</Version_Microsoft_VisualStudio_RpcContracts> + <Version_Microsoft_VisualStudio_ProjectSystem>16.2.133-pre</Version_Microsoft_VisualStudio_ProjectSystem> + <Version_Microsoft_VisualStudio_VCProjectEngine>16.10.31320.204</Version_Microsoft_VisualStudio_VCProjectEngine> + <Version_Microsoft_VisualStudio_TemplateWizardInterface>16.10.31320.204</Version_Microsoft_VisualStudio_TemplateWizardInterface> + <Version_Microsoft_VisualStudio_Shell_15>16.10.31321.278</Version_Microsoft_VisualStudio_Shell_15> </PropertyGroup> + <!-- // Visual Studio 2017 --> <PropertyGroup Condition="'$(VisualStudioVersion)'=='15.0'"> - <Version_Microsoft_Build - >15.9.20</Version_Microsoft_Build> - <Version_Microsoft_Build_Framework - >15.9.20</Version_Microsoft_Build_Framework> - <Version_Microsoft_Build_Tasks_Core - >15.9.20</Version_Microsoft_Build_Tasks_Core> - <Version_Microsoft_VisualStudio_SDK - >15.0.1</Version_Microsoft_VisualStudio_SDK> - <Version_Microsoft_VSSDK_BuildTools - >15.9.3039</Version_Microsoft_VSSDK_BuildTools> - <Version_Microsoft_VisualStudio_ProjectSystem - >15.8.243</Version_Microsoft_VisualStudio_ProjectSystem> - <Version_Microsoft_VisualStudio_Validation - >15.5.31</Version_Microsoft_VisualStudio_Validation> - <Version_Microsoft_VisualStudio_Shell_Framework - >15.9.28307</Version_Microsoft_VisualStudio_Shell_Framework> - <Name_Microsoft_VisualStudio_TemplateWizardInterface - >$(Name_DummyPackage)</Name_Microsoft_VisualStudio_TemplateWizardInterface> - <Version_Microsoft_VisualStudio_TemplateWizardInterface - >$(Version_DummyPackage)</Version_Microsoft_VisualStudio_TemplateWizardInterface> - <Name_Microsoft_VisualStudio_Threading - >Microsoft.VisualStudio.Threading</Name_Microsoft_VisualStudio_Threading> - <Version_Microsoft_VisualStudio_Threading - >15.8.209</Version_Microsoft_VisualStudio_Threading> - <Version_System_Collections_Immutable - >1.5.0</Version_System_Collections_Immutable> + <Version_Microsoft_Build>15.9.20</Version_Microsoft_Build> + <Version_Microsoft_VisualStudio_SDK>15.0.1</Version_Microsoft_VisualStudio_SDK> + <Version_Microsoft_Build_Tasks_Core>15.9.20</Version_Microsoft_Build_Tasks_Core> + <Version_Microsoft_VSSDK_BuildTools>15.9.3039</Version_Microsoft_VSSDK_BuildTools> + <Version_Microsoft_Bcl_AsyncInterfaces>5.0.0</Version_Microsoft_Bcl_AsyncInterfaces> + <Version_Microsoft_VisualStudio_ProjectSystem>15.8.243</Version_Microsoft_VisualStudio_ProjectSystem> + <Version_Microsoft_VisualStudio_Shell_Framework>15.9.28307</Version_Microsoft_VisualStudio_Shell_Framework> + <Version_Microsoft_VisualStudio_Shell_15>15.9.28307</Version_Microsoft_VisualStudio_Shell_15> </PropertyGroup> + </Project> diff --git a/version.targets b/version.targets index d6516b3..43fc5f6 100644 --- a/version.targets +++ b/version.targets @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup Condition="'$(QtVSToolsVersion)' == ''"> - <QtVSToolsVersion>2.8.1</QtVSToolsVersion> + <QtVSToolsVersion>2.9.0</QtVSToolsVersion> </PropertyGroup> </Project> diff --git a/vsconfig/2017.vsconfig b/vsconfig/2017.vsconfig new file mode 100644 index 0000000..6142b6e --- /dev/null +++ b/vsconfig/2017.vsconfig @@ -0,0 +1,48 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Component.CoreEditor", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.VisualStudio.Component.Roslyn.Compiler", + "Microsoft.Component.MSBuild", + "Microsoft.VisualStudio.Component.Static.Analysis.Tools", + "Microsoft.VisualStudio.Component.Roslyn.LanguageServices", + "Microsoft.VisualStudio.Component.PortableLibrary", + "Microsoft.Net.Component.4.6.1.SDK", + "Microsoft.Net.Component.4.6.1.TargetingPack", + "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites", + "Microsoft.Component.ClickOnce", + "Microsoft.VisualStudio.Component.SQL.CLR", + "Microsoft.VisualStudio.Component.VisualStudioData", + "Microsoft.VisualStudio.Component.TextTemplating", + "Microsoft.VisualStudio.Component.ManagedDesktop.Core", + "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites", + "Microsoft.Net.Component.4.TargetingPack", + "Microsoft.Net.Component.4.5.TargetingPack", + "Microsoft.Net.Component.4.5.1.TargetingPack", + "Microsoft.Net.Component.4.5.2.TargetingPack", + "Microsoft.Net.Component.4.6.TargetingPack", + "Microsoft.Net.ComponentGroup.TargetingPacks.Common", + "Microsoft.VisualStudio.Component.NuGet", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions", + "Microsoft.VisualStudio.Workload.ManagedDesktop", + "Microsoft.VisualStudio.Component.VC.CoreIde", + "Microsoft.VisualStudio.Component.VC.Redist.14.Latest", + "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.Graphics.Win81", + "Microsoft.VisualStudio.Component.Graphics.Tools", + "Microsoft.VisualStudio.Component.VC.DiagnosticTools", + "Microsoft.VisualStudio.Component.Windows10SDK.17763", + "Microsoft.VisualStudio.Component.VC.CMake.Project", + "Microsoft.VisualStudio.Component.VC.ATL", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.VisualStudio.Component.Windows10SDK", + "Microsoft.VisualStudio.Component.VSSDK", + "Microsoft.VisualStudio.ComponentGroup.VisualStudioExtension.Prerequisites", + "Microsoft.VisualStudio.Workload.VisualStudioExtension", + "Component.MDD.Linux", + "Component.Linux.CMake", + "Microsoft.VisualStudio.Workload.NativeCrossPlat" + ] +} \ No newline at end of file diff --git a/vsconfig/2019.vsconfig b/vsconfig/2019.vsconfig new file mode 100644 index 0000000..2bdc9aa --- /dev/null +++ b/vsconfig/2019.vsconfig @@ -0,0 +1,44 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Component.CoreEditor", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.NetCore.Component.Runtime.5.0", + "Microsoft.NetCore.Component.Runtime.3.1", + "Microsoft.NetCore.Component.SDK", + "Microsoft.VisualStudio.Component.NuGet", + "Microsoft.VisualStudio.Component.Roslyn.Compiler", + "Microsoft.VisualStudio.Component.Roslyn.LanguageServices", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions", + "Microsoft.Net.Component.4.8.SDK", + "Microsoft.Net.Component.4.7.2.TargetingPack", + "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites", + "Microsoft.VisualStudio.Component.TypeScript.4.3", + "Microsoft.VisualStudio.Component.JavaScript.TypeScript", + "Microsoft.Component.MSBuild", + "Microsoft.VisualStudio.Component.TextTemplating", + "Microsoft.Net.Component.4.6.TargetingPack", + "Microsoft.VisualStudio.Component.DiagnosticTools", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Component.Microsoft.VisualStudio.LiveShare", + "Microsoft.VisualStudio.Component.IntelliCode", + "Microsoft.VisualStudio.Component.VC.CoreIde", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.Graphics.Tools", + "Microsoft.VisualStudio.Component.VC.DiagnosticTools", + "Microsoft.VisualStudio.Component.Windows10SDK.19041", + "Microsoft.VisualStudio.Component.VC.Redist.14.Latest", + "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake", + "Microsoft.VisualStudio.Component.VC.CMake.Project", + "Microsoft.VisualStudio.Component.VC.ATL", + "Microsoft.VisualStudio.Component.VC.ASAN", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.VisualStudio.Component.VSSDK", + "Microsoft.VisualStudio.ComponentGroup.VisualStudioExtension.Prerequisites", + "Microsoft.VisualStudio.Workload.VisualStudioExtension", + "Component.MDD.Linux", + "Component.Linux.CMake", + "Microsoft.VisualStudio.Workload.NativeCrossPlat" + ] +} \ No newline at end of file diff --git a/vsconfig/2022.vsconfig b/vsconfig/2022.vsconfig new file mode 100644 index 0000000..ed6e494 --- /dev/null +++ b/vsconfig/2022.vsconfig @@ -0,0 +1,42 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Component.CoreEditor", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.Net.Component.4.8.SDK", + "Microsoft.Net.Component.4.7.2.TargetingPack", + "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions", + "Microsoft.VisualStudio.Component.Roslyn.Compiler", + "Microsoft.Component.MSBuild", + "Microsoft.VisualStudio.Component.Roslyn.LanguageServices", + "Microsoft.VisualStudio.Component.TextTemplating", + "Microsoft.VisualStudio.Component.NuGet", + "Microsoft.NetCore.Component.Runtime.6.0", + "Microsoft.NetCore.Component.SDK", + "Microsoft.VisualStudio.Component.DiagnosticTools", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Microsoft.VisualStudio.Component.IntelliCode", + "Microsoft.VisualStudio.Component.VC.CoreIde", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.Graphics.Tools", + "Microsoft.VisualStudio.Component.VC.DiagnosticTools", + "Microsoft.VisualStudio.Component.Windows10SDK.19041", + "Microsoft.VisualStudio.Component.VC.Redist.14.Latest", + "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake", + "Microsoft.VisualStudio.Component.VC.CMake.Project", + "Microsoft.VisualStudio.Component.VC.ATL", + "Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest", + "Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest", + "Microsoft.VisualStudio.Component.VC.ASAN", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.Net.Component.4.6.TargetingPack", + "Microsoft.VisualStudio.Component.VSSDK", + "Microsoft.VisualStudio.ComponentGroup.VisualStudioExtension.Prerequisites", + "Microsoft.VisualStudio.Workload.VisualStudioExtension", + "Component.MDD.Linux", + "Component.Linux.CMake", + "Microsoft.VisualStudio.Workload.NativeCrossPlat" + ] +} \ No newline at end of file diff --git a/vstools.bat b/vstools.bat index ad05fd5..656576f 100644 --- a/vstools.bat +++ b/vstools.bat @@ -12,7 +12,9 @@ SET VSWHERE=%VSWHERE_EXE% SET VSWHERE=%VSWHERE:(=^(% SET VSWHERE=%VSWHERE:)=^)% -SET QUERY=-latest -prerelease +SET QUERY_LATEST=-latest -prerelease +SET QUERY_ALL=-prerelease +SET QUERY=%QUERY_LATEST% SET VSWHERE_MAJOR=2 SET VSWHERE_MINOR=7 SET VSWHERE_PATCH=1 @@ -37,6 +39,7 @@ SET DO_INSTALL=%FALSE% SET TRANSFORM_INCREMENTAL=true SET START_VS=%FALSE% +SET LIST_VERSIONS=%FALSE% SET PLATFORM_VS2017="Any CPU" SET PLATFORM_VS2019="Any CPU" @@ -101,6 +104,10 @@ SET VS_LATEST=%VS2017% SET VS_VERSIONS_DEFAULT=%FALSE% SET FLAG_VS2017= + ) ELSE IF "%1"=="-list" ( + SET LIST_VERSIONS=%TRUE% + ) ELSE IF "%1"=="-all" ( + SET QUERY=%QUERY_ALL% ) ELSE IF "%1"=="-help" ( GOTO :usage ) ELSE ( @@ -203,15 +210,28 @@ IF %VERBOSE% ECHO ## catalog_productLineVersion: %%e IF %VERBOSE% ECHO ## %VSWHERE% -path "%%p" -property displayName - FOR /F %ALL% %%n IN (`"%VSWHERE% -path "%%p" -property displayName"`) DO ( - IF %VERBOSE% ECHO ## displayName: %%n + FOR /F %ALL% %%u IN (`"%VSWHERE% -path "%%p" -property displayName"`) DO ( + IF %VERBOSE% ECHO ## displayName: %%u + + IF %VERBOSE% ECHO ## %VSWHERE% -path "%%p" -property isPrerelease + FOR /F %ALL% %%b IN (`"%VSWHERE% -path "%%p" -property isPrerelease"`) DO ( + IF %VERBOSE% ECHO ## isPrerelease: %%b + + FOR /F %ALL% %%n IN (`"(ECHO %%b | FINDSTR /C:1 > NUL) && (ECHO %%u PREVIEW) || ECHO %%u"`) DO ( + IF %VERBOSE% ECHO ## friendlyName: %%n IF %VERBOSE% ECHO ## %VSWHERE% -path "%%p" -property installationVersion FOR /F %ALL% %%i IN (`"%VSWHERE% -path "%%p" -property installationVersion"`) DO ( IF %VERBOSE% ECHO ## installationVersion: %%i FOR /F %ALL% %%f IN (`CMD /C "ECHO %%PLATFORM_VS%%e%%"`) DO ( - IF %VERBOSE% ECHO ## platform: %%f + IF %VERBOSE% ECHO ## platform: %%f + + IF %LIST_VERSIONS% ( + IF %VERBOSE% ECHO ## listVersion + ECHO %%n ^(%%i^) + ECHO ^[%%p^] + ) ELSE ( IF "%%e"=="2022" ( IF %VERBOSE% ECHO ## CALL "%%p\VC\Auxiliary\Build\vcvars64.bat" @@ -368,9 +388,9 @@ EXIT /B 0 ) - ECHO. ) - )))) + ECHO. + ))))))) ENDLOCAL ) @@ -397,6 +417,8 @@ ECHO -init .......... Initialize vstools solution for the specified version of VS ECHO If multiple versions are specified, the last one is selected ECHO -startvs ....... Open vstools solution in selected VS version +ECHO -list .......... Print list of Visual Studio installations +ECHO -help .......... Print tool usage instructions ECHO. ECHO If no operation is specified, -build is assumed by default. ECHO. @@ -409,6 +431,9 @@ ECHO -install .................... Install extension to selected VS version(s) ECHO Only valid with -build or -rebuild ECHO -startvs .................... Open vstools solution in selected VS version +ECHO If multiple versions are specified, the last one is selected +ECHO -all ........................ Include all VS installations +ECHO By default, the latest installation is selected ECHO -verbose .................... Print more detailed log information ECHO -bl ......................... Generate MSBuild binary log ECHO Only valid with -build or -rebuild diff --git a/vstools.sln b/vstools.sln index 8bbcdd4..b69cbcd 100644 --- a/vstools.sln +++ b/vstools.sln @@ -35,13 +35,19 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QtTemplate.Item.QMLDir", "Templates\qmldir\QtTemplate.Item.QMLDir.csproj", "{7AF6C34B-65D2-4010-92F6-420E59DDE9BF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QtTemplate.Item.QtClass", "Templates\qtclass\QtTemplate.Item.QtClass.csproj", "{4981AAE8-9AC7-4758-87EA-FB2397D6C404}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QtTemplate.Project.Quick", "Templates\quick\QtTemplate.Project.Quick.csproj", "{4833E4C7-FFFF-4DA5-A7A5-36C6C3840F16}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QtTemplate.Item.Resource", "Templates\resource\QtTemplate.Item.Resource.csproj", "{BDA1CD69-624B-4D9D-9B88-ACBEB14AC471}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QtTemplate.Project.Server", "Templates\server\QtTemplate.Project.Server.csproj", "{8AE9D385-A379-4F5F-A703-3DF643DA6742}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QtTemplate.Item.Translation", "Templates\translation\QtTemplate.Item.Translation.csproj", "{202F4A6D-77CD-4992-AA53-01B585463287}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QtTemplate.Item.Widget", "Templates\widget\QtTemplate.Item.Widget.csproj", "{40ADFD6A-64EA-4C77-9D4B-3A91D6AB76B4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QtTemplate.Item.WidgetsClass", "Templates\widgetsclass\QtTemplate.Item.WidgetsClass.csproj", "{020422DA-33AB-4495-A439-7DAC2690795C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Item", "Item", "{A7918293-56E9-465A-AE1C-0724576ADD66}" EndProject @@ -92,6 +98,10 @@ EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test_QtMsBuild.Tasks", "Tests\Test_QtMsBuild.Tasks\Test_QtMsBuild.Tasks.csproj", "{E809DDE3-AE76-4F7A-8DC5-775AC4900138}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test_QtVsTools.Core", "Tests\Test_QtVsTools.Core\Test_QtVsTools.Core.csproj", "{4B8FC08C-4901-45D4-BC00-C0C461292FF2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test_QtVsTools.Package", "tests\Test_QtVsTools.Package\Test_QtVsTools.Package.csproj", "{AFD33401-2F15-4E72-AB35-42C3EE12E897}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -376,6 +386,24 @@ {7AF6C34B-65D2-4010-92F6-420E59DDE9BF}.Tests|x64.Build.0 = Release|Any CPU {7AF6C34B-65D2-4010-92F6-420E59DDE9BF}.Tests|x86.ActiveCfg = Release|Any CPU {7AF6C34B-65D2-4010-92F6-420E59DDE9BF}.Tests|x86.Build.0 = Release|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Debug|x64.ActiveCfg = Debug|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Debug|x64.Build.0 = Debug|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Debug|x86.ActiveCfg = Debug|x86 + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Debug|x86.Build.0 = Debug|x86 + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Release|Any CPU.Build.0 = Release|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Release|x64.ActiveCfg = Release|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Release|x64.Build.0 = Release|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Release|x86.ActiveCfg = Release|x86 + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Release|x86.Build.0 = Release|x86 + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Tests|Any CPU.ActiveCfg = Debug|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Tests|Any CPU.Build.0 = Debug|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Tests|x64.ActiveCfg = Debug|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Tests|x64.Build.0 = Debug|Any CPU + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Tests|x86.ActiveCfg = Debug|x86 + {4981AAE8-9AC7-4758-87EA-FB2397D6C404}.Tests|x86.Build.0 = Debug|x86 {4833E4C7-FFFF-4DA5-A7A5-36C6C3840F16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4833E4C7-FFFF-4DA5-A7A5-36C6C3840F16}.Debug|Any CPU.Build.0 = Debug|Any CPU {4833E4C7-FFFF-4DA5-A7A5-36C6C3840F16}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -448,6 +476,24 @@ {40ADFD6A-64EA-4C77-9D4B-3A91D6AB76B4}.Tests|x64.Build.0 = Release|Any CPU {40ADFD6A-64EA-4C77-9D4B-3A91D6AB76B4}.Tests|x86.ActiveCfg = Release|Any CPU {40ADFD6A-64EA-4C77-9D4B-3A91D6AB76B4}.Tests|x86.Build.0 = Release|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Debug|x64.ActiveCfg = Debug|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Debug|x64.Build.0 = Debug|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Debug|x86.ActiveCfg = Debug|x86 + {020422DA-33AB-4495-A439-7DAC2690795C}.Debug|x86.Build.0 = Debug|x86 + {020422DA-33AB-4495-A439-7DAC2690795C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Release|Any CPU.Build.0 = Release|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Release|x64.ActiveCfg = Release|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Release|x64.Build.0 = Release|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Release|x86.ActiveCfg = Release|x86 + {020422DA-33AB-4495-A439-7DAC2690795C}.Release|x86.Build.0 = Release|x86 + {020422DA-33AB-4495-A439-7DAC2690795C}.Tests|Any CPU.ActiveCfg = Debug|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Tests|Any CPU.Build.0 = Debug|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Tests|x64.ActiveCfg = Debug|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Tests|x64.Build.0 = Debug|Any CPU + {020422DA-33AB-4495-A439-7DAC2690795C}.Tests|x86.ActiveCfg = Debug|x86 + {020422DA-33AB-4495-A439-7DAC2690795C}.Tests|x86.Build.0 = Debug|x86 {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|Any CPU.ActiveCfg = Debug|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|Any CPU.Build.0 = Debug|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.ActiveCfg = Debug|x64 @@ -571,6 +617,54 @@ {E809DDE3-AE76-4F7A-8DC5-775AC4900138}.Tests|x64.Build.0 = Release|Any CPU {E809DDE3-AE76-4F7A-8DC5-775AC4900138}.Tests|x86.ActiveCfg = Release|Any CPU {E809DDE3-AE76-4F7A-8DC5-775AC4900138}.Tests|x86.Build.0 = Release|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Debug|Any CPU.Build.0 = Debug|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Debug|x64.ActiveCfg = Debug|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Debug|x64.Build.0 = Debug|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Debug|x86.ActiveCfg = Debug|x86 + {202F4A6D-77CD-4992-AA53-01B585463287}.Debug|x86.Build.0 = Debug|x86 + {202F4A6D-77CD-4992-AA53-01B585463287}.Release|Any CPU.ActiveCfg = Release|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Release|Any CPU.Build.0 = Release|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Release|x64.ActiveCfg = Release|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Release|x64.Build.0 = Release|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Release|x86.ActiveCfg = Release|x86 + {202F4A6D-77CD-4992-AA53-01B585463287}.Release|x86.Build.0 = Release|x86 + {202F4A6D-77CD-4992-AA53-01B585463287}.Tests|Any CPU.ActiveCfg = Debug|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Tests|Any CPU.Build.0 = Debug|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Tests|x64.ActiveCfg = Debug|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Tests|x64.Build.0 = Debug|Any CPU + {202F4A6D-77CD-4992-AA53-01B585463287}.Tests|x86.ActiveCfg = Debug|x86 + {202F4A6D-77CD-4992-AA53-01B585463287}.Tests|x86.Build.0 = Debug|x86 + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Debug|x64.ActiveCfg = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Debug|x64.Build.0 = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Debug|x86.ActiveCfg = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Debug|x86.Build.0 = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Release|x64.ActiveCfg = Release|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Release|x86.ActiveCfg = Release|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Tests|Any CPU.ActiveCfg = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Tests|Any CPU.Build.0 = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Tests|x64.ActiveCfg = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Tests|x64.Build.0 = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Tests|x86.ActiveCfg = Debug|Any CPU + {4B8FC08C-4901-45D4-BC00-C0C461292FF2}.Tests|x86.Build.0 = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Debug|x64.ActiveCfg = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Debug|x64.Build.0 = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Debug|x86.ActiveCfg = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Debug|x86.Build.0 = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Release|x64.ActiveCfg = Release|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Release|x86.ActiveCfg = Release|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Tests|Any CPU.ActiveCfg = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Tests|Any CPU.Build.0 = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Tests|x64.ActiveCfg = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Tests|x64.Build.0 = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Tests|x86.ActiveCfg = Debug|Any CPU + {AFD33401-2F15-4E72-AB35-42C3EE12E897}.Tests|x86.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -586,10 +680,12 @@ {20055427-1352-44FB-8442-BF7F15F9C59E} = {A7918293-56E9-465A-AE1C-0724576ADD66} {DC1AE91B-45CE-4C5B-8F77-CDB58566038F} = {A7918293-56E9-465A-AE1C-0724576ADD66} {7AF6C34B-65D2-4010-92F6-420E59DDE9BF} = {A7918293-56E9-465A-AE1C-0724576ADD66} + {4981AAE8-9AC7-4758-87EA-FB2397D6C404} = {A7918293-56E9-465A-AE1C-0724576ADD66} {4833E4C7-FFFF-4DA5-A7A5-36C6C3840F16} = {DD307619-BF80-4E5D-AE54-196057187702} {BDA1CD69-624B-4D9D-9B88-ACBEB14AC471} = {A7918293-56E9-465A-AE1C-0724576ADD66} {8AE9D385-A379-4F5F-A703-3DF643DA6742} = {DD307619-BF80-4E5D-AE54-196057187702} {40ADFD6A-64EA-4C77-9D4B-3A91D6AB76B4} = {A7918293-56E9-465A-AE1C-0724576ADD66} + {020422DA-33AB-4495-A439-7DAC2690795C} = {A7918293-56E9-465A-AE1C-0724576ADD66} {A7918293-56E9-465A-AE1C-0724576ADD66} = {9D9290B2-9E87-46EA-84EA-02836F699BB8} {DD307619-BF80-4E5D-AE54-196057187702} = {9D9290B2-9E87-46EA-84EA-02836F699BB8} {B12702AD-ABFB-343A-A199-8E24837244A3} = {9B109DDA-0521-46AD-B087-B7CBCB33FEE5} @@ -602,6 +698,9 @@ {A5320606-37B8-4F15-97E2-16314109CAF9} = {D6FB29A4-8921-46F5-B170-B15538AB4D69} {12857847-9877-466C-B056-DD286A219093} = {D6FB29A4-8921-46F5-B170-B15538AB4D69} {E809DDE3-AE76-4F7A-8DC5-775AC4900138} = {D6FB29A4-8921-46F5-B170-B15538AB4D69} + {202F4A6D-77CD-4992-AA53-01B585463287} = {A7918293-56E9-465A-AE1C-0724576ADD66} + {4B8FC08C-4901-45D4-BC00-C0C461292FF2} = {D6FB29A4-8921-46F5-B170-B15538AB4D69} + {AFD33401-2F15-4E72-AB35-42C3EE12E897} = {D6FB29A4-8921-46F5-B170-B15538AB4D69} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {17FF4AFE-273C-47CD-8D84-F0D023B10BE5} diff --git "a/\320\241\320\261\320\276\321\200\320\272\320\260.md" "b/\320\241\320\261\320\276\321\200\320\272\320\260.md" index dd25307..b3d918f 100644 --- "a/\320\241\320\261\320\276\321\200\320\272\320\260.md" +++ "b/\320\241\320\261\320\276\321\200\320\272\320\260.md" @@ -63,7 +63,7 @@ `Сборка под VS2022:` Обязательно наличие VS 2022 -Установить переменную среды QTBUILD_STATIC_VS2022 (Пример QTBUILD_STATIC_VS2022=C:\build\qt_5.12.9_msvc2022_x64) для VS 2012 только QT x64 +Установить переменную среды QTBUILD_STATIC_VS2022 (Пример QTBUILD_STATIC_VS2022=C:\build\qt_5.12.9_msvc2022_x64) для VS 2022 только QT x64 В директории через cmd вызвать vstools -vs2022 -init -config Release или Debug -rebuild -deploy Path -startvs -- Gitblit v1.9.1