确保QTableView中列的唯一值

时间:2014-11-03 22:50:00

标签: c++ qt

我已实施自定义QTableViewQAbstractTableModelQTableView使用Qt - 默认文本行编辑委托来操作字符串数据。我想确保在提交编辑(按enter)后,该字符串对于其列是唯一的。如果另一行具有该列的相同值,则编辑将被拒绝,可能使用弹出框,然后文本行编辑将以编程方式重新进入编辑模式,以便用户可以再次尝试。

我考虑过使用自定义委托,并可能通过信号和插槽在委托和表视图之间进行通信。委托可以确保setModelData()内的值是唯一的。要做到这一点,必须注入有关其他列的知识。如果该值不唯一,则委托可以发出表视图将拾取的信号;像notUniqueTryAgain()这样的东西。在该插槽内,表格会弹出一条消息,然后在单元格上调用edit()。这是正确的方法吗?

1 个答案:

答案 0 :(得分: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;

signals:

public slots:

};

#endif // ITEMDELEGATE_H

.cpp的

#include "itemdelegate.h"
#include <QLineEdit>
#include <QDebug>

ItemDelegate::ItemDelegate(QObject *parent) :
    QItemDelegate(parent)
{
}

QWidget *ItemDelegate::createEditor(QWidget *parent,
                                    const QStyleOptionViewItem &option,
                                    const QModelIndex &index) const
{
    QLineEdit *editor = new QLineEdit(parent);
    return editor;
}


void ItemDelegate::setEditorData(QWidget *editor,
                                 const QModelIndex &index) const
{
    QString value =index.model()->data(index, Qt::EditRole).toString();
    QLineEdit *line = static_cast<QLineEdit*>(editor);
    line->setText(value);
}


void ItemDelegate::setModelData(QWidget *editor,
                                QAbstractItemModel *model,
                                const QModelIndex &index) const
{
    QLineEdit *line = static_cast<QLineEdit*>(editor);
    QString data = line->text();

    int column = index.column();

    for(int i = 0; i < model->rowCount(); i++)
    {
        QModelIndex cur = model->index(i,column);
        qDebug() << data << model->data(cur, Qt::EditRole).toString();
        if(data == model->data(cur, Qt::EditRole).toString())
        {
            model->setData(index, "wrong");
            return;
        }
    }

    model->setData(index, data);
}


void ItemDelegate::updateEditorGeometry(QWidget *editor,
                                        const QStyleOptionViewItem &option,
                                        const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

用法:

ItemDelegate *itDelegate = new  ItemDelegate;
ui->tableView->setItemDelegate(itDelegate);

这是一个很好的例子,所以你可以做其他所有事情,例如:

if(data == model->data(cur, Qt::EditRole).toString())
{
    //model->setData(index, "wrong");
    QMessageBox msgBox;
    msgBox.setText("Try again.");
    msgBox.exec();
    return;
}

等等。

当然,如果视图中有很多项目,它可能会很慢,因此您可以使用QProgressDialog向用户显示您需要的次数:

QProgressDialog progress("Checking...", "Searching", 0, model->rowCount(), 0);
for(int i = 0; i < model->rowCount(); i++)
{
    progress.setValue(i);
    QModelIndex cur = model->index(i,column);
    qDebug() << data << model->data(cur, Qt::EditRole).toString();
    if(data == model->data(cur, Qt::EditRole).toString())
    {
        model->setData(index, "wrong");
        return;
    }
    if (progress.wasCanceled())
       return;
}
progress.close();