diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3479c6fd5..ecc963972 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -76,6 +76,7 @@ set(CLEMENTINE-SOURCES libraryplaylistitem.cpp scopedtransaction.cpp playlistundocommands.cpp + spinbox.cpp ) # Header files that have Q_OBJECT in @@ -138,6 +139,7 @@ set(CLEMENTINE-MOC-HEADERS equalizer.h equalizerslider.h stickyslider.h + spinbox.h ) # lists of engine source files diff --git a/src/edittagdialog.cpp b/src/edittagdialog.cpp index 48f0e9938..57cda013e 100644 --- a/src/edittagdialog.cpp +++ b/src/edittagdialog.cpp @@ -20,15 +20,12 @@ #include +const char* EditTagDialog::kHintText = QT_TR_NOOP("[click to edit]"); + EditTagDialog::EditTagDialog(QWidget* parent) : QDialog(parent) { ui_.setupUi(this); - - QString hint_text(tr("[click to edit]")); - ui_.album->SetHint(hint_text); - ui_.artist->SetHint(hint_text); - ui_.genre->SetHint(hint_text); } bool EditTagDialog::SetSongs(const SongList &s) { @@ -40,14 +37,20 @@ bool EditTagDialog::SetSongs(const SongList &s) { } songs_ = songs; + if (songs.count() == 0) + return false; + // Don't allow editing of fields that don't make sense for multiple items ui_.title->setEnabled(songs.count() == 1); ui_.track->setEnabled(songs.count() == 1); ui_.comment->setEnabled(songs.count() == 1); - if (songs.count() == 0) - return false; - else if (songs.count() == 1) { + common_artist_ = songs[0].artist(); + common_album_ = songs[0].album(); + common_genre_ = songs[0].genre(); + common_year_ = songs[0].year(); + + if (songs.count() == 1) { const Song& song = songs[0]; ui_.title->setText(song.title()); @@ -59,6 +62,10 @@ bool EditTagDialog::SetSongs(const SongList &s) { ui_.comment->setPlainText(song.comment()); ui_.filename->setText(song.filename()); + + ui_.artist->ClearHint(); + ui_.album->ClearHint(); + ui_.genre->ClearHint(); } else { // Find any fields that are common to all items @@ -66,26 +73,30 @@ bool EditTagDialog::SetSongs(const SongList &s) { ui_.track->clear(); ui_.comment->clear(); - QString artist(songs[0].artist()); - QString album(songs[0].album()); - QString genre(songs[0].genre()); - int year = songs[0].year(); - foreach (const Song& song, songs) { - if (artist != song.artist()) - artist = QString::null; - if (album != song.album()) - album = QString::null; - if (genre != song.genre()) - genre = QString::null; - if (year != song.year()) - year = -1; + if (common_artist_ != song.artist()) { + common_artist_ = QString::null; + ui_.artist->SetHint(kHintText); + } + + if (common_album_ != song.album()) { + common_album_ = QString::null; + ui_.album->SetHint(kHintText); + } + + if (common_genre_ != song.genre()) { + common_genre_ = QString::null; + ui_.genre->SetHint(kHintText); + } + + if (common_year_ != song.year()) + common_year_ = -1; } - ui_.artist->setText(artist); - ui_.album->setText(album); - ui_.genre->setText(genre); - ui_.year->setValue(year); + ui_.artist->setText(common_artist_); + ui_.album->setText(common_album_); + ui_.genre->setText(common_genre_); + ui_.year->setValue(common_year_); ui_.filename->setText(tr("Editing %n tracks", "", songs.count())); } @@ -102,19 +113,23 @@ void EditTagDialog::accept() { foreach (const Song& old, songs_) { Song song(old); - if (ui_.title->isEnabled() && !ui_.title->text().isEmpty()) - song.set_title(ui_.title->text()); - if (ui_.artist->isEnabled() && !ui_.artist->text().isEmpty()) - song.set_artist(ui_.artist->text()); - if (ui_.album->isEnabled() && !ui_.album->text().isEmpty()) - song.set_album(ui_.album->text()); - if (ui_.genre->isEnabled() && !ui_.genre->text().isEmpty()) - song.set_genre(ui_.genre->text()); + int track = ui_.track->text().isEmpty() ? -1 : ui_.track->value(); + int year = ui_.year->text().isEmpty() ? -1 : ui_.year->value(); + + if (ui_.title->isEnabled()) + song.set_title(ui_.title->text()); + + if (ui_.artist->isEnabled() && !(common_artist_.isNull() && ui_.artist->text().isEmpty())) + song.set_artist(ui_.artist->text()); + if (ui_.album->isEnabled() && !(common_album_.isNull() && ui_.album->text().isEmpty())) + song.set_album(ui_.album->text()); + if (ui_.genre->isEnabled() && !(common_genre_.isNull() && ui_.genre->text().isEmpty())) + song.set_genre(ui_.genre->text()); + if (ui_.year->isEnabled() && !(common_year_ == -1 && year == -1)) + song.set_year(year); - if (ui_.year->isEnabled()) - song.set_year(ui_.year->value()); if (ui_.track->isEnabled()) - song.set_track(ui_.track->value()); + song.set_track(track); if (ui_.comment->isEnabled()) song.set_comment(ui_.comment->toPlainText()); diff --git a/src/edittagdialog.h b/src/edittagdialog.h index 87ba71277..409956cf3 100644 --- a/src/edittagdialog.h +++ b/src/edittagdialog.h @@ -30,6 +30,8 @@ class EditTagDialog : public QDialog { public: EditTagDialog(QWidget* parent = 0); + static const char* kHintText; + bool SetSongs(const SongList& songs); void SetTagCompleter(Library* library); @@ -43,6 +45,11 @@ class EditTagDialog : public QDialog { Ui::EditTagDialog ui_; SongList songs_; + + QString common_artist_; + QString common_album_; + QString common_genre_; + int common_year_; }; #endif // EDITTAGDIALOG_H diff --git a/src/edittagdialog.ui b/src/edittagdialog.ui index e0f8a1c2c..d60da8bc9 100644 --- a/src/edittagdialog.ui +++ b/src/edittagdialog.ui @@ -87,7 +87,7 @@ - + 0 @@ -116,7 +116,7 @@ - + 0 @@ -157,7 +157,7 @@ QLineEdit { - background-color: transparent; + background-color: transparent; } @@ -194,6 +194,11 @@ QLineEdit
lineedit.h
+ + SpinBox + QSpinBox +
spinbox.h
+
buttonBox diff --git a/src/lineedit.h b/src/lineedit.h index cae399601..665491480 100644 --- a/src/lineedit.h +++ b/src/lineedit.h @@ -28,6 +28,7 @@ class LineEdit : public QLineEdit { QString GetHint() const { return hint_; } void SetHint(const QString& hint); + void ClearHint() { SetHint(QString()); } void paintEvent(QPaintEvent* e); diff --git a/src/spinbox.cpp b/src/spinbox.cpp new file mode 100644 index 000000000..559180fe7 --- /dev/null +++ b/src/spinbox.cpp @@ -0,0 +1,49 @@ +/* This file is part of Clementine. + + Clementine 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 3 of the License, or + (at your option) any later version. + + Clementine 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 Clementine. If not, see . +*/ + +#include "spinbox.h" + +#include + +SpinBox::SpinBox(QWidget *parent) + : QSpinBox(parent), + empty_value_(0) +{ +} + +int SpinBox::valueFromText(const QString &text) const { + if (text.isEmpty()) + return empty_value_; + return QSpinBox::valueFromText(text); +} + +QString SpinBox::textFromValue(int val) const { + if (val == empty_value_) + return ""; + return QSpinBox::textFromValue(val); +} + +void SpinBox::fixup(QString &str) const { + if (str.isEmpty()) + return; + QSpinBox::fixup(str); +} + +QValidator::State SpinBox::validate(QString &input, int &pos) const { + if (input.isEmpty()) + return QValidator::Acceptable; + return QSpinBox::validate(input, pos); +} diff --git a/src/spinbox.h b/src/spinbox.h new file mode 100644 index 000000000..2f1802dde --- /dev/null +++ b/src/spinbox.h @@ -0,0 +1,45 @@ +/* This file is part of Clementine. + + Clementine 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 3 of the License, or + (at your option) any later version. + + Clementine 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 Clementine. If not, see . +*/ + +#ifndef SPINBOX_H +#define SPINBOX_H + +#include + +// A spinbox that accepts the empty string as input +class SpinBox : public QSpinBox { + Q_OBJECT + Q_PROPERTY(int empty_value READ empty_value WRITE set_empty_value); + + public: + SpinBox(QWidget *parent = 0); + + // The empty_value must still be within the range of the spinbox. + // Defaults to 0 + int empty_value() const { return empty_value_; } + void set_empty_value(int v) { empty_value_ = v; } + + protected: + int valueFromText(const QString &text) const; + QString textFromValue(int val) const; + void fixup(QString &str) const; + QValidator::State validate(QString &input, int &pos) const; + + private: + int empty_value_; +}; + +#endif // SPINBOX_H