You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kbibtex/src/value.cpp

466 lines
15 KiB

11 years ago
/***************************************************************************
* Copyright (C) 2004-2009 by Thomas Fischer *
* fischer@unix-ag.uni-kl.de *
* *
* 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; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <tqregexp.h>
#include <tqstring.h>
#include <tqstringlist.h>
11 years ago
#include "value.h"
namespace BibTeX
{
ValueTextInterface::ValueTextInterface( const ValueTextInterface* other ) : m_text( other->text() )
{
// nothing
}
ValueTextInterface::ValueTextInterface( const TQString& text ) : m_text( text )
11 years ago
{
// nothing
}
void ValueTextInterface::setText( const TQString& text )
11 years ago
{
m_text = text;
}
TQString ValueTextInterface::text() const
11 years ago
{
return m_text;
}
TQString ValueTextInterface::simplifiedText() const
11 years ago
{
return text().replace( TQRegExp( "\\\\[A-Za-z0-9]+" ), "" ).replace( '{', "" ).replace( '}', "" );
11 years ago
}
void ValueTextInterface::replace( const TQString &before, const TQString &after )
11 years ago
{
if ( before == text() || before == simplifiedText() )
setText( after );
}
bool ValueTextInterface::containsPattern( const TQString &pattern, bool caseSensitive )
11 years ago
{
return text().contains( pattern, caseSensitive ) || simplifiedText().contains( pattern, caseSensitive );
}
ValueItem::ValueItem( const TQString& text ) : ValueTextInterface( text )
11 years ago
{
// nothing
}
Keyword::Keyword( Keyword *other ) : ValueTextInterface( other )
{
// nothing
}
Keyword::Keyword( const TQString& text ) : ValueTextInterface( text )
11 years ago
{
// nothing
}
Keyword *Keyword::clone()
{
return new Keyword( text() );
}
KeywordContainer::KeywordContainer(): ValueItem( "" )
{
// nothing
}
KeywordContainer::KeywordContainer( const TQString& text ) : ValueItem( text )
11 years ago
{
setText( text );
}
KeywordContainer::KeywordContainer( KeywordContainer *other ) : ValueItem( TQString::null )
11 years ago
{
for ( TQValueList<Keyword*>::Iterator it = other->keywords.begin(); it != other->keywords.end(); ++it )
11 years ago
keywords.append(( *it )->clone() );
}
KeywordContainer::KeywordContainer( const TQStringList& list ) : ValueItem( TQString::null )
11 years ago
{
setList( list );
}
ValueItem *KeywordContainer::clone()
{
return new KeywordContainer( this );
}
void KeywordContainer::setList( const TQStringList& list )
11 years ago
{
keywords.clear();
for ( TQStringList::ConstIterator it = list.begin(); it != list.end(); ++it )
11 years ago
keywords.append( new Keyword( *it ) );
}
void KeywordContainer::append( const TQString& text )
11 years ago
{
bool contains = FALSE;
for ( TQValueList<Keyword*>::ConstIterator it = keywords.begin(); !contains && it != keywords.end(); ++it )
contains = TQString::compare(( *it )->text(), text ) == 0;
11 years ago
if ( contains == 0 )
keywords.append( new Keyword( text ) );
}
void KeywordContainer::remove( const TQString& text )
11 years ago
{
bool contains = FALSE;
for ( TQValueList<Keyword*>::Iterator it = keywords.begin(); !contains && it != keywords.end(); ++it )
if ( TQString::compare(( *it )->text(), text ) == 0 )
11 years ago
{
keywords.remove( it );
break;
}
}
void KeywordContainer::setText( const TQString& text )
11 years ago
{
ValueItem::setText( text );
TQRegExp splitRegExp;
11 years ago
if ( text.contains( ";" ) )
splitRegExp = TQRegExp( "\\s*;\\s*" );
11 years ago
else
splitRegExp = TQRegExp( "\\s*,\\s*" );
11 years ago
keywords.clear();
TQStringList keywordList = TQStringList::split( splitRegExp, text, FALSE );
for ( TQStringList::ConstIterator it = keywordList.begin(); it != keywordList.end(); ++it )
11 years ago
keywords.append( new Keyword( *it ) );
}
TQString KeywordContainer::text() const
11 years ago
{
TQString result;
11 years ago
bool first = true;
for ( TQValueList<Keyword*>::ConstIterator it = keywords.begin(); it != keywords.end(); ++it )
11 years ago
{
if ( !first )
result.append( "; " );
else first = false;
result.append(( *it )->text() );
}
return result;
}
void KeywordContainer::replace( const TQString &before, const TQString &after )
11 years ago
{
for ( TQValueList<Keyword*>::ConstIterator it = keywords.begin(); it != keywords.end(); ++it )
11 years ago
( *it )->replace( before, after );
}
Person::Person( const TQString& text, bool firstNameFirst ) : ValueTextInterface( text ), m_firstNameFirst( firstNameFirst )
11 years ago
{
setText( text );
}
Person::Person( const TQString& firstName, const TQString& lastName, bool firstNameFirst ) : ValueTextInterface( TQString( firstName ).append( " " ).append( lastName ) ), m_firstName( firstName ), m_lastName( lastName ), m_firstNameFirst( firstNameFirst )
11 years ago
{
// nothing
}
Person *Person::clone()
{
return new Person( m_firstName, m_lastName, m_firstNameFirst );
}
void Person::setText( const TQString& text )
11 years ago
{
ValueTextInterface::setText( text );
TQStringList segments;
11 years ago
bool containsComma = splitName( text, segments );
m_firstName = "";
m_lastName = "";
if ( segments.isEmpty() )
return;
if ( !containsComma )
{
/** PubMed uses a special writing style for names, where the last name is followed by single capital letter, each being the first letter of each first name */
/** So, check how many single capital letters are at the end of the given segment list */
int singleCapitalLettersCounter = 0;
int p = segments.count() - 1;
while ( segments[p].length() == 1 && segments[p].compare( segments[p].upper() ) == 0 )
{
--p;
++singleCapitalLettersCounter;
}
if ( singleCapitalLettersCounter > 0 )
{
/** this is a special case for names from PubMed, which are formatted like "Fischer T" */
/** all segment values until the first single letter segment are last name parts */
for ( int i = 0; i < p; ++i )
m_lastName.append( segments[i] ).append( " " );
m_lastName.append( segments[p] );
/** single letter segments are first name parts */
for ( unsigned int i = p + 1; i < segments.count() - 1; ++i )
m_firstName.append( segments[i] ).append( " " );
m_firstName.append( segments[segments.count() - 1] );
}
else
{
int from = segments.count() - 1;
m_lastName = segments[from];
/** check for lower case parts of the last name such as "van", "von", "de", ... */
while ( from > 0 )
{
if ( segments[from - 1].compare( segments[from - 1].lower() ) != 0 )
break;
--from;
m_lastName.prepend( " " );
m_lastName.prepend( segments[from] );
}
if ( from > 0 )
{
/** there are segments left for the first name */
m_firstName = *segments.begin();
for ( TQStringList::Iterator it = ++segments.begin(); from > 1; ++it, --from )
11 years ago
{
m_firstName.append( " " );
m_firstName.append( *it );
}
}
}
}
else
{
bool inLastName = TRUE;
for ( unsigned int i = 0; i < segments.count();++i )
{
if ( segments[i] == "," )
inLastName = FALSE;
else if ( inLastName )
{
if ( !m_lastName.isEmpty() ) m_lastName.append( " " );
m_lastName.append( segments[i] );
}
else
{
if ( !m_firstName.isEmpty() ) m_firstName.append( " " );
m_firstName.append( segments[i] );
}
}
}
}
TQString Person::text() const
11 years ago
{
return text( m_firstNameFirst );
}
TQString Person::text( bool firstNameFirst ) const
11 years ago
{
if ( m_firstName.isEmpty() )
return m_lastName;
else
return firstNameFirst ? m_firstName + " " + m_lastName : m_lastName + ", " + m_firstName;
}
TQString Person::firstName()
11 years ago
{
return m_firstName;
}
TQString Person::lastName()
11 years ago
{
return m_lastName;
}
/** Splits a name into single words. If the name's text was reversed (Last, First), the result will be true and the comma will be added to segments. Otherwise the functions result will be false. This function respects protecting {...}. */
bool Person::splitName( const TQString& text, TQStringList& segments )
11 years ago
{
int bracketCounter = 0;
bool result = FALSE;
TQString buffer = "";
11 years ago
for ( unsigned int pos = 0; pos < text.length(); ++pos )
{
if ( text[pos] == '{' )
++bracketCounter;
else if ( text[pos] == '}' )
--bracketCounter;
if ( text[pos] == ' ' && bracketCounter == 0 )
{
if ( !buffer.isEmpty() )
{
segments.append( buffer );
buffer = "";
}
}
else if ( text[pos] == ',' && bracketCounter == 0 )
{
if ( !buffer.isEmpty() )
{
segments.append( buffer );
buffer = "";
}
segments.append( "," );
result = TRUE;
}
else
buffer.append( text[pos] );
}
if ( !buffer.isEmpty() )
segments.append( buffer );
return result;
}
PersonContainer::PersonContainer( bool firstNameFirst ) : ValueItem( TQString::null ), m_firstNameFirst( firstNameFirst )
11 years ago
{
// nothing
}
PersonContainer::PersonContainer( const TQString& text, bool firstNameFirst ) : ValueItem( text ), m_firstNameFirst( firstNameFirst )
11 years ago
{
persons.append( new Person( text, m_firstNameFirst ) );
}
ValueItem *PersonContainer::clone()
{
PersonContainer *result = new PersonContainer( m_firstNameFirst );
for ( TQValueList<Person*>::ConstIterator it = persons.begin(); it != persons.end(); ++it )
11 years ago
result->persons.append(( *it )->clone() );
return result;
}
void PersonContainer::setText( const TQString& text )
11 years ago
{
ValueTextInterface::setText( text );
tqDebug( "You cannot set a text ('%s') to a Value object", text.latin1() );
11 years ago
}
TQString PersonContainer::text() const
11 years ago
{
TQString result;
11 years ago
bool first = TRUE;
for ( TQValueList<Person*>::ConstIterator it = persons.begin(); it != persons.end(); ++it )
11 years ago
{
if ( !first )
result.append( " and " );
else
first = FALSE;
result.append(( *it )->text() );
}
return result;
}
void PersonContainer::replace( const TQString &before, const TQString &after )
11 years ago
{
for ( TQValueList<Person*>::ConstIterator it = persons.begin(); it != persons.end(); ++it )
11 years ago
( *it )->replace( before, after );
}
MacroKey::MacroKey( const TQString& text ) : ValueItem( text )
11 years ago
{
m_isValid = isValidInternal();
}
ValueItem *MacroKey::clone()
{
return new MacroKey( text() );
}
void MacroKey::setText( const TQString& text )
11 years ago
{
ValueItem::setText( text );
m_isValid = isValidInternal();
}
bool MacroKey::isValid()
{
return m_isValid;
}
bool MacroKey::isValidInternal()
{
return !text().contains( TQRegExp( "![-.:/+_a-zA-Z0-9]" ) );
11 years ago
}
PlainText::PlainText( const TQString& text ) : ValueItem( text )
11 years ago
{
// nothing
}
ValueItem *PlainText::clone()
{
return new PlainText( text() );
}
Value::Value() : ValueTextInterface( TQString::null )
11 years ago
{
// nothing
}
Value::Value( const Value *other ) : ValueTextInterface( other )
{
for ( TQValueList<ValueItem*>::ConstIterator it = other->items.begin(); it != other->items.end(); ++it )
11 years ago
items.append(( *it )->clone() );
}
Value::Value( const TQString& text, bool isMacroKey ): ValueTextInterface( text )
11 years ago
{
ValueItem *item = NULL;
if ( isMacroKey )
item = new MacroKey( text );
else
item = new PlainText( text );
items.append( item );
}
void Value::setText( const TQString& text )
11 years ago
{
ValueTextInterface::setText( text );
tqDebug( "You cannot set a text ('%s') to a Value object", text.latin1() );
11 years ago
}
TQString Value::text() const
11 years ago
{
TQString result;
11 years ago
for ( TQValueList<ValueItem*>::ConstIterator it = items.begin(); it != items.end(); ++it )
11 years ago
result.append(( *it )->text() );
return result;
}
void Value::replace( const TQString &before, const TQString &after )
11 years ago
{
for ( TQValueList<ValueItem*>::ConstIterator it = items.begin(); it != items.end(); ++it )
11 years ago
( *it )->replace( before, after );
}
}