25#include <klocalizedstring.h>
26#include <kmessagebox.h>
27#include <kconfiggroup.h>
30#include <KRichTextEdit>
31#include <kpimutils/kfileio.h>
34#include <QSharedPointer>
39#include <kpimtextedit/textedit.h>
41using namespace KPIMIdentities;
55 typedef QSharedPointer<EmbeddedImage> EmbeddedImagePtr;
59 QList<EmbeddedImagePtr> embeddedImages;
66QDataStream &operator<< ( QDataStream &stream,
const SignaturePrivate::EmbeddedImagePtr &img )
68 return stream << img->image << img->name;
71QDataStream &operator>> ( QDataStream &stream, SignaturePrivate::EmbeddedImagePtr &img )
73 return stream >> img->image >> img->name;
79typedef QHash<const Signature*,SignaturePrivate*> SigPrivateHash;
80Q_GLOBAL_STATIC( SigPrivateHash, d_func )
82static SignaturePrivate* d(
const Signature *sig )
84 SignaturePrivate *ret = d_func()->value( sig, 0 );
86 ret =
new SignaturePrivate;
87 d_func()->insert( sig, ret );
92static void delete_d(
const Signature* sig )
94 SignaturePrivate *ret = d_func()->value( sig, 0 );
96 d_func()->remove( sig );
101 mInlinedHtml( false )
107 mInlinedHtml( false )
112 mType( isExecutable ? FromCommand : FromFile ),
113 mInlinedHtml( false )
119 mInlinedHtml = that.mInlinedHtml;
122 d(
this )->enabled = d( &that )->enabled;
123 d(
this )->saveLocation = d( &that )->saveLocation;
124 d(
this )->embeddedImages = d( &that )->embeddedImages;
134 if (
this == &that ) {
161 return textFromFile( ok );
163 return textFromCommand( ok );
165 kFatal( 5325 ) <<
"Signature::type() returned unknown value!";
169QString Signature::textFromCommand(
bool *ok )
const
171 assert( mType == FromCommand );
174 if ( mUrl.isEmpty() ) {
183 proc.setOutputChannelMode( KProcess::SeparateChannels );
184 proc.setShellCommand( mUrl );
185 int rc = proc.execute();
192 QString wmsg = i18n(
"<qt>Failed to execute signature script<p><b>%1</b>:</p>"
193 "<p>%2</p></qt>", mUrl, QLatin1String( proc.readAllStandardError() ) );
194 KMessageBox::error( 0, wmsg );
204 QByteArray output = proc.readAllStandardOutput();
207 return QString::fromLocal8Bit( output.data(), output.size() );
210QString Signature::textFromFile(
bool *ok )
const
212 assert( mType == FromFile );
215 if ( !KUrl( mUrl ).isLocalFile() &&
216 !( QFileInfo( mUrl ).isRelative() &&
217 QFileInfo( mUrl ).exists() ) ) {
218 kDebug( 5325 ) <<
"Signature::textFromFile:"
219 <<
"non-local URLs are unsupported";
231 const QByteArray ba = KPIMUtils::kFileToByteArray( mUrl,
false );
232 return QString::fromLocal8Bit( ba.data(), ba.size() );
237 QString signature =
rawText( ok );
238 if ( ok && ( *ok ) ==
false ) {
242 if ( signature.isEmpty() ) {
246 const bool htmlSig = (
isInlinedHtml() && mType == Inlined );
247 QString newline = htmlSig ? QLatin1String(
"<br>") : QLatin1String(
"\n");
248 if ( htmlSig && signature.startsWith( QLatin1String(
"<p" ) ) ) {
252 if ( signature.startsWith( QString::fromLatin1(
"-- " ) + newline ) ||
253 ( signature.indexOf( newline + QString::fromLatin1(
"-- " ) + newline ) != -1 ) ) {
258 return QString::fromLatin1(
"-- " ) + newline + signature;
265 mType = isExecutable ? FromCommand : FromFile;
270 mInlinedHtml = isHtml;
279static const char sigTypeKey[] =
"Signature Type";
280static const char sigTypeInlineValue[] =
"inline";
281static const char sigTypeFileValue[] =
"file";
282static const char sigTypeCommandValue[] =
"command";
283static const char sigTypeDisabledValue[] =
"disabled";
284static const char sigTextKey[] =
"Inline Signature";
285static const char sigFileKey[] =
"Signature File";
286static const char sigCommandKey[] =
"Signature Command";
287static const char sigTypeInlinedHtmlKey[] =
"Inlined Html";
288static const char sigImageLocation[] =
"Image Location";
289static const char sigEnabled[] =
"Signature Enabled";
292static QStringList findImageNames(
const QString &htmlCode )
297 KPIMTextEdit::TextEdit edit;
298 edit.setHtml( htmlCode );
299 foreach (
const KPIMTextEdit::ImageWithNamePtr &image, edit.imagesWithName() ) {
305void Signature::cleanupImages()
const
309 foreach (
const SignaturePrivate::EmbeddedImagePtr &imageInList, d(
this )->embeddedImages ) {
311 foreach (
const QString &imageInHtml, findImageNames( mText ) ) {
312 if ( imageInHtml == imageInList->name ) {
318 d(
this )->embeddedImages.removeAll( imageInList );
324 if ( !d(
this )->saveLocation.isEmpty() ) {
325 QDir dir( d(
this )->saveLocation );
326 foreach (
const QString &fileName, dir.entryList( QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks ) ) {
327 if ( fileName.toLower().endsWith( QLatin1String(
".png" ) ) ) {
328 kDebug() <<
"Deleting old image" << dir.path() + fileName;
329 dir.remove( fileName );
335void Signature::saveImages()
const
337 if (
isInlinedHtml() && !d(
this )->saveLocation.isEmpty() ) {
338 foreach (
const SignaturePrivate::EmbeddedImagePtr &image, d(
this )->embeddedImages ) {
339 QString location = d(
this )->saveLocation + QLatin1Char(
'/') + image->name;
340 if ( !image->image.save( location,
"PNG" ) ) {
341 kWarning() <<
"Failed to save image" << location;
347void Signature::readConfig(
const KConfigGroup &config )
349 QString sigType = config.readEntry( sigTypeKey );
350 if ( sigType == QLatin1String(sigTypeInlineValue) ) {
352 mInlinedHtml = config.readEntry( sigTypeInlinedHtmlKey,
false );
353 }
else if ( sigType == QLatin1String(sigTypeFileValue) ) {
355 mUrl = config.readPathEntry( sigFileKey, QString() );
356 }
else if ( sigType == QLatin1String(sigTypeCommandValue) ) {
358 mUrl = config.readPathEntry( sigCommandKey, QString() );
359 }
else if ( sigType == QLatin1String(sigTypeDisabledValue) ) {
360 d(
this )->enabled =
false;
362 if ( mType != Disabled ) {
363 d(
this )->enabled = config.readEntry( sigEnabled,
true );
366 mText = config.readEntry( sigTextKey );
367 d(
this )->saveLocation = config.readEntry( sigImageLocation );
369 if (
isInlinedHtml() && !d(
this )->saveLocation.isEmpty() ) {
370 QDir dir( d(
this )->saveLocation );
371 foreach (
const QString &fileName, dir.entryList( QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks ) ) {
372 if ( fileName.toLower().endsWith( QLatin1String(
".png" ) ) ) {
374 if ( image.load( dir.path() + QLatin1Char(
'/') + fileName ) ) {
378 kWarning() <<
"Unable to load image" << dir.path() + QLatin1Char(
'/') + fileName;
385void Signature::writeConfig( KConfigGroup &config )
const
389 config.writeEntry( sigTypeKey, sigTypeInlineValue );
390 config.writeEntry( sigTypeInlinedHtmlKey, mInlinedHtml );
393 config.writeEntry( sigTypeKey, sigTypeFileValue );
394 config.writePathEntry( sigFileKey, mUrl );
397 config.writeEntry( sigTypeKey, sigTypeCommandValue );
398 config.writePathEntry( sigCommandKey, mUrl );
403 config.writeEntry( sigTextKey, mText );
404 config.writeEntry( sigImageLocation, d(
this )->saveLocation );
405 config.writeEntry( sigEnabled, d(
this )->enabled );
411static bool isCursorAtEndOfLine(
const QTextCursor &cursor )
413 QTextCursor testCursor = cursor;
414 testCursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
415 return !testCursor.hasSelection();
418static void insertSignatureHelper(
const QString &signature,
419 KRichTextEdit *textEdit,
424 if ( !signature.isEmpty() ) {
428 bool isModified = textEdit->document()->isModified();
431 QTextCursor cursor = textEdit->textCursor();
432 QTextCursor oldCursor = cursor;
433 cursor.beginEditBlock();
436 cursor.movePosition( QTextCursor::End );
438 cursor.movePosition( QTextCursor::Start );
440 cursor.movePosition( QTextCursor::StartOfLine );
442 textEdit->setTextCursor( cursor );
448 lineSep = QLatin1String(
"<br>" );
450 lineSep = QLatin1Char(
'\n' );
455 int newCursorPos = -1;
464 if ( oldCursor.position() == textEdit->toPlainText().length() ) {
465 newCursorPos = oldCursor.position();
473 headSep = lineSep + lineSep;
474 if ( !isCursorAtEndOfLine( cursor ) ) {
478 if ( !isCursorAtEndOfLine( cursor ) ) {
483 const QString full_signature = headSep + signature + tailSep;
485 textEdit->insertHtml( full_signature );
487 textEdit->insertPlainText( full_signature );
490 cursor.endEditBlock();
492 if ( newCursorPos != -1 ) {
493 oldCursor.setPosition( newCursorPos );
496 textEdit->setTextCursor( oldCursor );
497 textEdit->ensureCursorVisible();
499 textEdit->document()->setModified( isModified );
502 textEdit->enableRichTextMode();
510 if ( !isEnabledSignature() ) {
514 if ( addSeparator ) {
519 insertSignatureHelper( signature, textEdit, placement,
521 type() == KPIMIdentities::Signature::Inlined ),
526 KPIMTextEdit::TextEdit *textEdit )
const
528 insertSignatureText( placement, addedText, textEdit,
false );
532 KPIMTextEdit::TextEdit *textEdit,
bool forceDisplay )
const
534 insertSignatureText( placement, addedText, textEdit, forceDisplay );
537void Signature::insertSignatureText(Placement placement, AddedText addedText, KPIMTextEdit::TextEdit *textEdit,
bool forceDisplay)
const
539 if ( !forceDisplay ) {
540 if ( !isEnabledSignature() ) {
550 insertSignatureHelper( signature, textEdit, placement,
552 type() == KPIMIdentities::Signature::Inlined ),
557 foreach (
const SignaturePrivate::EmbeddedImagePtr &image, d(
this )->embeddedImages ) {
558 textEdit->loadImage( image->image, image->name, image->name );
567 insertSignatureHelper( signature, textEdit, placement, isHtml,
true );
572QDataStream &KPIMIdentities::operator<<
575 return stream << static_cast<quint8>( sig.mType ) << sig.mUrl << sig.mText
576 << d( &sig )->saveLocation << d( &sig )->embeddedImages << d( &sig )->enabled;
579QDataStream &KPIMIdentities::operator>>
583 stream >> s >> sig.mUrl >> sig.mText >> d( &sig )->saveLocation >> d( &sig )->embeddedImages >>d( &sig )->enabled;
590 if ( mType != other.mType ) {
594 if ( d(
this )->enabled != d( &other )->enabled ) {
598 if ( mType == Inlined && mInlinedHtml ) {
599 if ( d(
this )->saveLocation != d( &other )->saveLocation ) {
602 if ( d(
this )->embeddedImages != d( &other )->embeddedImages ) {
609 return mText == other.mText;
612 return mUrl == other.mUrl;
625 QTextDocument helper;
626 QTextCursor helperCursor( &helper );
627 helperCursor.insertHtml( sigText );
628 sigText = helper.toPlainText();
635 Q_ASSERT( !( d(
this )->saveLocation.isEmpty() ) );
636 SignaturePrivate::EmbeddedImagePtr image(
new SignaturePrivate::EmbeddedImage() );
637 image->image = imageData;
638 image->name = imageName;
639 d(
this )->embeddedImages.append( image );
644 d(
this )->saveLocation = path;
649QString Signature::text()
const
654QString Signature::url()
const
672void Signature::setType( Type type )
680 d(
this )->enabled = enabled;
683bool Signature::isEnabledSignature()
const
685 return d(
this )->enabled;
Abstraction of a signature (aka "footer").
bool operator==(const Signature &other) const
Used for comparison.
QFlags< AddedTextFlag > AddedText
Describes which additional parts should be added to the signature.
void KPIMIDENTITIES_DEPRECATED insertIntoTextEdit(KRichTextEdit *textEdit, Placement placement=End, bool addSeparator=true)
void setText(const QString &text)
Set the signature text and mark this signature as being of "inline text" type.
Placement
Describes the placement of the signature text when it is to be inserted into a text edit.
@ End
The signature is placed at the end of the textedit.
@ AtCursor
The signature is placed at the current cursor position.
@ Start
The signature is placed at the start of the textedit.
void setImageLocation(const QString &path)
Sets the location where the copies of the signature images will be stored.
static void KPIMIDENTITIES_DEPRECATED insertPlainSignatureIntoTextEdit(const QString &signature, KRichTextEdit *textEdit, Placement placement=End, bool isHtml=false)
Inserts this given signature into the given text edit.
@ AddNewLines
Add a newline character in front or after the signature, depending on the placement.
@ AddSeparator
The separator '– ' will be added in front of the signature.
void setInlinedHtml(bool isHtml)
Sets the inlined signature to text or html.
void setUrl(const QString &url, bool isExecutable=false)
Set the signature URL and mark this signature as being of "from file" resp.
bool isInlinedHtml() const
Signature()
Constructor for disabled signature.
QString rawText(bool *ok=0) const
void setEnabledSignature(bool enabled)
setEnabledSignature
QString toPlainText() const
Returns the text of the signature.
void addImage(const QImage &image, const QString &imageName)
Adds the given image to the signature.
Type
Type of signature (ie.
Signature & operator=(const Signature &that)
Assignment operator.
QString withSeparator(bool *ok=0) const