Results 1 to 9 of 9

Thread: Odd behavior when populating a Table

  1. #1
    Join Date
    Apr 2011
    Posts
    8
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Odd behavior when populating a Table

    Hi there, I guess this marks my first post here. I've been going at my own pace with Qt for a few weeks (and I have to say it's got to be my favorite Application development library of all time!)

    Anyway, since I'm a big music person, I have a good lot of files with different naming conventions and such, so I thought it would be cool to apply my skills as a programmer and write a simple batch music file renamer as my first independent Qt app. I have made some surprising progress in the first day, I have been able to specify a folder, and populate a table with the files in that folder (even being able to filter out to specific filetypes!) I know it must sound boring to you guys, but as a programmer who's spent most of his time with more realtime application development (games and such), I think it's just magical.

    I know my title states "Odd behavior," but in actual fact it's probably something so simple that I've overlooked and need a good bonk over the head for, but anyway, before I populate my table, all I have are three columns "File Name" (I'm still looking for a way to make this column non-editable), "Song Title" and "Song Number." The idea is that you're supposed load a folder (this is assuming you dont have all your mp3's in one folder, but rather separate them into separate folders by artist, album, whatever like myself), and then set some Global fields (artist name, album title, etc), then you can go into the local fields and set them yourself (or I could try to develop an algorithm to do it for you if I ever are smart to do that enough), then hit the rename button and its all done for you.

    Before I load in a folder, my application looks like this:



    And after I load in say Aerosmith's Ultimate Hits CD1:



    As you can see, the Column names have been replaced by numbers. Now I think the solution to this is probably very simple (problems like these usually are), but I cant for the life of me think of what is going on...

    Also the obligatory source code:

    Qt Code:
    1. void BatchRenamer::populateTable( QString folderName )
    2. {
    3. // no need to validate folderName because it's already done in openFolder()
    4. QDir activeDirectory( folderName );
    5. QStringList fileList = activeDirectory.entryList( QStringList() << "*.mp3" << "*.wma", QDir::Files );
    6.  
    7. // clear the current file list before doing anything
    8. ui.tblFiles->clear();
    9. if ( !oldFileList.isEmpty() )
    10. {
    11. for ( int i = 0 ; i < oldFileList.size() ; i++ )
    12. {
    13. ui.tblFiles->removeRow(i);
    14. ui.tblFiles->hideRow(i);
    15. }
    16. }
    17.  
    18.  
    19. for ( int i = 0; i < fileList.size() ; i++ )
    20. {
    21. QTableWidgetItem* item = new QTableWidgetItem( fileList.at(i));
    22. ui.tblFiles->insertRow(i);
    23. ui.tblFiles->setItem(i, 0, item);
    24. ui.tblFiles->showRow(i);
    25. }
    26.  
    27. oldFileList = fileList;
    28. }
    To copy to clipboard, switch view to plain text mode 

    And the method that calls populateTable(), which itself is called by a connection of the Find folder button clicked signal:
    Qt Code:
    1. void BatchRenamer::openFolder()
    2. {
    3. QString folderName = QFileDialog::getExistingDirectory( this, "Select Media Folder" );
    4.  
    5. if( !folderName.isEmpty() )
    6. {
    7. ui.ledSelectedFolder->setText(folderName);
    8. populateTable( folderName );
    9. }
    10. }
    To copy to clipboard, switch view to plain text mode 

    Thank you for your time. I would really appreciate instead of someone posting the code saying this works: go, take the time and explain to me why it's doing what it's doing and how I can go about fixing it. Of course, you dont have to though.

    tl;dr:
    When I populate my table, the column names get replaced with numbers.
    Last edited by Kyle_Katarn; 5th April 2011 at 18:26. Reason: spelling corrections

  2. #2
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Odd behavior when populating a Table

    Hi Kyle!

    Welcome! That's a very nice first post! You put a lot of effort into it!

    But as you suspected the solution to your problem is very simple: There is a difference between clear() and clearContents() ! The former clears all header-cells too! The later doesn't!

    To make the fileName items readonly you will have to remove the Qt::ItemIsEditable. That should work like this:

    Qt Code:
    1. QTableWidgetItem* item = new QTableWidgetItem( fileList.at(i));
    2. item->setFlags(item->flags() & ~Qt::ItemIsEditable);
    To copy to clipboard, switch view to plain text mode 
    I also would like to point out, that it is much faster to set the rowCount at once instead of removing and adding each row one by one:

    Qt Code:
    1. ui.tblFiles->setRowCount(fileList.size());
    To copy to clipboard, switch view to plain text mode 
    HIH

    Johannes
    Last edited by JohannesMunk; 5th April 2011 at 22:41.

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

    Kyle_Katarn (6th April 2011)

  4. #3
    Join Date
    Apr 2011
    Posts
    8
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Odd behavior when populating a Table

    Haha, well that's the thing about first impressions, you only get to make one (well, with a single account anyway). And D'oh! I cant believe I missed the clearContents() function! I stared at the QTableWidget documentation for at least half an hour! Must have had something to do with it being nearly 3am when I posted the topic... Anyway, thanks a bunch for your help, it all worked exactly as I wanted it to!

    Thanks again,
    Kyle

  5. #4
    Join Date
    Apr 2011
    Posts
    8
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Odd behavior when populating a Table

    I seem to have hit another snag, this time to do with the connections of the tables Cells. im trying to set up a connection with the hopes of each time a cell is clicked on (or navigated to via the arrow keys), so I'm guessing a cellPressed(int, int) would be suitable, although Qt doesn't seem to think so...

    When I run the program, the list populates properly, but when I click on a cell, regardless on if it's empty or not (which when it first loads up, it is empty), it will throw an unhandled exception:

    Unhandled exception at 0x657d748c (QtGuid4.dll) in BatchRenamer.exe: 0xC0000005: Access violation reading location 0x00000000.
    Then it will throw me out at line 108 in qtablewidget.h
    Qt Code:
    1. inline QString text() const
    2. { return data(Qt::DisplayRole).toString(); }
    To copy to clipboard, switch view to plain text mode 

    Now if I had to guess, it would be due to the fact that there's nothing in the cell, probably not even an empty string, but I'm not too sure how I can handle and catch this exception.

    Here's the code that sets up the connection:
    Qt Code:
    1. void BatchRenamer::populateTable( QString folderName )
    2. {
    3.  
    4. // no need to validate folderName because it's already done in openFolder()
    5. QDir activeDirectory( folderName );
    6. QStringList fileList = activeDirectory.entryList( QStringList() << "*.mp3" << "*.wma", QDir::Files );
    7.  
    8. // clear the current file list before doing anything
    9. ui.tblFiles->clearContents();
    10. disconnect( ui.tblFiles );
    11. if ( !oldFileList.isEmpty() )
    12. {
    13. for ( int i = 0 ; i < oldFileList.size() ; i++ )
    14. {
    15. ui.tblFiles->removeRow(i);
    16. ui.tblFiles->hideRow(i);
    17. }
    18. }
    19.  
    20. if ( !fileList.isEmpty() )
    21. {
    22. for ( int i = 0; i < fileList.size() ; i++ )
    23. {
    24. QTableWidgetItem* item = new QTableWidgetItem( fileList.at(i) );
    25. // make the items in the first column read only
    26. item->setFlags(item->flags() & ~Qt::ItemIsEditable);
    27.  
    28. ui.tblFiles->setRowCount( fileList.count() );
    29. ui.tblFiles->setItem( i, 0, item );
    30. ui.tblFiles->showRow( i );
    31.  
    32. }
    33. }
    34. ui.tblFiles->resizeColumnToContents( 0 );
    35. oldFileList = fileList;
    36.  
    37. // hook up the newly made table entries
    38. connect( ui.tblFiles, SIGNAL( cellChanged(int, int)), this, SLOT( changeLocalSongData( int, int )));
    39. connect( ui.tblFiles, SIGNAL( cellPressed(int, int)), this, SLOT( changeLocalSongData( int, int )));
    40. }
    To copy to clipboard, switch view to plain text mode 

    Here's the changeLocalSongData(int,int) code
    Qt Code:
    1. void BatchRenamer::changeLocalSongData( int row, int column )
    2. {
    3. if( column == 1)
    4. {
    5. songName = ui.tblFiles->item(row, column)->text();
    6. updatePreview();
    7. }
    8. }
    To copy to clipboard, switch view to plain text mode 

    And it may be pointless to do so, but here's the updatePreview() function (all this is really to display some hidden information down the bottom of the window (under the "Preview:" label in the screenshot above).
    Qt Code:
    1. void BatchRenamer::updatePreview()
    2. {
    3. QString previewText = "\t";
    4.  
    5. if ( artistName != "")
    6. {
    7. previewText += artistName;
    8. }
    9. if (albumTitle != "")
    10. {
    11. previewText += spacer + albumTitle;
    12. }
    13. if (songName != "")
    14. {
    15. previewText += spacer + songName;
    16. }
    17.  
    18. ui.lblPreviewFileName->setText( previewText );
    19. }
    To copy to clipboard, switch view to plain text mode 

    I've already tried catching the exception and handling it in the changeLocalSongData() function via this code:
    Qt Code:
    1. if (ui.tblFiles->item(row,column)->text() != "")
    2. {
    3. songName = ui.tblFiles->item(row, column)->text();
    4. updatePreview();
    5. }
    6. else
    7. ui.tblFiles->item(row,column)->setText("");
    To copy to clipboard, switch view to plain text mode 
    I have no doubt that this is a PEBKAC (problem existing between keyboard and char) error.

    I would appreciate any help.

    Thanks in advance.

    P.S. If I comment out the connection to cellPressed(), the cellChanged connection will work without a hitch.

  6. #5
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Odd behavior when populating a Table

    Hi Kyle!

    First of all, you did not quite get the part with the setRowCount. You don't need to set it in each iteration of your loop, but only once outside:

    Qt Code:
    1. void BatchRenamer::populateTable( QString folderName )
    2. {
    3. // no need to validate folderName because it's already done in openFolder()
    4. QDir activeDirectory( folderName );
    5. QStringList fileList = activeDirectory.entryList( QStringList() << "*.mp3" << "*.wma", QDir::Files );
    6. // clear the current file list before doing anything
    7. ui.tblFiles->clearContents();
    8.  
    9. ui.tblFiles->setRowCount( fileList.count() );
    10. // if ( !fileList.isEmpty() )
    11. // check not necessary because the for loop will not start, when fileList.size() is 0.
    12.  
    13. for ( int i = 0; i < fileList.size() ; i++ )
    14. {
    15. QTableWidgetItem* item = new QTableWidgetItem( fileList.at(i) );
    16. // make the items in the first column read only
    17. item->setFlags(item->flags() & ~Qt::ItemIsEditable);
    18. ui.tblFiles->setItem( i, 0, item );
    19. }
    20. ui.tblFiles->resizeColumnToContents( 0 );
    21. oldFileList = fileList; }
    To copy to clipboard, switch view to plain text mode 
    BTW: QList::count(), QList::size(), QList::length() are all the same, but you should probably decide which one you prefer and then use that one consistently.

    Now for your connection problem!

    Do not setup the connection each time your list is updated but rather in the constructor of your mainwindow. The connection is stored between the tblFiles object and your this-object. Not for individual items.

    Qt Code:
    1. BatchRenamer::BatchRenamer()
    2. {
    3. ....
    4. // hook up the table
    5. connect( ui.tblFiles, SIGNAL( cellChanged(int, int)), this, SLOT( changeLocalSongData( int, int )));
    6. connect( ui.tblFiles, SIGNAL( cellPressed(int, int)), this, SLOT( changeLocalSongData( int, int )));
    7. ...
    8. }
    To copy to clipboard, switch view to plain text mode 
    The access violation happens, because the row and col parameter point to a non existing item. thus ui.tblFiles->item(row,col) returns 0. If you want to check against that, don't check the text for beeing empty but for item returning 0. Your check throws an access violation, because in accessing text() you are trying to derefer a pointer to an object, that points to 0 instead to a valid object.

    And all that happens, because you did not create items for the other columns I guess.

    Johannes
    Last edited by JohannesMunk; 6th April 2011 at 10:10.

  7. The following user says thank you to JohannesMunk for this useful post:

    Kyle_Katarn (6th April 2011)

  8. #6
    Join Date
    Apr 2011
    Posts
    8
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Odd behavior when populating a Table

    Dude, you're awesome! Thanks again for the very informative post. I've managed to get everything once again working the way I want it to, thanks to you. =P

    Thanks again!

  9. #7
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Odd behavior when populating a Table

    You are welcome!

    Joh

  10. #8
    Join Date
    Apr 2011
    Posts
    8
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Odd behavior when populating a Table

    Sorry if this is considered a bump, but I want to say that my program is currently working exactly as I want it to (that is, it actually renames stuff!)

    Thanks for all the help.

  11. #9
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Odd behavior when populating a Table

    :-> That's good news!

    I think a bump is only when you are desparately fishing for an answer..

    Best of luck for your next projects,

    Joh

Similar Threads

  1. Querying a database and populating a combobox
    By Splatify in forum Newbie
    Replies: 7
    Last Post: 21st February 2011, 11:28
  2. Populating, signals and comboboxes
    By ShamusVW in forum Newbie
    Replies: 6
    Last Post: 12th August 2010, 06:43
  3. Replies: 3
    Last Post: 8th December 2009, 10:49
  4. Error when populating lazily QListView
    By Bakuriu in forum Qt Programming
    Replies: 2
    Last Post: 29th October 2009, 11:56
  5. QTableView populating question
    By onefootswill in forum Newbie
    Replies: 8
    Last Post: 7th August 2008, 22:29

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.