Results 1 to 4 of 4

Thread: QAbstractItemModel Subclass duplicate entries

  1. #1
    Join Date
    Jun 2008
    Location
    The Netherlands
    Posts
    8
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default QAbstractItemModel Subclass duplicate entries

    Hello people,

    I've successfully subclassed QAbstractItemModel to fit my needs. It acts as a frontend for the ls command. Ls feeds output in the following form to my model:
    ./parentfolder:
    subfolder1/
    subfolder2/

    ./parentfolder/subfolder1:
    dir/
    dir2/
    textfile.txt

    ./parentfolder/subfolder1/dir:

    ./parentfolder/subfolder1/dir2:

    ./parentfolder/subfolder2:
    textfile1.txt
    textfile2.txt
    textfile3.txt
    And displays it like in the attached image.
    The only thing I can't get fixed is the multiple occurence of parents. I've been struggeling with it the whole day so I hope someone with a fresh mind can see what's wrong with my code:

    Qt Code:
    1. void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
    2. {
    3. QList<TreeItem*> parents;
    4. QList<int> indentations;
    5. parents << parent;
    6. indentations << 0;
    7.  
    8. for( int r=0; r<lines.count(); r++ ) {
    9. QString lineData = lines[r].trimmed();
    10.  
    11. if (!lineData.isEmpty()) {
    12. qDebug() << QString(lineData) << "\n";
    13.  
    14. // Line is a dir
    15. if (lineData.endsWith(":")) {
    16. // Get rid of the colon
    17. lineData.chop(1);
    18.  
    19. // Check if the string is a dot from the beginning of the ls output
    20. if (lineData == ".") {
    21. // Get rid of the string
    22. lineData.clear();
    23. }
    24.  
    25. // Check if the line starts with a dot and get rid of it before we replace the backslashes
    26. if (lineData.startsWith("./")) {
    27. lineData.replace(QString("./"), QString("/"));
    28. }
    29. qDebug() << lineData;
    30.  
    31. QStringList list = lineData.split("/", QString::SkipEmptyParts);
    32. qDebug() << list << "start appending parent/child shit \n ";
    33.  
    34. // Reset the parent FIXME: horrible method
    35. parents << parents.first();
    36. for(int p = 0; p < list.size(); p++) {
    37.  
    38. QList<QVariant> column;
    39. column << list[p];
    40.  
    41. parents.last()->appendChild(new TreeItem(column, parents.last()));
    42. parents << parents.last()->child(parents.last()->childCount()-1);
    43. }
    44.  
    45. } else if (lineData.endsWith("/")) {
    46. qDebug() << "is a directory conjo!!!" << lineData << "\n";
    47. } else {
    48. QList<QVariant> column;
    49. column << lineData;
    50.  
    51. parents.last()->appendChild(new TreeItem(column, parents.last()));
    52. qDebug() << "appended file: " << lineData << "\n";
    53. }
    54. }
    55. }
    56. }
    To copy to clipboard, switch view to plain text mode 

    So, in short: I need my QAbstractItemModel to treat items with the same name under the same parent as one item, and not as duplicates.

    Thanks in advance,
    pvdk
    Attached Images Attached Images

  2. #2
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QAbstractItemModel Subclass duplicate entries

    You have to remember the last parent chain.
    If the next directory chain (your list in line 31) shares a common prefix with the last line you parsed, then remove only all those parents that do not match.

    Example:
    Qt Code:
    1. path list parents
    2. /a/b/c/d -> [a,b,c,d] [p1, p2, p3, p4]
    3. /a/b/e -> [a,b,e]
    To copy to clipboard, switch view to plain text mode 
    Then you reduce parents to [p1, p2] and insert your new item under that chain.
    You must not create a new parent chain all over for each line you parse.


    Note: this algorithm assumes that the lines are sorted properly, which they should be in your case.

    HTH

    PS: I did not quite see where you "clear" your parent list.
    Line 35 is beyond my understanding, too. Looks strange to me.
    (I did not study your code in detail, sorry.)

  3. The following user says thank you to caduel for this useful post:

    pvdk (14th July 2008)

  4. #3
    Join Date
    Jun 2008
    Location
    The Netherlands
    Posts
    8
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QAbstractItemModel Subclass duplicate entries

    Hello caduel,

    First of all hanks for your quick reply. I reply now because I was on vacation. Your suggestion put me on the right track but I still can't get it to work right. Could you explain your suggestion with a little more detail, maybe with code examples? As for your PS: that line is in there because it gave me the idea it worked a bit, but it should be replaced/removed with something better.

    Thanks alot!

    Regards,
    pvdk

  5. #4
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QAbstractItemModel Subclass duplicate entries

    basically, replace
    Qt Code:
    1. // Reset the parent FIXME: horrible method
    2. parents << parents.first();
    3. for(int p = 0; p < list.size(); p++) {
    4. QList<QVariant> column;
    5. column << list[p];
    6.  
    7. parents.last()->appendChild(new TreeItem(column, parents.last()));
    8. parents << parents.last()->child(parents.last()->childCount()-1);
    9. }
    To copy to clipboard, switch view to plain text mode 

    by

    Qt Code:
    1. // store last parent directory chain in a QStringList
    2. // add at [B]top[/B] of your function
    3. QStringList lLastDirChain;
    4.  
    5. ...
    6.  
    7. // and then replace the code above by
    8. QStringList common = common_prefix(lLastDirChain, list);
    9. // remove the un-common dirs from parents
    10. while (parents.count()>common.count()) parents.pop_back();
    11.  
    12. // now parents should be the common ones:
    13. for(int p=common.count(); p<list.size(); ++p) {
    14. QList<QVariant> column;
    15. column << list[p];
    16. TreeItem * const item = new TreeItem(column, parents.last());
    17. parents.last()->appendChild(item);
    18. parents << item;
    19. }
    20.  
    21. lLastDirChain = list;
    To copy to clipboard, switch view to plain text mode 

    untested, probably does not compile. hopefully still helpful.

    PS: use ++p instead of p++ (at least when free standing); faster for iterators.

    PPS: common_prefix could be implemented as
    Qt Code:
    1. static QStringList common_prefix(const QStringList &lhs, const QStringList &rhs)
    2. {
    3. int minlen = qMin(lhs.count(), rhs.count());
    4. for (int i=0; i<minlen; ++i)
    5. {
    6. if (lhs[i]==rhs[i])
    7. res << lhs[i];
    8. else break;
    9. }
    10. return res;
    11. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. QAbstractItemModel subclass for a treeview
    By pvdk in forum Qt Programming
    Replies: 2
    Last Post: 25th June 2008, 00:13
  2. Replies: 1
    Last Post: 2nd February 2007, 08:42

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.