QtQuick TableView CheckBox委托调用QAbstractTableModel的setData函数

时间:2014-06-16 11:40:37

标签: qt checkbox tableview qtquick2 qabstracttablemodel

我无法在QT中连接Qml中的T​​ableView和QA中的QAbstractTableModel的setData函数。我的想法是能够将活动检查为"完成"通过CkeckBox代表。我尝试覆盖setData函数以使用行而不是QmodelIndex并将其作为参数从qml文件发送到view.currentrow。但它不起作用(currentrow总是发送默认的-1值)。

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://Radost@bitbucket.org/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

知道我该怎么做吗?

1 个答案:

答案 0 :(得分: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中只应有一个大的switch语句,用于查找role的不同值。

为dataChanged()创建一个新索引是没有意义的:

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

您应该在setData( const QModelIndex& index ...中重复使用该参数,因为它具有唯一可能正确的值。