summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClinton Stimpson <clinton@elemtech.com>2007-11-02 15:50:17 (GMT)
committerClinton Stimpson <clinton@elemtech.com>2007-11-02 15:50:17 (GMT)
commit800cbd0550466794cf853c6fb4dc0349e245220c (patch)
tree6a55206bc76ac9a72f99906f341a8b7115879f8d
parentdcf21dd90b816d06b43716ce96e496fe3d591594 (diff)
downloadCMake-800cbd0550466794cf853c6fb4dc0349e245220c.zip
CMake-800cbd0550466794cf853c6fb4dc0349e245220c.tar.gz
CMake-800cbd0550466794cf853c6fb4dc0349e245220c.tar.bz2
ENH: Beginnings of a Qt UI for CMake.
-rw-r--r--Source/QtDialog/CMakeLists.txt37
-rw-r--r--Source/QtDialog/CMakeSetup.cxx21
-rw-r--r--Source/QtDialog/CMakeSetup.qrc5
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx193
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h47
-rw-r--r--Source/QtDialog/CMakeSetupDialog.pngbin0 -> 358 bytes
-rw-r--r--Source/QtDialog/CMakeSetupDialog.ui155
-rw-r--r--Source/QtDialog/QCMake.cxx179
-rw-r--r--Source/QtDialog/QCMake.h78
-rw-r--r--Source/QtDialog/QCMakeCacheView.cxx192
-rw-r--r--Source/QtDialog/QCMakeCacheView.h100
11 files changed, 1007 insertions, 0 deletions
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
new file mode 100644
index 0000000..b6cd7b1
--- /dev/null
+++ b/Source/QtDialog/CMakeLists.txt
@@ -0,0 +1,37 @@
+
+SET(QT_MIN_VERSION "4.3.0")
+FIND_PACKAGE(Qt4 REQUIRED)
+
+IF(NOT QT4_FOUND)
+ MESSAGE(SEND_ERROR "Failed to find Qt4.")
+ELSE(NOT QT4_FOUND)
+ INCLUDE(${QT_USE_FILE})
+
+ SET(SRCS
+ CMakeSetup.cxx
+ CMakeSetupDialog.cxx
+ QCMake.cxx
+ QCMakeCacheView.cxx
+ )
+
+ QT4_WRAP_UI(UI_SRCS
+ CMakeSetupDialog.ui
+ )
+ QT4_WRAP_CPP(MOC_SRCS
+ CMakeSetupDialog.h
+ QCMake.h
+ QCMakeCacheView.h
+ )
+ QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc)
+
+ SET(SRCS ${SRCS} ${UI_SRCS} ${MOC_SRCS} ${RC_SRCS})
+
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+ ADD_EXECUTABLE(QtDialog WIN32 MACOSX_BUNDLE ${SRCS})
+ TARGET_LINK_LIBRARIES(QtDialog CMakeLib ${QT_LIBRARIES})
+ ADD_DEPENDENCIES(QtDialog cmake)
+
+ENDIF(NOT QT4_FOUND)
+
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
new file mode 100644
index 0000000..655a4cf
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -0,0 +1,21 @@
+
+#include <QApplication>
+
+#include "cmSystemTools.h"
+
+#include "CMakeSetupDialog.h"
+
+int main(int argc, char** argv)
+{
+ QApplication app(argc, argv);
+ app.setApplicationName("CMakeSetup");
+ app.setOrganizationName("Kitware");
+
+ // TODO handle CMake args
+
+ CMakeSetupDialog dialog;
+ dialog.show();
+
+ return app.exec();
+}
+
diff --git a/Source/QtDialog/CMakeSetup.qrc b/Source/QtDialog/CMakeSetup.qrc
new file mode 100644
index 0000000..14357e0
--- /dev/null
+++ b/Source/QtDialog/CMakeSetup.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/Icons" >
+ <file>CMakeSetupDialog.png</file>
+ </qresource>
+</RCC>
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
new file mode 100644
index 0000000..7f2ab1d
--- /dev/null
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -0,0 +1,193 @@
+
+#include "CMakeSetupDialog.h"
+
+#include <QFileDialog>
+#include <QThread>
+#include <QProgressBar>
+#include <QMessageBox>
+
+#include "QCMake.h"
+#include "QCMakeCacheView.h"
+
+// QCMake instance on a thread
+class QCMakeThread : public QThread
+{
+public:
+ QCMakeThread(QObject* p) : QThread(p) { }
+ QCMake* CMakeInstance;
+
+protected:
+ virtual void run()
+ {
+ this->CMakeInstance = new QCMake;
+ this->exec();
+ delete this->CMakeInstance;
+ }
+};
+
+CMakeSetupDialog::CMakeSetupDialog()
+{
+ // create the GUI
+ this->setupUi(this);
+ this->ProgressBar = new QProgressBar();
+ this->ProgressBar->setRange(0,100);
+ this->statusBar()->addPermanentWidget(this->ProgressBar);
+
+ // start the cmake worker thread
+ this->CMakeThread = new QCMakeThread(this);
+ // TODO does this guarantee the QCMake instance is created before initialize is called?
+ QObject::connect(this->CMakeThread, SIGNAL(started()),
+ this, SLOT(initialize()));
+ this->CMakeThread->start();
+}
+
+void CMakeSetupDialog::initialize()
+{
+ // now the cmake worker thread is running, lets make our connections to it
+ QObject::connect(this->CMakeThread->CMakeInstance,
+ SIGNAL(propertiesChanged(const QCMakeCachePropertyList&)),
+ this->CacheValues->cacheModel(),
+ SLOT(setProperties(const QCMakeCachePropertyList&)));
+ QObject::connect(this,
+ SIGNAL(propertiesChanged(const QCMakeCachePropertyList&)),
+ this->CMakeThread->CMakeInstance,
+ SLOT(setProperties(const QCMakeCachePropertyList&)));
+
+ QObject::connect(this->configureButton, SIGNAL(clicked(bool)),
+ this, SLOT(doConfigure()));
+ QObject::connect(this, SIGNAL(configure()),
+ this->CMakeThread->CMakeInstance, SLOT(configure()));
+ QObject::connect(this->CMakeThread->CMakeInstance, SIGNAL(configureDone(int)),
+ this, SLOT(finishConfigure(int)));
+ QObject::connect(this->CMakeThread->CMakeInstance, SIGNAL(generateDone(int)),
+ this, SLOT(finishGenerate(int)));
+
+ QObject::connect(this->generateButton, SIGNAL(clicked(bool)),
+ this, SLOT(doOk()));
+ QObject::connect(this, SIGNAL(ok()),
+ this->CMakeThread->CMakeInstance, SLOT(generate()));
+
+ QObject::connect(this->cancelButton, SIGNAL(clicked(bool)),
+ this, SLOT(doCancel()));
+ QObject::connect(this, SIGNAL(cancel()),
+ this->CMakeThread->CMakeInstance, SLOT(interrupt()));
+
+ 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(textChanged(QString)),
+ this->CMakeThread->CMakeInstance, SLOT(setBinaryDirectory(QString)));
+
+ QObject::connect(this->CMakeThread->CMakeInstance, SIGNAL(sourceDirChanged(QString)),
+ this, SLOT(updateSourceDirectory(QString)));
+
+ QObject::connect(this->CMakeThread->CMakeInstance, SIGNAL(progressChanged(QString, float)),
+ this, SLOT(showProgress(QString,float)));
+
+ QObject::connect(this->CMakeThread->CMakeInstance, SIGNAL(error(QString, QString, bool*)),
+ this, SLOT(error(QString,QString,bool*)), Qt::BlockingQueuedConnection);
+
+}
+
+CMakeSetupDialog::~CMakeSetupDialog()
+{
+ // wait for thread to stop
+ this->CMakeThread->quit();
+ this->CMakeThread->wait();
+}
+
+void CMakeSetupDialog::doConfigure()
+{
+ emit this->propertiesChanged(this->CacheValues->cacheModel()->properties());
+ emit this->configure();
+}
+
+void CMakeSetupDialog::finishConfigure(int error)
+{
+ this->ProgressBar->reset();
+ this->statusBar()->showMessage("Configure Done", 2000);
+ if(error != 0)
+ {
+ bool dummy;
+ this->error("Error", "Error in configuration process, project files may be invalid", &dummy);
+ }
+}
+
+void CMakeSetupDialog::finishGenerate(int error)
+{
+ this->ProgressBar->reset();
+ this->statusBar()->showMessage("Generate Done", 2000);
+ if(error != 0)
+ {
+ bool dummy;
+ this->error("Error", "Error in generation process, project files may be invalid", &dummy);
+ }
+}
+
+void CMakeSetupDialog::doOk()
+{
+ emit this->ok();
+}
+
+void CMakeSetupDialog::doCancel()
+{
+ emit this->cancel();
+}
+
+void CMakeSetupDialog::doHelp()
+{
+}
+
+void CMakeSetupDialog::doSourceBrowse()
+{
+ QString dir = QFileDialog::getExistingDirectory(this, "TODO", this->SourceDirectory->text());
+ if(!dir.isEmpty())
+ {
+ this->updateSourceDirectory(dir);
+ }
+}
+
+void CMakeSetupDialog::updateSourceDirectory(const QString& dir)
+{
+ this->SourceDirectory->setText(dir);
+}
+
+void CMakeSetupDialog::doBinaryBrowse()
+{
+ QString dir = QFileDialog::getExistingDirectory(this, "TODO", this->BinaryDirectory->currentText());
+ if(!dir.isEmpty())
+ {
+ this->setBinaryDirectory(dir);
+ }
+}
+
+void CMakeSetupDialog::setBinaryDirectory(const QString& dir)
+{
+ if(dir != this->BinaryDirectory->currentText())
+ {
+ this->BinaryDirectory->setEditText(dir);
+ }
+}
+
+void CMakeSetupDialog::showProgress(const QString& msg, float percent)
+{
+ if(percent >= 0)
+ {
+ this->statusBar()->showMessage(msg);
+ this->ProgressBar->setValue(qRound(percent * 100));
+ }
+}
+
+void CMakeSetupDialog::error(const QString& title, const QString& message, bool* cancel)
+{
+ QMessageBox::StandardButton btn =
+ QMessageBox::critical(this, title, message, QMessageBox::Ok | QMessageBox::Cancel);
+ if(btn == QMessageBox::Cancel)
+ {
+ *cancel = false;
+ }
+}
+
+
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
new file mode 100644
index 0000000..71a51d9
--- /dev/null
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -0,0 +1,47 @@
+
+#include <QMainWindow>
+#include "ui_CMakeSetupDialog.h"
+#include "QCMake.h"
+
+class QCMakeThread;
+class CMakeCacheModel;
+class QProgressBar;
+
+/// Qt user interface for CMake
+class CMakeSetupDialog : public QMainWindow, public Ui::CMakeSetupDialog
+{
+ Q_OBJECT
+public:
+ CMakeSetupDialog();
+ ~CMakeSetupDialog();
+
+signals:
+ void configure();
+ void ok();
+ void cancel();
+ void propertiesChanged(const QCMakeCachePropertyList&);
+
+protected slots:
+ void initialize();
+ void doConfigure();
+ void doOk();
+ void doCancel();
+ void doHelp();
+ void finishConfigure(int error);
+ void finishGenerate(int error);
+ void error(const QString& title, const QString& message, bool* cancel);
+
+ void doSourceBrowse();
+ void doBinaryBrowse();
+ void updateSourceDirectory(const QString& dir);
+ void setBinaryDirectory(const QString& dir);
+
+ void showProgress(const QString& msg, float percent);
+
+protected:
+
+ QCMakeThread* CMakeThread;
+ QProgressBar* ProgressBar;
+
+};
+
diff --git a/Source/QtDialog/CMakeSetupDialog.png b/Source/QtDialog/CMakeSetupDialog.png
new file mode 100644
index 0000000..7bbcee4
--- /dev/null
+++ b/Source/QtDialog/CMakeSetupDialog.png
Binary files differ
diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui
new file mode 100644
index 0000000..9080f98
--- /dev/null
+++ b/Source/QtDialog/CMakeSetupDialog.ui
@@ -0,0 +1,155 @@
+<ui version="4.0" >
+ <class>CMakeSetupDialog</class>
+ <widget class="QMainWindow" name="CMakeSetupDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>650</width>
+ <height>505</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>CMakeSetup</string>
+ </property>
+ <property name="windowIcon" >
+ <iconset resource="CMakeSetup.qrc" >:/Icons/CMakeSetupDialog.png</iconset>
+ </property>
+ <widget class="QWidget" name="centralwidget" >
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QFrame" name="frame" >
+ <property name="frameShape" >
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </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="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...</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="editable" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QPushButton" name="BrowseBinaryDirectoryButton" >
+ <property name="text" >
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="3" >
+ <widget class="QCMakeCacheView" name="CacheValues" >
+ <property name="alternatingRowColors" >
+ <bool>true</bool>
+ </property>
+ <property name="selectionBehavior" >
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="3" >
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QPushButton" name="configureButton" >
+ <property name="text" >
+ <string>Configure</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="generateButton" >
+ <property name="text" >
+ <string>Ok</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancelButton" >
+ <property name="text" >
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>650</width>
+ <height>29</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar" />
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QCMakeCacheView</class>
+ <extends>QTableView</extends>
+ <header>QCMakeCacheView.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="CMakeSetup.qrc" />
+ </resources>
+ <connections/>
+</ui>
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
new file mode 100644
index 0000000..53519b4
--- /dev/null
+++ b/Source/QtDialog/QCMake.cxx
@@ -0,0 +1,179 @@
+
+#include "QCMake.h"
+
+#include <QCoreApplication>
+#include <QDir>
+
+#include "cmake.h"
+#include "cmCacheManager.h"
+#include "cmSystemTools.h"
+
+QCMake::QCMake(QObject* p)
+ : QObject(p)
+{
+ static int metaId = qRegisterMetaType<QCMakeCacheProperty>();
+ static int metaIdList = qRegisterMetaType<QCMakeCachePropertyList>();
+
+ QDir appDir(QCoreApplication::applicationDirPath());
+#if defined(Q_OS_WIN)
+ this->CMakeExecutable = appDir.filePath("cmake.exe");
+#elif defined(Q_OS_MAC)
+# error "need to implement for Mac OS X"
+#else
+ this->CMakeExecutable = appDir.filePath("cmake");
+#endif
+ // TODO: check for existence?
+
+ cmSystemTools::DisableRunCommandOutput();
+ cmSystemTools::SetRunCommandHideConsole(true);
+ cmSystemTools::SetErrorCallback(QCMake::errorCallback, this);
+
+ this->CMakeInstance = new cmake;
+ this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this);
+}
+
+QCMake::~QCMake()
+{
+ delete this->CMakeInstance;
+ //cmDynamicLoader::FlushCache();
+}
+
+void QCMake::loadCache(const QString& dir)
+{
+ this->setBinaryDirectory(dir);
+}
+
+void QCMake::setSourceDirectory(const QString& dir)
+{
+ this->SourceDirectory = dir;
+ emit this->sourceDirChanged(dir);
+}
+
+void QCMake::setBinaryDirectory(const QString& dir)
+{
+ cmCacheManager *cachem = this->CMakeInstance->GetCacheManager();
+ this->BinaryDirectory = dir;
+ this->CMakeInstance->GetCacheManager()->LoadCache(dir.toLocal8Bit().data());
+ QCMakeCachePropertyList props = this->properties();
+ emit this->propertiesChanged(props);
+ cmCacheManager::CacheIterator itm = cachem->NewIterator();
+ if ( itm.Find("CMAKE_HOME_DIRECTORY"))
+ {
+ setSourceDirectory(itm.GetValue());
+ }
+}
+
+
+void QCMake::setGenerator(const QString& generator)
+{
+}
+
+void QCMake::configure()
+{
+ this->CMakeInstance->SetHomeDirectory(this->SourceDirectory.toAscii().data());
+ this->CMakeInstance->SetStartDirectory(this->SourceDirectory.toAscii().data());
+ this->CMakeInstance->SetHomeOutputDirectory(this->BinaryDirectory.toAscii().data());
+ this->CMakeInstance->SetStartOutputDirectory(this->BinaryDirectory.toAscii().data());
+ this->CMakeInstance->SetGlobalGenerator(
+ this->CMakeInstance->CreateGlobalGenerator("Unix Makefiles")); // TODO
+ this->CMakeInstance->SetCMakeCommand(this->CMakeExecutable.toAscii().data());
+ this->CMakeInstance->LoadCache();
+
+ cmSystemTools::ResetErrorOccuredFlag();
+
+ int error = this->CMakeInstance->Configure();
+
+ emit this->propertiesChanged(this->properties());
+ emit this->configureDone(error);
+}
+
+void QCMake::generate()
+{
+ cmSystemTools::ResetErrorOccuredFlag();
+ int error = this->CMakeInstance->Generate();
+ emit this->generateDone(error);
+}
+
+void QCMake::setProperties(const QCMakeCachePropertyList& props)
+{
+ cmCacheManager *cachem = this->CMakeInstance->GetCacheManager();
+ cmCacheManager::CacheIterator it = cachem->NewIterator();
+ foreach(QCMakeCacheProperty prop, props)
+ {
+ if ( it.Find(prop.Key.toAscii().data()) )
+ {
+ it.SetValue(prop.Value.toAscii().data());
+ }
+ }
+}
+
+QCMakeCachePropertyList QCMake::properties()
+{
+ QCMakeCachePropertyList ret;
+
+ cmCacheManager *cachem = this->CMakeInstance->GetCacheManager();
+ for(cmCacheManager::CacheIterator i = cachem->NewIterator();
+ !i.IsAtEnd(); i.Next())
+ {
+
+ if(i.GetType() == cmCacheManager::INTERNAL ||
+ i.GetType() == cmCacheManager::STATIC)
+ {
+ continue;
+ }
+
+ QCMakeCacheProperty prop;
+ prop.Key = i.GetName();
+ prop.Help = i.GetProperty("HELPSTRING");
+ prop.Value = i.GetValue();
+ prop.Advanced = i.GetPropertyAsBool("ADVANCED");
+
+ if(i.GetType() == cmCacheManager::BOOL)
+ {
+ prop.Type = QCMakeCacheProperty::BOOL;
+ if(cmSystemTools::IsOn(prop.Value.toAscii().data()))
+ {
+ prop.Value = QString("ON");
+ }
+ else
+ {
+ prop.Value = QString("OFF");
+ }
+ }
+ else if(i.GetType() == cmCacheManager::PATH)
+ {
+ prop.Type = QCMakeCacheProperty::PATH;
+ }
+ else if(i.GetType() == cmCacheManager::FILEPATH)
+ {
+ prop.Type = QCMakeCacheProperty::FILEPATH;
+ }
+ else if(i.GetType() == cmCacheManager::STRING)
+ {
+ prop.Type = QCMakeCacheProperty::STRING;
+ }
+
+ ret.append(prop);
+ }
+
+ return ret;
+}
+
+void QCMake::interrupt()
+{
+ cmSystemTools::SetFatalErrorOccured();
+}
+
+void QCMake::progressCallback(const char* msg, float percent, void* cd)
+{
+ QCMake* self = reinterpret_cast<QCMake*>(cd);
+ emit self->progressChanged(msg, percent);
+ QCoreApplication::processEvents();
+}
+
+void QCMake::errorCallback(const char* msg, const char* title, bool& stop, void* cd)
+{
+ QCMake* self = reinterpret_cast<QCMake*>(cd);
+ emit self->error(title, msg, &stop);
+}
+
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
new file mode 100644
index 0000000..1e4b661
--- /dev/null
+++ b/Source/QtDialog/QCMake.h
@@ -0,0 +1,78 @@
+
+#ifndef __QCMake_h
+#define __QCMake_h
+
+#include <QObject>
+#include <QString>
+#include <QList>
+#include <QMetaType>
+
+class cmake;
+
+// struct to represent cache properties in Qt
+struct QCMakeCacheProperty
+{
+ enum PropertyType { BOOL, PATH, FILEPATH, STRING };
+ QString Key;
+ QString Value;
+ QString Help;
+ PropertyType Type;
+ bool Advanced;
+};
+
+// make types usable with QVariant
+Q_DECLARE_METATYPE(QCMakeCacheProperty)
+typedef QList<QCMakeCacheProperty> QCMakeCachePropertyList;
+Q_DECLARE_METATYPE(QCMakeCachePropertyList)
+
+// 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=0);
+ ~QCMake();
+
+public slots:
+ void loadCache(const QString& dir);
+ void setSourceDirectory(const QString& dir);
+ void setBinaryDirectory(const QString& dir);
+ void setGenerator(const QString& generator);
+ void configure();
+ void generate();
+ void setProperties(const QCMakeCachePropertyList&);
+ void interrupt();
+
+public:
+ QCMakeCachePropertyList properties();
+ QString binaryDirectory();
+ QString sourceDirectory();
+ QString generator();
+
+signals:
+ void propertiesChanged(const QCMakeCachePropertyList& vars);
+ void generatorChanged(const QString& gen);
+ void error(const QString& title, const QString& message, bool*);
+ void sourceDirChanged(const QString& dir);
+ void progressChanged(const QString& msg, float percent);
+ void configureDone(int error);
+ void generateDone(int error);
+ void configureReady();
+ void generateReady();
+
+protected:
+ cmake* CMakeInstance;
+
+ static void progressCallback(const char* msg, float percent, void* cd);
+ static void errorCallback(const char* msg, const char* title, bool&, void* cd);
+
+ QString SourceDirectory;
+ QString BinaryDirectory;
+ QString Generator;
+ QString CMakeExecutable;
+};
+
+#endif // __QCMake_h
+
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
new file mode 100644
index 0000000..f66f60f
--- /dev/null
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -0,0 +1,192 @@
+
+#include "QCMakeCacheView.h"
+
+#include <QToolButton>
+#include <QFileDialog>
+#include <QHBoxLayout>
+#include <QHeaderView>
+#include <QEvent>
+
+QCMakeCacheView::QCMakeCacheView(QWidget* p)
+ : QTableView(p)
+{
+ QCMakeCacheModel* m = new QCMakeCacheModel(this);
+ this->setModel(m);
+ this->horizontalHeader()->setStretchLastSection(true);
+ this->verticalHeader()->hide();
+
+ QCMakeCacheModelDelegate* delegate = new QCMakeCacheModelDelegate(this);
+ this->setItemDelegate(delegate);
+}
+
+bool QCMakeCacheView::event(QEvent* e)
+{
+ if(e->type() == QEvent::Polish)
+ {
+ // initialize the table view column size
+ int colWidth = this->columnWidth(0) + this->columnWidth(1);
+ this->setColumnWidth(0, colWidth/2);
+ this->setColumnWidth(1, colWidth/2);
+ }
+ return QTableView::event(e);
+}
+
+QCMakeCacheModel* QCMakeCacheView::cacheModel() const
+{
+ return qobject_cast<QCMakeCacheModel*>(this->model());
+}
+
+QCMakeCacheModel::QCMakeCacheModel(QObject* p)
+ : QAbstractTableModel(p)
+{
+}
+
+QCMakeCacheModel::~QCMakeCacheModel()
+{
+}
+
+void QCMakeCacheModel::setProperties(const QCMakeCachePropertyList& props)
+{
+ this->Properties = props;
+ this->reset();
+}
+
+QCMakeCachePropertyList QCMakeCacheModel::properties() const
+{
+ return this->Properties;
+}
+
+int QCMakeCacheModel::columnCount ( const QModelIndex & parent ) const
+{
+ return 2;
+}
+
+QVariant QCMakeCacheModel::data ( const QModelIndex & index, int role ) const
+{
+ if(index.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
+ {
+ return this->Properties[index.row()].Key;
+ }
+ else if(index.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
+ {
+ return this->Properties[index.row()].Value;
+ }
+ else if(role == QCMakeCacheModel::HelpRole)
+ {
+ return this->Properties[index.row()].Help;
+ }
+ else if(role == QCMakeCacheModel::TypeRole)
+ {
+ return this->Properties[index.row()].Type;
+ }
+ else if(role == QCMakeCacheModel::AdvancedRole)
+ {
+ return this->Properties[index.row()].Advanced;
+ }
+ return QVariant();
+}
+
+QModelIndex QCMakeCacheModel::parent ( const QModelIndex & index ) const
+{
+ return QModelIndex();
+}
+
+int QCMakeCacheModel::rowCount ( const QModelIndex & parent ) const
+{
+ if(parent.isValid())
+ return 0;
+ return this->Properties.count();
+}
+
+QVariant QCMakeCacheModel::headerData ( int section, Qt::Orientation orient, int role ) const
+{
+ if(role == Qt::DisplayRole && orient == Qt::Horizontal)
+ {
+ return section == 0 ? "Name" : "Value";
+ }
+ return QVariant();
+}
+
+Qt::ItemFlags QCMakeCacheModel::flags ( const QModelIndex& index ) const
+{
+ if(index.column() == 1)
+ {
+ return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
+ }
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
+
+
+bool QCMakeCacheModel::setData ( const QModelIndex & index, const QVariant& value, int role )
+{
+ if(index.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
+ {
+ this->Properties[index.row()].Key = value.toString();
+ }
+ else if(index.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
+ {
+ this->Properties[index.row()].Value = value.toString();
+ }
+ return false;
+}
+
+
+
+QCMakeCacheModelDelegate::QCMakeCacheModelDelegate(QObject* p)
+ : QItemDelegate(p)
+{
+}
+
+QWidget* QCMakeCacheModelDelegate::createEditor(QWidget* parent,
+ const QStyleOptionViewItem&, const QModelIndex& index) const
+{
+ QVariant type = index.data(QCMakeCacheModel::TypeRole);
+ if(type == QCMakeCacheProperty::BOOL)
+ {
+ return new QCMakeCacheBoolEditor(index.data().toString(), parent);
+ }
+ else if(type == QCMakeCacheProperty::PATH)
+ {
+ return new QCMakeCachePathEditor(index.data().toString(), parent);
+ }
+ else if(type == QCMakeCacheProperty::FILEPATH)
+ {
+ }
+
+ return new QLineEdit(parent);
+}
+
+
+QCMakeCachePathEditor::QCMakeCachePathEditor(const QString& file, QWidget* p)
+ : QWidget(p), LineEdit(this)
+{
+ QHBoxLayout* l = new QHBoxLayout(this);
+ l->setMargin(0);
+ l->setSpacing(0);
+ l->addWidget(&this->LineEdit);
+ QToolButton* tb = new QToolButton(this);
+ tb->setText("...");
+ l->addWidget(tb);
+ QObject::connect(tb, SIGNAL(clicked(bool)),
+ this, SLOT(chooseFile()));
+ this->LineEdit.setText(file);
+ tb->setFocusProxy(&this->LineEdit);
+ this->setFocusProxy(&this->LineEdit);
+}
+
+void QCMakeCachePathEditor::chooseFile()
+{
+ QString path = QFileDialog::getExistingDirectory(this, "TODO", this->value());
+ if(!path.isEmpty())
+ {
+ this->LineEdit.setText(path);
+ }
+}
+
+QString QCMakeCachePathEditor::value() const
+{
+ return this->LineEdit.text();
+}
+
+
+
diff --git a/Source/QtDialog/QCMakeCacheView.h b/Source/QtDialog/QCMakeCacheView.h
new file mode 100644
index 0000000..a284ecd
--- /dev/null
+++ b/Source/QtDialog/QCMakeCacheView.h
@@ -0,0 +1,100 @@
+
+#ifndef QCMakeCacheView_h
+#define QCMakeCacheView_h
+
+#include <QTableView>
+#include <QAbstractTableModel>
+#include <QComboBox>
+#include <QLineEdit>
+#include <QItemDelegate>
+
+#include "QCMake.h"
+class QCMakeCacheModel;
+
+
+/// Qt view class for cache properties
+class QCMakeCacheView : public QTableView
+{
+ Q_OBJECT
+public:
+ QCMakeCacheView(QWidget* p);
+
+ QCMakeCacheModel* cacheModel() const;
+
+protected:
+ bool event(QEvent*);
+};
+
+/// Qt model class for cache properties
+class QCMakeCacheModel : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ QCMakeCacheModel(QObject* parent);
+ ~QCMakeCacheModel();
+
+ enum { HelpRole = Qt::UserRole, TypeRole, AdvancedRole };
+
+public slots:
+ void setProperties(const QCMakeCachePropertyList& props);
+
+public:
+ int columnCount ( const QModelIndex & parent ) const;
+ QVariant data ( const QModelIndex & index, int role ) const;
+ QModelIndex parent ( const QModelIndex & index ) const;
+ int rowCount ( const QModelIndex & parent ) const;
+ QVariant headerData ( int section, Qt::Orientation orient, int role ) const;
+ Qt::ItemFlags flags ( const QModelIndex& index ) const;
+ bool setData ( const QModelIndex& index, const QVariant& value, int role );
+
+ QCMakeCachePropertyList properties() const;
+
+protected:
+ QCMakeCachePropertyList Properties;
+};
+
+/// Qt delegate class for interaction (or other customization) with cache properties
+class QCMakeCacheModelDelegate : public QItemDelegate
+{
+ Q_OBJECT
+public:
+ QCMakeCacheModelDelegate(QObject* p);
+ QWidget* createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
+};
+
+/// Editor widget for editing paths
+class QCMakeCachePathEditor : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QString value READ value USER true)
+public:
+ QCMakeCachePathEditor(const QString& file, QWidget* p);
+ QString value() const;
+protected slots:
+ void chooseFile();
+protected:
+ QLineEdit LineEdit;
+};
+
+/// Editor widget for editing file paths
+class QCMakeCacheFilePathEditor : public QWidget
+{
+};
+
+/// Editor widget for editing booleans
+class QCMakeCacheBoolEditor : public QComboBox
+{
+ Q_OBJECT
+ Q_PROPERTY(QString value READ currentText USER true)
+public:
+ QCMakeCacheBoolEditor(const QString& val, QWidget* p)
+ : QComboBox(p)
+ {
+ this->addItem("ON");
+ this->addItem("OFF");
+ this->setCurrentIndex(val == "ON" ? 0 : 1);
+ }
+};
+
+#endif
+