QItemDelegate does not save data
-
I have this delegate but sadly when i press enter on the delegate with the user role CanHaveChildren = false it doesn't save the data for my lineEdit. The picture and data for the checkbox however is saved. Also all data for the item with the user role CanHaveChildren to everything is saved. I don't get why i press enter on both, both look the same to me.
QWidget *ViewLayerItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { if(index.data(ViewLayerStandartItemModel::CanHaveChildrenRole).toBool() == false){ qDebug() << "NormalItem Editor created"; LineEditCheckBoxWidget *editor = new LineEditCheckBoxWidget(parent); // Ein Timer um direkt die Editierung des LineEdit zu ermöglichen //QTimer::singleShot(0, editor->lineEdit, SLOT(setFocus(Qt::MouseFocusReason))); return editor; }else if(index.data(ViewLayerStandartItemModel::CanHaveChildrenRole).toBool() == true){ qDebug() << "GroupItem Editor created"; GroupItemWidget *editor = new GroupItemWidget(parent); // Ein Timer um direkt die Editierung des LineEdit zu ermöglichen QTimer::singleShot(0, editor->lineEdit2, SLOT(setFocus(Qt::MouseFocusReason))); return editor; } //return nullptr; } void ViewLayerItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { if(index.data(ViewLayerStandartItemModel::CanHaveChildrenRole).toBool() == false){ LineEditCheckBoxWidget *widget = static_cast<LineEditCheckBoxWidget *>(editor); // Setzen Sie die Werte der SpinBox und CheckBox basierend auf den Modellwerten QString lineEditvalue = index.model()->data(index, Qt::EditRole).toString(); bool checkBoxValue = index.model()->data(index, Qt::CheckStateRole).toBool(); QPixmap IconPixmapValue = index.model()->data(index, Qt::DisplayRole).value<QPixmap>(); widget->lineEdit->setText(lineEditvalue); widget->checkBox->setChecked(checkBoxValue); widget->lineEdit->setStyleSheet("background: white"); widget->iconLabel->setAttribute(Qt::WA_TranslucentBackground); widget->iconLabel->setPixmap(IconPixmapValue); qDebug() << "lineValue1: " << lineEditvalue << widget->lineEdit->text(); // Setzen Sie den bearbeiteten Index const_cast<ViewLayerItemDelegate*>(this)->setCurrentlyEditedIndex(index); }else if(index.data(ViewLayerStandartItemModel::CanHaveChildrenRole).toBool() == true){ GroupItemWidget *widget = static_cast<GroupItemWidget *>(editor); // Setzen Sie die Werte der SpinBox und CheckBox basierend auf den Modellwerten QString lineEditvalue = index.model()->data(index, Qt::EditRole).toString(); bool checkBoxValue = index.model()->data(index, Qt::CheckStateRole).toBool(); widget->lineEdit2->setText(lineEditvalue); widget->checkBox2->setChecked(checkBoxValue); widget->lineEdit2->setStyleSheet("background: white"); widget->iconLabel2->setAttribute(Qt::WA_TranslucentBackground); // Setzen Sie den bearbeiteten Index const_cast<ViewLayerItemDelegate*>(this)->setCurrentlyEditedIndex(index); qDebug() << "lineValue2: " << lineEditvalue << widget->lineEdit2->text(); } } void ViewLayerItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { if(index.data(ViewLayerStandartItemModel::CanHaveChildrenRole).toBool() == false){ LineEditCheckBoxWidget *widget = static_cast<LineEditCheckBoxWidget *>(editor); // Speichern Sie die Werte der SpinBox und CheckBox im Modell QString lineEditvalue = widget->lineEdit->text(); bool checkBoxValue = widget->checkBox->isChecked(); QPixmap IconPixmapValue = widget->iconLabel->pixmap(); model->setData(index, lineEditvalue, Qt::EditRole); model->setData(index, checkBoxValue ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole); model->setData(index, IconPixmapValue, Qt::DisplayRole); qDebug() << "model dataset: "<< lineEditvalue; // Setzen Sie den bearbeiteten Index zurück const_cast<ViewLayerItemDelegate*>(this)->setCurrentlyEditedIndex(QModelIndex()); }else if(index.data(ViewLayerStandartItemModel::CanHaveChildrenRole).toBool() == true){ GroupItemWidget *widget = static_cast<GroupItemWidget *>(editor); // Speichern Sie die Werte der SpinBox und CheckBox im Modell QString lineEditvalue = widget->lineEdit2->text(); bool checkBoxValue = widget->checkBox2->isChecked(); model->setData(index, lineEditvalue, Qt::EditRole); model->setData(index, checkBoxValue ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole); qDebug() << "Model data set"; // Setzen Sie den bearbeiteten Index zurück const_cast<ViewLayerItemDelegate*>(this)->setCurrentlyEditedIndex(QModelIndex()); } }
ViewLayerList::ViewLayerList(CustomGraphicsScene *scene, QWidget *parent) : QTreeView{parent}, scene_durchgereicht(scene) { connect(scene_durchgereicht, &CustomGraphicsScene::SendNewItemWasAddedtoScene, this, &ViewLayerList::ReceiveNewItemWasAddedtoScene); setStyle(new ViewLayerDropIndicatorStyle(style())); // Ändern Sie den Abstand zwischen den Items und der vertikalen Scrollbar setViewportMargins(0, 0, 50, 0); // Passen Sie den rechten Rand (20) an Ihre Anforderungen an //Versteckt die sinnlose Kopfzeile setHeaderHidden(true); setRootIsDecorated(true); setMouseTracking(true); mydelegate = new ViewLayerItemDelegate(this); model = new ViewLayerStandartItemModel(3,1,this); for(int row = 0; row < 3; ++row) { for(int col = 0; col < 1; ++col) { QModelIndex index = model->index(row, col, QModelIndex()); model->setData(index, ""); model->setData(index, false, ViewLayerStandartItemModel::CanHaveChildrenRole); // Dieses Element kann keine Kinder haben // Angenommen, Sie haben einen gültigen QModelIndex "index" QPixmap ItemIconPixmap("C:/Users/Musik/Desktop/KSP Graphic Editor Sketch.png"); // Ersetzen Sie "path/to/your/pixmap.png" durch den Pfad zu Ihrer Bilddatei QPixmap SCItemIconPixmap = ItemIconPixmap.scaled(32,32, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); int xOffset = (SCItemIconPixmap.width() - 32) / 2; int yOffset = (SCItemIconPixmap.height() - 32) / 2; QPixmap finalPixmap = SCItemIconPixmap.copy(xOffset, yOffset, 32, 32); model->setData(index, finalPixmap, Qt::DisplayRole); if(row >= 1 && row <= 2 && col <= 1) { model->setData(index, true, ViewLayerStandartItemModel::CanHaveChildrenRole); // Dieses Element kann keine Kinder haben } //qDebug() << "Row: " << row << "ChildRole: " << model->data(index, ViewLayerStandartItemModel::CanHaveChildrenRole).toBool() << "Invisible: " << model->data(index, ViewLayerStandartItemModel::IsInvisibleRole).toBool(); } }
-
Hi,
Did you check what you get from the editor ?
Beside that, rather than having to extract stuff from widgets contained in your editors, you should rather add methods to your editors that return the values of interest. That way it will make your delegate code simpler and not dependent on whatever you use to implement your editors.
-
@SGaist i get:
lineValue1: "" ""
lineValue1: "test" "test"
lineValue1: "" ""
model dataset: "test"and for the working one i get:
lineValue2: "" ""
lineValue2: "test2" "test2"
lineValue2: "test2" "test2"
Model data setSo somehow it seems as if the value gets overwriten, but i could not figure out why and how. I really see no real difference in the code, besides the different user role used as boolean which theoretically shouldn't have any affect on this behaviour
Here are the two different widgets used in the delegate depending on the user role:
// Definieren Sie das benutzerdefinierte Widget class LineEditCheckBoxWidget : public QWidget { Q_OBJECT public: QLineEdit *lineEdit; QCheckBox *checkBox; QLabel *iconLabel; LineEditCheckBoxWidget(QWidget *parent = nullptr) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(this); layout->setContentsMargins(10,0,20,0); layout->setSpacing(0); lineEdit = new QLineEdit(this); checkBox = new QCheckBox(this); iconLabel = new QLabel(this); // Laden Sie das Icon und setzen Sie es auf das QLabel QPixmap iconPixmap("://resource/quick.png"); // Ersetzen Sie dies durch den Pfad zu Ihrer Icon-Datei QPixmap scaledPixmap = iconPixmap.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation); iconLabel->setPixmap(scaledPixmap); this->setStyleSheet("background-color: transparent"); layout->addWidget(iconLabel); layout->addSpacing(10); layout->addWidget(lineEdit); layout->addSpacing(10); layout->addWidget(checkBox); // Zugriff auf das QLineEdit-Widget und setzen Sie den Hintergrund transparent lineEdit->setStyleSheet("background-color: transparent;"); lineEdit->setFrame(false); lineEdit->setPlaceholderText("<Empty>"); checkBox->setStyleSheet("background-color: transparent"); //QPoint globalPos = checkBox->mapToGlobal(QPoint(0, 0)); //qDebug() << "Global position of checkbox on init: " << globalPos; } signals: }; // Definieren Sie das benutzerdefinierte Widget class GroupItemWidget : public QWidget { Q_OBJECT public: QLineEdit *lineEdit2; QCheckBox *checkBox2; QLabel *iconLabel2; GroupItemWidget(QWidget *parent = nullptr) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(this); layout->setContentsMargins(10,0,20,0); layout->setSpacing(0); lineEdit2 = new QLineEdit(this); checkBox2 = new QCheckBox(this); iconLabel2 = new QLabel(this); // Laden Sie das Icon und setzen Sie es auf das QLabel QPixmap iconPixmap(""); // Ersetzen Sie dies durch den Pfad zu Ihrer Icon-Datei QPixmap scaledPixmap = iconPixmap.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation); iconLabel2->setPixmap(scaledPixmap); this->setStyleSheet("background-color: transparent"); layout->addWidget(iconLabel2); layout->addSpacing(10); layout->addWidget(lineEdit2); layout->addSpacing(10); layout->addWidget(checkBox2); // Zugriff auf das QLineEdit-Widget und setzen Sie den Hintergrund transparent lineEdit2->setStyleSheet("background-color: transparent;"); lineEdit2->setFrame(false); lineEdit2->setPlaceholderText("<Empty>"); checkBox2->setStyleSheet("background-color: transparent"); } signals: };
-
Which kind of model are you using ?
-
@SGaist I subclassed QStandardItemModel. The wierd thing is it worked a day before and when i started it up the day after without making changes (i compared with my saved versions) i suddenly didn't work anymore.
Here is everything i reimplemented in the model:
#include "ViewLayerStandartItemModel.h" #include "ViewLayerList.h" #include <QMimeData> #include <QDataStream> ViewLayerStandartItemModel::ViewLayerStandartItemModel(int rows, int columns, QObject *parent) : QStandardItemModel(rows, columns, parent) { } Qt::ItemFlags ViewLayerStandartItemModel::flags(const QModelIndex &index) const { Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index); // Überprüfen Sie, ob der Index zu einem Ihrer speziellen Delegaten gehört if (!data(index, CanHaveChildrenRole).toBool()) { return (defaultFlags & ~Qt::ItemIsDropEnabled) | Qt::ItemIsDragEnabled; // Entfernen Sie das ItemIsDropEnabled-Flag und fügen Sie das ItemIsDragEnabled-Flag hinzu } return defaultFlags | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; // Fügen Sie das ItemIsDragEnabled und ItemIsDropEnabled Flag hinzu } Qt::DropActions ViewLayerStandartItemModel::supportedDragActions() const { return Qt::MoveAction; } Qt::DropActions ViewLayerStandartItemModel::supportedDropActions() const { return Qt::MoveAction; } t
-
@SGaist I found the line of code the prevents the saving, as soon as i comment this line out my image isn't shown anymore but my text is saved.
model->setData(index, QVariant::fromValue(IconPixmapValue), Qt::DisplayRole);
Thank you @SGaist. Setting to Qt::DecorationRole works, really saved my day. But still what a bummer, just a little confusion leading to this much of an problem. XD
Really appreciate you helping me out that quick. <3 -
I think what you want is
Qt::DecorationRole
. See here for more information. -