How do I know the values on Qt property browser changed? - c++

I'm using a Qt property browser widget. I'm creating all the values of the property grid automatically using the moc but I didn't find how to make the values entered in the property grid be set automatically in my class instance? is there any sginal where I can know that?
I creating the property grid like this:
QWidget *w = new QWidget();
Foo *o = new Foo();
QtBoolPropertyManager *boolManager = new QtBoolPropertyManager(w);
QtIntPropertyManager *intManager = new QtIntPropertyManager(w);
QtStringPropertyManager *stringManager = new QtStringPropertyManager(w);
QtGroupPropertyManager *groupManager = new QtGroupPropertyManager(w);
const QMetaObject *meta = o->metaObject();
const QString className = meta->className();
QMap<QString, PropManager*> dic;
QtProperty *root = groupManager->addProperty(className);
for(int i = meta->propertyOffset(); i < meta->propertyCount(); ++i)
{
QMetaProperty metaProp = meta->property(i);
const QString name = metaProp.name();
QVariant value = metaProp.read(o);
QVariant::Type t = metaProp.type();
QtProperty *prop = NULL;
PropManager *propMan = NULL;
switch(t)
{
case QVariant::Int:
{
prop = intManager->addProperty(name);
root->addSubProperty(prop);
intManager->setValue(prop, value.toInt());
propMan = new PropManager(prop, intManager, t);
break;
}
case QVariant::String:
{
prop = stringManager->addProperty(name);
root->addSubProperty(prop);
stringManager->setValue(prop, value.toString());
propMan = new PropManager(prop, stringManager, t);
break;
}
default:
throw std::invalid_argument("unknow type");
}
if(prop != NULL)
dic.insert(name, propMan);
}
QtCheckBoxFactory *checkBoxFactory = new QtCheckBoxFactory(w);
QtSpinBoxFactory *spinBoxFactory = new QtSpinBoxFactory(w);
QtLineEditFactory *lineEditFactory = new QtLineEditFactory(w);
QtAbstractPropertyBrowser *editor = new QtTreePropertyBrowser();
editor->setFactoryForManager(boolManager, checkBoxFactory);
editor->setFactoryForManager(intManager, spinBoxFactory);
editor->setFactoryForManager(stringManager, lineEditFactory);
editor->addProperty(root);
QGridLayout *layout = new QGridLayout(w);
layout->addWidget(editor, 1, 0);
w->show();
Foo.h is defined like this:
class Foo : public QObject
{
Q_OBJECT
public:
explicit Foo() { }
~Foo() { }
Q_PROPERTY(QString name READ getA WRITE setA)
Q_PROPERTY(int age READ getNum WRITE setNum)
QString name;
int age;
QString getA() const { return name; }
int getNum() const { return age; }
void setA(QString a) { this->name = a; }
void setNum(int n) { this->age = n; }
};

Partial solution:
I found propertyChanged() from QtAbstractPropertyManager but this does raise every time a single character is edited. I'd like to have an slot where this is fired when the user is done with the editing.

Related

Last character LineEdit

