Trolltech Home | Qt-jambi-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-jambi-interest Archive, January 2008
QDataWidgetMapper and custom model


Message 1 in thread

Hello !

Sorry if this message is a bit long but I'd like to be sure I don't forget
anything...

I'm developping a small bibliographic application based upon a PostgreSQL
database.

To fit my needs I defined my own model class inherited from
QSqlQueryModel. The data are obtained from a SQL query. Added to this
basic data, I create a new column to display bibliography of an author.
This additional data are obtained from another query located in function
getBiblio(index) which is itself located in the data() function inherited
from QSqlQueryModel.

Here the code:

public class M_AuteursManager extends QSqlQueryModel{ // my model
inherited from QSqlQueryModel.

        public M_AuteursManager() {
        super();
    }

    public void setupModel(){
        String query = "SELECT * FROM auteurs ORDER BY nom_aut ASC"; //
basic SQL query
        setQuery(query);
        setHeaderData(0, Qt.Orientation.Horizontal, "Id");
        setHeaderData(1, Qt.Orientation.Horizontal, "Nom");
        setHeaderData(2, Qt.Orientation.Horizontal, "Prénom");
        setHeaderData(3, Qt.Orientation.Horizontal, "Spécialité");
        setHeaderData(4, Qt.Orientation.Horizontal, "Nationalité");
        insertColumns(5, 1, null); // I add the new column
        setHeaderData(5, Qt.Orientation.Horizontal, "Bibliographie");
    }

    public Object data(QModelIndex index, int role){ // Overriding data()
function to populate the new column
        Object value = super.data(index, role);
        if (index != null && role == Qt.ItemDataRole.DisplayRole &&
index.column() == 5){
            return getBiblio(index);
        }
                return value;
    }

    private String getBiblio(QModelIndex index){ // I get the biblio data
as a String

       ... // code continuation

    }
}

All of this works fine when I display this model through a QTableView (or
more exactly my QTableViewer class inherited from QTableView). I obtain my
new column "Bibliographie" with the right content.

However, when I want to display my model through a form, my new column is
never displayed while the other columns are correctly displayed.
Everything goes as if only my "raw" model is took in consideration,
ignoring the data() function.

On the View/Controller side, I defined a class "Ui_AuteursManager" for
GUI, which includes two tabs : a "list" view to display the whole bunch of
authors into a QTableView and a "details" view to display authors one by
one into a form build with QLineEdit widgets, QTextBrowser widgets, etc. I
also defined the class "AuteursManager" which is supposed to manage all of
this. In this class, I use a QDataWidgetMapper to map my model items to my
form widgets.

Code:

public class AuteursManager extends QWidget{
    private M_AuteursManager model; // my custom model
    private Ui_AuteursManager ui; // my GUI which includes both the
QTableView and my form
    private QDataWidgetMapper mapper; // my mapper

    public AuteursManager(QWidget parent) {
        super(parent);
        model = new M_AuteursManager();
        model.setupModel(); // I setup my model. So here my new column is
added

        ui = new Ui_AuteursManager();
        ui.setupUi(this);

        ui.tableViewer.setModel(model); // I define the model for my
QTableView (included in my tableViewer custom widget which is
inherited from QTableView)
        ui.tableNavigator.setModel(model);

        mapper = new QDataWidgetMapper();
        mapper.setModel(model);
        mapper.addMapping(ui.nomEdit, 1);
        mapper.addMapping(ui.pnomEdit, 2);
        mapper.addMapping(ui.specEdit, 3);
        mapper.addMapping(ui.natEdit, 4);
        mapper.addMapping(ui.bibEdit, 5); // I do the mapping of all
widgets of the form including the ui.bibEdit widget which is
supposed to display the content of the new column)

        mapper.toFirst();

