2014-06-16 33 views
1

我無法連接QT中的TableView和QT中QAbstractTableModel的setData函數。我的想法是能夠通過CkeckBox委託檢查活動「完成」。我嘗試覆蓋setData函數來處理QmodelIndex行,並將其作爲參數從qml文件發送到view.currentrow。但它不起作用(currentrow總是發送默認的-1值)。QtQuick TableView CheckBox委託調用QAbstractTableModel的setData函數

main.qml

import QtQuick 2.0 
import QtQuick.Window 2.1 
import QtQuick.Controls 1.1 
import QtQuick.Dialogs 1.0 
import TodoM 1.0 

Rectangle{ 
width: 600 
height: 400 

TextField{ 
    id:activityDescriptionTextEdit 
    anchors.top: parent.top 
    width: 500 
    height: 50 
} 
Button{ 
    id: saveActivityButton 
    text: "Save Activity" 
    anchors.left: activityDescriptionTextEdit.right 
    onClicked: myModel.appendTodoFromQtQuick (activityDescriptionTextEdit.text) 
} 

TextField{ 
    id: filePathDisplay 
    anchors.top: activityDescriptionTextEdit.bottom 
    width: 500 
    height: 50 
} 
Button{ 
    text: "Save File" 
    anchors.left: filePathDisplay.right 
    anchors.top: activityDescriptionTextEdit.bottom 
    onClicked: saveFileDialog.open() 
} 

TableView{ 
id:view 
    anchors.top: filePathDisplay.bottom 
    width: 500 
    height: 400 

    TableViewColumn{ 
     id: firstColumn 
     title: "Is Done" 
     role: "isDoneStateCheckState" 
     width:100; 
     delegate: CheckBox { 
      id: checkBox 
      onCheckedChanged: { 
       //Here is where I want to call setData 
      } 
     } 
    } 

    TableViewColumn{ 

     title: "Activity" 
     role: "activityDescriptionState" 
     width:200 
    } 

    TableViewColumn{ 
     role: "timeStampState" 
     width:200 
    } 
    model: myModel 
} 
FileDialog{ 
    id: saveFileDialog 
    title: "Save File As" 
    selectExisting: false 
    selectMultiple: false 
    nameFilters: "*txt" 
    onAccepted: { 
     _ft.saveFile(saveFileDialog.fileUrl, myModel) 
    } 

    onRejected: { 
     console.log("Canceled") 
    } 
} 

}

TodoModel.cpp

