QTableView & CheckBox delegate alignmnent
-
Ok, I created my own subclass of QSqlRelationalDelegate and now everyhting works.
Here is the related code:
@QWidget *mySqlRelationalDelegate::createEditor(QWidget *aParent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
const QSqlRelationalTableModel *sqlModel = qobject_cast<const QSqlRelationalTableModel *>(index.model()); QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0; if (!childModel ) { const QSortFilterProxyModel* proxyModel = qobject_cast<const QSortFilterProxyModel *>(index.model()); if (proxyModel) { sqlModel = qobject_cast<const QSqlRelationalTableModel *>(proxyModel->sourceModel()); childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0; } } if (!childModel) { return QItemDelegate::createEditor(aParent, option, index); } QComboBox *combo = new QComboBox(aParent); combo->setModel(childModel); combo->setModelColumn(childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn())); combo->installEventFilter(const_cast<mySqlRelationalDelegate *>(this)); return combo;
}
void mySqlRelationalDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QString strVal = "";
const QSqlRelationalTableModel *sqlModel = qobject_cast<const QSqlRelationalTableModel >(index.model());
if (!sqlModel )
{
const QSortFilterProxyModel proxyModel = qobject_cast<const QSortFilterProxyModel *>(index.model());
if (proxyModel) {
strVal = proxyModel->data(index).toString();
}
} else {
strVal = sqlModel->data(index).toString();
}QComboBox *combo = qobject_cast<QComboBox *>(editor); if (strVal.isEmpty() || !combo) { QItemDelegate::setEditorData(editor, index); return; } combo->setCurrentIndex(combo->findText(strVal));
}
void mySqlRelationalDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if (!index.isValid())
return;QSqlRelationalTableModel *sqlModel = qobject_cast<QSqlRelationalTableModel *>(model); QSortFilterProxyModel* proxyModel = NULL; if (!sqlModel ) { proxyModel = qobject_cast<QSortFilterProxyModel *>(model); if (proxyModel) sqlModel = qobject_cast<QSqlRelationalTableModel *>(proxyModel->sourceModel()); } QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0; QComboBox *combo = qobject_cast<QComboBox *>(editor); if (!sqlModel || !childModel || !combo) { QItemDelegate::setModelData(editor, model, index); return; } int currentItem = combo->currentIndex(); int childColIndex = childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn()); int childEditIndex = childModel->fieldIndex(sqlModel->relation(index.column()).indexColumn()); if (proxyModel) { proxyModel->setData(index, childModel->data(childModel->index(currentItem, childColIndex), Qt::DisplayRole), Qt::DisplayRole); proxyModel->setData(index, childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole), Qt::EditRole); } else { sqlModel->setData(index, childModel->data(childModel->index(currentItem, childColIndex), Qt::DisplayRole), Qt::DisplayRole); sqlModel->setData(index, childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole), Qt::EditRole); }
}
@I'll try making it a Wiki!
-
[quote author="hsfougaris" date="1301553694"]Also if QSFPM means QSortFilterProxyModel, I agree it's not bad as a solution (especially after what I managed to build with a little help); I just wish I could do a few more things with it...[/quote]
Yes, QSFPM is a (here) common abbreveation for QSortFilterProxyModel :-)
Perhaps we should add a wiki page with common abbreveation sused here :-)
-
<dreaming>
We should have a feature where such abbreviations are automatically underlined with a dotted line (perhaps only for the first use in a post), which show an explanation on the meaning of that abbreviation (perhaps automagically retreived from that wiki page you talk about).
</dreaming> -
I tried to post the source as a wiki ( I created 2 separate pages - one for the delegate and one for the sortproxy thing), but I'm sure I messed it up.
Am I supposed to add them to a category, or does an admin do that?I tried adding the [[Category... thing but it appeared as plain text.
-
-
author="Andre" date="1301563925"]<dreaming>
We should have a feature where such abbreviations are automatically underlined with a dotted line (perhaps only for the first use in a post), which show an explanation on the meaning of that abbreviation (perhaps automagically retreived from that wiki page you talk about).
</dreaming>
[/quote]Make a feature request from this in Jira :-) The idea is cool.
[quote author="hsfougaris" date="1301564361"]I tried to post the source as a wiki ( I created 2 separate pages - one for the delegate and one for the sortproxy thing), but I'm sure I messed it up.
Am I supposed to add them to a category, or does an admin do that?I tried adding the [[Category... thing but it appeared as plain text.[/quote]
I added the category for you. Just have a look with edit :-)
-
Thanks... Do you have any references for suppliers of tableView alternatives?
-
Hi,
not more than you already found: devmachines and ICS. I'm sure, there are more, but I don't know who. You can search "Qt apps":http://www.qt-apps.org/
One side note to your wiki:
I found one error:
the data/setdata and flags methods should be public, as they are public in the base class. Making the protected in your derived class leads to strange behavior:
People using the base class pointers are able to call them, people using the pointers of type of your class may not. Please make them public.
-
[quote author="hsfougaris" date="1301564749"]http://developer.qt.nokia.com/wiki/QSortFilterProxyModel_subclass_for_readonly_columns_columns_with_checkboxes_and_password_columns
[/quote]
Pages, including categories, look fine to me.
-
Did you already do it in the wiki? Because I just looked at the wiki, and it's been removed.
-
[quote author="Andre" date="1301565818"]
[quote author="hsfougaris" date="1301564749"]http://developer.qt.nokia.com/wiki/QSortFilterProxyModel_subclass_for_readonly_columns_columns_with_checkboxes_and_password_columns[/quote]
Pages, including categories, look fine to me.
[/quote]
Yes, Gerolf was nice enough to fix them for me.
-
[quote author="harry" date="1301564361"]I tried to post the source as a wiki ( I created 2 separate pages - one for the delegate and one for the sortproxy thing), but I'm sure I messed it up.
Am I supposed to add them to a category, or does an admin do that?I tried adding the [[Category... thing but it appeared as plain text.[/quote]
I have modified your wiki page to add a link to "another solution":https://developer.qt.nokia.com/wiki/QSortFilterProxyModel_subclass_to_add_a_checkbox for adding checkboxes to an abstract item model. The use cases for both approaches are different, and I think they nicely supplement each other. I hope you don't mind.
Edit:
I have opened "this topic":https://developer.qt.nokia.com/forums/viewthread/5544/ to discuss the API of the class you posted in the snippet, as I think there is room for improvement. -
[quote author="harry" date="1301486015"]Ok I found something that seems to work.
(based on this http://www.qtcentre.org/archive/index.php/t-18675.html)I'm putting the code here, in case it helps someone else:
The basic idea is that there is something like a QList that holds the indexes of the columns that you want to have checkboxes (I'm already thinking of adding another QList for readonly columns).
Actual usage would be
@
CheckableSortFilterProxyModel *cfpm = new CheckableSortFilterProxyModel(this);
QList<int> boolCols;
boolCols.append( usrModel->fieldIndex("isActive") );
boolCols.append( usrModel->fieldIndex("isOk") );
cfpm->setParameters(boolCols);
cfpm->setSourceModel( mySqlTableModel );
myTableView->setModel(cfpm);
@Here is the code:
checkablesortfilterproxymodel.h:
@
#ifndef CHECKABLESORTFILTERPROXYMODEL_H
#define CHECKABLESORTFILTERPROXYMODEL_H#include <QSortFilterProxyModel>
class CheckableSortFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit CheckableSortFilterProxyModel(QObject *parent = 0);void setParameters(QList<int> boolCols);
protected:
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
Qt::ItemFlags flags ( const QModelIndex & index ) const;signals:
public slots:
private:
QList<int> booleanSet;};
#endif // CHECKABLESORTFILTERPROXYMODEL_H
@checkablesortfilterproxymodel.cpp:
@
#include "checkablesortfilterproxymodel.h"CheckableSortFilterProxyModel::CheckableSortFilterProxyModel(QObject *parent) :
QSortFilterProxyModel(parent)
{
}void CheckableSortFilterProxyModel::setParameters(QList<int> boolCols) {
booleanSet.clear();
if (!boolCols.isEmpty()) {
foreach(int column , boolCols)
{
booleanSet.append(column);
}
}
}QVariant CheckableSortFilterProxyModel::data(const QModelIndex &index, int role) const {
if(!index.isValid())
return QVariant();if(booleanSet.contains(index.column()) && (role == Qt::CheckStateRole || role == Qt::DisplayRole)) { if (role == Qt::CheckStateRole) return index.data(Qt::EditRole).toBool() ? QVariant(Qt::Checked) : QVariant(Qt::Unchecked); else if (role == Qt::DisplayRole) return QVariant(); } else return QSortFilterProxyModel::data(index,role);
}
bool CheckableSortFilterProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) {
if(!index.isValid())
return false;if(booleanSet.contains(index.column()) && role==Qt::CheckStateRole) { QVariant data = (value.toInt()==Qt::Checked) ? QVariant(1) : QVariant (0); return QSortFilterProxyModel::setData(index, data, Qt::EditRole); } else return QSortFilterProxyModel::setData(index,value,role);
}
Qt::ItemFlags CheckableSortFilterProxyModel::flags ( const QModelIndex & index ) const {
if(!index.isValid())
return Qt::ItemIsEnabled;if(booleanSet.contains(index.column())) return Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsEnabled; else return QSortFilterProxyModel::flags(index);
}
@
[/quote]I know its been over a year since this was las posted but I just wanted to say thank you to Harry for solving this because I have been struggeling with making a check box in a column for a while!