Paint in QStyledItemDelegate - other options?



  • I'm using a custom QStyledItemDelegate that is used to display item in a QListView, every item is a custom object that is represented by a custom Widget in the listView

    When i'm editing an item in the list, the createEditor() return the widget so that the user can edit the object fields. I'm having the problem that both createEditor() and paint() are rendering the widget at the same time. The paint method has no way of knowing when the item is being edited.

    What I am looking to achieve is something similar to this :
    https://www.dropbox.com/s/94sdayh0q5y4vfz/workoutList.png

    What I have now:
    https://www.youtube.com/watch?v=-XLK1UW6uM8&hd=1
    You can see the editing bug at 0:20 in the video, widget is displayed 2 times..)

    What I need to have and QDelegate doesn't provide :
    1- Different Size of the item when the item is being edited versus painted
    2- Custom edit button on the QListView item (not double clicked or stuff like that, I need to make my own trigger)
    3- Drag indicator on every list Item, helping user see that the item can be dragged

    What I don't understand from QDelegate

    • What trigger paint function in the delagate, I am seeing lot of paint call all the time, even when my model data didn't change.
    • From where createEditor() is triggered

    If anyone can tell me if there is another solution out there, not using QDelegate because i'm tired of this class. Thanks a lot.
    I'll post my current delegate code in the next message.



  • My delegate code:

    @#include "listintervaldelegate.h"
    #include <QDebug>
    #include "interval.h"
    #include "util.h"
    #include "intervalwidget.h"
    #include "edittargetpowerwidget.h"

    ListIntervalDelegate::ListIntervalDelegate(QObject parent) : QStyledItemDelegate(parent)
    {
    ptrParent = (QWidget
    )parent;
    widgetInterval = new IntervalWidget();
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    QWidget *ListIntervalDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const {

    IntervalWidget *widgetInterval = new IntervalWidget(parent);
    return widgetInterval;
    

    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ListIntervalDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {

    Interval interval = qvariant_cast<Interval>(index.model()->data(index, Qt::DisplayRole));
    IntervalWidget *widget = static_cast<IntervalWidget*>(editor);
    
    
    int stepType = interval.getType();
    QTime duration = interval.getDurationQTime();
    QString displayMsg = interval.getDisplayMessage();
    ///POWER
    int targetStepPower = interval.getPowerStepType();
    double startFTP = interval.getFTP_start() * 100;
    double endFTP = interval.getFTP_end() * 100;
    int range = interval.getFTP_range();
    
    
    widget->intervalComboBoxType->setCurrentIndex(stepType);
    widget->timeEdit->setTime(duration);
    widget->msgLineEdit->setText(displayMsg);
    ///POWER
    widget->stepTypeComboBoxPower->setCurrentIndex(targetStepPower);
    widget->targetStartValue->setValue(startFTP);
    widget->targetEndValue->setValue(endFTP);
    widget->targetRangeValue->setValue(range);
    

    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ListIntervalDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {

    IntervalWidget *widget = static_cast<IntervalWidget*>(editor);
    
    int stepTypeInt = widget->intervalComboBoxType->currentIndex();
    Interval::Type stepType = static_cast<Interval::Type>( stepTypeInt );
    QTime duration = widget->timeEdit->time();
    QString displayMsg = widget->msgLineEdit->text();
    ///POWER
    int targetStepPower = widget->stepTypeComboBoxPower->currentIndex();
    Interval::StepType stepTypePower = static_cast<Interval::StepType>( targetStepPower );
    double startFTP = widget->targetStartValue->value() / 100.0;
    double endFTP = widget->targetEndValue->value() / 100.0;
    int range = widget->targetRangeValue->value();
    
    
    
    Interval intervalTmp(duration, stepType, displayMsg,
                         stepTypePower, startFTP, endFTP, range,
                         stepTypePower, startFTP, endFTP, range,
                         stepTypePower, startFTP, endFTP, range);
    
    
    
    QVariant v = QVariant::fromValue(intervalTmp);
    model->setData(index, v, Qt::EditRole);
    

    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ListIntervalDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {

    painter->save();
    
    if(!index.isValid())
        return;
    
    QStyleOptionViewItemV4 opt = option;
    QStyledItemDelegate::initStyleOption(&opt, index);
    
    bool paint = true;
    if (option.state & QStyle::State_Selected) {
        painter->fillRect(option.rect, option.palette.highlight());
    }
    
    if (option.state & QStyle::State_Editing) {
        return;
        // dont paint when widget is already in shown in createEditor()
        // this state never get activated...
    }
    
    
    if (paint) {
    
        Interval interval = qvariant_cast<Interval>(index.model()->data(index, Qt::DisplayRole));
        int stepType = interval.getType();
        QTime duration = interval.getDurationQTime();
        QString displayMsg = interval.getDisplayMessage();
        ///POWER
        int targetStepPower = interval.getPowerStepType();
        double startFTP = interval.getFTP_start() * 100;
        double endFTP = interval.getFTP_end() * 100;
        int range = interval.getFTP_range();
    
        widgetInterval->intervalComboBoxType->setCurrentIndex(stepType);
        widgetInterval->timeEdit->setTime(duration);
        widgetInterval->msgLineEdit->setText(displayMsg);
        ///POWER
        widgetInterval->stepTypeComboBoxPower->setCurrentIndex(targetStepPower);
        widgetInterval->targetStartValue->setValue(startFTP);
        widgetInterval->targetEndValue->setValue(endFTP);
        widgetInterval->targetRangeValue->setValue(range);
    
        widgetInterval->resize( option.rect.size() );
        painter->translate(option.rect.topLeft());
        widgetInterval->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );
    }
    painter->restore();
    

    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ListIntervalDelegate::updateEditorGeometry(QWidget editor, const QStyleOptionViewItem &option, const QModelIndex &/ index */) const {

    editor->setGeometry(option.rect);
    

    }

    QSize ListIntervalDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const {

    return QSize(500, 160); //enter your values here
    

    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.