2010-08-06 2 views
8

C'è un modo per determinare se un QTableView ha un editor aperto nella cella corrente? Ho bisogno di gestire la seguente situazione:Determinare se QTableView ha un editor aperto

  • Un utente fa doppio clic su una cella e modifica i dati, ma lascia la cella in stato di "modifica".
  • Su un'altra parte dell'interfaccia utente, viene intrapresa un'azione che modifica la riga selezionata del modello sottostante.
  • Indietro sulla mia vista, voglio determinare se la riga appena selezionata è la stessa della riga aperta. In caso contrario, ho bisogno di agire. (Prompt l'utente? Commettere automaticamente? Ripristinare?)

vedo come ottenere l'elemento corrente, e può ottenere il delegato su tale elemento, ma non vedo alcun isEditMode() proprietà speravo di trovare.

Qualcuno può indicarmi la giusta direzione?

risposta

2

sottoclasse il delegato in modo che esso include una funzione di accesso che ti dice quando è la modifica:

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

allora si può solo controllare il delegato per vedere cosa sta succedendo. In alternativa e/o se non ti piace il mutable, è possibile emettere segnali in modo da sapere in quale stato il delegato è in.

+0

Solo una nota, penso che intendessi * mutevole *, non * volatile *. –

+0

@Caleb - Hai ragione. Modificato - e grazie per averlo indicato. –

+3

Come già indicato da Florian Kusche nella sua risposta, questo non funziona perché setModelData() viene chiamato solo se la modifica viene eseguita, ma non se è annullata. – emkey08

3

Connetti a modello DataChanged sottostante segnale

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

È possibile controllare se la cella dove i dati è cambiato è lo stesso che il currentIndex

QModelIndex QAbstractItemView::currentIndex() const 

non si può sapere se la cella corrente ha avuto un editor open rettilineo, ma può controllare se la vista è in QAbstractItemView :: EditingState

State QAbstractItemView::state() const 

Dovrebbe essere sufficiente per fare quello che vuoi.

2

È possibile creare una sottoclasse QTableView per poter accedere alla funzione state(), che purtroppo è protetta. Tuttavia, non l'ho provato.

Se si dispone già di una sottoclasse QStyledItemDelegate, è possibile utilizzarla per tracciare se un editor è attualmente aperto. Tuttavia, non è possibile utilizzare solo setEditorData/setModelData, perché setModelData non verrà chiamato, quando l'utente annulla la modifica. Invece, puoi tenere traccia della creazione e della distruzione dell'editor stesso.

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

Attuazione:

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

In alcuni casi, ad esempio quando si passa all'elemento successivo nell'albero usando i tasti cursore, Qt creerà prima il nuovo editor e quindi distruggerà quello vecchio. Quindi, m_editorCount deve essere un numero intero anziché un valore bool.

Sfortunatamente, createEditor() è una funzione const.Pertanto, non è possibile creare un int -member. Invece, crea un puntatore a int e usalo.

+0

Bello. Solo alcuni commenti: meglio usare mutable int anziché int *. Inoltre, non è necessario reimplementare setEditorData() e setModelData() nella soluzione fornita, quindi è possibile averli omessi per maggiore chiarezza. – emkey08

+0

Sì hai ragione. Gli INTI mutevoli sarebbero un po 'migliori. –

6

Basta verificare se il valore di ritorno di

State QAbstractItemView::state() const 

è

QTableView::EditingState 
+0

Non sono sicuro che se è su quello stato è sufficiente per determinare che è per la ** cella corrente ** – Trompa

0

Ecco un'idea, la sua anche utile per ottenere il widget di modifica/combo prima che inizi l'edit ...

emette semplicemente un segnale e lo consuma nella finestra principale ... questo è quello che ho usato per ottenere una casella combinata in QTableWidget prima di modificare ...

prima creare un segnale in ComoBoxItemDelegate ...

signals: 
    void OnComboEdit(QComboBox* pCombo) const; 

quindi emettono il segnale nel metodo 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; 
} 

e nel MainWindow dichiarare una funzione per ricevere singal ...

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

Poi finalmente nel costruttore di MainWindow collegarlo ...

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

Se si conosce l'indice dell'elemento che si modifica, è possibile chiamare indexWidget() e provare a lanciarlo. Se è valido, non solo sai che stai modificando, ma hai anche a portata di mano il tuo widget di editor.

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