I've two list of value. the first is list of integer and second is a list of strings. i want to display these different lists based on the last content of lineEdit. For Example when the user enter A => QCompleter show me list of strings. If the user enter A1 => QCompleter show me list of integer because the last character of input is 1.
I try like this :
void QtGuiApplication1::maFonction(QString text)
{
QString lastCaractor = text.mid(text.length() - 1, 1);
if (is_number(lastCaractor.toStdString()) == true)
{
QStringList list = { "1","2","7" };
StringCompleter->setModel(new QStringListModel(list, StringCompleter));
StringCompleter->setCompletionPrefix(lastCaractor);
}
else
{
QStringList list = { "AAAA","AA","BB","AC" };
StringCompleter->setModel(new QStringListModel(list, StringCompleter));
StringCompleter->setCompletionPrefix(lastCaractor);
}
}
bool QtGuiApplication1::is_number(const std::string& s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
return !s.empty() && it == s.end();
}
If The last character is number => QCompleter show me list = { "1","2","7" };
Else => list = { "AAAA","AA","BB","AC" };
Subclass your QLineEdit with 2 customs QCompleter
ExtendedLineEdit.h
class ExtendedLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit ExtendedLineEdit(QWidget *parent = nullptr);
void setWordCompleter(QCompleter* c);
void setNumberCompleter(QCompleter* c);
protected:
void keyPressEvent(QKeyEvent *e);
private slots:
void insertCompletionWord(const QString& txtComp);
void insertCompletionNumber(const QString& txtComp);
private:
QCompleter* m_completerWord;
QCompleter* m_completerNumber;
void showCustomCompleter(QCompleter* completer);
};
ExtendedLineEdit.cpp
ExtendedLineEdit::ExtendedLineEdit(QWidget *parent) :
QLineEdit(parent)
{
}
void ExtendedLineEdit::setWordCompleter(QCompleter *c)
{
m_completerWord = c;
m_completerWord->setWidget(this);
connect(m_completerWord, SIGNAL(activated(QString)),
this, SLOT(insertCompletionWord(QString)));
}
void ExtendedLineEdit::setNumberCompleter(QCompleter *c)
{
m_completerNumber = c;
m_completerNumber->setWidget(this);
connect(m_completerNumber, SIGNAL(activated(QString)),
this, SLOT(insertCompletionNumber(QString)));
}
void ExtendedLineEdit::keyPressEvent(QKeyEvent *e)
{
QLineEdit::keyPressEvent(e);
if (!m_completerWord || !m_completerNumber)
return;
QString lastCaractor = text().mid(text().length() - 1, 1);
bool okConvertion = false;
lastCaractor.toInt(&okConvertion);
if (okConvertion)
{
//show number completer
m_completerWord->popup()->hide();
m_completerNumber->setCompletionPrefix(lastCaractor);
showCustomCompleter(m_completerNumber);
}
else
{
//show word completer
m_completerNumber->popup()->hide();
m_completerWord->setCompletionPrefix(this->text());
showCustomCompleter(m_completerWord);
}
}
void ExtendedLineEdit::insertCompletionWord(const QString &txtComp)
{
setText(txtComp);
}
void ExtendedLineEdit::insertCompletionNumber(const QString &txtComp)
{
setText(text().mid(0, text().length() - 1) + txtComp);
}
void ExtendedLineEdit::showCustomCompleter(QCompleter *completer)
{
if (completer->completionPrefix().length() < 1)
{
completer->popup()->hide();
return;
}
QRect cr = cursorRect();
cr.setWidth(completer->popup()->sizeHintForColumn(0) + completer->popup()->verticalScrollBar()->sizeHint().width());
completer->complete(cr);
}
And using
QStringList list = { "AAAA","AA","BB","AC" };
m_wordCompleter = new QCompleter(list, this);
QStringList numbers = { "1","2","7", "15" };
m_numberCompleter = new QCompleter(numbers, this);
ui->lineEdit->setWordCompleter(m_wordCompleter);
ui->lineEdit->setNumberCompleter(m_numberCompleter);

Loading and saving a class using qsettings

