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