#include "TodoModel.h" 
    #include "QModelIndex" 
    #include "QDebug" 

    TodoModel::TodoModel(QObject *parent) 
    : QAbstractTableModel(parent) 

    { 

    } 

    TodoModel::~TodoModel() 
    { 
     } 

    QModelIndex TodoModel::parent(const QModelIndex& child) const 
    { 
    Q_UNUSED(child) 

    return QModelIndex(); 
    } 

    int TodoModel::rowCount(const QModelIndex& parent) const 
    { 
    Q_UNUSED(parent) 

    return m_todos.count(); 
    } 

    int TodoModel::columnCount(const QModelIndex& parent) const 
    { 
    Q_UNUSED(parent) 

    return ColumnsCount; 
    } 

    QVariant TodoModel::data(const QModelIndex& index, int role) const 
    { 
    int columnIndex = index.column(); 
    const int rowIndex = index.row(); 
    switch (role) 
    { 
     case IsDoneRole: 
     case IsDoneCheckStateRole: 
      columnIndex = ColumnIndexIsDone; 
      break; 
     case ActivityDesctriptionRole: 
      columnIndex = ColumnIndexActivityDescription; 
      break; 
     case TimeStampRole: 
      columnIndex = ColumnIndexTimestamp; 
      break; 
     default: 
      break; 
    } 
    if (! this->isValidColumnIndex(columnIndex) 
     || ! this->isValidRowIndex(rowIndex)) 
    { 
     return QVariant(); 
    } 
    const Todo& todo = m_todos[ rowIndex ]; 
    switch (columnIndex) 
    { 

     case ColumnIndexIsDone: 
      if (role == Qt::CheckStateRole 
       || role == IsDoneCheckStateRole) 
      { 
       return todo.isDone() 
         ? Qt::Checked 
         : Qt::Unchecked; 
      } 
      else if (role == Qt::UserRole 
         || role == IsDoneRole) 
      { 
       return todo.isDone(); 
      } 

      break; 

     case ColumnIndexActivityDescription: 
      if (role == Qt::DisplayRole) 
      { 

       return todo.activityDescription(); 
      } 
      else if (role == Qt::UserRole 
         || role == ActivityDesctriptionRole) 
      { 

       return todo.activityDescription(); 
      } 
      //Maham Brake-ovete i stava o.O 

      break; 

     case ColumnIndexTimestamp: 
      if (role == Qt::DisplayRole) 
      { 
       return todo.addedTimestamp().toString("dd/MM/yyyy hh:mm:ss.zzz"); 
      } 
      else if (role == Qt::UserRole 
         || role == TimeStampRole) 
      { 
       return todo.addedTimestamp(); 
      } 

      break; 

     default: 
      break; 
    } 

    return QVariant(); 
    } 

    QVariant TodoModel::headerData(int section, Qt::Orientation orientation, int role)  const 
    { 
    if (! this->isValidColumnIndex(section) 
     || orientation != Qt::Horizontal 
     || role != Qt::DisplayRole) 
    { 
     return QVariant(); 
    } 

    switch (section) 
    { 
     case ColumnIndexIsDone: 
      return tr("Is Done"); 
     case ColumnIndexActivityDescription: 
      return tr("Activity Description"); 
     case ColumnIndexTimestamp: 
      return tr("Timestamp"); 
     default: 
      break; 
    } 

    return QVariant(); 
    } 

    Qt::ItemFlags TodoModel::flags(const QModelIndex& index) const 
    { 
    Qt::ItemFlags finalFlags = QAbstractTableModel::flags(index); 
    if (index.column() == ColumnIndexIsDone) 
    { 
     finalFlags |= Qt::ItemIsUserCheckable; 
    } 

    return finalFlags; 
    } 
    bool TodoModel::setData(const QModelIndex& index, const QVariant& value, int role) 
    { 

    const int rowIndex = index.row(); 
    const int columnIndex = index.column(); 
    if (! this->isValidRowIndex(rowIndex) 
     || ! this->isValidColumnIndex(columnIndex)) 
    { 
     return false; 
    } 

    Todo& todo = m_todos[ rowIndex ]; 

    switch (columnIndex) 
    { 
     case ColumnIndexIsDone: 
     { 
      if (role != Qt::CheckStateRole 
       && role != IsDoneRole 
       && role != IsDoneCheckStateRole) 
      { 
       return false; 
      } 

      bool converted = false; 
      const Qt::CheckState checkState = static_cast<Qt::CheckState> (value.toInt(& converted)); 
      const bool isChecked = checkState == Qt::Checked; 
      if (! isChecked 
       && checkState != Qt::Unchecked) 
      { 
       return false; 
      } 

      if (todo.isDone() == isChecked) 
      { 
       return false; 
      } 

      todo.setIsDone(isChecked); 
      QModelIndex index; 
      index = index.child(rowIndex, 0); 
      emit dataChanged(index, index); 

      break; 
     } 
     default: 
      break; 
    } 

    return true; 
    } 

    void TodoModel::appendTodo(const Todo& aTodo) 
    { 
    const int previousRowsCount = this->rowCount(); 
    this->beginInsertRows(QModelIndex(), previousRowsCount, previousRowsCount); 
    m_todos.append(aTodo); 

    this->endInsertRows(); 
} 

    void TodoModel::clear() 
    { 
    const int rowsCount = this->rowCount(); 
    if (rowsCount <= 0) 
    { 
     return; 
    } 

    this->beginRemoveRows(QModelIndex(), 0, rowsCount - 1); 
    m_todos.clear(); 
    this->endRemoveRows(); 
    } 

    bool TodoModel::isValidColumnIndex(const int columnIndex) const 
    { 
    return 0 <= columnIndex && columnIndex < this->columnCount(); 
    } 

     bool TodoModel::isValidRowIndex(const int rowIndex) const 
     { 
     return 0 <= rowIndex && rowIndex < this->rowCount(); 
     } 
     QList<Todo> TodoModel::todos() const 
     { 
     return m_todos; 
     } 


     void TodoModel::appendTodoFromQtQuick(QString aActivityDescription) 
     { 
     Todo todo; 
     todo.setIsDone(false); 
     todo.setActivityDescription(aActivityDescription); 
     todo.setAddedTimestamp(QDateTime::currentDateTime()); 
     appendTodo(todo); 
     } 

     QHash<int, QByteArray> TodoModel::roleNames() const 
     { 
     QHash<int, QByteArray> roles; 
     roles[IsDoneRole] = "isDoneState"; 
     roles[IsDoneCheckStateRole] = "isDoneStateCheckState"; 
     roles[ActivityDesctriptionRole] = "activityDescriptionState"; 
     roles[TimeStampRole] = "timeStampState"; 
     return roles; 
     } 

