Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if QTableView has an open editor

Tags:

qt

qtableview

Is there any way to determine if a QTableView has an open editor in the current cell? I need to handle the following situation:

  • A user double-clicks a cell and edits the data, but leaves the cell in the "edit" state.
  • On another part of the UI, an action is taken that changes the selected row of the underlying model.
  • Back on my view, I want to determine if the newly selected row is the same as the open row. If not, I need to take an action. (Prompt the user? Commit automatically? Revert?)

I see how to get the current item, and can get the delegate on that item, but I don't see any isEditMode() property I was hoping to find.

Can someone point me in the right direction?

like image 611
Dave Mateer Avatar asked Aug 06 '10 18:08

Dave Mateer


4 Answers

Just check whether the return value of

State QAbstractItemView::state () const

is

QTableView::EditingState
like image 200
wedesoft Avatar answered Sep 17 '22 20:09

wedesoft


You can subclass QTableView in order to be able to access the state() function, which is unfortunately protected. However, I did not try that.

If you already have an QStyledItemDelegate subclass, you can use it to track whether an editor is currently open. However, you can't just use setEditorData/setModelData, because setModelData won't be called, when the user cancels editing. Instead, you can track the creation and destruction of the editor itself.

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 );
};

Implementation:

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)--;
}

On some occasions, e.g. when moving to the next item in the tree using the cursor keys, Qt will create the new editor first and then destroy the old one. Hence, m_editorCount must be an integer instead of a bool.

Unfortunately, createEditor() is a const function. Therefore, you cannot create an int-member. Instead, create a pointer to an int and use that.

like image 30
Florian Kusche Avatar answered Sep 18 '22 20:09

Florian Kusche


If you know the index of the item being edited, you can call indexWidget() and attempt to cast it. If it's valid, you not only know you're editing, but you also have your editor widget handy.

EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex()));
if(editWidget)
{
    //yep, ur editing bro
}
like image 29
mrg95 Avatar answered Sep 19 '22 20:09

mrg95


Subclass your delegate so that it includes an accessor that tells you when it's editing:

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; }

Then you can just check the delegate to see what's going on. Alternatively and/or if you don't like the mutable, you can emit signals so you know what state the delegate is in.

like image 40
Kaleb Pederson Avatar answered Sep 18 '22 20:09

Kaleb Pederson