Summary: | Amarok crashes when working with podcasts [@ Amarok::PrettyTreeView::drawRow] | ||
---|---|---|---|
Product: | [Applications] amarok | Reporter: | Mathias Panzenböck <grosser.meister.morti> |
Component: | Playlists/Saved Playlists | Assignee: | Amarok Developers <amarok-bugs-dist> |
Status: | RESOLVED FIXED | ||
Severity: | crash | CC: | andreaswuest, bart.cerneels, dominique195, gegen.nazi, grosser.meister.morti, matej, mtorresmbr, shaddowy2, solarisx, stebe |
Priority: | NOR | Keywords: | regression |
Version: | 2.6.0 | ||
Target Milestone: | 2.8 | ||
Platform: | Fedora RPMs | ||
OS: | Linux | ||
Latest Commit: | http://commits.kde.org/amarok/d3982dc6c2fa2953c37d4864bca61e73aff19a52 | Version Fixed In: | 2.8 |
Attachments: |
New crash information added by DrKonqi
New crash information added by DrKonqi |
Description
Mathias Panzenböck
2010-09-03 18:56:34 UTC
About the speed: I noticed only one podcast feed* has this problem and it isn't amaroks fault. They embed a tiny transparent gif (webbug) which takes a second to load. It would be nice if the loading of the information would be progressive like in a real webbrowser, though. * http://feeds.feedburner.com/mtvgameone I just had the same crash, but trying to rename a folder in the Saved Playlists. I reassign this to saved playlists, as it is the same code. Using latest git with KDE 4.5.1 on Kubuntu 10.04 Can this still be reproduced? Just tried it (randomly expanding/collapsing podcast feeds combined with toggling merged view) and it crashed again (segmentation fault, for some reason no kcrashmanager). The version I use: commit f1c2dc3376a5905de6ee0f207e71bfa4b0b56022 Author: Script Kiddy <scripty@kde.org> Date: Wed Sep 8 11:12:38 2010 +0200 Yes, reproducible every time I try to rename a second folder, sometimes it also crashes at the first try. It happens in both the podcast and the saved playlist section. And same problem here, Dr. Konqi doesn't start anymore, getting this error: klauncher(18040)/kio (KLauncher): SlavePool: No communication with slave. But that could also be due to me having upgraded to KDE 4.5.1 Can I get an updated stacktrace for this crash? The code changed so I want to really be sure where it's crashing. I can't reproduce. As I said dr. konqi does not start, so I ran it using gdb. When I run backtrace there I get a never ending list of: #0 0x00007ffff71062d2 in QtGroupingProxy::parent (this=Cannot access memory at address 0x7fffff3fdff8 ) at /home/panzi/software/amarok/src/browsers/playlistbrowser/QtGroupingProxy.cpp:235 #1 0x00007ffff6e042bf in QModelIndex::parent (this=0x7fffff3fe140) at /usr/include/QtCore/qabstractitemmodel.h:389 #2 0x00007ffff7107325 in QtGroupingProxy::mapToSource (this=0x1e4b2d0, index=...) at /home/panzi/software/amarok/src/browsers/playlistbrowser/QtGroupingProxy.cpp:405 #3 0x00007ffff7107350 in QtGroupingProxy::mapToSource (this=0x1e4b2d0, index=...) at /home/panzi/software/amarok/src/browsers/playlistbrowser/QtGroupingProxy.cpp:407 ... #60156 0x00007ffff7107350 in QtGroupingProxy::mapToSource (this=0x1e4b2d0, index=...) at /home/panzi/software/amarok/src/browsers/playlistbrowser/QtGroupingProxy.cpp:407 #60157 0x00007ffff7107350 in QtGroupingProxy::mapToSource (this=0x1e4b2d0, index=...) at /home/panzi/software/amarok/src/browsers/playlistbrowser/QtGroupingProxy.cpp:407 #60158 0x00007ffff7107350 in QtGroupingProxy::mapToSource (this=0x1e4b2d0, index=...) at /home/panzi/software/amarok/src/browsers/playlistbrowser/QtGroupingProxy.cpp:407 ... It only seems to happen when I play some music during clicking stuff in the podcast view. I absolutely can't reproduce this. Is there anything special about your podcast collection or with the save playlists? Not that I'd know of. Here is the list of feeds I'm subscribed to (an export option would be nice, btw.): http://alternativlos.org/ogg.rss http://chaosradio.ccc.de/chaosradio-latest.rss http://chaosradio.ccc.de/chaosradio_express-latest.rss http://feeds.feedburner.com/mtvgameone http://static.orf.at/podcast/fm4/fm4_science_busters.xml file:///home/panzi/tmp/podcast.atom (a local test atom feed) http://community.oreilly.de/blog/feed/ http://tim.geekheim.de/feed/ http://www.zreomusic.com/feed http://static.orf.at/podcast/oe1/oe1_digitalleben.xml http://static.orf.at/podcast/oe1/oe1_wissen.xml I still use Fedora 12 (I should update, I know): Qt: 4.6.3 KDE Development Platform: 4.4.5 (KDE 4.4.5) (In reply to comment #9) > Not that I'd know of. Here is the list of feeds I'm subscribed to (an export > option would be nice, btw.): Working on OPML export in a branch for the next release. > http://alternativlos.org/ogg.rss . . . > http://static.orf.at/podcast/oe1/oe1_wissen.xml That list doesn't look spectacularly long. Do you have any sorted in folders? Is Merged view enabled when crashing, do you have any provider filtered? Please also include the output on the terminal (at least the last 1000 lines). Perhaps I can find something there. > > > I still use Fedora 12 (I should update, I know): > Qt: 4.6.3 > KDE Development Platform: 4.4.5 (KDE 4.4.5) I doubt the Qt version has anything to do with it. I use KDE 4.5.1 and Qt 4.7.0 rc1 I finally got a backtrace and found the culprit, changed the bug title accordingly: Thread 1 (Thread 0x7ffd66d48780 (LWP 10561)): [KCrash Handler] #6 QModelIndex (this=0x2f4f830, child=...) at ../../include/QtCore/../../src/corelib/kernel/qabstractitemmodel.h:65 #7 QSortFilterProxyModel::parent (this=0x2f4f830, child=...) at itemviews/qsortfilterproxymodel.cpp:1656 #8 0x00007ffd6467b553 in QModelIndex::parent (this=<value optimized out>) at kernel/qabstractitemmodel.h:389 #9 QPersistentModelIndex::parent (this=<value optimized out>) at kernel/qabstractitemmodel.cpp:347 #10 0x00007ffd655f99bf in QItemSelectionRange::parent (this=0x2f63d80, index=...) at itemviews/qitemselectionmodel.h:78 #11 QItemSelectionRange::contains (this=0x2f63d80, index=...) at itemviews/qitemselectionmodel.h:85 #12 QItemSelection::contains (this=0x2f63d80, index=...) at itemviews/qitemselectionmodel.cpp:423 #13 0x00007ffd655fb055 in QItemSelectionModel::isSelected (this=<value optimized out>, index=...) at itemviews/qitemselectionmodel.cpp:1200 #14 0x00007ffd655ee7ab in QTreeView::drawRow (this=<value optimized out>, painter=<value optimized out>, option=<value optimized out>, index=<value optimized out>) at itemviews/qtreeview.cpp:1602 #15 0x00007ffd662d94f1 in Amarok::PrettyTreeView::drawRow (this=0x2f6a640, painter=0x7fff44787b50, option=..., index=...) at /home/myriam/kde/src/amarok/src/widgets/PrettyTreeView.cpp:44 #16 0x00007ffd655e9d4a in QTreeView::drawTree (this=0x2f6a640, painter=<value optimized out>, region=<value optimized out>) at itemviews/qtreeview.cpp:1441 #17 0x00007ffd655ea813 in QTreeView::paintEvent (this=0x2f6a640, event=0x7fff447887a0) at itemviews/qtreeview.cpp:1274 #18 0x00007ffd650aed4e in QWidget::event (this=0x2f6a640, event=0x7fff447887a0) at kernel/qwidget.cpp:8304 #19 0x00007ffd65475ba6 in QFrame::event (this=0x2f6a640, e=0x7fff447887a0) at widgets/qframe.cpp:557 #20 0x00007ffd655ad85b in QAbstractItemView::viewportEvent (this=0x2f6a640, event=0x7fff447887a0) at itemviews/qabstractitemview.cpp:1619 #21 0x00007ffd655eb615 in QTreeView::viewportEvent (this=0x2f6a640, event=0x7fff447887a0) at itemviews/qtreeview.cpp:1256 #22 0x00007ffd646888d7 in QCoreApplicationPrivate::sendThroughObjectEventFilters (this=<value optimized out>, receiver=0x2f73180, event=0x7fff447887a0) at kernel/qcoreapplication.cpp:847 #23 0x00007ffd6505973c in QApplicationPrivate::notify_helper (this=0x18e5dc0, receiver=0x2f73180, e=0x7fff447887a0) at kernel/qapplication.cpp:4392 #24 0x00007ffd6505f25d in QApplication::notify (this=0x7fff4478b200, receiver=0x2f73180, e=0x7fff447887a0) at kernel/qapplication.cpp:4277 #25 0x00007ffd6685e2e6 in KApplication::notify (this=0x7fff4478b200, receiver=0x2f73180, event=0x7fff447887a0) at ../../kdeui/kernel/kapplication.cpp:310 #26 0x00007ffd646890ac in QCoreApplication::notifyInternal (this=0x7fff4478b200, receiver=0x2f73180, event=0x7fff447887a0) at kernel/qcoreapplication.cpp:732 #27 0x00007ffd650b585d in QCoreApplication::sendSpontaneousEvent (this=0x2f4b430, pdev=<value optimized out>, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=0x0, backingStore=0x2e35240) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:218 #28 QWidgetPrivate::drawWidget (this=0x2f4b430, pdev=<value optimized out>, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5391 #29 0x00007ffd650b64f8 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=0, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5598 #30 0x00007ffd650b55ba in QWidgetPrivate::drawWidget (this=0x2f56ca0, pdev=<value optimized out>, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5444 #31 0x00007ffd650b64f8 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=3, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5598 #32 0x00007ffd650b55ba in QWidgetPrivate::drawWidget (this=0x2f68f30, pdev=<value optimized out>, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5444 #33 0x00007ffd650b64f8 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=3, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5598 #34 0x00007ffd650b55ba in QWidgetPrivate::drawWidget (this=0x2df6b90, pdev=<value optimized out>, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5444 #35 0x00007ffd650b64f8 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=3, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5598 #36 0x00007ffd650b55ba in QWidgetPrivate::drawWidget (this=0x2de87a0, pdev=<value optimized out>, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5444 #37 0x00007ffd650b64f8 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=5, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5598 #38 0x00007ffd650b55ba in QWidgetPrivate::drawWidget (this=0x2dde570, pdev=<value optimized out>, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5444 #39 0x00007ffd650b64f8 in QWidgetPrivate::paintSiblingsRecursive (this=<value optimized out>, pdev=<value optimized out>, siblings=..., index=63, rgn=<value optimized out>, offset=<value optimized out>, flags=4, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5598 #40 0x00007ffd650b55ba in QWidgetPrivate::drawWidget (this=0x1e6b1f0, pdev=<value optimized out>, rgn=..., offset=<value optimized out>, flags=<value optimized out>, sharedPainter=0x0, backingStore=0x2e35240) at kernel/qwidget.cpp:5444 #41 0x00007ffd65287d88 in QWidgetBackingStore::sync (this=0x2e35240) at painting/qbackingstore.cpp:1328 #42 0x00007ffd650a8dd0 in QWidgetPrivate::syncBackingStore (this=0x1e6b1f0) at kernel/qwidget.cpp:1776 #43 0x00007ffd650af415 in QWidget::event (this=0x1e6b0a0, event=0x3448190) at kernel/qwidget.cpp:8451 #44 0x00007ffd6549187b in QMainWindow::event (this=0x1e6b0a0, event=0x3448190) at widgets/qmainwindow.cpp:1417 #45 0x00007ffd6505976c in QApplicationPrivate::notify_helper (this=0x18e5dc0, receiver=0x1e6b0a0, e=0x3448190) at kernel/qapplication.cpp:4396 #46 0x00007ffd6505f25d in QApplication::notify (this=0x7fff4478b200, receiver=0x1e6b0a0, e=0x3448190) at kernel/qapplication.cpp:4277 #47 0x00007ffd6685e2e6 in KApplication::notify (this=0x7fff4478b200, receiver=0x1e6b0a0, event=0x3448190) at ../../kdeui/kernel/kapplication.cpp:310 #48 0x00007ffd646890ac in QCoreApplication::notifyInternal (this=0x7fff4478b200, receiver=0x1e6b0a0, event=0x3448190) at kernel/qcoreapplication.cpp:732 #49 0x00007ffd6468bfd2 in QCoreApplication::sendEvent (receiver=0x0, event_type=<value optimized out>, data=0x17919f0) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:215 #50 QCoreApplicationPrivate::sendPostedEvents (receiver=0x0, event_type=<value optimized out>, data=0x17919f0) at kernel/qcoreapplication.cpp:1373 #51 0x00007ffd646b5643 in QCoreApplication::sendPostedEvents (s=0x18ee6a0) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:220 #52 postEventSourceDispatch (s=0x18ee6a0) at kernel/qeventdispatcher_glib.cpp:277 #53 0x00007ffd5e10d8c2 in g_main_context_dispatch () from /lib/libglib-2.0.so.0 #54 0x00007ffd5e111748 in ?? () from /lib/libglib-2.0.so.0 #55 0x00007ffd5e1118fc in g_main_context_iteration () from /lib/libglib-2.0.so.0 #56 0x00007ffd646b5183 in QEventDispatcherGlib::processEvents (this=0x1791140, flags=<value optimized out>) at kernel/qeventdispatcher_glib.cpp:415 #57 0x00007ffd6510b78e in QGuiEventDispatcherGlib::processEvents (this=0x7fff447871b0, flags=<value optimized out>) at kernel/qguieventdispatcher_glib.cpp:204 #58 0x00007ffd64687dd2 in QEventLoop::processEvents (this=<value optimized out>, flags=) at kernel/qeventloop.cpp:149 #59 0x00007ffd646881bc in QEventLoop::exec (this=0x7fff4478b1a0, flags=) at kernel/qeventloop.cpp:201 #60 0x00007ffd6468c26b in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1009 #61 0x000000000040aec6 in main (argc=4, argv=0x7fff4478d158) at /home/myriam/kde/src/amarok/src/main.cpp:237 Gah, strange. Now I just can't reproduce the crash myself (so I cant post the console output). I use the same build I used yesterday. Very strange. *** Bug 230447 has been marked as a duplicate of this bug. *** *** Bug 255121 has been marked as a duplicate of this bug. *** Created attachment 52959 [details]
New crash information added by DrKonqi
Yet another crash. This time it occured when I clicked "download" of an episode.
*** Bug 258772 has been marked as a duplicate of this bug. *** commit bab911e4de92d2fc42aacd0f711eb01736e32d21 branch master Author: Bart Cerneels <bart.cerneels@kde.org> Date: Sun Dec 5 17:41:55 2010 +0100 Add inserted rows without doing a buildTree(). This ensures the view is not reset when saving a playlist, etc. The same still has to be done when removing a row (playlists & podcast, for tracks it's already OK). Possibly fixes the bug in CC, but I can't reproduce. BUG:245621 CCBUG:250062 diff --git a/src/browsers/playlistbrowser/PlaylistBrowserModel.cpp b/src/browsers/playlistbrowser/PlaylistBrowserModel.cpp index 34d84d9..fd7882f 100644 --- a/src/browsers/playlistbrowser/PlaylistBrowserModel.cpp +++ b/src/browsers/playlistbrowser/PlaylistBrowserModel.cpp @@ -56,6 +56,11 @@ PlaylistBrowserModel::PlaylistBrowserModel( int playlistCategory ) connect( The::playlistManager(), SIGNAL( providerRemoved( Playlists::PlaylistProvider*, int ) ), SLOT( slotUpdate() ) ); + connect( The::playlistManager(), SIGNAL( playlistAdded( Playlists::PlaylistPtr, int ) ), + SLOT( slotPlaylistAdded( Playlists::PlaylistPtr,int ) ) ); + connect( The::playlistManager(), SIGNAL( playlistRemoved( Playlists::PlaylistPtr, int ) ), + SLOT( slotPlaylistRemoved( Playlists::PlaylistPtr,int ) ) ); + connect( The::playlistManager(), SIGNAL(renamePlaylist( Playlists::PlaylistPtr )), SLOT(slotRenamePlaylist( Playlists::PlaylistPtr )) ); @@ -574,6 +579,37 @@ PlaylistBrowserModel::slotAppend() The::playlistController()->insertOptioned( tracks, Playlist::AppendAndPlay ); } +void +PlaylistBrowserModel::slotPlaylistAdded( Playlists::PlaylistPtr playlist, int category ) +{ + //ignore playlists of a different category + if( category != m_playlistCategory ) + return; + + subscribeTo( playlist ); + int i; + for( i = 0; i < m_playlists.count(); i++ ) + { + if( lessThanPlaylistTitles( playlist, m_playlists[i] ) ) + { + m_playlists.insert( i, playlist ); + break; + } + } + if( i == m_playlists.count() ) + m_playlists.append( playlist ); + + beginInsertRows( QModelIndex(), i, i ); + endInsertRows(); +} + +void +PlaylistBrowserModel::slotPlaylistRemoved( Playlists::PlaylistPtr playlist, int category ) +{ + if( category != m_playlistCategory ) + return; +} + Meta::TrackList PlaylistBrowserModel::tracksFromIndexes( const QModelIndexList &list ) const { diff --git a/src/browsers/playlistbrowser/PlaylistBrowserModel.h b/src/browsers/playlistbrowser/PlaylistBrowserModel.h index 0f32c96..feb6551 100644 --- a/src/browsers/playlistbrowser/PlaylistBrowserModel.h +++ b/src/browsers/playlistbrowser/PlaylistBrowserModel.h @@ -107,6 +107,8 @@ class PlaylistBrowserModel : public QAbstractItemModel, private slots: void slotLoad(); void slotAppend(); + void slotPlaylistAdded( Playlists::PlaylistPtr playlist, int category ); + void slotPlaylistRemoved( Playlists::PlaylistPtr playlist, int category ); private: int m_playlistCategory; diff --git a/src/browsers/playlistbrowser/PlaylistsByProviderProxy.cpp b/src/browsers/playlistbrowser/PlaylistsByProviderProxy.cpp index 813155f..adc2ff7 100644 --- a/src/browsers/playlistbrowser/PlaylistsByProviderProxy.cpp +++ b/src/browsers/playlistbrowser/PlaylistsByProviderProxy.cpp @@ -201,7 +201,7 @@ PlaylistsByProviderProxy::dropMimeData( const QMimeData *data, Qt::DropAction ac decodeMimeRows( data->data( AMAROK_PROVIDERPROXY_INDEXES ), m_model ); //set the groupedColumn data of all playlist indexes to the data of this group //the model will understand this as a copy to the provider it's dropped on - RoleVariantMap groupData = + IndexData groupData = m_groupMaps.value( parent.row() ).value( parent.column() ); bool result = !originalIndexes.isEmpty(); foreach( const QModelIndex& originalIndex, originalIndexes ) diff --git a/src/browsers/playlistbrowser/PlaylistsInFoldersProxy.cpp b/src/browsers/playlistbrowser/PlaylistsInFoldersProxy.cpp index e81e7ce..1eaf162 100644 --- a/src/browsers/playlistbrowser/PlaylistsInFoldersProxy.cpp +++ b/src/browsers/playlistbrowser/PlaylistsInFoldersProxy.cpp @@ -324,8 +324,8 @@ PlaylistsInFoldersProxy::deleteFolder( const QModelIndex &groupIdx ) QModelIndex PlaylistsInFoldersProxy::createNewFolder( const QString &groupName ) { - ColumnVariantMap data; - RoleVariantMap roleData; + RowData data; + IndexData roleData; roleData.insert( Qt::DisplayRole, groupName ); roleData.insert( Qt::DecorationRole, QVariant( KIcon( "folder" ) ) ); roleData.insert( Qt::EditRole, groupName ); diff --git a/src/browsers/playlistbrowser/QtGroupingProxy.cpp b/src/browsers/playlistbrowser/QtGroupingProxy.cpp index 731a533..70663f1 100644 --- a/src/browsers/playlistbrowser/QtGroupingProxy.cpp +++ b/src/browsers/playlistbrowser/QtGroupingProxy.cpp @@ -54,15 +54,15 @@ QtGroupingProxy::setGroupedColumn( int groupedColumn ) buildTree(); } -QList<ColumnVariantMap> +QList<RowData> QtGroupingProxy::belongsTo( const QModelIndex &idx ) { //qDebug() << __FILE__ << __FUNCTION__; - QList<ColumnVariantMap> cvmList; + QList<RowData> rowDataList; - //get all the data we have for this index - RoleVariantMap roleVariantMap = m_model->itemData( idx ); - QMapIterator<int, QVariant> i(roleVariantMap); + //get all the data for this index from the model + IndexData indexData = m_model->itemData( idx ); + QMapIterator<int, QVariant> i( indexData ); while( i.hasNext() ) { i.next(); @@ -75,41 +75,41 @@ QtGroupingProxy::belongsTo( const QModelIndex &idx ) QVariantList list = variant.toList(); for( int i = 0; i < list.length(); i++ ) { - //take an existing CVM or create a new one - ColumnVariantMap cvm = (cvmList.count() > i) ? cvmList.takeAt( i ) - : ColumnVariantMap(); + //take an existing row data or create a new one + RowData rowData = (rowDataList.count() > i) ? rowDataList.takeAt( i ) + : RowData(); //we only gather data for the first column - RoleVariantMap rvm = cvm.contains( 0 ) ? cvm.take( 0 ) : RoleVariantMap(); - rvm.insert( role, list.value( i ) ); - cvm.insert( 0, rvm ); + IndexData indexData = rowData.contains( 0 ) ? rowData.take( 0 ) : IndexData(); + indexData.insert( role, list.value( i ) ); + rowData.insert( 0, indexData ); //for the grouped column the data should not be gathered from the children //this will allow filtering on the content of this column with a QSFP - cvm.insert( m_groupedColumn, rvm ); - cvmList.insert( i, cvm ); + rowData.insert( m_groupedColumn, indexData ); + rowDataList.insert( i, rowData ); } } else if( !variant.isNull() ) { //it's just a normal item. Copy all the data and break this loop. - ColumnVariantMap cvm; - cvm.insert( 0, roleVariantMap ); - cvmList << cvm; + RowData rowData; + rowData.insert( 0, indexData ); + rowDataList << rowData; break; } } //for normal items (not root node) an empty list here means it's supposed to go in root. - if( cvmList.isEmpty() && idx != m_rootNode ) - cvmList << ColumnVariantMap(); + if( idx != m_rootNode && rowDataList.isEmpty() ) + rowDataList << RowData(); - return cvmList; + return rowDataList; } /* m_groupHash layout * key : index of the group in m_groupMaps -* values : original row in m_model of children of this group +* value : a QList of the original rows in m_model for the children of this group * -* key = -1 contains non-grouped indexes +* key = -1 contains a QList of the non-grouped indexes * * TODO: sub-groups */ @@ -130,66 +130,104 @@ QtGroupingProxy::buildTree() m_model->index( m_rootNode.row(), m_groupedColumn, m_rootNode.parent() ); if( rootGroupedIndex.column() == m_groupedColumn ) { - QList<ColumnVariantMap> groupData = belongsTo( rootGroupedIndex ); - foreach( ColumnVariantMap cvm , groupData ) + QList<RowData> groupData = belongsTo( rootGroupedIndex ); + foreach( RowData rowData , groupData ) { - // qDebug() << cvm; - if( cvm.contains( 0 ) && cvm[0].contains( Qt::DisplayRole ) ) + // qDebug() << rowData; + if( rowData.contains( 0 ) && rowData[0].contains( Qt::DisplayRole ) ) { - QString groupName = cvm[0][Qt::DisplayRole].toString(); - // qDebug() << "Creating empty group: " << groupName; - m_groupMaps << cvm; + // qDebug() << "Creating empty group: " << rowData[0][Qt::DisplayRole].toString(); + m_groupMaps << rowData; } } } int max = m_model->rowCount( m_rootNode ); //qDebug() << QString("building tree with %1 leafs.").arg( max ); - for( int row = max-1; row >= 0; row-- ) + //WARNING: these have to be added in order because the addToGroups function is optimized for + //modelRowsInserted(). Failure to do so will result in wrong data shown in the view at best. + for( int row = 0; row < max; row++ ) { QModelIndex idx = m_model->index( row, m_groupedColumn, m_rootNode ); - QList<ColumnVariantMap> groupData = belongsTo( idx ); + addSourceRow( idx ); + } +// dumpGroups(); + + emit layoutChanged(); +} + +QList<int> +QtGroupingProxy::addSourceRow( const QModelIndex &idx ) +{ + QList<int> updatedGroups; - //an item can be in multiple groups - foreach( ColumnVariantMap data, groupData ) + QList<RowData> groupData = belongsTo( idx ); + //an item can be in multiple groups + foreach( RowData data, groupData ) + { + int groupIndex = -1; + if( !data.isEmpty() ) { - int groupIndex = -1; - if( !data.isEmpty() ) - { - QString groupName = data[0][Qt::DisplayRole].toString(); - // qDebug() << QString("index %1 belongs to group %2").arg( row ).arg( groupName ); +// qDebug() << QString("index %1 belongs to group %2").arg( row ) +// .arg( data[0][Qt::DisplayRole].toString() ); - foreach( const ColumnVariantMap &cachedData, m_groupMaps ) + foreach( const RowData &cachedData, m_groupMaps ) + { + //when this matches the index belongs to an existing group + if( data[0][Qt::DisplayRole] == cachedData[0][Qt::DisplayRole] ) { - //when this matches the index belongs to an existing group - if( data[0][Qt::DisplayRole] == cachedData[0][Qt::DisplayRole] ) - { - data = cachedData; - break; - } + data = cachedData; + break; } + } - groupIndex = m_groupMaps.indexOf( data ); - //-1 means not found - if( groupIndex == -1 ) + groupIndex = m_groupMaps.indexOf( data ); + //-1 means not found + if( groupIndex == -1 ) + { + //new groups are added to the end of the existing list + m_groupMaps << data; + groupIndex = m_groupMaps.count() - 1; + } + } + + if( !updatedGroups.contains( groupIndex ) ) + updatedGroups << groupIndex; + + //it's possible it's a new group, QHash will create it for us with this call: + m_groupHash[groupIndex]; + + //update the groupHash to the new source-model layout (one row added) + QMutableHashIterator<quint32, QList<int> > i( m_groupHash ); + while( i.hasNext() ) + { + i.next(); + QList<int> &groupList = i.value(); + int insertedProxyRow = groupList.count(); + for( ; insertedProxyRow > 0 ; insertedProxyRow-- ) + { + int &rowValue = groupList[insertedProxyRow-1]; + if( idx.row() <= rowValue ) + { + //increment the rows that come after the new row since they moved one place up. + rowValue++; + } + else { - //new groups are added to the end of the existing list - m_groupMaps << data; - groupIndex = m_groupMaps.count() - 1; + break; } } - - m_groupHash.insertMulti( groupIndex, row ); + //the row needs to be added to this group + if( i.key() == (quint32)groupIndex ) + groupList.insert( insertedProxyRow, idx.row() ); } } -// dumpGroups(); - - emit layoutChanged(); + return updatedGroups; } -/** Each Modelindex has in it's internalId an index in the parentCreateList. +/** Each ModelIndex has in it's internalId a position in the parentCreateList. * struct ParentCreate are the instructions to recreate the parent index. - * It contains the row number and the index in this list of the grandfather. + * It contains the row number and the postion in this list of the grandfather. * This function creates the ParentCreate structs and saves them in a list. */ int @@ -215,7 +253,7 @@ QtGroupingProxy::indexOfParentCreate( const QModelIndex &parent ) const QModelIndex QtGroupingProxy::index( int row, int column, const QModelIndex& parent ) const { - //qDebug() << "index requested for: (" << row << "," << column << "), " << parent; +// qDebug() << "index requested for: (" << row << "," << column << "), " << parent; if( !hasIndex(row, column, parent) ) return QModelIndex(); @@ -255,7 +293,7 @@ QtGroupingProxy::rowCount( const QModelIndex& index ) const if( !index.isValid() ) { //the number of top level groups + the number of non-grouped playlists - int rows = m_groupMaps.count() + m_groupHash.values( -1 ).count(); + int rows = m_groupMaps.count() + m_groupHash.value( -1 ).count(); //qDebug() << rows << " in root group"; return rows; } @@ -264,7 +302,7 @@ QtGroupingProxy::rowCount( const QModelIndex& index ) const if( isGroup( index ) ) { qint64 groupIndex = index.row(); - int rows = m_groupHash.count( groupIndex ); + int rows = m_groupHash.value( groupIndex ).count(); //qDebug() << rows << " in group " << m_groupMaps[groupIndex]; return rows; } @@ -305,7 +343,7 @@ QtGroupingProxy::data( const QModelIndex &index, int role ) const //map all data from children to columns of group to allow grouping one level up QVariantList variantsOfChildren; - int childCount = m_groupHash.count( row ); + int childCount = m_groupHash.value( row ).count(); if( childCount == 0 ) return QVariant(); @@ -322,7 +360,7 @@ QtGroupingProxy::data( const QModelIndex &index, int role ) const } //qDebug() << "gathered this data from children: " << variantsOfChildren; //saving in cache - RoleVariantMap roleMap = m_groupMaps[row].value( column ); + IndexData roleMap = m_groupMaps[row].value( column ); foreach( const QVariant &variant, variantsOfChildren ) { if( roleMap[ role ] != variant ) @@ -355,7 +393,7 @@ QtGroupingProxy::setData( const QModelIndex &idx, const QVariant &value, int rol if( isGroup( idx ) ) { - RoleVariantMap columnData = m_groupMaps[idx.row()][idx.column()]; + IndexData columnData = m_groupMaps[idx.row()][idx.column()]; columnData.insert( role, value ); //also set the display role if we are changing the grouped column data or the @@ -366,7 +404,7 @@ QtGroupingProxy::setData( const QModelIndex &idx, const QVariant &value, int rol m_groupMaps[idx.row()].insert( idx.column(), columnData ); int columnToChange = idx.row() != 0 ? idx.row() : m_groupedColumn; - foreach( int originalRow, m_groupHash.values( idx.row() ) ) + foreach( int originalRow, m_groupHash.value( idx.row() ) ) { QModelIndex childIdx = m_model->index( originalRow, columnToChange, m_rootNode ); @@ -413,7 +451,7 @@ QtGroupingProxy::mapToSource( const QModelIndex& index ) const if( !proxyParent.isValid() ) indexInGroup -= m_groupMaps.count(); //qDebug() << "indexInGroup" << indexInGroup; - QList<int> childRows = m_groupHash.values( proxyParent.row() ); + QList<int> childRows = m_groupHash.value( proxyParent.row() ); if( childRows.isEmpty() || indexInGroup >= childRows.count() || indexInGroup < 0 ) return QModelIndex(); @@ -455,13 +493,23 @@ QtGroupingProxy::mapFromSource( const QModelIndex &idx ) const } else { - //idx is an item of the top level of the source model (child of the rootnode) - int groupRow = m_groupHash.key( sourceRow, -1 ); + //idx is an item in the top level of the source model (child of the rootnode) + int groupRow = -1; + QHashIterator<quint32, QList<int> > iterator( m_groupHash ); + while( iterator.hasNext() ) + { + iterator.next(); + if( iterator.value().contains( sourceRow ) ) + { + groupRow = iterator.key(); + break; + } + } if( groupRow != -1 ) //it's in a group, let's find the correct row. { proxyParent = this->index( groupRow, 0, QModelIndex() ); - proxyRow = m_groupHash.values( groupRow ).indexOf( sourceRow ); + proxyRow = m_groupHash.value( groupRow ).indexOf( sourceRow ); } else { @@ -469,7 +517,7 @@ QtGroupingProxy::mapFromSource( const QModelIndex &idx ) const // if the proxy item is not in a group it will be below the groups. int groupLength = m_groupMaps.count(); //qDebug() << "groupNames length: " << groupLength; - int i = m_groupHash.values( -1 ).indexOf( sourceRow ); + int i = m_groupHash.value( -1 ).indexOf( sourceRow ); //qDebug() << "index in hash: " << i; proxyRow = groupLength + i; } @@ -493,7 +541,7 @@ QtGroupingProxy::flags( const QModelIndex &idx ) const bool groupIsEditable = true; //it's possible to have empty groups - if( m_groupHash.count( idx.row() ) == 0 ) + if( m_groupHash.value( idx.row() ).count() == 0 ) { //check the flags of this column with the root node QModelIndex originalRootNode = m_model->index( m_rootNode.row(), m_groupedColumn, @@ -502,7 +550,7 @@ QtGroupingProxy::flags( const QModelIndex &idx ) const } else { - foreach( int originalRow, m_groupHash.values( idx.row() ) ) + foreach( int originalRow, m_groupHash.value( idx.row() ) ) { QModelIndex originalIdx = m_model->index( originalRow, m_groupedColumn, m_rootNode ); @@ -564,7 +612,7 @@ QtGroupingProxy::fetchMore ( const QModelIndex & parent ) } QModelIndex -QtGroupingProxy::addEmptyGroup( const ColumnVariantMap &data ) +QtGroupingProxy::addEmptyGroup( const RowData &data ) { int newRow = m_groupMaps.count(); beginInsertRows( QModelIndex(), newRow, newRow ); @@ -595,7 +643,7 @@ QtGroupingProxy::hasChildren( const QModelIndex &parent ) const return true; if( isGroup( parent ) ) - return !m_groupHash.values( parent.row() ).isEmpty(); + return !m_groupHash.value( parent.row() ).isEmpty(); return m_model->hasChildren( mapToSource( parent ) ); } @@ -611,20 +659,46 @@ QtGroupingProxy::modelDataChanged( const QModelIndex& start, const QModelIndex& } void -QtGroupingProxy::modelRowsInserted( const QModelIndex& index, int start, int end ) +QtGroupingProxy::modelRowsInserted( const QModelIndex &parent, int start, int end ) { - Q_UNUSED( index ) - Q_UNUSED( start ) - Q_UNUSED( end ) - //TODO: see if new groups have to be created, deleted or adjusted. Try to avoid buildTree() - buildTree(); + if( parent == m_rootNode ) + { + //top level of the model changed, these new rows need to be put in groups + for( int modelRow = start; modelRow <= end ; modelRow++ ) + { + QList<int> updatedGroups; + updatedGroups << addSourceRow( m_model->index( modelRow, m_groupedColumn, m_rootNode ) ); + foreach( int groupIndex, updatedGroups ) + { + QModelIndex updatedProxyParent = ( groupIndex == -1 ) ? QModelIndex() + : index( groupIndex, 0 ); + int insertedProxyRow = m_groupHash[groupIndex].indexOf( modelRow ); + //non-grouped items are below the groups, so offset the row + if( groupIndex == -1 ) + insertedProxyRow += m_groupMaps.count(); + + beginInsertRows( updatedProxyParent, insertedProxyRow, insertedProxyRow ); + endInsertRows(); + } + } + } + else + { + //a item was added to one of the original index, remap and pass it on + QModelIndex proxyParent = mapFromSource( parent ); + qDebug() << proxyParent; + //TODO: move this to slot connected to rowsAboutToBeInserted() + beginInsertRows( proxyParent, start, end ); + endInsertRows(); + } } void -QtGroupingProxy::modelRowsRemoved( const QModelIndex &idx, int start, int end ) +QtGroupingProxy::modelRowsRemoved( const QModelIndex &parent, int start, int end ) { - QModelIndex proxyIndex = mapFromSource( idx ); - beginRemoveRows( proxyIndex, start, end ); + QModelIndex proxyParent = mapFromSource( parent ); + //TODO: move this to slot connected to rowsAboutToBeRemoved() + beginRemoveRows( proxyParent, start, end ); endRemoveRows(); } @@ -640,7 +714,7 @@ QtGroupingProxy::slotRenameGroup() const QString newName = QInputDialog::getText( 0, tr("New name"), tr("Enter a new name for a group that already exists", "Enter new group name:") ); - foreach( int originalRow, m_groupHash.values( m_selectedGroups.first().row() ) ) + foreach( int originalRow, m_groupHash.value( m_selectedGroups.first().row() ) ) { QModelIndex index = m_model->index( originalRow, 0, QModelIndex() ); QStringList groups; @@ -668,12 +742,11 @@ QtGroupingProxy::dumpGroups() const qDebug() << "m_groupHash: "; for( int groupIndex = -1; groupIndex < m_groupHash.keys().count() - 1; groupIndex++ ) { - qDebug() << groupIndex << " : " << m_groupHash.values( groupIndex ); + qDebug() << groupIndex << " : " << m_groupHash.value( groupIndex ); } qDebug() << "m_groupMaps: "; for( int groupIndex = 0; groupIndex < m_groupMaps.count(); groupIndex++ ) - qDebug() << m_groupMaps[groupIndex] << ": " << m_groupHash.values( groupIndex ); - qDebug() << m_groupHash.values( -1 ); + qDebug() << m_groupMaps[groupIndex] << ": " << m_groupHash.value( groupIndex ); + qDebug() << m_groupHash.value( -1 ); } -//#include "GroupingProxy.moc" diff --git a/src/browsers/playlistbrowser/QtGroupingProxy.h b/src/browsers/playlistbrowser/QtGroupingProxy.h index 0c0006b..b7fd9ff 100644 --- a/src/browsers/playlistbrowser/QtGroupingProxy.h +++ b/src/browsers/playlistbrowser/QtGroupingProxy.h @@ -23,8 +23,8 @@ #include <QStringList> #include <QIcon> -typedef QMap<int, QVariant> RoleVariantMap; -typedef QMap<int, RoleVariantMap> ColumnVariantMap; +typedef QMap<int, QVariant> IndexData; +typedef QMap<int, IndexData> RowData; class QtGroupingProxy : public QAbstractProxyModel @@ -57,7 +57,7 @@ class QtGroupingProxy : public QAbstractProxyModel virtual bool hasChildren( const QModelIndex &parent = QModelIndex() ) const; /* QtGroupingProxy methods */ - virtual QModelIndex addEmptyGroup( const ColumnVariantMap &data ); + virtual QModelIndex addEmptyGroup( const RowData &data ); virtual bool removeGroup( const QModelIndex &idx ); protected slots: @@ -79,18 +79,31 @@ class QtGroupingProxy : public QAbstractProxyModel * This data prepolulates the group-data cache. The rest is gathered on demand * from the children of the group. */ - virtual QList<ColumnVariantMap> belongsTo( const QModelIndex &idx ); + virtual QList<RowData> belongsTo( const QModelIndex &idx ); + + /** + * calls belongsTo(), checks cached data and adds the index to existing or new groups. + * @returns the groups this index was added to where -1 means it was added to the root. + */ + QList<int> addSourceRow( const QModelIndex &idx ); bool isGroup( const QModelIndex &index ) const; bool isAGroupSelected( const QModelIndexList& list ) const; QAbstractItemModel *m_model; - QMultiHash<quint32, int> m_groupHash; - QList<ColumnVariantMap> m_groupMaps; + /** Maintains the group -> sourcemodel row mapping + * The reason a QList<int> is use instead of a QMultiHash is that the values have to be + * reordered when new rows are inserted. + */ + QHash<quint32, QList<int> > m_groupHash; + /** The data cache of the groups. + * This can be pre-loaded with data in belongsTo() + */ + QList<RowData> m_groupMaps; /** "instuctions" how to create an item in the tree. - This is used by parent( QModelIndex ) + * This is used by parent( QModelIndex ) */ struct ParentCreate { diff --git a/src/browsers/playlistbrowser/UserPlaylistModel.cpp b/src/browsers/playlistbrowser/UserPlaylistModel.cpp index 2178d27..9f00c0c 100644 --- a/src/browsers/playlistbrowser/UserPlaylistModel.cpp +++ b/src/browsers/playlistbrowser/UserPlaylistModel.cpp @@ -184,10 +184,8 @@ PlaylistBrowserNS::UserModel::dropMimeData ( const QMimeData *data, Qt::DropActi if( playlist ) { int insertAt = (row == -1) ? playlist->tracks().count() : row; - beginInsertRows( parent, insertAt, dragList->tracks().count() ); foreach( Meta::TrackPtr track, dragList->tracks() ) playlist->addTrack( track, insertAt++ ); - endInsertRows(); } return !playlist.isNull(); } diff --git a/src/playlistmanager/PlaylistManager.cpp b/src/playlistmanager/PlaylistManager.cpp index fb13ea7..32faa30 100644 --- a/src/playlistmanager/PlaylistManager.cpp +++ b/src/playlistmanager/PlaylistManager.cpp @@ -112,6 +112,9 @@ PlaylistManager::addProvider( Playlists::PlaylistProvider *provider, int categor if( !m_providerMap.uniqueKeys().contains( category ) ) newCategory = true; + //disconnect all signals connected to this object to be sure. + provider->disconnect( this, 0 ); + m_providerMap.insert( category, provider ); connect( provider, SIGNAL(updated()), SLOT(slotUpdated())); connect( provider, SIGNAL(playlistAdded( Playlists::PlaylistPtr )), @@ -141,17 +144,22 @@ PlaylistManager::addPlaylist( Playlists::PlaylistPtr playlist, int category ) if( shouldBeSynced( playlist ) ) { SyncedPlaylistPtr syncedPlaylist = m_syncRelStore->asSyncedPlaylist( playlist ); + Playlists::PlaylistPtr syncedPlaylistPtr = + Playlists::PlaylistPtr::dynamicCast( syncedPlaylist ); m_syncedPlaylistMap.insert( syncedPlaylist, playlist ); if( !m_playlistMap.values( category ).contains( - Playlists::PlaylistPtr::dynamicCast( syncedPlaylist ) ) ) + Playlists::PlaylistPtr::dynamicCast( syncedPlaylistPtr ) ) ) { - m_playlistMap.insert( category, - Playlists::PlaylistPtr::dynamicCast( syncedPlaylist ) ); + m_playlistMap.insert( category, syncedPlaylistPtr ); + //reemit so models know about new playlist in their category + emit playlistAdded( syncedPlaylistPtr, category ); } } else { m_playlistMap.insert( category, playlist ); + //reemit so models know about new playlist in their category + emit playlistAdded( playlist, category ); } } @@ -219,7 +227,6 @@ void PlaylistManager::slotPlaylistAdded( Playlists::PlaylistPtr playlist ) { addPlaylist( playlist, playlist->provider()->category() ); - emit updated(); } void diff --git a/src/playlistmanager/PlaylistManager.h b/src/playlistmanager/PlaylistManager.h index 943fcf1..8eaa0e1 100644 --- a/src/playlistmanager/PlaylistManager.h +++ b/src/playlistmanager/PlaylistManager.h @@ -144,6 +144,8 @@ class AMAROK_EXPORT PlaylistManager : public QObject void categoryAdded( int category ); void providerAdded( Playlists::PlaylistProvider *provider, int category ); void providerRemoved( Playlists::PlaylistProvider *provider, int category ); + void playlistAdded( Playlists::PlaylistPtr playlist, int category ); + void playlistRemoved( Playlists::PlaylistPtr playlist, int category ); void renamePlaylist( Playlists::PlaylistPtr playlist ); diff --git a/src/playlistmanager/sql/SqlPlaylistGroup.h b/src/playlistmanager/sql/SqlPlaylistGroup.h index d93e683..0e68c57 100644 --- a/src/playlistmanager/sql/SqlPlaylistGroup.h +++ b/src/playlistmanager/sql/SqlPlaylistGroup.h @@ -61,6 +61,10 @@ namespace Playlists SqlPlaylistGroupList allChildGroups() const; SqlPlaylistList allChildPlaylists() const; + //transitional: this class is deprecated but we do need access to the children until + //the database changes to using labels for playlist groups. + friend class SqlUserPlaylistProvider; + private: SqlPlaylistGroupList childSqlGroups() const; SqlPlaylistList childSqlPlaylists() const; diff --git a/src/playlistmanager/sql/SqlUserPlaylistProvider.cpp b/src/playlistmanager/sql/SqlUserPlaylistProvider.cpp index a899843..f4c4262 100644 --- a/src/playlistmanager/sql/SqlUserPlaylistProvider.cpp +++ b/src/playlistmanager/sql/SqlUserPlaylistProvider.cpp @@ -261,10 +261,11 @@ SqlUserPlaylistProvider::deleteSqlPlaylists( Playlists::SqlPlaylistList playlist if( sqlPlaylist ) { debug() << "deleting " << sqlPlaylist->name(); + m_root->m_childPlaylists.removeAll( sqlPlaylist ); + emit playlistRemoved( Playlists::PlaylistPtr::dynamicCast( sqlPlaylist ) ); sqlPlaylist->removeFromDb(); } } - reloadFromDb(); return true; } @@ -287,9 +288,12 @@ SqlUserPlaylistProvider::save( const Meta::TrackList &tracks, const QString& nam Playlists::SqlPlaylistGroupPtr(), this ) ); - reloadFromDb(); + m_root->m_childPlaylists << sqlPlaylist; + Playlists::PlaylistPtr playlist = Playlists::PlaylistPtr::dynamicCast( sqlPlaylist ); + + emit playlistAdded( playlist ); - return Playlists::PlaylistPtr::dynamicCast( sqlPlaylist ); //assumes insertion in db was successful! + return playlist; //assumes insertion in db was successful! } bool diff --git a/src/playlistmanager/sql/SqlUserPlaylistProvider.h b/src/playlistmanager/sql/SqlUserPlaylistProvider.h index 3a5a62e..ee48b24 100644 --- a/src/playlistmanager/sql/SqlUserPlaylistProvider.h +++ b/src/playlistmanager/sql/SqlUserPlaylistProvider.h @@ -66,6 +66,11 @@ class AMAROK_EXPORT SqlUserPlaylistProvider : public UserPlaylistProvider static Playlists::SqlPlaylistList toSqlPlaylists( Playlists::PlaylistList playlists ); + signals: + void updated(); + void playlistAdded( Playlists::PlaylistPtr playlist ); + void playlistRemoved( Playlists::PlaylistPtr playlist ); + private slots: void slotDelete(); void slotRename(); I can't reproduce this anymore with 2.4-git. Mathias, could you test again, please? I can't reproduce the crash with current git anymore. Nice, thank you for your fast feedback. *** Bug 259301 has been marked as a duplicate of this bug. *** *** Bug 266117 has been marked as a duplicate of this bug. *** Created attachment 62258 [details]
New crash information added by DrKonqi
amarok (2.3.2) on KDE Platform 4.5.3 (KDE 4.5.3) using Qt 4.7.0
i subscribed to a podcast and after opening the local podcast list amarok crashes
-- Backtrace (Reduced):
#7 QModelIndex (this=0x8a0f778, child=...) at ../../include/QtCore/../../src/corelib/kernel/qabstractitemmodel.h:65
#8 QSortFilterProxyModel::parent (this=0x8a0f778, child=...) at itemviews/qsortfilterproxymodel.cpp:1656
#9 0x06e3d3e2 in QModelIndex::parent (this=0x8a3c718, index=...) at ../../include/QtCore/../../src/corelib/kernel/qabstractitemmodel.h:389
#10 QTreeView::indexRowSizeHint (this=0x8a3c718, index=...) at itemviews/qtreeview.cpp:2758
#11 0x06e3dc1b in QTreeViewPrivate::itemHeight (this=0x8a1e940, item=2) at itemviews/qtreeview.cpp:3229
*** Bug 289452 has been marked as a duplicate of this bug. *** Reopening based on bug 289452 Was this bug actually reproduced with 2.5? Bart: it was reproduced with 2.4.3 where it was supposed to be fixed already since version 2.4.0, reason why I reopened it and asked the reporter to test with Amarok 2.5 *** Bug 310532 has been marked as a duplicate of this bug. *** Reopening, reproducible in 2.6, see also bug 310532 While this is a nasty bug, recent efforts and Bart's commits reduced its probability, plus it hopefully no longer appears spontaneously. Additionally, I only get this crash on Amarok exit, which is not that severe IMO. Removing release_blocker so that we can release 2.7. There's also a question whether this is a regression, IMO this was just never fixed from the point it was reported. This should now be fixed, especially after these commits: http://commits.kde.org/amarok/fcb69ca30692266c6be4a8dccf26094d0962753b http://commits.kde.org/amarok/d3982dc6c2fa2953c37d4864bca61e73aff19a52 |