From 800cbd0550466794cf853c6fb4dc0349e245220c Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Fri, 2 Nov 2007 11:50:17 -0400 Subject: [PATCH] ENH: Beginnings of a Qt UI for CMake. --- Source/QtDialog/CMakeLists.txt | 37 +++++ Source/QtDialog/CMakeSetup.cxx | 21 +++ Source/QtDialog/CMakeSetup.qrc | 5 + Source/QtDialog/CMakeSetupDialog.cxx | 193 +++++++++++++++++++++++++++ Source/QtDialog/CMakeSetupDialog.h | 47 +++++++ Source/QtDialog/CMakeSetupDialog.png | Bin 0 -> 358 bytes Source/QtDialog/CMakeSetupDialog.ui | 155 +++++++++++++++++++++ Source/QtDialog/QCMake.cxx | 179 +++++++++++++++++++++++++ Source/QtDialog/QCMake.h | 78 +++++++++++ Source/QtDialog/QCMakeCacheView.cxx | 192 ++++++++++++++++++++++++++ Source/QtDialog/QCMakeCacheView.h | 100 ++++++++++++++ 11 files changed, 1007 insertions(+) create mode 100644 Source/QtDialog/CMakeLists.txt create mode 100644 Source/QtDialog/CMakeSetup.cxx create mode 100644 Source/QtDialog/CMakeSetup.qrc create mode 100644 Source/QtDialog/CMakeSetupDialog.cxx create mode 100644 Source/QtDialog/CMakeSetupDialog.h create mode 100644 Source/QtDialog/CMakeSetupDialog.png create mode 100644 Source/QtDialog/CMakeSetupDialog.ui create mode 100644 Source/QtDialog/QCMake.cxx create mode 100644 Source/QtDialog/QCMake.h create mode 100644 Source/QtDialog/QCMakeCacheView.cxx create mode 100644 Source/QtDialog/QCMakeCacheView.h diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt new file mode 100644 index 000000000..b6cd7b1dd --- /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 000000000..655a4cf79 --- /dev/null +++ b/Source/QtDialog/CMakeSetup.cxx @@ -0,0 +1,21 @@ + +#include + +#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 000000000..14357e036 --- /dev/null +++ b/Source/QtDialog/CMakeSetup.qrc @@ -0,0 +1,5 @@ + + + CMakeSetupDialog.png + + diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx new file mode 100644 index 000000000..7f2ab1dcb --- /dev/null +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -0,0 +1,193 @@ + +#include "CMakeSetupDialog.h" + +#include +#include +#include +#include + +#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 000000000..71a51d923 --- /dev/null +++ b/Source/QtDialog/CMakeSetupDialog.h @@ -0,0 +1,47 @@ + +#include +#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 0000000000000000000000000000000000000000..7bbcee413c54c4d10e0c484c4d57a3c3eb0f9761 GIT binary patch literal 358 zcmV-s0h#`ZP);p`P#|k5gaOX1ehQ$a*%U$mXICEv z7-=R2H^3FuhXC42o$&b59kXA>0ZNg9W0pk{oh`_NlMgoiG zN01^BD}@Y@C$4zu6(C2|=fK*##ijCGFx&8#y8X}T3*E!3SIemRGXMYp07*qoM6N<$ Eg5PG87XSbN literal 0 HcmV?d00001 diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui new file mode 100644 index 000000000..9080f98e6 --- /dev/null +++ b/Source/QtDialog/CMakeSetupDialog.ui @@ -0,0 +1,155 @@ + + CMakeSetupDialog + + + + 0 + 0 + 650 + 505 + + + + CMakeSetup + + + :/Icons/CMakeSetupDialog.png + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Where is the source code: + + + + + + + + + + Browse... + + + + + + + Where to build the binaries: + + + + + + + true + + + + + + + Browse... + + + + + + + true + + + QAbstractItemView::SelectRows + + + + + + + + + Configure + + + + + + + Ok + + + + + + + Cancel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + 0 + 650 + 29 + + + + + + + + QCMakeCacheView + QTableView +
QCMakeCacheView.h
+
+
+ + + + +
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx new file mode 100644 index 000000000..53519b425 --- /dev/null +++ b/Source/QtDialog/QCMake.cxx @@ -0,0 +1,179 @@ + +#include "QCMake.h" + +#include +#include + +#include "cmake.h" +#include "cmCacheManager.h" +#include "cmSystemTools.h" + +QCMake::QCMake(QObject* p) + : QObject(p) +{ + static int metaId = qRegisterMetaType(); + static int metaIdList = qRegisterMetaType(); + + 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(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(cd); + emit self->error(title, msg, &stop); +} + diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h new file mode 100644 index 000000000..1e4b6614f --- /dev/null +++ b/Source/QtDialog/QCMake.h @@ -0,0 +1,78 @@ + +#ifndef __QCMake_h +#define __QCMake_h + +#include +#include +#include +#include + +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 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 000000000..f66f60fbe --- /dev/null +++ b/Source/QtDialog/QCMakeCacheView.cxx @@ -0,0 +1,192 @@ + +#include "QCMakeCacheView.h" + +#include +#include +#include +#include +#include + +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(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 000000000..a284ecdec --- /dev/null +++ b/Source/QtDialog/QCMakeCacheView.h @@ -0,0 +1,100 @@ + +#ifndef QCMakeCacheView_h +#define QCMakeCacheView_h + +#include +#include +#include +#include +#include + +#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 +