TodoModel.h

#ifndef TODOMODEL_H 
#define TODOMODEL_H 

#include "Todo.h" 

#include <QAbstractTableModel> 
#include <QList> 

enum ColumnIndex 
{ 
    ColumnIndexIsDone    = 0, 
    ColumnIndexActivityDescription = 1, 
    ColumnIndexTimestamp   = 2, 
    ColumnsCount     = 3 
}; 



class TodoModel : public QAbstractTableModel 
{ 
    Q_OBJECT 

public: 
    explicit TodoModel(QObject* parent = 0); 
    virtual ~TodoModel(); 

    enum TodoColumnRoles { 
     IsDoneRole    = Qt::UserRole + 1, 
     IsDoneCheckStateRole  = Qt::UserRole + 2, 
     ActivityDesctriptionRole = Qt::UserRole + 3, 
     TimeStampRole   = Qt::UserRole + 4 
    }; 

    virtual QModelIndex parent(const QModelIndex& child) const; 
    virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; 
    virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; 
    virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; 
    virtual QVariant headerData(int section, Qt::Orientation orientation, 
           int role = Qt::DisplayRole) const; 
    // https://[email protected]/Radost/qtquickcontrols.git 
    Qt::ItemFlags flags(const QModelIndex& index) const; 
    Q_INVOKABLE virtual bool setData(const QModelIndex& index, const QVariant &value, int role = Qt::EditRole); 

    void appendTodo(const Todo& aTodo); 
    void clear(); 

    bool isValidColumnIndex(const int columnIndex) const; 
    bool isValidRowIndex(const int rowIndex) const; 

    Q_INVOKABLE QList<Todo> todos() const; 
    //Q_INVOKABLE QList<Todo*> ptodos() const; 

public slots: 

    Q_INVOKABLE void appendTodoFromQtQuick(QString aActivityDescription); 
protected: 
    QHash<int, QByteArray> roleNames() const; 
private: 
    QList<Todo> m_todos; 
    //Q_QList< Todo* > m_ptodos; 

}; 

#endif // TODOMODEL_H 

任何想法,我該怎麼辦呢?

回答

0

你的代碼是閱讀和維護的噩夢。請注意你的製表和空格。

您可以通過在代理設置變量(稱爲類的角色名)隱含調用setData

TableViewColumn{ 
    id: firstColumn 
    title: "Is Done" 
    role: "isDoneStateCheckState" 
    width:100; 
    delegate: CheckBox { 
     id: checkBox 
     onCheckedChanged: { 
      isDoneState = checked 
     } 
    } 
} 

枚舉自動列舉,去爲:

enum TodoColumnRoles { 
    IsDoneRole = Qt::UserRole, 
    IsDoneCheckStateRole, 
    ActivityDesctriptionRole, 
    TimeStampRole 
}; 

應該只有一個setData中的大開關語句查找role的不同值。

這是沒有意義的,爲dataChanged()創建新的索引:

QModelIndex index; 
index = index.child(rowIndex, 0); 
emit dataChanged(index, index); 

你應該重用setData(const QModelIndex& index ...的參數,因爲它具有唯一可能正確的值。