I have an ini file as shown
[Profiles]
hh\Ta=20
hh\Te=48
hh\Texp=38
hh\lim1=0
hh\lim2=0
hh\offset=0
hh\profilename=hh
tt\Ta=20
tt\Te=48
tt\Texp=38
tt\lim1=0
tt\lim2=0
tt\offset=0
tt\profilename=hh
I'm trying to load it, but I get all the data as zeros, like Ta Te Texp,..etc
The file is saved correctly but loading the values back is not working.
Is it a problem with setting the group,..etc ?
here is my load and save mechanism
void Method::loadFrom(Settings &set, bool ownGroup)
{
set.beginGroup("Profiles");
foreach (const QString &group, set.childGroups()) {
set.beginGroup(group);
Profile *profile = new Profile();
profile->setObjectName(group);
profile->loadFrom(set);
set.endGroup();
m_currentProfile->m_Profiles << profile;
}
set.endGroup();
EraObject::staticLoadFrom(set, this, ownGroup);
}
void Method::saveTo(Settings &set, bool ownGroup, bool force)
{
set.beginGroup("Profiles");
foreach(Profile * profile, m_currentProfile->m_Profiles) {
profile->saveTo(set);
set.endGroup();
}
set.sync();
EraObject::staticSaveTo(set, this, ownGroup, force);
}
class Settings : public QSettings
{
Q_OBJECT
public:
explicit Settings(QString fileName);
~Settings();
private:
Q_DISABLE_COPY(Settings)
};
void EraObject::staticLoadFrom(Settings &set, QObject *object, const bool &ownGroup)
{
Q_ASSERT(object);
bool modified;
const QMetaObject *superMeta = object->metaObject()->superClass();
const QMetaObject *meta = object->metaObject();
const QString &group = object->objectName().isEmpty() ? meta->className() : object->objectName();
if (ownGroup)
set.beginGroup(group);
qCDebug(loadLog) << group;
for (int i = superMeta->propertyOffset(); i < meta->propertyCount(); i++) {
modified = false;
const QMetaProperty &prop = meta->property(i);
QMetaType::Type type = (QMetaType::Type)prop.type();
if (prop.isUser()) {
switch (type) {
case QMetaType::QDateTime:
modified = setOrReset(set, object, prop, QDateTime::fromString(set.value(prop.name(), "").toString(), "yyyyMMddhhmmsszzz"));
break;
case QMetaType::QString: { //check if there is an localized string first (eg.: name#de=test)
const QVariant value = set.value(QString("%1#%2").arg(prop.name()).arg(QLocale::system().bcp47Name()),
set.value(prop.name(), ""));
modified = setOrReset(set, object, prop, value);
break;
}
case QVariant::UserType: {
QObject *obj = prop.read(object).value<QObject *>();
Q_ASSERT_X(obj, "staticLoadFrom", "Custom class NOT known to QMetaType, register it with qmlRegisterType()!");
bool check = QMetaObject::invokeMethod(obj,
"loadFrom",
Qt::DirectConnection,
Q_ARG(Settings &, set)); //we invoke cause it can be just QObject(e.g. QAbstractItemModel)
Q_ASSERT_X(check, "staticLoadFrom", "Could not invoke. Be sure you subclassed EraObject or defined method!: " + obj->objectName().toLatin1());
break;
}
default:
modified = setOrReset(set, object, prop, set.value(prop.name(), ""));
}
qCDebug(loadLog) << "modified:" << modified << "Property:" << prop.name();
}
}
if (ownGroup)
set.endGroup();
object->setProperty("dirty", NotDirty);
}
void EraObject::staticSaveTo(Settings &set, QObject *object, const bool &ownGroup, const bool &force)
{
Q_ASSERT(object);
if (force || object->property("dirty").toInt() == RamDirty) {
const QMetaObject *superMeta = object->metaObject()->superClass();
const QMetaObject *meta = object->metaObject();
const QString &group = object->objectName().isEmpty() ? meta->className() : object->objectName();
if (ownGroup)
set.beginGroup(group);
qCDebug(saveLog) << group;
for (int i = superMeta->propertyOffset(); i < meta->propertyCount(); i++) {
const QMetaProperty &prop = meta->property(i);
if (prop.isUser()) {
QMetaType::Type type = (QMetaType::Type)prop.type();
switch (type) {
case QMetaType::QDateTime:
set.setValue(prop.name(), prop.read(object).toDateTime().toString("yyyyMMddhhmmsszzz"));
break;
case QMetaType::Float:
case QMetaType::Double:
set.setValue(prop.name(), QString::number(prop.read(object).toDouble(), 'g', MAX_SAVED_DECIMALS));
break;
case QMetaType::User: {
QObject *obj = prop.read(object).value<QObject *>();
Q_ASSERT_X(obj, "staticLoadFrom", "Custom class NOT known to QMetaType, register it with qmlRegisterType()!");
bool check = QMetaObject::invokeMethod(obj,
"saveTo",
Qt::DirectConnection,
Q_ARG(Settings &, set),
Q_ARG(bool, true),
Q_ARG(bool, force));
Q_ASSERT_X(check, "saveTo", "Could not invoke. Be sure you subclassed EraObject or defined method!: " + obj->objectName().toLatin1());
break;
}
default:
if (!prop.isConstant())
set.setValue(prop.name(), prop.read(object));
}
}
}
if (ownGroup)
set.endGroup();
object->setProperty("dirty", NotDirty);
set.sync();
}
}

QAbstractItemModel dynamic item insertion

