2010-08-06 13 views
8

¿Hay alguna forma de determinar si un QTableView tiene un editor abierto en la celda actual? Necesito para manejar la siguiente situación:Determinar si QTableView tiene un editor abierto

  • Un usuario hace doble clic en una celda y edita los datos, pero sale de la celda en el estado "editar".
  • En otra parte de la interfaz de usuario, se realiza una acción que cambia la fila seleccionada del modelo subyacente.
  • De nuevo en mi punto de vista, quiero determinar si la fila recién seleccionada es la misma que la abierta. Si no, necesito tomar una acción. (Preguntar al usuario? Commit automáticamente? Revert?)

que ver cómo conseguir el elemento actual, y puede conseguir el delegado sobre ese tema, pero yo no veo ninguna isEditMode() propiedad que esperaba encontrar.

¿Puede alguien señalarme en la dirección correcta?

Respuesta

2

Subclase su delegado para que incluya un descriptor de acceso que le indica cuando está editando:

void MyDelegate::setEditorData (QWidget * editor, const QModelIndex & index) const { 
    // _isEditing will have to be mutable because this method is const 
    _isEditing = true; 
    QStyledItemDelegate::setEditorData(editor, index); 
} 

void MyDelegate::setModelData (QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const { 
    QStyledItemDelegate::setModelData(editor, model, index); 
    _isEditing = false; 
} 

bool MyDelegate::isEditing() const { return _isEditing; } 

a continuación, puedes comprobar el delegado para ver lo que está pasando. Como alternativa y/o si no te gusta el mutable, puede emitir señales para que sepa en qué estado está en el delegado.

+0

Solo una nota, creo que se refería a * mutable *, not * volátil *. –

+0

@Caleb - Tienes razón. Cambiado, y gracias por señalarlo. –

+3

Como ya señaló Florian Kusche en su respuesta, esto no funciona porque setModelData() solo se invoca si la edición está confirmada, pero no si se cancela. – emkey08

3

Conectar a DataChanged modelo de señal subyacente

void QAbstractItemModel::dataChanged (const QModelIndex & topLeft, const QModelIndex & bottomRight) 

Puede comprobar si la célula donde los datos ha cambiado es el mismo que el currentIndex

QModelIndex QAbstractItemView::currentIndex() const 

no se puede saber si la celda actual tuvo un editor abierto recta, pero puede comprobar si la vista está en QAbstractItemView :: EditingState

State QAbstractItemView::state() const 

Debe ser suficiente para hacer lo que desee.

2

Puede subclase QTableView para poder acceder a la función state(), que desafortunadamente está protegida. Sin embargo, no intenté eso.

Si ya tiene una subclase QStyledItemDelegate, puede usarla para rastrear si un editor está actualmente abierto. Sin embargo, no puede usar setEditorData/setModelData, porque setModelData no se invocará cuando el usuario cancele la edición. En cambio, puede rastrear la creación y destrucción del editor en sí.

class MyItemDelegate : public QStyledItemDelegate 
{ 
    Q_OBJECT 

public: 
    MyItemDelegate(QObject* parent = nullptr); 
    ~MyItemDelegate(); 

    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; 

    bool isEditorOpen() const { return *m_editorCount > 0; } 

protected: 
    int* m_editorCount; 

protected slots: 
    void onEditorDestroyed(QObject* obj); 
}; 

Implementación:

MyItemDelegate::MyItemDelegate(QObject* parent) : 
    QStyledItemDelegate(parent) 
{ 
    m_editorCount = new int; 
    *m_editorCount = 0; 
} 

MyItemDelegate::~MyItemDelegate() 
{ 
    delete m_editorCount; 
} 

QWidget* MyItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const 
{ 
    // create an editor, can be changed as needed 
    QWidget* editor = QStyledItemDelegate::createEditor(parent, option, index); 

    connect(editor, SIGNAL(destroyed(QObject*)), SLOT(onEditorDestroyed(QObject*))); 
    printf("editor %p created\n", (void*) editor); 
    (*m_editorCount)++; 

    return editor; 
} 

void MyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const 
{ 
    ... 
} 

void MyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const 
{ 
    ... 
} 

void MyItemDelegate::onEditorDestroyed(QObject* obj) 
{ 
    printf("editor %p destroyed\n", (void*) obj); 
    (*m_editorCount)--; 
} 

En algunas ocasiones, por ejemplo, cuando se mueve al siguiente elemento en el árbol usando las teclas del cursor, Qt creará primero el nuevo editor y luego destruirá el anterior. Por lo tanto, m_editorCount debe ser un número entero en lugar de un bool.

Desafortunadamente, createEditor() es una función const.Por lo tanto, no puede crear un int-miembro. En su lugar, cree un puntero a un int y úselo.

+0

Agradable. Solo algunos comentarios: use mejor mutable int en lugar de int *. Además, no es necesario volver a implementar setEditorData() y setModelData() en la solución proporcionada, por lo que podría haberlos omitido para mayor claridad. – emkey08

+0

Sí, tienes razón. Ints mutables sería un poco mejor. –

6

Sólo comprobar si el valor de retorno de

State QAbstractItemView::state() const 

es

QTableView::EditingState 
+0

No estoy seguro de que si está en ese estado es suficiente para determinar que es para ** la celda actual ** – Trompa

0

Aquí es una idea, es incluso útil para obtener el widget de edición/combinado antes de la edición comienza ...

simplemente emite una señal y la consume en la ventana principal ... esto es lo que utilicé para obtener el cuadro combinado en QTableWidget antes de editar ...

primero crear una señal en ComoBoxItemDelegate ...

signals: 
    void OnComboEdit(QComboBox* pCombo) const; 

luego emiten la señal en el método createEditor ...

QWidget* ComboBoxItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const 
{ 
    // Create the combobox and populate it 
    QComboBox* cb = new QComboBox(parent); 
    emit OnComboEdit(cb); 
    return cb; 
} 

y en el MainWindow declarar una función para recibir el Singal ...

void MainWindow::OnComboEidt(QComboBox *pCB) const 
{ 
    qDebug() << "Combo Eidt Singal Received"; 
} 

Entonces, finalmente, en el constructor de MainWindow conectarlo ...

ComboBoxItemDelegate* cbid = new ComboBoxItemDelegate(ui->tableWidget); 
connect(cbid, &ComboBoxItemDelegate::OnComboEdit, this, &MainWindow::OnComboEidt); 
ui->tableWidget->setItemDelegateForColumn(0, cbid); 
1

Si conoce el índice del elemento que se está editando, puede llamar al indexWidget() e intentar echarlo. Si es válido, no solo sabrá que está editando, sino que también tendrá a mano su widget de editor.

EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex())); 
if(editWidget) 
{ 
    //yep, ur editing bro 
} 
Cuestiones relacionadas