August 11, 2012

oggie oggie
Lab Rat
5 posts

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

  1. ButtonColumnDelegate::ButtonColumnDelegate(QObject *parent) :
  2.     QStyledItemDelegate(parent)
  3. {
  4.     if(QTableView *tableView = qobject_cast<QTableView *>(parent))
  5.     {
  6.         myWidget = tableView;
  7.         btn = new QPushButton("...", myWidget);
  8.         btn->show();
  9.         myWidget->setMouseTracking(true);
  10.         connect(myWidget, SIGNAL(entered(QModelIndex)),
  11.                               this, SLOT(cellEntered(QModelIndex)));
  12.         isOneCellInEditMode = false;
  13.     }
  14. }
  15.  
  16. ButtonColumnDelegate::~ButtonColumnDelegate()
  17. {
  18.  
  19. }
  20.  
  21. //createEditor
  22. QWidget * ButtonColumnDelegate::createEditor(QWidget *parent,
  23.         const QStyleOptionViewItem &option,
  24.         const QModelIndex &index) const
  25. {
  26.     QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
  27.     if ((header == "Update") || (header == "Insert"))
  28.     {
  29.         QPushButton * btn = new QPushButton(parent);
  30.         btn->setText(index.data().toString());
  31.         return btn;
  32.     } else {
  33.         return QStyledItemDelegate::createEditor(parent, option, index);
  34.     }
  35. }
  36.  
  37. //setEditorData
  38. void ButtonColumnDelegate::setEditorData(QWidget *editor,
  39.                                  const QModelIndex &index) const
  40. {
  41.     QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
  42.     if ((header == "Update") || (header == "Insert"))
  43.     {
  44.         QPushButton * btn = qobject_cast<QPushButton *>(editor);
  45.         btn->setProperty("data_value", index.data());
  46.     } else {
  47.         QStyledItemDelegate::setEditorData(editor, index);
  48.     }
  49. }
  50.  
  51. //setModelData
  52. void ButtonColumnDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
  53.                                 const QModelIndex &index) const
  54. {
  55.     QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
  56.     if ((header == "Update") || (header == "Insert"))
  57.     {
  58.         QPushButton *btn = qobject_cast<QPushButton *>(editor);
  59.         model->setData(index, btn->property("data_value"));
  60.     } else {
  61.         QStyledItemDelegate::setModelData(editor, model, index);
  62.     }
  63. }
  64.  
  65. //paint
  66. void ButtonColumnDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
  67. {
  68.     QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
  69.     if((header == "Update") || (header == "Insert"))
  70.     {
  71.         btn->setGeometry(option.rect);
  72.         btn->setText(index.data().toString());
  73.         if (option.state == QStyle::State_Selected)
  74.                      painter->fillRect(option.rect, option.palette.highlight());
  75.         QPixmap map = QPixmap::grabWidget(btn);
  76.         painter->drawPixmap(option.rect.x(),option.rect.y(),map);
  77.     } else {
  78.         QStyledItemDelegate::paint(painter, option, index);
  79.     }
  80. }
  81.  
  82. //updateGeometry
  83. void ButtonColumnDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
  84. {
  85.     editor->setGeometry(option.rect);
  86. }
  87.  
  88. //cellEntered
  89. void ButtonColumnDelegate::cellEntered(const QModelIndex &index)
  90. {
  91.     QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
  92.     if((header == "Update") || (header == "Insert"))
  93.     {
  94.         if(isOneCellInEditMode)
  95.         {
  96.             myWidget->closePersistentEditor(currentEditedCellIndex);
  97.         }
  98.         myWidget->openPersistentEditor(index);
  99.         isOneCellInEditMode = true;
  100.         currentEditedCellIndex = index;
  101.     } else {
  102.         if(isOneCellInEditMode)
  103.         {
  104.             isOneCellInEditMode = false;
  105.             myWidget->closePersistentEditor(currentEditedCellIndex);
  106.         }
  107.     }
  108. }

Está tomado de internet adding-button-to-qviewtable [qtadventures.wordpress.com].

