如何在QModelViews中组合模态对话框编辑器和就地小部件编辑器?

时间:2014-11-28 01:02:16

标签: c++ qt model-view-controller delegates

我有一个包含简单和复杂数据的模型,我希望有就地小部件来编辑简单数据,但是模态对话框可以编辑复杂数据......我怎样才能以干净的方式实现这一目标? (我真的更喜欢通过QItemDelegate的子类做一切,而且没有特定的视图黑客)

3 个答案:

答案 0 :(得分:2)

我认为你必须对视图进行子类化并覆盖QAbstractItemView::edit()函数来处理不同的编辑路径。例如:

class MyView : public QTreeView
{
    [..]
protected:
    bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event)
    {
        if (index.row() > 5) { // Use your own criteria for simple/complex data
            // Simple data with default editor.
            return QTreeView::edit(index, trigger, event);
        } else {
            // Edit complex data.
            QDialog dialog;
            dialog.exec();
            return false;
        }
    }
    [..]
};

答案 1 :(得分:2)

尝试下一个代表。我在示例中展示了主要想法:

部首:

#ifndef ITEMDELEGATE_H
#define ITEMDELEGATE_H

#include <QItemDelegate>

class ItemDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    explicit ItemDelegate(QObject *parent = 0);

protected:
    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;
    void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const;
    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);

signals:

public slots:

};

#endif // ITEMDELEGATE_H

我只向您展示editorEvent,因为您可以自己编写所有其他方法,它将是自定义委托,但在editorEvent我们创建模态对话框。

bool ItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
                               const QStyleOptionViewItem &option,
                               const QModelIndex &index)
{
    if(index.row()%2)//specific items, you can use it another options, it is just example
    {
        QInputDialog* dia = new QInputDialog;//create dialog, just example, it can be your QDialog subclass        
        dia->setInputMode(QInputDialog::TextInput);
        //dia->setAttribute(Qt::WA_DeleteOnClose);
        dia->setModal(true);
        connect(dia, &QInputDialog::finished,[=]()//connection which will take data from dialog
        {
           model->setData(index,dia->textValue());//provide some method in your dialog to get user data and set it in model 
           delete dia;//we don't want memory leaks
         });
        dia->show();
    }
    return QItemDelegate::editorEvent(event,model,option,index);
}

我在这里使用C++11CONFIG += c++11.pro文件)和new syntax of signals and slots

答案 2 :(得分:0)

这是一个古老的问题,但是鉴于两个答案都无法令人满意(返回错误,嵌套事件循环等时崩溃)... 请注意,我并没有责怪张贴者说“那样做不能干净”。

完全不同的受支持方法如何?

我以前有这样的实现(伪代码):

  1. 禁用“复杂”项目的编辑触发器

auto item = model->item(row, column);
item->setFlags(item->flags() & ~Qt::ItemFlag::ItemIsEditable); // not editable
  1. 连接到QAbstractItemView::activated

忽略“简单”项目的事件

connect(m_ui.tableView,
  &QAbstractItemView::activated,
  this,
  &QtGuiApplication2::onDataActivated);

//...

void QtGuiApplication2::onDataActivated(const QModelIndex &index) {
  if(!is_complex)
    return;

  EditDialog dlg;
  if(dlg.exec() == QDialog::DialogCode::Accepted) {
    updatemodel();
  }

}
  1. 项目委托: 忽略“复杂”项目。

    QWidget* VariableEditorDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &option,
    const QModelIndex &index) const {
      if(is_complex)
        return nullptr; // same as base class
      return new EditorWidget(parent);
    }
    

现在这当然不像只有委托人那样好,但是至少在崩溃时它不会如此紧密地绕过。