Results 1 to 20 of 20

Thread: one model for several viewings

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,371
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: one model for several viewings

    An example says more than a thousand words

    The first widget on the left is a view that displays the whole model so that you can see how it is structured. The second one shows only the first column of the model and the third one shows the second list of strings for the item currently selected in the previous view.

    Please note, that I restructured the model a bit to get rid of stringlists in favour of strings.
    You could simplify it even more and place the image in the first column using the decoration role (instead of display role).
    Attached Files Attached Files

  2. #2
    Join Date
    Dec 2006
    Posts
    31
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: one model for several viewings

    Thank you so much for the example. It really helped me to understand "model/view" mechanism. However, I couldn't understand the whole thing.
    I have two questions appeared while completing the task. I'd be very grateful if you could help me to understand it better.
    1.As you can see from my example, every item_1, item_2, item_3 corresponds to QImage, which has to transfer to another widget like a parameter by a click to the corresponding item in this list (in your example it is lv list). How can I get this QImage from a model by clicking to on of the strings of lv?
    2.And how, by clicking to a string in lv_2, can I get another column of this string in a model that corresponds to the string, displayed in lv_2 list?
    And one more thing, can you please show me on example how data method should look like, while creating such a model based on QAbstractItemModel?

    Thank you very much in advance! You are really helping me out.

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,371
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: one model for several viewings

    Quote Originally Posted by someralex View Post
    1.As you can see from my example, every item_1, item_2, item_3 corresponds to QImage, which has to transfer to another widget like a parameter by a click to the corresponding item in this list (in your example it is lv list). How can I get this QImage from a model by clicking to on of the strings of lv?
    Exactly the same as I "transfered" the stringlist to lv2 - when you click on an item in a view, a signal is emitted that carries a QModelIndex of the item clicked. Now you have two choices:
    1. The image is a second column of the model - in this situation you find an index which represents the second column of the same row using QModelIndex::sibling() and you query the model to return the data corresponding to the index using QAbstractItemModel::data()
    2. The image is in the same column of the model but under a different role (like Qt::DecorationRole) - in this situation you use QAbstractItemModel::data() directly, just passing Qt::DecorationRole as the role you wish to fetch.

    2.And how, by clicking to a string in lv_2, can I get another column of this string in a model that corresponds to the string, displayed in lv_2 list?
    I don't understand what exactly you want here, but the general answer is - the same as in my example - using QAbstractItemView::setRootIndex() and probably some custom slot connected to clicked() signal of the view.

    And one more thing, can you please show me on example how data method should look like, while creating such a model based on QAbstractItemModel?
    You have an example in my first post in this thread. If you want something more complex, please state what you have problems with, so that I can create an example focused on what you need.

  4. #4
    Join Date
    Dec 2006
    Posts
    31
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: one model for several viewings

    Here is my problem.

    There's a directory, for example /docs, that contains a lot of other directories - /docs/doc_1, /docs/doc_2 and so on. Every directory in /docs folder contains files, for example with .tst extension, and one of the files is an image with .jpg extension.
    There are two widgets to display the lists and one widget to display the graphical file and my class. The inner parameter to my class's constructor is the full path to the file, i.e. /docs/doc_1/file_1.tst

    I thought that it would be easier to create a model with such an inner structure:
    Qt Code:
    1. class MyModel::QAbstractTableModel{
    2. //...
    3. private:
    4. struct customType {
    5. QString first; //folder name in /doc ( doc_1, doc_2 and so on .. )
    6. QImage second; //graphical file from this folder
    7. QStringList third; // the list of .tst files in this folder (without .tst extension, i.e. file_1, file_2 and so on)
    8. QStringList fourth; // the list of full paths to these files (/doc/doc_1/file_1.tst ,/doc/doc_1/file_1.tst and so on)
    9. };
    10. QList<customType> _data;
    11. public:
    12. void init_data();
    13. };
    To copy to clipboard, switch view to plain text mode 

    and to bundle it with the corresponding views.

    So, I need to display in one QListView (lv_1) the contents of /docs folder, thus, the field first from _data (doc_1, doc_2, doc_3 and so on). By clicking on item in lv_1 in another QListView (lv_2) I need to display the list of files from corresponding directory, i.e. the list lv_2 is filled with data from _data.third , and widget for graphical file displays the image from _data.second.
    By clicking on item in lv_2 list the whole path to the file is transfered to my function, i.e. corresponding _data.fourth (for example the user clicked the second string in lv_2 - the value of _data.firth[1] is transfered to function, clicked the third string, we get _data.firth[2] and so on).

    I'd be very grateful for help in solving this problem. It would help me to understand model/view mechanism better.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,371
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: one model for several viewings

    Ok, let's focus on the model first.
    As your model is hierarchical, it makes more sense to subclass either QStandardItemModel or QAbstractItemModel than QAbstractTableModel
    Let's make it a two-level hierarchy - in the top level you'll have a list of folders in /doc and the image that goes with that folder and in the bottom level you'll have a list of files in each folder.

    In the top level you need to store two things - (1) name of the folder itself and (2) name of the image inside the folder (or the image itself, whatever you prefer).

    In the bottom level you need two another things - (1) name of the file and (2) complete path to the file.

    Note, that if you're operating on real folders and files, you don't need any custom data structures - you can use the model only as a data layer over the filesystem itself. If you're not operating on real files, then you'll need to store the data in the model.

    Qt Model/View implementation allows an item to have different roles - like the text to display, an icon, a font, colour of text, colour of background, etc. You can also add new roles - in this situation I'd suggest using Qt::DisplayRole as the name of the folder for the upper level and name of the file for lower level and adding two custom roles - ImageRole that will hold the path to the image (or the image itself, whatever you prefer) of the upper level and PathRole which will store a complete path to a file in the lower level.

    This way you'll end up with a single column model, which simplifies things a bit.

    In your situation I'd use a QStandardItemModel as there is no need to implement an own model from scratch unless you want the approach I mentioned earlier, where you only provide a wrapper over the filesystem - in such situation you don't have any benefits of using QStandardItemModel.

    Using QStandardItemModel is quite simple - you either use the item approach (QStandardItem) or the index approach (I prefer the latter). Only methods you'll need to use are index(), data(), setData(), insertRow(), insertColumn(), removeRow() and removeColumn(). Just use insertRow/Column and setData to fill your model using the roles I mentioned earlier and use data() to fetch data from the model. You have an example of using such approach in the example I provided few posts earlier.

    QStandardItemModel is the way to go in most situations if you don't feel experienced enough to implement an own model from scratch. The only thing more you can do is to subclass QStandardItemModel and extend it with some convenience methods which will call insertRow(), insertColumn() and setData() for you, for example:

    Qt Code:
    1. QModelIndex MyModel::addFolder(const QString &foldername, const QString &imagefile){
    2. int row = rowCount(); // number of folders already in the model
    3. insertRow(row); // add a new row
    4. QModelIndex ind = index(row, 0); // index of the newly created item
    5. insertColumn(0, ind); // add a column for future children of the item
    6. setData(ind, foldername, Qt::DisplayRole);
    7. setData(ind, imageFile, ImageRole); // ImageRole = Qt::UserRole
    8. setData(ind, QPixmap(rootPath+"/"+foldername+"/"+imageFile+".jpg"), ImageDataRole); // ImageDataRole = ImageRole+1; (this keeps the actual image)
    9. return ind;
    10. }
    11. QModelIndex MyModel::addFile(const QModelIndex &parent, const QString &filename){
    12. int row = rowCount(parent); // get number of files
    13. insertRow(row, parent); // insert new file
    14. QModelIndex ind = index(row, 0, parent); // get index
    15. setData(ind, filename, Qt::DisplayRole); // insert filename
    16. QString filePath = rootPath+"/"+data(parent, Qt::DisplayRole).toString()+"/"+filename+".tst"; // assemble file path
    17. setData(ind, filePath, PathRole); // PathRole = ImageDataRole+1
    18. return ind;
    19. }
    To copy to clipboard, switch view to plain text mode 
    Then you can use these like so:
    Qt Code:
    1. MyModel model(rootPath); // rootPath holds the path to the "/docs" folder
    2. QModelIndex fld = model.addFolder("doc_1", "imageInDoc1");
    3. QModelIndex fil1 = model.addFile(fld, "file_1");
    4. QModelIndex fil2 = model.addFile(fld, "file_2");
    5. QModelIndex fld2 = model.addFolder("doc_2", "imageInDoc2");
    6. // etc.
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Dec 2006
    Posts
    31
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: one model for several viewings

    9th December 2006 17:30
    wysota
    An example says more than a thousand words ;-)
    :-)

    If it is not very hard for you, could you please make the working example? I can't understand theoretically how it works, especially the mechanism with role. It would be easier to grasp the idea using the working example.

    I've made the following code:
    Qt Code:
    1. QPair<QStringList,QStringList> listFiles;
    2. QStringList listDirs;
    3.  
    4. const char * path = "/docs";
    5.  
    6. QDir dir(path);
    7. if (!dir.exists()) qFatal ("Dir not found: %s",dir.dirName());
    8. QFileInfoList fileList;
    9. QFileInfoList dirList = dir.entryInfoList(QDir::Dirs);
    10.  
    11. foreach (QFileInfo curDir, dirList){
    12. if (curDir.isDir() & curDir.baseName()!="") {
    13. QDir currentDir = curDir.absoluteFilePath();
    14. listDirs.append(currentDir.dirName());
    15. fileList = currentDir.entryInfoList(QDir::Files);
    16. foreach (QFileInfo file, fileList){
    17. listFiles.second.append(file.absoluteFilePath());
    18. listFiles.first.append(file.baseName());
    19. }
    20. }
    21. }
    To copy to clipboard, switch view to plain text mode 

    I would be very grateful for the working example.

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,371
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: one model for several viewings

    Did you go through the examples that come with Qt?

  8. #8
    Join Date
    Dec 2006
    Posts
    31
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: one model for several viewings

    I could modify the example /examples/itemview/sampletreeview to use for my own purposes, but couldn't get the role. But there you use two columns for one item, and I would like to understaned how to do it using the role.

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,371
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: one model for several viewings

    I didn't say to modify the code, but to understand it. At least one of the examples provided uses custom roles.

    I can't write the complete code for you - you won't learn this way. Besides, I have given you an almost complete solution using QStandardItemModel, what more do you need?

  10. #10
    Join Date
    Dec 2006
    Posts
    31
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: one model for several viewings

    I really can't figure it out. The deadline is coming, and I still don't get it. And it is always easier to understand something using the example. If you can, just provide the approximate code, so I could get it clear. I really need it. I'd be very grateful.
    Thank you in advance.

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,371
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: one model for several viewings

    What's wrong with my example a few posts earlier? Or with the one before? If you assemble them both, you get a complete solution for your problem. The first example shows you how to retrieve data from the standard item model and the last shows how to add data to the model. What more do you need? Just wrap the methods I have written into a complete class and you're ready to go.

  12. The following user says thank you to wysota for this useful post:

    someralex (15th December 2006)

  13. #12
    Join Date
    Dec 2006
    Posts
    31
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: one model for several viewings

    I have figured everything out! Thanks so much.
    I just read it through, studied the code, read the assistent and got it all clear.
    I have done the following methods:
    Qt Code:
    1. QModelIndex myModel::addFolder(const QDir &foldername){
    2. int row = rowCount(); // number of folders already in the model
    3. insertRow(row); // add a new row
    4. QModelIndex ind = index(row, 0); // index of the newly created item
    5. insertColumn(0, ind); // add a column for future children of the item
    6. setData(ind, foldername.dirName(), Qt::DisplayRole);
    7. return ind;
    8. }
    9.  
    10. QModelIndex myModel::addFile(const QModelIndex &parent, const QFileInfo &file){
    11. int row = rowCount(parent); // get number of files
    12. insertRow(row, parent); // insert new file
    13. QModelIndex ind = index(row, 0, parent); // get index
    14. setData(ind, file.completeBaseName(), Qt::DisplayRole); // insert filename in
    15. setData(ind, file.absoluteFilePath(), Qt::UserRole); // insert full path in Qt
    16. return ind;
    17. }
    18. QModelIndex myModel::addImage(const QModelIndex &parent, const QPixmap &image){
    19. setData(parent, image, Qt::UserRole+1);
    20. return parent;
    21. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void MainWindow::changeItemInLV2(const QModelIndex &myIndex){
    2. imageLabel->setText(myIndex.sibling(myIndex.row(),0).data(Qt::UserRole).toString());
    3. }
    To copy to clipboard, switch view to plain text mode 
    And how to create a method to get an image from Qt::UserRole+1 I can't understand.
    QVariant doesn't have toPixmap method.
    I'm asking for your help. again.
    Last edited by someralex; 15th December 2006 at 19:12.

Similar Threads

  1. Sharing Selections between Model and ProxyModel
    By mentat in forum Qt Programming
    Replies: 14
    Last Post: 27th January 2010, 17:31
  2. hierarchical model in a flat view
    By gniking in forum Qt Programming
    Replies: 4
    Last Post: 10th November 2009, 20:17
  3. Modify model data in QTreeView
    By YuriyRusinov in forum Qt Programming
    Replies: 6
    Last Post: 26th October 2006, 17:28
  4. Model sorting vs. selection
    By VlJE in forum Qt Programming
    Replies: 2
    Last Post: 25th October 2006, 16:46
  5. Table model / view editing issue
    By Caius Aérobus in forum Qt Programming
    Replies: 9
    Last Post: 7th April 2006, 11:03

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.