2.- clase Browser (la ventana de la aplicación)

  1. void Browser::exec()
  2. {
  3.     QSqlQueryModel *myModel = new QSqlQueryModel(table);
  4.     myModel->setQuery(QSqlQuery(sqlEdit->toPlainText(), connectionWidget->currentDatabase()));
  5.  
  6.     if (myModel->query().isSelect()) {
  7.         // Create the data model
  8.         model = new QStandardItemModel();
  9.         table->setModel(model);
  10.         ButtonColumnDelegate *update = new ButtonColumnDelegate(table);
  11.         ButtonColumnDelegate *insert = new ButtonColumnDelegate(table);
  12.         table->setItemDelegateForColumn(2, update);
  13.         table->setItemDelegateForColumn(3, insert);
  14.  
  15.  
  16.         model->insertRows(0, myModel->query().size());
  17.         model->insertColumns(0, 4);
  18.  
  19.         // Set the localized header captions
  20.         model->setHeaderData(0, Qt::Horizontal, "Id", Qt::UserRole);
  21.         model->setHeaderData(1, Qt::Horizontal, "Word", Qt::UserRole);
  22.         model->setHeaderData(2, Qt::Horizontal, "Update", Qt::UserRole);
  23.         model->setHeaderData(3, Qt::Horizontal, "Insert", Qt::UserRole);
  24.  
  25.         // ...
  26. }

Y duplica el botón de la ultima fila.

Gracias de antemano,
oggie

2 replies

August 13, 2012

oggie oggie
Lab Rat
5 posts

Creo que posiblemente la causa esté en la lógica de la función,

  1. //cellEntered
  2. void ButtonColumnDelegate::cellEntered(const QModelIndex &index)
  3. {
  4.     QString header = index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toString();
  5.     if((header == "Update") || (header == "Insert"))
  6.     {
  7.         if(isOneCellInEditMode)
  8.         {
  9.             myWidget->closePersistentEditor(currentEditedCellIndex);
  10.         }
  11.         myWidget->openPersistentEditor(index);
  12.         isOneCellInEditMode = true;
  13.         currentEditedCellIndex = index;
  14.     } else {
  15.         if(isOneCellInEditMode)
  16.         {
  17.             isOneCellInEditMode = false;
  18.             myWidget->closePersistentEditor(currentEditedCellIndex);
  19.         }
  20.     }
  21. }

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

August 18, 2012

oggie oggie
Lab Rat
5 posts

Al final preferí usar esta otra clase con las correciones que aparecen en el código y ya funciona.

customitemdelegate.h.-

  1. #ifndef CUSTOMITEMDELEGATE_H
  2. #define CUSTOMITEMDELEGATE_H
  3.  
  4. #include <QItemDelegate>
  5.  
  6. class CustomItemDelegate : public QItemDelegate
  7. {
  8.     Q_OBJECT
  9.  
  10. public:
  11.     explicit CustomItemDelegate(QObject *parent = 0);
  12.  
  13.     virtual void paint(QPainter *painter,
  14.                        const QStyleOptionViewItem &option,
  15.                        const QModelIndex &index) const ;
  16.  
  17.     virtual QSize sizeHint(const QStyleOptionViewItem &option,
  18.                            const QModelIndex &index) const ;
  19.  
  20.     bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
  21.  
  22. signals:
  23.     void updButtonClicked(const QModelIndex &index);
  24.     void delButtonClicked(const QModelIndex &index);
  25.  
  26. public slots:
  27.  
  28. private:
  29.     QStyle::State  _state;
  30.     QRect oldRect;
  31. };
  32.  
  33. #endif // CUSTOMITEMDELEGATE_H

customitemdelegate.cpp.-

  1. #include "customitemdelegate.h"
  2. #include <QModelIndex>
  3. #include <QStandardItemModel>
  4. #include <QStandardItem>
  5. #include <QPainter>
  6. #include <QStyleOptionButton>
  7. #include <QApplication>
  8. #include <QEvent>
  9. #include <QDebug>
  10. #include <QMouseEvent>
  11.  
  12. CustomItemDelegate::CustomItemDelegate(QObject *parent) :
  13.     QItemDelegate(parent)
  14. {
  15.     _state =  QStyle::State_Enabled;
  16. }
  17.  
  18. void CustomItemDelegate::paint(QPainter *painter,
  19.                    const QStyleOptionViewItem &option,
  20.                    const QModelIndex &index) const
  21. {
  22.    //const QStandardItemModel* model = static_cast<const QStandardItemModel*>(index.model());
  23.    //QStandardItem* item = model->item(index.row());
  24.    //QString text = item->text();
  25.  
  26.    QString text = index.data().toString();
  27.  
  28.    QRect rect = option.rect;
  29.  
  30.    //QRect textRect(rect);
  31.    //textRect.setHeight(30);
  32.    //painter->drawText(textRect,text);
  33.    painter->drawText(rect,text);
  34.  
  35.    QRect buttonRect(rect);
  36.    //buttonRect.setY(textRect.y() + 35);
  37.    //buttonRect.setY(rect.y() + 35);
  38.    buttonRect.setHeight(30);
  39.    QStyleOptionButton button;
  40.    button.rect = buttonRect;
  41.    button.text = text;
  42.    button.state = _state | QStyle::State_Enabled;
  43.  
  44.    QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
  45. }
  46.  
  47. QSize CustomItemDelegate::sizeHint(const QStyleOptionViewItem &/*option*/,
  48.                        const QModelIndex &/*index*/) const
  49. {
  50.     return QSize(800,70);
  51. }
  52.  
  53. bool CustomItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
  54. {
  55.     qDebug() << "editorEvent on row: " << index.row();
  56.     qDebug() << "editorEvent:: " << event->type();
  57.  
  58.     if( event->type() == QEvent::MouseButtonPress ||
  59.         event->type() == QEvent::MouseButtonRelease ) {
  60.     } else {
  61.          _state = QStyle::State_Raised;
  62.         return true;
  63.     }
  64.  
  65.     QRect buttonRect(option.rect);
  66.     //buttonRect.setY(option.rect.y() + 35);
  67.     buttonRect.setHeight(30);
  68.  
  69.     QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
  70.     if( !buttonRect.contains( mouseEvent->pos()) ) {
  71.         _state = QStyle::State_Raised;
  72.         return true;
  73.     }
  74.  
  75.     if( event->type() == QEvent::MouseButtonPress) {
  76.         _state = QStyle::State_Sunken;
  77.     } else if(event->type() == QEvent::MouseButtonRelease) {
  78.         _state = QStyle::State_Raised;
  79.         if(index.data().toString().contains("Update"))
  80.             emit updButtonClicked(index);
  81.         else if(index.data().toString().contains("Delete"))
  82.             emit delButtonClicked(index);
  83.         else
  84.             qDebug() << "¡¡¡ --ERROR-- !!!" << index.row();
  85.     }
  86.     return true;
  87. }

No duplicaba el ultimo botón sino que los había desplazado en la columna hacia abajo.

Gracias,
oggie

 
  ‹‹ Salida standard no hace nada      acceder antes de mostrar cn QSqlTableModel ››

You must log in to post a reply. Not a member yet? Register here!