Собственно модель - наследник QAbstractListModel, представление - GridView. Проблема в том, что по doubleClick на элементе я должен изменить текст внутри него. относительно документации реализовал в наследнике setData и flags, при доблклике в модели проиходит обновление значения по роли, но обратно представление его уже не получает. хотя явный вызов dataChanged присутствует, т.е. не срабатвает привязка что-ли. ниже код
@audioTrackSetupModel.h
#ifndef AUDIOTRACKSETUPMODEL_H
#define AUDIOTRACKSETUPMODEL_H
#include <QObject>
#include <QAbstractListModel>
#include <QList>
#include <QVariant>
#include <QMetaType>
class AudioTrackItem : public QObject
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged)
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
public:
AudioTrackItem(QString text = "", bool selected = false, bool enabled = false, QObject *parent = 0);
QString text() const;
void setText(QString text);
bool selected() const;
void setSelected(bool value);
bool enabled() const;
void setEnabled(bool state);
signals:
void textChanged();
void selectedChanged();
void enabledChanged();
private:
QString m_text;
bool m_selected;
bool m_enabled;
};
class AudioTrackSetupModel : public QAbstractListModel
{
Q_OBJECT
public:
enum ATSRItemRoles
{
TextRole = Qt::UserRole + 1,
SelectedRole,
LabelsRole
};
AudioTrackSetupModel(QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole);
Qt::ItemFlags flags(const QModelIndex &index) const;
void initGrid();
public slots:
QList<QVariant> chLabels() const;
bool isInSelection(QVariant index) const;
private:
QList<AudioTrackItem* > m_items;
QHash<int, QByteArray> roleNames() const;
int m_selectedRow;
};
#endif // AUDIOTRACKSETUPMODEL_H
@audioTrackSetupModel.cpp
#include "audiotracksetupmodel.h"
#include <QDebug>
AudioTrackItem::AudioTrackItem(QString text, bool selected, bool enabled, QObject *parent)
: QObject(parent),
m_text(text),
m_selected(selected),
m_enabled(enabled)
{
}
QString AudioTrackItem::text() const
{
return m_text;
}
void AudioTrackItem::setText(QString text)
{
if (m_text != text)
{
m_text = text;
emit textChanged();
}
}
bool AudioTrackItem::selected() const
{
return m_selected;
}
void AudioTrackItem::setSelected(bool value)
{
if (m_selected != value)
{
m_selected = value;
emit selectedChanged();
}
}
bool AudioTrackItem::enabled() const
{
return m_enabled;
}
void AudioTrackItem::setEnabled(bool state)
{
if (m_enabled != state)
{
m_enabled = state;
emit enabledChanged();
}
}
AudioTrackSetupModel::AudioTrackSetupModel(QObject *parent)
: QAbstractListModel(parent),
m_selectedRow(-1)
{
}
int AudioTrackSetupModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_items.count();
// return 1024; // 32 ch * 32 ch
}
QHash<int, QByteArray> AudioTrackSetupModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[TextRole] = "text";
roles[SelectedRole] = "selected";
roles[LabelsRole] = "labels";
return roles;
}
QVariant AudioTrackSetupModel::data(const QModelIndex &index, int role) const
{
if (role == TextRole)
{
return m_items[index.row()] -> text();
}
if (role == SelectedRole)
{
return m_items[index.row()] -> selected();
}
if (role == LabelsRole)
{
return chLabels();
}
return QVariant();
}
void AudioTrackSetupModel::initGrid()
{
for (int i = 0; i < 1024; ++i)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_items.append(new AudioTrackItem);
endInsertRows();
}
}
Qt::ItemFlags AudioTrackSetupModel::flags(const QModelIndex &index) const
{
return (QAbstractListModel::flags(index)|Qt::ItemIsEditable);
}
bool AudioTrackSetupModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role == TextRole)
{
qDebug()<<index.row();
m_items[index.row()] -> setText(value.toString());
qDebug()<<m_items[index.row()]->text();
//emit dataChanged(QAbstractListModel::createIndex(index.row(), 0), QAbstractListModel::createIndex(index.row(), 0));
emit dataChanged(QAbstractListModel::createIndex(0, 0), QAbstractListModel::createIndex(1024, 0));
return true;
}
if (role == SelectedRole)
{
if (m_selectedRow != index.row() / 32)
{
if (m_selectedRow >= 0)
{
for (int i = m_selectedRow * 32; i < (m_selectedRow + 1) * 32; ++i)
m_items[i] -> setSelected(false);
emit dataChanged(QAbstractListModel::createIndex(m_selectedRow * 32, 0), QAbstractListModel::createIndex((m_selectedRow + 1) * 32, 0));
}
m_selectedRow = index.row() / 32;
for (int i = m_selectedRow * 32; i < (m_selectedRow + 1) * 32; ++i)
m_items[i] -> setSelected(value.toBool());
emit dataChanged(QAbstractListModel::createIndex(m_selectedRow * 32, 0), QAbstractListModel::createIndex((m_selectedRow + 1) * 32, 0));
//emit dataChanged(QAbstractListModel::createIndex(0, 0), QAbstractListModel::createIndex(1024, 0));
return true;
}
}
return false;
}
QList<QVariant> AudioTrackSetupModel::chLabels() const
{
QList<QVariant> tl;
for (int i = 0; i < 32; ++i)
{
tl<<QVariant::fromValue(i + 1);
}
return tl;
}
bool AudioTrackSetupModel::isInSelection(QVariant index) const
{
return index.toInt() == m_selectedRow;
}
@main.qml
import QtQuick 2.0
import "Style.js" as S
Rectangle {
width: 800
height: 800
property int gridItemWidth: 20
property int gridItemHeight: 15
property int marginSize: 1
color: S.blueBackgroundColor
GridView {
id: grid
width: 32 * gridItemWidth
height: 32 * gridItemHeight
model: atm
cellWidth: gridItemWidth
cellHeight: gridItemHeight
header: chLabels
footer: chLabels
Component {
id: chLabels
Rectangle {
width: grid.width - 2 * marginSize
height: gridItemHeight - 2 * marginSize
color: "transparent"
ListView {
width: parent.width
height: parent.height
model: atm.chLabels() //labels
orientation: ListView.Horizontal
delegate: Rectangle {
width: gridItemWidth
height: gridItemHeight
color: "transparent"
Text {
text: modelData// + 1
color: modelData === 5 ? S.yellowColor : S.orangeColor
anchors.centerIn: parent
}
}
}
}
}
delegate: Rectangle {
width: gridItemWidth - 2 * marginSize
height: gridItemHeight - 2 * marginSize
color: S.blueBackgroundColor
border {
width: 1
color: selected ? S.yellowColor :S.blueColor
}
Rectangle {
width: parent.width - 2 * parent.border.width
height: parent.height - 2 * parent.border.width
anchors.centerIn: parent
color: selected ? S.yellowColor : S.blueBackgroundColor
opacity: text === "" && selected ? 0.25 : 1
Text {
id: textBox1
text: text
color: S.blackColor
font.pixelSize: S.mediumTextSize - 1
anchors.centerIn: parent
//z: 1
}
}
MouseArea {
anchors.fill: parent
onClicked: {
selected = !selected
console.log("qml:", text)
console.log("textBox1", textBox1.text)
}
onDoubleClicked: {
text = "5"
//textBox1.text = "5"
}
}
}
}
}
@main.cpp
#include <QGuiApplication>
#include <QQuickView>
#include <QQmlContext>
#include <QDebug>
#include "audiotracksetupmodel.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
AudioTrackSetupModel atm;
atm.initGrid();
view.rootContext()->setContextProperty("atm", &atm);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.show();
return app.exec();
}
Вывод вот этих значений
console.log("qml:", text)
console.log("textBox1", textBox1.text)
показывает как раз, что в модели значение изменилось, qml его успешно читает при этом как новое, в то же время не изменилось значение текста для textBox1, хотя его значение это же вроде как привязка по роли:
Text {
id: textBox1
text: text
...