Невозможно редактировать пользовательские элементы в QAbstractItemModel с пользовательским делегатом, производным от QStyledItemDelegate

Мне трудно реализовать свой собственный подход MVC в рамках Qt5.

Я создал собственный класс элементов, получил класс модели из QAbstractItemModel, класс делегата из QStyledItemDelegate и собрал все вместе в QTreeView.

Я максимально сократил свой код, чтобы создать несколько «минимальный» пример.

Я вижу следующее:
Я вижу мой заголовок с 42 там, и я вижу одну запись с надписью «Тестовый элемент». Тем не менее, когда я дважды щелкаю последний или нажимаю F2, пока он выбран — ничего не происходит.
Вызов editTriggers возвращает 10, что означает двойной щелчок должен работать (но они этого не делают).
Я, очевидно, что-то здесь упускаю, но после нескольких дней попыток выяснить это сам, я должен признать, что понятия не имею.
Вот моя программа:

РЕДАКТИРОВАТЬ НАЧИНАЕТСЯ, 28 ноября

Как мне предложил @eyllanesc, для удобства я создал небольшой репозиторий Github. Ссылка здесь:

https://github.com/phyz777/DelegateTest.git

РЕДАКТИРОВАТЬ КОНЕЦ, 28 ноября

main.cpp:

int main(int argc, char* argv[]){
QApplication a(argc, argv);
MainWindow w;
w.showFullScreen();

return a.exec();
}

mainwindow.hpp:

class MainWindow : public QMainWindow{
Q_OBJECT

public:
MainWindow(QWidget* parent = 0);
~MainWindow();
private slots:

private:
TestModel model;
};

mainwindow.cpp:

MainWindow::MainWindow(QWidget *parent)
:QMainWindow(parent),
model(){
this->model.insertTestItem(new TestClass());

QTreeView* treeView = new QTreeView(this);
treeView->setItemDelegate(new TestModelItemDelegate());
treeView->setModel(&this->model);
treeView->setRootIndex(this->model.index(0, 0, QModelIndex()));
std::cout << "Edit triggers: " << (int)treeView->editTriggers() << std::endl;
this->setCentralWidget(treeView);
}

MainWindow::~MainWindow(){
;
}

testmodel.hpp:

class TestModel:public QAbstractItemModel{
public:
TestModel();
~TestModel();

int rowCount(QModelIndex const& =QModelIndex()) const;
int columnCount(QModelIndex const& =QModelIndex()) const;

QModelIndex index(int, int, QModelIndex const& =QModelIndex()) const;
QModelIndex parent(QModelIndex const&) const;

QVariant headerData(int, Qt::Orientation, int=Qt::DisplayRole) const;
QVariant data(const QModelIndex&, int=Qt::DisplayRole) const;
Qt::ItemFlags flags(QModelIndex const&);

bool setHeaderData(int, Qt::Orientation, QVariant const&, int);
bool setData(QModelIndex const&, QVariant const&, int);

void insertTestItem(TestClass*);

RootItem* getRoot();
private:
RootItem* root;
};

testmodel.cpp:

TestModel::TestModel()
:root(new RootItem()){

}

TestModel::~TestModel(){

}

int TestModel::rowCount(QModelIndex const& parent) const{
TestModelItemBase* itemBase =
reinterpret_cast<TestModelItemBase*>(parent.internalPointer());
switch(itemBase->getItemType()){
case TestModelItemBase::ITEM_TYPE::ROOT:
{
RootItem* item = dynamic_cast<RootItem*>(itemBase);
return item->getList().size();
}
case TestModelItemBase::ITEM_TYPE::TEST_ITEM:
{
TestModelItem* item = dynamic_cast<TestModelItem*>(itemBase);
return 0;
}
default:
return -1;
}
}

int TestModel::columnCount(QModelIndex const& parent) const{
return 1;
}

