diff options
author | Clinton Stimpson <clinton@elemtech.com> | 2007-11-02 15:50:17 (GMT) |
---|---|---|
committer | Clinton Stimpson <clinton@elemtech.com> | 2007-11-02 15:50:17 (GMT) |
commit | 800cbd0550466794cf853c6fb4dc0349e245220c (patch) | |
tree | 6a55206bc76ac9a72f99906f341a8b7115879f8d /Source | |
parent | dcf21dd90b816d06b43716ce96e496fe3d591594 (diff) | |
download | CMake-800cbd0550466794cf853c6fb4dc0349e245220c.zip CMake-800cbd0550466794cf853c6fb4dc0349e245220c.tar.gz CMake-800cbd0550466794cf853c6fb4dc0349e245220c.tar.bz2 |
ENH: Beginnings of a Qt UI for CMake.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/QtDialog/CMakeLists.txt | 37 | ||||
-rw-r--r-- | Source/QtDialog/CMakeSetup.cxx | 21 | ||||
-rw-r--r-- | Source/QtDialog/CMakeSetup.qrc | 5 | ||||
-rw-r--r-- | Source/QtDialog/CMakeSetupDialog.cxx | 193 | ||||
-rw-r--r-- | Source/QtDialog/CMakeSetupDialog.h | 47 | ||||
-rw-r--r-- | Source/QtDialog/CMakeSetupDialog.png | bin | 0 -> 358 bytes | |||
-rw-r--r-- | Source/QtDialog/CMakeSetupDialog.ui | 155 | ||||
-rw-r--r-- | Source/QtDialog/QCMake.cxx | 179 | ||||
-rw-r--r-- | Source/QtDialog/QCMake.h | 78 | ||||
-rw-r--r-- | Source/QtDialog/QCMakeCacheView.cxx | 192 | ||||
-rw-r--r-- | Source/QtDialog/QCMakeCacheView.h | 100 |
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 Binary files differnew file mode 100644 index 0000000..7bbcee4 --- /dev/null +++ b/Source/QtDialog/CMakeSetupDialog.png 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 + |