Changed: #1306 added basic editing possibillities for normal and parent values (no default values and no saving of changed values yet); added possibillity to expand/collapse whole tree by header click
parent
0f8ce66f50
commit
16b3e28b7a
@ -0,0 +1,143 @@
|
||||
// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2011 Adrian Jaekel <aj at elane2k dot com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Project includes
|
||||
#include "expandable_headerview.h"
|
||||
|
||||
// Qt includes
|
||||
#include <QApplication>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
namespace Plugin
|
||||
{
|
||||
|
||||
ExpandableHeaderView::ExpandableHeaderView(Qt::Orientation orientation, QWidget * parent)
|
||||
: QHeaderView(orientation, parent),
|
||||
m_expanded(true),
|
||||
m_inDecoration(false)
|
||||
{
|
||||
}
|
||||
|
||||
void ExpandableHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
|
||||
{
|
||||
painter->save();
|
||||
QHeaderView::paintSection(painter, rect, logicalIndex);
|
||||
painter->restore();
|
||||
|
||||
if (logicalIndex == 0)
|
||||
{
|
||||
QRect sectionRect = this->orientation() == Qt::Horizontal ?
|
||||
QRect(this->sectionPosition(logicalIndex), 0,
|
||||
this->sectionSize(logicalIndex), this->height()):
|
||||
QRect(0, this->sectionPosition(logicalIndex),
|
||||
this->width(), this->sectionSize(logicalIndex));
|
||||
|
||||
QStyleOptionHeader opt;
|
||||
initStyleOption(&opt);
|
||||
opt.iconAlignment = Qt::AlignVCenter;
|
||||
|
||||
QVariant variant = this->model()->headerData(logicalIndex, this->orientation(),
|
||||
Qt::DecorationRole);
|
||||
opt.icon = qvariant_cast<QIcon>(variant);
|
||||
if (opt.icon.isNull())
|
||||
{
|
||||
opt.icon = qvariant_cast<QPixmap>(variant);
|
||||
}
|
||||
QRect headerLabelRect = this->style()->subElementRect(QStyle::SE_HeaderLabel, &opt, this);
|
||||
|
||||
QPixmap pixmap
|
||||
= opt.icon.pixmap(this->style()->pixelMetric(QStyle::PM_SmallIconSize),
|
||||
(opt.state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled);
|
||||
QRect aligned = this->style()->alignedRect(opt.direction, QFlag(opt.iconAlignment),
|
||||
pixmap.size(), headerLabelRect);
|
||||
QRect inter = aligned.intersected(headerLabelRect);
|
||||
|
||||
QStyleOption option;
|
||||
option.rect = QRect(inter.x()-2,inter.y(),inter.width(),inter.height());
|
||||
if (m_expanded)
|
||||
option.state = QStyle::State_Children | QStyle::State_Open;
|
||||
else
|
||||
option.state = QStyle::State_Children;
|
||||
if (m_inDecoration)
|
||||
option.state |= QStyle::State_MouseOver;
|
||||
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorBranch, &option, painter);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpandableHeaderView::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
int section = logicalIndexAt(e->x());
|
||||
|
||||
if (section == 0 && m_inDecoration) {
|
||||
if (m_expanded)
|
||||
m_expanded = false;
|
||||
else
|
||||
m_expanded = true;
|
||||
this->QHeaderView::mousePressEvent(e);
|
||||
Q_EMIT headerClicked(section);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpandableHeaderView::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
int section = this->logicalIndexAt(e->x());
|
||||
|
||||
if (section != 0)
|
||||
return;
|
||||
|
||||
bool tmp = m_inDecoration;
|
||||
if (isPointInDecoration(section, e->pos()))
|
||||
m_inDecoration = true;
|
||||
else
|
||||
m_inDecoration = false;
|
||||
|
||||
if (m_inDecoration != tmp)
|
||||
updateSection(0);
|
||||
}
|
||||
|
||||
bool ExpandableHeaderView::isPointInDecoration(int section, QPoint pos)const
|
||||
{
|
||||
QRect sectionRect = this->orientation() == Qt::Horizontal ?
|
||||
QRect(this->sectionPosition(section), 0,
|
||||
this->sectionSize(section), this->height()):
|
||||
QRect(0, this->sectionPosition(section),
|
||||
this->width(), this->sectionSize(section));
|
||||
QStyleOptionHeader opt;
|
||||
this->initStyleOption(&opt);
|
||||
opt.iconAlignment = Qt::AlignVCenter;
|
||||
QVariant variant = this->model()->headerData(section, this->orientation(),
|
||||
Qt::DecorationRole);
|
||||
opt.icon = qvariant_cast<QIcon>(variant);
|
||||
if (opt.icon.isNull())
|
||||
{
|
||||
opt.icon = qvariant_cast<QPixmap>(variant);
|
||||
}
|
||||
QRect headerLabelRect = this->style()->subElementRect(QStyle::SE_HeaderLabel, &opt, this);
|
||||
// from qcommonstyle.cpp
|
||||
if (opt.icon.isNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QPixmap pixmap
|
||||
= opt.icon.pixmap(this->style()->pixelMetric(QStyle::PM_SmallIconSize),
|
||||
(opt.state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled);
|
||||
QRect aligned = this->style()->alignedRect(opt.direction, QFlag(opt.iconAlignment),
|
||||
pixmap.size(), headerLabelRect);
|
||||
QRect inter = aligned.intersected(headerLabelRect);
|
||||
return inter.contains(pos);
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2011 Adrian Jaekel <aj at elane2k dot com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EXPANDABLE_HEADERVIEW_H
|
||||
#define EXPANDABLE_HEADERVIEW_H
|
||||
|
||||
// Qt includes
|
||||
#include <QHeaderView>
|
||||
|
||||
namespace Plugin
|
||||
{
|
||||
class ExpandableHeaderView : public QHeaderView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ExpandableHeaderView(Qt::Orientation orientation, QWidget * parent = 0);
|
||||
|
||||
bool* expanded() { return &m_expanded; }
|
||||
|
||||
protected:
|
||||
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
|
||||
bool isPointInDecoration(int section, QPoint pos)const;
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
private:
|
||||
bool m_expanded;
|
||||
bool m_inDecoration;
|
||||
|
||||
Q_SIGNALS:
|
||||
void headerClicked(int);
|
||||
};
|
||||
|
||||
} /* namespace NLQT */
|
||||
|
||||
#endif // EXPANDABLE_HEADERVIEW_H
|
@ -0,0 +1,278 @@
|
||||
// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2011 Adrian Jaekel <aj at elane2k dot com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "formdelegate.h"
|
||||
|
||||
// NeL includes
|
||||
#include <nel/misc/debug.h>
|
||||
#include <nel/georges/u_type.h>
|
||||
#include <nel/georges/u_form_elm.h>
|
||||
|
||||
// Qt includes
|
||||
#include <QSpinBox>
|
||||
#include <QLineEdit>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QColorDialog>
|
||||
#include <QComboBox>
|
||||
#include <QApplication>
|
||||
#include <QTextDocument>
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QPainter>
|
||||
|
||||
// Project includes
|
||||
#include "georgesform_model.h"
|
||||
#include "georgesform_proxy_model.h"
|
||||
#include "formitem.h"
|
||||
|
||||
namespace Plugin
|
||||
{
|
||||
|
||||
FormDelegate::FormDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QWidget *FormDelegate::createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem & option ,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
const CGeorgesFormProxyModel * mp = dynamic_cast<const CGeorgesFormProxyModel *>(index.model());
|
||||
const CGeorgesFormModel * m = dynamic_cast<const CGeorgesFormModel *>(mp->sourceModel());
|
||||
CFormItem *item = static_cast<CFormItem*>(mp->mapToSource(index).internalPointer());
|
||||
QString value = item->data(1).toString();
|
||||
|
||||
if (value.isEmpty() || !mp || !m)
|
||||
return 0;
|
||||
|
||||
CFormItem* curItem = m->getItem(mp->mapToSource(index));
|
||||
NLGEORGES::UFormElm *curElm = curItem->getFormElm();
|
||||
if (!curElm) {
|
||||
// TODO: create new Element
|
||||
return 0;
|
||||
}
|
||||
const NLGEORGES::UType *type = curElm->getType();
|
||||
if(type)
|
||||
{
|
||||
int numDefinitions = type->getNumDefinition();
|
||||
|
||||
if (numDefinitions)
|
||||
{
|
||||
std::string l, v;
|
||||
QString label,value;
|
||||
|
||||
QComboBox *editor = new QComboBox(parent);
|
||||
for (int i = 0; i < numDefinitions; i++)
|
||||
{
|
||||
type->getDefinition(i,l,v);
|
||||
label = l.c_str();
|
||||
value = v.c_str();
|
||||
editor->addItem(label);
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type->getType())
|
||||
{
|
||||
case NLGEORGES::UType::UnsignedInt:
|
||||
case NLGEORGES::UType::SignedInt:
|
||||
{
|
||||
QSpinBox *editor = new QSpinBox(parent);
|
||||
|
||||
//QString min = QString(type->getMin().c_str());
|
||||
//QString max = QString(type->getMax().c_str());
|
||||
//QString inc = QString(type->getIncrement().c_str());
|
||||
//nldebug(QString("min %1 max %2 inc %3").arg(min).arg(max).arg(inc).toStdString().c_str());
|
||||
|
||||
// TODO: use saved min/max values
|
||||
editor->setMinimum(-99999);
|
||||
editor->setMaximum(99999);
|
||||
editor->setSingleStep(1);
|
||||
return editor;
|
||||
}
|
||||
case NLGEORGES::UType::Double:
|
||||
{
|
||||
QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
|
||||
|
||||
//QString min = QString(type->getMin().c_str());
|
||||
//QString max = QString(type->getMax().c_str());
|
||||
//QString inc = QString(type->getIncrement().c_str());
|
||||
//nldebug(QString("min %1 max %2 inc %3").arg(min).arg(max).arg(inc).toStdString().c_str());
|
||||
|
||||
// TODO: use saved min/max values
|
||||
editor->setMinimum(-99999);
|
||||
editor->setMaximum(99999);
|
||||
editor->setSingleStep(0.1);
|
||||
editor->setDecimals(1);
|
||||
return editor;
|
||||
}
|
||||
case NLGEORGES::UType::Color:
|
||||
{
|
||||
return new QColorDialog();
|
||||
}
|
||||
default: // UType::String
|
||||
{
|
||||
QLineEdit *editor = new QLineEdit(parent);
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FormDelegate::setEditorData(QWidget *editor,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
const CGeorgesFormProxyModel * mp = dynamic_cast<const CGeorgesFormProxyModel *>(index.model());
|
||||
const CGeorgesFormModel * m = dynamic_cast<const CGeorgesFormModel *>(mp->sourceModel());
|
||||
|
||||
const NLGEORGES::UType *type = m->getItem(mp->mapToSource(index))->getFormElm()->getType();
|
||||
int numDefinitions = type->getNumDefinition();
|
||||
QString value = index.model()->data(index, Qt::DisplayRole).toString();
|
||||
|
||||
if (numDefinitions)
|
||||
{
|
||||
QComboBox *cb = static_cast<QComboBox*>(editor);
|
||||
cb->setCurrentIndex(cb->findText(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type->getType())
|
||||
{
|
||||
case NLGEORGES::UType::UnsignedInt:
|
||||
case NLGEORGES::UType::SignedInt:
|
||||
{
|
||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
||||
spinBox->setValue((int)value.toDouble());
|
||||
break;
|
||||
}
|
||||
case NLGEORGES::UType::Double:
|
||||
{
|
||||
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
|
||||
spinBox->setValue(value.toDouble());
|
||||
break;
|
||||
}
|
||||
case NLGEORGES::UType::Color:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
QLineEdit *textEdit = static_cast<QLineEdit*>(editor);
|
||||
textEdit->setText(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FormDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
const CGeorgesFormProxyModel * mp = dynamic_cast<const CGeorgesFormProxyModel *>(index.model());
|
||||
const CGeorgesFormModel * m = dynamic_cast<const CGeorgesFormModel *>(mp->sourceModel());
|
||||
|
||||
const NLGEORGES::UType *type = m->getItem(mp->mapToSource(index))->getFormElm()->getType();
|
||||
int numDefinitions = type->getNumDefinition();
|
||||
|
||||
if (numDefinitions)
|
||||
{
|
||||
QComboBox *comboBox = static_cast<QComboBox*>(editor);
|
||||
QString value = comboBox->currentText();
|
||||
QString oldValue = index.model()->data(index, Qt::DisplayRole).toString();
|
||||
if (value == oldValue)
|
||||
{
|
||||
// nothing's changed
|
||||
}
|
||||
else
|
||||
{
|
||||
nldebug(QString("setModelData from %1 to %2")
|
||||
.arg(oldValue).arg(value).toStdString().c_str());
|
||||
model->setData(index, value, Qt::EditRole);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type->getType())
|
||||
{
|
||||
case NLGEORGES::UType::UnsignedInt:
|
||||
case NLGEORGES::UType::SignedInt:
|
||||
{
|
||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
||||
int value = spinBox->value();
|
||||
QString oldValue = index.model()->data(index, Qt::DisplayRole).toString();
|
||||
if (QString("%1").arg(value) == oldValue)
|
||||
{
|
||||
// nothing's changed
|
||||
}
|
||||
else
|
||||
{
|
||||
nldebug(QString("setModelData from %1 to %2")
|
||||
.arg(oldValue).arg(value).toStdString().c_str());
|
||||
model->setData(index, value, Qt::EditRole);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NLGEORGES::UType::Double:
|
||||
{
|
||||
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
|
||||
double value = spinBox->value();
|
||||
QString oldValue = index.model()->data(index, Qt::DisplayRole).toString();
|
||||
if (QString("%1").arg(value) == oldValue)
|
||||
{
|
||||
// nothing's changed
|
||||
}
|
||||
else
|
||||
{
|
||||
nldebug(QString("setModelData from %1 to %2")
|
||||
.arg(oldValue).arg(value).toStdString().c_str());
|
||||
model->setData(index, value, Qt::EditRole);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NLGEORGES::UType::Color:
|
||||
{
|
||||
break; // TODO
|
||||
}
|
||||
default: // UType::String
|
||||
{
|
||||
QLineEdit *textEdit = static_cast<QLineEdit*>(editor);
|
||||
QString value = textEdit->text();
|
||||
QString oldValue = index.model()->data(index, Qt::DisplayRole).toString();
|
||||
if (value == oldValue)
|
||||
{
|
||||
// nothing's changed
|
||||
}
|
||||
else
|
||||
{
|
||||
nldebug(QString("setModelData from %1 to %2")
|
||||
.arg(oldValue).arg(value).toStdString().c_str());
|
||||
model->setData(index, value, Qt::EditRole);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FormDelegate::updateEditorGeometry(QWidget *editor,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QRect r = option.rect;
|
||||
editor->setGeometry(r);
|
||||
}
|
||||
} /* namespace Plugin */
|
@ -0,0 +1,41 @@
|
||||
// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2011 Adrian Jaekel <aj at elane2k dot com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef FORMDELEGATE_H
|
||||
#define FORMDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
namespace Plugin
|
||||
{
|
||||
|
||||
class FormDelegate : public QStyledItemDelegate
|
||||
{
|
||||
|
||||
public:
|
||||
FormDelegate(QObject *parent = 0);
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const;
|
||||
void updateEditorGeometry(QWidget *editor,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // FORMDELEGATE_H
|
Loading…
Reference in New Issue