QModelIndex TestModel::index(int row, int column, QModelIndex const& parent) const{
if(0!=column){
return QModelIndex();
}
if(!parent.isValid()){
if(row==0){
return this->createIndex(0, 0, this->root);
}
return QModelIndex();
}
TestModelItemBase* parentItemBase = reinterpret_cast<TestModelItemBase*>(parent.internalPointer());
TestModelItemBase::ITEM_TYPE itemType = parentItemBase->getItemType();
switch(itemType){
case TestModelItemBase::ITEM_TYPE::ROOT:
{
RootItem* parentItem = dynamic_cast<RootItem*>(parentItemBase);
return this->createIndex(row, 0, reinterpret_cast<void*>(parentItem->getList().at(row)));
}
case TestModelItemBase::ITEM_TYPE::TEST_ITEM:
return QModelIndex();
default:
return QModelIndex();
}
}

QModelIndex TestModel::parent(QModelIndex const& index) const{
TestModelItemBase* parent =
reinterpret_cast<TestModelItemBase*>(index.internalPointer());
return this->createIndex(parent->getIndex(), 0,
reinterpret_cast<void*>(parent->getParent()));
}

QVariant TestModel::headerData(int section, Qt::Orientation orientation, int role) const{
if (0==section && Qt::Orientation::Horizontal==orientation && Qt::DisplayRole==role) {
int i = 42;
return QVariant(i);
} else {
return QVariant();
}
}

QVariant TestModel::data(QModelIndex const& index, int role) const{
TestModelItemBase* item = reinterpret_cast<TestModelItemBase*>(index.internalPointer());
if(Qt::DisplayRole==role){
switch(item->getItemType()){
case TestModelItemBase::ITEM_TYPE::TEST_ITEM:
return QString("Test item");
default:
return QString("");
}
}else{
if(Qt::EditRole==role){
QMessageBox::information(nullptr, "Model data", "We have an edit role");
}
if(Qt::UserRole==role){
QMessageBox::information(nullptr, "Model data", "We have a user role");
}

return QVariant();
}
}

