[Interest] Depending QCombobox

Michele Ciampichetti cia.michele at gmail.com
Thu Jan 12 08:51:44 CET 2012


Hello Alex,
thanks for your answer. Could you send any example of your ideas?
I attach what I got, so you can valutate it.

1) I subclass QRelationalDelegate to make the column behaves different

class PicLoadDelegate: public QSqlRelationalDelegate

{

    Q_OBJECT

public:

    PicLoadDelegate(QObject * parent = 0 ): QSqlRelationalDelegate(parent)

    {}

   ~PicLoadDelegate()

    {}

    void setEditorData(QWidget *editor, const QModelIndex &index) const

    {

        switch(index.column()) {

        case 4:

        {

            const QSqlRelationalTableModel * sqlModel = qobject_cast
<const QSqlRelationalTableModel *>(index.model());

            QSqlTableModel * childModel = sqlModel ?
sqlModel->relationModel(index.column()) : 0;

            QString filter=QString("CodRegione=(SELECT ID FROM REGIONI
WHERE NOME='%1')").arg(sqlModel->index(index.row(),10).data().toString());

            childModel->setFilter(filter);

            QComboBox * combo = qobject_cast <QComboBox *>(editor);

            if(!sqlModel || !combo){

                QSqlRelationalDelegate::setEditorData(editor,index);

                return;

            }

            combo->setModel(childModel);

            combo->setCurrentIndex(combo->findText(sqlModel->data(index).toString()));

            break;

        }

        case 5:{

            const QSqlRelationalTableModel * sqlModel = qobject_cast
<const QSqlRelationalTableModel *>(index.model());

            QSqlTableModel * childModel = sqlModel ?
sqlModel->relationModel(index.column()) : 0;

            QString filter=QString("CodProvincia=(SELECT ID FROM
PROVINCE WHERE NOME='%1')").arg(sqlModel->index(index.row(),4).data().toString());

            childModel->setFilter(filter);

            QComboBox * combo = qobject_cast <QComboBox *>(editor);

            if(!sqlModel || !combo){

                QSqlRelationalDelegate::setEditorData(editor,index);

                return;

            }

            combo->setModel(childModel);

            combo->setCurrentIndex(combo->findText(sqlModel->data(index).toString()));

            break;

        }

        case 9: // do something special for blob column 2

        {

            QLabel *label = qobject_cast<QLabel*>(editor);

            //Q_ASSERT(label);

            if (label) {

                QByteArray imageData = index.data(Qt::EditRole).toByteArray();

                QPixmap pixmap;

                if (pixmap.loadFromData(imageData))

                    label->setPixmap(pixmap);

            }

            break;

        }

        default:

            QSqlRelationalDelegate::setEditorData(editor, index);

        }

    }

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

    {

        switch(index.column()) {

        case 9: // do something special for blob column 2

        {

            QLabel *label = qobject_cast<QLabel*>(editor);

            Q_ASSERT(label);

            if (label) {

                QBuffer buf;

                buf.open(QIODevice::WriteOnly);

                if (label->pixmap()!=0){

                    if (label->pixmap()->save(&buf,"PNG"))

                    model->setData(index, buf.data(), Qt::EditRole);

                }else

                     model->setData(index, buf.data(), Qt::EditRole);

            }

            break;

        }

        default: // so does anything we've missed

        {

                    if (!index.isValid())

                        return;

                    QSqlRelationalTableModel *sqlModel =
qobject_cast<QSqlRelationalTableModel *>(model);

                    QSqlTableModel *childModel;

                    QComboBox *combo = qobject_cast<QComboBox *>(editor);

                    if (combo)

                        childModel= qobject_cast<QSqlTableModel
*>(combo->model());

                    else

                        childModel = sqlModel ?
sqlModel->relationModel(index.column()) : 0;

                    if (!sqlModel || !childModel || !combo) {

                        QItemDelegate::setModelData(editor, model, index);

                        return;

                    }

                    int rows = childModel->rowCount();

                    QString name= combo->accessibleName();

                    QString testo = combo->currentText();

                    int currentItem = combo->currentIndex();

                    int childColIndex =
childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn());

                    int childEditIndex =
childModel->fieldIndex(sqlModel->relation(index.column()).indexColumn());

                    QString display =
childModel->data(childModel->index(currentItem,
childColIndex)).toString();

                    int indice =
childModel->data(childModel->index(currentItem,
childEditIndex)).toInt();

                    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);

                    break;

                }

        }

2) I use the signal-slot link to change the content of the QComboBox at
selection of the master one:

LMForn class constructor
[...]
      connect(ui->cboRegione,SIGNAL(currentIndexChanged(int)),this,SLOT(
setFilterProv(int)));

    connect(ui->cboProv,SIGNAL(currentIndexChanged(int)),this,SLOT(setFilterCom(int)));

