summaryrefslogtreecommitdiffstats
path: root/Source/QtDialog
diff options
context:
space:
mode:
Diffstat (limited to 'Source/QtDialog')
-rw-r--r--Source/QtDialog/AddCacheEntry.cxx99
-rw-r--r--Source/QtDialog/AddCacheEntry.h35
-rw-r--r--Source/QtDialog/AddCacheEntry.ui97
-rw-r--r--Source/QtDialog/CMake.desktop12
-rw-r--r--Source/QtDialog/CMakeLists.txt232
-rw-r--r--Source/QtDialog/CMakeSetup.cxx253
-rw-r--r--Source/QtDialog/CMakeSetup.icnsbin0 -> 138205 bytes
-rw-r--r--Source/QtDialog/CMakeSetup.icobin0 -> 24542 bytes
-rw-r--r--Source/QtDialog/CMakeSetup.qrc8
-rw-r--r--Source/QtDialog/CMakeSetup.rc1
-rw-r--r--Source/QtDialog/CMakeSetup128.pngbin0 -> 13269 bytes
-rw-r--r--Source/QtDialog/CMakeSetup32.pngbin0 -> 358 bytes
-rw-r--r--Source/QtDialog/CMakeSetup64.pngbin0 -> 7213 bytes
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx1330
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h140
-rw-r--r--Source/QtDialog/CMakeSetupDialog.ui320
-rw-r--r--Source/QtDialog/Compilers.h23
-rw-r--r--Source/QtDialog/Compilers.ui87
-rw-r--r--Source/QtDialog/CrossCompiler.ui213
-rw-r--r--Source/QtDialog/Delete16.pngbin0 -> 731 bytes
-rw-r--r--Source/QtDialog/FirstConfigure.cxx581
-rw-r--r--Source/QtDialog/FirstConfigure.h189
-rw-r--r--Source/QtDialog/Info.plist.in34
-rw-r--r--Source/QtDialog/Plus16.pngbin0 -> 358 bytes
-rw-r--r--Source/QtDialog/QCMake.cxx452
-rw-r--r--Source/QtDialog/QCMake.h176
-rw-r--r--Source/QtDialog/QCMakeCacheView.cxx678
-rw-r--r--Source/QtDialog/QCMakeCacheView.h170
-rw-r--r--Source/QtDialog/QCMakeWidgets.cxx118
-rw-r--r--Source/QtDialog/QCMakeWidgets.h82
-rw-r--r--Source/QtDialog/QtDialogCPack.cmake.in15
-rw-r--r--Source/QtDialog/RegexExplorer.cxx136
-rw-r--r--Source/QtDialog/RegexExplorer.h38
-rw-r--r--Source/QtDialog/RegexExplorer.ui155
-rw-r--r--Source/QtDialog/WarningMessagesDialog.cxx86
-rw-r--r--Source/QtDialog/WarningMessagesDialog.h65
-rw-r--r--Source/QtDialog/WarningMessagesDialog.ui173
-rw-r--r--Source/QtDialog/cmakecache.xml8
38 files changed, 6006 insertions, 0 deletions
diff --git a/Source/QtDialog/AddCacheEntry.cxx b/Source/QtDialog/AddCacheEntry.cxx
new file mode 100644
index 0000000..daf4bd1
--- /dev/null
+++ b/Source/QtDialog/AddCacheEntry.cxx
@@ -0,0 +1,99 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "AddCacheEntry.h"
+
+#include <QCompleter>
+#include <QMetaProperty>
+
+static const int NumTypes = 4;
+static const int DefaultTypeIndex = 0;
+static const QByteArray TypeStrings[NumTypes] = { "BOOL", "PATH", "FILEPATH",
+ "STRING" };
+static const QCMakeProperty::PropertyType Types[NumTypes] = {
+ QCMakeProperty::BOOL, QCMakeProperty::PATH, QCMakeProperty::FILEPATH,
+ QCMakeProperty::STRING
+};
+
+AddCacheEntry::AddCacheEntry(QWidget* p, const QStringList& varNames,
+ const QStringList& varTypes)
+ : QWidget(p)
+ , VarNames(varNames)
+ , VarTypes(varTypes)
+{
+ this->setupUi(this);
+ for (int i = 0; i < NumTypes; i++) {
+ this->Type->addItem(TypeStrings[i]);
+ }
+ QWidget* cb = new QCheckBox();
+ QWidget* path = new QCMakePathEditor();
+ QWidget* filepath = new QCMakeFilePathEditor();
+ QWidget* string = new QLineEdit();
+ this->StackedWidget->addWidget(cb);
+ this->StackedWidget->addWidget(path);
+ this->StackedWidget->addWidget(filepath);
+ this->StackedWidget->addWidget(string);
+ this->setTabOrder(this->Name, this->Type);
+ this->setTabOrder(this->Type, cb);
+ this->setTabOrder(cb, path);
+ this->setTabOrder(path, filepath);
+ this->setTabOrder(filepath, string);
+ this->setTabOrder(string, this->Description);
+ QCompleter* completer = new QCompleter(this->VarNames, this);
+ this->Name->setCompleter(completer);
+ connect(completer, SIGNAL(activated(const QString&)), this,
+ SLOT(onCompletionActivated(const QString&)));
+}
+
+QString AddCacheEntry::name() const
+{
+ return this->Name->text();
+}
+
+QVariant AddCacheEntry::value() const
+{
+ QWidget* w = this->StackedWidget->currentWidget();
+ if (qobject_cast<QLineEdit*>(w)) {
+ return static_cast<QLineEdit*>(w)->text();
+ }
+ if (qobject_cast<QCheckBox*>(w)) {
+ return static_cast<QCheckBox*>(w)->isChecked();
+ }
+ return QVariant();
+}
+
+QString AddCacheEntry::description() const
+{
+ return this->Description->text();
+}
+
+QCMakeProperty::PropertyType AddCacheEntry::type() const
+{
+ int idx = this->Type->currentIndex();
+ if (idx >= 0 && idx < NumTypes) {
+ return Types[idx];
+ }
+ return Types[DefaultTypeIndex];
+}
+
+QString AddCacheEntry::typeString() const
+{
+ int idx = this->Type->currentIndex();
+ if (idx >= 0 && idx < NumTypes) {
+ return TypeStrings[idx];
+ }
+ return TypeStrings[DefaultTypeIndex];
+}
+
+void AddCacheEntry::onCompletionActivated(const QString& text)
+{
+ int idx = this->VarNames.indexOf(text);
+ if (idx != -1) {
+ QString vartype = this->VarTypes[idx];
+ for (int i = 0; i < NumTypes; i++) {
+ if (TypeStrings[i] == vartype) {
+ this->Type->setCurrentIndex(i);
+ break;
+ }
+ }
+ }
+}
diff --git a/Source/QtDialog/AddCacheEntry.h b/Source/QtDialog/AddCacheEntry.h
new file mode 100644
index 0000000..cc710f5
--- /dev/null
+++ b/Source/QtDialog/AddCacheEntry.h
@@ -0,0 +1,35 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef AddCacheEntry_h
+#define AddCacheEntry_h
+
+#include "QCMake.h"
+
+#include <QCheckBox>
+#include <QStringList>
+#include <QWidget>
+
+#include "ui_AddCacheEntry.h"
+
+class AddCacheEntry : public QWidget, public Ui::AddCacheEntry
+{
+ Q_OBJECT
+public:
+ AddCacheEntry(QWidget* p, const QStringList& varNames,
+ const QStringList& varTypes);
+
+ QString name() const;
+ QVariant value() const;
+ QString description() const;
+ QCMakeProperty::PropertyType type() const;
+ QString typeString() const;
+
+private slots:
+ void onCompletionActivated(const QString& text);
+
+private:
+ const QStringList& VarNames;
+ const QStringList& VarTypes;
+};
+
+#endif
diff --git a/Source/QtDialog/AddCacheEntry.ui b/Source/QtDialog/AddCacheEntry.ui
new file mode 100644
index 0000000..a815874
--- /dev/null
+++ b/Source/QtDialog/AddCacheEntry.ui
@@ -0,0 +1,97 @@
+<ui version="4.0" >
+ <class>AddCacheEntry</class>
+ <widget class="QWidget" name="AddCacheEntry" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>380</width>
+ <height>158</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="Name" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Type:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QComboBox" name="Type" >
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_5" >
+ <property name="text" >
+ <string>Value:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QStackedWidget" name="StackedWidget" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>Description:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QLineEdit" name="Description" />
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QCMakePathEditor</class>
+ <extends>QLineEdit</extends>
+ <header>QCMakeWidgets.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QCMakeFilePathEditor</class>
+ <extends>QLineEdit</extends>
+ <header>QCMakeWidgets.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>Type</sender>
+ <signal>currentIndexChanged(int)</signal>
+ <receiver>StackedWidget</receiver>
+ <slot>setCurrentIndex(int)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>229</x>
+ <y>34</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>287</x>
+ <y>65</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/Source/QtDialog/CMake.desktop b/Source/QtDialog/CMake.desktop
new file mode 100644
index 0000000..842091f
--- /dev/null
+++ b/Source/QtDialog/CMake.desktop
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Version=1.0
+Name=CMake
+Comment=Cross-platform buildsystem
+Exec=cmake-gui %f
+Icon=CMakeSetup
+Terminal=false
+X-MultipleArgs=false
+Type=Application
+Categories=Development;
+StartupNotify=true
+MimeType=application/x-cmakecache;
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
new file mode 100644
index 0000000..10fd718
--- /dev/null
+++ b/Source/QtDialog/CMakeLists.txt
@@ -0,0 +1,232 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+project(QtDialog)
+if(POLICY CMP0020)
+ cmake_policy(SET CMP0020 NEW) # Drop when CMake >= 2.8.11 required
+endif()
+CMake_OPTIONAL_COMPONENT(cmake-gui)
+find_package(Qt5Widgets QUIET)
+if (Qt5Widgets_FOUND)
+ include_directories(${Qt5Widgets_INCLUDE_DIRS})
+ add_definitions(${Qt5Widgets_DEFINITONS})
+ macro(qt4_wrap_ui)
+ qt5_wrap_ui(${ARGN})
+ endmacro()
+ macro(qt4_wrap_cpp)
+ qt5_wrap_cpp(${ARGN})
+ endmacro()
+ macro(qt4_add_resources)
+ qt5_add_resources(${ARGN})
+ endmacro()
+ set(CMake_QT_LIBRARIES ${Qt5Widgets_LIBRARIES})
+ set(QT_QTMAIN_LIBRARY ${Qt5Core_QTMAIN_LIBRARIES})
+
+ # Remove this when the minimum version of Qt is 4.6.
+ add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
+
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
+
+ if(CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES)
+ list(APPEND CMake_QT_LIBRARIES ${CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES})
+ set_property(SOURCE CMakeSetup.cxx
+ PROPERTY COMPILE_DEFINITIONS USE_QXcbIntegrationPlugin)
+ endif()
+
+ # We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows.
+ # FIXME: This should be part of Qt5 CMake scripts, but unfortunatelly
+ # Qt5 support is missing there.
+ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
+ macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var)
+ get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION)
+ if(EXISTS "${_qt_plugin_path}")
+ get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME)
+ get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH)
+ get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME)
+ if(APPLE)
+ set(_qt_plugin_dir "PlugIns")
+ elseif(WIN32)
+ set(_qt_plugin_dir "plugins")
+ endif()
+ set(_qt_plugin_dest "${_qt_plugin_dir}/${_qt_plugin_type}")
+ install(FILES "${_qt_plugin_path}"
+ DESTINATION "${_qt_plugin_dest}"
+ ${COMPONENT})
+ set(${_qt_plugins_var}
+ "${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}")
+ else()
+ message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found")
+ endif()
+ endmacro()
+ if(APPLE)
+ install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS)
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ "[Paths]\nPlugins = ${_qt_plugin_dir}\n")
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources"
+ ${COMPONENT})
+ elseif(WIN32)
+ install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS)
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ "[Paths]\nPlugins = ../${_qt_plugin_dir}\n")
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ DESTINATION bin
+ ${COMPONENT})
+ endif()
+ endif()
+
+ if(TARGET Qt5::Core)
+ get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION)
+ get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH)
+ if(APPLE)
+ get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH)
+ endif()
+ endif()
+else()
+ set(QT_MIN_VERSION "4.4.0")
+ find_package(Qt4 REQUIRED)
+ if(NOT QT4_FOUND)
+ message(SEND_ERROR "Failed to find Qt 4.4 or greater.")
+ return()
+ endif()
+
+ include(${QT_USE_FILE})
+
+ set(CMake_QT_LIBRARIES ${QT_LIBRARIES})
+
+endif()
+
+set(SRCS
+ AddCacheEntry.cxx
+ AddCacheEntry.h
+ CMakeSetup.cxx
+ CMakeSetupDialog.cxx
+ CMakeSetupDialog.h
+ FirstConfigure.cxx
+ FirstConfigure.h
+ QCMake.cxx
+ QCMake.h
+ QCMakeCacheView.cxx
+ QCMakeCacheView.h
+ QCMakeWidgets.cxx
+ QCMakeWidgets.h
+ RegexExplorer.cxx
+ RegexExplorer.h
+ WarningMessagesDialog.cxx
+ WarningMessagesDialog.h
+ )
+QT4_WRAP_UI(UI_SRCS
+ CMakeSetupDialog.ui
+ Compilers.ui
+ CrossCompiler.ui
+ AddCacheEntry.ui
+ RegexExplorer.ui
+ WarningMessagesDialog.ui
+ )
+QT4_WRAP_CPP(MOC_SRCS
+ AddCacheEntry.h
+ Compilers.h
+ CMakeSetupDialog.h
+ FirstConfigure.h
+ QCMake.h
+ QCMakeCacheView.h
+ QCMakeWidgets.h
+ RegexExplorer.h
+ WarningMessagesDialog.h
+ )
+QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc)
+
+set(SRCS ${SRCS} ${UI_SRCS} ${MOC_SRCS} ${RC_SRCS})
+if(WIN32)
+ set(SRCS ${SRCS} CMakeSetup.rc)
+endif()
+if(APPLE)
+ set(SRCS ${SRCS} CMakeSetup.icns)
+ set(MACOSX_BUNDLE_ICON_FILE CMakeSetup.icns)
+ set_source_files_properties(CMakeSetup.icns PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources)
+endif()
+
+if(USE_LGPL)
+ install(FILES ${CMake_SOURCE_DIR}/Licenses/LGPLv${USE_LGPL}.txt
+ DESTINATION ${CMAKE_DATA_DIR}/Licenses
+ ${COMPONENT})
+ set_property(SOURCE CMakeSetupDialog.cxx
+ PROPERTY COMPILE_DEFINITIONS USE_LGPL="${USE_LGPL}")
+endif()
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE})
+target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES})
+
+if(APPLE)
+ file(STRINGS "${CMake_SOURCE_DIR}/Copyright.txt" copyright_line
+ LIMIT_COUNT 1 REGEX "^Copyright 2000-20[0-9][0-9] Kitware")
+
+ set_target_properties(cmake-gui PROPERTIES
+ OUTPUT_NAME CMake
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in"
+ MACOSX_BUNDLE_SHORT_VERSION_STRING "${CMAKE_BUNDLE_VERSION}"
+ # TBD: MACOSX_BUNDLE_BUNDLE_VERSION "${CMAKE_BUNDLE_VERSION}"
+ MACOSX_BUNDLE_COPYRIGHT "${copyright_line}"
+ MACOSX_BUNDLE_GUI_IDENTIFIER "org.cmake.cmake"
+ )
+
+ # Create a symlink in the build tree to provide a "cmake-gui" next
+ # to the "cmake" executable that refers to the application bundle.
+ add_custom_command(TARGET cmake-gui POST_BUILD
+ COMMAND ln -sf CMake.app/Contents/MacOS/CMake
+ $<TARGET_FILE_DIR:cmake>/cmake-gui
+ )
+endif()
+set(CMAKE_INSTALL_DESTINATION_ARGS
+ BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" ${COMPONENT})
+
+install(TARGETS cmake-gui
+ RUNTIME DESTINATION bin ${COMPONENT}
+ ${CMAKE_INSTALL_DESTINATION_ARGS})
+
+if(UNIX AND NOT APPLE)
+ foreach (size IN ITEMS 32 128)
+ install(
+ FILES "${CMAKE_CURRENT_SOURCE_DIR}/CMakeSetup${size}.png"
+ DESTINATION "${CMAKE_XDGDATA_DIR}/icons/hicolor/${size}x${size}/apps"
+ ${COMPONENT}
+ RENAME "CMakeSetup.png")
+ endforeach ()
+
+ # install a desktop file so CMake appears in the application start menu
+ # with an icon
+ install(FILES CMake.desktop
+ DESTINATION "${CMAKE_XDGDATA_DIR}/applications"
+ ${COMPONENT})
+ install(FILES cmakecache.xml
+ DESTINATION "${CMAKE_XDGDATA_DIR}/mime/packages"
+ ${COMPONENT})
+endif()
+
+if(APPLE)
+ install(CODE "
+ execute_process(COMMAND ln -s \"../MacOS/CMake\" cmake-gui
+ WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)
+ " ${COMPONENT})
+endif()
+
+if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
+ # install rules for including 3rd party libs such as Qt
+ # if a system Qt is used (e.g. installed in /usr/lib/), it will not be included in the installation
+ set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/cmake-gui${CMAKE_EXECUTABLE_SUFFIX}")
+ if(APPLE)
+ set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/CMake")
+ endif()
+ install(CODE "
+ include(\"${CMake_SOURCE_DIR}/Modules/BundleUtilities.cmake\")
+ set(BU_CHMOD_BUNDLE_ITEMS ON)
+ fixup_bundle(\"${fixup_exe}\" \"${QT_PLUGINS}\" \"${Qt_BIN_DIR};${QT_LIBRARY_DIR};${QT_BINARY_DIR}\")
+ " ${COMPONENT})
+endif()
+
+set(CMAKE_PACKAGE_QTGUI TRUE)
+configure_file("${QtDialog_SOURCE_DIR}/QtDialogCPack.cmake.in"
+ "${QtDialog_BINARY_DIR}/QtDialogCPack.cmake" @ONLY)
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
new file mode 100644
index 0000000..5e03c39
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -0,0 +1,253 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMake.h" // include to disable MS warnings
+
+#include "CMakeSetupDialog.h"
+#include "cmAlgorithms.h"
+#include "cmDocumentation.h"
+#include "cmDocumentationEntry.h"
+#include "cmVersion.h"
+#include "cmake.h"
+#include <QApplication>
+#include <QDir>
+#include <QLocale>
+#include <QString>
+#include <QTextCodec>
+#include <QTranslator>
+#include <QtPlugin>
+#include <cmsys/CommandLineArguments.hxx>
+#include <cmsys/Encoding.hxx>
+#include <cmsys/SystemTools.hxx>
+#include <iostream>
+
+#include "cmSystemTools.h" // IWYU pragma: keep
+
+static const char* cmDocumentationName[][2] = { { CM_NULLPTR,
+ " cmake-gui - CMake GUI." },
+ { CM_NULLPTR, CM_NULLPTR } };
+
+static const char* cmDocumentationUsage[][2] = {
+ { CM_NULLPTR, " cmake-gui [options]\n"
+ " cmake-gui [options] <path-to-source>\n"
+ " cmake-gui [options] <path-to-existing-build>" },
+ { CM_NULLPTR, CM_NULLPTR }
+};
+
+static const char* cmDocumentationOptions[]
+ [2] = { { CM_NULLPTR, CM_NULLPTR } };
+
+#if defined(Q_OS_MAC)
+static int cmOSXInstall(std::string dir);
+static void cmAddPluginPath();
+#endif
+
+#if defined(USE_QXcbIntegrationPlugin)
+Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
+#endif
+
+int main(int argc, char** argv)
+{
+ cmsys::Encoding::CommandLineArguments encoding_args =
+ cmsys::Encoding::CommandLineArguments::Main(argc, argv);
+ int argc2 = encoding_args.argc();
+ char const* const* argv2 = encoding_args.argv();
+
+ cmSystemTools::FindCMakeResources(argv2[0]);
+ // check docs first so that X is not need to get docs
+ // do docs, if args were given
+ cmDocumentation doc;
+ doc.addCMakeStandardDocSections();
+ if (argc2 > 1 && doc.CheckOptions(argc2, argv2)) {
+ // Construct and print requested documentation.
+ cmake hcm;
+ hcm.SetHomeDirectory("");
+ hcm.SetHomeOutputDirectory("");
+ hcm.AddCMakePaths();
+
+ std::vector<cmDocumentationEntry> generators;
+ hcm.GetGeneratorDocumentation(generators);
+ doc.SetName("cmake");
+ doc.SetSection("Name", cmDocumentationName);
+ doc.SetSection("Usage", cmDocumentationUsage);
+ doc.AppendSection("Generators", generators);
+ doc.PrependSection("Options", cmDocumentationOptions);
+
+ return (doc.PrintRequestedDocumentation(std::cout) ? 0 : 1);
+ }
+
+#if defined(Q_OS_MAC)
+ if (argc2 == 2 && strcmp(argv2[1], "--install") == 0) {
+ return cmOSXInstall("/usr/local/bin");
+ }
+ if (argc2 == 2 && cmHasLiteralPrefix(argv2[1], "--install=")) {
+ return cmOSXInstall(argv2[1] + 10);
+ }
+#endif
+
+// When we are on OSX and we are launching cmake-gui from a symlink, the
+// application will fail to launch as it can't find the qt.conf file which
+// tells it what the name of the plugin folder is. We need to add this path
+// BEFORE the application is constructed as that is what triggers the
+// searching for the platform plugins
+#if defined(Q_OS_MAC)
+ cmAddPluginPath();
+#endif
+
+ QApplication app(argc, argv);
+
+ setlocale(LC_NUMERIC, "C");
+
+ QTextCodec* utf8_codec = QTextCodec::codecForName("UTF-8");
+ QTextCodec::setCodecForLocale(utf8_codec);
+
+#if QT_VERSION < 0x050000
+ // clean out standard Qt paths for plugins, which we don't use anyway
+ // when creating Mac bundles, it potentially causes problems
+ foreach (QString p, QApplication::libraryPaths()) {
+ QApplication::removeLibraryPath(p);
+ }
+#endif
+
+ // tell the cmake library where cmake is
+ QDir cmExecDir(QApplication::applicationDirPath());
+#if defined(Q_OS_MAC)
+ cmExecDir.cd("../../../");
+#endif
+
+ // pick up translation files if they exists in the data directory
+ QDir translationsDir = cmExecDir;
+ translationsDir.cd(QString::fromLocal8Bit(".." CMAKE_DATA_DIR));
+ translationsDir.cd("i18n");
+ QTranslator translator;
+ QString transfile = QString("cmake_%1").arg(QLocale::system().name());
+ translator.load(transfile, translationsDir.path());
+ app.installTranslator(&translator);
+
+ // app setup
+ app.setApplicationName("CMakeSetup");
+ app.setOrganizationName("Kitware");
+ QIcon appIcon;
+ appIcon.addFile(":/Icons/CMakeSetup32.png");
+ appIcon.addFile(":/Icons/CMakeSetup128.png");
+ app.setWindowIcon(appIcon);
+
+ CMakeSetupDialog dialog;
+ dialog.show();
+
+ cmsys::CommandLineArguments arg;
+ arg.Initialize(argc2, argv2);
+ std::string binaryDirectory;
+ std::string sourceDirectory;
+ typedef cmsys::CommandLineArguments argT;
+ arg.AddArgument("-B", argT::CONCAT_ARGUMENT, &binaryDirectory,
+ "Binary Directory");
+ arg.AddArgument("-H", argT::CONCAT_ARGUMENT, &sourceDirectory,
+ "Source Directory");
+ // do not complain about unknown options
+ arg.StoreUnusedArguments(true);
+ arg.Parse();
+ if (!sourceDirectory.empty() && !binaryDirectory.empty()) {
+ dialog.setSourceDirectory(QString::fromLocal8Bit(sourceDirectory.c_str()));
+ dialog.setBinaryDirectory(QString::fromLocal8Bit(binaryDirectory.c_str()));
+ } else {
+ QStringList args = app.arguments();
+ if (args.count() == 2) {
+ std::string filePath =
+ cmSystemTools::CollapseFullPath(args[1].toLocal8Bit().data());
+
+ // check if argument is a directory containing CMakeCache.txt
+ std::string buildFilePath =
+ cmSystemTools::CollapseFullPath("CMakeCache.txt", filePath.c_str());
+
+ // check if argument is a CMakeCache.txt file
+ if (cmSystemTools::GetFilenameName(filePath) == "CMakeCache.txt" &&
+ cmSystemTools::FileExists(filePath.c_str())) {
+ buildFilePath = filePath;
+ }
+
+ // check if argument is a directory containing CMakeLists.txt
+ std::string srcFilePath =
+ cmSystemTools::CollapseFullPath("CMakeLists.txt", filePath.c_str());
+
+ if (cmSystemTools::FileExists(buildFilePath.c_str())) {
+ dialog.setBinaryDirectory(QString::fromLocal8Bit(
+ cmSystemTools::GetFilenamePath(buildFilePath).c_str()));
+ } else if (cmSystemTools::FileExists(srcFilePath.c_str())) {
+ dialog.setSourceDirectory(QString::fromLocal8Bit(filePath.c_str()));
+ dialog.setBinaryDirectory(QString::fromLocal8Bit(
+ cmSystemTools::CollapseFullPath(".").c_str()));
+ }
+ }
+ }
+
+ return app.exec();
+}
+
+#if defined(Q_OS_MAC)
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+static bool cmOSXInstall(std::string const& dir, std::string const& tool)
+{
+ if (tool.empty()) {
+ return true;
+ }
+ std::string link = dir + cmSystemTools::GetFilenameName(tool);
+ struct stat st;
+ if (lstat(link.c_str(), &st) == 0 && S_ISLNK(st.st_mode)) {
+ char buf[4096];
+ ssize_t s = readlink(link.c_str(), buf, sizeof(buf) - 1);
+ if (s >= 0 && std::string(buf, s) == tool) {
+ std::cerr << "Exists: '" << link << "' -> '" << tool << "'\n";
+ return true;
+ }
+ }
+ cmSystemTools::MakeDirectory(dir);
+ if (symlink(tool.c_str(), link.c_str()) == 0) {
+ std::cerr << "Linked: '" << link << "' -> '" << tool << "'\n";
+ return true;
+ } else {
+ int err = errno;
+ std::cerr << "Failed: '" << link << "' -> '" << tool
+ << "': " << strerror(err) << "\n";
+ return false;
+ }
+}
+static int cmOSXInstall(std::string dir)
+{
+ if (!cmHasLiteralSuffix(dir, "/")) {
+ dir += "/";
+ }
+ return (cmOSXInstall(dir, cmSystemTools::GetCMakeCommand()) &&
+ cmOSXInstall(dir, cmSystemTools::GetCTestCommand()) &&
+ cmOSXInstall(dir, cmSystemTools::GetCPackCommand()) &&
+ cmOSXInstall(dir, cmSystemTools::GetCMakeGUICommand()) &&
+ cmOSXInstall(dir, cmSystemTools::GetCMakeCursesCommand()))
+ ? 0
+ : 1;
+}
+
+// Locate the PlugIns directory and add it to the QApplication library paths.
+// We need to resolve all symlinks so we have a known relative path between
+// MacOS/CMake and the PlugIns directory.
+//
+// Note we are using cmSystemTools since Qt can't provide the path to the
+// executable before the QApplication is created, and that is when plugin
+// searching occurs.
+static void cmAddPluginPath()
+{
+ std::string const& path = cmSystemTools::GetCMakeGUICommand();
+ if (path.empty()) {
+ return;
+ }
+ std::string const& realPath = cmSystemTools::GetRealPath(path);
+ QFileInfo appPath(QString::fromLocal8Bit(realPath.c_str()));
+ QDir pluginDir = appPath.dir();
+ bool const foundPluginDir = pluginDir.cd("../PlugIns");
+ if (foundPluginDir) {
+ QApplication::addLibraryPath(pluginDir.path());
+ }
+}
+
+#endif
diff --git a/Source/QtDialog/CMakeSetup.icns b/Source/QtDialog/CMakeSetup.icns
new file mode 100644
index 0000000..4a50c04
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup.icns
Binary files differ
diff --git a/Source/QtDialog/CMakeSetup.ico b/Source/QtDialog/CMakeSetup.ico
new file mode 100644
index 0000000..e13bb15
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup.ico
Binary files differ
diff --git a/Source/QtDialog/CMakeSetup.qrc b/Source/QtDialog/CMakeSetup.qrc
new file mode 100644
index 0000000..eaac192
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/Icons" >
+ <file>CMakeSetup128.png</file>
+ <file>CMakeSetup32.png</file>
+ <file>Delete16.png</file>
+ <file>Plus16.png</file>
+ </qresource>
+</RCC>
diff --git a/Source/QtDialog/CMakeSetup.rc b/Source/QtDialog/CMakeSetup.rc
new file mode 100644
index 0000000..fcc887d
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "CMakeSetup.ico"
diff --git a/Source/QtDialog/CMakeSetup128.png b/Source/QtDialog/CMakeSetup128.png
new file mode 100644
index 0000000..12f1d9a
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup128.png
Binary files differ
diff --git a/Source/QtDialog/CMakeSetup32.png b/Source/QtDialog/CMakeSetup32.png
new file mode 100644
index 0000000..7bbcee4
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup32.png
Binary files differ
diff --git a/Source/QtDialog/CMakeSetup64.png b/Source/QtDialog/CMakeSetup64.png
new file mode 100644
index 0000000..43a8cc6
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup64.png
Binary files differ
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
new file mode 100644
index 0000000..111b28a
--- /dev/null
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -0,0 +1,1330 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "CMakeSetupDialog.h"
+
+#include <QCloseEvent>
+#include <QCoreApplication>
+#include <QDesktopServices>
+#include <QDialogButtonBox>
+#include <QDragEnterEvent>
+#include <QFileDialog>
+#include <QInputDialog>
+#include <QKeySequence>
+#include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QMimeData>
+#include <QProgressBar>
+#include <QSettings>
+#include <QShortcut>
+#include <QStatusBar>
+#include <QToolButton>
+#include <QUrl>
+
+#include "AddCacheEntry.h"
+#include "FirstConfigure.h"
+#include "QCMake.h"
+#include "QCMakeCacheView.h"
+#include "RegexExplorer.h"
+#include "WarningMessagesDialog.h"
+#include "cmSystemTools.h"
+#include "cmVersion.h"
+
+QCMakeThread::QCMakeThread(QObject* p)
+ : QThread(p)
+ , CMakeInstance(CM_NULLPTR)
+{
+}
+
+QCMake* QCMakeThread::cmakeInstance() const
+{
+ return this->CMakeInstance;
+}
+
+void QCMakeThread::run()
+{
+ this->CMakeInstance = new QCMake;
+ // emit that this cmake thread is ready for use
+ emit this->cmakeInitialized();
+ this->exec();
+ delete this->CMakeInstance;
+ this->CMakeInstance = CM_NULLPTR;
+}
+
+CMakeSetupDialog::CMakeSetupDialog()
+ : ExitAfterGenerate(true)
+ , CacheModified(false)
+ , ConfigureNeeded(true)
+ , CurrentState(Interrupting)
+{
+ QString title = QString(tr("CMake %1"));
+ title = title.arg(cmVersion::GetCMakeVersion());
+ this->setWindowTitle(title);
+
+ // create the GUI
+ QSettings settings;
+ settings.beginGroup("Settings/StartPath");
+ restoreGeometry(settings.value("geometry").toByteArray());
+ restoreState(settings.value("windowState").toByteArray());
+
+ this->AddVariableNames =
+ settings.value("AddVariableNames", QStringList("CMAKE_INSTALL_PREFIX"))
+ .toStringList();
+ this->AddVariableTypes =
+ settings.value("AddVariableTypes", QStringList("PATH")).toStringList();
+
+ QWidget* cont = new QWidget(this);
+ this->setupUi(cont);
+ this->Splitter->setStretchFactor(0, 3);
+ this->Splitter->setStretchFactor(1, 1);
+ this->setCentralWidget(cont);
+ this->ProgressBar->reset();
+ this->RemoveEntry->setEnabled(false);
+ this->AddEntry->setEnabled(false);
+
+ QByteArray p = settings.value("SplitterSizes").toByteArray();
+ this->Splitter->restoreState(p);
+
+ bool groupView = settings.value("GroupView", false).toBool();
+ this->setGroupedView(groupView);
+ this->groupedCheck->setCheckState(groupView ? Qt::Checked : Qt::Unchecked);
+
+ bool advancedView = settings.value("AdvancedView", false).toBool();
+ this->setAdvancedView(advancedView);
+ this->advancedCheck->setCheckState(advancedView ? Qt::Checked
+ : Qt::Unchecked);
+
+ QMenu* FileMenu = this->menuBar()->addMenu(tr("&File"));
+ this->ReloadCacheAction = FileMenu->addAction(tr("&Reload Cache"));
+ QObject::connect(this->ReloadCacheAction, SIGNAL(triggered(bool)), this,
+ SLOT(doReloadCache()));
+ this->DeleteCacheAction = FileMenu->addAction(tr("&Delete Cache"));
+ QObject::connect(this->DeleteCacheAction, SIGNAL(triggered(bool)), this,
+ SLOT(doDeleteCache()));
+ this->ExitAction = FileMenu->addAction(tr("E&xit"));
+ this->ExitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
+ QObject::connect(this->ExitAction, SIGNAL(triggered(bool)), this,
+ SLOT(close()));
+
+ QMenu* ToolsMenu = this->menuBar()->addMenu(tr("&Tools"));
+ this->ConfigureAction = ToolsMenu->addAction(tr("&Configure"));
+ // prevent merging with Preferences menu item on Mac OS X
+ this->ConfigureAction->setMenuRole(QAction::NoRole);
+ QObject::connect(this->ConfigureAction, SIGNAL(triggered(bool)), this,
+ SLOT(doConfigure()));
+ this->GenerateAction = ToolsMenu->addAction(tr("&Generate"));
+ QObject::connect(this->GenerateAction, SIGNAL(triggered(bool)), this,
+ SLOT(doGenerate()));
+ QAction* showChangesAction = ToolsMenu->addAction(tr("&Show My Changes"));
+ QObject::connect(showChangesAction, SIGNAL(triggered(bool)), this,
+ SLOT(showUserChanges()));
+#if defined(Q_WS_MAC) || defined(Q_OS_MAC)
+ this->InstallForCommandLineAction =
+ ToolsMenu->addAction(tr("&How to Install For Command Line Use"));
+ QObject::connect(this->InstallForCommandLineAction, SIGNAL(triggered(bool)),
+ this, SLOT(doInstallForCommandLine()));
+#endif
+ ToolsMenu->addSeparator();
+ ToolsMenu->addAction(tr("Regular Expression Explorer..."), this,
+ SLOT(doRegexExplorerDialog()));
+ ToolsMenu->addSeparator();
+ ToolsMenu->addAction(tr("&Find in Output..."), this,
+ SLOT(doOutputFindDialog()), QKeySequence::Find);
+ ToolsMenu->addAction(tr("Find Next"), this, SLOT(doOutputFindNext()),
+ QKeySequence::FindNext);
+ ToolsMenu->addAction(tr("Find Previous"), this, SLOT(doOutputFindPrev()),
+ QKeySequence::FindPrevious);
+ ToolsMenu->addAction(tr("Goto Next Error"), this, SLOT(doOutputErrorNext()),
+ QKeySequence(Qt::Key_F8)); // in Visual Studio
+ new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Period), this,
+ SLOT(doOutputErrorNext())); // in Eclipse
+
+ QMenu* OptionsMenu = this->menuBar()->addMenu(tr("&Options"));
+ OptionsMenu->addAction(tr("Warning Messages..."), this,
+ SLOT(doWarningMessagesDialog()));
+ this->WarnUninitializedAction =
+ OptionsMenu->addAction(tr("&Warn Uninitialized (--warn-uninitialized)"));
+ this->WarnUninitializedAction->setCheckable(true);
+ this->WarnUnusedAction =
+ OptionsMenu->addAction(tr("&Warn Unused (--warn-unused-vars)"));
+ this->WarnUnusedAction->setCheckable(true);
+
+ QAction* debugAction = OptionsMenu->addAction(tr("&Debug Output"));
+ debugAction->setCheckable(true);
+ QObject::connect(debugAction, SIGNAL(toggled(bool)), this,
+ SLOT(setDebugOutput(bool)));
+
+ OptionsMenu->addSeparator();
+ QAction* expandAction =
+ OptionsMenu->addAction(tr("&Expand Grouped Entries"));
+ QObject::connect(expandAction, SIGNAL(triggered(bool)), this->CacheValues,
+ SLOT(expandAll()));
+ QAction* collapseAction =
+ OptionsMenu->addAction(tr("&Collapse Grouped Entries"));
+ QObject::connect(collapseAction, SIGNAL(triggered(bool)), this->CacheValues,
+ SLOT(collapseAll()));
+
+ QMenu* HelpMenu = this->menuBar()->addMenu(tr("&Help"));
+ QAction* a = HelpMenu->addAction(tr("About"));
+ QObject::connect(a, SIGNAL(triggered(bool)), this, SLOT(doAbout()));
+ a = HelpMenu->addAction(tr("Help"));
+ QObject::connect(a, SIGNAL(triggered(bool)), this, SLOT(doHelp()));
+
+ this->setAcceptDrops(true);
+
+ // get the saved binary directories
+ QStringList buildPaths = this->loadBuildPaths();
+ this->BinaryDirectory->addItems(buildPaths);
+
+ this->BinaryDirectory->setCompleter(new QCMakeFileCompleter(this, true));
+ this->SourceDirectory->setCompleter(new QCMakeFileCompleter(this, true));
+
+ // fixed pitch font in output window
+ QFont outputFont("Courier");
+ this->Output->setFont(outputFont);
+ this->ErrorFormat.setForeground(QBrush(Qt::red));
+
+ this->Output->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(this->Output, SIGNAL(customContextMenuRequested(const QPoint&)),
+ this, SLOT(doOutputContextMenu(const QPoint&)));
+
+ // start the cmake worker thread
+ this->CMakeThread = new QCMakeThread(this);
+ QObject::connect(this->CMakeThread, SIGNAL(cmakeInitialized()), this,
+ SLOT(initialize()), Qt::QueuedConnection);
+ this->CMakeThread->start();
+
+ this->enterState(ReadyConfigure);
+
+ ProgressOffset = 0.0;
+ ProgressFactor = 1.0;
+}
+
+void CMakeSetupDialog::initialize()
+{
+ // now the cmake worker thread is running, lets make our connections to it
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(propertiesChanged(const QCMakePropertyList&)),
+ this->CacheValues->cacheModel(),
+ SLOT(setProperties(const QCMakePropertyList&)));
+
+ QObject::connect(this->ConfigureButton, SIGNAL(clicked(bool)), this,
+ SLOT(doConfigure()));
+
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(configureDone(int)), this, SLOT(exitLoop(int)));
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(generateDone(int)), this, SLOT(exitLoop(int)));
+
+ QObject::connect(this->GenerateButton, SIGNAL(clicked(bool)), this,
+ SLOT(doGenerate()));
+ QObject::connect(this->OpenProjectButton, SIGNAL(clicked(bool)), this,
+ SLOT(doOpenProject()));
+
+ QObject::connect(this->BrowseSourceDirectoryButton, SIGNAL(clicked(bool)),
+ this, SLOT(doSourceBrowse()));
+ QObject::connect(this->BrowseBinaryDirectoryButton, SIGNAL(clicked(bool)),
+ this, SLOT(doBinaryBrowse()));
+
+ QObject::connect(this->BinaryDirectory, SIGNAL(editTextChanged(QString)),
+ this, SLOT(onBinaryDirectoryChanged(QString)));
+ QObject::connect(this->SourceDirectory, SIGNAL(textChanged(QString)), this,
+ SLOT(onSourceDirectoryChanged(QString)));
+
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(sourceDirChanged(QString)), this,
+ SLOT(updateSourceDirectory(QString)));
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(binaryDirChanged(QString)), this,
+ SLOT(updateBinaryDirectory(QString)));
+
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(progressChanged(QString, float)), this,
+ SLOT(showProgress(QString, float)));
+
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(errorMessage(QString)), this, SLOT(error(QString)));
+
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(outputMessage(QString)), this,
+ SLOT(message(QString)));
+
+ QObject::connect(this->groupedCheck, SIGNAL(toggled(bool)), this,
+ SLOT(setGroupedView(bool)));
+ QObject::connect(this->advancedCheck, SIGNAL(toggled(bool)), this,
+ SLOT(setAdvancedView(bool)));
+ QObject::connect(this->Search, SIGNAL(textChanged(QString)), this,
+ SLOT(setSearchFilter(QString)));
+
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(generatorChanged(QString)), this,
+ SLOT(updateGeneratorLabel(QString)));
+ this->updateGeneratorLabel(QString());
+
+ QObject::connect(this->CacheValues->cacheModel(),
+ SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(setCacheModified()));
+
+ QObject::connect(this->CacheValues->selectionModel(),
+ SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+ this, SLOT(selectionChanged()));
+ QObject::connect(this->RemoveEntry, SIGNAL(clicked(bool)), this,
+ SLOT(removeSelectedCacheEntries()));
+ QObject::connect(this->AddEntry, SIGNAL(clicked(bool)), this,
+ SLOT(addCacheEntry()));
+
+ QObject::connect(this->WarnUninitializedAction, SIGNAL(triggered(bool)),
+ this->CMakeThread->cmakeInstance(),
+ SLOT(setWarnUninitializedMode(bool)));
+ QObject::connect(this->WarnUnusedAction, SIGNAL(triggered(bool)),
+ this->CMakeThread->cmakeInstance(),
+ SLOT(setWarnUnusedMode(bool)));
+
+ if (!this->SourceDirectory->text().isEmpty() ||
+ !this->BinaryDirectory->lineEdit()->text().isEmpty()) {
+ this->onSourceDirectoryChanged(this->SourceDirectory->text());
+ this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
+ } else {
+ this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
+ }
+}
+
+CMakeSetupDialog::~CMakeSetupDialog()
+{
+ QSettings settings;
+ settings.beginGroup("Settings/StartPath");
+ settings.setValue("windowState", QVariant(saveState()));
+ settings.setValue("geometry", QVariant(saveGeometry()));
+ settings.setValue("SplitterSizes", this->Splitter->saveState());
+
+ // wait for thread to stop
+ this->CMakeThread->quit();
+ this->CMakeThread->wait();
+}
+
+bool CMakeSetupDialog::prepareConfigure()
+{
+ // make sure build directory exists
+ QString bindir = this->CMakeThread->cmakeInstance()->binaryDirectory();
+ QDir dir(bindir);
+ if (!dir.exists()) {
+ QString msg = tr("Build directory does not exist, "
+ "should I create it?\n\n"
+ "Directory: ");
+ msg += bindir;
+ QString title = tr("Create Directory");
+ QMessageBox::StandardButton btn;
+ btn = QMessageBox::information(this, title, msg,
+ QMessageBox::Yes | QMessageBox::No);
+ if (btn == QMessageBox::No) {
+ return false;
+ }
+ if (!dir.mkpath(".")) {
+ QMessageBox::information(
+ this, tr("Create Directory Failed"),
+ QString(tr("Failed to create directory %1")).arg(dir.path()),
+ QMessageBox::Ok);
+
+ return false;
+ }
+ }
+
+ // if no generator, prompt for it and other setup stuff
+ if (this->CMakeThread->cmakeInstance()->generator().isEmpty()) {
+ if (!this->setupFirstConfigure()) {
+ return false;
+ }
+ }
+
+ // remember path
+ this->addBinaryPath(dir.absolutePath());
+
+ return true;
+}
+
+void CMakeSetupDialog::exitLoop(int err)
+{
+ this->LocalLoop.exit(err);
+}
+
+void CMakeSetupDialog::doConfigure()
+{
+ if (this->CurrentState == Configuring) {
+ // stop configure
+ doInterrupt();
+ return;
+ }
+
+ if (!prepareConfigure()) {
+ return;
+ }
+
+ this->enterState(Configuring);
+
+ bool ret = doConfigureInternal();
+
+ if (ret) {
+ this->ConfigureNeeded = false;
+ }
+
+ if (ret && !this->CacheValues->cacheModel()->newPropertyCount()) {
+ this->enterState(ReadyGenerate);
+ } else {
+ this->enterState(ReadyConfigure);
+ this->CacheValues->scrollToTop();
+ }
+ this->ProgressBar->reset();
+}
+
+bool CMakeSetupDialog::doConfigureInternal()
+{
+ this->Output->clear();
+ this->CacheValues->selectionModel()->clear();
+
+ QMetaObject::invokeMethod(
+ this->CMakeThread->cmakeInstance(), "setProperties", Qt::QueuedConnection,
+ Q_ARG(QCMakePropertyList, this->CacheValues->cacheModel()->properties()));
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "configure",
+ Qt::QueuedConnection);
+
+ int err = this->LocalLoop.exec();
+
+ if (err != 0) {
+ QMessageBox::critical(
+ this, tr("Error"),
+ tr("Error in configuration process, project files may be invalid"),
+ QMessageBox::Ok);
+ }
+
+ return 0 == err;
+}
+
+void CMakeSetupDialog::doInstallForCommandLine()
+{
+ QString title = tr("How to Install For Command Line Use");
+ QString msg = tr("One may add CMake to the PATH:\n"
+ "\n"
+ " PATH=\"%1\":\"$PATH\"\n"
+ "\n"
+ "Or, to install symlinks to '/usr/local/bin', run:\n"
+ "\n"
+ " sudo \"%2\" --install\n"
+ "\n"
+ "Or, to install symlinks to another directory, run:\n"
+ "\n"
+ " sudo \"%3\" --install=/path/to/bin\n");
+ msg = msg.arg(
+ cmSystemTools::GetFilenamePath(cmSystemTools::GetCMakeCommand()).c_str());
+ msg = msg.arg(cmSystemTools::GetCMakeGUICommand().c_str());
+ msg = msg.arg(cmSystemTools::GetCMakeGUICommand().c_str());
+
+ QDialog dialog;
+ dialog.setWindowTitle(title);
+ QVBoxLayout* l = new QVBoxLayout(&dialog);
+ QLabel* lab = new QLabel(&dialog);
+ l->addWidget(lab);
+ lab->setText(msg);
+ lab->setWordWrap(false);
+ lab->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ QDialogButtonBox* btns =
+ new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog);
+ QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
+ l->addWidget(btns);
+ dialog.exec();
+}
+
+bool CMakeSetupDialog::doGenerateInternal()
+{
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "generate",
+ Qt::QueuedConnection);
+
+ int err = this->LocalLoop.exec();
+
+ if (err != 0) {
+ QMessageBox::critical(
+ this, tr("Error"),
+ tr("Error in generation process, project files may be invalid"),
+ QMessageBox::Ok);
+ }
+
+ return 0 == err;
+}
+
+void CMakeSetupDialog::doGenerate()
+{
+ if (this->CurrentState == Generating) {
+ // stop generate
+ doInterrupt();
+ return;
+ }
+
+ // see if we need to configure
+ // we'll need to configure if:
+ // the configure step hasn't been done yet
+ // generate was the last step done
+ if (this->ConfigureNeeded) {
+ if (!prepareConfigure()) {
+ return;
+ }
+ }
+
+ this->enterState(Generating);
+
+ bool config_passed = true;
+ if (this->ConfigureNeeded) {
+ this->CacheValues->cacheModel()->setShowNewProperties(false);
+ this->ProgressFactor = 0.5;
+ config_passed = doConfigureInternal();
+ this->ProgressOffset = 0.5;
+ }
+
+ if (config_passed) {
+ doGenerateInternal();
+ }
+
+ this->ProgressOffset = 0.0;
+ this->ProgressFactor = 1.0;
+ this->CacheValues->cacheModel()->setShowNewProperties(true);
+
+ this->enterState(ReadyConfigure);
+ this->ProgressBar->reset();
+
+ this->ConfigureNeeded = true;
+}
+
+QString CMakeSetupDialog::getProjectFilename()
+{
+ QStringList nameFilter;
+ nameFilter << "*.sln"
+ << "*.xcodeproj";
+ QDir directory(this->BinaryDirectory->currentText());
+ QStringList nlnFile = directory.entryList(nameFilter);
+
+ if (nlnFile.count() == 1) {
+ return this->BinaryDirectory->currentText() + "/" + nlnFile.at(0);
+ }
+
+ return QString();
+}
+
+void CMakeSetupDialog::doOpenProject()
+{
+ QDesktopServices::openUrl(QUrl::fromLocalFile(this->getProjectFilename()));
+}
+
+void CMakeSetupDialog::closeEvent(QCloseEvent* e)
+{
+ // prompt for close if there are unsaved changes, and we're not busy
+ if (this->CacheModified) {
+ QString msg = tr("You have changed options but not rebuilt, "
+ "are you sure you want to exit?");
+ QString title = tr("Confirm Exit");
+ QMessageBox::StandardButton btn;
+ btn = QMessageBox::critical(this, title, msg,
+ QMessageBox::Yes | QMessageBox::No);
+ if (btn == QMessageBox::No) {
+ e->ignore();
+ }
+ }
+
+ // don't close if we're busy, unless the user really wants to
+ if (this->CurrentState == Configuring) {
+ QString msg =
+ tr("You are in the middle of a Configure.\n"
+ "If you Exit now the configure information will be lost.\n"
+ "Are you sure you want to Exit?");
+ QString title = tr("Confirm Exit");
+ QMessageBox::StandardButton btn;
+ btn = QMessageBox::critical(this, title, msg,
+ QMessageBox::Yes | QMessageBox::No);
+ if (btn == QMessageBox::No) {
+ e->ignore();
+ } else {
+ this->doInterrupt();
+ }
+ }
+
+ // let the generate finish
+ if (this->CurrentState == Generating) {
+ e->ignore();
+ }
+}
+
+void CMakeSetupDialog::doHelp()
+{
+ QString msg = tr(
+ "CMake is used to configure and generate build files for "
+ "software projects. The basic steps for configuring a project are as "
+ "follows:\r\n\r\n1. Select the source directory for the project. This "
+ "should "
+ "contain the CMakeLists.txt files for the project.\r\n\r\n2. Select the "
+ "build "
+ "directory for the project. This is the directory where the project "
+ "will be "
+ "built. It can be the same or a different directory than the source "
+ "directory. For easy clean up, a separate build directory is "
+ "recommended. "
+ "CMake will create the directory if it does not exist.\r\n\r\n3. Once the "
+ "source and binary directories are selected, it is time to press the "
+ "Configure button. This will cause CMake to read all of the input files "
+ "and "
+ "discover all the variables used by the project. The first time a "
+ "variable "
+ "is displayed it will be in Red. Users should inspect red variables "
+ "making "
+ "sure the values are correct. For some projects the Configure process "
+ "can "
+ "be iterative, so continue to press the Configure button until there are "
+ "no "
+ "longer red entries.\r\n\r\n4. Once there are no longer red entries, you "
+ "should click the Generate button. This will write the build files to "
+ "the build "
+ "directory.");
+
+ QDialog dialog;
+ QFontMetrics met(this->font());
+ int msgWidth = met.width(msg);
+ dialog.setMinimumSize(msgWidth / 15, 20);
+ dialog.setWindowTitle(tr("Help"));
+ QVBoxLayout* l = new QVBoxLayout(&dialog);
+ QLabel* lab = new QLabel(&dialog);
+ lab->setText(msg);
+ lab->setWordWrap(true);
+ QDialogButtonBox* btns =
+ new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog);
+ QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
+ l->addWidget(lab);
+ l->addWidget(btns);
+ dialog.exec();
+}
+
+void CMakeSetupDialog::doInterrupt()
+{
+ this->enterState(Interrupting);
+ this->CMakeThread->cmakeInstance()->interrupt();
+}
+
+void CMakeSetupDialog::doSourceBrowse()
+{
+ QString dir = QFileDialog::getExistingDirectory(
+ this, tr("Enter Path to Source"), this->SourceDirectory->text(),
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+ if (!dir.isEmpty()) {
+ this->setSourceDirectory(dir);
+ }
+}
+
+void CMakeSetupDialog::updateSourceDirectory(const QString& dir)
+{
+ if (this->SourceDirectory->text() != dir) {
+ this->SourceDirectory->blockSignals(true);
+ this->SourceDirectory->setText(dir);
+ this->SourceDirectory->blockSignals(false);
+ }
+}
+
+void CMakeSetupDialog::updateBinaryDirectory(const QString& dir)
+{
+ if (this->BinaryDirectory->currentText() != dir) {
+ this->BinaryDirectory->blockSignals(true);
+ this->BinaryDirectory->setEditText(dir);
+ this->BinaryDirectory->blockSignals(false);
+ }
+ if (!this->getProjectFilename().isEmpty()) {
+ this->OpenProjectButton->setEnabled(true);
+ } else {
+ this->OpenProjectButton->setEnabled(false);
+ }
+}
+
+void CMakeSetupDialog::doBinaryBrowse()
+{
+ QString dir = QFileDialog::getExistingDirectory(
+ this, tr("Enter Path to Build"), this->BinaryDirectory->currentText(),
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+ if (!dir.isEmpty() && dir != this->BinaryDirectory->currentText()) {
+ this->setBinaryDirectory(dir);
+ }
+}
+
+void CMakeSetupDialog::setBinaryDirectory(const QString& dir)
+{
+ this->BinaryDirectory->setEditText(dir);
+}
+
+void CMakeSetupDialog::onSourceDirectoryChanged(const QString& dir)
+{
+ this->Output->clear();
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
+ "setSourceDirectory", Qt::QueuedConnection,
+ Q_ARG(QString, dir));
+}
+
+void CMakeSetupDialog::onBinaryDirectoryChanged(const QString& dir)
+{
+ QString title = QString(tr("CMake %1 - %2"));
+ title = title.arg(cmVersion::GetCMakeVersion());
+ title = title.arg(dir);
+ this->setWindowTitle(title);
+
+ this->CacheModified = false;
+ this->CacheValues->cacheModel()->clear();
+ qobject_cast<QCMakeCacheModelDelegate*>(this->CacheValues->itemDelegate())
+ ->clearChanges();
+ this->Output->clear();
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
+ "setBinaryDirectory", Qt::QueuedConnection,
+ Q_ARG(QString, dir));
+}
+
+void CMakeSetupDialog::setSourceDirectory(const QString& dir)
+{
+ this->SourceDirectory->setText(dir);
+}
+
+void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent)
+{
+ percent = (percent * ProgressFactor) + ProgressOffset;
+ this->ProgressBar->setValue(qRound(percent * 100));
+}
+
+void CMakeSetupDialog::error(const QString& msg)
+{
+ this->Output->setCurrentCharFormat(this->ErrorFormat);
+ // QTextEdit will terminate the msg with a ParagraphSeparator, but it also
+ // replaces
+ // all newlines with ParagraphSeparators. By replacing the newlines by
+ // ourself, one
+ // error msg will be one paragraph.
+ QString paragraph(msg);
+ paragraph.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ this->Output->append(paragraph);
+}
+
+void CMakeSetupDialog::message(const QString& msg)
+{
+ this->Output->setCurrentCharFormat(this->MessageFormat);
+ this->Output->append(msg);
+}
+
+void CMakeSetupDialog::setEnabledState(bool enabled)
+{
+ // disable parts of the GUI during configure/generate
+ this->CacheValues->cacheModel()->setEditEnabled(enabled);
+ this->SourceDirectory->setEnabled(enabled);
+ this->BrowseSourceDirectoryButton->setEnabled(enabled);
+ this->BinaryDirectory->setEnabled(enabled);
+ this->BrowseBinaryDirectoryButton->setEnabled(enabled);
+ this->ReloadCacheAction->setEnabled(enabled);
+ this->DeleteCacheAction->setEnabled(enabled);
+ this->ExitAction->setEnabled(enabled);
+ this->ConfigureAction->setEnabled(enabled);
+ this->AddEntry->setEnabled(enabled);
+ this->RemoveEntry->setEnabled(false); // let selection re-enable it
+}
+
+bool CMakeSetupDialog::setupFirstConfigure()
+{
+ FirstConfigure dialog;
+
+ // initialize dialog and restore saved settings
+
+ // add generators
+ dialog.setGenerators(
+ this->CMakeThread->cmakeInstance()->availableGenerators());
+
+ // restore from settings
+ dialog.loadFromSettings();
+
+ if (dialog.exec() == QDialog::Accepted) {
+ dialog.saveToSettings();
+ this->CMakeThread->cmakeInstance()->setGenerator(dialog.getGenerator());
+ this->CMakeThread->cmakeInstance()->setToolset(dialog.getToolset());
+
+ QCMakeCacheModel* m = this->CacheValues->cacheModel();
+
+ if (dialog.compilerSetup()) {
+ QString fortranCompiler = dialog.getFortranCompiler();
+ if (!fortranCompiler.isEmpty()) {
+ m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_Fortran_COMPILER",
+ "Fortran compiler.", fortranCompiler, false);
+ }
+ QString cxxCompiler = dialog.getCXXCompiler();
+ if (!cxxCompiler.isEmpty()) {
+ m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_CXX_COMPILER",
+ "CXX compiler.", cxxCompiler, false);
+ }
+
+ QString cCompiler = dialog.getCCompiler();
+ if (!cCompiler.isEmpty()) {
+ m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_C_COMPILER",
+ "C compiler.", cCompiler, false);
+ }
+ } else if (dialog.crossCompilerSetup()) {
+ QString fortranCompiler = dialog.getFortranCompiler();
+ if (!fortranCompiler.isEmpty()) {
+ m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_Fortran_COMPILER",
+ "Fortran compiler.", fortranCompiler, false);
+ }
+
+ QString mode = dialog.getCrossIncludeMode();
+ m->insertProperty(QCMakeProperty::STRING,
+ "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE",
+ tr("CMake Find Include Mode"), mode, false);
+ mode = dialog.getCrossLibraryMode();
+ m->insertProperty(QCMakeProperty::STRING,
+ "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY",
+ tr("CMake Find Library Mode"), mode, false);
+ mode = dialog.getCrossProgramMode();
+ m->insertProperty(QCMakeProperty::STRING,
+ "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM",
+ tr("CMake Find Program Mode"), mode, false);
+
+ QString rootPath = dialog.getCrossRoot();
+ m->insertProperty(QCMakeProperty::PATH, "CMAKE_FIND_ROOT_PATH",
+ tr("CMake Find Root Path"), rootPath, false);
+
+ QString systemName = dialog.getSystemName();
+ m->insertProperty(QCMakeProperty::STRING, "CMAKE_SYSTEM_NAME",
+ tr("CMake System Name"), systemName, false);
+ QString systemVersion = dialog.getSystemVersion();
+ m->insertProperty(QCMakeProperty::STRING, "CMAKE_SYSTEM_VERSION",
+ tr("CMake System Version"), systemVersion, false);
+ QString cxxCompiler = dialog.getCXXCompiler();
+ m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_CXX_COMPILER",
+ tr("CXX compiler."), cxxCompiler, false);
+ QString cCompiler = dialog.getCCompiler();
+ m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_C_COMPILER",
+ tr("C compiler."), cCompiler, false);
+ } else if (dialog.crossCompilerToolChainFile()) {
+ QString toolchainFile = dialog.getCrossCompilerToolChainFile();
+ m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_TOOLCHAIN_FILE",
+ tr("Cross Compile ToolChain File"), toolchainFile,
+ false);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void CMakeSetupDialog::updateGeneratorLabel(const QString& gen)
+{
+ QString str = tr("Current Generator: ");
+ if (gen.isEmpty()) {
+ str += tr("None");
+ } else {
+ str += gen;
+ }
+ this->Generator->setText(str);
+}
+
+void CMakeSetupDialog::doReloadCache()
+{
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "reloadCache",
+ Qt::QueuedConnection);
+}
+
+void CMakeSetupDialog::doDeleteCache()
+{
+ QString title = tr("Delete Cache");
+ QString msg = tr("Are you sure you want to delete the cache?");
+ QMessageBox::StandardButton btn;
+ btn = QMessageBox::information(this, title, msg,
+ QMessageBox::Yes | QMessageBox::No);
+ if (btn == QMessageBox::No) {
+ return;
+ }
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "deleteCache",
+ Qt::QueuedConnection);
+}
+
+void CMakeSetupDialog::doAbout()
+{
+ QString msg = tr(
+ "CMake %1 (cmake.org).\n"
+ "CMake suite maintained and supported by Kitware (kitware.com/cmake).\n"
+ "Distributed under terms of the BSD 3-Clause License.\n"
+ "\n"
+ "CMake GUI maintained by csimsoft,\n"
+ "built using Qt %2 (qt-project.org).\n"
+#ifdef USE_LGPL
+ "\n"
+ "The Qt Toolkit is Copyright (C) Digia Plc and/or its subsidiary(-ies).\n"
+ "Qt is licensed under terms of the GNU LGPLv" USE_LGPL ", available at:\n"
+ " \"%3\""
+#endif
+ );
+ msg = msg.arg(cmVersion::GetCMakeVersion());
+ msg = msg.arg(qVersion());
+#ifdef USE_LGPL
+ std::string lgpl =
+ cmSystemTools::GetCMakeRoot() + "/Licenses/LGPLv" USE_LGPL ".txt";
+ msg = msg.arg(lgpl.c_str());
+#endif
+
+ QDialog dialog;
+ dialog.setWindowTitle(tr("About"));
+ QVBoxLayout* l = new QVBoxLayout(&dialog);
+ QLabel* lab = new QLabel(&dialog);
+ l->addWidget(lab);
+ lab->setText(msg);
+ lab->setWordWrap(true);
+ QDialogButtonBox* btns =
+ new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog);
+ QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
+ l->addWidget(btns);
+ dialog.exec();
+}
+
+void CMakeSetupDialog::setExitAfterGenerate(bool b)
+{
+ this->ExitAfterGenerate = b;
+}
+
+void CMakeSetupDialog::addBinaryPath(const QString& path)
+{
+ QString cleanpath = QDir::cleanPath(path);
+
+ // update UI
+ this->BinaryDirectory->blockSignals(true);
+ int idx = this->BinaryDirectory->findText(cleanpath);
+ if (idx != -1) {
+ this->BinaryDirectory->removeItem(idx);
+ }
+ this->BinaryDirectory->insertItem(0, cleanpath);
+ this->BinaryDirectory->setCurrentIndex(0);
+ this->BinaryDirectory->blockSignals(false);
+
+ // save to registry
+ QStringList buildPaths = this->loadBuildPaths();
+ buildPaths.removeAll(cleanpath);
+ buildPaths.prepend(cleanpath);
+ this->saveBuildPaths(buildPaths);
+}
+
+void CMakeSetupDialog::dragEnterEvent(QDragEnterEvent* e)
+{
+ if (!(this->CurrentState == ReadyConfigure ||
+ this->CurrentState == ReadyGenerate)) {
+ e->ignore();
+ return;
+ }
+
+ const QMimeData* dat = e->mimeData();
+ QList<QUrl> urls = dat->urls();
+ QString file = urls.count() ? urls[0].toLocalFile() : QString();
+ if (!file.isEmpty() &&
+ (file.endsWith("CMakeCache.txt", Qt::CaseInsensitive) ||
+ file.endsWith("CMakeLists.txt", Qt::CaseInsensitive))) {
+ e->accept();
+ } else {
+ e->ignore();
+ }
+}
+
+void CMakeSetupDialog::dropEvent(QDropEvent* e)
+{
+ if (!(this->CurrentState == ReadyConfigure ||
+ this->CurrentState == ReadyGenerate)) {
+ return;
+ }
+
+ const QMimeData* dat = e->mimeData();
+ QList<QUrl> urls = dat->urls();
+ QString file = urls.count() ? urls[0].toLocalFile() : QString();
+ if (file.endsWith("CMakeCache.txt", Qt::CaseInsensitive)) {
+ QFileInfo info(file);
+ if (this->CMakeThread->cmakeInstance()->binaryDirectory() !=
+ info.absolutePath()) {
+ this->setBinaryDirectory(info.absolutePath());
+ }
+ } else if (file.endsWith("CMakeLists.txt", Qt::CaseInsensitive)) {
+ QFileInfo info(file);
+ if (this->CMakeThread->cmakeInstance()->binaryDirectory() !=
+ info.absolutePath()) {
+ this->setSourceDirectory(info.absolutePath());
+ this->setBinaryDirectory(info.absolutePath());
+ }
+ }
+}
+
+QStringList CMakeSetupDialog::loadBuildPaths()
+{
+ QSettings settings;
+ settings.beginGroup("Settings/StartPath");
+
+ QStringList buildPaths;
+ for (int i = 0; i < 10; i++) {
+ QString p = settings.value(QString("WhereBuild%1").arg(i)).toString();
+ if (!p.isEmpty()) {
+ buildPaths.append(p);
+ }
+ }
+ return buildPaths;
+}
+
+void CMakeSetupDialog::saveBuildPaths(const QStringList& paths)
+{
+ QSettings settings;
+ settings.beginGroup("Settings/StartPath");
+
+ int num = paths.count();
+ if (num > 10) {
+ num = 10;
+ }
+
+ for (int i = 0; i < num; i++) {
+ settings.setValue(QString("WhereBuild%1").arg(i), paths[i]);
+ }
+}
+
+void CMakeSetupDialog::setCacheModified()
+{
+ this->CacheModified = true;
+ this->ConfigureNeeded = true;
+ this->enterState(ReadyConfigure);
+}
+
+void CMakeSetupDialog::removeSelectedCacheEntries()
+{
+ QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
+ QList<QPersistentModelIndex> pidxs;
+ foreach (QModelIndex i, idxs) {
+ pidxs.append(i);
+ }
+ foreach (QPersistentModelIndex pi, pidxs) {
+ this->CacheValues->model()->removeRow(pi.row(), pi.parent());
+ }
+}
+
+void CMakeSetupDialog::selectionChanged()
+{
+ QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
+ if (idxs.count() && (this->CurrentState == ReadyConfigure ||
+ this->CurrentState == ReadyGenerate)) {
+ this->RemoveEntry->setEnabled(true);
+ } else {
+ this->RemoveEntry->setEnabled(false);
+ }
+}
+
+void CMakeSetupDialog::enterState(CMakeSetupDialog::State s)
+{
+ if (s == this->CurrentState) {
+ return;
+ }
+
+ this->CurrentState = s;
+
+ if (s == Interrupting) {
+ this->ConfigureButton->setEnabled(false);
+ this->GenerateButton->setEnabled(false);
+ this->OpenProjectButton->setEnabled(false);
+ } else if (s == Configuring) {
+ this->setEnabledState(false);
+ this->GenerateButton->setEnabled(false);
+ this->GenerateAction->setEnabled(false);
+ this->OpenProjectButton->setEnabled(false);
+ this->ConfigureButton->setText(tr("&Stop"));
+ } else if (s == Generating) {
+ this->CacheModified = false;
+ this->setEnabledState(false);
+ this->ConfigureButton->setEnabled(false);
+ this->GenerateAction->setEnabled(false);
+ this->OpenProjectButton->setEnabled(false);
+ this->GenerateButton->setText(tr("&Stop"));
+ } else if (s == ReadyConfigure) {
+ this->setEnabledState(true);
+ this->GenerateButton->setEnabled(true);
+ this->GenerateAction->setEnabled(true);
+ this->ConfigureButton->setEnabled(true);
+ if (!this->getProjectFilename().isEmpty()) {
+ this->OpenProjectButton->setEnabled(true);
+ }
+ this->ConfigureButton->setText(tr("&Configure"));
+ this->GenerateButton->setText(tr("&Generate"));
+ } else if (s == ReadyGenerate) {
+ this->setEnabledState(true);
+ this->GenerateButton->setEnabled(true);
+ this->GenerateAction->setEnabled(true);
+ this->ConfigureButton->setEnabled(true);
+ if (!this->getProjectFilename().isEmpty()) {
+ this->OpenProjectButton->setEnabled(true);
+ }
+ this->ConfigureButton->setText(tr("&Configure"));
+ this->GenerateButton->setText(tr("&Generate"));
+ }
+}
+
+void CMakeSetupDialog::addCacheEntry()
+{
+ QDialog dialog(this);
+ dialog.resize(400, 200);
+ dialog.setWindowTitle(tr("Add Cache Entry"));
+ QVBoxLayout* l = new QVBoxLayout(&dialog);
+ AddCacheEntry* w =
+ new AddCacheEntry(&dialog, this->AddVariableNames, this->AddVariableTypes);
+ QDialogButtonBox* btns = new QDialogButtonBox(
+ QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
+ QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
+ QObject::connect(btns, SIGNAL(rejected()), &dialog, SLOT(reject()));
+ l->addWidget(w);
+ l->addStretch();
+ l->addWidget(btns);
+ if (QDialog::Accepted == dialog.exec()) {
+ QCMakeCacheModel* m = this->CacheValues->cacheModel();
+ m->insertProperty(w->type(), w->name(), w->description(), w->value(),
+ false);
+
+ // only add variable names to the completion which are new
+ if (!this->AddVariableNames.contains(w->name())) {
+ this->AddVariableNames << w->name();
+ this->AddVariableTypes << w->typeString();
+ // limit to at most 100 completion items
+ if (this->AddVariableNames.size() > 100) {
+ this->AddVariableNames.removeFirst();
+ this->AddVariableTypes.removeFirst();
+ }
+ // make sure CMAKE_INSTALL_PREFIX is always there
+ if (!this->AddVariableNames.contains("CMAKE_INSTALL_PREFIX")) {
+ this->AddVariableNames << "CMAKE_INSTALL_PREFIX";
+ this->AddVariableTypes << "PATH";
+ }
+ QSettings settings;
+ settings.beginGroup("Settings/StartPath");
+ settings.setValue("AddVariableNames", this->AddVariableNames);
+ settings.setValue("AddVariableTypes", this->AddVariableTypes);
+ }
+ }
+}
+
+void CMakeSetupDialog::startSearch()
+{
+ this->Search->setFocus(Qt::OtherFocusReason);
+ this->Search->selectAll();
+}
+
+void CMakeSetupDialog::setDebugOutput(bool flag)
+{
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
+ "setDebugOutput", Qt::QueuedConnection,
+ Q_ARG(bool, flag));
+}
+
+void CMakeSetupDialog::setGroupedView(bool v)
+{
+ this->CacheValues->cacheModel()->setViewType(v ? QCMakeCacheModel::GroupView
+ : QCMakeCacheModel::FlatView);
+ this->CacheValues->setRootIsDecorated(v);
+
+ QSettings settings;
+ settings.beginGroup("Settings/StartPath");
+ settings.setValue("GroupView", v);
+}
+
+void CMakeSetupDialog::setAdvancedView(bool v)
+{
+ this->CacheValues->setShowAdvanced(v);
+ QSettings settings;
+ settings.beginGroup("Settings/StartPath");
+ settings.setValue("AdvancedView", v);
+}
+
+void CMakeSetupDialog::showUserChanges()
+{
+ QSet<QCMakeProperty> changes =
+ qobject_cast<QCMakeCacheModelDelegate*>(this->CacheValues->itemDelegate())
+ ->changes();
+
+ QDialog dialog(this);
+ dialog.setWindowTitle(tr("My Changes"));
+ dialog.resize(600, 400);
+ QVBoxLayout* l = new QVBoxLayout(&dialog);
+ QTextEdit* textedit = new QTextEdit(&dialog);
+ textedit->setReadOnly(true);
+ l->addWidget(textedit);
+ QDialogButtonBox* btns =
+ new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, &dialog);
+ QObject::connect(btns, SIGNAL(rejected()), &dialog, SLOT(accept()));
+ l->addWidget(btns);
+
+ QString command;
+ QString cache;
+
+ foreach (QCMakeProperty prop, changes) {
+ QString type;
+ switch (prop.Type) {
+ case QCMakeProperty::BOOL:
+ type = "BOOL";
+ break;
+ case QCMakeProperty::PATH:
+ type = "PATH";
+ break;
+ case QCMakeProperty::FILEPATH:
+ type = "FILEPATH";
+ break;
+ case QCMakeProperty::STRING:
+ type = "STRING";
+ break;
+ }
+ QString value;
+ if (prop.Type == QCMakeProperty::BOOL) {
+ value = prop.Value.toBool() ? "1" : "0";
+ } else {
+ value = prop.Value.toString();
+ }
+
+ QString line("%1:%2=");
+ line = line.arg(prop.Key);
+ line = line.arg(type);
+
+ command += QString("-D%1\"%2\" ").arg(line).arg(value);
+ cache += QString("%1%2\n").arg(line).arg(value);
+ }
+
+ textedit->append(tr("Commandline options:"));
+ textedit->append(command);
+ textedit->append("\n");
+ textedit->append(tr("Cache file:"));
+ textedit->append(cache);
+
+ dialog.exec();
+}
+
+void CMakeSetupDialog::setSearchFilter(const QString& str)
+{
+ this->CacheValues->selectionModel()->clear();
+ this->CacheValues->setSearchFilter(str);
+}
+
+void CMakeSetupDialog::doOutputContextMenu(const QPoint& pt)
+{
+ QMenu* menu = this->Output->createStandardContextMenu();
+
+ menu->addSeparator();
+ menu->addAction(tr("Find..."), this, SLOT(doOutputFindDialog()),
+ QKeySequence::Find);
+ menu->addAction(tr("Find Next"), this, SLOT(doOutputFindNext()),
+ QKeySequence::FindNext);
+ menu->addAction(tr("Find Previous"), this, SLOT(doOutputFindPrev()),
+ QKeySequence::FindPrevious);
+ menu->addSeparator();
+ menu->addAction(tr("Goto Next Error"), this, SLOT(doOutputErrorNext()),
+ QKeySequence(Qt::Key_F8));
+
+ menu->exec(this->Output->mapToGlobal(pt));
+ delete menu;
+}
+
+void CMakeSetupDialog::doOutputFindDialog()
+{
+ QStringList strings(this->FindHistory);
+
+ QString selection = this->Output->textCursor().selectedText();
+ if (!selection.isEmpty() && !selection.contains(QChar::ParagraphSeparator) &&
+ !selection.contains(QChar::LineSeparator)) {
+ strings.push_front(selection);
+ }
+
+ bool ok;
+ QString search = QInputDialog::getItem(this, tr("Find in Output"),
+ tr("Find:"), strings, 0, true, &ok);
+ if (ok && !search.isEmpty()) {
+ if (!this->FindHistory.contains(search)) {
+ this->FindHistory.push_front(search);
+ }
+ doOutputFindNext();
+ }
+}
+
+void CMakeSetupDialog::doRegexExplorerDialog()
+{
+ RegexExplorer dialog(this);
+ dialog.exec();
+}
+
+void CMakeSetupDialog::doOutputFindPrev()
+{
+ doOutputFindNext(false);
+}
+
+void CMakeSetupDialog::doOutputFindNext(bool directionForward)
+{
+ if (this->FindHistory.isEmpty()) {
+ doOutputFindDialog(); // will re-call this function again
+ return;
+ }
+
+ QString search = this->FindHistory.front();
+
+ QTextCursor textCursor = this->Output->textCursor();
+ QTextDocument* document = this->Output->document();
+ QTextDocument::FindFlags flags;
+ if (!directionForward) {
+ flags |= QTextDocument::FindBackward;
+ }
+
+ textCursor = document->find(search, textCursor, flags);
+
+ if (textCursor.isNull()) {
+ // first search found nothing, wrap around and search again
+ textCursor = this->Output->textCursor();
+ textCursor.movePosition(directionForward ? QTextCursor::Start
+ : QTextCursor::End);
+ textCursor = document->find(search, textCursor, flags);
+ }
+
+ if (textCursor.hasSelection()) {
+ this->Output->setTextCursor(textCursor);
+ }
+}
+
+void CMakeSetupDialog::doOutputErrorNext()
+{
+ QTextCursor textCursor = this->Output->textCursor();
+ bool atEnd = false;
+
+ // move cursor out of current error-block
+ if (textCursor.blockCharFormat() == this->ErrorFormat) {
+ atEnd = !textCursor.movePosition(QTextCursor::NextBlock);
+ }
+
+ // move cursor to next error-block
+ while (textCursor.blockCharFormat() != this->ErrorFormat && !atEnd) {
+ atEnd = !textCursor.movePosition(QTextCursor::NextBlock);
+ }
+
+ if (atEnd) {
+ // first search found nothing, wrap around and search again
+ atEnd = !textCursor.movePosition(QTextCursor::Start);
+
+ // move cursor to next error-block
+ while (textCursor.blockCharFormat() != this->ErrorFormat && !atEnd) {
+ atEnd = !textCursor.movePosition(QTextCursor::NextBlock);
+ }
+ }
+
+ if (!atEnd) {
+ textCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
+
+ QTextCharFormat selectionFormat;
+ selectionFormat.setBackground(Qt::yellow);
+ QTextEdit::ExtraSelection extraSelection = { textCursor, selectionFormat };
+ this->Output->setExtraSelections(QList<QTextEdit::ExtraSelection>()
+ << extraSelection);
+
+ // make the whole error-block visible
+ this->Output->setTextCursor(textCursor);
+
+ // remove the selection to see the extraSelection
+ textCursor.setPosition(textCursor.anchor());
+ this->Output->setTextCursor(textCursor);
+ }
+}
+
+void CMakeSetupDialog::doWarningMessagesDialog()
+{
+ WarningMessagesDialog dialog(this, this->CMakeThread->cmakeInstance());
+ dialog.exec();
+}
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
new file mode 100644
index 0000000..1abdb46
--- /dev/null
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -0,0 +1,140 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef CMakeSetupDialog_h
+#define CMakeSetupDialog_h
+
+#include "QCMake.h"
+
+#include "ui_CMakeSetupDialog.h"
+#include <QEventLoop>
+#include <QMainWindow>
+#include <QThread>
+
+class QCMakeThread;
+class CMakeCacheModel;
+class QProgressBar;
+class QToolButton;
+
+/// Qt user interface for CMake
+class CMakeSetupDialog : public QMainWindow, public Ui::CMakeSetupDialog
+{
+ Q_OBJECT
+public:
+ CMakeSetupDialog();
+ ~CMakeSetupDialog();
+
+public slots:
+ void setBinaryDirectory(const QString& dir);
+ void setSourceDirectory(const QString& dir);
+
+protected slots:
+ void initialize();
+ void doConfigure();
+ void doGenerate();
+ QString getProjectFilename();
+ void doOpenProject();
+ void doInstallForCommandLine();
+ void doHelp();
+ void doAbout();
+ void doInterrupt();
+ void error(const QString& message);
+ void message(const QString& message);
+
+ void doSourceBrowse();
+ void doBinaryBrowse();
+ void doReloadCache();
+ void doDeleteCache();
+ void updateSourceDirectory(const QString& dir);
+ void updateBinaryDirectory(const QString& dir);
+ void showProgress(const QString& msg, float percent);
+ void setEnabledState(bool);
+ bool setupFirstConfigure();
+ void updateGeneratorLabel(const QString& gen);
+ void setExitAfterGenerate(bool);
+ void addBinaryPath(const QString&);
+ QStringList loadBuildPaths();
+ void saveBuildPaths(const QStringList&);
+ void onBinaryDirectoryChanged(const QString& dir);
+ void onSourceDirectoryChanged(const QString& dir);
+ void setCacheModified();
+ void removeSelectedCacheEntries();
+ void selectionChanged();
+ void addCacheEntry();
+ void startSearch();
+ void setDebugOutput(bool);
+ void setAdvancedView(bool);
+ void setGroupedView(bool);
+ void showUserChanges();
+ void setSearchFilter(const QString& str);
+ bool prepareConfigure();
+ bool doConfigureInternal();
+ bool doGenerateInternal();
+ void exitLoop(int);
+ void doOutputContextMenu(const QPoint&);
+ void doOutputFindDialog();
+ void doOutputFindNext(bool directionForward = true);
+ void doOutputFindPrev();
+ void doOutputErrorNext();
+ void doRegexExplorerDialog();
+ /// display the modal warning messages dialog window
+ void doWarningMessagesDialog();
+
+protected:
+ enum State
+ {
+ Interrupting,
+ ReadyConfigure,
+ ReadyGenerate,
+ Configuring,
+ Generating
+ };
+ void enterState(State s);
+
+ void closeEvent(QCloseEvent*);
+ void dragEnterEvent(QDragEnterEvent*);
+ void dropEvent(QDropEvent*);
+
+ QCMakeThread* CMakeThread;
+ bool ExitAfterGenerate;
+ bool CacheModified;
+ bool ConfigureNeeded;
+ QAction* ReloadCacheAction;
+ QAction* DeleteCacheAction;
+ QAction* ExitAction;
+ QAction* ConfigureAction;
+ QAction* GenerateAction;
+ QAction* WarnUninitializedAction;
+ QAction* WarnUnusedAction;
+ QAction* InstallForCommandLineAction;
+ State CurrentState;
+
+ QTextCharFormat ErrorFormat;
+ QTextCharFormat MessageFormat;
+
+ QStringList AddVariableNames;
+ QStringList AddVariableTypes;
+ QStringList FindHistory;
+
+ QEventLoop LocalLoop;
+
+ float ProgressOffset;
+ float ProgressFactor;
+};
+
+// QCMake instance on a thread
+class QCMakeThread : public QThread
+{
+ Q_OBJECT
+public:
+ QCMakeThread(QObject* p);
+ QCMake* cmakeInstance() const;
+
+signals:
+ void cmakeInitialized();
+
+protected:
+ virtual void run();
+ QCMake* CMakeInstance;
+};
+
+#endif // CMakeSetupDialog_h
diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui
new file mode 100644
index 0000000..8d8e0cd
--- /dev/null
+++ b/Source/QtDialog/CMakeSetupDialog.ui
@@ -0,0 +1,320 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CMakeSetupDialog</class>
+ <widget class="QWidget" name="CMakeSetupDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>707</width>
+ <height>582</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>9</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="0" column="0">
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Where is the source code:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="SourceDirectory"/>
+ </item>
+ <item row="0" column="2">
+ <widget class="QPushButton" name="BrowseSourceDirectoryButton">
+ <property name="text">
+ <string>Browse &amp;Source...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Where to build the binaries:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="BinaryDirectory">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Ignored" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="BrowseBinaryDirectoryButton">
+ <property name="text">
+ <string>Browse &amp;Build...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QSplitter" name="Splitter">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>S&amp;earch:</string>
+ </property>
+ <property name="buddy">
+ <cstring>Search</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="Search">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>12</width>
+ <height>23</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="groupedCheck">
+ <property name="text">
+ <string>Grouped</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="advancedCheck">
+ <property name="text">
+ <string>Advanced</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="AddEntry">
+ <property name="toolTip">
+ <string>Add New Entry</string>
+ </property>
+ <property name="text">
+ <string>&amp;Add Entry</string>
+ </property>
+ <property name="icon">
+ <iconset resource="CMakeSetup.qrc">
+ <normaloff>:/Icons/Plus16.png</normaloff>:/Icons/Plus16.png</iconset>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="RemoveEntry">
+ <property name="toolTip">
+ <string>Remove Selected Entries</string>
+ </property>
+ <property name="text">
+ <string>&amp;Remove Entry</string>
+ </property>
+ <property name="icon">
+ <iconset resource="CMakeSetup.qrc">
+ <normaloff>:/Icons/Delete16.png</normaloff>:/Icons/Delete16.png</iconset>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCMakeCacheView" name="CacheValues">
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::ExtendedSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Press Configure to update and display new values in red, then press Generate to generate selected build files.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="ConfigureButton">
+ <property name="text">
+ <string>&amp;Configure</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="GenerateButton">
+ <property name="text">
+ <string>&amp;Generate</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="OpenProjectButton">
+ <property name="text">
+ <string>Open &amp;Project</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="Generator">
+ <property name="text">
+ <string>Current Generator:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>121</width>
+ <height>27</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="ProgressBar">
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ <property name="textVisible">
+ <bool>false</bool>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="textDirection">
+ <enum>QProgressBar::BottomToTop</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QTextEdit" name="Output">
+ <property name="lineWrapMode">
+ <enum>QTextEdit::NoWrap</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QCMakeCacheView</class>
+ <extends>QTreeView</extends>
+ <header>QCMakeCacheView.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="CMakeSetup.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/Source/QtDialog/Compilers.h b/Source/QtDialog/Compilers.h
new file mode 100644
index 0000000..276e2a5
--- /dev/null
+++ b/Source/QtDialog/Compilers.h
@@ -0,0 +1,23 @@
+
+
+#ifndef COMPILERS_HPP
+#define COMPILERS_HPP
+
+#include <cmConfigure.h>
+
+#include <QWidget>
+
+#include <ui_Compilers.h>
+
+class Compilers : public QWidget, public Ui::Compilers
+{
+ Q_OBJECT
+public:
+ Compilers(QWidget* p = CM_NULLPTR)
+ : QWidget(p)
+ {
+ this->setupUi(this);
+ }
+};
+
+#endif
diff --git a/Source/QtDialog/Compilers.ui b/Source/QtDialog/Compilers.ui
new file mode 100644
index 0000000..41f70ac
--- /dev/null
+++ b/Source/QtDialog/Compilers.ui
@@ -0,0 +1,87 @@
+<ui version="4.0" >
+ <class>Compilers</class>
+ <widget class="QWidget" name="Compilers" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>506</width>
+ <height>115</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="groupBox_4" >
+ <property name="title" >
+ <string>Compilers</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="leftMargin" >
+ <number>4</number>
+ </property>
+ <property name="topMargin" >
+ <number>4</number>
+ </property>
+ <property name="rightMargin" >
+ <number>4</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_16" >
+ <property name="text" >
+ <string>C</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QCMakeFilePathEditor" name="CCompiler" />
+ </item>
+ <item row="0" column="2" >
+ <widget class="QLabel" name="label_17" >
+ <property name="text" >
+ <string>C++</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3" >
+ <widget class="QCMakeFilePathEditor" name="CXXCompiler" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_18" >
+ <property name="text" >
+ <string>Fortran</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QCMakeFilePathEditor" name="FortranCompiler" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QCMakeFilePathEditor</class>
+ <extends>QLineEdit</extends>
+ <header>QCMakeWidgets.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Source/QtDialog/CrossCompiler.ui b/Source/QtDialog/CrossCompiler.ui
new file mode 100644
index 0000000..1fb1ebf
--- /dev/null
+++ b/Source/QtDialog/CrossCompiler.ui
@@ -0,0 +1,213 @@
+<ui version="4.0" >
+ <class>CrossCompiler</class>
+ <widget class="QWidget" name="CrossCompiler" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>433</width>
+ <height>319</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>CrossCompiler</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Target System</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_6" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Operating System</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="systemName" />
+ </item>
+ <item row="0" column="2" colspan="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_10" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Version</string>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="systemVersion" />
+ </item>
+ <item row="1" column="2" >
+ <widget class="QLabel" name="label_11" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Processor</string>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <widget class="QLineEdit" name="systemProcessor" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Find Program/Library/Include</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_9" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Target Root</string>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QCMakePathEditor" name="crossFindRoot" />
+ </item>
+ <item row="0" column="2" >
+ <widget class="QLabel" name="label_12" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Program Mode</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3" >
+ <widget class="QComboBox" name="crossProgramMode" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_13" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Library Mode</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QComboBox" name="crossLibraryMode" />
+ </item>
+ <item row="1" column="2" >
+ <widget class="QLabel" name="label_14" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Include Mode</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <widget class="QComboBox" name="crossIncludeMode" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="Compilers" native="1" name="CrossCompilers" >
+ <property name="focusPolicy" >
+ <enum>Qt::TabFocus</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QCMakePathEditor</class>
+ <extends>QLineEdit</extends>
+ <header>QCMakeWidgets.h</header>
+ </customwidget>
+ <customwidget>
+ <class>Compilers</class>
+ <extends>QWidget</extends>
+ <header>Compilers.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>systemVersion</tabstop>
+ <tabstop>systemProcessor</tabstop>
+ <tabstop>CrossCompilers</tabstop>
+ <tabstop>crossFindRoot</tabstop>
+ <tabstop>crossProgramMode</tabstop>
+ <tabstop>crossLibraryMode</tabstop>
+ <tabstop>crossIncludeMode</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Source/QtDialog/Delete16.png b/Source/QtDialog/Delete16.png
new file mode 100644
index 0000000..16989fee
--- /dev/null
+++ b/Source/QtDialog/Delete16.png
Binary files differ
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx
new file mode 100644
index 0000000..c34751a
--- /dev/null
+++ b/Source/QtDialog/FirstConfigure.cxx
@@ -0,0 +1,581 @@
+
+#include "FirstConfigure.h"
+
+#include "Compilers.h"
+
+#include <QComboBox>
+#include <QRadioButton>
+#include <QSettings>
+#include <QVBoxLayout>
+
+StartCompilerSetup::StartCompilerSetup(QWidget* p)
+ : QWizardPage(p)
+{
+ QVBoxLayout* l = new QVBoxLayout(this);
+ l->addWidget(new QLabel(tr("Specify the generator for this project")));
+ this->GeneratorOptions = new QComboBox(this);
+ l->addWidget(this->GeneratorOptions);
+
+ // Add the ability to specify toolset (-T parameter)
+ ToolsetFrame = CreateToolsetWidgets();
+ l->addWidget(ToolsetFrame);
+
+ l->addSpacing(6);
+
+ this->CompilerSetupOptions[0] =
+ new QRadioButton(tr("Use default native compilers"), this);
+ this->CompilerSetupOptions[1] =
+ new QRadioButton(tr("Specify native compilers"), this);
+ this->CompilerSetupOptions[2] =
+ new QRadioButton(tr("Specify toolchain file for cross-compiling"), this);
+ this->CompilerSetupOptions[3] =
+ new QRadioButton(tr("Specify options for cross-compiling"), this);
+ l->addWidget(this->CompilerSetupOptions[0]);
+ l->addWidget(this->CompilerSetupOptions[1]);
+ l->addWidget(this->CompilerSetupOptions[2]);
+ l->addWidget(this->CompilerSetupOptions[3]);
+
+ this->CompilerSetupOptions[0]->setChecked(true);
+
+ QObject::connect(this->CompilerSetupOptions[0], SIGNAL(toggled(bool)), this,
+ SLOT(onSelectionChanged(bool)));
+ QObject::connect(this->CompilerSetupOptions[1], SIGNAL(toggled(bool)), this,
+ SLOT(onSelectionChanged(bool)));
+ QObject::connect(this->CompilerSetupOptions[2], SIGNAL(toggled(bool)), this,
+ SLOT(onSelectionChanged(bool)));
+ QObject::connect(this->CompilerSetupOptions[3], SIGNAL(toggled(bool)), this,
+ SLOT(onSelectionChanged(bool)));
+ QObject::connect(GeneratorOptions,
+ SIGNAL(currentIndexChanged(QString const&)), this,
+ SLOT(onGeneratorChanged(QString const&)));
+}
+
+QFrame* StartCompilerSetup::CreateToolsetWidgets()
+{
+ QFrame* frame = new QFrame(this);
+ QVBoxLayout* l = new QVBoxLayout(frame);
+ l->setContentsMargins(0, 0, 0, 0);
+
+ ToolsetLabel = new QLabel(tr("Optional toolset to use (-T parameter)"));
+ l->addWidget(ToolsetLabel);
+
+ Toolset = new QLineEdit(frame);
+ l->addWidget(Toolset);
+
+ return frame;
+}
+
+StartCompilerSetup::~StartCompilerSetup()
+{
+}
+
+void StartCompilerSetup::setGenerators(
+ std::vector<cmake::GeneratorInfo> const& gens)
+{
+ this->GeneratorOptions->clear();
+
+ QStringList generator_list;
+
+ std::vector<cmake::GeneratorInfo>::const_iterator it;
+ for (it = gens.begin(); it != gens.end(); ++it) {
+ generator_list.append(QString::fromLocal8Bit(it->name.c_str()));
+
+ if (it->supportsToolset) {
+ this->GeneratorsSupportingToolset.append(
+ QString::fromLocal8Bit(it->name.c_str()));
+ }
+ }
+
+ this->GeneratorOptions->addItems(generator_list);
+}
+
+void StartCompilerSetup::setCurrentGenerator(const QString& gen)
+{
+ int idx = this->GeneratorOptions->findText(gen);
+ if (idx != -1) {
+ this->GeneratorOptions->setCurrentIndex(idx);
+ }
+}
+
+QString StartCompilerSetup::getGenerator() const
+{
+ return this->GeneratorOptions->currentText();
+};
+
+QString StartCompilerSetup::getToolset() const
+{
+ return this->Toolset->text();
+};
+
+bool StartCompilerSetup::defaultSetup() const
+{
+ return this->CompilerSetupOptions[0]->isChecked();
+}
+
+bool StartCompilerSetup::compilerSetup() const
+{
+ return this->CompilerSetupOptions[1]->isChecked();
+}
+
+bool StartCompilerSetup::crossCompilerToolChainFile() const
+{
+ return this->CompilerSetupOptions[2]->isChecked();
+}
+
+bool StartCompilerSetup::crossCompilerSetup() const
+{
+ return this->CompilerSetupOptions[3]->isChecked();
+}
+
+void StartCompilerSetup::onSelectionChanged(bool on)
+{
+ if (on) {
+ selectionChanged();
+ }
+}
+
+void StartCompilerSetup::onGeneratorChanged(QString const& name)
+{
+ if (GeneratorsSupportingToolset.contains(name)) {
+ ToolsetFrame->show();
+ } else {
+ ToolsetFrame->hide();
+ }
+}
+
+int StartCompilerSetup::nextId() const
+{
+ if (compilerSetup()) {
+ return NativeSetup;
+ }
+ if (crossCompilerSetup()) {
+ return CrossSetup;
+ }
+ if (crossCompilerToolChainFile()) {
+ return ToolchainSetup;
+ }
+ return -1;
+}
+
+NativeCompilerSetup::NativeCompilerSetup(QWidget* p)
+ : QWizardPage(p)
+{
+ QVBoxLayout* l = new QVBoxLayout(this);
+ QWidget* c = new QWidget(this);
+ l->addWidget(c);
+ this->setupUi(c);
+}
+
+NativeCompilerSetup::~NativeCompilerSetup()
+{
+}
+
+QString NativeCompilerSetup::getCCompiler() const
+{
+ return this->CCompiler->text();
+}
+
+void NativeCompilerSetup::setCCompiler(const QString& s)
+{
+ this->CCompiler->setText(s);
+}
+
+QString NativeCompilerSetup::getCXXCompiler() const
+{
+ return this->CXXCompiler->text();
+}
+
+void NativeCompilerSetup::setCXXCompiler(const QString& s)
+{
+ this->CXXCompiler->setText(s);
+}
+
+QString NativeCompilerSetup::getFortranCompiler() const
+{
+ return this->FortranCompiler->text();
+}
+
+void NativeCompilerSetup::setFortranCompiler(const QString& s)
+{
+ this->FortranCompiler->setText(s);
+}
+
+CrossCompilerSetup::CrossCompilerSetup(QWidget* p)
+ : QWizardPage(p)
+{
+ this->setupUi(this);
+ QWidget::setTabOrder(systemName, systemVersion);
+ QWidget::setTabOrder(systemVersion, systemProcessor);
+ QWidget::setTabOrder(systemProcessor, CrossCompilers->CCompiler);
+ QWidget::setTabOrder(CrossCompilers->CCompiler, CrossCompilers->CXXCompiler);
+ QWidget::setTabOrder(CrossCompilers->CXXCompiler,
+ CrossCompilers->FortranCompiler);
+ QWidget::setTabOrder(CrossCompilers->FortranCompiler, crossFindRoot);
+ QWidget::setTabOrder(crossFindRoot, crossProgramMode);
+ QWidget::setTabOrder(crossProgramMode, crossLibraryMode);
+ QWidget::setTabOrder(crossLibraryMode, crossIncludeMode);
+
+ // fill in combo boxes
+ QStringList modes;
+ modes << tr("Search in Target Root, then native system");
+ modes << tr("Search only in Target Root");
+ modes << tr("Search only in native system");
+ crossProgramMode->addItems(modes);
+ crossLibraryMode->addItems(modes);
+ crossIncludeMode->addItems(modes);
+ crossProgramMode->setCurrentIndex(2);
+ crossLibraryMode->setCurrentIndex(1);
+ crossIncludeMode->setCurrentIndex(1);
+
+ this->registerField("systemName*", this->systemName);
+}
+
+CrossCompilerSetup::~CrossCompilerSetup()
+{
+}
+
+QString CrossCompilerSetup::getCCompiler() const
+{
+ return this->CrossCompilers->CCompiler->text();
+}
+
+void CrossCompilerSetup::setCCompiler(const QString& s)
+{
+ this->CrossCompilers->CCompiler->setText(s);
+}
+
+QString CrossCompilerSetup::getCXXCompiler() const
+{
+ return this->CrossCompilers->CXXCompiler->text();
+}
+
+void CrossCompilerSetup::setCXXCompiler(const QString& s)
+{
+ this->CrossCompilers->CXXCompiler->setText(s);
+}
+
+QString CrossCompilerSetup::getFortranCompiler() const
+{
+ return this->CrossCompilers->FortranCompiler->text();
+}
+
+void CrossCompilerSetup::setFortranCompiler(const QString& s)
+{
+ this->CrossCompilers->FortranCompiler->setText(s);
+}
+
+QString CrossCompilerSetup::getSystem() const
+{
+ return this->systemName->text();
+}
+
+void CrossCompilerSetup::setSystem(const QString& t)
+{
+ this->systemName->setText(t);
+}
+
+QString CrossCompilerSetup::getVersion() const
+{
+ return this->systemVersion->text();
+}
+
+void CrossCompilerSetup::setVersion(const QString& t)
+{
+ this->systemVersion->setText(t);
+}
+
+QString CrossCompilerSetup::getProcessor() const
+{
+ return this->systemProcessor->text();
+}
+
+void CrossCompilerSetup::setProcessor(const QString& t)
+{
+ this->systemProcessor->setText(t);
+}
+
+QString CrossCompilerSetup::getFindRoot() const
+{
+ return this->crossFindRoot->text();
+}
+
+void CrossCompilerSetup::setFindRoot(const QString& t)
+{
+ return this->crossFindRoot->setText(t);
+}
+
+int CrossCompilerSetup::getProgramMode() const
+{
+ return this->crossProgramMode->currentIndex();
+}
+
+int CrossCompilerSetup::getLibraryMode() const
+{
+ return this->crossLibraryMode->currentIndex();
+}
+
+int CrossCompilerSetup::getIncludeMode() const
+{
+ return this->crossIncludeMode->currentIndex();
+}
+
+void CrossCompilerSetup::setProgramMode(int m)
+{
+ this->crossProgramMode->setCurrentIndex(m);
+}
+
+void CrossCompilerSetup::setLibraryMode(int m)
+{
+ this->crossLibraryMode->setCurrentIndex(m);
+}
+
+void CrossCompilerSetup::setIncludeMode(int m)
+{
+ this->crossIncludeMode->setCurrentIndex(m);
+}
+
+ToolchainCompilerSetup::ToolchainCompilerSetup(QWidget* p)
+ : QWizardPage(p)
+{
+ QVBoxLayout* l = new QVBoxLayout(this);
+ l->addWidget(new QLabel(tr("Specify the Toolchain file")));
+ this->ToolchainFile = new QCMakeFilePathEditor(this);
+ l->addWidget(this->ToolchainFile);
+}
+
+ToolchainCompilerSetup::~ToolchainCompilerSetup()
+{
+}
+
+QString ToolchainCompilerSetup::toolchainFile() const
+{
+ return this->ToolchainFile->text();
+}
+
+void ToolchainCompilerSetup::setToolchainFile(const QString& t)
+{
+ this->ToolchainFile->setText(t);
+}
+
+FirstConfigure::FirstConfigure()
+{
+ // this->setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
+ this->mStartCompilerSetupPage = new StartCompilerSetup(this);
+ this->setPage(Start, this->mStartCompilerSetupPage);
+ QObject::connect(this->mStartCompilerSetupPage, SIGNAL(selectionChanged()),
+ this, SLOT(restart()));
+
+ this->mNativeCompilerSetupPage = new NativeCompilerSetup(this);
+ this->setPage(NativeSetup, this->mNativeCompilerSetupPage);
+
+ this->mCrossCompilerSetupPage = new CrossCompilerSetup(this);
+ this->setPage(CrossSetup, this->mCrossCompilerSetupPage);
+
+ this->mToolchainCompilerSetupPage = new ToolchainCompilerSetup(this);
+ this->setPage(ToolchainSetup, this->mToolchainCompilerSetupPage);
+}
+
+FirstConfigure::~FirstConfigure()
+{
+}
+
+void FirstConfigure::setGenerators(
+ std::vector<cmake::GeneratorInfo> const& gens)
+{
+ this->mStartCompilerSetupPage->setGenerators(gens);
+}
+
+QString FirstConfigure::getGenerator() const
+{
+ return this->mStartCompilerSetupPage->getGenerator();
+}
+
+QString FirstConfigure::getToolset() const
+{
+ return this->mStartCompilerSetupPage->getToolset();
+}
+
+void FirstConfigure::loadFromSettings()
+{
+ QSettings settings;
+ // restore generator
+ settings.beginGroup("Settings/StartPath");
+ QString lastGen = settings.value("LastGenerator").toString();
+ this->mStartCompilerSetupPage->setCurrentGenerator(lastGen);
+ settings.endGroup();
+
+ // restore compiler setup
+ settings.beginGroup("Settings/Compiler");
+ this->mNativeCompilerSetupPage->setCCompiler(
+ settings.value("CCompiler").toString());
+ this->mNativeCompilerSetupPage->setCXXCompiler(
+ settings.value("CXXCompiler").toString());
+ this->mNativeCompilerSetupPage->setFortranCompiler(
+ settings.value("FortranCompiler").toString());
+ settings.endGroup();
+
+ // restore cross compiler setup
+ settings.beginGroup("Settings/CrossCompiler");
+ this->mCrossCompilerSetupPage->setCCompiler(
+ settings.value("CCompiler").toString());
+ this->mCrossCompilerSetupPage->setCXXCompiler(
+ settings.value("CXXCompiler").toString());
+ this->mCrossCompilerSetupPage->setFortranCompiler(
+ settings.value("FortranCompiler").toString());
+ this->mToolchainCompilerSetupPage->setToolchainFile(
+ settings.value("ToolChainFile").toString());
+ this->mCrossCompilerSetupPage->setSystem(
+ settings.value("SystemName").toString());
+ this->mCrossCompilerSetupPage->setVersion(
+ settings.value("SystemVersion").toString());
+ this->mCrossCompilerSetupPage->setProcessor(
+ settings.value("SystemProcessor").toString());
+ this->mCrossCompilerSetupPage->setFindRoot(
+ settings.value("FindRoot").toString());
+ this->mCrossCompilerSetupPage->setProgramMode(
+ settings.value("ProgramMode", 0).toInt());
+ this->mCrossCompilerSetupPage->setLibraryMode(
+ settings.value("LibraryMode", 0).toInt());
+ this->mCrossCompilerSetupPage->setIncludeMode(
+ settings.value("IncludeMode", 0).toInt());
+ settings.endGroup();
+}
+
+void FirstConfigure::saveToSettings()
+{
+ QSettings settings;
+
+ // save generator
+ settings.beginGroup("Settings/StartPath");
+ QString lastGen = this->mStartCompilerSetupPage->getGenerator();
+ settings.setValue("LastGenerator", lastGen);
+ settings.endGroup();
+
+ // save compiler setup
+ settings.beginGroup("Settings/Compiler");
+ settings.setValue("CCompiler",
+ this->mNativeCompilerSetupPage->getCCompiler());
+ settings.setValue("CXXCompiler",
+ this->mNativeCompilerSetupPage->getCXXCompiler());
+ settings.setValue("FortranCompiler",
+ this->mNativeCompilerSetupPage->getFortranCompiler());
+ settings.endGroup();
+
+ // save cross compiler setup
+ settings.beginGroup("Settings/CrossCompiler");
+ settings.setValue("CCompiler",
+ this->mCrossCompilerSetupPage->getCCompiler());
+ settings.setValue("CXXCompiler",
+ this->mCrossCompilerSetupPage->getCXXCompiler());
+ settings.setValue("FortranCompiler",
+ this->mCrossCompilerSetupPage->getFortranCompiler());
+ settings.setValue("ToolChainFile", this->getCrossCompilerToolChainFile());
+ settings.setValue("SystemName", this->mCrossCompilerSetupPage->getSystem());
+ settings.setValue("SystemVersion",
+ this->mCrossCompilerSetupPage->getVersion());
+ settings.setValue("SystemProcessor",
+ this->mCrossCompilerSetupPage->getProcessor());
+ settings.setValue("FindRoot", this->mCrossCompilerSetupPage->getFindRoot());
+ settings.setValue("ProgramMode",
+ this->mCrossCompilerSetupPage->getProgramMode());
+ settings.setValue("LibraryMode",
+ this->mCrossCompilerSetupPage->getLibraryMode());
+ settings.setValue("IncludeMode",
+ this->mCrossCompilerSetupPage->getIncludeMode());
+ settings.endGroup();
+}
+
+bool FirstConfigure::defaultSetup() const
+{
+ return this->mStartCompilerSetupPage->defaultSetup();
+}
+
+bool FirstConfigure::compilerSetup() const
+{
+ return this->mStartCompilerSetupPage->compilerSetup();
+}
+
+bool FirstConfigure::crossCompilerSetup() const
+{
+ return this->mStartCompilerSetupPage->crossCompilerSetup();
+}
+
+bool FirstConfigure::crossCompilerToolChainFile() const
+{
+ return this->mStartCompilerSetupPage->crossCompilerToolChainFile();
+}
+
+QString FirstConfigure::getCrossCompilerToolChainFile() const
+{
+ return this->mToolchainCompilerSetupPage->toolchainFile();
+}
+
+QString FirstConfigure::getSystemName() const
+{
+ return this->mCrossCompilerSetupPage->getSystem();
+}
+
+QString FirstConfigure::getCCompiler() const
+{
+ if (this->compilerSetup()) {
+ return this->mNativeCompilerSetupPage->getCCompiler();
+ }
+ if (this->crossCompilerSetup()) {
+ return this->mCrossCompilerSetupPage->getCCompiler();
+ }
+ return QString();
+}
+
+QString FirstConfigure::getCXXCompiler() const
+{
+ if (this->compilerSetup()) {
+ return this->mNativeCompilerSetupPage->getCXXCompiler();
+ }
+ if (this->crossCompilerSetup()) {
+ return this->mCrossCompilerSetupPage->getCXXCompiler();
+ }
+ return QString();
+}
+
+QString FirstConfigure::getFortranCompiler() const
+{
+ if (this->compilerSetup()) {
+ return this->mNativeCompilerSetupPage->getFortranCompiler();
+ }
+ if (this->crossCompilerSetup()) {
+ return this->mCrossCompilerSetupPage->getFortranCompiler();
+ }
+ return QString();
+}
+
+QString FirstConfigure::getSystemVersion() const
+{
+ return this->mCrossCompilerSetupPage->getVersion();
+}
+
+QString FirstConfigure::getSystemProcessor() const
+{
+ return this->mCrossCompilerSetupPage->getProcessor();
+}
+
+QString FirstConfigure::getCrossRoot() const
+{
+ return this->mCrossCompilerSetupPage->getFindRoot();
+}
+
+const QString CrossModes[] = { "BOTH", "ONLY", "NEVER" };
+
+QString FirstConfigure::getCrossProgramMode() const
+{
+ return CrossModes[this->mCrossCompilerSetupPage->getProgramMode()];
+}
+
+QString FirstConfigure::getCrossLibraryMode() const
+{
+ return CrossModes[this->mCrossCompilerSetupPage->getLibraryMode()];
+}
+
+QString FirstConfigure::getCrossIncludeMode() const
+{
+ return CrossModes[this->mCrossCompilerSetupPage->getIncludeMode()];
+}
diff --git a/Source/QtDialog/FirstConfigure.h b/Source/QtDialog/FirstConfigure.h
new file mode 100644
index 0000000..c467ddb
--- /dev/null
+++ b/Source/QtDialog/FirstConfigure.h
@@ -0,0 +1,189 @@
+
+#ifndef FirstConfigure_h
+#define FirstConfigure_h
+
+#include <QWizard>
+#include <QWizardPage>
+
+#include "cmake.h"
+
+#include "ui_Compilers.h"
+#include "ui_CrossCompiler.h"
+
+class QRadioButton;
+class QComboBox;
+
+//! the wizard pages we'll use for the first configure of a build
+enum FirstConfigurePages
+{
+ Start,
+ NativeSetup,
+ ToolchainSetup,
+ CrossSetup,
+ Done
+};
+
+//! the first page that gives basic options for what compilers setup to choose
+//! from
+class StartCompilerSetup : public QWizardPage
+{
+ Q_OBJECT
+public:
+ StartCompilerSetup(QWidget* p);
+ ~StartCompilerSetup();
+ void setGenerators(std::vector<cmake::GeneratorInfo> const& gens);
+ void setCurrentGenerator(const QString& gen);
+ QString getGenerator() const;
+ QString getToolset() const;
+
+ bool defaultSetup() const;
+ bool compilerSetup() const;
+ bool crossCompilerSetup() const;
+ bool crossCompilerToolChainFile() const;
+
+ int nextId() const;
+
+signals:
+ void selectionChanged();
+
+protected slots:
+ void onSelectionChanged(bool);
+ void onGeneratorChanged(QString const& name);
+
+protected:
+ QComboBox* GeneratorOptions;
+ QRadioButton* CompilerSetupOptions[4];
+ QFrame* ToolsetFrame;
+ QLineEdit* Toolset;
+ QLabel* ToolsetLabel;
+ QStringList GeneratorsSupportingToolset;
+
+private:
+ QFrame* CreateToolsetWidgets();
+};
+
+//! the page that gives basic options for native compilers
+class NativeCompilerSetup : public QWizardPage, protected Ui::Compilers
+{
+ Q_OBJECT
+public:
+ NativeCompilerSetup(QWidget* p);
+ ~NativeCompilerSetup();
+
+ QString getCCompiler() const;
+ void setCCompiler(const QString&);
+
+ QString getCXXCompiler() const;
+ void setCXXCompiler(const QString&);
+
+ QString getFortranCompiler() const;
+ void setFortranCompiler(const QString&);
+
+ int nextId() const { return -1; }
+};
+
+//! the page that gives options for cross compilers
+class CrossCompilerSetup : public QWizardPage, protected Ui::CrossCompiler
+{
+ Q_OBJECT
+public:
+ CrossCompilerSetup(QWidget* p);
+ ~CrossCompilerSetup();
+
+ QString getSystem() const;
+ void setSystem(const QString&);
+
+ QString getVersion() const;
+ void setVersion(const QString&);
+
+ QString getProcessor() const;
+ void setProcessor(const QString&);
+
+ QString getCCompiler() const;
+ void setCCompiler(const QString&);
+
+ QString getCXXCompiler() const;
+ void setCXXCompiler(const QString&);
+
+ QString getFortranCompiler() const;
+ void setFortranCompiler(const QString&);
+
+ QString getFindRoot() const;
+ void setFindRoot(const QString&);
+
+ enum CrossMode
+ {
+ BOTH,
+ ONLY,
+ NEVER
+ };
+
+ int getProgramMode() const;
+ void setProgramMode(int);
+ int getLibraryMode() const;
+ void setLibraryMode(int);
+ int getIncludeMode() const;
+ void setIncludeMode(int);
+
+ int nextId() const { return -1; }
+};
+
+//! the page that gives options for a toolchain file
+class ToolchainCompilerSetup : public QWizardPage
+{
+ Q_OBJECT
+public:
+ ToolchainCompilerSetup(QWidget* p);
+ ~ToolchainCompilerSetup();
+
+ QString toolchainFile() const;
+ void setToolchainFile(const QString&);
+
+ int nextId() const { return -1; }
+
+protected:
+ QCMakeFilePathEditor* ToolchainFile;
+};
+
+//! the wizard with the pages
+class FirstConfigure : public QWizard
+{
+ Q_OBJECT
+public:
+ FirstConfigure();
+ ~FirstConfigure();
+
+ void setGenerators(std::vector<cmake::GeneratorInfo> const& gens);
+ QString getGenerator() const;
+ QString getToolset() const;
+
+ bool defaultSetup() const;
+ bool compilerSetup() const;
+ bool crossCompilerSetup() const;
+ bool crossCompilerToolChainFile() const;
+
+ QString getCCompiler() const;
+ QString getCXXCompiler() const;
+ QString getFortranCompiler() const;
+
+ QString getSystemName() const;
+ QString getSystemVersion() const;
+ QString getSystemProcessor() const;
+ QString getCrossRoot() const;
+ QString getCrossProgramMode() const;
+ QString getCrossLibraryMode() const;
+ QString getCrossIncludeMode() const;
+
+ QString getCrossCompilerToolChainFile() const;
+
+ void loadFromSettings();
+ void saveToSettings();
+
+protected:
+ StartCompilerSetup* mStartCompilerSetupPage;
+ NativeCompilerSetup* mNativeCompilerSetupPage;
+ CrossCompilerSetup* mCrossCompilerSetupPage;
+ ToolchainCompilerSetup* mToolchainCompilerSetupPage;
+};
+
+#endif // FirstConfigure_h
diff --git a/Source/QtDialog/Info.plist.in b/Source/QtDialog/Info.plist.in
new file mode 100644
index 0000000..00a27c3
--- /dev/null
+++ b/Source/QtDialog/Info.plist.in
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>LSApplicationCategoryType</key>
+ <string>public.app-category.developer-tools</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+ <key>NSHighResolutionCapable</key>
+ <true/>
+</dict>
+</plist>
diff --git a/Source/QtDialog/Plus16.png b/Source/QtDialog/Plus16.png
new file mode 100644
index 0000000..552f6f0
--- /dev/null
+++ b/Source/QtDialog/Plus16.png
Binary files differ
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
new file mode 100644
index 0000000..abeff97
--- /dev/null
+++ b/Source/QtDialog/QCMake.cxx
@@ -0,0 +1,452 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMake.h"
+
+#include <QCoreApplication>
+#include <QDir>
+
+#include "cmExternalMakefileProjectGenerator.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
+
+#ifdef Q_OS_WIN
+#include "qt_windows.h" // For SetErrorMode
+#endif
+
+QCMake::QCMake(QObject* p)
+ : QObject(p)
+{
+ this->WarnUninitializedMode = false;
+ this->WarnUnusedMode = false;
+ qRegisterMetaType<QCMakeProperty>();
+ qRegisterMetaType<QCMakePropertyList>();
+
+ cmSystemTools::DisableRunCommandOutput();
+ cmSystemTools::SetRunCommandHideConsole(true);
+ cmSystemTools::SetMessageCallback(QCMake::messageCallback, this);
+ cmSystemTools::SetStdoutCallback(QCMake::stdoutCallback, this);
+ cmSystemTools::SetStderrCallback(QCMake::stderrCallback, this);
+
+ this->CMakeInstance = new cmake;
+ this->CMakeInstance->SetCMakeEditCommand(
+ cmSystemTools::GetCMakeGUICommand());
+ this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this);
+
+ cmSystemTools::SetInterruptCallback(QCMake::interruptCallback, this);
+
+ std::vector<cmake::GeneratorInfo> generators;
+ this->CMakeInstance->GetRegisteredGenerators(generators);
+
+ std::vector<cmake::GeneratorInfo>::const_iterator it;
+ for (it = generators.begin(); it != generators.end(); ++it) {
+ // Skip the generator "KDevelop3", since there is also
+ // "KDevelop3 - Unix Makefiles", which is the full and official name.
+ // The short name is actually only still there since this was the name
+ // in CMake 2.4, to keep "command line argument compatibility", but
+ // this is not necessary in the GUI.
+ if (it->name == "KDevelop3") {
+ continue;
+ }
+
+ this->AvailableGenerators.push_back(*it);
+ }
+}
+
+QCMake::~QCMake()
+{
+ delete this->CMakeInstance;
+ // cmDynamicLoader::FlushCache();
+}
+
+void QCMake::loadCache(const QString& dir)
+{
+ this->setBinaryDirectory(dir);
+}
+
+void QCMake::setSourceDirectory(const QString& _dir)
+{
+ QString dir = QString::fromLocal8Bit(
+ cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
+ if (this->SourceDirectory != dir) {
+ this->SourceDirectory = QDir::fromNativeSeparators(dir);
+ emit this->sourceDirChanged(this->SourceDirectory);
+ }
+}
+
+void QCMake::setBinaryDirectory(const QString& _dir)
+{
+ QString dir = QString::fromLocal8Bit(
+ cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
+ if (this->BinaryDirectory != dir) {
+ this->BinaryDirectory = QDir::fromNativeSeparators(dir);
+ emit this->binaryDirChanged(this->BinaryDirectory);
+ cmState* state = this->CMakeInstance->GetState();
+ this->setGenerator(QString());
+ this->setToolset(QString());
+ if (!this->CMakeInstance->LoadCache(
+ this->BinaryDirectory.toLocal8Bit().data())) {
+ QDir testDir(this->BinaryDirectory);
+ if (testDir.exists("CMakeCache.txt")) {
+ cmSystemTools::Error(
+ "There is a CMakeCache.txt file for the current binary "
+ "tree but cmake does not have permission to read it. "
+ "Please check the permissions of the directory you are trying to "
+ "run CMake on.");
+ }
+ }
+
+ QCMakePropertyList props = this->properties();
+ emit this->propertiesChanged(props);
+ const char* homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
+ if (homeDir) {
+ setSourceDirectory(QString::fromLocal8Bit(homeDir));
+ }
+ const char* gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
+ if (gen) {
+ const char* extraGen =
+ state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
+ std::string curGen =
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
+ gen, extraGen ? extraGen : "");
+ this->setGenerator(QString::fromLocal8Bit(curGen.c_str()));
+ }
+
+ const char* toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
+ if (toolset) {
+ this->setToolset(QString::fromLocal8Bit(toolset));
+ }
+ }
+}
+
+void QCMake::setGenerator(const QString& gen)
+{
+ if (this->Generator != gen) {
+ this->Generator = gen;
+ emit this->generatorChanged(this->Generator);
+ }
+}
+
+void QCMake::setToolset(const QString& toolset)
+{
+ if (this->Toolset != toolset) {
+ this->Toolset = toolset;
+ emit this->toolsetChanged(this->Toolset);
+ }
+}
+
+void QCMake::configure()
+{
+#ifdef Q_OS_WIN
+ UINT lastErrorMode = SetErrorMode(0);
+#endif
+
+ this->CMakeInstance->SetHomeDirectory(
+ this->SourceDirectory.toLocal8Bit().data());
+ this->CMakeInstance->SetHomeOutputDirectory(
+ this->BinaryDirectory.toLocal8Bit().data());
+ this->CMakeInstance->SetGlobalGenerator(
+ this->CMakeInstance->CreateGlobalGenerator(
+ this->Generator.toLocal8Bit().data()));
+ this->CMakeInstance->SetGeneratorPlatform("");
+ this->CMakeInstance->SetGeneratorToolset(this->Toolset.toLocal8Bit().data());
+ this->CMakeInstance->LoadCache();
+ this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);
+ this->CMakeInstance->SetWarnUnused(this->WarnUnusedMode);
+ this->CMakeInstance->PreLoadCMakeFiles();
+
+ InterruptFlag = 0;
+ cmSystemTools::ResetErrorOccuredFlag();
+
+ int err = this->CMakeInstance->Configure();
+
+#ifdef Q_OS_WIN
+ SetErrorMode(lastErrorMode);
+#endif
+
+ emit this->propertiesChanged(this->properties());
+ emit this->configureDone(err);
+}
+
+void QCMake::generate()
+{
+#ifdef Q_OS_WIN
+ UINT lastErrorMode = SetErrorMode(0);
+#endif
+
+ InterruptFlag = 0;
+ cmSystemTools::ResetErrorOccuredFlag();
+
+ int err = this->CMakeInstance->Generate();
+
+#ifdef Q_OS_WIN
+ SetErrorMode(lastErrorMode);
+#endif
+
+ emit this->generateDone(err);
+}
+
+void QCMake::setProperties(const QCMakePropertyList& newProps)
+{
+ QCMakePropertyList props = newProps;
+
+ QStringList toremove;
+
+ // set the value of properties
+ cmState* state = this->CMakeInstance->GetState();
+ std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
+ for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
+ it != cacheKeys.end(); ++it) {
+ cmStateEnums::CacheEntryType t = state->GetCacheEntryType(*it);
+ if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC) {
+ continue;
+ }
+
+ QCMakeProperty prop;
+ prop.Key = QString::fromLocal8Bit(it->c_str());
+ int idx = props.indexOf(prop);
+ if (idx == -1) {
+ toremove.append(QString::fromLocal8Bit(it->c_str()));
+ } else {
+ prop = props[idx];
+ if (prop.Value.type() == QVariant::Bool) {
+ state->SetCacheEntryValue(*it, prop.Value.toBool() ? "ON" : "OFF");
+ } else {
+ state->SetCacheEntryValue(*it,
+ prop.Value.toString().toLocal8Bit().data());
+ }
+ props.removeAt(idx);
+ }
+ }
+
+ // remove some properites
+ foreach (QString s, toremove) {
+ this->CMakeInstance->UnwatchUnusedCli(s.toLocal8Bit().data());
+
+ state->RemoveCacheEntry(s.toLocal8Bit().data());
+ }
+
+ // add some new properites
+ foreach (QCMakeProperty s, props) {
+ this->CMakeInstance->WatchUnusedCli(s.Key.toLocal8Bit().data());
+
+ if (s.Type == QCMakeProperty::BOOL) {
+ this->CMakeInstance->AddCacheEntry(
+ s.Key.toLocal8Bit().data(), s.Value.toBool() ? "ON" : "OFF",
+ s.Help.toLocal8Bit().data(), cmStateEnums::BOOL);
+ } else if (s.Type == QCMakeProperty::STRING) {
+ this->CMakeInstance->AddCacheEntry(
+ s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
+ s.Help.toLocal8Bit().data(), cmStateEnums::STRING);
+ } else if (s.Type == QCMakeProperty::PATH) {
+ this->CMakeInstance->AddCacheEntry(
+ s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
+ s.Help.toLocal8Bit().data(), cmStateEnums::PATH);
+ } else if (s.Type == QCMakeProperty::FILEPATH) {
+ this->CMakeInstance->AddCacheEntry(
+ s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
+ s.Help.toLocal8Bit().data(), cmStateEnums::FILEPATH);
+ }
+ }
+
+ this->CMakeInstance->SaveCache(this->BinaryDirectory.toLocal8Bit().data());
+}
+
+QCMakePropertyList QCMake::properties() const
+{
+ QCMakePropertyList ret;
+
+ cmState* state = this->CMakeInstance->GetState();
+ std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
+ for (std::vector<std::string>::const_iterator i = cacheKeys.begin();
+ i != cacheKeys.end(); ++i) {
+ cmStateEnums::CacheEntryType t = state->GetCacheEntryType(*i);
+ if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
+ t == cmStateEnums::UNINITIALIZED) {
+ continue;
+ }
+
+ const char* cachedValue = state->GetCacheEntryValue(*i);
+
+ QCMakeProperty prop;
+ prop.Key = QString::fromLocal8Bit(i->c_str());
+ prop.Help =
+ QString::fromLocal8Bit(state->GetCacheEntryProperty(*i, "HELPSTRING"));
+ prop.Value = QString::fromLocal8Bit(cachedValue);
+ prop.Advanced = state->GetCacheEntryPropertyAsBool(*i, "ADVANCED");
+ if (t == cmStateEnums::BOOL) {
+ prop.Type = QCMakeProperty::BOOL;
+ prop.Value = cmSystemTools::IsOn(cachedValue);
+ } else if (t == cmStateEnums::PATH) {
+ prop.Type = QCMakeProperty::PATH;
+ } else if (t == cmStateEnums::FILEPATH) {
+ prop.Type = QCMakeProperty::FILEPATH;
+ } else if (t == cmStateEnums::STRING) {
+ prop.Type = QCMakeProperty::STRING;
+ const char* stringsProperty =
+ state->GetCacheEntryProperty(*i, "STRINGS");
+ if (stringsProperty) {
+ prop.Strings = QString::fromLocal8Bit(stringsProperty).split(";");
+ }
+ }
+
+ ret.append(prop);
+ }
+
+ return ret;
+}
+
+void QCMake::interrupt()
+{
+ this->InterruptFlag.ref();
+}
+
+bool QCMake::interruptCallback(void* cd)
+{
+ QCMake* self = reinterpret_cast<QCMake*>(cd);
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ return self->InterruptFlag;
+#else
+ return self->InterruptFlag.load();
+#endif
+}
+
+void QCMake::progressCallback(const char* msg, float percent, void* cd)
+{
+ QCMake* self = reinterpret_cast<QCMake*>(cd);
+ if (percent >= 0) {
+ emit self->progressChanged(QString::fromLocal8Bit(msg), percent);
+ } else {
+ emit self->outputMessage(QString::fromLocal8Bit(msg));
+ }
+ QCoreApplication::processEvents();
+}
+
+void QCMake::messageCallback(const char* msg, const char* /*title*/,
+ bool& /*stop*/, void* cd)
+{
+ QCMake* self = reinterpret_cast<QCMake*>(cd);
+ emit self->errorMessage(QString::fromLocal8Bit(msg));
+ QCoreApplication::processEvents();
+}
+
+void QCMake::stdoutCallback(const char* msg, size_t len, void* cd)
+{
+ QCMake* self = reinterpret_cast<QCMake*>(cd);
+ emit self->outputMessage(QString::fromLocal8Bit(msg, int(len)));
+ QCoreApplication::processEvents();
+}
+
+void QCMake::stderrCallback(const char* msg, size_t len, void* cd)
+{
+ QCMake* self = reinterpret_cast<QCMake*>(cd);
+ emit self->outputMessage(QString::fromLocal8Bit(msg, int(len)));
+ QCoreApplication::processEvents();
+}
+
+QString QCMake::binaryDirectory() const
+{
+ return this->BinaryDirectory;
+}
+
+QString QCMake::sourceDirectory() const
+{
+ return this->SourceDirectory;
+}
+
+QString QCMake::generator() const
+{
+ return this->Generator;
+}
+
+std::vector<cmake::GeneratorInfo> const& QCMake::availableGenerators() const
+{
+ return AvailableGenerators;
+}
+
+void QCMake::deleteCache()
+{
+ // delete cache
+ this->CMakeInstance->DeleteCache(this->BinaryDirectory.toLocal8Bit().data());
+ // reload to make our cache empty
+ this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
+ // emit no generator and no properties
+ this->setGenerator(QString());
+ this->setToolset(QString());
+ QCMakePropertyList props = this->properties();
+ emit this->propertiesChanged(props);
+}
+
+void QCMake::reloadCache()
+{
+ // emit that the cache was cleaned out
+ QCMakePropertyList props;
+ emit this->propertiesChanged(props);
+ // reload
+ this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
+ // emit new cache properties
+ props = this->properties();
+ emit this->propertiesChanged(props);
+}
+
+void QCMake::setDebugOutput(bool flag)
+{
+ if (flag != this->CMakeInstance->GetDebugOutput()) {
+ this->CMakeInstance->SetDebugOutputOn(flag);
+ emit this->debugOutputChanged(flag);
+ }
+}
+
+bool QCMake::getDebugOutput() const
+{
+ return this->CMakeInstance->GetDebugOutput();
+}
+
+bool QCMake::getSuppressDevWarnings()
+{
+ return this->CMakeInstance->GetSuppressDevWarnings();
+}
+
+void QCMake::setSuppressDevWarnings(bool value)
+{
+ this->CMakeInstance->SetSuppressDevWarnings(value);
+}
+
+bool QCMake::getSuppressDeprecatedWarnings()
+{
+ return this->CMakeInstance->GetSuppressDeprecatedWarnings();
+}
+
+void QCMake::setSuppressDeprecatedWarnings(bool value)
+{
+ this->CMakeInstance->SetSuppressDeprecatedWarnings(value);
+}
+
+bool QCMake::getDevWarningsAsErrors()
+{
+ return this->CMakeInstance->GetDevWarningsAsErrors();
+}
+
+void QCMake::setDevWarningsAsErrors(bool value)
+{
+ this->CMakeInstance->SetDevWarningsAsErrors(value);
+}
+
+bool QCMake::getDeprecatedWarningsAsErrors()
+{
+ return this->CMakeInstance->GetDeprecatedWarningsAsErrors();
+}
+
+void QCMake::setDeprecatedWarningsAsErrors(bool value)
+{
+ this->CMakeInstance->SetDeprecatedWarningsAsErrors(value);
+}
+
+void QCMake::setWarnUninitializedMode(bool value)
+{
+ this->WarnUninitializedMode = value;
+}
+
+void QCMake::setWarnUnusedMode(bool value)
+{
+ this->WarnUnusedMode = value;
+}
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
new file mode 100644
index 0000000..12f6037
--- /dev/null
+++ b/Source/QtDialog/QCMake.h
@@ -0,0 +1,176 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef QCMake_h
+#define QCMake_h
+
+#include <cmConfigure.h>
+
+#include "cmake.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4127)
+#pragma warning(disable : 4512)
+#endif
+
+#include <vector>
+
+#include <QAtomicInt>
+#include <QList>
+#include <QMetaType>
+#include <QObject>
+#include <QString>
+#include <QStringList>
+#include <QVariant>
+
+/// struct to represent cmake properties in Qt
+/// Value is of type String or Bool
+struct QCMakeProperty
+{
+ enum PropertyType
+ {
+ BOOL,
+ PATH,
+ FILEPATH,
+ STRING
+ };
+ QString Key;
+ QVariant Value;
+ QStringList Strings;
+ QString Help;
+ PropertyType Type;
+ bool Advanced;
+ bool operator==(const QCMakeProperty& other) const
+ {
+ return this->Key == other.Key;
+ }
+ bool operator<(const QCMakeProperty& other) const
+ {
+ return this->Key < other.Key;
+ }
+};
+
+// list of properties
+typedef QList<QCMakeProperty> QCMakePropertyList;
+
+// allow QVariant to be a property or list of properties
+Q_DECLARE_METATYPE(QCMakeProperty)
+Q_DECLARE_METATYPE(QCMakePropertyList)
+
+/// Qt API for CMake library.
+/// Wrapper like class allows for easier integration with
+/// Qt features such as, signal/slot connections, multi-threading, etc..
+class QCMake : public QObject
+{
+ Q_OBJECT
+public:
+ QCMake(QObject* p = CM_NULLPTR);
+ ~QCMake();
+public slots:
+ /// load the cache file in a directory
+ void loadCache(const QString& dir);
+ /// set the source directory containing the source
+ void setSourceDirectory(const QString& dir);
+ /// set the binary directory to build in
+ void setBinaryDirectory(const QString& dir);
+ /// set the desired generator to use
+ void setGenerator(const QString& generator);
+ /// set the desired generator to use
+ void setToolset(const QString& toolset);
+ /// do the configure step
+ void configure();
+ /// generate the files
+ void generate();
+ /// set the property values
+ void setProperties(const QCMakePropertyList&);
+ /// interrupt the configure or generate process (if connecting, make a direct
+ /// connection)
+ void interrupt();
+ /// delete the cache in binary directory
+ void deleteCache();
+ /// reload the cache in binary directory
+ void reloadCache();
+ /// set whether to do debug output
+ void setDebugOutput(bool);
+ /// get whether to do suppress dev warnings
+ bool getSuppressDevWarnings();
+ /// set whether to do suppress dev warnings
+ void setSuppressDevWarnings(bool value);
+ /// get whether to do suppress deprecated warnings
+ bool getSuppressDeprecatedWarnings();
+ /// set whether to do suppress deprecated warnings
+ void setSuppressDeprecatedWarnings(bool value);
+ /// get whether to treat developer (author) warnings as errors
+ bool getDevWarningsAsErrors();
+ /// set whether to treat developer (author) warnings as errors
+ void setDevWarningsAsErrors(bool value);
+ /// get whether to treat deprecated warnings as errors
+ bool getDeprecatedWarningsAsErrors();
+ /// set whether to treat deprecated warnings as errors
+ void setDeprecatedWarningsAsErrors(bool value);
+ /// set whether to run cmake with warnings about uninitialized variables
+ void setWarnUninitializedMode(bool value);
+ /// set whether to run cmake with warnings about unused variables
+ void setWarnUnusedMode(bool value);
+
+public:
+ /// get the list of cache properties
+ QCMakePropertyList properties() const;
+ /// get the current binary directory
+ QString binaryDirectory() const;
+ /// get the current source directory
+ QString sourceDirectory() const;
+ /// get the current generator
+ QString generator() const;
+ /// get the available generators
+ std::vector<cmake::GeneratorInfo> const& availableGenerators() const;
+ /// get whether to do debug output
+ bool getDebugOutput() const;
+
+signals:
+ /// signal when properties change (during read from disk or configure
+ /// process)
+ void propertiesChanged(const QCMakePropertyList& vars);
+ /// signal when the generator changes
+ void generatorChanged(const QString& gen);
+ /// signal when the source directory changes (binary directory already
+ /// containing a CMakeCache.txt file)
+ void sourceDirChanged(const QString& dir);
+ /// signal when the binary directory changes
+ void binaryDirChanged(const QString& dir);
+ /// signal for progress events
+ void progressChanged(const QString& msg, float percent);
+ /// signal when configure is done
+ void configureDone(int error);
+ /// signal when generate is done
+ void generateDone(int error);
+ /// signal when there is an output message
+ void outputMessage(const QString& msg);
+ /// signal when there is an error message
+ void errorMessage(const QString& msg);
+ /// signal when debug output changes
+ void debugOutputChanged(bool);
+ /// signal when the toolset changes
+ void toolsetChanged(const QString& toolset);
+
+protected:
+ cmake* CMakeInstance;
+
+ static bool interruptCallback(void*);
+ static void progressCallback(const char* msg, float percent, void* cd);
+ static void messageCallback(const char* msg, const char* title, bool&,
+ void* cd);
+ static void stdoutCallback(const char* msg, size_t len, void* cd);
+ static void stderrCallback(const char* msg, size_t len, void* cd);
+ bool WarnUninitializedMode;
+ bool WarnUnusedMode;
+ bool WarnUnusedAllMode;
+ QString SourceDirectory;
+ QString BinaryDirectory;
+ QString Generator;
+ QString Toolset;
+ std::vector<cmake::GeneratorInfo> AvailableGenerators;
+ QString CMakeExecutable;
+ QAtomicInt InterruptFlag;
+};
+
+#endif // QCMake_h
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
new file mode 100644
index 0000000..9f5208a
--- /dev/null
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -0,0 +1,678 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMakeCacheView.h"
+
+#include <QApplication>
+#include <QEvent>
+#include <QHBoxLayout>
+#include <QHeaderView>
+#include <QKeyEvent>
+#include <QMetaProperty>
+#include <QSortFilterProxyModel>
+#include <QStyle>
+
+#include "QCMakeWidgets.h"
+
+// filter for searches
+class QCMakeSearchFilter : public QSortFilterProxyModel
+{
+public:
+ QCMakeSearchFilter(QObject* o)
+ : QSortFilterProxyModel(o)
+ {
+ }
+
+protected:
+ bool filterAcceptsRow(int row, const QModelIndex& p) const CM_OVERRIDE
+ {
+ QStringList strs;
+ const QAbstractItemModel* m = this->sourceModel();
+ QModelIndex idx = m->index(row, 0, p);
+
+ // if there are no children, get strings for column 0 and 1
+ if (!m->hasChildren(idx)) {
+ strs.append(m->data(idx).toString());
+ idx = m->index(row, 1, p);
+ strs.append(m->data(idx).toString());
+ } else {
+ // get strings for children entries to compare with
+ // instead of comparing with the parent
+ int num = m->rowCount(idx);
+ for (int i = 0; i < num; i++) {
+ QModelIndex tmpidx = m->index(i, 0, idx);
+ strs.append(m->data(tmpidx).toString());
+ tmpidx = m->index(i, 1, idx);
+ strs.append(m->data(tmpidx).toString());
+ }
+ }
+
+ // check all strings for a match
+ foreach (QString str, strs) {
+ if (str.contains(this->filterRegExp())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+};
+
+// filter for searches
+class QCMakeAdvancedFilter : public QSortFilterProxyModel
+{
+public:
+ QCMakeAdvancedFilter(QObject* o)
+ : QSortFilterProxyModel(o)
+ , ShowAdvanced(false)
+ {
+ }
+
+ void setShowAdvanced(bool f)
+ {
+ this->ShowAdvanced = f;
+ this->invalidate();
+ }
+ bool showAdvanced() const { return this->ShowAdvanced; }
+
+protected:
+ bool ShowAdvanced;
+
+ bool filterAcceptsRow(int row, const QModelIndex& p) const CM_OVERRIDE
+ {
+ const QAbstractItemModel* m = this->sourceModel();
+ QModelIndex idx = m->index(row, 0, p);
+
+ // if there are no children
+ if (!m->hasChildren(idx)) {
+ bool adv = m->data(idx, QCMakeCacheModel::AdvancedRole).toBool();
+ return !adv || this->ShowAdvanced;
+ }
+
+ // check children
+ int num = m->rowCount(idx);
+ for (int i = 0; i < num; i++) {
+ bool accept = this->filterAcceptsRow(i, idx);
+ if (accept) {
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+QCMakeCacheView::QCMakeCacheView(QWidget* p)
+ : QTreeView(p)
+{
+ // hook up our model and search/filter proxies
+ this->CacheModel = new QCMakeCacheModel(this);
+ this->AdvancedFilter = new QCMakeAdvancedFilter(this);
+ this->AdvancedFilter->setSourceModel(this->CacheModel);
+ this->AdvancedFilter->setDynamicSortFilter(true);
+ this->SearchFilter = new QCMakeSearchFilter(this);
+ this->SearchFilter->setSourceModel(this->AdvancedFilter);
+ this->SearchFilter->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ this->SearchFilter->setDynamicSortFilter(true);
+ this->setModel(this->SearchFilter);
+
+ // our delegate for creating our editors
+ QCMakeCacheModelDelegate* delegate = new QCMakeCacheModelDelegate(this);
+ this->setItemDelegate(delegate);
+
+ this->setUniformRowHeights(true);
+
+ this->setEditTriggers(QAbstractItemView::AllEditTriggers);
+
+ // tab, backtab doesn't step through items
+ this->setTabKeyNavigation(false);
+
+ this->setRootIsDecorated(false);
+}
+
+bool QCMakeCacheView::event(QEvent* e)
+{
+ if (e->type() == QEvent::Show) {
+ this->header()->setDefaultSectionSize(this->viewport()->width() / 2);
+ }
+ return QTreeView::event(e);
+}
+
+QCMakeCacheModel* QCMakeCacheView::cacheModel() const
+{
+ return this->CacheModel;
+}
+
+QModelIndex QCMakeCacheView::moveCursor(CursorAction act,
+ Qt::KeyboardModifiers mod)
+{
+ // want home/end to go to begin/end of rows, not columns
+ if (act == MoveHome) {
+ return this->model()->index(0, 1);
+ }
+ if (act == MoveEnd) {
+ return this->model()->index(this->model()->rowCount() - 1, 1);
+ }
+ return QTreeView::moveCursor(act, mod);
+}
+
+void QCMakeCacheView::setShowAdvanced(bool s)
+{
+#if QT_VERSION >= 040300
+ // new 4.3 API that needs to be called. what about an older Qt?
+ this->SearchFilter->invalidate();
+#endif
+
+ this->AdvancedFilter->setShowAdvanced(s);
+}
+
+bool QCMakeCacheView::showAdvanced() const
+{
+ return this->AdvancedFilter->showAdvanced();
+}
+
+void QCMakeCacheView::setSearchFilter(const QString& s)
+{
+ this->SearchFilter->setFilterFixedString(s);
+}
+
+QCMakeCacheModel::QCMakeCacheModel(QObject* p)
+ : QStandardItemModel(p)
+ , EditEnabled(true)
+ , NewPropertyCount(0)
+ , View(FlatView)
+{
+ this->ShowNewProperties = true;
+ QStringList labels;
+ labels << tr("Name") << tr("Value");
+ this->setHorizontalHeaderLabels(labels);
+}
+
+QCMakeCacheModel::~QCMakeCacheModel()
+{
+}
+
+static uint qHash(const QCMakeProperty& p)
+{
+ return qHash(p.Key);
+}
+
+void QCMakeCacheModel::setShowNewProperties(bool f)
+{
+ this->ShowNewProperties = f;
+}
+
+void QCMakeCacheModel::clear()
+{
+ this->QStandardItemModel::clear();
+ this->NewPropertyCount = 0;
+
+ QStringList labels;
+ labels << tr("Name") << tr("Value");
+ this->setHorizontalHeaderLabels(labels);
+}
+
+void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
+{
+ QSet<QCMakeProperty> newProps, newProps2;
+
+ if (this->ShowNewProperties) {
+ newProps = props.toSet();
+ newProps2 = newProps;
+ QSet<QCMakeProperty> oldProps = this->properties().toSet();
+ oldProps.intersect(newProps);
+ newProps.subtract(oldProps);
+ newProps2.subtract(newProps);
+ } else {
+ newProps2 = props.toSet();
+ }
+
+ bool b = this->blockSignals(true);
+
+ this->clear();
+ this->NewPropertyCount = newProps.size();
+
+ if (View == FlatView) {
+ QCMakePropertyList newP = newProps.toList();
+ QCMakePropertyList newP2 = newProps2.toList();
+ qSort(newP);
+ qSort(newP2);
+ int row_count = 0;
+ foreach (QCMakeProperty p, newP) {
+ this->insertRow(row_count);
+ this->setPropertyData(this->index(row_count, 0), p, true);
+ row_count++;
+ }
+ foreach (QCMakeProperty p, newP2) {
+ this->insertRow(row_count);
+ this->setPropertyData(this->index(row_count, 0), p, false);
+ row_count++;
+ }
+ } else if (this->View == GroupView) {
+ QMap<QString, QCMakePropertyList> newPropsTree;
+ this->breakProperties(newProps, newPropsTree);
+ QMap<QString, QCMakePropertyList> newPropsTree2;
+ this->breakProperties(newProps2, newPropsTree2);
+
+ QStandardItem* root = this->invisibleRootItem();
+
+ foreach (QString key, newPropsTree.keys()) {
+ QCMakePropertyList props2 = newPropsTree[key];
+
+ QList<QStandardItem*> parentItems;
+ parentItems.append(
+ new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key));
+ parentItems.append(new QStandardItem());
+ parentItems[0]->setData(QBrush(QColor(255, 100, 100)),
+ Qt::BackgroundColorRole);
+ parentItems[1]->setData(QBrush(QColor(255, 100, 100)),
+ Qt::BackgroundColorRole);
+ parentItems[0]->setData(1, GroupRole);
+ parentItems[1]->setData(1, GroupRole);
+ root->appendRow(parentItems);
+
+ int num = props2.size();
+ for (int i = 0; i < num; i++) {
+ QCMakeProperty prop = props2[i];
+ QList<QStandardItem*> items;
+ items.append(new QStandardItem());
+ items.append(new QStandardItem());
+ parentItems[0]->appendRow(items);
+ this->setPropertyData(this->indexFromItem(items[0]), prop, true);
+ }
+ }
+
+ foreach (QString key, newPropsTree2.keys()) {
+ QCMakePropertyList props2 = newPropsTree2[key];
+
+ QStandardItem* parentItem =
+ new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key);
+ root->appendRow(parentItem);
+ parentItem->setData(1, GroupRole);
+
+ int num = props2.size();
+ for (int i = 0; i < num; i++) {
+ QCMakeProperty prop = props2[i];
+ QList<QStandardItem*> items;
+ items.append(new QStandardItem());
+ items.append(new QStandardItem());
+ parentItem->appendRow(items);
+ this->setPropertyData(this->indexFromItem(items[0]), prop, false);
+ }
+ }
+ }
+
+ this->blockSignals(b);
+ this->reset();
+}
+
+QCMakeCacheModel::ViewType QCMakeCacheModel::viewType() const
+{
+ return this->View;
+}
+
+void QCMakeCacheModel::setViewType(QCMakeCacheModel::ViewType t)
+{
+ this->View = t;
+
+ QCMakePropertyList props = this->properties();
+ QCMakePropertyList oldProps;
+ int numNew = this->NewPropertyCount;
+ int numTotal = props.count();
+ for (int i = numNew; i < numTotal; i++) {
+ oldProps.append(props[i]);
+ }
+
+ bool b = this->blockSignals(true);
+ this->clear();
+ this->setProperties(oldProps);
+ this->setProperties(props);
+ this->blockSignals(b);
+ this->reset();
+}
+
+void QCMakeCacheModel::setPropertyData(const QModelIndex& idx1,
+ const QCMakeProperty& prop, bool isNew)
+{
+ QModelIndex idx2 = idx1.sibling(idx1.row(), 1);
+
+ this->setData(idx1, prop.Key, Qt::DisplayRole);
+ this->setData(idx1, prop.Help, QCMakeCacheModel::HelpRole);
+ this->setData(idx1, prop.Type, QCMakeCacheModel::TypeRole);
+ this->setData(idx1, prop.Advanced, QCMakeCacheModel::AdvancedRole);
+
+ if (prop.Type == QCMakeProperty::BOOL) {
+ int check = prop.Value.toBool() ? Qt::Checked : Qt::Unchecked;
+ this->setData(idx2, check, Qt::CheckStateRole);
+ } else {
+ this->setData(idx2, prop.Value, Qt::DisplayRole);
+ }
+ this->setData(idx2, prop.Help, QCMakeCacheModel::HelpRole);
+
+ if (!prop.Strings.isEmpty()) {
+ this->setData(idx1, prop.Strings, QCMakeCacheModel::StringsRole);
+ }
+
+ if (isNew) {
+ this->setData(idx1, QBrush(QColor(255, 100, 100)),
+ Qt::BackgroundColorRole);
+ this->setData(idx2, QBrush(QColor(255, 100, 100)),
+ Qt::BackgroundColorRole);
+ }
+}
+
+void QCMakeCacheModel::getPropertyData(const QModelIndex& idx1,
+ QCMakeProperty& prop) const
+{
+ QModelIndex idx2 = idx1.sibling(idx1.row(), 1);
+
+ prop.Key = this->data(idx1, Qt::DisplayRole).toString();
+ prop.Help = this->data(idx1, HelpRole).toString();
+ prop.Type = static_cast<QCMakeProperty::PropertyType>(
+ this->data(idx1, TypeRole).toInt());
+ prop.Advanced = this->data(idx1, AdvancedRole).toBool();
+ prop.Strings =
+ this->data(idx1, QCMakeCacheModel::StringsRole).toStringList();
+ if (prop.Type == QCMakeProperty::BOOL) {
+ int check = this->data(idx2, Qt::CheckStateRole).toInt();
+ prop.Value = check == Qt::Checked;
+ } else {
+ prop.Value = this->data(idx2, Qt::DisplayRole).toString();
+ }
+}
+
+QString QCMakeCacheModel::prefix(const QString& s)
+{
+ QString prefix = s.section('_', 0, 0);
+ if (prefix == s) {
+ prefix = QString();
+ }
+ return prefix;
+}
+
+void QCMakeCacheModel::breakProperties(
+ const QSet<QCMakeProperty>& props, QMap<QString, QCMakePropertyList>& result)
+{
+ QMap<QString, QCMakePropertyList> tmp;
+ // return a map of properties grouped by prefixes, and sorted
+ foreach (QCMakeProperty p, props) {
+ QString prefix = QCMakeCacheModel::prefix(p.Key);
+ tmp[prefix].append(p);
+ }
+ // sort it and re-org any properties with only one sub item
+ QCMakePropertyList reorgProps;
+ QMap<QString, QCMakePropertyList>::iterator iter;
+ for (iter = tmp.begin(); iter != tmp.end();) {
+ if (iter->count() == 1) {
+ reorgProps.append((*iter)[0]);
+ iter = tmp.erase(iter);
+ } else {
+ qSort(*iter);
+ ++iter;
+ }
+ }
+ if (reorgProps.count()) {
+ tmp[QString()] += reorgProps;
+ }
+ result = tmp;
+}
+
+QCMakePropertyList QCMakeCacheModel::properties() const
+{
+ QCMakePropertyList props;
+
+ if (!this->rowCount()) {
+ return props;
+ }
+
+ QList<QModelIndex> idxs;
+ idxs.append(this->index(0, 0));
+
+ // walk the entire model for property entries
+ // this works regardless of a flat view or a tree view
+ while (!idxs.isEmpty()) {
+ QModelIndex idx = idxs.last();
+ if (this->hasChildren(idx) && this->rowCount(idx)) {
+ idxs.append(this->index(0, 0, idx));
+ } else {
+ if (!data(idx, GroupRole).toInt()) {
+ // get data
+ QCMakeProperty prop;
+ this->getPropertyData(idx, prop);
+ props.append(prop);
+ }
+
+ // go to the next in the tree
+ while (!idxs.isEmpty() &&
+ (
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && \
+ QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+ (idxs.last().row() + 1) >= rowCount(idxs.last().parent()) ||
+#endif
+ !idxs.last().sibling(idxs.last().row() + 1, 0).isValid())) {
+ idxs.removeLast();
+ }
+ if (!idxs.isEmpty()) {
+ idxs.last() = idxs.last().sibling(idxs.last().row() + 1, 0);
+ }
+ }
+ }
+
+ return props;
+}
+
+bool QCMakeCacheModel::insertProperty(QCMakeProperty::PropertyType t,
+ const QString& name,
+ const QString& description,
+ const QVariant& value, bool advanced)
+{
+ QCMakeProperty prop;
+ prop.Key = name;
+ prop.Value = value;
+ prop.Help = description;
+ prop.Type = t;
+ prop.Advanced = advanced;
+
+ // insert at beginning
+ this->insertRow(0);
+ this->setPropertyData(this->index(0, 0), prop, true);
+ this->NewPropertyCount++;
+ return true;
+}
+
+void QCMakeCacheModel::setEditEnabled(bool e)
+{
+ this->EditEnabled = e;
+}
+
+bool QCMakeCacheModel::editEnabled() const
+{
+ return this->EditEnabled;
+}
+
+int QCMakeCacheModel::newPropertyCount() const
+{
+ return this->NewPropertyCount;
+}
+
+Qt::ItemFlags QCMakeCacheModel::flags(const QModelIndex& idx) const
+{
+ Qt::ItemFlags f = QStandardItemModel::flags(idx);
+ if (!this->EditEnabled) {
+ f &= ~Qt::ItemIsEditable;
+ return f;
+ }
+ if (QCMakeProperty::BOOL == this->data(idx, TypeRole).toInt()) {
+ f |= Qt::ItemIsUserCheckable;
+ }
+ return f;
+}
+
+QModelIndex QCMakeCacheModel::buddy(const QModelIndex& idx) const
+{
+ if (!this->hasChildren(idx) &&
+ this->data(idx, TypeRole).toInt() != QCMakeProperty::BOOL) {
+ return this->index(idx.row(), 1, idx.parent());
+ }
+ return idx;
+}
+
+QCMakeCacheModelDelegate::QCMakeCacheModelDelegate(QObject* p)
+ : QItemDelegate(p)
+ , FileDialogFlag(false)
+{
+}
+
+void QCMakeCacheModelDelegate::setFileDialogFlag(bool f)
+{
+ this->FileDialogFlag = f;
+}
+
+QWidget* QCMakeCacheModelDelegate::createEditor(
+ QWidget* p, const QStyleOptionViewItem& /*option*/,
+ const QModelIndex& idx) const
+{
+ QModelIndex var = idx.sibling(idx.row(), 0);
+ int type = var.data(QCMakeCacheModel::TypeRole).toInt();
+ if (type == QCMakeProperty::BOOL) {
+ return CM_NULLPTR;
+ }
+ if (type == QCMakeProperty::PATH) {
+ QCMakePathEditor* editor =
+ new QCMakePathEditor(p, var.data(Qt::DisplayRole).toString());
+ QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
+ SLOT(setFileDialogFlag(bool)));
+ return editor;
+ }
+ if (type == QCMakeProperty::FILEPATH) {
+ QCMakeFilePathEditor* editor =
+ new QCMakeFilePathEditor(p, var.data(Qt::DisplayRole).toString());
+ QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
+ SLOT(setFileDialogFlag(bool)));
+ return editor;
+ }
+ if (type == QCMakeProperty::STRING &&
+ var.data(QCMakeCacheModel::StringsRole).isValid()) {
+ QCMakeComboBox* editor = new QCMakeComboBox(
+ p, var.data(QCMakeCacheModel::StringsRole).toStringList());
+ editor->setFrame(false);
+ return editor;
+ }
+
+ QLineEdit* editor = new QLineEdit(p);
+ editor->setFrame(false);
+ return editor;
+}
+
+bool QCMakeCacheModelDelegate::editorEvent(QEvent* e,
+ QAbstractItemModel* model,
+ const QStyleOptionViewItem& option,
+ const QModelIndex& index)
+{
+ Qt::ItemFlags flags = model->flags(index);
+ if (!(flags & Qt::ItemIsUserCheckable) ||
+ !(option.state & QStyle::State_Enabled) ||
+ !(flags & Qt::ItemIsEnabled)) {
+ return false;
+ }
+
+ QVariant value = index.data(Qt::CheckStateRole);
+ if (!value.isValid()) {
+ return false;
+ }
+
+ if ((e->type() == QEvent::MouseButtonRelease) ||
+ (e->type() == QEvent::MouseButtonDblClick)) {
+ // eat the double click events inside the check rect
+ if (e->type() == QEvent::MouseButtonDblClick) {
+ return true;
+ }
+ } else if (e->type() == QEvent::KeyPress) {
+ if (static_cast<QKeyEvent*>(e)->key() != Qt::Key_Space &&
+ static_cast<QKeyEvent*>(e)->key() != Qt::Key_Select) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ Qt::CheckState state =
+ (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked ? Qt::Unchecked
+ : Qt::Checked);
+ bool success = model->setData(index, state, Qt::CheckStateRole);
+ if (success) {
+ this->recordChange(model, index);
+ }
+ return success;
+}
+
+// Issue 205903 fixed in Qt 4.5.0.
+// Can remove this function and FileDialogFlag when minimum Qt version is 4.5
+bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* evt)
+{
+ // workaround for what looks like a bug in Qt on Mac OS X
+ // where it doesn't create a QWidget wrapper for the native file dialog
+ // so the Qt library ends up assuming the focus was lost to something else
+
+ if (evt->type() == QEvent::FocusOut && this->FileDialogFlag) {
+ return false;
+ }
+ return QItemDelegate::eventFilter(object, evt);
+}
+
+void QCMakeCacheModelDelegate::setModelData(QWidget* editor,
+ QAbstractItemModel* model,
+ const QModelIndex& index) const
+{
+ QItemDelegate::setModelData(editor, model, index);
+ const_cast<QCMakeCacheModelDelegate*>(this)->recordChange(model, index);
+}
+
+QSize QCMakeCacheModelDelegate::sizeHint(const QStyleOptionViewItem& option,
+ const QModelIndex& index) const
+{
+ QSize sz = QItemDelegate::sizeHint(option, index);
+ QStyle* style = QApplication::style();
+
+ // increase to checkbox size
+ QStyleOptionButton opt;
+ opt.QStyleOption::operator=(option);
+ sz = sz.expandedTo(
+ style->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, CM_NULLPTR)
+ .size());
+
+ return sz;
+}
+
+QSet<QCMakeProperty> QCMakeCacheModelDelegate::changes() const
+{
+ return mChanges;
+}
+
+void QCMakeCacheModelDelegate::clearChanges()
+{
+ mChanges.clear();
+}
+
+void QCMakeCacheModelDelegate::recordChange(QAbstractItemModel* model,
+ const QModelIndex& index)
+{
+ QModelIndex idx = index;
+ QAbstractItemModel* mymodel = model;
+ while (qobject_cast<QAbstractProxyModel*>(mymodel)) {
+ idx = static_cast<QAbstractProxyModel*>(mymodel)->mapToSource(idx);
+ mymodel = static_cast<QAbstractProxyModel*>(mymodel)->sourceModel();
+ }
+ QCMakeCacheModel* cache_model = qobject_cast<QCMakeCacheModel*>(mymodel);
+ if (cache_model && idx.isValid()) {
+ QCMakeProperty prop;
+ idx = idx.sibling(idx.row(), 0);
+ cache_model->getPropertyData(idx, prop);
+
+ // clean out an old one
+ QSet<QCMakeProperty>::iterator iter = mChanges.find(prop);
+ if (iter != mChanges.end()) {
+ mChanges.erase(iter);
+ }
+ // now add the new item
+ mChanges.insert(prop);
+ }
+}
diff --git a/Source/QtDialog/QCMakeCacheView.h b/Source/QtDialog/QCMakeCacheView.h
new file mode 100644
index 0000000..c1debf5
--- /dev/null
+++ b/Source/QtDialog/QCMakeCacheView.h
@@ -0,0 +1,170 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef QCMakeCacheView_h
+#define QCMakeCacheView_h
+
+#include "QCMake.h"
+
+#include <QItemDelegate>
+#include <QSet>
+#include <QStandardItemModel>
+#include <QTreeView>
+
+class QSortFilterProxyModel;
+class QCMakeCacheModel;
+class QCMakeAdvancedFilter;
+
+/// Qt view class for cache properties
+class QCMakeCacheView : public QTreeView
+{
+ Q_OBJECT
+public:
+ QCMakeCacheView(QWidget* p);
+
+ // retrieve the QCMakeCacheModel storing all the pointers
+ // this isn't necessarily the model one would get from model()
+ QCMakeCacheModel* cacheModel() const;
+
+ // get whether to show advanced entries
+ bool showAdvanced() const;
+
+ QSize sizeHint() const { return QSize(200, 200); }
+
+public slots:
+ // set whether to show advanced entries
+ void setShowAdvanced(bool);
+ // set the search filter string. any property key or value not matching will
+ // be filtered out
+ void setSearchFilter(const QString&);
+
+protected:
+ QModelIndex moveCursor(CursorAction, Qt::KeyboardModifiers);
+ bool event(QEvent* e);
+ QCMakeCacheModel* CacheModel;
+ QCMakeAdvancedFilter* AdvancedFilter;
+ QSortFilterProxyModel* SearchFilter;
+};
+
+/// Qt model class for cache properties
+class QCMakeCacheModel : public QStandardItemModel
+{
+ Q_OBJECT
+public:
+ QCMakeCacheModel(QObject* parent);
+ ~QCMakeCacheModel();
+
+ // roles used to retrieve extra data such has help strings, types of
+ // properties, and the advanced flag
+ enum
+ {
+ HelpRole = Qt::ToolTipRole,
+ TypeRole = Qt::UserRole,
+ AdvancedRole,
+ StringsRole,
+ GroupRole
+ };
+
+ enum ViewType
+ {
+ FlatView,
+ GroupView
+ };
+
+public slots:
+ // set a list of properties. This list will be sorted and grouped according
+ // to prefix. Any property that existed already and which is found in this
+ // list of properties to set will become an old property. All others will
+ // become new properties and be marked red.
+ void setProperties(const QCMakePropertyList& props);
+
+ // set whether to show new properties in red
+ void setShowNewProperties(bool);
+
+ // clear everything from the model
+ void clear();
+
+ // set flag whether the model can currently be edited.
+ void setEditEnabled(bool);
+
+ // insert a new property at a row specifying all the information about the
+ // property
+ bool insertProperty(QCMakeProperty::PropertyType t, const QString& name,
+ const QString& description, const QVariant& value,
+ bool advanced);
+
+ // set the view type
+ void setViewType(ViewType t);
+ ViewType viewType() const;
+
+public:
+ // get the properties
+ QCMakePropertyList properties() const;
+
+ // editing enabled
+ bool editEnabled() const;
+
+ // returns how many new properties there are
+ int newPropertyCount() const;
+
+ // return flags (overloaded to modify flag based on EditEnabled flag)
+ Qt::ItemFlags flags(const QModelIndex& index) const;
+ QModelIndex buddy(const QModelIndex& idx) const;
+
+ // get the data in the model for this property
+ void getPropertyData(const QModelIndex& idx1, QCMakeProperty& prop) const;
+
+protected:
+ bool EditEnabled;
+ int NewPropertyCount;
+ bool ShowNewProperties;
+ ViewType View;
+
+ // set the data in the model for this property
+ void setPropertyData(const QModelIndex& idx1, const QCMakeProperty& p,
+ bool isNew);
+
+ // breaks up he property list into groups
+ // where each group has the same prefix up to the first underscore
+ static void breakProperties(const QSet<QCMakeProperty>& props,
+ QMap<QString, QCMakePropertyList>& result);
+
+ // gets the prefix of a string up to the first _
+ static QString prefix(const QString& s);
+};
+
+/// Qt delegate class for interaction (or other customization)
+/// with cache properties
+class QCMakeCacheModelDelegate : public QItemDelegate
+{
+ Q_OBJECT
+public:
+ QCMakeCacheModelDelegate(QObject* p);
+ /// create our own editors for cache properties
+ QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option,
+ const QModelIndex& index) const;
+ bool editorEvent(QEvent* event, QAbstractItemModel* model,
+ const QStyleOptionViewItem& option,
+ const QModelIndex& index);
+ bool eventFilter(QObject* object, QEvent* event);
+ void setModelData(QWidget* editor, QAbstractItemModel* model,
+ const QModelIndex& index) const;
+ QSize sizeHint(const QStyleOptionViewItem& option,
+ const QModelIndex& index) const;
+
+ QSet<QCMakeProperty> changes() const;
+ void clearChanges();
+
+protected slots:
+ void setFileDialogFlag(bool);
+
+protected:
+ bool FileDialogFlag;
+ // record a change to an item in the model.
+ // this simply saves the item in the set of changes
+ void recordChange(QAbstractItemModel* model, const QModelIndex& index);
+
+ // properties changed by user via this delegate
+ QSet<QCMakeProperty> mChanges;
+};
+
+#endif
diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx
new file mode 100644
index 0000000..6a55a76
--- /dev/null
+++ b/Source/QtDialog/QCMakeWidgets.cxx
@@ -0,0 +1,118 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMakeWidgets.h"
+
+#include <QDirModel>
+#include <QFileDialog>
+#include <QFileInfo>
+#include <QResizeEvent>
+#include <QToolButton>
+
+QCMakeFileEditor::QCMakeFileEditor(QWidget* p, const QString& var)
+ : QLineEdit(p)
+ , Variable(var)
+{
+ this->ToolButton = new QToolButton(this);
+ this->ToolButton->setText("...");
+ this->ToolButton->setCursor(QCursor(Qt::ArrowCursor));
+ QObject::connect(this->ToolButton, SIGNAL(clicked(bool)), this,
+ SLOT(chooseFile()));
+}
+
+QCMakeFilePathEditor::QCMakeFilePathEditor(QWidget* p, const QString& var)
+ : QCMakeFileEditor(p, var)
+{
+ this->setCompleter(new QCMakeFileCompleter(this, false));
+}
+
+QCMakePathEditor::QCMakePathEditor(QWidget* p, const QString& var)
+ : QCMakeFileEditor(p, var)
+{
+ this->setCompleter(new QCMakeFileCompleter(this, true));
+}
+
+void QCMakeFileEditor::resizeEvent(QResizeEvent* e)
+{
+ // make the tool button fit on the right side
+ int h = e->size().height();
+ // move the line edit to make room for the tool button
+ this->setContentsMargins(0, 0, h, 0);
+ // put the tool button in its place
+ this->ToolButton->resize(h, h);
+ this->ToolButton->move(this->width() - h, 0);
+}
+
+void QCMakeFilePathEditor::chooseFile()
+{
+ // choose a file and set it
+ QString path;
+ QFileInfo info(this->text());
+ QString title;
+ if (this->Variable.isEmpty()) {
+ title = tr("Select File");
+ } else {
+ title = tr("Select File for %1");
+ title = title.arg(this->Variable);
+ }
+ this->fileDialogExists(true);
+ path =
+ QFileDialog::getOpenFileName(this, title, info.absolutePath(), QString(),
+ CM_NULLPTR, QFileDialog::DontResolveSymlinks);
+ this->fileDialogExists(false);
+
+ if (!path.isEmpty()) {
+ this->setText(QDir::fromNativeSeparators(path));
+ }
+}
+
+void QCMakePathEditor::chooseFile()
+{
+ // choose a file and set it
+ QString path;
+ QString title;
+ if (this->Variable.isEmpty()) {
+ title = tr("Select Path");
+ } else {
+ title = tr("Select Path for %1");
+ title = title.arg(this->Variable);
+ }
+ this->fileDialogExists(true);
+ path = QFileDialog::getExistingDirectory(this, title, this->text(),
+ QFileDialog::ShowDirsOnly |
+ QFileDialog::DontResolveSymlinks);
+ this->fileDialogExists(false);
+ if (!path.isEmpty()) {
+ this->setText(QDir::fromNativeSeparators(path));
+ }
+}
+
+// use same QDirModel for all completers
+static QDirModel* fileDirModel()
+{
+ static QDirModel* m = CM_NULLPTR;
+ if (!m) {
+ m = new QDirModel();
+ }
+ return m;
+}
+static QDirModel* pathDirModel()
+{
+ static QDirModel* m = CM_NULLPTR;
+ if (!m) {
+ m = new QDirModel();
+ m->setFilter(QDir::AllDirs | QDir::Drives | QDir::NoDotAndDotDot);
+ }
+ return m;
+}
+
+QCMakeFileCompleter::QCMakeFileCompleter(QObject* o, bool dirs)
+ : QCompleter(o)
+{
+ QDirModel* m = dirs ? pathDirModel() : fileDirModel();
+ this->setModel(m);
+}
+
+QString QCMakeFileCompleter::pathFromIndex(const QModelIndex& idx) const
+{
+ return QDir::fromNativeSeparators(QCompleter::pathFromIndex(idx));
+}
diff --git a/Source/QtDialog/QCMakeWidgets.h b/Source/QtDialog/QCMakeWidgets.h
new file mode 100644
index 0000000..0db810c
--- /dev/null
+++ b/Source/QtDialog/QCMakeWidgets.h
@@ -0,0 +1,82 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef QCMakeWidgets_h
+#define QCMakeWidgets_h
+
+#include <cmConfigure.h>
+
+#include <QComboBox>
+#include <QCompleter>
+#include <QLineEdit>
+
+class QToolButton;
+
+// common widgets for Qt based CMake
+
+/// Editor widget for editing paths or file paths
+class QCMakeFileEditor : public QLineEdit
+{
+ Q_OBJECT
+public:
+ QCMakeFileEditor(QWidget* p, const QString& var);
+protected slots:
+ virtual void chooseFile() = 0;
+signals:
+ void fileDialogExists(bool);
+
+protected:
+ void resizeEvent(QResizeEvent* e);
+ QToolButton* ToolButton;
+ QString Variable;
+};
+
+/// editor widget for editing files
+class QCMakePathEditor : public QCMakeFileEditor
+{
+ Q_OBJECT
+public:
+ QCMakePathEditor(QWidget* p = CM_NULLPTR, const QString& var = QString());
+ void chooseFile();
+};
+
+/// editor widget for editing paths
+class QCMakeFilePathEditor : public QCMakeFileEditor
+{
+ Q_OBJECT
+public:
+ QCMakeFilePathEditor(QWidget* p = CM_NULLPTR,
+ const QString& var = QString());
+ void chooseFile();
+};
+
+/// completer class that returns native cmake paths
+class QCMakeFileCompleter : public QCompleter
+{
+ Q_OBJECT
+public:
+ QCMakeFileCompleter(QObject* o, bool dirs);
+ virtual QString pathFromIndex(const QModelIndex& idx) const;
+};
+
+// editor for strings
+class QCMakeComboBox : public QComboBox
+{
+ Q_OBJECT
+ Q_PROPERTY(QString value READ currentText WRITE setValue USER true);
+
+public:
+ QCMakeComboBox(QWidget* p, QStringList strings)
+ : QComboBox(p)
+ {
+ this->addItems(strings);
+ }
+ void setValue(const QString& v)
+ {
+ int i = this->findText(v);
+ if (i != -1) {
+ this->setCurrentIndex(i);
+ }
+ }
+};
+
+#endif
diff --git a/Source/QtDialog/QtDialogCPack.cmake.in b/Source/QtDialog/QtDialogCPack.cmake.in
new file mode 100644
index 0000000..7ae8605
--- /dev/null
+++ b/Source/QtDialog/QtDialogCPack.cmake.in
@@ -0,0 +1,15 @@
+set(IS_APPLE @APPLE@)
+set(CMAKE_PACKAGE_QTGUI @CMAKE_PACKAGE_QTGUI@)
+
+if(CMAKE_PACKAGE_QTGUI)
+ set(CPACK_PACKAGE_EXECUTABLES "cmake-gui" "CMake (cmake-gui)" ${CPACK_PACKAGE_EXECUTABLES})
+ set(CPACK_CREATE_DESKTOP_LINKS "cmake-gui" ${CPACK_CREATE_DESKTOP_LINKS})
+ if(IS_APPLE)
+ # for apple install we set the install prefix to
+ # / and then install
+ # cmake into the bundle for cmake-gui and must use DESTDIR
+ set(CPACK_SET_DESTDIR TRUE)
+ endif()
+endif()
+
+
diff --git a/Source/QtDialog/RegexExplorer.cxx b/Source/QtDialog/RegexExplorer.cxx
new file mode 100644
index 0000000..1512166
--- /dev/null
+++ b/Source/QtDialog/RegexExplorer.cxx
@@ -0,0 +1,136 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "RegexExplorer.h"
+
+RegexExplorer::RegexExplorer(QWidget* p)
+ : QDialog(p)
+ , m_matched(false)
+{
+ this->setupUi(this);
+
+ for (int i = 1; i < cmsys::RegularExpression::NSUBEXP; ++i) {
+ matchNumber->addItem(QString("Match %1").arg(QString::number(i)),
+ QVariant(i));
+ }
+ matchNumber->setCurrentIndex(0);
+}
+
+void RegexExplorer::setStatusColor(QWidget* widget, bool successful)
+{
+ QColor color = successful ? QColor(0, 127, 0) : Qt::red;
+
+ QPalette palette = widget->palette();
+ palette.setColor(QPalette::Foreground, color);
+ widget->setPalette(palette);
+}
+
+void RegexExplorer::on_regularExpression_textChanged(const QString& text)
+{
+#ifdef QT_NO_STL
+ m_regex = text.toAscii().constData();
+#else
+ m_regex = text.toStdString();
+#endif
+
+ bool validExpression =
+ stripEscapes(m_regex) && m_regexParser.compile(m_regex);
+ if (!validExpression) {
+ m_regexParser.set_invalid();
+ }
+
+ setStatusColor(labelRegexValid, validExpression);
+
+ on_inputText_textChanged();
+}
+
+void RegexExplorer::on_inputText_textChanged()
+{
+ if (m_regexParser.is_valid()) {
+ QString plainText = inputText->toPlainText();
+#ifdef QT_NO_STL
+ m_text = plainText.toAscii().constData();
+#else
+ m_text = plainText.toStdString();
+#endif
+ m_matched = m_regexParser.find(m_text);
+ } else {
+ m_matched = false;
+ }
+
+ setStatusColor(labelRegexMatch, m_matched);
+
+ if (!m_matched) {
+ clearMatch();
+ return;
+ }
+
+#ifdef QT_NO_STL
+ QString matchText = m_regexParser.match(0).c_str();
+#else
+ QString matchText = QString::fromStdString(m_regexParser.match(0));
+#endif
+ match0->setPlainText(matchText);
+
+ on_matchNumber_currentIndexChanged(matchNumber->currentIndex());
+}
+
+void RegexExplorer::on_matchNumber_currentIndexChanged(int index)
+{
+ if (!m_matched) {
+ return;
+ }
+
+ QVariant itemData = matchNumber->itemData(index);
+ int idx = itemData.toInt();
+
+ if (idx < 1 || idx >= cmsys::RegularExpression::NSUBEXP) {
+ return;
+ }
+
+#ifdef QT_NO_STL
+ QString match = m_regexParser.match(idx).c_str();
+#else
+ QString match = QString::fromStdString(m_regexParser.match(idx));
+#endif
+ matchN->setPlainText(match);
+}
+
+void RegexExplorer::clearMatch()
+{
+ match0->clear();
+ matchN->clear();
+}
+
+bool RegexExplorer::stripEscapes(std::string& source)
+{
+ const char* in = source.c_str();
+
+ std::string result;
+ result.reserve(source.size());
+
+ for (char inc = *in; inc != '\0'; inc = *++in) {
+ if (inc == '\\') {
+ char nextc = in[1];
+ if (nextc == 't') {
+ result.append(1, '\t');
+ in++;
+ } else if (nextc == 'n') {
+ result.append(1, '\n');
+ in++;
+ } else if (nextc == 't') {
+ result.append(1, '\t');
+ in++;
+ } else if (isalnum(nextc) || nextc == '\0') {
+ return false;
+ } else {
+ result.append(1, nextc);
+ in++;
+ }
+ } else {
+ result.append(1, inc);
+ }
+ }
+
+ source = result;
+ return true;
+}
diff --git a/Source/QtDialog/RegexExplorer.h b/Source/QtDialog/RegexExplorer.h
new file mode 100644
index 0000000..f1c1e5f
--- /dev/null
+++ b/Source/QtDialog/RegexExplorer.h
@@ -0,0 +1,38 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef RegexExplorer_h
+#define RegexExplorer_h
+
+#include <QDialog>
+#include <cmsys/RegularExpression.hxx>
+#include <string>
+
+#include "ui_RegexExplorer.h"
+
+class QString;
+class QWidget;
+
+class RegexExplorer : public QDialog, public Ui::RegexExplorer
+{
+ Q_OBJECT
+public:
+ RegexExplorer(QWidget* p);
+
+private slots:
+ void on_regularExpression_textChanged(const QString& text);
+ void on_inputText_textChanged();
+ void on_matchNumber_currentIndexChanged(int index);
+
+private:
+ static void setStatusColor(QWidget* widget, bool successful);
+ static bool stripEscapes(std::string& regex);
+
+ void clearMatch();
+
+ cmsys::RegularExpression m_regexParser;
+ std::string m_text;
+ std::string m_regex;
+ bool m_matched;
+};
+
+#endif
diff --git a/Source/QtDialog/RegexExplorer.ui b/Source/QtDialog/RegexExplorer.ui
new file mode 100644
index 0000000..2c2d761
--- /dev/null
+++ b/Source/QtDialog/RegexExplorer.ui
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RegexExplorer</class>
+ <widget class="QDialog" name="RegexExplorer">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>639</width>
+ <height>555</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Regular Expression Explorer</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Input Text</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="inputText"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Regular Expression</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelRegexValid">
+ <property name="text">
+ <string>Valid</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelRegexMatch">
+ <property name="text">
+ <string>Match</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="regularExpression"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Complete Match</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="match0">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QComboBox" name="matchNumber">
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="matchN">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Source/QtDialog/WarningMessagesDialog.cxx b/Source/QtDialog/WarningMessagesDialog.cxx
new file mode 100644
index 0000000..f608a84
--- /dev/null
+++ b/Source/QtDialog/WarningMessagesDialog.cxx
@@ -0,0 +1,86 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "WarningMessagesDialog.h"
+
+WarningMessagesDialog::WarningMessagesDialog(QWidget* prnt, QCMake* instance)
+ : QDialog(prnt)
+ , cmakeInstance(instance)
+{
+ this->setupUi(this);
+ this->setInitialValues();
+ this->setupSignals();
+}
+
+void WarningMessagesDialog::setInitialValues()
+{
+ this->suppressDeveloperWarnings->setChecked(
+ this->cmakeInstance->getSuppressDevWarnings());
+ this->suppressDeprecatedWarnings->setChecked(
+ this->cmakeInstance->getSuppressDeprecatedWarnings());
+
+ this->developerWarningsAsErrors->setChecked(
+ this->cmakeInstance->getDevWarningsAsErrors());
+ this->deprecatedWarningsAsErrors->setChecked(
+ this->cmakeInstance->getDeprecatedWarningsAsErrors());
+}
+
+void WarningMessagesDialog::setupSignals()
+{
+ QObject::connect(this->buttonBox, SIGNAL(accepted()), this,
+ SLOT(doAccept()));
+
+ QObject::connect(this->suppressDeveloperWarnings, SIGNAL(stateChanged(int)),
+ this, SLOT(doSuppressDeveloperWarningsChanged(int)));
+ QObject::connect(this->suppressDeprecatedWarnings, SIGNAL(stateChanged(int)),
+ this, SLOT(doSuppressDeprecatedWarningsChanged(int)));
+
+ QObject::connect(this->developerWarningsAsErrors, SIGNAL(stateChanged(int)),
+ this, SLOT(doDeveloperWarningsAsErrorsChanged(int)));
+ QObject::connect(this->deprecatedWarningsAsErrors, SIGNAL(stateChanged(int)),
+ this, SLOT(doDeprecatedWarningsAsErrorsChanged(int)));
+}
+
+void WarningMessagesDialog::doAccept()
+{
+ this->cmakeInstance->setSuppressDevWarnings(
+ this->suppressDeveloperWarnings->isChecked());
+ this->cmakeInstance->setSuppressDeprecatedWarnings(
+ this->suppressDeprecatedWarnings->isChecked());
+
+ this->cmakeInstance->setDevWarningsAsErrors(
+ this->developerWarningsAsErrors->isChecked());
+ this->cmakeInstance->setDeprecatedWarningsAsErrors(
+ this->deprecatedWarningsAsErrors->isChecked());
+}
+
+void WarningMessagesDialog::doSuppressDeveloperWarningsChanged(int state)
+{
+ // no warnings implies no errors either
+ if (state) {
+ this->developerWarningsAsErrors->setChecked(false);
+ }
+}
+
+void WarningMessagesDialog::doSuppressDeprecatedWarningsChanged(int state)
+{
+ // no warnings implies no errors either
+ if (state) {
+ this->deprecatedWarningsAsErrors->setChecked(false);
+ }
+}
+
+void WarningMessagesDialog::doDeveloperWarningsAsErrorsChanged(int state)
+{
+ // warnings as errors implies warnings are not suppressed
+ if (state) {
+ this->suppressDeveloperWarnings->setChecked(false);
+ }
+}
+
+void WarningMessagesDialog::doDeprecatedWarningsAsErrorsChanged(int state)
+{
+ // warnings as errors implies warnings are not suppressed
+ if (state) {
+ this->suppressDeprecatedWarnings->setChecked(false);
+ }
+}
diff --git a/Source/QtDialog/WarningMessagesDialog.h b/Source/QtDialog/WarningMessagesDialog.h
new file mode 100644
index 0000000..acb830d
--- /dev/null
+++ b/Source/QtDialog/WarningMessagesDialog.h
@@ -0,0 +1,65 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef WarningMessagesDialog_h
+#define WarningMessagesDialog_h
+
+#include <QDialog>
+#include <QWidget>
+
+#include "QCMake.h"
+#include "ui_WarningMessagesDialog.h"
+
+/**
+ * Dialog window for setting the warning message related options.
+ */
+class WarningMessagesDialog : public QDialog, public Ui_MessagesDialog
+{
+ Q_OBJECT
+
+public:
+ WarningMessagesDialog(QWidget* prnt, QCMake* instance);
+
+private slots:
+ /**
+ * Handler for the accept event of the ok/cancel button box.
+ */
+ void doAccept();
+
+ /**
+ * Handler for checked state changed event of the suppress developer warnings
+ * checkbox.
+ */
+ void doSuppressDeveloperWarningsChanged(int state);
+ /**
+ * Handler for checked state changed event of the suppress deprecated
+ * warnings checkbox.
+ */
+ void doSuppressDeprecatedWarningsChanged(int state);
+
+ /**
+ * Handler for checked state changed event of the developer warnings as
+ * errors checkbox.
+ */
+ void doDeveloperWarningsAsErrorsChanged(int state);
+ /**
+ * Handler for checked state changed event of the deprecated warnings as
+ * errors checkbox.
+ */
+ void doDeprecatedWarningsAsErrorsChanged(int state);
+
+private:
+ QCMake* cmakeInstance;
+
+ /**
+ * Set the initial values of the widgets on this dialog window, using the
+ * current state of the cache.
+ */
+ void setInitialValues();
+
+ /**
+ * Setup the signals for the widgets on this dialog window.
+ */
+ void setupSignals();
+};
+
+#endif /* MessageDialog_h */
diff --git a/Source/QtDialog/WarningMessagesDialog.ui b/Source/QtDialog/WarningMessagesDialog.ui
new file mode 100644
index 0000000..3b35cbc
--- /dev/null
+++ b/Source/QtDialog/WarningMessagesDialog.ui
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MessagesDialog</class>
+ <widget class="QDialog" name="MessagesDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Warning Messages</string>
+ </property>
+ <property name="modal">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Suppress Warnings</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="suppressDeveloperWarnings">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Suppress developer (author) warnings.</string>
+ </property>
+ <property name="text">
+ <string>Developer Warnings</string>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="suppressDeprecatedWarnings">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Suppress deprecated warnings.</string>
+ </property>
+ <property name="text">
+ <string>Deprecated Warnings</string>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Warnings as Errors</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QCheckBox" name="developerWarningsAsErrors">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Treat developer (author) warnings as errors.</string>
+ </property>
+ <property name="text">
+ <string>Developer Warnings as Errors</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="deprecatedWarningsAsErrors">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Treat deprecated warnings as errors.</string>
+ </property>
+ <property name="text">
+ <string>Deprecated Warnings as Errors</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>MessagesDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>MessagesDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/Source/QtDialog/cmakecache.xml b/Source/QtDialog/cmakecache.xml
new file mode 100644
index 0000000..a13b5b1
--- /dev/null
+++ b/Source/QtDialog/cmakecache.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+ <mime-type type="application/x-cmakecache">
+ <comment>CMake cache file</comment>
+ <glob pattern="CMakeCache.txt"/>
+ <sub-class-of type="text/plain"/>
+ </mime-type>
+</mime-info>