/* * Cantata * * Copyright (c) 2011-2022 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 "widgets/icons.h" #include "support/utils.h" #include #include #include class CoverNameValidator : public QValidator { public: CoverNameValidator(QObject *parent) : QValidator(parent) { } State validate(QString &input, int &) const override { 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() << tr("No maximum size") << tr("400 pixels") << tr("300 pixels") << tr("200 pixels") << tr("100 pixels")); fixVariousArtists->setToolTip(tr("

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(tr("

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=nullptr; vfatSafe=nullptr; asciiOnly=nullptr; ignoreThe=nullptr; replaceSpaces=nullptr; configFilename=nullptr; } origOpts=opts; if (props&Prop_Folder) { musicFolder->setText(Utils::convertPathForDisplay(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(tr("Do not transcode"), QString()); transcoderName->setCurrentIndex(0); transcoderValue->setVisible(false); transcoderWhen->addItem(tr("Always transcode"), DeviceOptions::TW_Always); transcoderWhen->addItem(tr("Only transcode if source file is of a different format"), DeviceOptions::TW_IfDifferent); transcoderWhen->addItem(tr("Only transcode if source is FLAC/WAV"), DeviceOptions::TW_IfLossess); transcoderWhen->setVisible(false); transcoderWhen->setCurrentIndex(0); for (int i=0; icount(); ++i) { if (transcoderWhen->itemData(i).toInt()==opts.transcoderWhen) { transcoderWhen->setCurrentIndex(i); break; } } connect(transcoderWhen, SIGNAL(currentIndexChanged(int)), this, SLOT(checkSaveable())); } else { transcoderFrame->setTitle(tr("Encoder")); REMOVE(transcoderWhen); } QList encs=Encoders::getAvailable(); if (encs.isEmpty()) { transcoderFrame->setVisible(false); } else { for (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 ? tr("Transcode to %1").arg(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 { for (const DeviceStorage &ds: storage) { defaultVolume->addItem(tr("%1 (%2 free)", "name (size free)") .arg(ds.description).arg(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(); } QTimer::singleShot(0, this, SLOT(setSize())); } void DevicePropertiesWidget::transcoderChanged() { QString codec=transcoderName->itemData(transcoderName->currentIndex()).toString(); if (codec.isEmpty()) { transcoderName->setToolTip(QString()); transcoderValue->setVisible(false); if (transcoderWhen) { transcoderWhen->setVisible(false); } } else { Encoders::Encoder enc=Encoders::getEncoder(codec); transcoderName->setToolTip(enc.description); if (transcoderWhen) { transcoderWhen->setVisible(true); } if (enc.values.count()) { transcoderValue->setValues(enc); transcoderValue->setVisible(true); } else { transcoderValue->setVisible(false); } } Utils::resizeWindow(this, true, 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.transcoderWhen=DeviceOptions::TW_Always; 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); if (transcoderWhen) { opts.transcoderWhen=(DeviceOptions::TranscodeWhen)transcoderWhen->itemData(transcoderWhen->currentIndex()).toUInt(); } 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; } void DevicePropertiesWidget::setSize() { Utils::resizeWindow(this, true, false); } #include "moc_devicepropertieswidget.cpp"