Определите, есть ли у QTableView открытый редактор - PullRequest
9 голосов
/ 06 августа 2010

Есть ли способ определить, есть ли у QTableView открытый редактор в текущей ячейке? Мне нужно разобраться в следующей ситуации:

  • Пользователь дважды щелкает ячейку и редактирует данные, но оставляет ячейку в состоянии «редактирования» .
  • В другой части пользовательского интерфейса выполняется действие, которое изменяет выбранную строку базовой модели.
  • Вернувшись к своему виду, я хочу определить, совпадает ли вновь выбранная строка с открытой строкой. Если нет, мне нужно принять меры. (Подскажите пользователю «Подтвердить автоматически», «Восстановить»)

Я вижу, как получить текущий элемент, и могу получить делегата для этого элемента, но я не вижу ни одного свойства isEditMode(), которое я надеялся найти.

Может ли кто-нибудь указать мне правильное направление?

Ответы [ 6 ]

7 голосов
/ 13 марта 2014

Просто проверьте, является ли возвращаемое значение

State QAbstractItemView::state () const

есть

QTableView::EditingState
3 голосов
/ 29 августа 2013

Вы можете создать подкласс QTableView для доступа к функции state(), которая, к сожалению, защищена. Однако я этого не пробовал.

Если у вас уже есть подкласс QStyledItemDelegate, вы можете использовать его для отслеживания того, открыт ли редактор в данный момент. Однако вы не можете просто использовать setEditorData / setModelData, потому что setModelData не будет вызываться, когда пользователь отменяет редактирование. Вместо этого вы можете отслеживать создание и уничтожение самого редактора.

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

Реализация:

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

В некоторых случаях, например, при переходе к следующему элементу в дереве с помощью клавиш курсора, Qt сначала создаст новый редактор, а затем уничтожит старый. Следовательно, m_editorCount должно быть целым числом вместо bool.

К сожалению, createEditor() - это функция const. Следовательно, вы не можете создать int -члена. Вместо этого создайте указатель на int и используйте его.

3 голосов
/ 11 декабря 2012

Подключение к базовым данным модели. Измененный сигнал

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

Вы можете проверить, совпадает ли ячейка, в которой изменились данные, с текущим индексом

QModelIndex QAbstractItemView::currentIndex () const

Вы не можете знать, был ли в текущей ячейке открытый редактор, но можете проверить, находится ли представление в QAbstractItemView :: EditingState

State QAbstractItemView::state () const

Этого должно быть достаточно, чтобы делать то, что вы хотите.

2 голосов
/ 07 августа 2010

Подкласс вашего делегата, чтобы он включал аксессор, который сообщает вам, когда он редактирует:

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

Тогда вы можете просто проверить делегата, чтобы увидеть, что происходит.Альтернативно и / или если вам не нравится mutable, вы можете излучать сигналы, чтобы вы знали, в каком состоянии находится делегат.

1 голос
/ 31 декабря 2016

Если вам известен индекс редактируемого элемента, вы можете позвонить indexWidget() и попытаться разыграть его.Если он действителен, вы не только знаете, что редактируете, но и имеете удобный виджет для редактирования.

EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex()));
if(editWidget)
{
    //yep, ur editing bro
}
0 голосов
/ 08 сентября 2016

Вот идея, даже полезно получить виджет редактирования / комбо до начала редактирования ...

просто испустите сигнал и используйте его в главном окне ... вот что я использовал, чтобы получить поле со списком в QTableWidget перед редактированием ...

сначала создайте сигнал в ComoBoxItemDelegate ...

signals:
   void OnComboEdit(QComboBox* pCombo) const;

затем сгенерируйте сигнал в методе 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;
}

и в MainWindow объявить функцию для получения сингала ...

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

Затем, наконец, в конструкторе MainWindow подключите его ...

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