I inherited QAbstractItemModel class for my model. To easily insert new items to the model I wrote next method:
void addItem(MyData *parent, MyData *children) {
QModelIndex idx = createIndex(parent->row(), 0, parent);
if (!idx.isValid()) {
return;
}
int childCount = parent->getChildCount();
beginInsertRows(idx, childCount, childCount);
parent->addChild(children);
endInsertRows();
emit layoutChanged(QList<QPersistentModelIndex>{idx});
}
It works well with QListView, but QML's TreeView does not updates values after it once showed it:
int main(int argc, char ** argv) {
Q_INIT_RESOURCE(ui);
QApplication application(argc, argv);
MyModel model;
for (int i = 0; i < 10; ++ i) {
MyData *firstLevelItem = new MyData(i);
for (int k = 0; k < 3; ++ k) {
MyData *secondLevelItem = new MyData(i);
model.addItem(firstLevelItem, secondLevelItem);
}
model.addItem(model.getRootItem(), firstLevelItem);
}
QQuickView view;
QQmlContext *context = view.rootContext();
context->setContextProperty("MyModel", &model);
view.setSource(QUrl("qrc:///ui/form.qml"));
view.show();
QTreeView t;
t.setModel(&model);
t.show();
MyData *data = new MyData(2281488);
model.addItem(model.getRootItem(), data);
// t displays changes, view - not
return application.exec();
}
MyData class:
class MyModel;
class MyData: public QObject {
Q_OBJECT
public:
explicit MyData() :
QObject() {
_parent = nullptr;
}
~MyData() {
qDeleteAll(_data);
}
// getters / setters
MyData *getChildItem(int index) const {
if (index < 0 || index >= _data.size()) {
return nullptr;
}
return _data[index];
}
int getChildCount() const {
return _data.size();
}
MyData *parent() const {
return _parent;
}
int row() const {
if (_parent) {
return _parent->_data.indexOf(const_cast<MyData *>(this));
} else {
return 0;
}
}
private:
void addChild(MyData *data) {
if (data) {
if (data->_parent) {
_parent->removeChild(data);
}
data->_parent = this;
_data << data;
}
}
void removeChild(MyData *data) {
_data.removeAll(data);
}
// some private fields
MyData *_parent;
QVector<MyData *> _data;
friend class MyModel;
};
QML's ListView is not suited to display tree-like structures like a directory tree, for example. It only works with list models typically inherited from QAbstractListModel. If you derive your model from QAbstractItemModel, you must specialise it such that it behaves like a list.
Since Qt 5.5 there is a QML TreeView componenent in the module QtQuick.Controls (v1.4). You may want to try this.

Using QTableView with a model

