2014-12-01 4 views
6

나는 QStandardItemModel으로 설정 한 QTableView입니다. 사용자가보기의 일부 색인에서 데이터를 편집하면 모델에서 dataChanged() 신호를 내 보냅니다. SLOT에서 신호를 처리 할 때 QModelIndex 범위의 사용자가 변경되어 사용자가 입력 한 새 값을 가져올 수 있습니다. 그 시점에서 어떻게 이전 값을 얻을 수 있습니까?QAbstractItemModel :: dataChanged() 신호를 처리 할 때 이전 값을 얻는 방법?

+0

slot'a 인수에 언급 된 색인에 이전 값이 아닌 새로운 값이 포함되어 있는지 실제로 확인 했습니까? – vahancho

+0

예. 이것이 신호가 "dataBeforeChange"가 아닌 dataChanged()라고하는 이유입니다. –

+0

글쎄, 데이터가 이미 변경된 경우, 이전 데이터가 필요한 것은 무엇입니까? – vahancho

답변

2

QStandardItemModel은 간단한 모델이므로이 기능이있는 신호가 없습니다. 이러한 기능을 원할 경우 QAbstractItemModel의 하위 클래스를 만들고 사용자 정의 클래스를 사용하여 setData을 구현하고 이전 값과 새 값을 모두 포함하는 사용자 정의 신호를 내보낼 수 있습니다.

해결 방법으로 일부 슬롯 QStandardItemModelitemChanged 신호를 연결할 수 있습니다

connect(model,SIGNAL(itemChanged(QStandardItem*)),this, SLOT(onModelChanged(QStandardItem*))); 

, 이전의 값으로 사용하는 모델의 Qt::UserRole로 새로운 값을 저장 슬롯은 다음에 호출 할 때 :

void MyClass::onModelChanged(QStandardItem *item) 
{ 

    disconnect(model,SIGNAL(itemChanged(QStandardItem*)),this, SLOT(onModelChanged(QStandardItem*))); 

    QVariant oldValue = item->data(Qt::UserRole); 

    item->setData(item->data(Qt::DisplayRole), Qt::UserRole); //Store the new value for next use 

    connect(model,SIGNAL(itemChanged(QStandardItem*)),this, SLOT(onModelChanged(QStandardItem*))); 

} 
1

사용자 대리인 그래서 가능한 솔루션과 데이터를 변경하는 단계이다

#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: 
    void dataChanged(QString oldValue,QString newValue) const; 

public slots: 
private: 
    mutable QString old;//we want change member data in const method 

}; 

#endif // ITEMDELEGATE_H 

많은 방법을 볼 수 있듯이 기본적으로 const이므로 문제를 피하기 위해 몇 가지 트릭 (예 : mutable)을 수행했습니다. 또한 편집 된 대답에서 이전 데이터를 저장하지 않습니다. UserRole+1, 모두 이전의 mutable 변수와 함께 수행됩니다.

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 
{ 
    old = index.model()->data(index, Qt::EditRole).toString();//store old data 
    QLineEdit *line = qobject_cast<QLineEdit*>(editor); 
    line->setText(old); 
} 


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

    emit dataChanged(old, line->text()); 
    model->setData(index, data); 
} 


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

사용법 :

ItemDelegate * del = new ItemDelegate; 
    connect(del,&ItemDelegate::dataChanged,[=](QString oldValue,QString newValue) { 
     qDebug() << "old" << oldValue<< "new" <<newValue ; 
    }); 
    ui->tableView->setItemDelegate(del); 

나는 그것을 테스트하고 작동합니다. 다른 모델에서도 작동합니다. QTableView은 기본적으로 lineEdit을 위임자로 사용하므로 사용자는 변경 사항을 볼 수 없습니다.

여기서는 C++11 (CONFIG += c++11 ~ .pro 파일)과 new syntax of signals and slots을 사용했지만 원하는 경우 이전 구문을 사용할 수 있습니다.

2

일부 연구 끝에 나는이 동작을 달성 할 표준 방법이 없다는 것을 알아 냈습니다. 이 문제를 해결하기 위해 나는 QStandardItemModel을 상속 같은 setData() 다시 구현했다 :

void SomeObject::handleDataChange(const QModelIndex &topLeft, const QModelIndex &bottomRight) 
{ 
    ... 
    const QVariant &vOldData = index.data(Qt::UserRole + 1); // here is the old data 
    const QVariant &vNewData = index.data(Qt::DisplayRole); // here is the new data 
    ... 
} 
0

모든 솔루션이 전에 :

class RecallModel : public QStandardItemModel 
{ 
public: 
    RecallModel (QObject * parent = 0) : QStandardItemModel(parent) {} 

    // Reimplemented 
    bool setData(const QModelIndex &index, const QVariant &value, int role= Qt::EditRole) 
    { 
     // backup the previous model data 
     if (role == Qt::EditRole || role == Qt::DisplayRole) 
      QStandardItemModel::setData(index, data(index), Qt::UserRole + 1); 

     return QStandardItemModel::setData(index, value, role); 
    } 
}; 

그리고 그 후 나는 dataChanged() 신호를 처리하는 슬롯에있는 기존 데이터에 액세스 할 수 있습니다

대답은 Qt 특정 기능에 의존합니다. 그러나 INSERT, UPDATE, DELETE (SQL은 아니지만 공통) 기능을 Qt 프레임 워크 외부로 이동할 수 있습니다. 단위 작업 디자인 패턴 및 관련 도메인 개체 패턴 "엔터프라이즈 응용 프로그램 아키텍처의 패턴"에서 확인하십시오.

setData() 중 수정할 때이 값을 유지하고 수정할 수 있습니다.