[...]

void LMForn::setFilterProv(int currentIndex){

    mdlProv = new QSqlTableModel(this);

    mdlProv->setTable("Province");

    mdlProv->setFilter (QString("CodRegione=(SELECT ID FROM REGIONI
WHERE NOME='%1')").arg(ui->cboRegione->currentText()));

    mdlProv->select();

    ui->cboProv->setModel(mdlProv);

}

void LMForn::setFilterCom(int currentIndex){

    mdlCom = new QSqlTableModel(this);

    mdlCom->setTable("Comuni");

    mdlCom->setFilter (QString("CodProvincia=(SELECT ID FROM PROVINCE
WHERE NOME='%1')").arg(ui->cboProv->currentText()));

    mdlCom->select();

    ui->cboComune->setModel(mdlCom);

}


It work in this way: if I have a congruent configuration of three combobox,
the load is ok, but if I change one of three, the update of the
QSqlRelationalTableModel fails and need two time of same configuration to
objain the saving.

What could be the mistake? If I watch in debug the combo->currentIndex() or
combo->currentText() are corrects, but the save data don't write data into
model. It want preserve the relations on data? How can I solve this problem?

Thanks a lot for your time

Michele

2012/1/12 Alex Malyushytskyy <alexmalvtk at gmail.com>

> Since nobody posted I decided to give my comments, even though I have
> not worked with mentioned classes.
> As far as I see your problem,
>
> You need to be able:
>
> 1. to be notified when selection in combo-box is changed
>
> This can be done by overriding createEditor and connecting combobox
> signal (mostly likely you would want activated (const QString& ) )
> to custom slot.
> I recommend to use Qt::QueuedConnection.
> This should insure that slots is not called when data is still changing.
>
> 2. apply filter to model index based on selection value.
>
> Do this in the custom slot I mentioned above.
> Only difficulty might be to find out index for which slot is called.
>
> I would subclassed QComboBox,
> added variable where I would store QModelIndex it was created for and
> signal   activated ( const QModelIndex& , const QString& ),
> which I would emit when selection changed
>
> This way you will have enough information about
> where action happened and what current selection is.
>
> So you might find out index you have to apply filter to.
>
>
> Regards,
>   Alex
>
> On Tue, Jan 10, 2012 at 9:45 AM, Michele Ciampichetti
> <cia.michele at gmail.com> wrote:
> > Hello to everybody,
> > To solve this problem, i trying to subclass a QSqlRelationalDelegate, so
> > that, at che column of second combobox, I can apply a filter on the
> > QSqlTableModel returned by relationalModel; but i can't do this, because
> the
> > delegate use only a const QModelIndex so i can't access the complete
> model
> > and use the setFilter method. This is my code:
> >
> > void setEditorData(QWidget *editor, const QModelIndex &index) const
> >    {
> >        switch(index.column()) {
> >        case 4:{
> >            const QSqlRelationalTableModel * sqlModel = qobject_cast<const
> > QSqlRelationalTableModel *>(index.model());
> >
> >
> sqlModel->setFilter(QString("CodProvincia=%1").arg(sqlModel->index(index.row,10).data().toInt());
> >            QComboBox * combo = qobject_cast<QComboBox *> (editor);
> >            if (!sqlModel || !combo){
> >                QItemDelegate::setEditorData(editor,index);
> >                return;
> >            }
> >
> >
>  combo->setCurrentIndex(combo->findText(sqlModel->data(index).toString()));
> > break;}
> >
> > But it return an error, because the index is only a constant. This is the
> > error:
> >
> > ..\picloaddelegate.h:24: error: passing 'const QSqlRelationalTableModel'
> > as 'this' argument of 'virtual void QSqlTableModel::setFilter(const
> > QString&)' discards qualifiers
> >
> >
> > Any ideas of how resolve it?
> >
> >
> > thanks a lot for your time!
> >
> > Michele
> >
> >
> >
> >
> > 2012/1/9 Michele Ciampichetti <cia.michele at gmail.com>
> >>
> >> Good morning to all,
> >> How can I create 3 depending QCombobox, for example Country, City and
> Zip
> >> Code, so that when I select one, the other ones are filtered by the
> value of
> >> the first one? I'm use a QSqlRelationalTableModel and 3 relations (so
> also 3
> >> QSqlTableModel). I know that I can use QComboBox signal to filter data
> of
> >> QSqlTableModel, but if I use the QDataWidgetMapper the search on it
> don't
> >> fire any QCombobox Signal, so, how can I got what I want?
> >>
> >>
> >> Thanks a lot for your time!
> >>
> >> Michele
> >
> >
> > _______________________________________________
> > Interest mailing list
> > Interest at qt-project.org
> > http://lists.qt-project.org/mailman/listinfo/interest
> >
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20120112/6602d483/attachment.html>


More information about the Interest mailing list