PDA

View Full Version : How to set lower precision only for "view"



lain
25th March 2012, 07:15
I am trying to implement a table widget which displays (real) numbers.
I want to display data in the table with lower precision (say, number
of digits after the decimal point is 2) without reducing the actual presicion of the referenced data.
I thought that I can store the rounded and not-rounded data separately as
DisplayRole and EditRole, respectively, but it turns out not true
as far as looking at the sources of QStandardItemModel::setData() and
QTableWidgetItem::setData().


void QStandardItem::setData(const QVariant &value, int role)
{
Q_D(QStandardItem);
role = (role == Qt::EditRole) ? Qt::DisplayRole : role;
.......
}

Should I prepare another instance of StandardItemModel or my own container to store unrounded data?

wysota
25th March 2012, 10:01
You could just use a custom delegate that would reduce precision for Qt::DisplayRole.

lain
25th March 2012, 11:45
Hi, thank you very much for reply.

I am using a custom delegate which uses QLineEdit as an editor.
I set the rounded data to the editor as below, but it does not seem to work.
The data are still shown as they are.
I may be misunderstanding the role of delegate...


LineEditDelegate::LineEditDelegate(QWidget *parent)
: QStyledItemDelegate(parent), validator(new QDoubleValidator(this))
{
}

QWidget *LineEditDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QLineEdit *editor = new QLineEdit(parent);
editor->setValidator(validator);
return editor;
}

void LineEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QLineEdit *e = qobject_cast<QLineEdit *>(editor);
e->setText(QString::number(index.data(Qt::EditRole).t oDouble(), 'f', 2));
}

void LineEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QLineEdit *e = qobject_cast<QLineEdit *>(editor);
model->setData(index, e->text(), Qt::EditRole);
}


You could just use a custom delegate that would reduce precision for Qt:isplayRole.
But as far as DisplayRole and EditRole are not actually distinguished,
won't it overwrite the original with the rounded data?

wysota
25th March 2012, 17:32
I don't see any benefits of editing an approximated value. I could see the benefit of displaying an approximated value in regular display and editing a precise value in the editor.

d_stranz
25th March 2012, 17:34
You could derive a class from QStandardItemModel and override setData() and data() so that the two roles are distinguished. Unless you want more customization, the only roles you need to override are EditRole and DisplayRole - you can simply return QVariant() for everything else and let the base class handle it. You might even be able to get away with simply overriding the data() method. Since you know that setData() always puts the value into the DisplayRole, you use setData() with full precision but return the reduced precision in the data( Qt::DisplayRole )

ChrisW67
26th March 2012, 00:13
Displaying a certain number of decimal places for doubles in the table widget should be as simple as using a delegate like:


class Delegate: public QStyledItemDelegate {
Q_OBJECT
public:
Delegate(QObject *p = 0): QStyledItemDelegate(p) { }

QString displayText(const QVariant &value, const QLocale &locale) const
{
if (value.type() == QVariant::Double) {
return locale.toString(value.toDouble(), 'f', 2);
}
else
return QStyledItemDelegate::displayText(value, locale);
}
};

This is quite distinct from anything to do with what is displayed in an editor for that value.

lain
26th March 2012, 01:37
Displaying a certain number of decimal places for doubles in the table widget should be as simple as using a delegate like:
Hi, thank you for reply.

This is exactly what I wanted!
I've never noticed the presence of virtual function: QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale &locale) const.

But it is a pity that I cannot access the model index from this function.
I want to set different precision for each column...

ChrisW67
26th March 2012, 02:06
Apply a different delegate to each column QAbstractItemView::setItemDelegateForColumn(). If all that varies is the number of decimal places then you can use the same class with a parameter (passed in at construction of the delegate).

lain
26th March 2012, 02:44
Apply a different delegate to each column QAbstractItemView::setItemDelegateForColumn(). If all that varies is the number of decimal places then you can use the same class with a parameter (passed in at construction of the delegate).

It did the trick.
Thank you very much for the prompt and helpful reply!!