File indexing completed on 2024-05-05 04:48:35
0001 /**************************************************************************************** 0002 * Copyright (c) 2010 Sergey Ivanov <123kash@gmail.com> * 0003 * Copyright (c) 2013 Alberto Villa <avilla@FreeBSD.org> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify it under * 0006 * the terms of the GNU General Public License as published by the Free Software * 0007 * Foundation; either version 2 of the License, or (at your option) any later * 0008 * version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0011 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0012 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0013 * * 0014 * You should have received a copy of the GNU General Public License along with * 0015 * this program. If not, see <http://www.gnu.org/licenses/>. * 0016 ****************************************************************************************/ 0017 0018 #define DEBUG_PREFIX "MusicBrainzTagsView" 0019 0020 #include "MusicBrainzTagsView.h" 0021 0022 #include "core/support/Debug.h" 0023 #include "MusicBrainzTagsModel.h" 0024 0025 #include <KActionMenu> 0026 #include <KLocalizedString> 0027 #include <QStandardPaths> 0028 0029 #include <QContextMenuEvent> 0030 #include <QDesktopServices> 0031 #include <QMenu> 0032 #include <QSortFilterProxyModel> 0033 #include <QUrl> 0034 0035 MusicBrainzTagsView::MusicBrainzTagsView( QWidget *parent ) 0036 : QTreeView( parent ) 0037 { 0038 m_artistIcon = QIcon::fromTheme( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/mb_aicon.png" ) ); 0039 m_releaseIcon = QIcon::fromTheme( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/mb_licon.png" ) ); 0040 m_trackIcon = QIcon::fromTheme( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/mb_ticon.png" ) ); 0041 } 0042 0043 MusicBrainzTagsModel * 0044 MusicBrainzTagsView::sourceModel() const 0045 { 0046 QSortFilterProxyModel *model = qobject_cast<QSortFilterProxyModel *>( this->model() ); 0047 if( !model ) 0048 return nullptr; 0049 0050 MusicBrainzTagsModel *sourceModel = qobject_cast<MusicBrainzTagsModel *>( model->sourceModel() ); 0051 return sourceModel; 0052 } 0053 0054 void 0055 MusicBrainzTagsView::contextMenuEvent( QContextMenuEvent *event ) 0056 { 0057 QModelIndex index = indexAt( event->pos() ); 0058 if( !index.isValid() || !index.internalPointer() ) 0059 { 0060 event->ignore(); 0061 return; 0062 } 0063 0064 QAbstractItemModel *model = this->model(); 0065 if( !model ) 0066 return; 0067 0068 if( ~index.flags() & Qt::ItemIsUserCheckable ) 0069 { 0070 event->ignore(); 0071 return; 0072 } 0073 0074 QMenu *menu = new QMenu( this ); 0075 QList<QAction *> actions; 0076 0077 if( model->rowCount() > 1 && !index.data( MusicBrainzTagsModel::ReleasesRole ).isNull() ) 0078 { 0079 QAction *action = new QAction( QIcon::fromTheme( "filename-album-amarok" ), 0080 i18n( "Choose Best Matches from This Album" ), menu ); 0081 connect( action, &QAction::triggered, this, &MusicBrainzTagsView::chooseBestMatchesFromRelease ); 0082 menu->addAction( action ); 0083 menu->addSeparator(); 0084 } 0085 0086 QVariantMap artists; 0087 if( !index.data( MusicBrainzTagsModel::ArtistsRole ).toList().isEmpty() ) 0088 artists = index.data( MusicBrainzTagsModel::ArtistsRole ).toList().first().toMap(); 0089 if( !artists.isEmpty() ) 0090 { 0091 KActionMenu *action = new KActionMenu( m_artistIcon, i18n( "Go to Artist Page" ), menu ); 0092 if( artists.size() > 1 ) 0093 { 0094 foreach( const QVariant &id, artists.keys() ) 0095 { 0096 QAction *subAction = new QAction( artists.value( id.toString() ).toString(), action ); 0097 subAction->setData( id ); 0098 connect( subAction, &QAction::triggered, this, &MusicBrainzTagsView::openArtistPage ); 0099 action->addAction( subAction ); 0100 } 0101 } 0102 else 0103 { 0104 action->setData( artists.keys().first() ); 0105 connect( action, &QAction::triggered, this, &MusicBrainzTagsView::openArtistPage ); 0106 } 0107 actions << action; 0108 } 0109 0110 if( !index.data( MusicBrainzTagsModel::ReleasesRole ).toList().isEmpty() ) 0111 { 0112 QAction *action = new QAction( m_releaseIcon, i18n( "Go to Album Page" ), menu ); 0113 connect( action, &QAction::triggered, this, &MusicBrainzTagsView::openReleasePage ); 0114 actions << action; 0115 } 0116 0117 if( !index.data( MusicBrainzTagsModel::TracksRole ).toList().isEmpty() ) 0118 { 0119 QAction *action = new QAction( m_trackIcon, i18n( "Go to Track Page" ), menu ); 0120 connect( action, &QAction::triggered, this, &MusicBrainzTagsView::openTrackPage ); 0121 actions << action; 0122 } 0123 0124 if( actions.isEmpty() ) 0125 { 0126 delete menu; 0127 event->ignore(); 0128 return; 0129 } 0130 0131 menu->addActions( actions ); 0132 menu->exec( event->globalPos() ); 0133 event->accept(); 0134 delete menu; 0135 } 0136 0137 void 0138 MusicBrainzTagsView::collapseChosen() 0139 { 0140 QAbstractItemModel *model = this->model(); 0141 if( !model ) 0142 return; 0143 0144 for( int i = 0; i < model->rowCount(); i++ ) 0145 { 0146 QModelIndex index = model->index( i, 0 ); 0147 if( index.isValid() && 0148 index.data( MusicBrainzTagsModel::ChosenStateRole ) == MusicBrainzTagsModel::Chosen ) 0149 collapse( index ); 0150 } 0151 } 0152 0153 void 0154 MusicBrainzTagsView::expandUnchosen() 0155 { 0156 QAbstractItemModel *model = this->model(); 0157 if( !model ) 0158 return; 0159 0160 for( int i = 0; i < model->rowCount(); i++ ) 0161 { 0162 QModelIndex index = model->index( i, 0 ); 0163 if( index.isValid() && 0164 index.data( MusicBrainzTagsModel::ChosenStateRole ) == MusicBrainzTagsModel::Unchosen ) 0165 expand( index ); 0166 } 0167 } 0168 0169 void 0170 MusicBrainzTagsView::chooseBestMatchesFromRelease() const 0171 { 0172 QModelIndex index = selectedIndexes().first(); 0173 if( !index.isValid() || !index.internalPointer() ) 0174 return; 0175 0176 MusicBrainzTagsModel *sourceModel = this->sourceModel(); 0177 if( !sourceModel ) 0178 return; 0179 0180 QStringList releases = index.data( MusicBrainzTagsModel::ReleasesRole ).toStringList(); 0181 if( releases.isEmpty() ) 0182 return; 0183 0184 sourceModel->chooseBestMatchesFromRelease( releases ); 0185 } 0186 0187 void 0188 MusicBrainzTagsView::openArtistPage() const 0189 { 0190 QModelIndex index = selectedIndexes().first(); 0191 if( !index.isValid() || !index.internalPointer() ) 0192 return; 0193 0194 QAction *action = qobject_cast<QAction *>( sender() ); 0195 if( !action ) 0196 return; 0197 0198 QString artistID = action->data().toString(); 0199 if( artistID.isEmpty() ) 0200 return; 0201 0202 QString url = QString( "http://musicbrainz.org/artist/%1.html" ).arg( artistID ); 0203 0204 QDesktopServices::openUrl( QUrl::fromUserInput(url) ); 0205 } 0206 0207 void 0208 MusicBrainzTagsView::openReleasePage() const 0209 { 0210 QModelIndex index = selectedIndexes().first(); 0211 if( !index.isValid() || !index.internalPointer() ) 0212 return; 0213 0214 QString releaseID = index.data( MusicBrainzTagsModel::ReleasesRole ).toStringList().first(); 0215 if( releaseID.isEmpty() ) 0216 return; 0217 0218 QString url = QString( "http://musicbrainz.org/release/%1.html" ).arg( releaseID ); 0219 0220 QDesktopServices::openUrl( QUrl::fromUserInput(url) ); 0221 } 0222 0223 void 0224 MusicBrainzTagsView::openTrackPage() const 0225 { 0226 QModelIndex index = selectedIndexes().first(); 0227 if( !index.isValid() || !index.internalPointer() ) 0228 return; 0229 0230 QString trackID = index.data( MusicBrainzTagsModel::TracksRole ).toStringList().first(); 0231 if( trackID.isEmpty() ) 0232 return; 0233 0234 QString url = QString( "http://musicbrainz.org/recording/%1.html" ).arg( trackID ); 0235 0236 QDesktopServices::openUrl( QUrl::fromUserInput(url) ); 0237 } 0238