/* * Cantata * * Copyright (c) 2011-2014 Craig Drummond * * ---- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "devicepropertieswidget.h" #include "filenameschemedialog.h" #include "gui/covers.h" #include "support/localize.h" #include "widgets/icons.h" #include "support/utils.h" #include #include class CoverNameValidator : public QValidator { public: CoverNameValidator(QObject *parent) : QValidator(parent) { } State validate(QString &input, int &) const { int dotCount(0); for (int i=0; i1) { return Invalid; } } else if (!input[i].isLetterOrNumber() || input[i].isSpace()) { return Invalid; } } if (input.endsWith('.')) { return Intermediate; } return Acceptable; } // void fixup(QString &input) const // { // QString out; // int dotCount(0); // for (int i=0; isetIcon(Icons::self()->configureIcon); coverMaxSize->insertItems(0, QStringList() << i18n("No maximum size") << i18n("400 pixels") << i18n("300 pixels") << i18n("200 pixels") << i18n("100 pixels")); fixVariousArtists->setToolTip(i18n("

When copying tracks to a device, and the 'Album Artist' is set to 'Various Artists', " "then Cantata will set the 'Artist' tag of all tracks to 'Various Artists' and the " "track 'Title' tag to 'TrackArtist - TrackTitle'.


When copying from a device, Cantata " "will check if 'Album Artist' and 'Artist' are both set to 'Various Artists'. If so, it " "will attempt to extract the real artist from the 'Title' tag, and remove the artist name " "from the 'Title' tag.

")); useCache->setToolTip(i18n("

If you enable this, then Cantata will create a cache of the device's music library. " "This will help to speed up subsequent library scans (as the cache file will be used instead of " "having to read the tags of each file.)


NOTE: If you use another application to update " "the device's library, then this cache will become out-of-date. To rectify this, simply " "click on the 'refresh' icon in the device list. This will cause the cache file to be removed, and " "the contents of the device re-scanned.

")); if (qobject_cast(parent)) { verticalLayout->setMargin(4); } } #define REMOVE(w) \ w->setVisible(false); \ w->deleteLater(); \ w=0; void DevicePropertiesWidget::update(const QString &path, const DeviceOptions &opts, const QList &storage, int props, int disabledProps) { bool allowCovers=(props&Prop_CoversAll)||(props&Prop_CoversBasic); albumCovers->clear(); if (allowCovers) { if (props&Prop_CoversAll) { albumCovers->insertItems(0, QStringList() << noCoverText << embedCoverText << Covers::standardNames()); } else { albumCovers->insertItems(0, QStringList() << noCoverText << embedCoverText); } } if (props&Prop_Name) { name->setText(opts.name); connect(name, SIGNAL(textChanged(const QString &)), SLOT(checkSaveable())); } else { REMOVE(name) REMOVE(nameLabel) } if (props&Prop_FileName) { filenameScheme->setText(opts.scheme); vfatSafe->setChecked(opts.vfatSafe); asciiOnly->setChecked(opts.asciiOnly); ignoreThe->setChecked(opts.ignoreThe); replaceSpaces->setChecked(opts.replaceSpaces); } else { REMOVE(filenamesGroupBox) filenameScheme=0; vfatSafe=0; asciiOnly=0; ignoreThe=0; replaceSpaces=0; configFilename=0; } origOpts=opts; if (props&Prop_Folder) { musicFolder->setText(Utils::convertDirForDisplay(path)); connect(musicFolder, SIGNAL(textChanged(const QString &)), this, SLOT(checkSaveable())); if (disabledProps&Prop_Folder) { musicFolder->setDisabled(true); } } else { REMOVE(musicFolder); REMOVE(musicFolderLabel); } if (allowCovers) { albumCovers->setEditable(props&Prop_CoversAll); if (origOpts.coverName==Device::constNoCover) { origOpts.coverName=noCoverText; albumCovers->setCurrentIndex(0); } if (origOpts.coverName==Device::constEmbedCover) { origOpts.coverName=embedCoverText; albumCovers->setCurrentIndex(1); } else { albumCovers->setCurrentIndex(0); for (int i=1; icount(); ++i) { if (albumCovers->itemText(i)==origOpts.coverName) { albumCovers->setCurrentIndex(i); break; } } } if (0!=origOpts.coverMaxSize) { int coverMax=origOpts.coverMaxSize/100; if (coverMax<0 || coverMax>=coverMaxSize->count()) { coverMax=0; } coverMaxSize->setCurrentIndex(0==coverMax ? 0 : (coverMaxSize->count()-coverMax)); } else { coverMaxSize->setCurrentIndex(0); } albumCovers->setValidator(new CoverNameValidator(this)); connect(albumCovers, SIGNAL(editTextChanged(const QString &)), this, SLOT(albumCoversChanged())); connect(coverMaxSize, SIGNAL(currentIndexChanged(int)), this, SLOT(checkSaveable())); } else { REMOVE(albumCovers); REMOVE(albumCoversLabel); REMOVE(coverMaxSize); REMOVE(coverMaxSizeLabel); } if (props&Prop_Va) { fixVariousArtists->setChecked(opts.fixVariousArtists); connect(fixVariousArtists, SIGNAL(stateChanged(int)), this, SLOT(checkSaveable())); } else { REMOVE(fixVariousArtists); } if (props&Prop_Cache) { useCache->setChecked(opts.useCache); connect(useCache, SIGNAL(stateChanged(int)), this, SLOT(checkSaveable())); } else { REMOVE(useCache); } if (props&Prop_AutoScan) { autoScan->setChecked(opts.autoScan); connect(autoScan, SIGNAL(stateChanged(int)), this, SLOT(checkSaveable())); } else { REMOVE(autoScan); } if (props&Prop_Transcoder || props&Prop_Encoder) { bool transcode=props&Prop_Transcoder; transcoderName->clear(); if (transcode) { transcoderName->addItem(i18n("Do not transcode"), QString()); transcoderName->setCurrentIndex(0); transcoderValue->setVisible(false); transcoderWhenDifferent->setVisible(false); transcoderWhenDifferent->setChecked(opts.transcoderWhenDifferent); connect(transcoderWhenDifferent, SIGNAL(stateChanged(int)), this, SLOT(checkSaveable())); } else { transcoderFrame->setTitle(i18n("Encoder")); REMOVE(transcoderWhenDifferent); } QList encs=Encoders::getAvailable(); if (encs.isEmpty()) { transcoderFrame->setVisible(false); } else { foreach (const Encoders::Encoder &e, encs) { if (!transcode || e.transcoder) { QString name=e.name; if (transcode && name.endsWith(QLatin1String(" (ffmpeg)"))) { name=name.left(name.length()-9); } transcoderName->addItem(transcode ? i18n("Transcode to %1", name) : name, e.codec); } } if (opts.transcoderCodec.isEmpty()) { transcoderChanged(); } else { Encoders::Encoder enc=Encoders::getEncoder(opts.transcoderCodec); if (!enc.isNull()) { for (int i=1; icount(); ++i) { if (transcoderName->itemData(i).toString()==opts.transcoderCodec) { transcoderName->setCurrentIndex(i); transcoderChanged(); transcoderValue->setValue(opts.transcoderValue); break; } } } } } connect(transcoderName, SIGNAL(currentIndexChanged(int)), this, SLOT(transcoderChanged())); connect(transcoderValue, SIGNAL(valueChanged(int)), this, SLOT(checkSaveable())); } else { REMOVE(transcoderFrame); } if (storage.count()<2) { REMOVE(defaultVolume); REMOVE(defaultVolumeLabel); } else { foreach (const DeviceStorage &ds, storage) { defaultVolume->addItem(i18nc("name (size free)", "%1 (%2 free)", ds.description, Utils::formatByteSize(ds.size-ds.used)), ds.volumeIdentifier); } for (int i=0; icount(); ++i) { if (defaultVolume->itemData(i).toString()==opts.volumeId) { defaultVolume->setCurrentIndex(i); break; } } connect(defaultVolume,SIGNAL(currentIndexChanged(int)), this, SLOT(checkSaveable())); } origMusicFolder=Utils::fixPath(path); if (props&Prop_FileName) { connect(configFilename, SIGNAL(clicked()), SLOT(configureFilenameScheme())); connect(filenameScheme, SIGNAL(textChanged(const QString &)), this, SLOT(checkSaveable())); connect(vfatSafe, SIGNAL(stateChanged(int)), this, SLOT(checkSaveable())); connect(asciiOnly, SIGNAL(stateChanged(int)), this, SLOT(checkSaveable())); connect(ignoreThe, SIGNAL(stateChanged(int)), this, SLOT(checkSaveable())); connect(replaceSpaces, SIGNAL(stateChanged(int)), this, SLOT(checkSaveable())); } if (albumCovers) { albumCoversChanged(); } } void DevicePropertiesWidget::transcoderChanged() { QString codec=transcoderName->itemData(transcoderName->currentIndex()).toString(); if (codec.isEmpty()) { transcoderName->setToolTip(QString()); transcoderValue->setVisible(false); if (transcoderWhenDifferent) { transcoderWhenDifferent->setVisible(false); } } else { Encoders::Encoder enc=Encoders::getEncoder(codec); transcoderName->setToolTip(enc.description); if (transcoderWhenDifferent) { transcoderWhenDifferent->setVisible(true); } if (enc.values.count()) { transcoderValue->setValues(enc); transcoderValue->setVisible(true); } else { transcoderValue->setVisible(false); } } checkSaveable(); } void DevicePropertiesWidget::albumCoversChanged() { if (coverMaxSize) { bool enableSize=albumCovers->currentText()!=noCoverText; coverMaxSize->setEnabled(enableSize); coverMaxSizeLabel->setEnabled(enableSize); } checkSaveable(); } void DevicePropertiesWidget::checkSaveable() { DeviceOptions opts=settings(); bool checkFolder=musicFolder ? musicFolder->isEnabled() : false; modified=opts!=origOpts; if (!modified && checkFolder) { modified=music()!=origMusicFolder; } saveable=!opts.scheme.isEmpty() && (!checkFolder || !music().isEmpty()) && !opts.coverName.isEmpty(); if (saveable && ( (-1!=opts.coverName.indexOf(noCoverText) && opts.coverName!=noCoverText) || (-1!=opts.coverName.indexOf(embedCoverText) && opts.coverName!=embedCoverText) ) ) { saveable=false; } emit updated(); } void DevicePropertiesWidget::configureFilenameScheme() { if (!schemeDlg) { schemeDlg=new FilenameSchemeDialog(this); connect(schemeDlg, SIGNAL(scheme(const QString &)), filenameScheme, SLOT(setText(const QString &))); } schemeDlg->show(settings()); } DeviceOptions DevicePropertiesWidget::settings() { DeviceOptions opts; if (name && name->isEnabled()) { opts.name=name->text().trimmed(); } if (filenameScheme) { opts.scheme=filenameScheme->text().trimmed(); } if (vfatSafe) { opts.vfatSafe=vfatSafe->isChecked(); } if (asciiOnly) { opts.asciiOnly=asciiOnly->isChecked(); } if (ignoreThe) { opts.ignoreThe=ignoreThe->isChecked(); } if (replaceSpaces) { opts.replaceSpaces=replaceSpaces->isChecked(); } opts.fixVariousArtists=fixVariousArtists ? fixVariousArtists->isChecked() : false; opts.useCache=useCache ? useCache->isChecked() : false; opts.autoScan=autoScan ? autoScan->isChecked() : false; opts.transcoderCodec=QString(); opts.transcoderValue=0; opts.transcoderWhenDifferent=false; opts.coverName=cover(); opts.coverMaxSize=(!coverMaxSize || 0==coverMaxSize->currentIndex()) ? 0 : ((coverMaxSize->count()-coverMaxSize->currentIndex())*100); opts.volumeId=defaultVolume && defaultVolume->isVisible() ? defaultVolume->itemData(defaultVolume->currentIndex()).toString() : QString(); if (transcoderFrame && transcoderFrame->isVisible()) { opts.transcoderCodec=transcoderName->itemData(transcoderName->currentIndex()).toString(); if (!opts.transcoderCodec.isEmpty()) { Encoders::Encoder enc=Encoders::getEncoder(opts.transcoderCodec); opts.transcoderWhenDifferent=transcoderWhenDifferent ? transcoderWhenDifferent->isChecked() : false; if (!enc.isNull() && transcoderValue->value()value()).value; } } } return opts; } QString DevicePropertiesWidget::cover() const { QString coverName=albumCovers ? albumCovers->currentText().trimmed() : noCoverText; return coverName==noCoverText ? Device::constNoCover : coverName==embedCoverText ? Device::constEmbedCover : coverName; }