Skip to content

Commit

Permalink
Improved title case conversion, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed May 16, 2018
1 parent 825a697 commit 3949802
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 7 deletions.
23 changes: 16 additions & 7 deletions src/core/qgsstringutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <QRegExp>
#include <QStringList>
#include <QTextBoundaryFinder>
#include <QRegularExpression>

QString QgsStringUtils::capitalize( const QString &string, QgsStringUtils::Capitalization capitalization )
{
Expand Down Expand Up @@ -61,29 +62,37 @@ QString QgsStringUtils::capitalize( const QString &string, QgsStringUtils::Capit
// yes, this is MASSIVELY simplifying the problem!!

static QStringList smallWords;
static QStringList newPhraseSeparators;
static QRegularExpression splitWords;
if ( smallWords.empty() )
{
smallWords = QObject::tr( "a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs.|vs|via" ).split( '|' );
smallWords = QObject::tr( "a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|s|the|to|vs.|vs|via" ).split( '|' );

This comment has been minimized.

Copy link
@DelazJ

DelazJ Aug 16, 2018

Contributor

@nyalldawson is this worth putting to translation? I guess English title case rules are different from other languages and those may not be concerned by the small words rules eg. And that translators do apply their rules manually.
(unless I misunderstood what is supposed to be done here and would then need some guidance to know how handle this as a translator). Thanks.

newPhraseSeparators = QObject::tr( ".|:" ).split( '|' );
splitWords = QRegularExpression( QStringLiteral( "\\b" ) );
}

const QStringList parts = string.split( ' ' );
const QStringList parts = string.split( splitWords, QString::SkipEmptyParts );
QString result;
bool firstWord = true;
int i = 0;
int lastWord = parts.count() - 1;
for ( const QString &word : qgis::as_const( parts ) )
{
if ( word.isEmpty() )
if ( newPhraseSeparators.contains( word.trimmed() ) )
{
result += ' ';
firstWord = true;
result += word;
}
else if ( firstWord || !smallWords.contains( word ) )
else if ( firstWord || ( i == lastWord ) || !smallWords.contains( word ) )
{
result += ' ' + word.at( 0 ).toUpper() + word.mid( 1 );
result += word.at( 0 ).toUpper() + word.mid( 1 );
firstWord = false;
}
else
{
result += ' ' + word;
result += word;
}
i++;
}
return result;
}
Expand Down
29 changes: 29 additions & 0 deletions tests/src/core/testqgsstringutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class TestQgsStringUtils : public QObject
void hammingDistance();
void soundex();
void insertLinks();
void titleCase_data();
void titleCase();

};

Expand Down Expand Up @@ -154,6 +156,33 @@ void TestQgsStringUtils::insertLinks()
QVERIFY( !found );
}

void TestQgsStringUtils::titleCase_data()
{
QTest::addColumn<QString>( "input" );
QTest::addColumn<QString>( "expected" );

// invalid strings
QTest::newRow( "empty string" ) << "" << "";
QTest::newRow( "single character" ) << "a" << "A";
QTest::newRow( "string 1" ) << "follow step-by-step instructions" << "Follow Step-by-Step Instructions";
QTest::newRow( "string 2" ) << "this sub-phrase is nice" << "This Sub-Phrase Is Nice";
QTest::newRow( "" ) << "catchy title: a subtitle" << "Catchy Title: A Subtitle";
QTest::newRow( "string 3" ) << "all words capitalized" << "All Words Capitalized";
QTest::newRow( "string 4" ) << "small words are for by and of lowercase" << "Small Words Are for by and of Lowercase";
QTest::newRow( "string 5" ) << "a small word starts" << "A Small Word Starts";
QTest::newRow( "last word" ) << "a small word it ends on" << "A Small Word It Ends On";
QTest::newRow( "last word2" ) << "Ends with small word of" << "Ends With Small Word Of";
QTest::newRow( "string 6" ) << "Merge VRT(s)" << "Merge VRT(s)";
QTest::newRow( "string 6" ) << "multiple sentences. more than one." << "Multiple Sentences. More Than One.";
}

void TestQgsStringUtils::titleCase()
{
QFETCH( QString, input );
QFETCH( QString, expected );
QCOMPARE( QgsStringUtils::capitalize( input, QgsStringUtils::TitleCase ), expected );
}


QGSTEST_MAIN( TestQgsStringUtils )
#include "testqgsstringutils.moc"

0 comments on commit 3949802

Please sign in to comment.