I have the QVector cars that I want to filter basing on the car's registration number. I want to create a new filtered vector. I don't think that this is ok because i'm iterating 2 vectors, copying from the first one to the second one. Am I doing this right?
void MainWindow::on_actionBy_registration_number_triggered()
{
myDialog = new MyDialog(this);
myDialog->exec();
QString toSearchString = myDialog->getRegistrationNumber();
QVector<Vehicle> founded;
QVectorIterator<Vehicle> iterator(cars);
while(iterator.hasNext()){
Vehicle car = iterator.next();
QString num = car.getRegistration().getRegistrationNumber();
if(num.contains(toSearchString,Qt::CaseInsensitive)){
founded.append(car);
}
}
model = new QStandardItemModel(founded.size(),5,this);
//create header
createHeader(model);
int j = 0; //row
QVectorIterator<Vehicle> iter(founded);
while(iter.hasNext()){
Vehicle output = iter.next();
//set car
QString makeAndModel = output.getGeneralData().getMake() + output.getGeneralData().getModel();
QStandardItem *mAndM = new QStandardItem(QString(makeAndModel));
model->setItem(j,0,mAndM);
//set type
QStandardItem *type = new QStandardItem(QString(output.getGeneralData().getType()));
model->setItem(j,1,type);
//set mileage
QString mileageString = QString::number(output.getGeneralData().getMileage());
QStandardItem *mileage = new QStandardItem(QString(mileageString));
model->setItem(j,2,mileage);
//set year
QString yearString = QString::number(output.getGeneralData().getYear());
QStandardItem *year = new QStandardItem(QString(yearString));
model->setItem(j,3,year);
//set registration
QString regString = VehicleHelper::convertBoolToString(output.getRegistration().isRegistered());
QStandardItem *regDate = new QStandardItem(QString(regString));
model->setItem(j,4,regDate);
j++;
}
ui->tableView->setModel(model);
ui->tableView->setEnabled(false);
}
This can be done neatly using a proxy filter model. Below is a self-contained example that runs on both Qt 4 and 5.
// https://github.com/KubaO/stackoverflown/tree/master/questions/filter-18964377
#include <QtGui>
#if QT_VERSION_MAJOR > 4
#include <QtWidgets>
#endif
class Vehicle {
QString m_make, m_model, m_registrationNumber;
public:
Vehicle(const QString & make, const QString & model, const QString & registrationNumber) :
m_make{make}, m_model{model}, m_registrationNumber{registrationNumber} {}
QString make() const { return m_make; }
QString model() const { return m_model; }
QString registrationNumber() const { return m_registrationNumber; }
bool isRegistered() const { return !m_registrationNumber.isEmpty(); }
};
class VehicleModel : public QAbstractTableModel {
QList<Vehicle> m_data;
public:
VehicleModel(QObject * parent = {}) : QAbstractTableModel{parent} {}
int rowCount(const QModelIndex &) const override { return m_data.count(); }
int columnCount(const QModelIndex &) const override { return 3; }
QVariant data(const QModelIndex &index, int role) const override {
if (role != Qt::DisplayRole && role != Qt::EditRole) return {};
const auto & vehicle = m_data[index.row()];
switch (index.column()) {
case 0: return vehicle.make();
case 1: return vehicle.model();
case 2: return vehicle.registrationNumber();
default: return {};
};
}
QVariant headerData(int section, Qt::Orientation orientation, int role) const override {
if (orientation != Qt::Horizontal || role != Qt::DisplayRole) return {};
switch (section) {
case 0: return "Make";
case 1: return "Model";
case 2: return "Reg.#";
default: return {};
}
}
void append(const Vehicle & vehicle) {
beginInsertRows({}, m_data.count(), m_data.count());
m_data.append(vehicle);
endInsertRows();
}
};
class Widget : public QWidget {
QGridLayout m_layout{this};
QTableView m_view;
QPushButton m_button{"Filter"};
VehicleModel m_model;
QSortFilterProxyModel m_proxy;
QInputDialog m_dialog;
public:
Widget() {
m_layout.addWidget(&m_view, 0, 0, 1, 1);
m_layout.addWidget(&m_button, 1, 0, 1, 1);
connect(&m_button, SIGNAL(clicked()), &m_dialog, SLOT(open()));
m_model.append({"Volvo", "240", "SQL8941"});
m_model.append({"Volvo", "850", {}});
m_model.append({"Volvo", "940", "QRZ1321"});
m_model.append({"Volvo", "960", "QRZ1628"});
m_proxy.setSourceModel(&m_model);
m_proxy.setFilterKeyColumn(2);
m_view.setModel(&m_proxy);
m_dialog.setLabelText("Enter registration number fragment to filter on. Leave empty to clear filter.");
m_dialog.setInputMode(QInputDialog::TextInput);
connect(&m_dialog, SIGNAL(textValueSelected(QString)),
&m_proxy, SLOT(setFilterFixedString(QString)));
}
};
int main(int argc, char *argv[])
{
QApplication a{argc, argv};
Widget w;
w.show();
return a.exec();
}

Redefining QTreeWidgetItem::operator<

