Files
qt-creator/shared/proparser/valueeditor.cpp
2008-12-09 11:07:24 +01:00

501 lines
15 KiB
C++

/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "valueeditor.h"
#include "proitems.h"
#include "proeditormodel.h"
#include "proiteminfo.h"
#include <QtGui/QMenu>
#include <QtGui/QKeyEvent>
using namespace Qt4ProjectManager::Internal;
ValueEditor::ValueEditor(QWidget *parent)
: QWidget(parent),
m_model(0),
m_handleModelChanges(true),
m_infomanager(0)
{
setupUi(this);
}
ValueEditor::~ValueEditor()
{
}
void ValueEditor::initialize(ProEditorModel *model, ProItemInfoManager *infomanager)
{
m_model = model;
m_infomanager = infomanager;
initialize();
}
void ValueEditor::hideVariable()
{
m_varGroupBox->setVisible(false);
}
void ValueEditor::showVariable(bool advanced)
{
m_varComboBoxLabel->setVisible(!advanced);
m_varComboBox->setVisible(!advanced);
m_varLineEditLabel->setVisible(advanced);
m_varLineEdit->setVisible(advanced);
m_assignComboBoxLabel->setVisible(advanced);
m_assignComboBox->setVisible(advanced);
m_varGroupBox->setVisible(true);
}
void ValueEditor::setItemEditType(ItemEditType type)
{
m_editStackWidget->setCurrentIndex(type);
}
void ValueEditor::setDescription(ItemEditType type, const QString &header, const QString &description)
{
switch (type) {
case MultiUndefined:
m_multiUndefinedGroupBox->setTitle(header);
m_multiUndefinedDescriptionLabel->setVisible(!description.isEmpty());
m_multiUndefinedDescriptionLabel->setText(description);
break;
case MultiDefined:
m_multiDefinedGroupBox->setTitle(header);
m_multiDefinedDescriptionLabel->setVisible(!description.isEmpty());
m_multiDefinedDescriptionLabel->setText(description);
break;
case SingleUndefined:
m_singleUndefinedGroupBox->setTitle(header);
m_singleUndefinedDescriptionLabel->setVisible(!description.isEmpty());
m_singleUndefinedDescriptionLabel->setText(description);
break;
default:
m_singleDefinedGroupBox->setTitle(header);
m_singleDefinedDescriptionLabel->setVisible(!description.isEmpty());
m_singleDefinedDescriptionLabel->setText(description);
break;
}
}
void ValueEditor::initialize()
{
hideVariable();
setItemEditType(MultiUndefined);
m_itemListView->setModel(m_model);
m_itemListView->setRootIndex(QModelIndex());
connect(m_itemAddButton, SIGNAL(clicked()),
this, SLOT(addItem()));
connect(m_itemRemoveButton, SIGNAL(clicked()),
this, SLOT(removeItem()));
connect(m_itemListView->selectionModel(),
SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(updateItemList(const QModelIndex &)));
connect(m_itemListWidget, SIGNAL(itemChanged(QListWidgetItem *)),
this, SLOT(updateItemChanges(QListWidgetItem *)));
foreach (ProVariableInfo *varinfo, m_infomanager->variables()) {
m_varComboBox->addItem(varinfo->name(), varinfo->id());
}
connect(m_varLineEdit, SIGNAL(editingFinished()), this, SLOT(updateVariableId()));
connect(m_varComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateVariableId(int)));
connect(m_assignComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateVariableOp(int)));
connect(m_itemLineEdit, SIGNAL(editingFinished()), this, SLOT(updateItemId()));
connect(m_itemComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateItemId(int)));
connect(m_model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
this, SLOT(modelChanged(const QModelIndex &)));
connect(m_model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
this, SLOT(modelChanged(const QModelIndex &)));
connect(m_model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(modelChanged(const QModelIndex &)));
updateItemList(QModelIndex());
}
void ValueEditor::modelChanged(const QModelIndex &index)
{
if (m_handleModelChanges) {
if (m_currentIndex == index || m_currentIndex == index.parent())
editIndex(m_currentIndex);
}
}
void ValueEditor::editIndex(const QModelIndex &index)
{
if (!m_model)
return;
m_currentIndex = index;
ProBlock *block = m_model->proBlock(index);
m_varGroupBox->setEnabled(block != 0);
m_editStackWidget->setEnabled(block != 0);
if (!block)
return;
if (block->blockKind() & ProBlock::ScopeContentsKind) {
showScope(block);
} else if (block->blockKind() & ProBlock::VariableKind) {
showVariable(static_cast<ProVariable*>(block));
} else {
showOther(block);
}
}
ValueEditor::ItemEditType ValueEditor::itemType(bool defined, bool multiple) const
{
if (defined) {
if (multiple)
return MultiDefined;
else
return SingleDefined;
} else {
if (multiple)
return MultiUndefined;
else
return SingleUndefined;
}
}
void ValueEditor::showVariable(ProVariable *variable)
{
if (!m_model)
return;
ProVariableInfo *info = m_infomanager->variable(variable->variable());
const bool advanced = (!m_model->infoManager() || (info == 0));
bool defined = false;
bool multiple = true;
QSet<QString> values;
foreach(ProItem *proitem, variable->items()) {
if (proitem->kind() == ProItem::ValueKind) {
ProValue *val = static_cast<ProValue *>(proitem);
values.insert(val->value());
}
}
if (!advanced && info) {
defined = !info->values().isEmpty();
// check if all values are known
foreach(QString val, values) {
if (!info->value(val)) {
defined = false;
break;
}
}
multiple = info->multiple();
}
if (values.count() > 1)
multiple = true;
bool wasblocked;
if (!advanced) {
const int index = m_varComboBox->findData(variable->variable(), Qt::UserRole, Qt::MatchExactly);
wasblocked = m_varComboBox->blockSignals(true);
m_varComboBox->setCurrentIndex(index);
m_varComboBox->blockSignals(wasblocked);
} else {
wasblocked = m_varLineEdit->blockSignals(true);
m_varLineEdit->setText(variable->variable());
m_varLineEdit->blockSignals(wasblocked);
}
ItemEditType type = itemType(defined, multiple);
wasblocked = m_assignComboBox->blockSignals(true);
m_assignComboBox->setCurrentIndex(variable->variableOperator());
m_assignComboBox->blockSignals(wasblocked);
QString header = tr("Edit Values");
QString desc;
if (info) {
header = tr("Edit %1").arg(info->name());
desc = info->description();
}
setDescription(type, header, desc);
m_itemListWidget->clear();
switch (type) {
case MultiUndefined: {
const QModelIndex parent = m_currentIndex;
m_itemListView->setRootIndex(parent);
m_itemListView->setCurrentIndex(m_model->index(0,0,parent));
}
break;
case MultiDefined:
wasblocked = m_itemListWidget->blockSignals(true);
foreach(ProValueInfo *valinfo, info->values()) {
QListWidgetItem *item = new QListWidgetItem(m_itemListWidget);
item->setText(valinfo->name());
item->setData(Qt::UserRole, valinfo->id());
if (values.contains(valinfo->id()))
item->setCheckState(Qt::Checked);
else
item->setCheckState(Qt::Unchecked);
}
m_itemListWidget->blockSignals(wasblocked);
break;
case SingleUndefined:
wasblocked = m_itemLineEdit->blockSignals(true);
if (values.isEmpty())
m_itemLineEdit->setText(QString());
else
m_itemLineEdit->setText(values.toList().first());
m_itemLineEdit->blockSignals(wasblocked);
break;
case SingleDefined:
wasblocked = m_itemComboBox->blockSignals(true);
m_itemComboBox->clear();
foreach(ProValueInfo *valinfo, info->values()) {
m_itemComboBox->addItem(valinfo->name(), valinfo->id());
}
int index = -1;
if (!values.isEmpty()) {
const QString id = values.toList().first();
index = m_itemComboBox->findData(id, Qt::UserRole, Qt::MatchExactly);
}
m_itemComboBox->setCurrentIndex(index);
m_itemComboBox->blockSignals(wasblocked);
break;
}
showVariable(advanced);
setItemEditType(type);
}
void ValueEditor::showScope(ProBlock *)
{
if (!m_model)
return;
const bool wasblocked = m_itemLineEdit->blockSignals(true);
m_itemLineEdit->setText(m_model->data(m_currentIndex, Qt::EditRole).toString());
m_itemLineEdit->blockSignals(wasblocked);
setDescription(SingleUndefined, tr("Edit Scope"));
hideVariable();
setItemEditType(SingleUndefined);
}
void ValueEditor::showOther(ProBlock *)
{
if (!m_model)
return;
const bool wasblocked = m_itemLineEdit->blockSignals(true);
m_itemLineEdit->setText(m_model->data(m_currentIndex, Qt::EditRole).toString());
m_itemLineEdit->blockSignals(wasblocked);
setDescription(SingleUndefined, tr("Edit Advanced Expression"));
hideVariable();
setItemEditType(SingleUndefined);
}
void ValueEditor::addItem(QString value)
{
if (!m_model)
return;
QModelIndex parent = m_currentIndex;
ProVariable *var = static_cast<ProVariable *>(m_model->proBlock(parent));
if (value.isEmpty()) {
value = QLatin1String("...");
if (ProVariableInfo *varinfo = m_infomanager->variable(var->variable())) {
const QList<ProValueInfo *> vals = varinfo->values();
if (!vals.isEmpty())
value = vals.first()->id();
}
}
m_handleModelChanges = false;
m_model->insertItem(new ProValue(value, var),
m_model->rowCount(parent), parent);
const QModelIndex idx = m_model->index(m_model->rowCount(parent)-1, 0, parent);
m_itemListView->setCurrentIndex(idx);
m_itemListView->edit(idx);
m_itemListView->scrollToBottom();
m_handleModelChanges = true;
}
void ValueEditor::removeItem()
{
if (!m_model)
return;
m_handleModelChanges = false;
const QModelIndex idx = m_itemListView->currentIndex();
m_itemListView->closePersistentEditor(idx);
m_model->removeItem(idx);
m_handleModelChanges = true;
}
void ValueEditor::updateItemList(const QModelIndex &)
{
if (!m_model)
return;
m_itemRemoveButton->setEnabled(m_model->rowCount(m_currentIndex));
}
QModelIndex ValueEditor::findValueIndex(const QString &id) const
{
if (!m_model)
return QModelIndex();
const QModelIndex parent = m_currentIndex;
const int rows = m_model->rowCount(parent);
for (int row=0; row<rows; ++row) {
const QModelIndex index = m_model->index(row, 0, parent);
ProItem *item = m_model->proItem(index);
if (!item || item->kind() != ProItem::ValueKind)
continue;
if (static_cast<ProValue*>(item)->value() == id)
return index;
}
return QModelIndex();
}
void ValueEditor::updateItemChanges(QListWidgetItem *item)
{
if (!m_model)
return;
const QModelIndex parent = m_currentIndex;
ProBlock *block = m_model->proBlock(parent);
if (!block || !(block->blockKind() & ProBlock::VariableKind))
return;
ProVariable *var = static_cast<ProVariable *>(block);
const QString id = item->data(Qt::UserRole).toString();
m_handleModelChanges = false;
const QModelIndex index = findValueIndex(id);
if (item->checkState() == Qt::Checked && !index.isValid()) {
m_model->insertItem(new ProValue(id, var),
m_model->rowCount(parent), m_currentIndex);
} else if (item->checkState() != Qt::Checked && index.isValid()) {
m_model->removeItem(index);
}
m_handleModelChanges = true;
}
void ValueEditor::updateVariableId()
{
if (!m_model)
return;
m_handleModelChanges = false;
m_model->setData(m_currentIndex, QVariant(m_varLineEdit->text()));
m_handleModelChanges = true;
}
void ValueEditor::updateVariableId(int index)
{
if (!m_model)
return;
ProVariableInfo *info = m_infomanager->variable(m_varComboBox->itemData(index).toString());
m_model->setData(m_currentIndex, info->id());
m_model->setData(m_currentIndex, info->defaultOperator());
}
void ValueEditor::updateVariableOp(int index)
{
if (!m_model)
return;
m_handleModelChanges = false;
m_model->setData(m_currentIndex, QVariant(index));
m_handleModelChanges = true;
}
void ValueEditor::updateItemId()
{
if (!m_model)
return;
QModelIndex index = m_currentIndex;
if (m_varGroupBox->isVisible()) {
index = m_model->index(0,0,index);
if (!index.isValid()) {
addItem(m_itemLineEdit->text());
return;
}
}
m_handleModelChanges = false;
m_model->setData(index, QVariant(m_itemLineEdit->text()));
m_handleModelChanges = true;
}
void ValueEditor::updateItemId(int index)
{
if (!m_model)
return;
QModelIndex idx = m_currentIndex;
if (m_varGroupBox->isVisible()) {
idx = m_model->index(0,0,idx);
if (!idx.isValid()) {
addItem(m_itemComboBox->itemData(index).toString());
return;
}
}
m_handleModelChanges = false;
m_model->setData(idx, m_itemComboBox->itemData(index));
m_handleModelChanges = true;
}