diff --git a/kpimidentities/signature.cpp b/kpimidentities/signature.cpp index 6ce71c6dc..5bd23bbe5 100644 --- a/kpimidentities/signature.cpp +++ b/kpimidentities/signature.cpp @@ -1,386 +1,549 @@ /* Copyright (c) 2002-2004 Marc Mutz Copyright (c) 2007 Tom Albers + 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. */ #include "signature.h" #include #include #include #include #include #include #include #include #include +#include +#include + #include +#include +#include using namespace KPIMIdentities; +class SignaturePrivate +{ + public: + struct EmbeddedImage + { + QImage image; + QString name; + }; + typedef QSharedPointer EmbeddedImagePtr; + + /// List of images that belong to this signature. Either added by addImage() or + /// by readConfig(). + QList embeddedImages; + + /// The directory where the images will be saved to. + QString saveLocation; +}; + +QDataStream &operator<< ( QDataStream &stream, const SignaturePrivate::EmbeddedImagePtr &img ) +{ + return stream << img->image << img->name; +} + +QDataStream &operator>> ( QDataStream &stream, SignaturePrivate::EmbeddedImagePtr &img ) +{ + return stream >> img->image >> img->name; +} + +// TODO: KDE5: BIC: Add a real d-pointer. +// This QHash is just a workaround around BIC issues, for more info see +// http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++ +typedef QHash SigPrivateHash; +Q_GLOBAL_STATIC(SigPrivateHash, d_func) + +static SignaturePrivate* d( const Signature *sig ) +{ + SignaturePrivate *ret = d_func()->value( sig, 0 ); + if ( !ret ) { + ret = new SignaturePrivate; + d_func()->insert( sig, ret ); + } + return ret; +} + +static void delete_d( const Signature* sig ) +{ + SignaturePrivate *ret = d_func()->value( sig, 0 ); + delete ret; + d_func()->remove( sig ); +} + 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 ) {} +void Signature::assignFrom ( const KPIMIdentities::Signature &that ) +{ + mUrl = that.mUrl; + mInlinedHtml = that.mInlinedHtml; + mText = that.mText; + mType = that.mType; + d( this )->saveLocation = d( &that )->saveLocation; + d( this )->embeddedImages = d( &that )->embeddedImages; +} + +Signature::Signature ( const Signature &that ) +{ + assignFrom( that ); +} + +Signature& Signature::operator= ( const KPIMIdentities::Signature & that ) +{ + if ( this == &that ) + return *this; + + assignFrom( that ); + return *this; +} + +Signature::~Signature() +{ + delete_d( this ); +} + 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"; +static const char sigImageLocation[] = "Image Location"; 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 ); + d( this )->saveLocation = config.readEntry( sigImageLocation ); + + if ( isInlinedHtml() && !d( this )->saveLocation.isEmpty() ) { + QDir dir( d( this )->saveLocation ); + foreach( const QString &fileName, dir.entryList( QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks ) ) { + if ( fileName.toLower().endsWith( ".png" ) ) { + QImage image; + if ( image.load( dir.path() + '/' + fileName ) ) { + addImage( image, fileName ); + } + else { + kWarning() << "Unable to load image" << dir.path() + '/' + fileName; + } + } + } + } } 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 ); + config.writeEntry( sigImageLocation, d( this )->saveLocation ); + + // First delete the old image files + if ( !d( this )->saveLocation.isEmpty() ) { + QDir dir( d( this )->saveLocation ); + foreach( const QString &fileName, dir.entryList( QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks ) ) { + if ( fileName.toLower().endsWith( ".png" ) ) { + kDebug() << "Deleting old image" << dir.path() + fileName; + dir.remove( fileName ); + } + } + } + + // Then, save the new images + if ( isInlinedHtml() && !d( this )->saveLocation.isEmpty() ) { + foreach( const SignaturePrivate::EmbeddedImagePtr &image, d( this )->embeddedImages ) { + QString location = d( this )->saveLocation + '/' + image->name; + if ( !image->image.save( location, "PNG" ) ) { + kWarning() << "Failed to save image" << location; + } + } + } } void Signature::insertIntoTextEdit( KRichTextEdit *textEdit, Placement placement, bool addSeparator ) +{ + // Bah. + const_cast( this )->insertIntoTextEdit( textEdit, placement, addSeparator ); +} + +void Signature::insertIntoTextEdit( KRichTextEdit *textEdit, + Placement placement, bool addSeparator ) const { QString signature; if ( addSeparator ) signature = withSeparator(); else signature = rawText(); insertPlainSignatureIntoTextEdit( signature, textEdit, placement, ( isInlinedHtml() && type() == KPIMIdentities::Signature::Inlined ) ); + + // We added the text of the signature above, now it is time to add the images as well. + KPIMTextEdit::TextEdit *pimEdit = dynamic_cast( textEdit ); + if ( pimEdit && isInlinedHtml() ) { + foreach( const SignaturePrivate::EmbeddedImagePtr &image, d( this )->embeddedImages ) { + pimEdit->loadImage( image->image, image->name, image->name ); + } + } } 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 ) + if ( isHtml ) { textEdit->enableRichTextMode(); + } } } // --------------------- Operators -------------------// QDataStream &KPIMIdentities::operator<< ( QDataStream &stream, const KPIMIdentities::Signature &sig ) { - return stream << static_cast( sig.mType ) << sig.mUrl << sig.mText; + return stream << static_cast( sig.mType ) << sig.mUrl << sig.mText + << d( &sig )->saveLocation << d( &sig )->embeddedImages; } QDataStream &KPIMIdentities::operator>> ( QDataStream &stream, KPIMIdentities::Signature &sig ) { quint8 s; - stream >> s >> sig.mUrl >> sig.mText; + stream >> s >> sig.mUrl >> sig.mText >> d( &sig )->saveLocation >> d( &sig )->embeddedImages; sig.mType = static_cast( s ); return stream; } bool Signature::operator== ( const Signature &other ) const { if ( mType != other.mType ) { return false; } + if ( mType == Inlined && mInlinedHtml ) { + if ( d( this )->saveLocation != d( &other )->saveLocation ) + return false; + if ( d( this )->embeddedImages != d( &other )->embeddedImages ) + return false; + } + switch ( mType ) { case Inlined: return mText == other.mText; case FromFile: case FromCommand: return mUrl == other.mUrl; default: case Disabled: return true; } } QString Signature::plainText() const { QString sigText = rawText(); if ( isInlinedHtml() && type() == Inlined ) { // Use a QTextDocument as a helper, it does all the work for us and // strips all HTML tags. QTextDocument helper; QTextCursor helperCursor( &helper ); helperCursor.insertHtml( sigText ); sigText = helper.toPlainText(); } return sigText; } +void Signature::addImage ( const QImage& imageData, const QString& imageName ) +{ + Q_ASSERT( !( d( this )->saveLocation.isEmpty() ) ); + SignaturePrivate::EmbeddedImagePtr image( new SignaturePrivate::EmbeddedImage() ); + image->image = imageData; + image->name = imageName; + d( this )->embeddedImages.append( image ); +} + +void Signature::setImageLocation ( const QString& path ) +{ + d( this )->saveLocation = path; +} + // --------------- 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/signature.h b/kpimidentities/signature.h index f6aa795e4..0de5aa3dd 100644 --- a/kpimidentities/signature.h +++ b/kpimidentities/signature.h @@ -1,195 +1,265 @@ /* Copyright (c) 2002-2004 Marc Mutz Copyright (c) 2007 Tom Albers + Copyright (c) 2009 Thomas McGuire Author: Stefan Taferner 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 KPIMIDENTITIES_SIGNATURE_H #define KPIMIDENTITIES_SIGNATURE_H #include "kpimidentities_export.h" #include #include #include #include #include #include namespace KPIMIdentities { class Signature; + class Identity; } class KConfigGroup; class KRichTextEdit; namespace KPIMIdentities { KPIMIDENTITIES_EXPORT QDataStream &operator<< ( QDataStream &stream, const KPIMIdentities::Signature &sig ); KPIMIDENTITIES_EXPORT QDataStream &operator>> ( QDataStream &stream, KPIMIdentities::Signature &sig ); /** - * @short abstraction of a signature (aka "footer"). - * @author Marc Mutz + * @short Abstraction of a signature (aka "footer"). + * + * The signature can either be plain text, HTML text, text returned from a command or text stored + * in a file. + * + * In case of HTML text, the signature can contain images. + * Since you set the HTML source with setText(), there also needs to be a way to add the images + * to the signature, as the HTML source contains only the img tags that reference those images. + * To add the image to the signature, call addImage(). The name given there must match the name + * of the img tag in the HTML source. + * + * The images need to be stored somewhere. The Signature class handles that by storing all images + * in a directory. You must set that directory with setImageLocation(), before calling addImage(). + * The images added with addImage() are then saved to that directory when calling writeConfig(). + * When loading a signature, readConfig() automatically loads the images as well. + * To actually add the images to a text edit, call insertIntoTextEdit(). */ class KPIMIDENTITIES_EXPORT Signature { friend class Identity; friend KPIMIDENTITIES_EXPORT QDataStream &operator<< ( QDataStream &stream, const Signature &sig ); friend KPIMIDENTITIES_EXPORT QDataStream &operator>> ( QDataStream &stream, Signature &sig ); public: /** Type of signature (ie. way to obtain the signature text) */ enum Type { Disabled = 0, Inlined = 1, FromFile = 2, FromCommand = 3 }; /** * Describes the placement of the signature text when it is to be inserted into a * text edit */ enum Placement { Start, ///< The signature is placed at the start of the textedit End, ///< The signature is placed at the end of the textedit AtCursor ///< The signature is placed at the current cursor position }; /** Used for comparison */ bool operator== ( const Signature &other ) const; /** Constructor for disabled signature */ Signature(); /** Constructor for inline text */ Signature( const QString &text ); /** Constructor for text from a file or from output of a command */ Signature( const QString &url, bool isExecutable ); + /** Copy constructor */ + Signature( const Signature &that ); + /** Assignment operator */ + Signature& operator= ( const Signature &that ); + /** Destructor */ + ~Signature(); /** @return the raw signature text as entered resp. read from file. */ QString rawText( bool *ok=0 ) const; /** @return the signature text with a "-- \n" separator added, if necessary. A newline will not be appended or prepended. */ QString withSeparator( bool *ok=0 ) const; /** Set the signature text and mark this signature as being of "inline text" type. */ void setText( const QString &text ); QString text() const; /** * Returns the text of the signature. If the signature is HTML, the HTML * tags will be stripped. * @since 4.4 */ QString plainText() const; /** Set the signature URL and mark this signature as being of "from file" resp. "from output of command" type. */ void setUrl( const QString &url, bool isExecutable=false ); QString url() const; /// @return the type of signature (ie. way to obtain the signature text) Type type() const; void setType( Type type ); /** * Sets the inlined signature to text or html * @param isHtml sets the inlined signature to html * @since 4.1 */ void setInlinedHtml( bool isHtml ); /** * @return boolean whether the inlined signature is html * @since 4.1 */ bool isInlinedHtml() const; + /** + * Sets the location where the copies of the signature images will be stored. + * The images will be stored there when calling writeConfig(). The image location + * is stored in the config, so the next readConfig() call knows where to look for + * images. + * It is recommended to use KStandardDirs::locateLocal( "data", "emailidentities/%1" ) + * for the location, where %1 is the unique identifier of the identity. + * + * @warning readConfig will delete all other PNG files in this directory, as they could + * be stale inline image files + * + * Like with addImage(), the SignatureConfigurator will handle this for you. + * + * @since 4.4 + */ + void setImageLocation( const QString &path ); + + /** + * Adds the given image to the signature. + * This is needed if you use setText() to set some HTML source that references images. Those + * referenced images needed to be added by calling this function. The @imageName has to match + * the src attribute of the img tag. + * + * If you use SignatureConfigurator, you don't need to call this function, as the configurator + * will handle this for you. + * setImageLocation() needs to be called once before. + * @since 4.4 + */ + void addImage( const QImage &image, const QString &imageName ); /** * Inserts this signature into the given text edit. * The cursor position is preserved. * A leading or trailing newline is also added automatically, depending on * the placement. * For undo/redo, this is treated as one operation. * * Rich text mode of the text edit will be enabled if the signature is in * inlined HTML format. * + * If this signature uses images, they will be added automatically. + * * @param textEdit the signature will be inserted into this text edit. * @param placement defines where in the text edit the signature should be * inserted. * @param addSeparator if true, the separator '-- \n' will be added in front * of the signature * * @since 4.3 + * TODO: KDE5: BIC: remove, as we have a const version below + * TODO: KDE5: BIC: Change from KRichTextEdit to KPIMTextEdit::TextEdit, to avoid + * the dynamic_cast used here */ void insertIntoTextEdit( KRichTextEdit *textEdit, Placement placement = End, bool addSeparator = true ); + /** + * Same as the other insertIntoTextEdit(), only that this is the const version + * @since 4.4 + */ + void insertIntoTextEdit( KRichTextEdit *textEdit, + Placement placement = End, bool addSeparator = true ) const; + /** * Inserts this given signature into the given text edit. * The cursor position is preserved. * A leading or trailing newline is also added automatically, depending on * the placement. * For undo/redo, this is treated as one operation. * A separator is not added. * * Use the insertIntoTextEdit() function if possible, as it has support * for separators and does HTML detection automatically. * * Rich text mode of the text edit will be enabled if @p isHtml is true. * * @param signature the signature, either as plain text or as HTML * @param textEdit the text edit to insert the signature into * @param placement defines where in the textedit the signature should be * inserted. * @param isHtml defines whether the signature should be inserted as text or html * * @since 4.3 */ static void insertPlainSignatureIntoTextEdit( const QString &signature, KRichTextEdit *textEdit, Placement placement = End, bool isHtml = false ); protected: void writeConfig( KConfigGroup &config ) const; void readConfig( const KConfigGroup &config ); + /** + * Helper used for the copy constructor and the assignment operator + */ + void assignFrom( const Signature &that ); + private: QString textFromFile( bool *ok ) const; QString textFromCommand( bool *ok ) const; + // TODO: KDE5: BIC: Add a d-pointer!!! + // There is already a pseude private class in the .cpp, using a hash. QString mUrl; QString mText; Type mType; bool mInlinedHtml; }; } #endif /*kpim_signature_h*/ diff --git a/kpimidentities/signatureconfigurator.cpp b/kpimidentities/signatureconfigurator.cpp index 802f3d75e..52fcda16b 100644 --- a/kpimidentities/signatureconfigurator.cpp +++ b/kpimidentities/signatureconfigurator.cpp @@ -1,418 +1,465 @@ /* -*- c++ -*- Copyright 2008 Thomas McGuire Copyright 2008 Edwin Schepers Copyright 2004 Marc Mutz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "signatureconfigurator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KPIMIdentities; namespace KPIMIdentities { /** Private class that helps to provide binary compatibility between releases. @internal */ //@cond PRIVATE -class KPIMIdentities::SignatureConfigurator::Private +class SignatureConfigurator::Private { public: + Private( SignatureConfigurator *parent ); + void init(); + + SignatureConfigurator *q; bool inlinedHtml; + HtmlImageMode imageMode; + QString imageLocation; }; //@endcond -SignatureConfigurator::SignatureConfigurator( QWidget * parent ) - : QWidget( parent ), d( new Private ) +SignatureConfigurator::Private::Private( SignatureConfigurator *parent ) + :q( parent ), imageMode( DisableHtmlImages ) +{ +} + +void SignatureConfigurator::Private::init() +{ + // tmp. vars: + QLabel * label; + QWidget * page; + QHBoxLayout * hlay; + QVBoxLayout * vlay; + QVBoxLayout * page_vlay; + + vlay = new QVBoxLayout( q ); + vlay->setObjectName( "main layout" ); + vlay->setMargin( 0 ); + + // "enable signatue" checkbox: + q->mEnableCheck = new QCheckBox( i18n("&Enable signature"), q ); + q->mEnableCheck->setWhatsThis( + i18n("Check this box if you want KMail to append a signature to mails " + "written with this identity.")); + vlay->addWidget( q->mEnableCheck ); + + // "obtain signature text from" combo and label: + hlay = new QHBoxLayout(); // inherits spacing + vlay->addLayout( hlay ); + q->mSourceCombo = new KComboBox( q ); + q->mSourceCombo->setEditable( false ); + q->mSourceCombo->setWhatsThis( + i18n("Click on the widgets below to obtain help on the input methods.")); + q->mSourceCombo->setEnabled( false ); // since !mEnableCheck->isChecked() + q->mSourceCombo->addItems( QStringList() + << i18nc("continuation of \"obtain signature text from\"", + "Input Field Below") + << i18nc("continuation of \"obtain signature text from\"", + "File") + << i18nc("continuation of \"obtain signature text from\"", + "Output of Command") + ); + label = new QLabel( i18n("Obtain signature &text from:"), q ); + label->setBuddy( q->mSourceCombo ); + label->setEnabled( false ); // since !mEnableCheck->isChecked() + hlay->addWidget( label ); + hlay->addWidget( q->mSourceCombo, 1 ); + + // widget stack that is controlled by the source combo: + QStackedWidget * widgetStack = new QStackedWidget( q ); + widgetStack->setEnabled( false ); // since !mEnableCheck->isChecked() + vlay->addWidget( widgetStack, 1 ); + q->connect( q->mSourceCombo, SIGNAL(currentIndexChanged(int)), + widgetStack, SLOT(setCurrentIndex (int)) ); + q->connect( q->mSourceCombo, SIGNAL(highlighted(int)), + widgetStack, SLOT(setCurrentIndex (int)) ); + // connects for the enabling of the widgets depending on + // signatureEnabled: + q->connect( q->mEnableCheck, SIGNAL(toggled(bool)), + q->mSourceCombo, SLOT(setEnabled(bool)) ); + q->connect( q->mEnableCheck, SIGNAL(toggled(bool)), + widgetStack, SLOT(setEnabled(bool)) ); + q->connect( q->mEnableCheck, SIGNAL(toggled(bool)), + label, SLOT(setEnabled(bool)) ); + // The focus might be still in the widget that is disabled + q->connect( q->mEnableCheck, SIGNAL(clicked()), + q->mEnableCheck, SLOT(setFocus()) ); + + int pageno = 0; + // page 0: input field for direct entering: + page = new QWidget( widgetStack ); + widgetStack->insertWidget( pageno, page ); + page_vlay = new QVBoxLayout( page ); + + q->mEditToolBar = new KToolBar( q ); + q->mEditToolBar->setToolButtonStyle( Qt::ToolButtonIconOnly ); + page_vlay->addWidget( q->mEditToolBar, 0 ); + + q->mFormatToolBar = new KToolBar( q ); + q->mFormatToolBar->setToolButtonStyle( Qt::ToolButtonIconOnly ); + page_vlay->addWidget( q->mFormatToolBar, 1 ); + + q->mTextEdit = new KPIMTextEdit::TextEdit( q ); + static_cast( q->mTextEdit )->enableImageActions(); + page_vlay->addWidget( q->mTextEdit, 2 ); + q->mTextEdit->setWhatsThis( i18n("Use this field to enter an arbitrary static signature.")); + // exclude SupportToPlainText. + q->mTextEdit->setRichTextSupport( KRichTextWidget::FullTextFormattingSupport | + KRichTextWidget::FullListSupport | + KRichTextWidget::SupportAlignment | + KRichTextWidget::SupportRuleLine | + KRichTextWidget::SupportHyperlinks | + KRichTextWidget::SupportFormatPainting ); + + // Fill the toolbars. + KActionCollection *actionCollection = new KActionCollection( q ); + q->mTextEdit->createActions( actionCollection ); + q->mEditToolBar->addAction( actionCollection->action( "format_text_bold" ) ); + q->mEditToolBar->addAction( actionCollection->action( "format_text_italic" ) ); + q->mEditToolBar->addAction( actionCollection->action( "format_text_underline" ) ); + q->mEditToolBar->addAction( actionCollection->action( "format_text_strikeout" ) ); + q->mEditToolBar->addAction( actionCollection->action( "format_text_foreground_color" ) ); + q->mEditToolBar->addAction( actionCollection->action( "format_text_background_color" ) ); + q->mEditToolBar->addAction( actionCollection->action( "format_font_family" ) ); + q->mEditToolBar->addAction( actionCollection->action( "format_font_size" ) ); + + q->mFormatToolBar->addAction( actionCollection->action( "format_list_style" ) ); + q->mFormatToolBar->addAction( actionCollection->action( "format_list_indent_more" ) ); + q->mFormatToolBar->addAction( actionCollection->action( "format_list_indent_less" ) ); + q->mFormatToolBar->addAction( actionCollection->action( "format_list_indent_less" ) ); + q->mFormatToolBar->addSeparator(); + + q->mFormatToolBar->addAction( actionCollection->action( "format_align_left" ) ); + q->mFormatToolBar->addAction( actionCollection->action( "format_align_center" ) ); + q->mFormatToolBar->addAction( actionCollection->action( "format_align_right" ) ); + q->mFormatToolBar->addAction( actionCollection->action( "format_align_justify" ) ); + q->mFormatToolBar->addSeparator(); + + q->mFormatToolBar->addAction( actionCollection->action( "insert_horizontal_rule" ) ); + q->mFormatToolBar->addAction( actionCollection->action( "manage_link" ) ); + q->mFormatToolBar->addAction( actionCollection->action( "format_painter" ) ); + + if ( imageMode == EnableHtmlImages ) { + q->mFormatToolBar->addSeparator(); + q->mFormatToolBar->addAction( actionCollection->action( "add_image" ) ); + } + + hlay = new QHBoxLayout(); // inherits spacing + page_vlay->addLayout( hlay ); + q->mHtmlCheck = new QCheckBox( i18n("&Use HTML"), page ); + q->connect( q->mHtmlCheck, SIGNAL(clicked()), + q, SLOT(slotSetHtml()) ); + hlay->addWidget( q->mHtmlCheck ); + inlinedHtml = true; + + widgetStack->setCurrentIndex( 0 ); // since mSourceCombo->currentItem() == 0 + + // page 1: "signature file" requester, label, "edit file" button: + ++pageno; + page = new QWidget( widgetStack ); + widgetStack->insertWidget( pageno, page ); // force sequential numbers (play safe) + page_vlay = new QVBoxLayout( page ); + page_vlay->setMargin( 0 ); + hlay = new QHBoxLayout(); // inherits spacing + page_vlay->addLayout( hlay ); + q->mFileRequester = new KUrlRequester( page ); + q->mFileRequester->setWhatsThis( + i18n("Use this requester to specify a text file that contains your " + "signature. It will be read every time you create a new mail or " + "append a new signature.")); + label = new QLabel( i18n("S&pecify file:"), page ); + label->setBuddy( q->mFileRequester ); + hlay->addWidget( label ); + hlay->addWidget( q->mFileRequester, 1 ); + q->mFileRequester->button()->setAutoDefault( false ); + q->connect( q->mFileRequester, SIGNAL(textChanged(const QString &)), + q, SLOT(slotEnableEditButton(const QString &)) ); + q->mEditButton = new QPushButton( i18n("Edit &File"), page ); + q->mEditButton->setWhatsThis( i18n("Opens the specified file in a text editor.")); + q->connect( q->mEditButton, SIGNAL(clicked()), + q, SLOT(slotEdit()) ); + q->mEditButton->setAutoDefault( false ); + q->mEditButton->setEnabled( false ); // initially nothing to edit + hlay->addWidget( q->mEditButton ); + page_vlay->addStretch( 1 ); // spacer + + // page 2: "signature command" requester and label: + ++pageno; + page = new QWidget( widgetStack ); + widgetStack->insertWidget( pageno,page ); + page_vlay = new QVBoxLayout( page ); + page_vlay->setMargin( 0 ); + hlay = new QHBoxLayout(); // inherits spacing + page_vlay->addLayout( hlay ); + q->mCommandEdit = new KLineEdit( page ); + q->mCommandEdit->setCompletionObject( new KShellCompletion() ); + q->mCommandEdit->setAutoDeleteCompletionObject( true ); + q->mCommandEdit->setWhatsThis( + i18n("You can add an arbitrary command here, either with or without path " + "depending on whether or not the command is in your Path. For every " + "new mail, KMail will execute the command and use what it outputs (to " + "standard output) as a signature. Usual commands for use with this " + "mechanism are \"fortune\" or \"ksig -random\".")); + label = new QLabel( i18n("S&pecify command:"), page ); + label->setBuddy( q->mCommandEdit ); + hlay->addWidget( label ); + hlay->addWidget( q->mCommandEdit, 1 ); + page_vlay->addStretch( 1 ); // spacer +} + + SignatureConfigurator::SignatureConfigurator( QWidget * parent ) + : QWidget( parent ), d( new Private( this ) ) { - // tmp. vars: - QLabel * label; - QWidget * page; - QHBoxLayout * hlay; - QVBoxLayout * vlay; - QVBoxLayout * page_vlay; - - vlay = new QVBoxLayout( this ); - vlay->setObjectName( "main layout" ); - vlay->setMargin( 0 ); - - // "enable signatue" checkbox: - mEnableCheck = new QCheckBox( i18n("&Enable signature"), this ); - mEnableCheck->setWhatsThis( - i18n("Check this box if you want KMail to append a signature to mails " - "written with this identity.")); - vlay->addWidget( mEnableCheck ); - - // "obtain signature text from" combo and label: - hlay = new QHBoxLayout(); // inherits spacing - vlay->addLayout( hlay ); - mSourceCombo = new KComboBox( this ); - mSourceCombo->setEditable( false ); - mSourceCombo->setWhatsThis( - i18n("Click on the widgets below to obtain help on the input methods.")); - mSourceCombo->setEnabled( false ); // since !mEnableCheck->isChecked() - mSourceCombo->addItems( QStringList() - << i18nc("continuation of \"obtain signature text from\"", - "Input Field Below") - << i18nc("continuation of \"obtain signature text from\"", - "File") - << i18nc("continuation of \"obtain signature text from\"", - "Output of Command") - ); - label = new QLabel( i18n("Obtain signature &text from:"), this ); - label->setBuddy( mSourceCombo ); - label->setEnabled( false ); // since !mEnableCheck->isChecked() - hlay->addWidget( label ); - hlay->addWidget( mSourceCombo, 1 ); - - // widget stack that is controlled by the source combo: - QStackedWidget * widgetStack = new QStackedWidget( this ); - widgetStack->setEnabled( false ); // since !mEnableCheck->isChecked() - vlay->addWidget( widgetStack, 1 ); - connect( mSourceCombo, SIGNAL(currentIndexChanged(int)), - widgetStack, SLOT(setCurrentIndex (int)) ); - connect( mSourceCombo, SIGNAL(highlighted(int)), - widgetStack, SLOT(setCurrentIndex (int)) ); - // connects for the enabling of the widgets depending on - // signatureEnabled: - connect( mEnableCheck, SIGNAL(toggled(bool)), - mSourceCombo, SLOT(setEnabled(bool)) ); - connect( mEnableCheck, SIGNAL(toggled(bool)), - widgetStack, SLOT(setEnabled(bool)) ); - connect( mEnableCheck, SIGNAL(toggled(bool)), - label, SLOT(setEnabled(bool)) ); - // The focus might be still in the widget that is disabled - connect( mEnableCheck, SIGNAL(clicked()), - mEnableCheck, SLOT(setFocus()) ); - - int pageno = 0; - // page 0: input field for direct entering: - page = new QWidget( widgetStack ); - widgetStack->insertWidget( pageno, page ); - page_vlay = new QVBoxLayout( page ); - - mEditToolBar = new KToolBar( this ); - mEditToolBar->setToolButtonStyle( Qt::ToolButtonIconOnly ); - page_vlay->addWidget( mEditToolBar, 0 ); - - mFormatToolBar = new KToolBar( this ); - mFormatToolBar->setToolButtonStyle( Qt::ToolButtonIconOnly ); - page_vlay->addWidget( mFormatToolBar, 1 ); - - mTextEdit = new KPIMTextEdit::TextEdit( this ); - page_vlay->addWidget( mTextEdit, 2 ); - mTextEdit->setWhatsThis( i18n("Use this field to enter an arbitrary static signature.")); - // exclude SupportToPlainText. - mTextEdit->setRichTextSupport( KRichTextWidget::FullTextFormattingSupport | - KRichTextWidget::FullListSupport | - KRichTextWidget::SupportAlignment | - KRichTextWidget::SupportRuleLine | - KRichTextWidget::SupportHyperlinks | - KRichTextWidget::SupportFormatPainting ); - - // Fill the toolbars. - KActionCollection *actionCollection = new KActionCollection(this); - mTextEdit->createActions( actionCollection ); - mEditToolBar->addAction( actionCollection->action( "format_text_bold" ) ); - mEditToolBar->addAction( actionCollection->action( "format_text_italic" ) ); - mEditToolBar->addAction( actionCollection->action( "format_text_underline" ) ); - mEditToolBar->addAction( actionCollection->action( "format_text_strikeout" ) ); - mEditToolBar->addAction( actionCollection->action( "format_text_foreground_color" ) ); - mEditToolBar->addAction( actionCollection->action( "format_text_background_color" ) ); - mEditToolBar->addAction( actionCollection->action( "format_font_family" ) ); - mEditToolBar->addAction( actionCollection->action( "format_font_size" ) ); - - mFormatToolBar->addAction( actionCollection->action( "format_list_style" ) ); - mFormatToolBar->addAction( actionCollection->action( "format_list_indent_more" ) ); - mFormatToolBar->addAction( actionCollection->action( "format_list_indent_less" ) ); - mFormatToolBar->addAction( actionCollection->action( "format_list_indent_less" ) ); - mFormatToolBar->addSeparator(); - - mFormatToolBar->addAction( actionCollection->action( "format_align_left" ) ); - mFormatToolBar->addAction( actionCollection->action( "format_align_center" ) ); - mFormatToolBar->addAction( actionCollection->action( "format_align_right" ) ); - mFormatToolBar->addAction( actionCollection->action( "format_align_justify" ) ); - mFormatToolBar->addSeparator(); - - mFormatToolBar->addAction( actionCollection->action( "insert_horizontal_rule" ) ); - mFormatToolBar->addAction( actionCollection->action( "manage_link" ) ); - mFormatToolBar->addAction( actionCollection->action( "format_painter" ) ); - - hlay = new QHBoxLayout(); // inherits spacing - page_vlay->addLayout( hlay ); - mHtmlCheck = new QCheckBox( i18n("&Use HTML"), page ); - connect( mHtmlCheck, SIGNAL(clicked()), - this, SLOT(slotSetHtml()) ); - hlay->addWidget( mHtmlCheck ); - d->inlinedHtml = true; - - widgetStack->setCurrentIndex( 0 ); // since mSourceCombo->currentItem() == 0 - - // page 1: "signature file" requester, label, "edit file" button: - ++pageno; - page = new QWidget( widgetStack ); - widgetStack->insertWidget( pageno, page ); // force sequential numbers (play safe) - page_vlay = new QVBoxLayout( page ); - page_vlay->setMargin( 0 ); - hlay = new QHBoxLayout(); // inherits spacing - page_vlay->addLayout( hlay ); - mFileRequester = new KUrlRequester( page ); - mFileRequester->setWhatsThis( - i18n("Use this requester to specify a text file that contains your " - "signature. It will be read every time you create a new mail or " - "append a new signature.")); - label = new QLabel( i18n("S&pecify file:"), page ); - label->setBuddy( mFileRequester ); - hlay->addWidget( label ); - hlay->addWidget( mFileRequester, 1 ); - mFileRequester->button()->setAutoDefault( false ); - connect( mFileRequester, SIGNAL(textChanged(const QString &)), - this, SLOT(slotEnableEditButton(const QString &)) ); - mEditButton = new QPushButton( i18n("Edit &File"), page ); - mEditButton->setWhatsThis( i18n("Opens the specified file in a text editor.")); - connect( mEditButton, SIGNAL(clicked()), SLOT(slotEdit()) ); - mEditButton->setAutoDefault( false ); - mEditButton->setEnabled( false ); // initially nothing to edit - hlay->addWidget( mEditButton ); - page_vlay->addStretch( 1 ); // spacer - - // page 2: "signature command" requester and label: - ++pageno; - page = new QWidget( widgetStack ); - widgetStack->insertWidget( pageno,page ); - page_vlay = new QVBoxLayout( page ); - page_vlay->setMargin( 0 ); - hlay = new QHBoxLayout(); // inherits spacing - page_vlay->addLayout( hlay ); - mCommandEdit = new KLineEdit( page ); - mCommandEdit->setCompletionObject( new KShellCompletion() ); - mCommandEdit->setAutoDeleteCompletionObject( true ); - mCommandEdit->setWhatsThis( - i18n("You can add an arbitrary command here, either with or without path " - "depending on whether or not the command is in your Path. For every " - "new mail, KMail will execute the command and use what it outputs (to " - "standard output) as a signature. Usual commands for use with this " - "mechanism are \"fortune\" or \"ksig -random\".")); - label = new QLabel( i18n("S&pecify command:"), page ); - label->setBuddy( mCommandEdit ); - hlay->addWidget( label ); - hlay->addWidget( mCommandEdit, 1 ); - page_vlay->addStretch( 1 ); // spacer + d->init(); + } + + SignatureConfigurator::SignatureConfigurator( HtmlImageMode imageMode, QWidget * parent ) + : QWidget( parent ), d( new Private( this ) ) + { + d->imageMode = imageMode; + d->init(); } SignatureConfigurator::~SignatureConfigurator() { delete d; } bool SignatureConfigurator::isSignatureEnabled() const { return mEnableCheck->isChecked(); } void SignatureConfigurator::setSignatureEnabled( bool enable ) { mEnableCheck->setChecked( enable ); } Signature::Type SignatureConfigurator::signatureType() const { if ( !isSignatureEnabled() ) return Signature::Disabled; switch ( mSourceCombo->currentIndex() ) { case 0: return Signature::Inlined; case 1: return Signature::FromFile; case 2: return Signature::FromCommand; default: return Signature::Disabled; } } void SignatureConfigurator::setSignatureType( Signature::Type type ) { setSignatureEnabled( type != Signature::Disabled ); int idx = 0; switch( type ) { case Signature::Inlined: idx = 0; break; case Signature::FromFile: idx = 1; break; case Signature::FromCommand: idx = 2; break; default: idx = 0; break; }; mSourceCombo->setCurrentIndex( idx ); } void SignatureConfigurator::setInlineText( const QString & text ) { mTextEdit->setTextOrHtml( text ); } QString SignatureConfigurator::fileURL() const { QString file = mFileRequester->url().path(); // Force the filename to be relative to ~ instead of $PWD depending // on the rest of the code (KRun::run in Edit and KFileItem on save) if ( !file.isEmpty() && QFileInfo( file ).isRelative() ) file = QDir::home().absolutePath() + QDir::separator() + file; return file; } void SignatureConfigurator::setFileURL( const QString & url ) { mFileRequester->setUrl( url ); } QString SignatureConfigurator::commandURL() const { return mCommandEdit->text(); } void SignatureConfigurator::setCommandURL( const QString & url ) { mCommandEdit->setText( url ); } Signature SignatureConfigurator::signature() const { Signature sig; const Signature::Type sigType = signatureType(); switch ( sigType ) { case Signature::Inlined: sig.setInlinedHtml( d->inlinedHtml ); sig.setText( d->inlinedHtml ? asCleanedHTML() : mTextEdit->textOrHtml() ); + if ( d->inlinedHtml ) { + if ( !d->imageLocation.isEmpty() ) + sig.setImageLocation( d->imageLocation ); + KPIMTextEdit::ImageWithNameList images = static_cast< KPIMTextEdit::TextEdit*>( mTextEdit )->imagesWithName(); + foreach( const KPIMTextEdit::ImageWithNamePtr &image, images ) { + sig.addImage( image->image, image->name ); + } + } break; case Signature::FromCommand: sig.setUrl( commandURL(), true ); break; case Signature::FromFile: sig.setUrl( fileURL(), false ); break; case Signature::Disabled: /* do nothing */ break; } + sig.setType( sigType ); return sig; } void SignatureConfigurator::setSignature( const Signature & sig ) { setSignatureType( sig.type() ); if ( sig.isInlinedHtml() ) mHtmlCheck->setCheckState( Qt::Checked ); else mHtmlCheck->setCheckState( Qt::Unchecked ); slotSetHtml(); - setInlineText( sig.text() ); + + // Let insertIntoTextEdit() handle setting the text, as that function also adds the images. + mTextEdit->clear(); + sig.insertIntoTextEdit( mTextEdit, KPIMIdentities::Signature::Start, false /* no seperator*/ ); if ( sig.type() == Signature::FromFile ) setFileURL( sig.url() ); else setFileURL( QString() ); if ( sig.type() == Signature::FromCommand ) setCommandURL( sig.url() ); else setCommandURL( QString() ); } void SignatureConfigurator::slotEnableEditButton( const QString & url ) { mEditButton->setDisabled( url.trimmed().isEmpty() ); } void SignatureConfigurator::slotEdit() { QString url = fileURL(); // slotEnableEditButton should prevent this assert from being hit: assert( !url.isEmpty() ); (void)KRun::runUrl( KUrl( url ), QString::fromLatin1("text/plain"), this ); } QString SignatureConfigurator::asCleanedHTML() const { QString text = mTextEdit->toHtml(); // Beautiful little hack to find the html headers produced by Qt. QTextDocument textDocument; QString html = textDocument.toHtml(); // Now remove each line from the text, the result is clean html. foreach( const QString& line, html.split( '\n' ) ){ text.remove( line + '\n' ); } return text; } // "use HTML"-checkbox (un)checked void SignatureConfigurator::slotSetHtml() { if ( mHtmlCheck->checkState() == Qt::Unchecked ) { mHtmlCheck->setText( i18n("&Use HTML") ); mEditToolBar->setVisible( false ); mEditToolBar->setEnabled( false ); mFormatToolBar->setVisible( false ); mFormatToolBar->setEnabled( false ); mTextEdit->switchToPlainText(); d->inlinedHtml = false; } else { mHtmlCheck->setText( i18n("&Use HTML (disabling removes formatting)") ); d->inlinedHtml = true; mEditToolBar->setVisible( true ); mEditToolBar->setEnabled( true ); mFormatToolBar->setVisible( true ); mFormatToolBar->setEnabled( true ); mTextEdit->enableRichTextMode(); } } + void SignatureConfigurator::setImageLocation ( const QString& path ) + { + d->imageLocation = path; + } + } #include "signatureconfigurator.moc" diff --git a/kpimidentities/signatureconfigurator.h b/kpimidentities/signatureconfigurator.h index aee9f3900..15309bcae 100644 --- a/kpimidentities/signatureconfigurator.h +++ b/kpimidentities/signatureconfigurator.h @@ -1,168 +1,193 @@ /* -*- c++ -*- Copyright 2008 Thomas McGuire Copyright 2008 Edwin Schepers Copyright 2008 Tom Albers Copyright 2004 Marc Mutz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef KPIMIDENTITIES_SIGNATURECONFIGURATOR_H #define KPIMIDENTITIES_SIGNATURECONFIGURATOR_H #include "kpimidentities_export.h" #include "signature.h" // for Signature::Type #include using KPIMIdentities::Signature; class QCheckBox; class KComboBox; class KUrlRequester; class KLineEdit; class KToolBar; class KRichTextWidget; class QString; class QPushButton; class QTextEdit; class QTextCharFormat; namespace KPIMIdentities { /** * This widget gives an interface so users can edit their signature. * You can set a signature via setSignature(), let the user edit the * signature and when done, read the signature back. */ class KPIMIDENTITIES_EXPORT SignatureConfigurator : public QWidget { Q_OBJECT public: /** * Constructor + * @deprecated: Use the other constructor + * TODO: KDE5: BIC: remove */ - SignatureConfigurator( QWidget * parent=0 ); + KDE_DEPRECATED SignatureConfigurator( QWidget * parent = 0 ); + + /// Used to decide whether to allow the user to add images or not + enum HtmlImageMode { EnableHtmlImages, DisableHtmlImages }; + + /** + * Constructor. If you want that the user sees a button to add images in the HTML toolbar, + * enable HTML images by setting @p HtmlImageMode to EnableHtmlImages. + * + * @since 4.4 + */ + explicit SignatureConfigurator( HtmlImageMode imageMode = DisableHtmlImages, QWidget * parent = 0 ); /** * destructor */ virtual ~SignatureConfigurator(); /** * Enum for the different viemodes. */ enum ViewMode { ShowCode, ShowHtml }; /** * Indicated if the user wants a signature */ bool isSignatureEnabled() const; /** * Use this to activate the signature. */ void setSignatureEnabled( bool enable ); /** * This returns the type of the signature, * so that can be Disabled, Inline, fromFile, etc. */ Signature::Type signatureType() const; /** * Set the signature type to @p type. */ void setSignatureType( Signature::Type type ); /** * Returns the inline text, only useful * when this is the appropriate Signature::Type */ QString inlineText() const; /** * Make @p text the text for the signature. */ void setInlineText( const QString & text ); /** * Returns the file url which the user wants * to use as a signature. */ QString fileURL() const; /** * Set @p url for the file url part of the * widget. */ void setFileURL( const QString & url ); /** * Returns the url of the command which the * users wants to use as signature. */ QString commandURL() const; /** * Sets @p url as the command to execute. */ void setCommandURL( const QString & url ); /** Conveniece method. @return a Signature object representing the state of the widgets. **/ Signature signature() const; /** Convenience method. Sets the widgets according to @p sig **/ void setSignature( const Signature & sig ); + /** + * Sets the directory where the images used in the HTML signature will be stored. + * Needs to be called before calling setSignature(), as each signature should use + * a different location. + * The directory needs to exist, it will not be created. + * @since 4.4 + * @sa Signature::setImageLocation + */ + void setImageLocation( const QString &path ); + private: void toggleHtmlBtnState( ViewMode state ); void initHtmlState(); // Returns the current text of the textedit as HTML code, but strips // unnecessary tags Qt inserts QString asCleanedHTML() const; protected Q_SLOTS: void slotEnableEditButton( const QString & ); void slotEdit(); void slotSetHtml(); protected: + + // TODO: KDE5: BIC: Move to private class! QCheckBox * mEnableCheck; QCheckBox * mHtmlCheck; KComboBox * mSourceCombo; KUrlRequester * mFileRequester; QPushButton * mEditButton; KLineEdit * mCommandEdit; KToolBar * mEditToolBar; KToolBar * mFormatToolBar; KRichTextWidget * mTextEdit; // Grmbl, why is this not in the private class? // This is a KPIMTextEdit::TextEdit, really. private: //@cond PRIVATE class Private; Private *const d; //@endcond }; } #endif