My main goal here is to redefine operator< so that I can sort my columns numerically instead of alphabetically. The code I have so far:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
//bunch of includes...
#include <QTreeWidgetItem>
#include <QTreeWidget>
extern QSqlDatabase db;
extern QString prefix;
extern QString site;
extern QString dbname;
extern QString user;
namespace Ui {
class mainwindow;
}
class clientinfo;
class mainwindow : public QMainWindow
{
Q_OBJECT
public:
explicit mainwindow(QWidget *parent = 0);
void rPopulate();
void rbookingdisplay();
QPushButton *button;
~mainwindow();
public slots:
//slots...
private:
Ui::mainwindow *ui;
void closeEvent(QCloseEvent *close);
};
class TreeWidgetItem : public QTreeWidgetItem
{
public:
TreeWidgetItem(QTreeWidget *tree) : QTreeWidgetItem(tree) {}
TreeWidgetItem(QTreeWidget * parent, const QStringList & strings)
: QTreeWidgetItem (parent,strings) {}
bool operator< (const QTreeWidgetItem &other) const
{
int sortCol = treeWidget()->sortColumn();
int myNumber = text(sortCol).toInt();
int otherNumber = other.text(sortCol).toInt();
return myNumber < otherNumber;
}
};
#endif // MAINWINDOW_H
and in mainwindow.cpp I have ui->_display->setSortingEnabled(true);
somehow it doesn't use the redefined operator< (the redefined function is never called, it uses the predefined one). Please help.
ui->_abooking->clear();
ui->_abooking->setSortingEnabled(false);
QSqlQuery query;
query.prepare(" SELECT shownumdays, shownumpastdays FROM setting_"+ user +
" WHERE id = 1; ");
query.exec();
query.first();
int days = query.record().value("shownumdays").toInt();
int pastdays = query.record().value("shownumpastdays").toInt();
query.prepare(" SELECT `"+Columns.join("`, `")+
"`,`Currency`, `# of Room` "
" FROM abooking "
" WHERE (DATE_ADD(`Arrival Date`,INTERVAL `Nights` - 1 DAY) >= (CURRENT_DATE - "+ QString::number(pastdays) +") AND "
" (TO_DAYS(`Arrival Date`) + `Nights` - 1 - TO_DAYS(NOW())) <= "+ QString::number(days) +") ");
query.exec();
QString confirm_num = "";
bool flip = true;
while (query.next()){
if (!(confirm_num == query.record().value("Confirmation #").toString())) {
flip = (!flip);
}
QTreeWidgetItem *item = new QTreeWidgetItem();
for (int i = 0; i < Columns.length(); i++) {
if (Columns.at(i) == "Arrival Date") {
item->setText(i, query.record().value(Columns.at(i)).toDate().toString("dd-MM-yyyy"));
} else if ((Columns.at(i) == "Amount Due" || Columns.at(i) == "Paid") && (confirm_num == query.record().value("Confirmation #").toString())) {
item->setText(i, "");
} else if ((Columns.at(i) == "Arrival Time")){
item->setText(i, " " + query.record().value(Columns.at(i)).toTime().toString("hh:mm"));
} else {
item->setText(i, query.record().value(Columns.at(i)).toString());
}
if (Columns.at(i) == "Amount Due" && (!(item->text(i) == ""))) {
item->setTextColor(i, Qt::darkRed);
item->setText(i, item->text(i) + " " + query.record().value("Currency").toString());
} else if (Columns.at(i) == "Room") {
item->setText(i, query.record().value("# of Room").toString() + " " + item->text(i));
}
if (flip) {
item->setBackground(i , Qt::gray);
}
}
if ((!(confirm_num == query.record().value("Confirmation #").toString()))) {
confirm_num = query.record().value("Confirmation #").toString();
ui->_abooking->addTopLevelItem(item);
} else {
ui->_abooking->topLevelItem(ui->_abooking->topLevelItemCount() - 1)->addChild(item);
ui->_abooking->topLevelItem(ui->_abooking->topLevelItemCount() - 1)->setExpanded(true);
}
}
ui->_abooking->setSortingEnabled(true);
You're reimplementing QTreeWidgetItem with a custom class, but then you don't use it when populating the QTreeWidget.
Instead of
QTreeWidgetItem *item = new QTreeWidgetItem();
this should be:
TreeWidgetItem *item = new TreeWidgetItem();
Other than that, your code for operator < looks fine. I'm using the same and it works for me.
bool operator< (const QTreeWidgetItem &other) const
{
int sortCol = treeWidget()->sortColumn();
int myNumber = text(sortCol).toInt();
int otherNumber = other.text(sortCol).toInt();
return myNumber < otherNumber;
}
With reference to your code here above:
I think your problem is that the sort column on the widget remains constant for all QTreeWidgetItems. You have to sort on the value of the item (not the column of the widget):
Therefore the code should look like this:
bool operator< (const QTreeWidgetItem &other) const
{
Q_ASSERT( other.treeWidget() == treeWidget() );
const int col = treeWidget()->sortColumn();
const int role = Qt::DisplayRole;
return( data( col, role ).toInt() < other.data( col, role ).toInt() );
}
The cells are sorted according to the type of data you store in them. You don't need to redefine an operator for that, because QVariant will take care of the comparison for you.
For example, you should use:
item−>setData(0, `Qt::EditRole`, 10);
instead of:
item->setText(0, "10");