               ... // code continuation

I can't figure out why the content of the new column is never mapped !

During my investigations, I did a test modifying the base query to do
"SELECT *, 'biblio' FROM auteurs ORDER BY nom_aut ASC". Using PostgreSQL,
this query creates a new column containing the string 'biblio' on each
row. Doing this, the QTextBrowser widget (ui.bibEdit), which is supposed
to display my new column in the form, displays the string 'biblio' for
each row. Once again, everything goes exactly as if the mapper ignores the
data() function in my model.

I suppose something wrong in my approach but I can't figure out what it
is. Isn't the mapper supposed to take in consideration the data() function
? If not, how can I obtain the same result ?

Every help would be appreciated.

jMax

PS: Sorry for french strings in code parts, I hope they don't complicate
the understanding of the code. Hopefully for once, english words and
french words are quite similar (auteur means author, nom means name,
etc...)



Message 2 in thread

moebius@xxxxxxxxxx wrote:

Hi,

>     public void setupModel(){
>         String query = "SELECT * FROM auteurs ORDER BY nom_aut ASC"; //
> basic SQL query
>         setQuery(query);
>         setHeaderData(0, Qt.Orientation.Horizontal, "Id");
>         setHeaderData(1, Qt.Orientation.Horizontal, "Nom");
>         setHeaderData(2, Qt.Orientation.Horizontal, "Prénom");
>         setHeaderData(3, Qt.Orientation.Horizontal, "Spécialité");
>         setHeaderData(4, Qt.Orientation.Horizontal, "Nationalité");
>         insertColumns(5, 1, null); // I add the new column
>         setHeaderData(5, Qt.Orientation.Horizontal, "Bibliographie");
>     }

I haven't verified this with an example so I might be wrong, but I 
believe you have a bug with how you do insertColumns. 
QAbstractTableModel at least, does not store the columnCount() so when 
you do insertColumns() and this shows up in the view may be luck more 
than a safe bet.

When you insert columns into a table you should do:

beginInsertColumns(...);
insertColumns(...);
endInsertColumns(...);

This is to notify any listeners to the view that the view is changed. In 
addition to that you should reimplement the public int 
columnCount(QModelIndex) function in the baseclass to return the size of 
the querymodel + your inserted column.

---

Aside from that, I'm not sure if changing the table itself is the best 
solution here. There might be some internal logic in the querymodel that 
relies consistent size between the actual database table and the 
querymodel itself. Maybe a proxy model that adds the extra column and 
looks up the bibliographie is simpler. That way you don't modify the 
database model.

best regards,
Gunnar


Message 3 in thread

> moebius@xxxxxxxxxx wrote:
>
> Hi,
>
>>     public void setupModel(){
>>         String query = "SELECT * FROM auteurs ORDER BY nom_aut ASC"; //
>> basic SQL query
>>         setQuery(query);
>>         setHeaderData(0, Qt.Orientation.Horizontal, "Id");
>>         setHeaderData(1, Qt.Orientation.Horizontal, "Nom");
>>         setHeaderData(2, Qt.Orientation.Horizontal, "Prénom");
>>         setHeaderData(3, Qt.Orientation.Horizontal, "Spécialité");
>>         setHeaderData(4, Qt.Orientation.Horizontal, "Nationalité");
>>         insertColumns(5, 1, null); // I add the new column
>>         setHeaderData(5, Qt.Orientation.Horizontal, "Bibliographie");
>>     }
>
> I haven't verified this with an example so I might be wrong, but I
> believe you have a bug with how you do insertColumns.
> QAbstractTableModel at least, does not store the columnCount() so when
> you do insertColumns() and this shows up in the view may be luck more
> than a safe bet.
>
> When you insert columns into a table you should do:
>
> beginInsertColumns(...);
> insertColumns(...);
> endInsertColumns(...);
>
> This is to notify any listeners to the view that the view is changed. In
> addition to that you should reimplement the public int
> columnCount(QModelIndex) function in the baseclass to return the size of
> the querymodel + your inserted column.
>
> ---
>
> Aside from that, I'm not sure if changing the table itself is the best
> solution here. There might be some internal logic in the querymodel that
> relies consistent size between the actual database table and the
> querymodel itself. Maybe a proxy model that adds the extra column and
> looks up the bibliographie is simpler. That way you don't modify the
> database model.
>
> best regards,
> Gunnar
>

Hello !

First I would thank you for answering my question.

Unfortunately, I can't solve my problem, even with your suggestions.

Adding beginInsertColumns(...); and endInsertColumns(...); doesn't change
the way the whole thing behaves...

Futhermore I read on the reference that these functions are needed "When
reimplementing insertColumns in a subclass...", but I'm not sure I need to
reimplement insertColumns(). I don't want to change the way columns are
inserted, I just want to insert a new column...

I feel I miss something important in Model/View approach :-(

To test the proxy model approach, I wrote a (not so) small example based
on a QStandardItemModel. The model is quite simple : one column "Name",
one column "Surname", few rows... My goal is to display a "modified" model
with the two original columns plus a new "Fullname" column (Surname +
Name).

The window is split in 3 part :
 - the QTableView at the top should display the original model (2 columns)
 - the QTableView in the middle should display the "modified" model (3
columns)
 - the few widgets at the bottom should display the current row of the
"modified" model according a QDataWidgetMapper. I also add two
QToolButtons to change the current row.

Here is my code (sorry, I can't make it shorter):

package tests.proxymodel;

import com.trolltech.qt.core.QModelIndex;
import com.trolltech.qt.core.QObject;
import com.trolltech.qt.core.Qt;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QDataWidgetMapper;
import com.trolltech.qt.gui.QGridLayout;
import com.trolltech.qt.gui.QHBoxLayout;
import com.trolltech.qt.gui.QLabel;
import com.trolltech.qt.gui.QLineEdit;
import com.trolltech.qt.gui.QSortFilterProxyModel;
import com.trolltech.qt.gui.QStandardItemModel;
import com.trolltech.qt.gui.QTableView;
import com.trolltech.qt.gui.QToolButton;
import com.trolltech.qt.gui.QVBoxLayout;
import com.trolltech.qt.gui.QWidget;

public class ProxyModel extends QWidget {
	public static void main(String[] args) {

		QApplication.initialize(args);
		ProxyModel widget = new ProxyModel();
		widget.show();
		QApplication.exec();
	}

	private QStandardItemModel model;
	private MySortFilterProxyModel proxyModel;

	private QTableView sourceView;
	private QTableView proxyView;
	private QLineEdit nameEdit;
	private QLineEdit surnameEdit;
	private QLineEdit fullnameEdit;
	private QDataWidgetMapper mapper;

	public ProxyModel() {
		createsModel(this);

		proxyModel = new MySortFilterProxyModel(this);

		createsView(this);

		sourceView.setModel(model);
		proxyView.setModel(proxyModel);

		mapper = new QDataWidgetMapper();
		mapper.setModel(proxyModel);
		mapper.addMapping(nameEdit, 0);
		mapper.addMapping(surnameEdit, 1);
		mapper.addMapping(fullnameEdit, 2);
		mapper.toFirst();
	}

	private void createsModel(QObject parent) {
		model = new QStandardItemModel(3, 2, parent);
		model.setHeaderData(0, Qt.Orientation.Horizontal, "Name");
		model.setHeaderData(1, Qt.Orientation.Horizontal, "Surname");

		model.setData(model.index(0, 0), "Torvalds");
		model.setData(model.index(0, 1), "Linus");
		model.setData(model.index(1, 0), "Cox");
		model.setData(model.index(1, 1), "Alan");
		model.setData(model.index(2, 0), "Stallman");
		model.setData(model.index(2, 1), "Richard");
	}

	private void createsView(QObject parent) {
		QVBoxLayout vboxLayout = new QVBoxLayout(this);

		QLabel sourceViewLabel = new QLabel(this);
		sourceViewLabel.setText("Source View :");
		vboxLayout.addWidget(sourceViewLabel);
		sourceView = new QTableView(this);
		sourceView.setFocusPolicy(Qt.FocusPolicy.WheelFocus);
		vboxLayout.addWidget(sourceView);

		QLabel proxyViewLabel = new QLabel(this);
		proxyViewLabel.setText("Proxy View :");
		vboxLayout.addWidget(proxyViewLabel);
		proxyView = new QTableView(this);
		proxyView.setFocusPolicy(Qt.FocusPolicy.WheelFocus);
		vboxLayout.addWidget(proxyView);

		QHBoxLayout hboxLayout = new QHBoxLayout();
		QLabel mappedViewLabel = new QLabel(this);
		mappedViewLabel.setText("Mapped View :");
		QToolButton nextTB = new QToolButton(this);
		nextTB.setText(">");
		QToolButton prevTB = new QToolButton(this);
		prevTB.setText("<");
		hboxLayout.addWidget(mappedViewLabel);
		hboxLayout.addWidget(prevTB);
		hboxLayout.addWidget(nextTB);
		vboxLayout.addLayout(hboxLayout);

		QGridLayout gridLayout = new QGridLayout();
		QLabel nameLabel = new QLabel(this);
		nameLabel.setText("Name");
		nameEdit = new QLineEdit(this);
		QLabel surnameLabel = new QLabel(this);
		surnameLabel.setText("Surname");
		surnameEdit = new QLineEdit(this);
		QLabel fullnameLabel = new QLabel(this);
		fullnameLabel.setText("Fullname");
		fullnameEdit = new QLineEdit(this);
		fullnameEdit.setReadOnly(true);
		gridLayout.addWidget(nameLabel, 0, 0, 1, 1);
		gridLayout.addWidget(nameEdit, 0, 1, 1, 1);
		gridLayout.addWidget(surnameLabel, 1, 0, 1, 1);
		gridLayout.addWidget(surnameEdit, 1, 1, 1, 1);
		gridLayout.addWidget(fullnameLabel, 2, 0, 1, 1);
		gridLayout.addWidget(fullnameEdit, 2, 1, 1, 1);
		vboxLayout.addLayout(gridLayout);

		nextTB.clicked.connect(this, "next()");
		prevTB.clicked.connect(this, "prev()");
	}

	@SuppressWarnings("unused")
	private void next(){
		mapper.toNext();
	}

	@SuppressWarnings("unused")
	private void prev(){
		mapper.toPrevious();
	}

	private class MySortFilterProxyModel extends QSortFilterProxyModel {
        private MySortFilterProxyModel(QObject parent) {
            super(parent);
            setSourceModel(model);
            this.beginInsertColumns(null, 2, 2);
            this.insertColumns(model.columnCount(), 1, null);
            this.endInsertColumns();
        }

        public Object data(QModelIndex index, int role){
        	Object value = model.data(index, role);

        	if (index != null && role == Qt.ItemDataRole.DisplayRole && 
index.column() == 2 )
        		value = new String(model.data(index.row(), 1, role).toString()
+" "+ model.data(index.row(), 0, role).toString());

        	return value;
        }

		@Override
		public int columnCount(QModelIndex arg0) {
			return super.columnCount(arg0)+1;
		}
	}
}

For moment :
 - the top QTableView displays the original model, but it also displays a
third empty column :-(
 - the middle QTableView displays the right "Fullname" data in its third
column, but doesn't displays anything in the two first columns and
futhermore it displays a additional empty column too :-(
 - the bottom widgets doesn't display anything.

As you can see I'm quite far from my objective :-(

Some tests around this :
 - if I remove the columnCount function the additional column in middle
QTableView disappears.
 - if I set the original model to my mapper, bottom widgets display right
original model data. Navigation with QToolButtons is OK.

Want I want to do is not so complex, so it would be possible to be
obtained using Model/View approach but I can't manage it.

Once again any help would be helpfull...

jMax



Message 4 in thread

moebius@xxxxxxxxxx wrote:

Hi,

> For moment :
>  - the top QTableView displays the original model, but it also displays a
> third empty column :-(

I guess this teaches me to give advice without verifying it with an 
example. When calling insertColumn() on a proxy model, this is 
propegated to the source model too, so in this case you end up with 
adding an extra column to the source model.


>  - the middle QTableView displays the right "Fullname" data in its third
> column, but doesn't displays anything in the two first columns and
> futhermore it displays a additional empty column too :-(

In addition to that you add +1 column in the columnCount method which is 
added to the already +1 source model leaving you with four columns...

>  - the bottom widgets doesn't display anything.

The item role used to display text in a QTextEdit is not the displayrole 
but the EditRole, as you can see from the documentation:

http://doc.trolltech.com/qtjambi-4.3.3_01/com/trolltech/qt/core/Qt.ItemDataRole.html#EditRole

> As you can see I'm quite far from my objective :-(

Indeed, Hopefully my attached modified version of your example will 
bring you a bit closer.

---

In addition to the problem with using insertColumn() on a proxy model, I 
also noticed that the QSortFilterProxyModel actually doesn't support 
adding entries to the source model, it only provides operations on the 
existing data. This led me scrapping the ProxyModel class and simply 
implementing the proxy manually, as it was not a lot of extra code to do so.

So... I implemented rowCount() to return the source models rowCount and 
columnCount to return source +1. parent() and index() are default 
implementations, really so they can be ignored.

In the headerData() function I filter out the third column and handle it 
properly, otherwise return the source data. I did more or less the same 
in the data() function, but return the name for multiple roles, so I get 
tooltips, display in the line edit, etc.

--
 [ signature omitted ] 

Message 5 in thread

and the attachment...

import com.trolltech.qt.core.*;
import com.trolltech.qt.core.*;
import com.trolltech.qt.gui.*;

public class ProxyModel extends QWidget {

    public static void main(String[] args) {
        QApplication.initialize(args);
        ProxyModel widget = new ProxyModel();
        widget.show();
        QApplication.exec();
    }

    private QStandardItemModel model;
    private QAbstractItemModel proxyModel;

    private QTableView sourceView;
    private QTableView proxyView;
    private QLineEdit nameEdit;
    private QLineEdit surnameEdit;
    private QLineEdit fullnameEdit;
    private QDataWidgetMapper mapper;

    public ProxyModel() {
        createsModel(this);

        proxyModel = new MyProxyModel(this, model);

        createsView(this);

        sourceView.setModel(model);
        proxyView.setModel(proxyModel);

        mapper = new QDataWidgetMapper();
        mapper.setModel(proxyModel);
        mapper.addMapping(nameEdit, 0);
        mapper.addMapping(surnameEdit, 1);
        mapper.addMapping(fullnameEdit, 2);
        mapper.toFirst();
    }


    private void createsModel(QObject parent) {
        model = new QStandardItemModel(3, 2, parent);
        model.setHeaderData(0, Qt.Orientation.Horizontal, "Name");
        model.setHeaderData(1, Qt.Orientation.Horizontal, "Surname");

        model.setData(0, 0, "Torvalds");
        model.setData(0, 1, "Linus");
        model.setData(1, 0, "Cox");
        model.setData(1, 1, "Alan");
        model.setData(2, 0, "Stallman");
        model.setData(2, 1, "Richard");
    }


    private void createsView(QObject parent) {
        QVBoxLayout vboxLayout = new QVBoxLayout(this);

        QLabel sourceViewLabel = new QLabel(this);
        sourceViewLabel.setText("Source View :");
        vboxLayout.addWidget(sourceViewLabel);
        sourceView = new QTableView(this);
        sourceView.setFocusPolicy(Qt.FocusPolicy.WheelFocus);
        vboxLayout.addWidget(sourceView);

        QLabel proxyViewLabel = new QLabel(this);
        proxyViewLabel.setText("Proxy View :");
        vboxLayout.addWidget(proxyViewLabel);
        proxyView = new QTableView(this);
        proxyView.setFocusPolicy(Qt.FocusPolicy.WheelFocus);
        vboxLayout.addWidget(proxyView);

        QHBoxLayout hboxLayout = new QHBoxLayout();
        QLabel mappedViewLabel = new QLabel(this);
        mappedViewLabel.setText("Mapped View :");
        QToolButton nextTB = new QToolButton(this);
        nextTB.setText(">");
        QToolButton prevTB = new QToolButton(this);
        prevTB.setText("<");
        hboxLayout.addWidget(mappedViewLabel);
        hboxLayout.addWidget(prevTB);
        hboxLayout.addWidget(nextTB);
        vboxLayout.addLayout(hboxLayout);

        QGridLayout gridLayout = new QGridLayout();
        QLabel nameLabel = new QLabel(this);
        nameLabel.setText("Name");
        nameEdit = new QLineEdit(this);
        QLabel surnameLabel = new QLabel(this);
        surnameLabel.setText("Surname");
        surnameEdit = new QLineEdit(this);
        QLabel fullnameLabel = new QLabel(this);
        fullnameLabel.setText("Fullname");
        fullnameEdit = new QLineEdit(this);
//         fullnameEdit.setReadOnly(true);
        gridLayout.addWidget(nameLabel, 0, 0, 1, 1);
        gridLayout.addWidget(nameEdit, 0, 1, 1, 1);
        gridLayout.addWidget(surnameLabel, 1, 0, 1, 1);
        gridLayout.addWidget(surnameEdit, 1, 1, 1, 1);
        gridLayout.addWidget(fullnameLabel, 2, 0, 1, 1);
        gridLayout.addWidget(fullnameEdit, 2, 1, 1, 1);
        vboxLayout.addLayout(gridLayout);

        nextTB.clicked.connect(this, "next()");
        prevTB.clicked.connect(this, "prev()");
    }

    private void next(){
        mapper.toNext();
    }

    private void prev(){
        mapper.toPrevious();
    }


    private static class MyProxyModel extends QAbstractItemModel {

        private QAbstractItemModel model;

        private MyProxyModel(QObject parent, QAbstractItemModel src) {
            super(parent);
            model = src;
        }

        public Object data(QModelIndex index, int role) {
            if (index != null && index.column() == 2) {
                switch (role) {
                case Qt.ItemDataRole.DisplayRole:
                case Qt.ItemDataRole.EditRole:
                case Qt.ItemDataRole.ToolTipRole:
                case Qt.ItemDataRole.StatusTipRole:
                case Qt.ItemDataRole.WhatsThisRole:
                    String first = String.valueOf(model.data(index.row(), 1, role));
                    String last = String.valueOf(data(index.row(), 0, role));
                    System.out.println(" --> " + first + ", " + last);
                    return first + " " + last;
                }
            } else {
                return model.data(mapToSource(index), role);
            }

            return null;
        }

        public Object headerData(int section, Qt.Orientation orient, int role) {
            if (section == 2) {
                if (orient == Qt.Orientation.Horizontal && role == Qt.ItemDataRole.DisplayRole)
                    return "Full Name";
                if (orient == Qt.Orientation.Vertical && role == Qt.ItemDataRole.DisplayRole)
                    return String.valueOf(section + 1);
            }

            return model.headerData(section, orient, role);
        }

        private QModelIndex mapToSource(QModelIndex index) {
            if (index == null)
                return null;
            else
                return model.index(index.row(), index.column());
        }

        public QModelIndex index(int rows, int columns, QModelIndex parent) {
            return createIndex(rows, columns);
        }

        public int rowCount(QModelIndex root) {
            return model.rowCount(mapToSource(root));
        }

        public int columnCount(QModelIndex root) {
            return model.columnCount(mapToSource(root)) + 1;
        }

        public QModelIndex parent(QModelIndex parent) {
            return null;
        }
    }


}

Message 6 in thread

> moebius@xxxxxxxxxx wrote:
>
> Hi,
>
>> For moment :
>>  - the top QTableView displays the original model, but it also displays
>> a
>> third empty column :-(
>
> I guess this teaches me to give advice without verifying it with an
> example. When calling insertColumn() on a proxy model, this is
> propegated to the source model too, so in this case you end up with
> adding an extra column to the source model.
>
>
>>  - the middle QTableView displays the right "Fullname" data in its third
>> column, but doesn't displays anything in the two first columns and
>> futhermore it displays a additional empty column too :-(
>
> In addition to that you add +1 column in the columnCount method which is
> added to the already +1 source model leaving you with four columns...
>
>>  - the bottom widgets doesn't display anything.
>
> The item role used to display text in a QTextEdit is not the displayrole
> but the EditRole, as you can see from the documentation:
>
> http://doc.trolltech.com/qtjambi-4.3.3_01/com/trolltech/qt/core/Qt.ItemDataRole.html#EditRole
>
>> As you can see I'm quite far from my objective :-(
>
> Indeed, Hopefully my attached modified version of your example will
> bring you a bit closer.
>
> ---
>
> In addition to the problem with using insertColumn() on a proxy model, I
> also noticed that the QSortFilterProxyModel actually doesn't support
> adding entries to the source model, it only provides operations on the
> existing data. This led me scrapping the ProxyModel class and simply
> implementing the proxy manually, as it was not a lot of extra code to do
> so.
>
> So... I implemented rowCount() to return the source models rowCount and
> columnCount to return source +1. parent() and index() are default
> implementations, really so they can be ignored.
>
> In the headerData() function I filter out the third column and handle it
> properly, otherwise return the source data. I did more or less the same
> in the data() function, but return the name for multiple roles, so I get
> tooltips, display in the line edit, etc.
>
> --
>
> The thing that is definitly missing from my model is handling when the
> original model changes. When it does, you will get the various signals
> fired in the source model. You must connect to these and update the
> proxy properly.
>
> --
>
> I hope this brings you a bit closer.
>
> best regards,
> Gunnar
>

Gunnar, you're my hero :-)

Thank you very much !

It now works as expected... and furthermore, I learn a lot of things ! I
could test my new skills with my "real" app, including database models and
multiple views and everything is ok.

Just something I didn't understand : I don't see the difference between

model.rowCount(mapToSource(root));
and
model.rowCount();

Where is the interest of mapToSource(root) here since the model is flat ?
Did I missed something (again) ?

Anyway thanks again for your help. A lot of things are clearer for me now...

jMax


Message 7 in thread

moebius@xxxxxxxxxx wrote:

> Just something I didn't understand : I don't see the difference between
> 
> model.rowCount(mapToSource(root));
> and
> model.rowCount();
> 
> Where is the interest of mapToSource(root) here since the model is flat ?
> Did I missed something (again) ?


Hi,

Well spotted ;-)

Since the table is non-hierarchical there is no difference between using 
rowCount(null), rowCount(), or rowCount(mapToSource(root)), but in the 
chance that you would ever try this on a tree-model, I thought it best 
to be consistent and always map from proxy to source.

-
Gunnar