ENH: Beginnings of a Qt UI for CMake.

This commit is contained in:
Clinton Stimpson 2007-11-02 11:50:17 -04:00
parent dcf21dd90b
commit 800cbd0550
11 changed files with 1007 additions and 0 deletions

View File

@ -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)

View File

@ -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();
}

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/Icons" >
<file>CMakeSetupDialog.png</file>
</qresource>
</RCC>

View File

@ -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;
}
}

View File

@ -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;
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

View File

@ -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>

179
Source/QtDialog/QCMake.cxx Normal file
View File

@ -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);
}

78
Source/QtDialog/QCMake.h Normal file
View File

@ -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

View File

@ -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();
}

View File

@ -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