1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-06-17 17:32:18 +08:00
CMake/Source/QtDialog/QCMakeCacheView.cxx
Clinton Stimpson 1e91100599 ENH: Disable menu/buttons when doing configure.
Also disable generate until configure is done.
      Save more settings (last 10 binary directories, exit after generate,
                          last generator)
      Some UI tweaks for better layout.
      Support drag & drop of CMakeLists.txt/CMakeCache.txt files.
2007-11-06 19:25:43 -05:00

356 lines
9.2 KiB
C++

/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "QCMakeCacheView.h"
#include <QToolButton>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QEvent>
#include <QFileInfo>
#include <QStyle>
#include <QKeyEvent>
static QRegExp AdvancedRegExp[2] = { QRegExp("(false)"), QRegExp("(true|false)") };
QCMakeCacheView::QCMakeCacheView(QWidget* p)
: QTableView(p), Init(false)
{
// hook up our model and search/filter proxies
this->CacheModel = new QCMakeCacheModel(this);
this->AdvancedFilter = new QSortFilterProxyModel(this);
this->AdvancedFilter->setSourceModel(this->CacheModel);
this->AdvancedFilter->setFilterRole(QCMakeCacheModel::AdvancedRole);
this->AdvancedFilter->setFilterRegExp(AdvancedRegExp[0]);
this->SearchFilter = new QSortFilterProxyModel(this);
this->SearchFilter->setSourceModel(this->AdvancedFilter);
this->SearchFilter->setFilterCaseSensitivity(Qt::CaseInsensitive);
this->setModel(this->SearchFilter);
// our delegate for creating our editors
QCMakeCacheModelDelegate* delegate = new QCMakeCacheModelDelegate(this);
this->setItemDelegate(delegate);
// set up headers and sizes
int h = 0;
QFontMetrics met(this->font());
h = qMax(met.height(), this->style()->pixelMetric(QStyle::PM_IndicatorHeight));
this->verticalHeader()->setDefaultSectionSize(h + 4);
this->horizontalHeader()->setStretchLastSection(true);
this->verticalHeader()->hide();
}
void QCMakeCacheView::showEvent(QShowEvent* e)
{
if(!this->Init)
{
// initialize the table view column size
int colWidth = this->columnWidth(0) + this->columnWidth(1);
this->setColumnWidth(0, colWidth/2);
this->setColumnWidth(1, colWidth/2);
this->Init = true;
}
return QTableView::showEvent(e);
}
QCMakeCacheModel* QCMakeCacheView::cacheModel() const
{
return this->CacheModel;
}
QModelIndex QCMakeCacheView::moveCursor(CursorAction act,
Qt::KeyboardModifiers mod)
{
// tab through values only (not names)
QModelIndex current = this->currentIndex();
if(act == MoveNext)
{
if(!current.isValid())
{
return this->model()->index(0, 1);
}
else if(current.column() == 0)
{
return this->model()->index(current.row(), 1);
}
else
{
return this->model()->index(current.row()+1, 1);
}
}
else if(act == MovePrevious)
{
if(!current.isValid())
{
return this->model()->index(0, 1);
}
else
{
return this->model()->index(current.row()-1, 1);
}
}
return QTableView::moveCursor(act, mod);
}
void QCMakeCacheView::setShowAdvanced(bool s)
{
this->AdvancedFilter->setFilterRegExp(
s ? AdvancedRegExp[1] : AdvancedRegExp[0]);
}
bool QCMakeCacheView::showAdvanced() const
{
return this->AdvancedFilter->filterRegExp() == AdvancedRegExp[1];
}
void QCMakeCacheView::setSearchFilter(const QString& s)
{
this->SearchFilter->setFilterRegExp(s);
}
QCMakeCacheModel::QCMakeCacheModel(QObject* p)
: QAbstractTableModel(p), NewCount(0), ModifiedValues(false)
{
}
QCMakeCacheModel::~QCMakeCacheModel()
{
}
bool QCMakeCacheModel::modifiedValues() const
{
return this->ModifiedValues;
}
static uint qHash(const QCMakeCacheProperty& p)
{
return qHash(p.Key);
}
void QCMakeCacheModel::clear()
{
this->setProperties(QCMakeCachePropertyList());
}
void QCMakeCacheModel::setProperties(const QCMakeCachePropertyList& props)
{
QSet<QCMakeCacheProperty> newProps = props.toSet();
QSet<QCMakeCacheProperty> oldProps = this->Properties.toSet();
oldProps.intersect(newProps);
newProps.subtract(oldProps);
this->NewCount = newProps.count();
this->Properties.clear();
this->Properties = newProps.toList();
qSort(this->Properties);
QCMakeCachePropertyList tmp = oldProps.toList();
qSort(tmp);
this->Properties += tmp;
this->ModifiedValues = NewCount != 0;
this->reset();
}
QCMakeCachePropertyList QCMakeCacheModel::properties() const
{
return this->Properties;
}
int QCMakeCacheModel::columnCount (const QModelIndex& /*p*/ ) const
{
return 2;
}
QVariant QCMakeCacheModel::data (const QModelIndex& idx, int role) const
{
if(idx.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
{
return this->Properties[idx.row()].Key;
}
else if(idx.column() == 0 && role == Qt::ToolTipRole)
{
return this->data(idx, Qt::DisplayRole).toString() + "\n" +
this->data(idx, QCMakeCacheModel::HelpRole).toString();
}
else if(idx.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
{
if(this->Properties[idx.row()].Type != QCMakeCacheProperty::BOOL)
{
return this->Properties[idx.row()].Value;
}
}
else if(idx.column() == 1 && role == Qt::CheckStateRole)
{
if(this->Properties[idx.row()].Type == QCMakeCacheProperty::BOOL)
{
return this->Properties[idx.row()].Value.toBool() ? Qt::Checked : Qt::Unchecked;
}
}
else if(role == QCMakeCacheModel::HelpRole)
{
return this->Properties[idx.row()].Help;
}
else if(role == QCMakeCacheModel::TypeRole)
{
return this->Properties[idx.row()].Type;
}
else if(role == QCMakeCacheModel::AdvancedRole)
{
return this->Properties[idx.row()].Advanced;
}
else if(role == Qt::BackgroundRole && idx.row()+1 <= this->NewCount)
{
return QBrush(QColor(255,100,100));
}
return QVariant();
}
QModelIndex QCMakeCacheModel::parent (const QModelIndex& /*idx*/) const
{
return QModelIndex();
}
int QCMakeCacheModel::rowCount (const QModelIndex& p) const
{
if(p.isValid())
{
return 0;
}
return this->Properties.count();
}
QVariant QCMakeCacheModel::headerData (int section, Qt::Orientation orient, int role) const
{
// return header labels
if(role == Qt::DisplayRole && orient == Qt::Horizontal)
{
return section == 0 ? "Name" : "Value";
}
return QVariant();
}
Qt::ItemFlags QCMakeCacheModel::flags (const QModelIndex& idx) const
{
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
// all column 1's are editable
if(idx.column() == 1)
{
f |= Qt::ItemIsEditable;
// booleans are editable in place
if(this->Properties[idx.row()].Type == QCMakeCacheProperty::BOOL)
{
f |= Qt::ItemIsUserCheckable;
}
}
return f;
}
bool QCMakeCacheModel::setData (const QModelIndex& idx, const QVariant& value, int role)
{
if(idx.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole))
{
this->Properties[idx.row()].Key = value.toString();
this->ModifiedValues = true;
emit this->dataChanged(idx, idx);
}
else if(idx.column() == 1 && (role == Qt::DisplayRole || role == Qt::EditRole))
{
this->Properties[idx.row()].Value = value.toString();
this->ModifiedValues = true;
emit this->dataChanged(idx, idx);
}
else if(idx.column() == 1 && (role == Qt::CheckStateRole))
{
this->Properties[idx.row()].Value = value.toInt() == Qt::Checked;
this->ModifiedValues = true;
emit this->dataChanged(idx, idx);
}
return false;
}
QCMakeCacheModelDelegate::QCMakeCacheModelDelegate(QObject* p)
: QItemDelegate(p)
{
}
QWidget* QCMakeCacheModelDelegate::createEditor(QWidget* p,
const QStyleOptionViewItem&, const QModelIndex& idx) const
{
QVariant type = idx.data(QCMakeCacheModel::TypeRole);
if(type == QCMakeCacheProperty::BOOL)
{
return NULL;
}
else if(type == QCMakeCacheProperty::PATH)
{
return new QCMakeCachePathEditor(idx.data().toString(), false, p);
}
else if(type == QCMakeCacheProperty::FILEPATH)
{
return new QCMakeCachePathEditor(idx.data().toString(), true, p);
}
return new QLineEdit(p);
}
QCMakeCachePathEditor::QCMakeCachePathEditor(const QString& file, bool fp,
QWidget* p)
: QWidget(p), LineEdit(this), IsFilePath(fp)
{
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);
this->LineEdit.selectAll();
tb->setFocusProxy(&this->LineEdit);
this->setFocusProxy(&this->LineEdit);
}
void QCMakeCachePathEditor::chooseFile()
{
QString path;
if(this->IsFilePath)
{
QFileInfo info(this->value());
path = QFileDialog::getOpenFileName(this, tr("Select File"),
info.absolutePath());
}
else
{
path = QFileDialog::getExistingDirectory(this, tr("Select Path"),
this->value());
}
if(!path.isEmpty())
{
this->LineEdit.setText(path);
}
}