views:

83

answers:

2

Hi there!

I have a QTableView defines in UI file. Here is the figure:

alt text

I'd like to make month change (where the red array points) with QComboBox widget, dealing with delegates, but for me, for my custom delegate and model it's a too complex problem, and I can't figure out what is wrong?!

Problem: on my opinion, QAbstractTableModel can't work with QItemDelegate, because I'm unable to combine my custom simple ComboBoxDelegate widget with QTableView. Wtf?

Here is what I have:

My custom delegate header/source data:

class ComboBoxDelegate : public QItemDelegate
{
    Q_OBJECT

public:
    ComboBoxDelegate(QObject *parent = 0);

    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option,
        const QModelIndex &index) const;

    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                        const QModelIndex &index) const;

    void updateEditorGeometry(QWidget *editor,
        const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

ComboBoxDelegate::ComboBoxDelegate(QObject *parent)
    : QItemDelegate(parent)
{}

QWidget *ComboBoxDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &/* option */,
    const QModelIndex &index) const
{
    QComboBox* editor = new QComboBox(parent);
    editor->addItem(index.data(Qt::DisplayRole).toString());
    return editor;
}

void ComboBoxDelegate::setEditorData(QWidget *editor,
    const QModelIndex &index) const
{
    QString value = index.model()->data(index, Qt::EditRole).toString();
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    comboBox->setCurrentIndex(comboBox->findText(value));
}

void ComboBoxDelegate::setModelData(QWidget *editor,
    QAbstractItemModel *model,
    const QModelIndex &index) const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    QString value = comboBox->currentText();
    model->setData(index, value, Qt::EditRole);
}

Model data:

class PortfolioModel : public QAbstractTableModel
{
    Q_OBJECT;

    // types
    enum Position
    {
          ePosValue = 0
        , eColumnCount
    };

    enum Constants
    {
          eLocalCcy = 0
            , eCurrentTime
        , eCurrentMonthName
        , eRowCount
    };

    // data
    static QFont    font_;
    static QBrush   foreground_;
    static QBrush   background_;

    // methods
    QVariant        _valueName(int index) const;
    QVariant        _valueNameTooltip(int index) const;
    QVariant        _data(int index, int col, bool tooltip) const;

public:
    PortfolioModel(QObject* parent = 0);
    ~PortfolioModel();

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

    QVariant        data(const QModelIndex& index, int role = Qt::DisplayRole) const;
    QVariant        headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;

signals:
    void            resizeToContents(void);

public slots:
    void            refreshData(void);
};

QFont PortfolioModel::font_ = QFont("Tahoma", 8, QFont::Normal);
QBrush PortfolioModel::foreground_ = QBrush(QColor("#000000")); // Black
QBrush PortfolioModel::background_ = QBrush(QColor("#C3FDB8")); // Dark Sea Green1

PortfolioModel::PortfolioModel(QObject* parent)
    : QAbstractTableModel(parent)
{}

PortfolioModel::~PortfolioModel()
{}

void PortfolioModel::refreshData(void)
{
    emit dataChanged(QModelIndex(), QModelIndex());
    emit resizeToContents();
}

int PortfolioModel::rowCount(const QModelIndex& parent/* = QModelIndex()*/) const
{
    return eRowCount;
}

int PortfolioModel::columnCount(const QModelIndex& parent/* = QModelIndex()*/) const
{
    return eColumnCount;
}

QVariant PortfolioModel::data(const QModelIndex& index, int role/* = Qt::DisplayRole*/) const
{
    if (!index.isValid())
        return QVariant();

    switch (role)
    {
        case Qt::DisplayRole:
            return _data(index.row(), index.column(), false);
        case Qt::FontRole:
            break;
        case Qt::BackgroundRole:
            return background_;
        case Qt::ForegroundRole:
            return foreground_;
        case Qt::TextAlignmentRole:
        case Qt::DecorationRole:
        case Qt::EditRole:
            break;
        case Qt::ToolTipRole:
            return _data(index.row(), index.column(), true);
        case Qt::StatusTipRole:
        case Qt::WhatsThisRole:
        case Qt::SizeHintRole:
            break;
    }
    return QVariant();
}

