diff --git a/kpimidentities/signature.cpp b/kpimidentities/signature.cpp index 7761bafc6..c3d1618bd 100644 --- a/kpimidentities/signature.cpp +++ b/kpimidentities/signature.cpp @@ -1,371 +1,372 @@ /* Copyright (c) 2002-2004 Marc Mutz Copyright (c) 2007 Tom Albers This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "signature.h" #include #include #include #include #include #include #include #include #include #include using namespace KPIMIdentities; Signature::Signature() : mType( Disabled ), mInlinedHtml( false ) {} Signature::Signature( const QString &text ) : mText( text ), mType( Inlined ), mInlinedHtml( false ) {} Signature::Signature( const QString &url, bool isExecutable ) : mUrl( url ), mType( isExecutable ? FromCommand : FromFile ), mInlinedHtml( false ) {} QString Signature::rawText( bool *ok ) const { switch ( mType ) { case Disabled: if ( ok ) { *ok = true; } return QString(); case Inlined: if ( ok ) { *ok = true; } return mText; case FromFile: return textFromFile( ok ); case FromCommand: return textFromCommand( ok ); }; kFatal(5325) << "Signature::type() returned unknown value!"; return QString(); // make compiler happy } QString Signature::textFromCommand( bool *ok ) const { assert( mType == FromCommand ); // handle pathological cases: if ( mUrl.isEmpty() ) { if ( ok ) { *ok = true; } return QString(); } // create a shell process: KProcess proc; proc.setOutputChannelMode( KProcess::SeparateChannels ); proc.setShellCommand( mUrl ); int rc = proc.execute(); // handle errors, if any: if ( rc != 0 ) { if ( ok ) { *ok = false; } QString wmsg = i18n( "Failed to execute signature script

%1:

" "

%2

", mUrl, QString( proc.readAllStandardError() ) ); KMessageBox::error( 0, wmsg ); return QString(); } // no errors: if ( ok ) { *ok = true; } // get output: QByteArray output = proc.readAllStandardOutput(); // TODO: hmm, should we allow other encodings, too? return QString::fromLocal8Bit( output.data(), output.size() ); } QString Signature::textFromFile( bool *ok ) const { assert( mType == FromFile ); // TODO: Use KIO::NetAccess to download non-local files! if ( !KUrl( mUrl ).isLocalFile() && !( QFileInfo( mUrl ).isRelative() && QFileInfo( mUrl ).exists() ) ) { kDebug(5325) << "Signature::textFromFile:" << "non-local URLs are unsupported"; if ( ok ) { *ok = false; } return QString(); } if ( ok ) { *ok = true; } // TODO: hmm, should we allow other encodings, too? const QByteArray ba = KPIMUtils::kFileToByteArray( mUrl, false ); return QString::fromLocal8Bit( ba.data(), ba.size() ); } QString Signature::withSeparator( bool *ok ) const { QString signature = rawText( ok ); if ( ok && (*ok) == false ) return QString(); if ( signature.isEmpty() ) { return signature; // don't add a separator in this case } QString newline = ( isInlinedHtml() && mType == Inlined ) ? "
" : "\n"; if ( signature.startsWith( QString::fromLatin1( "-- " ) + newline ) || ( signature.indexOf( newline + QString::fromLatin1( "-- " ) + newline ) != -1 ) ) { // already have signature separator at start of sig or inside sig: return signature; } else { // need to prepend one: return QString::fromLatin1( "-- " ) + newline + signature; } } void Signature::setUrl( const QString &url, bool isExecutable ) { mUrl = url; mType = isExecutable ? FromCommand : FromFile; } void Signature::setInlinedHtml( bool isHtml ) { mInlinedHtml = isHtml; } bool Signature::isInlinedHtml() const { return mInlinedHtml; } // config keys and values: static const char sigTypeKey[] = "Signature Type"; static const char sigTypeInlineValue[] = "inline"; static const char sigTypeFileValue[] = "file"; static const char sigTypeCommandValue[] = "command"; static const char sigTypeDisabledValue[] = "disabled"; static const char sigTextKey[] = "Inline Signature"; static const char sigFileKey[] = "Signature File"; static const char sigCommandKey[] = "Signature Command"; static const char sigTypeInlinedHtmlKey[] = "Inlined Html"; void Signature::readConfig( const KConfigGroup &config ) { QString sigType = config.readEntry( sigTypeKey ); if ( sigType == sigTypeInlineValue ) { mType = Inlined; mInlinedHtml = config.readEntry( sigTypeInlinedHtmlKey, false ); } else if ( sigType == sigTypeFileValue ) { mType = FromFile; mUrl = config.readPathEntry( sigFileKey, QString() ); } else if ( sigType == sigTypeCommandValue ) { mType = FromCommand; mUrl = config.readPathEntry( sigCommandKey, QString() ); } else { mType = Disabled; } mText = config.readEntry( sigTextKey ); } void Signature::writeConfig( KConfigGroup &config ) const { switch ( mType ) { case Inlined: config.writeEntry( sigTypeKey, sigTypeInlineValue ); config.writeEntry( sigTypeInlinedHtmlKey, mInlinedHtml ); break; case FromFile: config.writeEntry( sigTypeKey, sigTypeFileValue ); config.writePathEntry( sigFileKey, mUrl ); break; case FromCommand: config.writeEntry( sigTypeKey, sigTypeCommandValue ); config.writePathEntry( sigCommandKey, mUrl ); break; case Disabled: config.writeEntry( sigTypeKey, sigTypeDisabledValue ); default: break; } config.writeEntry( sigTextKey, mText ); } void Signature::insertIntoTextEdit( KRichTextEdit *textEdit, Placement placement, bool addSeparator ) { QString signature; if ( addSeparator ) signature = withSeparator(); else signature = rawText(); insertPlainSignatureIntoTextEdit( signature, textEdit, placement, ( isInlinedHtml() && type() == KPIMIdentities::Signature::Inlined ) ); } void Signature::insertPlainSignatureIntoTextEdit( const QString &signature, KRichTextEdit *textEdit, Signature::Placement placement, bool isHtml ) { if ( !signature.isEmpty() ) { // Save the modified state of the document, as inserting a signature // shouldn't change this. Restore it at the end of this function. bool isModified = textEdit->document()->isModified(); // Move to the desired position, where the signature should be inserted QTextCursor cursor = textEdit->textCursor(); QTextCursor oldCursor = cursor; cursor.beginEditBlock(); if ( placement == End ) cursor.movePosition( QTextCursor::End ); else if ( placement == Start ) cursor.movePosition( QTextCursor::Start ); textEdit->setTextCursor( cursor ); // Insert the signature and newlines depending on where it was inserted. bool hackForCursorsAtEnd = false; int oldCursorPos = -1; if ( placement == End ) { if ( oldCursor.position() == textEdit->toPlainText().length() ) { hackForCursorsAtEnd = true; oldCursorPos = oldCursor.position(); } if ( isHtml ) { textEdit->insertHtml( QLatin1String( "
" ) + signature ); } else { textEdit->insertPlainText( QLatin1Char( '\n' ) + signature ); } } else if ( placement == Start || placement == AtCursor ) { if ( isHtml ) { textEdit->insertHtml( QLatin1String( "
" ) + signature + QLatin1String( "
" ) ); } else { textEdit->insertPlainText( QLatin1Char( '\n' ) + signature + QLatin1Char( '\n' ) ); } } cursor.endEditBlock(); // There is one special case when re-setting the old cursor: The cursor // was at the end. In this case, QTextEdit has no way to know // if the signature was added before or after the cursor, and just decides // that it was added before (and the cursor moves to the end, but it should // not when appending a signature). See bug 167961 if ( hackForCursorsAtEnd ) oldCursor.setPosition( oldCursorPos ); textEdit->setTextCursor( oldCursor ); textEdit->ensureCursorVisible(); textEdit->document()->setModified( isModified ); if ( isHtml ) textEdit->enableRichTextMode(); } } // --------------------- Operators -------------------// QDataStream &KPIMIdentities::operator<< ( QDataStream &stream, const KPIMIdentities::Signature &sig ) { return stream << static_cast( sig.mType ) << sig.mUrl << sig.mText; } QDataStream &KPIMIdentities::operator>> ( QDataStream &stream, KPIMIdentities::Signature &sig ) { quint8 s; stream >> s >> sig.mUrl >> sig.mText; sig.mType = static_cast( s ); return stream; } bool Signature::operator== ( const Signature &other ) const { if ( mType != other.mType ) { return false; } switch ( mType ) { case Inlined: return mText == other.mText; case FromFile: case FromCommand: return mUrl == other.mUrl; default: case Disabled: return true; } } // --------------- Getters -----------------------// QString Signature::text() const { return mText; } QString Signature::url() const { return mUrl; } Signature::Type Signature::type() const { return mType; } // --------------- Setters -----------------------// void Signature::setText( const QString &text ) { mText = text; + mType = Inlined; } void Signature::setType( Type type ) { mType = type; } diff --git a/kpimidentities/tests/CMakeLists.txt b/kpimidentities/tests/CMakeLists.txt index c014248e8..a5d58d6e4 100644 --- a/kpimidentities/tests/CMakeLists.txt +++ b/kpimidentities/tests/CMakeLists.txt @@ -1,9 +1,20 @@ set (identitytest_SRCS identitytest.cpp ) kde4_add_unit_test (identitytest TESTNAME identitytest ${identitytest_SRCS}) target_link_libraries ( identitytest ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} ${KDE4_KDECORE_LIBS} kpimidentities ) + +set (signaturetest_SRCS signaturetest.cpp ) +kde4_add_unit_test (signaturetest TESTNAME signaturetest ${signaturetest_SRCS}) + +target_link_libraries ( signaturetest + ${QT_QTTEST_LIBRARY} + ${QT_QTCORE_LIBRARY} + ${KDE4_KDECORE_LIBS} + kpimidentities + kpimtextedit + ) diff --git a/kpimidentities/tests/signaturetest.cpp b/kpimidentities/tests/signaturetest.cpp new file mode 100644 index 000000000..c9da83bff --- /dev/null +++ b/kpimidentities/tests/signaturetest.cpp @@ -0,0 +1,71 @@ +/* + Copyright (c) 20089 Thomas McGuire + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ +#include "qtest_kde.h" +#include "signaturetest.h" + +#include "../signature.h" + +#include "kpimtextedit/textedit.h" + +using namespace KPIMIdentities; +using namespace KPIMTextEdit; + +QTEST_KDEMAIN( SignatureTester, GUI ) + +void SignatureTester::testSignatures() +{ + Signature sig1; + sig1.setText( "Hello World" ); + QCOMPARE( sig1.text(), QString( "Hello World" ) ); + QCOMPARE( sig1.type(), Signature::Inlined ); + QCOMPARE( sig1.rawText(), QString( "Hello World" ) ); + QVERIFY( !sig1.isInlinedHtml() ); + QCOMPARE( sig1.withSeparator(), QString( "-- \nHello World" ) ); + + Signature sig2; + sig2.setText( "Hello World" ); + sig2.setInlinedHtml( true ); + QVERIFY( sig2.isInlinedHtml() ); + QCOMPARE( sig2.type(), Signature::Inlined ); + QCOMPARE( sig2.rawText(), QString( "Hello World" ) ); + QCOMPARE( sig2.withSeparator(), QString( "--
Hello World" ) ); + + // Read this very file in, we use it for the tests + QFile thisFile( __FILE__ ); + thisFile.open( QIODevice::ReadOnly ); + QString fileContent = QString::fromUtf8( thisFile.readAll() ); + + Signature sig3; + sig3.setUrl( QString( "cat " ) + QString( __FILE__ ), true ); + QCOMPARE( sig3.rawText(), fileContent ); + QVERIFY( !sig3.isInlinedHtml() ); + QVERIFY( sig3.text().isEmpty() ); + QCOMPARE( sig3.type(), Signature::FromCommand ); + QCOMPARE( sig3.withSeparator(), QString( "-- \n" ) + fileContent ); + + Signature sig4; + sig4.setUrl( __FILE__, false ); + QCOMPARE( sig4.rawText(), fileContent ); + QVERIFY( !sig4.isInlinedHtml() ); + QVERIFY( sig4.text().isEmpty() ); + QCOMPARE( sig4.type(), Signature::FromFile ); + QCOMPARE( sig4.withSeparator(), QString( "-- \n" ) + fileContent ); + +} + diff --git a/kpimidentities/tests/signaturetest.h b/kpimidentities/tests/signaturetest.h new file mode 100644 index 000000000..8cdc853f8 --- /dev/null +++ b/kpimidentities/tests/signaturetest.h @@ -0,0 +1,33 @@ +/* + Copyright (c) 2009 Thomas McGuire + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#ifndef SIGNATURETEST_H +#define SIGNATURETEST_H + +#include + +class SignatureTester : public QObject +{ + Q_OBJECT + +private slots: + void testSignatures(); +}; + +#endif