From d70be143fd0654be73d31a59f562c28e2c88da6e Mon Sep 17 00:00:00 2001 From: Lasse Liehu Date: Sat, 27 Jul 2013 21:21:04 +0300 Subject: [PATCH 1/2] Add internationalization context for song types --- .../playlist/dynamic/echonest/EchonestControl.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp index 16c33576b..7fca59043 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp @@ -494,11 +494,11 @@ Tomahawk::EchonestControl::updateWidgets() match->addItem( tr( "is not" ), 0 ); QComboBox* combo = new QComboBox(); - combo->addItem( tr( "Studio" ), "studio" ); - combo->addItem( tr( "Live" ), "live" ); - combo->addItem( tr( "Acoustic" ), "acoustic" ); - combo->addItem( tr( "Electric" ), "electric" ); - combo->addItem( tr( "Christmas" ), "christmas" ); + combo->addItem( tr( "Studio", "Song type: The song was recorded in a studio." ), "studio" ); + combo->addItem( tr( "Live", "Song type: The song was a life performance." ), "live" ); + combo->addItem( tr( "Acoustic", "Song type" ), "acoustic" ); + combo->addItem( tr( "Electric", "Song type" ), "electric" ); + combo->addItem( tr( "Christmas", "Song type: A christmas song" ), "christmas" ); connect( match, SIGNAL( activated( int ) ), this, SLOT( updateData() ) ); connect( match, SIGNAL( activated( int ) ), this, SLOT( editingFinished() ) ); From 48bf95c8f8f250f2078ebf27f54e595260ac51fe Mon Sep 17 00:00:00 2001 From: Lasse Liehu Date: Sun, 28 Jul 2013 00:07:43 +0300 Subject: [PATCH 2/2] Make automatic playlist UI more translatable Using QObject::tr in EchonestGenerator::sentenceSummary (a virtual method) because if just using tr the translations wouldn't show up. --- .../dynamic/echonest/EchonestControl.cpp | 16 +++---- .../dynamic/echonest/EchonestGenerator.cpp | 44 ++++++++++++------- .../dynamic/widgets/DynamicControlWrapper.cpp | 22 +++++++--- .../dynamic/widgets/DynamicControlWrapper.h | 2 +- 4 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp index 7fca59043..ba2040f79 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp @@ -164,12 +164,12 @@ Tomahawk::EchonestControl::updateWidgets() QComboBox* match = new QComboBox(); QLineEdit* input = new QLineEdit(); - match->addItem( "Similar To", Echonest::DynamicPlaylist::ArtistRadioType ); - match->addItem( "Limit To", Echonest::DynamicPlaylist::ArtistType ); + match->addItem( tr( "Similar To" ), Echonest::DynamicPlaylist::ArtistRadioType ); + match->addItem( tr( "Limit To" ), Echonest::DynamicPlaylist::ArtistType ); m_matchString = match->currentText(); m_matchData = match->itemData( match->currentIndex() ).toString(); - input->setPlaceholderText( "Artist name" ); + input->setPlaceholderText( tr( "Artist name" ) ); input->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); input->setCompleter( new QCompleter( QStringList(), input ) ); input->completer()->setCaseSensitivity( Qt::CaseInsensitive ); @@ -245,7 +245,7 @@ Tomahawk::EchonestControl::updateWidgets() QLabel* match = new QLabel( tr( "similar to" ) ); QLineEdit* input = new QLineEdit(); - input->setPlaceholderText( "Enter any combination of song name and artist here..." ); + input->setPlaceholderText( tr( "Enter any combination of song name and artist here..." ) ); m_matchString = QString(); m_matchData = QString::number( (int)Echonest::DynamicPlaylist::SongRadioType ); @@ -361,14 +361,14 @@ Tomahawk::EchonestControl::updateWidgets() { m_currentType = Echonest::DynamicPlaylist::ArtistMinLatitude; QString deg = QString( QChar( 0x00B0 ) ); - setupMinMaxWidgets( Echonest::DynamicPlaylist::ArtistMinLatitude, Echonest::DynamicPlaylist::ArtistMaxLatitude, QString( "-180%1" ).arg( deg ), QString( "180%1" ).arg( deg ), 180 ); + setupMinMaxWidgets( Echonest::DynamicPlaylist::ArtistMinLatitude, Echonest::DynamicPlaylist::ArtistMaxLatitude, QString( tr( "-180%1" ) ).arg( deg ), QString( tr( "180%1" ) ).arg( deg ), 180 ); qobject_cast< LabeledSlider* >( m_input.data() )->slider()->setMinimum( -180 ); } else if( selectedType() == "Longitude" ) { m_currentType = Echonest::DynamicPlaylist::ArtistMinLongitude; QString deg = QString( QChar( 0x00B0 ) ); - setupMinMaxWidgets( Echonest::DynamicPlaylist::ArtistMinLongitude, Echonest::DynamicPlaylist::ArtistMaxLongitude, QString( "-180%1" ).arg( deg ), QString( "180%1" ).arg( deg ), 180 ); + setupMinMaxWidgets( Echonest::DynamicPlaylist::ArtistMinLongitude, Echonest::DynamicPlaylist::ArtistMaxLongitude, QString( tr( "-180%1" ) ).arg( deg ), QString( tr( "180%1" ) ).arg( deg ), 180 ); qobject_cast< LabeledSlider* >( m_input.data() )->slider()->setMinimum( -180 ); } else if( selectedType() == "Mode" ) @@ -525,8 +525,8 @@ void Tomahawk::EchonestControl::setupMinMaxWidgets( Echonest::DynamicPlaylist::PlaylistParam min, Echonest::DynamicPlaylist::PlaylistParam max, const QString& leftL, const QString& rightL, int maxRange ) { QComboBox* match = new QComboBox; - match->addItem( "At Least", min ); - match->addItem( "At Most", max ); + match->addItem( tr( "At Least" ), min ); + match->addItem( tr( "At Most" ), max ); LabeledSlider* input = new LabeledSlider( leftL, rightL ); input->slider()->setRange( 0, maxRange ); diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp index 9e23f7d45..be52121fa 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp @@ -71,9 +71,19 @@ EchonestFactory::createControl( const QString& controlType ) QStringList EchonestFactory::typeSelectors() const { - QStringList types = QStringList() << "Artist" << "Artist Description" << "User Radio" << "Song" << "Genre" << "Mood" << "Style" << "Adventurousness" << "Variety" << "Tempo" << "Duration" << "Loudness" - << "Danceability" << "Energy" << "Artist Familiarity" << "Artist Hotttnesss" << "Song Hotttnesss" - << "Longitude" << "Latitude" << "Mode" << "Key" << "Sorting" << "Song Type"; + // Using QT_TRANSLATE_NOOP here because this function should return the untranslated types + QStringList types = QStringList() << QT_TRANSLATE_NOOP( "Type selector", "Artist" ) << QT_TRANSLATE_NOOP( "Type selector", "Artist Description" ) + << QT_TRANSLATE_NOOP( "Type selector", "User Radio" ) << QT_TRANSLATE_NOOP( "Type selector", "Song" ) + << QT_TRANSLATE_NOOP( "Type selector", "Genre" ) << QT_TRANSLATE_NOOP( "Type selector", "Mood" ) + << QT_TRANSLATE_NOOP( "Type selector", "Style" ) << QT_TRANSLATE_NOOP( "Type selector", "Adventurousness" ) + << QT_TRANSLATE_NOOP( "Type selector", "Variety" ) << QT_TRANSLATE_NOOP( "Type selector", "Tempo" ) + << QT_TRANSLATE_NOOP( "Type selector", "Duration" ) << QT_TRANSLATE_NOOP( "Type selector", "Loudness" ) + << QT_TRANSLATE_NOOP( "Type selector", "Danceability" ) << QT_TRANSLATE_NOOP( "Type selector", "Energy" ) + << QT_TRANSLATE_NOOP( "Type selector", "Artist Familiarity" ) << QT_TRANSLATE_NOOP( "Type selector", "Artist Hotttnesss" ) + << QT_TRANSLATE_NOOP( "Type selector", "Song Hotttnesss" ) << QT_TRANSLATE_NOOP( "Type selector", "Longitude" ) + << QT_TRANSLATE_NOOP( "Type selector", "Latitude" ) << QT_TRANSLATE_NOOP( "Type selector", "Mode" ) + << QT_TRANSLATE_NOOP( "Type selector", "Key" ) << QT_TRANSLATE_NOOP( "Type selector", "Sorting" ) + << QT_TRANSLATE_NOOP( "Type selector", "Song Type" ); return types; } @@ -530,7 +540,7 @@ EchonestGenerator::sentenceSummary() * and all Artist types must be the same. The filters aren't checked at the moment until Generate / Play is pressed. Consider doing a check on hide as well. */ QList< dyncontrol_ptr > allcontrols = m_controls; - QString sentence = "Songs "; + QString sentence = QObject::tr( "Songs ", "Beginning of a sentence summary" ); /// 1. Collect all required filters /// 2. Get the sorted by filter if it exists. @@ -559,7 +569,7 @@ EchonestGenerator::sentenceSummary() /// If there are no artists and no filters, show some help text if( required.isEmpty() && allcontrols.isEmpty() ) - sentence = "No configured filters!"; + sentence = QObject::tr( "No configured filters!" ); /// Do the assembling. Start with the artists if there are any, then do all the rest. for( int i = 0; i < required.size(); i++ ) { @@ -573,24 +583,24 @@ EchonestGenerator::sentenceSummary() if( i == 0 ) { // if it's the first.. special casez center = summary.remove( "~" ); if( required.size() == 2 ) // special case for 2, no comma. ( X and Y ) - suffix = " and "; + suffix = QObject::tr( " and ", "Inserted between items in a list of two" ); else if( required.size() > 2 ) // in a list with more after - suffix = ", "; + suffix = QObject::tr( ", ", "Inserted between items in a list" ); else if( allcontrols.isEmpty() && sorting.isNull() ) // the last one, and no more controls, so put a period - suffix = "."; + suffix = QObject::tr( ".", "Inserted when ending a sentence summary" ); else - suffix = " "; + suffix = " "; // shouldn't happen, but don't fail. it doesn't make sense to have this translatable } else { center = summary.mid( summary.indexOf( "~" ) + 1 ); if( i == required.size() - 1 ) { // if there are more, add an " and " if( !( allcontrols.isEmpty() && sorting.isNull() ) ) - suffix = ", "; + suffix = QObject::tr( ", ", "Inserted between items in a list" ); else - suffix = "."; + suffix = QObject::tr( ".", "Inserted when ending a sentence summary" ); } else if ( i < required.size() - 2 ) // An item in the list that is before the second to last one, don't use ", and", we only want that for the last item - suffix += ", "; + suffix += QObject::tr( ", ", "Inserted between items in a list" ); else - suffix += ", and "; + suffix += QObject::tr( ", and ", "Inserted between the last two items in a list of more than two" ); } sentence += center + suffix; } @@ -601,15 +611,15 @@ EchonestGenerator::sentenceSummary() QString prefix, suffix; if( last ) { // only if there is not just 1 if( !( required.isEmpty() && allcontrols.size() == 1 ) ) - prefix = "and "; - suffix = "."; + prefix = QObject::tr( "and ", "Inserted before the last item in a list" ); + suffix = QObject::tr( ".", "Inserted when ending a sentence summary" ); } else - suffix = ", "; + suffix = QObject::tr( ", ", "Inserted between items in a list" ); sentence += prefix + allcontrols.value( i ).dynamicCast< EchonestControl >()->summary() + suffix; } if( !sorting.isNull() ) { - sentence += "and " + sorting.dynamicCast< EchonestControl >()->summary() + "."; + sentence += QObject::tr( "and ", "Inserted before the sorting summary in a sentence summary" ) + sorting.dynamicCast< EchonestControl >()->summary() + QObject::tr( ".","Inserted when ending a sentence summary" ); } return sentence; diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.cpp index 30e7c7941..d9c3529b0 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.cpp +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.cpp @@ -29,6 +29,7 @@ #include #include #include +#include using namespace Tomahawk; @@ -57,17 +58,23 @@ DynamicControlWrapper::DynamicControlWrapper( const Tomahawk::dyncontrol_ptr& co m_plusL->addWidget( m_minusButton ); m_plusL->addWidget( createDummy( m_minusButton, m_parent ) ); // :-( - connect( m_typeSelector, SIGNAL( activated( QString) ), SLOT( typeSelectorChanged( QString ) ) ); + connect( m_typeSelector, SIGNAL( activated( int ) ), SLOT( typeSelectorChanged( int ) ) ); connect( m_control.data(), SIGNAL( changed() ), this, SIGNAL( changed() ) ); m_layout.data()->addWidget( m_typeSelector, row, 0, Qt::AlignLeft ); if( !control.isNull() ) { foreach( const QString& type, control->typeSelectors() ) - m_typeSelector->addItem( type ); + m_typeSelector->addItem( qApp->translate( "Type selector", type.toUtf8() ), type ); } - typeSelectorChanged( m_control.isNull() ? "" : m_control->selectedType(), true ); + + int typeIndex = 0; + if ( !m_control.isNull() ) { + typeIndex = m_typeSelector->findData( m_control->selectedType() ); + if (typeIndex == -1) typeIndex = 0; + } + typeSelectorChanged( typeIndex, true ); m_layout.data()->addLayout( m_plusL, m_row, 3, Qt::AlignCenter ); m_plusL->setCurrentIndex( 0 ); @@ -141,19 +148,20 @@ DynamicControlWrapper::createDummy( QWidget* fromW, QWidget* parent ) void -DynamicControlWrapper::typeSelectorChanged( const QString& type, bool firstLoad ) +DynamicControlWrapper::typeSelectorChanged( int typeIndex, bool firstLoad ) { Q_ASSERT( !m_layout.isNull() ); m_layout.data()->removeWidget( m_matchSelector.data() ); m_layout.data()->removeWidget( m_entryWidget.data() ); + // Get the untranslated type name + QString type = m_typeSelector->itemData(typeIndex).toString(); + if( m_control->selectedType() != type && !firstLoad ) m_control->setSelectedType( type ); - int idx = m_typeSelector->findText( type ); - if( idx > -1 ) - m_typeSelector->setCurrentIndex( idx ); + m_typeSelector->setCurrentIndex( typeIndex ); if( m_control->matchSelector() ) { diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.h b/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.h index ed70f08e3..10599a878 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.h +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.h @@ -61,7 +61,7 @@ signals: void changed(); private slots: - void typeSelectorChanged( const QString& selectedType, bool firstLoad = false ); + void typeSelectorChanged( int selectedTypeIndex, bool firstLoad = false ); private: QWidget* m_parent;