QPushButton delegate en QTableView
-
Hola,
Tengo una aplicación de escritorio que simula un CRUD y uso un buttondelegate
para actualizar y borrar. La questión es que para cada delegate me despliega un
botón de más.1.- clase ButtonColumnDelegate
@
ButtonColumnDelegate::ButtonColumnDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{
if(QTableView *tableView = qobject_cast<QTableView *>(parent))
{
myWidget = tableView;
btn = new QPushButton("...", myWidget);
btn->show();
myWidget->setMouseTracking(true);
connect(myWidget, SIGNAL(entered(QModelIndex)),
this, SLOT(cellEntered(QModelIndex)));
isOneCellInEditMode = false;
}
}ButtonColumnDelegate::~ButtonColumnDelegate()
{}
//createEditor
QWidget * ButtonColumnDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
if ((header == "Update") || (header == "Insert"))
{
QPushButton * btn = new QPushButton(parent);
btn->setText(index.data().toString());
return btn;
} else {
return QStyledItemDelegate::createEditor(parent, option, index);
}
}//setEditorData
void ButtonColumnDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
if ((header == "Update") || (header == "Insert"))
{
QPushButton * btn = qobject_cast<QPushButton *>(editor);
btn->setProperty("data_value", index.data());
} else {
QStyledItemDelegate::setEditorData(editor, index);
}
}//setModelData
void ButtonColumnDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
if ((header == "Update") || (header == "Insert"))
{
QPushButton *btn = qobject_cast<QPushButton *>(editor);
model->setData(index, btn->property("data_value"));
} else {
QStyledItemDelegate::setModelData(editor, model, index);
}
}//paint
void ButtonColumnDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
if((header == "Update") || (header == "Insert"))
{
btn->setGeometry(option.rect);
btn->setText(index.data().toString());
if (option.state == QStyle::State_Selected)
painter->fillRect(option.rect, option.palette.highlight());
QPixmap map = QPixmap::grabWidget(btn);
painter->drawPixmap(option.rect.x(),option.rect.y(),map);
} else {
QStyledItemDelegate::paint(painter, option, index);
}
}//updateGeometry
void ButtonColumnDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}//cellEntered
void ButtonColumnDelegate::cellEntered(const QModelIndex &index)
{
QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
if((header == "Update") || (header == "Insert"))
{
if(isOneCellInEditMode)
{
myWidget->closePersistentEditor(currentEditedCellIndex);
}
myWidget->openPersistentEditor(index);
isOneCellInEditMode = true;
currentEditedCellIndex = index;
} else {
if(isOneCellInEditMode)
{
isOneCellInEditMode = false;
myWidget->closePersistentEditor(currentEditedCellIndex);
}
}
}
@Está tomado de internet "adding-button-to-qviewtable":http://qtadventures.wordpress.com/2012/02/04/adding-button-to-qviewtable/.
2.- clase Browser (la ventana de la aplicación)
@
void Browser::exec()
{
QSqlQueryModel *myModel = new QSqlQueryModel(table);
myModel->setQuery(QSqlQuery(sqlEdit->toPlainText(), connectionWidget->currentDatabase()));if (myModel->query().isSelect()) { // Create the data model model = new QStandardItemModel(); table->setModel(model); ButtonColumnDelegate *update = new ButtonColumnDelegate(table); ButtonColumnDelegate *insert = new ButtonColumnDelegate(table); table->setItemDelegateForColumn(2, update); table->setItemDelegateForColumn(3, insert); model->insertRows(0, myModel->query().size()); model->insertColumns(0, 4); // Set the localized header captions model->setHeaderData(0, Qt::Horizontal, "Id", Qt::UserRole); model->setHeaderData(1, Qt::Horizontal, "Word", Qt::UserRole); model->setHeaderData(2, Qt::Horizontal, "Update", Qt::UserRole); model->setHeaderData(3, Qt::Horizontal, "Insert", Qt::UserRole); // ...
}
@Y duplica el botón de la ultima fila.
Gracias de antemano,
oggie -
Creo que posiblemente la causa esté en la lógica de la función,
@
//cellEntered
void ButtonColumnDelegate::cellEntered(const QModelIndex &index)
{
QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
if((header == "Update") || (header == "Insert"))
{
if(isOneCellInEditMode)
{
myWidget->closePersistentEditor(currentEditedCellIndex);
}
myWidget->openPersistentEditor(index);
isOneCellInEditMode = true;
currentEditedCellIndex = index;
} else {
if(isOneCellInEditMode)
{
isOneCellInEditMode = false;
myWidget->closePersistentEditor(currentEditedCellIndex);
}
}
}
@No estoy seguro dado que soy nuevo en esto pero posiblemente la variable booleana isOneCellInEditMode no esté bien controlada y habilite la opción de editar un botón de más.
Cualquier sugerencia será gratamente apreciada.
oggie
-
Al final preferí usar esta otra clase con las correciones que aparecen en el código y ya funciona.
customitemdelegate.h.-
@
#ifndef CUSTOMITEMDELEGATE_H
#define CUSTOMITEMDELEGATE_H#include <QItemDelegate>
class CustomItemDelegate : public QItemDelegate
{
Q_OBJECTpublic:
explicit CustomItemDelegate(QObject *parent = 0);virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const ; virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const ; bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
signals:
void updButtonClicked(const QModelIndex &index);
void delButtonClicked(const QModelIndex &index);public slots:
private:
QStyle::State _state;
QRect oldRect;
};#endif // CUSTOMITEMDELEGATE_H
@customitemdelegate.cpp.-
@
#include "customitemdelegate.h"
#include <QModelIndex>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QPainter>
#include <QStyleOptionButton>
#include <QApplication>
#include <QEvent>
#include <QDebug>
#include <QMouseEvent>CustomItemDelegate::CustomItemDelegate(QObject *parent) :
QItemDelegate(parent)
{
_state = QStyle::State_Enabled;
}void CustomItemDelegate::paint(QPainter painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
//const QStandardItemModel model = static_cast<const QStandardItemModel*>(index.model());
//QStandardItem* item = model->item(index.row());
//QString text = item->text();QString text = index.data().toString();
QRect rect = option.rect;
//QRect textRect(rect);
//textRect.setHeight(30);
//painter->drawText(textRect,text);
painter->drawText(rect,text);QRect buttonRect(rect);
//buttonRect.setY(textRect.y() + 35);
//buttonRect.setY(rect.y() + 35);
buttonRect.setHeight(30);
QStyleOptionButton button;
button.rect = buttonRect;
button.text = text;
button.state = _state | QStyle::State_Enabled;QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
}QSize CustomItemDelegate::sizeHint(const QStyleOptionViewItem &/option/,
const QModelIndex &/index/) const
{
return QSize(800,70);
}bool CustomItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
qDebug() << "editorEvent on row: " << index.row();
qDebug() << "editorEvent:: " << event->type();if( event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease ) { } else { _state = QStyle::State_Raised; return true; } QRect buttonRect(option.rect); //buttonRect.setY(option.rect.y() + 35); buttonRect.setHeight(30); QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); if( !buttonRect.contains( mouseEvent->pos()) ) { _state = QStyle::State_Raised; return true; } if( event->type() == QEvent::MouseButtonPress) { _state = QStyle::State_Sunken; } else if(event->type() == QEvent::MouseButtonRelease) { _state = QStyle::State_Raised; if(index.data().toString().contains("Update")) emit updButtonClicked(index); else if(index.data().toString().contains("Delete")) emit delButtonClicked(index); else qDebug() << "¡¡¡ --ERROR-- !!!" << index.row(); } return true;
}
@No duplicaba el ultimo botón sino que los había desplazado en la columna hacia abajo.
Gracias,
oggie