Tom
Tom

Reputation: 181

How to visualize model data in different ways in QTableView?

I have a model containing in one column floats (ex: 22.7). Now, I want that in QTableView, it will be visualized together with the unit (MB): 22.7 MB. The reason I am doing so is because I want that sorting is based on floats, but the visualization is as I said with units.

I created a Model, a Filter and a View. But it does not work. Here is a piece of my code:

QStandardItemModel* model = new QStandardItemModel(this);
QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(0);
filterModel->setSourceModel(model);

QStandardItem* vSItem6 = new QStandardItem();
vSItem6->setData(22.7, Qt::DisplayRole); 
model->setItem(1, 7, vSItem6);
QModelIndex index = model->index(1, 7, QModelIndex());
QString itext = model->data(index, Qt::DisplayRole).toString(); 
filterModel->setData(index, itext + " MB", Qt::DisplayRole);


mUi.tableView->setModel(filterModel);
mUi.tableView->setSortingEnabled(true);
mUi.tableView->show();

Everything seems to be fine, but in QTableView, only the float number is visualized (without the unit MB). Can anybody please help me? Thanks

Upvotes: 1

Views: 2471

Answers (4)

momesana
momesana

Reputation: 41

If you just want to take the value of the model and modify it's string representation you can do so easily by inheriting from QStyledItemDelegate and just overriding a single method namely displayText(), which returns a QString. I just did that to have the values (representing the amount of memory consumed by a process) displayed in the most appropriate unit (byte, kbyte, megabyte and so on). So it's a usecase that is more or less similar to the problem described above and it works like a charme. You can see the code below (but ignore the application specific parts).

Header file:

#pragma once 

#include <QStyledItemDelegate>

class UnitAwareItemDelegate : public QStyledItemDelegate {
    Q_OBJECT
public:
    explicit UnitAwareItemDelegate(QObject* parent = 0);
    virtual QString displayText(const QVariant & value, const QLocale & locale) const;
};

Implementation file:

#include "UnitAwareItemDelegate.hpp"
#include "UnitUtils.hpp"

#include <QPainter>
#include <QStyleOptionViewItem>
#include <QModelIndex>

UnitAwareItemDelegate::UnitAwareItemDelegate(QObject* parent): QStyledItemDelegate(parent)
{
}

QString UnitAwareItemDelegate::displayText(const QVariant& value, const QLocale& locale) const
{
    if (value == 0)
    return QString();

    // value supplied by libproc is in kb so we mul by 1024 to get the byte value
    uint64_t oldValue = value.toULongLong() * 1024;
    const UnitUtils::ValueUnit unit = UnitUtils::findSuitableUnit(oldValue);
    const uint64_t newValue = oldValue / UnitUtils::value(unit);

    return QString("%1 %2")
    .arg(QString::number(newValue))
    .arg(QString(UnitUtils::name(unit).at(0)).toUpper());
}

Upvotes: 1

ivanc
ivanc

Reputation: 11

I'm a newbie in Qt development, but can't you derive from class QAbstactTableModel, and implement the data method so that it returns the float value plus "MB" (in a QString object), when role is DisplayRole?

Upvotes: 1

hmuelner
hmuelner

Reputation: 8221

Have a look at setItemDelegate or setItemDelegateForColumn. You can derive your delegate class from QStyledItemDelegate, and in the overridden paint method you can paint your numbers including the units.

Upvotes: 1

Live
Live

Reputation: 2001

I know your question was about QTableView, but it might be easier if it is the only thing you want to display (I don't know your objectives) to use a QTableWidget with a QDoubleSpinBox since it has a method that allows you to set a suffix to the value that is displayed.

In your case, it would be:

QDoubleSpinBox* spin = new QDoubleSpinBox();
spin->setSuffix("MB");

Note that the range is set by default from 0.0 to 99.99 so if you want to set other values you should change the range before.

Hope this helps.

Upvotes: 0

Related Questions