QVariant PortfolioModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    switch (orientation)
    {
    case Qt::Horizontal:
        switch (role)
        {
        case Qt::DisplayRole:
            if (section == ePosValue)
            {
                return QVariant("Value");
            }
        case Qt::ToolTipRole:
            if (section == ePosValue)
            {
                return QVariant("Fund values");
            }
            break;
        }
    case Qt::Vertical:
        switch (role)
        {
        case Qt::DisplayRole:
            return _valueName(section);
        case Qt::ToolTipRole:
            return _valueNameTooltip(section);
        }
        break;
    }

    return QVariant();
}

QVariant PortfolioModel::_valueNameTooltip(int index) const
{
    switch (index)
    {
    case eLocalCcy:
        return QObject::tr("Local currency");
    case eCurrentTime:
        return QObject::tr("Current time");
    case eCurrentMonthName:
        return QObject::tr("Current Month");
    }
    return QVariant();
}

QVariant PortfolioModel::_valueName(int index) const
{
    switch (index)
    {
    case eLocalCcy:
        return QObject::tr("Local Currency");
    case eCurrentTime:
        return QObject::tr("Current Time");
    case eCurrentMonthName:
        return QObject::tr("Month");
    }
    return QVariant();
}

QVariant PortfolioModel::_data(int index, int col, bool tooltip) const
{
    switch (index)
    {
    case eLocalCcy:
        if (col == ePosValue)
        {
            return QString(Nav::bk()->currentFund().currency(Nav::bk()->currentFund().localCcy()).code());
        }
        break;
    case eCurrentTime:
        if (col == ePosValue)
        {
            return Nav::bk()->currentFund().currentTime();
        }
        break;
    case eCurrentMonthName:
        if (col == ePosValue)
        {
            return QDate::longMonthName(Nav::bk()->currentFund().currentTime().date().month());
        }
        break;
    }
    return QVariant();
}

And after that I made init delegate like that:

ComboBoxDelegate *delegate_ = new ComboBoxDelegate(this);
this->ui.tableView->setItemDelegate(delegate_);

PS: sorry for the long output, but I think it's will be better If all sources will be presented here.

Thanks!


  1. Added:
A: 

in this blog http://qt-articles.blogspot.com/2010/07/how-to-customize-listview-in-qt-using.html one delegate example is given.. please check your delegate with the sample example of the delegate present in blog. hope you might get some clue.

Shadow
Hm, as you can see from my question I used another method to combine `QTableView` class with `QComboBox` widgets, but if no other answers will be done for my post in future, I'll try paint() method (but I think this is not the best one)... Thanks
mosg
@Shadow I have checked code from you URL and, truly said, that is not what I really need. What I need, is the working delegate, but not the picture/figure on the `QTableView`...Any other ideas? Some one? :)
mosg
working delegate means?..the delegate method which you have posted is not working you meant?(i have not tried yet in my editor)..another thing i wanted to ask you is, why don't you write a delegate which inherit from QStyledItemDelegate..?if so tell me.. i'll check and tell if i can find some solution for ur problem :)..
Shadow
@Shadow Yes, my top method does not work. In `QTableView` I saw nothing (no text or widgets), and when I setup few breaks on the `createEditor` or `setModelData` functions, they are didn't executed at all! I replaces `QItemDelegate` with `QStyledItemDelegate`, but that didn't get the trick :( Oh, and by the way: adding to the top of the comment `@{user_name}` text bring that {user_name} will get email... It's much quicker way.
mosg
+1  A: 

From the overview of QAbstractItemModel (see the Subclassing heading):

To enable editing in your model, you must also implement setData(), and reimplement flags() to ensure that ItemIsEditable is returned.

The same information is given in the overview of QAbstractTableModel. Your PortfolioModel class does not reimplement either of these functions. In order to use the delegate's editor, you need to use do so.

Alternately, you may only want it to appear as if a combobox is there (not actually allow editing). If that is the case, you will probably need to do some drawing hacks yourself to make it appear that way... or mark it as editable but disable the widget, or something like that.

Caleb Huitt - cjhuitt
@Caleb Thanks, Caleb, I think you are right, that kind of answer I'm looking for. I checked this out next week, and reply, is it success or not!
mosg
@Caleb All I need it to reimplement `flags()` method! Thanks again.
mosg