Qt::ItemFlags TestModel::flags(QModelIndex const&){
QMessageBox::information(nullptr, "Model Flags", "Selectable, Editable, Enabled");

return (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}

bool TestModel::setHeaderData(int, Qt::Orientation, const QVariant&, int){
QMessageBox::information(nullptr, "Set header data", "Just return true");

return true;
}

bool TestModel::setData(const QModelIndex&, const QVariant&, int){
QMessageBox::information(nullptr, "Set data", "Just return true");

return true;
}

void TestModel::insertTestItem(TestClass* testClass){
if(nullptr==testClass){
QMessageBox::critical(nullptr, "Critical", "Not inserting nullptr");
return;
}

TestModelItem* child = new TestModelItem(testClass, this->root->size(), this->root);
this->beginInsertRows(this->createIndex(0, 0, reinterpret_cast<void*>(this->root)),
this->root->size(), this->root->size());
this->root->appendChild(child);
this->endInsertRows();
}

RootItem* TestModel::getRoot(){
return this->root;
}

testmodelitem.hpp:

class TestModelItemBase{
public:
enum class ITEM_TYPE{
ISNULL, INVALID, ROOT, TEST_ITEM
};

TestModelItemBase();
TestModelItemBase(ITEM_TYPE, int, TestModelItemBase*);
virtual ~TestModelItemBase();

ITEM_TYPE getItemType() const;
int getIndex() const;
TestModelItemBase* getParent();

virtual int size();

private:
ITEM_TYPE itemType;
int index;
TestModelItemBase* parent;
};

class RootItem;
class TestModelItem;
class TestClass;

class RootItem:public TestModelItemBase{
public:
RootItem();
~RootItem();

QList<TestModelItem*>& getList();

void appendChild(TestModelItem*);

virtual int size();
private:
QList<TestModelItem*> list;
};

class TestModelItem:public TestModelItemBase{
public:
TestModelItem(TestClass*, int, RootItem*);
~TestModelItem();

TestClass* getData();

virtual int size();
private:
TestClass* data;
};

class TestClass{

};

testmodelitem.cpp:

TestModelItemBase::TestModelItemBase()
:itemType(TestModelItemBase::ITEM_TYPE::INVALID), index(-1), parent(nullptr){

}

TestModelItemBase::TestModelItemBase(TestModelItemBase::ITEM_TYPE type, int i, TestModelItemBase* p)
:itemType(type), index(i), parent(p){

}

TestModelItemBase::~TestModelItemBase(){

}

TestModelItemBase::ITEM_TYPE TestModelItemBase::getItemType() const{
if(nullptr==this){
return TestModelItemBase::ITEM_TYPE::ISNULL;
}
return this->itemType;
}

int TestModelItemBase::getIndex() const{
if(nullptr==this){
return -2;
}
return this->index;
}

TestModelItemBase* TestModelItemBase::getParent(){
if(nullptr==this){
return nullptr;
}
return this->parent;
}

int TestModelItemBase::size(){
return -1;
}

RootItem::RootItem()
:TestModelItemBase(TestModelItemBase::ITEM_TYPE::ROOT,
0, nullptr){

}

RootItem::~RootItem(){

}

QList<TestModelItem*>& RootItem::getList(){
return this->list;
}

void RootItem::appendChild(TestModelItem* child){
this->list.append(child);
}

int RootItem::size(){
return this->list.size();
}

TestModelItem::TestModelItem(TestClass* d, int index, RootItem* parent)
:data(d),
TestModelItemBase(TestModelItemBase::ITEM_TYPE::TEST_ITEM,
index, parent){

}

TestModelItem::~TestModelItem(){

}

TestClass* TestModelItem::getData(){
return this->data;
}

int TestModelItem::size(){
return 0;
}

testmodelitemdelegate.hpp:

class TestModelItemDelegate:public QStyledItemDelegate{
Q_OBJECT

public:
TestModelItemDelegate();
~TestModelItemDelegate();

QWidget* createEditor(QWidget*, QStyleOptionViewItem const&, QModelIndex const&) const override;
void setEditorData(QWidget*, QModelIndex const&) const override;
void setModelData(QWidget*, QAbstractItemModel*, QModelIndex const&);
void updateEditorGeometry(QWidget* editor, QStyleOptionViewItem const& option,
QModelIndex const& index) const;

private:
QWidget* createTestEditor(QWidget*) const;
};

testmodelitemdelegate.cpp:

TestModelItemDelegate::TestModelItemDelegate(){
;
}

TestModelItemDelegate::~TestModelItemDelegate(){
;
}

QWidget* TestModelItemDelegate::createEditor(QWidget* parent,
QStyleOptionViewItem const& option,
QModelIndex const& index) const{
QMessageBox::information(nullptr, "Create editor", "Creating editor...");

TestModelItemBase* item = reinterpret_cast<TestModelItemBase*>(index.internalPointer());

switch(item->getItemType()){
case TestModelItemBase::ITEM_TYPE::TEST_ITEM:
return TestModelItemDelegate::createTestEditor(parent);
default:
break;
}
}

void TestModelItemDelegate::setEditorData(QWidget*, QModelIndex const&) const{
QMessageBox::information(nullptr, "Set editor data", "Doing nothing");
}

void TestModelItemDelegate::setModelData(QWidget*, QAbstractItemModel*,
QModelIndex const&){
QMessageBox::information(nullptr, "Set model data", "Doing nothing");
}

void TestModelItemDelegate::updateEditorGeometry(QWidget* editor, QStyleOptionViewItem const& option,
QModelIndex const& index) const{
QMessageBox::information(nullptr, "Update editor geometry", "Doing nothing");
}

QWidget* TestModelItemDelegate::createTestEditor(QWidget* parent) const{
QMessageBox::information(nullptr, "Create test editor", "Editor for testing");

QWidget* editor = new QWidget(parent);

QHBoxLayout* layout = new QHBoxLayout(editor);

layout->addWidget(new QPushButton(editor));
layout->addWidget(new QLineEdit(editor));

editor->setLayout(layout);

return editor;
}

Я усек все включения.
Я очень ценю любую помощь.
Заранее спасибо!

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]