File indexing completed on 2024-05-19 04:48:45
0001 /**************************************************************************************** 0002 * Copyright (c) 2012 Matěj Laitl <matej@laitl.cz> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #include "MetadataConfig.h" 0018 0019 #include "amarokconfig.h" 0020 #include "configdialog/ConfigDialog.h" 0021 #include "configdialog/dialogs/ExcludedLabelsDialog.h" 0022 #include "core/meta/support/MetaConstants.h" 0023 #include "core/support/Components.h" 0024 #include "core/support/Debug.h" 0025 #include "statsyncing/Config.h" 0026 #include "statsyncing/Controller.h" 0027 0028 #include "MetaValues.h" 0029 0030 MetadataConfig::MetadataConfig( Amarok2ConfigDialog *parent ) 0031 : ConfigDialogBase( parent ) 0032 { 0033 connect( this, &MetadataConfig::changed, 0034 parent, &Amarok2ConfigDialog::updateButtons ); 0035 0036 setupUi( this ); 0037 0038 m_writeBackCoverDimensions->addItem( 0039 i18nc("Maximum cover size option", "Small (200 px)" ), QVariant( 200 ) ); 0040 m_writeBackCoverDimensions->addItem( 0041 i18nc("Maximum cover size option", "Medium (400 px)" ), QVariant( 400 ) ); 0042 m_writeBackCoverDimensions->addItem( 0043 i18nc("Maximum cover size option", "Large (800 px)" ), QVariant( 800 ) ); 0044 m_writeBackCoverDimensions->addItem( 0045 i18nc("Maximum cover size option", "Huge (1600 px)" ), QVariant( 1600 ) ); 0046 0047 m_writeBack->setChecked( AmarokConfig::writeBack() ); 0048 m_writeBack->setVisible( false ); // probably not a usecase 0049 m_writeBackStatistics->setChecked( AmarokConfig::writeBackStatistics() ); 0050 m_writeBackStatistics->setEnabled( m_writeBack->isChecked() ); 0051 m_writeBackCover->setChecked( AmarokConfig::writeBackCover() ); 0052 m_writeBackCover->setEnabled( m_writeBack->isChecked() ); 0053 if( m_writeBackCoverDimensions->findData( AmarokConfig::writeBackCoverDimensions() ) != -1 ) 0054 m_writeBackCoverDimensions->setCurrentIndex( m_writeBackCoverDimensions->findData( AmarokConfig::writeBackCoverDimensions() ) ); 0055 else 0056 m_writeBackCoverDimensions->setCurrentIndex( 1 ); // medium 0057 m_writeBackCoverDimensions->setEnabled( m_writeBackCover->isEnabled() && m_writeBackCover->isChecked() ); 0058 m_useCharsetDetector->setChecked( AmarokConfig::useCharsetDetector() ); 0059 connect( m_writeBack, &QCheckBox::toggled, this, &MetadataConfig::changed ); 0060 connect( m_writeBackStatistics, &QCheckBox::toggled, this, &MetadataConfig::changed ); 0061 connect( m_writeBackCover, &QCheckBox::toggled, this, &MetadataConfig::changed ); 0062 connect( m_writeBackCoverDimensions, QOverload<int>::of(&KComboBox::currentIndexChanged), 0063 this, &MetadataConfig::changed ); 0064 connect( m_useCharsetDetector, &QCheckBox::toggled, this, &MetadataConfig::changed ); 0065 0066 StatSyncing::Controller *controller = Amarok::Components::statSyncingController(); 0067 StatSyncing::Config *config = controller ? controller->config() : nullptr; 0068 m_statSyncingConfig = config; 0069 m_statSyncingProvidersView->setModel( config ); 0070 m_synchronizeButton->setIcon( QIcon::fromTheme( QStringLiteral("amarok_playcount") ) ); 0071 m_configureTargetButton->setIcon( QIcon::fromTheme( QStringLiteral("configure") ) ); 0072 connect( config, &StatSyncing::Config::dataChanged, this, &MetadataConfig::changed ); 0073 connect( config, &StatSyncing::Config::rowsInserted, this, &MetadataConfig::changed ); 0074 connect( config, &StatSyncing::Config::rowsRemoved, this, &MetadataConfig::changed ); 0075 connect( config, &StatSyncing::Config::modelReset, this, &MetadataConfig::changed ); 0076 0077 // Add target button 0078 m_addTargetButton->setEnabled( controller && controller->hasProviderFactories() ); 0079 connect( m_addTargetButton, &QAbstractButton::clicked, this, &MetadataConfig::slotCreateProviderDialog ); 0080 0081 // Configure target button 0082 m_configureTargetButton->setEnabled( false ); 0083 connect( m_statSyncingProvidersView->selectionModel(), &QItemSelectionModel::selectionChanged, 0084 this, &MetadataConfig::slotUpdateProviderConfigureButton ); 0085 connect( m_configureTargetButton, &QAbstractButton::clicked, this, &MetadataConfig::slotConfigureProvider ); 0086 0087 // Forget target button 0088 connect( m_statSyncingProvidersView->selectionModel(), &QItemSelectionModel::selectionChanged, 0089 this, &MetadataConfig::slotUpdateForgetButton ); 0090 connect( m_forgetTargetsButton, &QAbstractButton::clicked, this, &MetadataConfig::slotForgetCollections ); 0091 0092 // Synchronize button 0093 if( controller ) 0094 connect( m_synchronizeButton, &QAbstractButton::clicked, 0095 controller, &StatSyncing::Controller::synchronize ); 0096 else 0097 m_synchronizeButton->setEnabled( false ); 0098 0099 slotUpdateForgetButton(); 0100 0101 const qint64 checkedFields = config ? config->checkedFields() : 0; 0102 QMap<qint64, QString> i18nSyncLabels; // to avoid word puzzles, bug 334561 0103 i18nSyncLabels.insert( Meta::valRating, i18nc( "Statistics sync checkbox label", 0104 "Synchronize Ratings" ) ); 0105 i18nSyncLabels.insert( Meta::valFirstPlayed, i18nc( "Statistics sync checkbox label", 0106 "Synchronize First Played Times" ) ); 0107 i18nSyncLabels.insert( Meta::valLastPlayed, i18nc( "Statistics sync checkbox label", 0108 "Synchronize Last Played Times" ) ); 0109 i18nSyncLabels.insert( Meta::valPlaycount, i18nc( "Statistics sync checkbox label", 0110 "Synchronize Playcounts" ) ); 0111 i18nSyncLabels.insert( Meta::valLabel, i18nc( "Statistics sync checkbox label", 0112 "Synchronize Labels" ) ); 0113 0114 foreach( qint64 field, StatSyncing::Controller::availableFields() ) 0115 { 0116 QString name = i18nSyncLabels.value( field ); 0117 if( name.isEmpty() ) 0118 { 0119 name = i18nc( "%1 is field name such as Play Count (this string is only used " 0120 "as a fallback)", "Synchronize %1", Meta::i18nForField( field ) ); 0121 warning() << Q_FUNC_INFO << "no explicit traslation for" << name << "using fallback"; 0122 } 0123 QCheckBox *checkBox = new QCheckBox( name ); 0124 0125 if( field == Meta::valLabel ) // special case, we want plural: 0126 { 0127 QHBoxLayout *lineLayout = new QHBoxLayout(); 0128 QLabel *button = new QLabel(); 0129 button->setObjectName( QStringLiteral("configureLabelExceptions") ); 0130 connect( button, &QLabel::linkActivated, 0131 this, &MetadataConfig::slotConfigureExcludedLabels ); 0132 0133 lineLayout->addWidget( checkBox ); 0134 lineLayout->addWidget( button ); 0135 lineLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) ); 0136 m_statSyncingFieldsLayout->addLayout( lineLayout ); 0137 0138 slotUpdateConfigureExcludedLabelsLabel(); 0139 } 0140 else 0141 { 0142 m_statSyncingFieldsLayout->addWidget( checkBox ); 0143 } 0144 checkBox->setCheckState( ( field & checkedFields ) ? Qt::Checked : Qt::Unchecked ); 0145 checkBox->setProperty( "field", field ); 0146 connect( checkBox, &QCheckBox::stateChanged, this, &MetadataConfig::changed ); 0147 } 0148 } 0149 0150 MetadataConfig::~MetadataConfig() 0151 { 0152 if( m_statSyncingConfig ) 0153 { 0154 disconnect( this, &MetadataConfig::changed, nullptr, nullptr ); 0155 m_statSyncingConfig.data()->read(); // reset unsaved changes 0156 } 0157 } 0158 0159 bool 0160 MetadataConfig::isDefault() 0161 { 0162 return false; 0163 } 0164 0165 bool 0166 MetadataConfig::hasChanged() 0167 { 0168 // a bit hacky, but updating enabled status here does the trick 0169 m_writeBackStatistics->setEnabled( m_writeBack->isChecked() ); 0170 m_writeBackCover->setEnabled( m_writeBack->isChecked() ); 0171 m_writeBackCoverDimensions->setEnabled( m_writeBackCover->isEnabled() && m_writeBackCover->isChecked() ); 0172 0173 return 0174 m_writeBack->isChecked() != AmarokConfig::writeBack() || 0175 m_writeBackStatistics->isChecked() != AmarokConfig::writeBackStatistics() || 0176 m_writeBackCover->isChecked() != AmarokConfig::writeBackCover() || 0177 writeBackCoverDimensions() != AmarokConfig::writeBackCoverDimensions() || 0178 m_useCharsetDetector->isChecked() != AmarokConfig::useCharsetDetector() || 0179 ( m_statSyncingConfig.data() ? ( checkedFields() != m_statSyncingConfig->checkedFields() ) : false ) || 0180 ( m_statSyncingConfig.data() ? m_statSyncingConfig->hasChanged() : false ); 0181 } 0182 0183 void 0184 MetadataConfig::updateSettings() 0185 { 0186 AmarokConfig::setWriteBack( m_writeBack->isChecked() ); 0187 AmarokConfig::setWriteBackStatistics( m_writeBackStatistics->isChecked() ); 0188 AmarokConfig::setWriteBackCover( m_writeBackCover->isChecked() ); 0189 if( writeBackCoverDimensions() > 0 ) 0190 AmarokConfig::setWriteBackCoverDimensions( writeBackCoverDimensions() ); 0191 AmarokConfig::setUseCharsetDetector( m_useCharsetDetector->isChecked() ); 0192 if( m_statSyncingConfig ) 0193 { 0194 m_statSyncingConfig->setCheckedFields( checkedFields() ); 0195 m_statSyncingConfig->save(); 0196 } 0197 } 0198 0199 void 0200 MetadataConfig::slotForgetCollections() 0201 { 0202 if( !m_statSyncingConfig ) 0203 return; 0204 foreach( const QModelIndex &idx, m_statSyncingProvidersView->selectionModel()->selectedIndexes() ) 0205 { 0206 QString id = idx.data( StatSyncing::Config::ProviderIdRole ).toString(); 0207 m_statSyncingConfig->forgetProvider( id ); 0208 } 0209 } 0210 0211 void 0212 MetadataConfig::slotUpdateForgetButton() 0213 { 0214 QItemSelectionModel *selectionModel = m_statSyncingProvidersView->selectionModel(); 0215 // note: hasSelection() and selection() gives false positives! 0216 m_forgetTargetsButton->setEnabled( !selectionModel->selectedIndexes().isEmpty() ); 0217 } 0218 0219 void 0220 MetadataConfig::slotUpdateConfigureExcludedLabelsLabel() 0221 { 0222 QLabel *label = findChild<QLabel *>( QStringLiteral("configureLabelExceptions") ); 0223 if( !label || !m_statSyncingConfig ) 0224 { 0225 warning() << __PRETTY_FUNCTION__ << "label or m_statSyncingConfig is null!"; 0226 return; 0227 } 0228 int exceptions = m_statSyncingConfig->excludedLabels().count(); 0229 QString begin = QStringLiteral("<a href='dummy'>"); 0230 QString end = QStringLiteral("</a>"); 0231 label->setText( i18np( "(%2one exception%3)", "(%2%1 exceptions%3)", exceptions, 0232 begin, end ) ); 0233 } 0234 0235 void 0236 MetadataConfig::slotConfigureExcludedLabels() 0237 { 0238 ExcludedLabelsDialog dialog( m_statSyncingConfig.data(), this ); 0239 if( dialog.exec() == QDialog::Accepted ) 0240 { 0241 slotUpdateConfigureExcludedLabelsLabel(); 0242 Q_EMIT changed(); 0243 } 0244 } 0245 0246 void 0247 MetadataConfig::slotConfigureProvider() 0248 { 0249 StatSyncing::Controller *controller = Amarok::Components::statSyncingController(); 0250 if( controller ) 0251 { 0252 QModelIndexList selected = m_statSyncingProvidersView->selectionModel()->selectedIndexes(); 0253 if( selected.size() == 1 ) 0254 { 0255 const QString id = selected.front().data( StatSyncing::Config::ProviderIdRole ).toString(); 0256 0257 QWidget *dialog = controller->providerConfigDialog( id ); 0258 if( dialog ) 0259 { 0260 dialog->show(); 0261 dialog->activateWindow(); 0262 dialog->raise(); 0263 } 0264 } 0265 } 0266 } 0267 0268 void 0269 MetadataConfig::slotUpdateProviderConfigureButton() 0270 { 0271 QModelIndexList selected = m_statSyncingProvidersView->selectionModel()->selectedIndexes(); 0272 StatSyncing::Controller *controller = Amarok::Components::statSyncingController(); 0273 0274 if( selected.size() != 1 || !controller ) 0275 { 0276 m_configureTargetButton->setEnabled( false ); 0277 } 0278 else 0279 { 0280 const QString id = selected.front().data( StatSyncing::Config::ProviderIdRole ).toString(); 0281 m_configureTargetButton->setEnabled( controller->providerIsConfigurable( id ) ); 0282 } 0283 } 0284 0285 void 0286 MetadataConfig::slotCreateProviderDialog() 0287 { 0288 StatSyncing::Controller *controller = Amarok::Components::statSyncingController(); 0289 if( controller ) 0290 { 0291 QWidget *dialog = controller->providerCreationDialog(); 0292 if( dialog ) 0293 { 0294 dialog->show(); 0295 dialog->activateWindow(); 0296 dialog->raise(); 0297 } 0298 } 0299 } 0300 0301 int 0302 MetadataConfig::writeBackCoverDimensions() const 0303 { 0304 return m_writeBackCoverDimensions->itemData( m_writeBackCoverDimensions->currentIndex() ).toInt(); 0305 } 0306 0307 qint64 0308 MetadataConfig::checkedFields() const 0309 { 0310 qint64 ret = 0; 0311 foreach( QCheckBox *checkBox, m_statSyncingFieldsLayout->parentWidget()->findChildren<QCheckBox *>() ) 0312 { 0313 if( checkBox->isChecked() && checkBox->property( "field" ).canConvert<qint64>() ) 0314 ret |= checkBox->property( "field" ).value<qint64>(); 0315 } 0316 return ret; 0317 }