/* KNode, the KDE newsreader Copyright (c) 1999-2006 the KNode authors. See file AUTHORS for details 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. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US */ #include "kncomposer.h" #include #include #include #include #include #include #include #include "libkdepim/addressline/recentaddresses.h" using KPIM::RecentAddresses; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kngroupselectdialog.h" #include "utilities.h" #include "knglobals.h" #include "knmainwidget.h" #include "knaccountmanager.h" #include "knnntpaccount.h" #include "settings.h" #include "kncomposerview.h" #include "utils/locale.h" using namespace KNode::Utilities; using namespace KNode::Composer; KNLineEdit::KNLineEdit( View *parent, bool useCompletion ) : KABC::AddressLineEdit( parent, useCompletion ), composerView( parent ) { } KNLineEdit::KNLineEdit( QWidget *parent, bool useCompletion ) : KABC::AddressLineEdit( parent, useCompletion ), composerView(0) { } void KNLineEdit::contextMenuEvent( QContextMenuEvent*e ) { QMenu *popup = KLineEdit::createStandardContextMenu(); popup->addSeparator(); popup->addAction( i18n( "Edit Recent Addresses..." ), this, SLOT(editRecentAddresses()) ); popup->exec( e->globalPos() ); delete popup; } void KNLineEdit::editRecentAddresses() { KPIM::RecentAddressDialog dlg( this ); dlg.setAddresses( RecentAddresses::self( knGlobals.config() )->addresses() ); if ( dlg.exec() ) { RecentAddresses::self( knGlobals.config() )->clear(); QStringList addrList = dlg.addresses(); QStringList::Iterator it; for ( it = addrList.begin(); it != addrList.end(); ++it ) RecentAddresses::self( knGlobals.config() )->add( *it ); loadAddresses(); } } void KNLineEdit::loadAddresses() { KABC::AddressLineEdit::loadAddresses(); QStringList recent = RecentAddresses::self(knGlobals.config())->addresses(); QStringList::Iterator it = recent.begin(); for ( ; it != recent.end(); ++it ) addAddress( *it ); } void KNLineEdit::keyPressEvent(QKeyEvent *e) { // ---sven's Return is same Tab and arrow key navigation start --- if ((e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) && !completionBox()->isVisible()) { composerView->focusNextPrevEdit( this, true ); return; } if (e->key() == Qt::Key_Up) { composerView->focusNextPrevEdit( this, false ); // Go up return; } if (e->key() == Qt::Key_Down) { composerView->focusNextPrevEdit( this, true ); // Go down return; } // ---sven's Return is same Tab and arrow key navigation end --- KABC::AddressLineEdit::keyPressEvent(e); } KNLineEditSpell::KNLineEditSpell( View *parent, bool useCompletion ) : KNLineEdit( parent, useCompletion ) { } KNLineEditSpell::KNLineEditSpell( QWidget *parent, bool useCompletion ) : KNLineEdit( parent, useCompletion ) { } void KNLineEditSpell::highLightWord( unsigned int length, unsigned int pos ) { setSelection ( pos, length ); } void KNLineEditSpell::spellCheckDone( const QString &s ) { if( s != text() ) setText( s ); } void KNLineEditSpell::spellCheckerMisspelling( const QString &_text, const QStringList &, unsigned int pos) { highLightWord( _text.length(),pos ); } void KNLineEditSpell::spellCheckerCorrected( const QString &old, const QString &corr, unsigned int pos) { if( old!= corr ) { setSelection ( pos, old.length() ); insert( corr ); setSelection ( pos, corr.length() ); } } KNComposer::KNComposer( KNLocalArticle::Ptr a, const QString &text, const QString &unwraped, bool firstEdit, bool dislikesCopies, bool createCopy, bool allowMail ) : KXmlGuiWindow(0), r_esult(CRsave), a_rticle(a), u_nwraped(unwraped), n_eeds8Bit(true), v_alidated(false), a_uthorDislikesMailCopies(dislikesCopies), e_xternalEdited(false), e_xternalEditor(0), e_ditorTempfile(0), a_ttChanged(false), mFirstEdit( firstEdit ) { setObjectName( "composerWindow" ); if( knGlobals.componentData().isValid() ) setComponentData( knGlobals.componentData() ); // activate dnd of attachments... setAcceptDrops(true); //init v_iew v_iew = new View( this ); setCentralWidget(v_iew); connect( v_iew, SIGNAL(closeExternalEditor()), this, SLOT(slotCancelEditor()) ); //statusbar KStatusBar *sb=statusBar(); sb->insertItem( QString(), 1, 1 ); // type sb->setItemAlignment( 1, Qt::AlignLeft | Qt::AlignVCenter ); sb->insertItem( QString(), 2, 1 ); // charset sb->setItemAlignment( 2, Qt::AlignLeft | Qt::AlignVCenter ); sb->insertItem( QString(), 3, 1 ); // write mode sb->setItemAlignment(3, Qt::AlignCenter | Qt::AlignVCenter ); sb->insertItem( QString(), 4, 1 ); // column sb->setItemAlignment(4, Qt::AlignCenter | Qt::AlignVCenter ); sb->insertItem( QString(), 5, 1 ); // line sb->setItemAlignment( 5, Qt::AlignCenter | Qt::AlignVCenter ); connect(v_iew->editor(), SIGNAL(cursorPositionChanged()), SLOT(slotUpdateCursorPos())); connect(v_iew->editor(), SIGNAL(insertModeChanged()), SLOT(slotUpdateStatusBar())); QDBusConnection::sessionBus().registerObject( "/Composer", this, QDBusConnection::ExportScriptableSlots ); //------------------------------- -------------------------------------- //file menu KAction *action = actionCollection()->addAction("send_now"); action->setIcon(KIcon("mail-send")); action->setText(i18n("&Send Now")); connect(action, SIGNAL(triggered(bool)), SLOT(slotSendNow())); action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return)); action = actionCollection()->addAction("send_later"); action->setIcon(KIcon("mail-queue")); action->setText(i18n("Send &Later")); connect(action, SIGNAL(triggered(bool)), SLOT(slotSendLater())); action = actionCollection()->addAction("save_as_draft"); action->setIcon(KIcon("document-save")); action->setText(i18n("Save as &Draft")); connect(action, SIGNAL(triggered(bool)), SLOT(slotSaveAsDraft())); action = actionCollection()->addAction("art_delete"); action->setIcon(KIcon("edit-delete")); action->setText(i18n("D&elete")); connect(action, SIGNAL(triggered(bool)), SLOT(slotArtDelete())); KStandardAction::close(this, SLOT(close()),actionCollection()); //edit menu KStandardAction::undo(this, SLOT(slotUndo()), actionCollection()); KStandardAction::redo(this, SLOT(slotRedo()), actionCollection()); KStandardAction::cut(this, SLOT(slotCut()), actionCollection()); KStandardAction::copy(this, SLOT(slotCopy()), actionCollection()); KStandardAction::pasteText(this, SLOT(slotPaste()), actionCollection()); action = actionCollection()->addAction("paste_quoted"); action->setText(i18n("Paste as &Quotation")); connect(action, SIGNAL(triggered(bool)), v_iew->editor(), SLOT(slotPasteAsQuotation())); KStandardAction::selectAll(this, SLOT(slotSelectAll()), actionCollection()); KStandardAction::find(v_iew->editor(), SLOT(slotFind()), actionCollection()); KStandardAction::findNext(v_iew->editor(), SLOT(slotFindNext()), actionCollection()); KStandardAction::replace(v_iew->editor(), SLOT(slotReplace()), actionCollection()); //attach menu action = actionCollection()->addAction("append_signature"); action->setText(i18n("Append &Signature")); connect( action, SIGNAL(triggered(bool)), v_iew, SLOT(appendSignature()) ); action = actionCollection()->addAction("insert_file"); action->setText(i18n("&Insert File...")); connect(action, SIGNAL(triggered(bool)), SLOT(slotInsertFile())); action = actionCollection()->addAction("insert_file_boxed"); action->setText(i18n("Insert File (in a &box)...")); connect(action, SIGNAL(triggered(bool)), SLOT(slotInsertFileBoxed())); action = actionCollection()->addAction("attach_file"); action->setIcon(KIcon("mail-attachment")); action->setText(i18n("Attach &File...")); connect(action, SIGNAL(triggered(bool)), SLOT(slotAttachFile())); a_ctPGPsign = actionCollection()->add("sign_article"); a_ctPGPsign->setText(i18n("Sign Article with &PGP")); a_ctPGPsign->setIcon(KIcon("document-sign")); a_ctRemoveAttachment = actionCollection()->addAction("remove_attachment"); a_ctRemoveAttachment->setText(i18n("&Remove")); connect( a_ctRemoveAttachment, SIGNAL(triggered(bool)), v_iew, SLOT(removeCurrentAttachment()) ); a_ctAttachmentProperties = actionCollection()->addAction("attachment_properties"); a_ctAttachmentProperties->setText(i18n("&Properties")); connect( a_ctAttachmentProperties, SIGNAL(triggered(bool)), v_iew, SLOT(editCurrentAttachment()) ); //options menu a_ctDoPost = actionCollection()->add("send_news"); a_ctDoPost->setIcon(KIcon("document-new")); a_ctDoPost->setText(i18n("Send &News Article")); connect(a_ctDoPost, SIGNAL(triggered(bool)), SLOT(slotToggleDoPost())); a_ctDoMail = actionCollection()->add("send_mail"); a_ctDoMail->setIcon(KIcon("mail-send")); a_ctDoMail->setText(i18n("Send E&mail")); a_ctDoMail->setEnabled(allowMail); connect(a_ctDoMail, SIGNAL(triggered(bool)), SLOT(slotToggleDoMail())); a_ctSetCharset = actionCollection()->add("set_charset"); a_ctSetCharset->setText(i18n("Set &Charset")); a_ctSetCharset->setItems( Locale::encodings() ); a_ctSetCharset->setShortcutConfigurable(false); connect(a_ctSetCharset, SIGNAL(triggered(QString)), this, SLOT(slotSetCharset(QString))); a_ctSetCharsetKeyb = actionCollection()->addAction("set_charset_keyboard"); a_ctSetCharsetKeyb->setText(i18n("Set Charset")); connect(a_ctSetCharsetKeyb, SIGNAL(triggered(bool)), SLOT(slotSetCharsetKeyboard())); addAction( a_ctSetCharsetKeyb ); a_ctWordWrap = actionCollection()->add("toggle_wordwrap"); a_ctWordWrap->setText(i18n("&Word Wrap")); connect(a_ctWordWrap, SIGNAL(triggered(bool)), SLOT(slotToggleWordWrap())); a_ctAutoSpellChecking = new KToggleAction( KIcon( "tools-check-spelling" ), i18n("&Automatic Spellchecking"), this ); actionCollection()->addAction( "options_auto_spellchecking", a_ctAutoSpellChecking ); a_ctAutoSpellChecking->setChecked( knGlobals.settings()->autoSpellChecking() ); slotUpdateCheckSpellChecking( knGlobals.settings()->autoSpellChecking() ); slotAutoSpellCheckingToggled(); connect(a_ctAutoSpellChecking, SIGNAL(triggered(bool)), SLOT(slotAutoSpellCheckingToggled())); connect( v_iew->editor(), SIGNAL(checkSpellingChanged(bool)), this, SLOT(slotUpdateCheckSpellChecking(bool))); //tools menu action = actionCollection()->addAction("tools_quote"); action->setText(i18n("Add &Quote Characters")); connect(action, SIGNAL(triggered(bool)), v_iew->editor(), SLOT(slotAddQuotes())); action = actionCollection()->addAction("tools_unquote"); action->setText(i18n("&Remove Quote Characters")); connect(action, SIGNAL(triggered(bool)), v_iew->editor(), SLOT(slotRemoveQuotes())); action = actionCollection()->addAction("tools_box"); action->setText(i18n("Add &Box")); connect(action, SIGNAL(triggered(bool)), v_iew->editor(), SLOT(slotAddBox())); action = actionCollection()->addAction("tools_unbox"); action->setText(i18n("Re&move Box")); connect(action, SIGNAL(triggered(bool)), v_iew->editor(), SLOT(slotRemoveBox())); QAction *undoRewrap = actionCollection()->addAction("tools_undoRewrap"); undoRewrap->setText(i18n("Get &Original Text (not re-wrapped)")); connect(undoRewrap, SIGNAL(triggered(bool)), SLOT(slotUndoRewrap())); undoRewrap->setEnabled(!u_nwraped.isNull()); QAction *rot13 = actionCollection()->addAction("tools_rot13"); rot13->setIcon(KIcon("document-encrypt")); rot13->setText(i18n("S&cramble (Rot 13)")); connect(rot13, SIGNAL(triggered(bool)), v_iew->editor(), SLOT(slotRot13())); rot13->setEnabled(false); connect(v_iew->editor(), SIGNAL(copyAvailable(bool)), rot13, SLOT(setEnabled(bool))); a_ctExternalEditor = actionCollection()->addAction("external_editor"); a_ctExternalEditor->setIcon(KIcon("system-run")); a_ctExternalEditor->setText(i18n("Start &External Editor")); connect(a_ctExternalEditor, SIGNAL(triggered(bool)), SLOT(slotExternalEditor())); a_ctSpellCheck = KStandardAction::spelling ( v_iew->editor(), SLOT(checkSpelling()), actionCollection()); //settings menu createStandardStatusBarAction(); setStandardToolBarMenuEnabled(true); KStandardAction::keyBindings(this, SLOT(slotConfKeys()), actionCollection()); KStandardAction::configureToolbars(this, SLOT(slotConfToolbar()), actionCollection()); KStandardAction::preferences(knGlobals.top, SLOT(slotSettings()), actionCollection()); createGUI("kncomposerui.rc"); //---------------------------------- ---------------------------------------- //init initData(text); //apply configuration setConfig(false); if (createCopy && (m_ode==news)) { a_ctDoMail->setChecked(true); slotToggleDoMail(); } v_iew->completeSetup( firstEdit, m_ode ); // restore window & toolbar configuration resize(535,450); // default optimized for 800x600 applyMainWindowSettings(knGlobals.config()->group("composerWindow_options")); // starting the external editor if ( knGlobals.settings()->useExternalEditor() ) slotExternalEditor(); } KNComposer::~KNComposer() { // prevent slotEditorFinished from being called if (e_xternalEditor) e_xternalEditor->disconnect(); delete e_xternalEditor; // this also kills the editor process if it's still running delete e_ditorTempfile; saveMainWindowSettings(knGlobals.config()->group("composerWindow_options")); KNGlobals::self()->settings()->setAutoSpellChecking( a_ctAutoSpellChecking->isChecked() ); KNGlobals::self()->settings()->writeConfig(); } void KNComposer::slotUpdateCheckSpellChecking(bool _b) { a_ctAutoSpellChecking->setChecked(_b); } void KNComposer::slotUndo() { QWidget* fw = focusWidget(); if (!fw) return; if (fw->inherits("KTextEdit")) ((KTextEdit*)fw)->undo(); else if (fw->inherits("QLineEdit")) ((QLineEdit*)fw)->undo(); } void KNComposer::slotRedo() { QWidget* fw = focusWidget(); if (!fw) return; if (fw->inherits("KTextEdit")) ((KTextEdit*)fw)->redo(); else if (fw->inherits("QLineEdit")) ((QLineEdit*)fw)->redo(); } void KNComposer::slotCut() { QWidget* fw = focusWidget(); if (!fw) return; if (fw->inherits("KTextEdit")) ((KTextEdit*)fw)->cut(); else if (fw->inherits("QLineEdit")) ((QLineEdit*)fw)->cut(); else kDebug(5003) <<"wrong focus widget"; } void KNComposer::slotCopy() { QWidget* fw = focusWidget(); if (!fw) return; if (fw->inherits("KTextEdit")) ((KTextEdit*)fw)->copy(); else if (fw->inherits("QLineEdit")) ((QLineEdit*)fw)->copy(); else kDebug(5003) <<"wrong focus widget"; } void KNComposer::slotPaste() { QWidget* fw = focusWidget(); if (!fw) return; if (fw->inherits("KTextEdit")) ((KTextEdit*)fw)->paste(); else if (fw->inherits("QLineEdit")) ((QLineEdit*)fw)->paste(); else kDebug(5003) <<"wrong focus widget"; } void KNComposer::slotSelectAll() { QWidget* fw = focusWidget(); if (!fw) return; if (fw->inherits("QLineEdit")) ((QLineEdit*)fw)->selectAll(); else if (fw->inherits("KTextEdit")) ((KTextEdit*)fw)->selectAll(); } void KNComposer::setConfig(bool onlyFonts) { if (!onlyFonts) { a_ctWordWrap->setChecked( knGlobals.settings()->wordWrap() ); slotToggleWordWrap(); a_ctAutoSpellChecking->setChecked( knGlobals.settings()->autoSpellChecking() ); Kpgp::Module *pgp = Kpgp::Module::getKpgp(); a_ctPGPsign->setEnabled(pgp->usePGP()); } v_iew->setComposingFont( knGlobals.settings()->composerFont() ); slotUpdateStatusBar(); } void KNComposer::setMessageMode(MessageMode mode) { m_ode = mode; a_ctDoPost->setChecked(m_ode!=mail); a_ctDoMail->setChecked(m_ode!=news); v_iew->setMessageMode(m_ode); //Laurent fixme #if 0 QString s = v_iew->editor()->document ()->begin().text (); if (m_ode == news_mail) { if (!s.contains(i18n(""))) { QTextCursor cursor(v_iew->editor()->document ()->begin()); cursor.setPosition(0); cursor.insertText(i18n("\n\n")); v_iew->editor()->setTextCursor(cursor); } } else { if (s == i18n("")) { v_iew->editor()->removeLine(0); if (v_iew->editor()->textLine(0).isEmpty()) v_iew->editor()->removeLine(0); } } #endif slotUpdateStatusBar(); } bool KNComposer::hasValidData() { v_alidated=false; n_eeds8Bit=false; // header checks if ( KPIMUtils::isValidAddress( v_iew->from() ) != KPIMUtils::AddressOk ) { KMessageBox::sorry( this, i18n( "Your email address does not appears to be valid. Please modify it." ) ); return false; } if ( v_iew->subject().isEmpty() ) { KMessageBox::sorry(this, i18n("Please enter a subject.")); return false; } if ( !n_eeds8Bit && !KMime::isUsAscii( v_iew->subject() ) ) { n_eeds8Bit=true; } if (m_ode != mail) { int groupCount = v_iew->groups().count(); if ( groupCount == 0 ) { KMessageBox::sorry(this, i18n("Please enter a newsgroup.")); return false; } if (groupCount>12) { KMessageBox::sorry(this, i18n("You are crossposting to more than 12 newsgroups.\nPlease remove all newsgroups in which your article is off-topic.")); return false; } if (groupCount>5) if ( KMessageBox::warningYesNo( this, i18n("You are crossposting to more than five newsgroups.\nPlease reconsider whether this is really useful\nand remove groups in which your article is off-topic.\nDo you want to re-edit the article or send it anyway?"), QString(), KGuiItem(i18n("&Send")), KGuiItem(i18nc("edit article","&Edit")) ) != KMessageBox::Yes ) return false; int fupCount = v_iew->followupTo().count(); if ( fupCount == 0 && groupCount > 2 ) { if ( KMessageBox::warningYesNo( this, i18n("You are crossposting to more than two newsgroups.\n" "Please use the \"Followup-To\" header to direct the replies " "to your article into one group.\n" "Do you want to re-edit the article or send it anyway?"), QString(), KGuiItem(i18n("&Send")), KGuiItem(i18nc("edit article","&Edit")), "missingFollowUpTo" ) != KMessageBox::Yes ) return false; } if (fupCount>12) { KMessageBox::sorry(this, i18n("You are directing replies to more than 12 newsgroups.\nPlease remove some newsgroups from the \"Followup-To\" header.")); return false; } if (fupCount>5) if ( KMessageBox::warningYesNo( this, i18n("You are directing replies to more than five newsgroups.\nPlease reconsider whether this is really useful.\nDo you want to re-edit the article or send it anyway?"), QString(), KGuiItem(i18n("&Send")),KGuiItem(i18nc("edit article","&Edit")) ) != KMessageBox::Yes ) return false; } if (m_ode != news) { if ( v_iew->emailRecipient().isEmpty() ) { KMessageBox::sorry(this, i18n("Please enter the email address.")); return false; } if ( !n_eeds8Bit && !KMime::isUsAscii( v_iew->emailRecipient() ) ) { n_eeds8Bit=true; } } //GNKSA body checks bool firstLine = true; bool empty = true; bool longLine = false; bool hasAttributionLine = false; int sigLength = 0; int notQuoted = 0; int textLines = 0; QStringList text = v_iew->editor()->toWrappedPlainText().split('\n'); for (QStringList::Iterator it = text.begin(); it != text.end(); ++it) { if (!n_eeds8Bit && !KMime::isUsAscii(*it)) n_eeds8Bit=true; if (*it == "-- ") { // signature text for (++it; it != text.end(); ++it) { if (!n_eeds8Bit && !KMime::isUsAscii(*it)) n_eeds8Bit=true; sigLength++; if((*it).length()>80) { longLine = true; } } break; } if(!(*it).isEmpty()) { empty = false; textLines++; if ((*it)[0]!='>') { notQuoted++; if (firstLine) hasAttributionLine = true; } } if((*it).length()>80) { longLine = true; } firstLine = false; } if (n_eeds8Bit && ( mCharset.toLower()=="us-ascii" )) { KMessageBox::sorry(this, i18n("Your message contains characters which are not included\nin the \"us-ascii\" character set; please choose\na suitable character set from the \"Options\" menu.")); return false; } if (empty) { KMessageBox::sorry(this, i18n("You cannot post an empty message.")); return false; } if ((textLines>1)&&(notQuoted==1)) { if (hasAttributionLine) if ( KMessageBox::warningYesNo( this, i18n("Your article seems to consist entirely of quoted text;\ndo you want to re-edit the article or send it anyway?"), QString(), KGuiItem(i18n("&Send")), KGuiItem(i18nc("edit article","&Edit")) ) != KMessageBox::Yes ) return false; } else { if (notQuoted==0) { KMessageBox::sorry(this, i18n("You cannot post an article consisting\n" "entirely of quoted text.")); return false; } } if (longLine) if ( KMessageBox::warningYesNo( this, i18n("Your article contains lines longer than 80 characters.\n" "Do you want to re-edit the article or send it anyway?"), QString(), KGuiItem(i18n("&Send")), KGuiItem(i18nc("edit article","&Edit")) ) != KMessageBox::Yes ) return false; if (sigLength>8) { if ( KMessageBox::warningYesNo( this, i18n("Your signature is more than 8 lines long.\nYou should shorten it to match the widely accepted limit of 4 lines.\nDo you want to re-edit the article or send it anyway?"), QString(), KGuiItem(i18n("&Send")), KGuiItem(i18nc("edit article","&Edit")) ) != KMessageBox::Yes ) return false; } else if (sigLength>4) KMessageBox::information( this, i18n("Your signature exceeds the widely-accepted limit of 4 lines:\nplease consider shortening your signature;\notherwise, you will probably annoy your readers."), QString(), "longSignatureWarning" ); // check if article can be signed if ( a_ctPGPsign->isChecked() ) { // try to get the signing key QByteArray signingKey = KNGlobals::self()->settings()->identity().pgpSigningKey(); KNNntpAccount::Ptr acc = knGlobals.accountManager()->account( a_rticle->serverId() ); if ( acc ) { KMime::Headers::Newsgroups *grps = a_rticle->newsgroups(); if ( !grps->isEmpty() ) { KNGroup::Ptr grp = knGlobals.groupManager()->group( grps->groups().first(), acc ); if ( grp && !grp->identity().isNull() ) { signingKey = grp->identity().pgpSigningKey(); } else if ( !acc->identity().isNull() ) { signingKey = acc->identity().pgpSigningKey(); } } } // the article can only be signed if we have a key if (signingKey.isEmpty()) { if ( KMessageBox::warningContinueCancel( this, i18n("You have not configured your preferred " "signing key yet;\n" "please specify it in the global " "identity configuration,\n" "in the account properties or in the " "group properties.\n" "The article will be sent unsigned." ), QString(), KGuiItem(i18n( "Send Unsigned" )), KStandardGuiItem::cancel(), "sendUnsignedDialog" ) == KMessageBox::Cancel ) return false; } } v_alidated=true; return true; } bool KNComposer::applyChanges() { KMime::Content *text=0; bool result = true; // no error occurs ? // Identity (for later edition) const KPIMIdentities::Identity identity = KNGlobals::self()->identityManager()->identityForUoid( v_iew->selectedIdentity() ); if ( !identity.isNull() ) { KMime::Headers::Generic *xKnodeIdentity = new KMime::Headers::Generic( "X-KNode-Identity", a_rticle.get(), QByteArray::number( identity.uoid() ) ); a_rticle->setHeader( xKnodeIdentity ); } //From if ( KPIMUtils::isValidAddress( v_iew->from() ) != KPIMUtils::AddressOk ) { result = false; } // FIXME: if v_iew->from() is not valid, the following call is a // no-op: the content of the from keeps its previous value! (thanks KMime) a_rticle->from()->fromUnicodeString( v_iew->from(), mCharset.toLatin1() ); //Reply-To if ( KPIMUtils::isValidAddress( identity.replyToAddr() ) == KPIMUtils::AddressOk ) { a_rticle->replyTo()->fromUnicodeString( identity.replyToAddr(), mCharset.toLatin1() ); } else { a_rticle->removeHeader( "Reply-To" ); } //Mail-Copies-To if ( !identity.property( "Mail-Copies-To" ).toString().trimmed().isEmpty() ) { a_rticle->mailCopiesTo()->fromUnicodeString( identity.property( "Mail-Copies-To" ).toString(), mCharset.toLatin1() ); } else { a_rticle->removeHeader( "Mail-Copies-To" ); } //Organization if ( !identity.organization().trimmed().isEmpty() ) { a_rticle->organization()->fromUnicodeString( identity.organization(), mCharset.toLatin1() ); } else { a_rticle->removeHeader( "Organization" ); } //Date a_rticle->date()->setDateTime( KDateTime::currentLocalDateTime() ); //set current date+time //Subject a_rticle->subject()->fromUnicodeString( v_iew->subject(), mCharset.toLatin1() ); //Newsgroups if (m_ode != mail) { a_rticle->newsgroups()->fromUnicodeString( v_iew->groups().join( QString( ',' ) ), KMime::Headers::Latin1 ); a_rticle->setDoPost(true); } else { a_rticle->setDoPost(false); a_rticle->removeHeader( "Newsgroups" ); } //To if (m_ode != news) { a_rticle->to()->fromUnicodeString( v_iew->emailRecipient(), mCharset.toLatin1() ); a_rticle->setDoMail(true); } else { a_rticle->setDoMail(false); a_rticle->removeHeader( "To" ); a_rticle->removeHeader( "Cc" ); } //Followup-To if ( a_rticle->doPost() && !v_iew->followupTo().isEmpty() ) { a_rticle->followUpTo()->fromUnicodeString( v_iew->followupTo().join( QString( ',' ) ), KMime::Headers::Latin1 ); } else { a_rticle->removeHeader("Followup-To"); } // Attachments if ( a_ttChanged ) { const QList l = v_iew->attachments(); foreach ( const KNAttachment::Ptr a, l ) { if(a->hasChanged()) { if(a->isAttached()) a->updateContentInfo(); else a->attach( a_rticle.get() ); } } } for ( QList::Iterator it = mDeletedAttachments.begin(); it != mDeletedAttachments.end(); ++it ) if ( (*it)->isAttached() ) (*it)->detach( a_rticle.get() ); text=a_rticle->textContent(); if(!text) { text=new KMime::Content(); KMime::Headers::ContentType *type=text->contentType(); KMime::Headers::ContentTransferEncoding *enc=text->contentTransferEncoding(); type->setMimeType("text/plain"); enc->setDecoded(true); text->assemble(); a_rticle->addContent(text, true); } //set text if (v_alidated) { if (n_eeds8Bit) { text->contentType()->setCharset( mCharset.toLatin1() ); if ( knGlobals.settings()->allow8BitBody() ) text->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit); else text->contentTransferEncoding()->setEncoding(KMime::Headers::CEquPr); } else { setCharset( "us-ascii" ); // fall back to us-ascii text->contentType()->setCharset( mCharset.toLatin1() ); text->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit); } } else { // save as draft text->contentType()->setCharset( mCharset.toLatin1() ); if ( mCharset.toLower()=="us-ascii" ) { text->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit); } else { text->contentTransferEncoding()->setEncoding( knGlobals.settings()->allow8BitBody() ? KMime::Headers::CE8Bit : KMime::Headers::CEquPr ); } } QString tmp = v_iew->editor()->toWrappedPlainText(); // Sign article if needed if ( a_ctPGPsign->isChecked() ) { QByteArray signingKey = identity.pgpSigningKey(); if (!signingKey.isEmpty()) { QString tmpText = tmp; Kpgp::Block block; bool ok=true; QTextCodec *codec=KGlobal::charsets()->codecForName( mCharset, ok); if(!ok) // no suitable codec found => try local settings and hope the best ;-) codec=KGlobal::locale()->codecForEncoding(); block.setText( codec->fromUnicode(tmpText) ); kDebug(5003) <<"signing article from" << article()->from()->addresses(); if( block.clearsign( signingKey, codec->name() ) == Kpgp::Ok ) { QByteArray result = block.text(); tmp = codec->toUnicode(result.data(), result.length() ); } else { result = false; } } } text->fromUnicodeString(tmp); //text is set and all attached contents have been assembled => now set lines a_rticle->lines()->setNumberOfLines(a_rticle->lineCount()); a_rticle->assemble(); a_rticle->updateListItem(); return result; } void KNComposer::setCharset( const QString &charset ) { mCharset = Locale::toMimeCharset( charset ); slotUpdateStatusBar(); } void KNComposer::closeEvent(QCloseEvent *e) { if(!v_iew->editor()->document()->isModified() && !a_ttChanged) { // nothing to save, don't show nag screen if(a_rticle->id()==-1) r_esult=CRdel; else r_esult=CRcancel; } else { switch ( KMessageBox::warningYesNoCancel( this, i18n("Do you want to save this article in the draft folder?"), QString(), KStandardGuiItem::save(), KStandardGuiItem::discard() ) ) { case KMessageBox::Yes : r_esult=CRsave; break; case KMessageBox::No : if (a_rticle->id()==-1) r_esult=CRdel; else r_esult=CRcancel; break; default: // cancel e->ignore(); return; } } e->accept(); emit composerDone(this); // we're dead at this point, don't access members! } void KNComposer::initData(const QString &text) { // Identity KPIMIdentities::IdentityManager *idManager = KNGlobals::self()->identityManager(); KPIMIdentities::Identity identity = idManager->defaultIdentity(); KMime::Headers::Base* xKnodeIdentity = a_rticle->headerByType( "X-KNode-Identity" ); if ( xKnodeIdentity && !xKnodeIdentity->isEmpty() ) { uint uoid = xKnodeIdentity->asUnicodeString().toUInt(); // Note: this ensure the identity exists even if it was removed identity = idManager->identityForUoidOrDefault( uoid ); } v_iew->setIdentity( identity.uoid() ); //From KMime::Headers::From *from = a_rticle->from( false ); if ( from ) { v_iew->setFrom( from->asUnicodeString() ); } else { v_iew->setFrom( identity.fullEmailAddr() ); } //Subject if(a_rticle->subject()->isEmpty()) slotSubjectChanged( QString() ); else v_iew->setSubject( a_rticle->subject()->asUnicodeString() ); //Newsgroups KMime::Headers::Newsgroups *hNewsgroup = a_rticle->newsgroups( false ); if ( hNewsgroup && !hNewsgroup->isEmpty() ) { v_iew->setGroups( hNewsgroup->asUnicodeString() ); } //To KMime::Headers::To *hTo = a_rticle->to( false ); if ( hTo && !hTo->isEmpty() ) { v_iew->setEmailRecipient( hTo->asUnicodeString() ); } //Followup-To KMime::Headers::FollowUpTo *fup2=a_rticle->followUpTo(false); if( fup2 && !fup2->isEmpty() ) { v_iew->setFollowupTo( fup2->asUnicodeString() ); } KMime::Content *textContent=a_rticle->textContent(); QString s; if(text.isEmpty()) { if(textContent) s = textContent->decodedText(); } else s = text; v_iew->editor()->setText(s); // initialize the charset select action if(textContent) { setCharset( textContent->contentType()->charset() ); } else { setCharset( knGlobals.settings()->charset() ); } QString charsetDesc = KGlobal::charsets()->descriptionForEncoding( mCharset ); a_ctSetCharset->setCurrentItem( a_ctSetCharset->items().indexOf( charsetDesc ) ); // initialize the message type select action if (a_rticle->doPost() && a_rticle->doMail()) m_ode = news_mail; else if (a_rticle->doPost()) m_ode = news; else m_ode = mail; setMessageMode(m_ode); if(a_rticle->contentType()->isMultipart()) { v_iew->showAttachmentView(); const KMime::Content::List attList = a_rticle->attachments(); foreach ( KMime::Content *c, attList ) { v_iew->addAttachment( KNAttachment::Ptr( new KNAttachment( c ) ) ); } } } // inserts at cursor position if clear is false, replaces content otherwise // puts the file content into a box if box==true // "file" is already open for reading void KNComposer::insertFile( QFile *file, bool clear, bool box, const QString &boxTitle ) { QString temp; bool ok=true; QTextCodec *codec=KGlobal::charsets()->codecForName( mCharset, ok); QTextStream ts(file); ts.setCodec(codec); if (box) temp = QString::fromLatin1(",----[ %1 ]\n").arg(boxTitle); //Laurent fixme if (box && (v_iew->editor()->wordWrapMode()!=QTextOption::NoWrap)) { int wrapAt = v_iew->editor()->lineWrapColumnOrWidth(); QStringList lst; QString line; while(!ts.atEnd()) { line=ts.readLine(); if (!ts.atEnd()) line+='\n'; lst.append(line); } temp+=KNHelper::rewrapStringList(lst, wrapAt, '|', false, true); } else { while(!ts.atEnd()) { if (box) temp+="| "; temp+=ts.readLine(); if (!ts.atEnd()) temp += '\n'; } } if (box) temp += QString::fromLatin1("`----"); if(clear) v_iew->editor()->setText(temp); else v_iew->editor()->insertPlainText(temp); } // ask for a filename, handle network urls void KNComposer::insertFile(bool clear, bool box) { KNLoadHelper helper(this); QFile *file = helper.getFile(i18n("Insert File")); KUrl url; QString boxName; if (file) { url = helper.getURL(); if (url.isLocalFile()) boxName = url.toLocalFile(); else boxName = url.prettyUrl(); insertFile(file,clear,box,boxName); } } //-------------------------------- ------------------------------------ void KNComposer::addRecentAddress() { if ( m_ode == mail || m_ode == news_mail ) { RecentAddresses::self( knGlobals.config() )->add( v_iew->emailRecipient() ); } } void KNComposer::slotSendNow() { r_esult=CRsendNow; addRecentAddress(); emit composerDone(this); } void KNComposer::slotSendLater() { r_esult=CRsendLater; addRecentAddress(); emit composerDone(this); } void KNComposer::slotSaveAsDraft() { r_esult=CRsave; addRecentAddress(); emit composerDone(this); } void KNComposer::slotArtDelete() { r_esult=CRdelAsk; emit composerDone(this); } void KNComposer::slotInsertFile() { insertFile(false,false); } void KNComposer::slotInsertFileBoxed() { insertFile(false,true); } void KNComposer::slotAttachFile() { KNLoadHelper *helper = new KNLoadHelper(this); if (helper->getFile(i18n("Attach File"))) { if ( !v_iew->isAttachmentViewVisible() ) { KNHelper::saveWindowSize("composer", size()); v_iew->showAttachmentView(); } v_iew->addAttachment( KNAttachment::Ptr( new KNAttachment( helper ) ) ); a_ttChanged=true; } else { delete helper; } } void KNComposer::slotAttachmentRemoved( KNAttachment::Ptr attachment, bool last ) { if( !attachment ) { return; } if ( attachment->isAttached() ) { mDeletedAttachments.append( attachment ); } if ( last ) { KNHelper::saveWindowSize( "composerAtt", size() ); v_iew->hideAttachmentView(); } a_ttChanged = true; } void KNComposer::slotAttachmentChanged() { a_ttChanged = true; } void KNComposer::slotToggleDoPost() { if (a_ctDoPost->isChecked()) { if (a_ctDoMail->isChecked()) m_ode=news_mail; else m_ode=news; } else { if (a_ctDoMail->isChecked()) m_ode=mail; else { // invalid a_ctDoPost->setChecked(true); //revert return; } } setMessageMode(m_ode); } void KNComposer::slotToggleDoMail() { if (a_ctDoMail->isChecked()) { if (a_uthorDislikesMailCopies) { if ( KMessageBox::warningContinueCancel( this, i18n("The poster does not want a mail copy of your reply (Mail-Copies-To: nobody);\nplease respect their request."), QString(), KGuiItem(i18n("&Send Copy")) ) != KMessageBox::Continue ) { a_ctDoMail->setChecked(false); //revert return; } } } //Laurent fix me #if 0 if ( knGlobals.settings()->useExternalMailer() ) { QString s = v_iew->editor()->textLine(0); if (!s.contains(i18n(""))) v_iew->editor()->insertAt(i18n("\n\n"),0,0); QString tmp; QStringList textLines = v_iew->editor()->processedText(); for (QStringList::Iterator it = textLines.begin(); it != textLines.end(); ++it) { if (*it == "-- ") // try to be smart, don't include the signature, break; // kmail will append one, too. tmp+=*it+'\n'; } knGlobals.artFactory->sendMailExternal( v_iew->t_o->text(), v_iew->subject(), tmp ); a_ctDoMail->setChecked(false); //revert return; } else { #endif if (a_ctDoMail->isChecked()) { if (a_ctDoPost->isChecked()) m_ode=news_mail; else m_ode=mail; } else { if (a_ctDoPost->isChecked()) m_ode=news; else { // invalid a_ctDoMail->setChecked(true); //revert return; } } setMessageMode(m_ode); } void KNComposer::slotSetCharset(const QString &s) { if(s.isEmpty()) return; QString charset = KGlobal::charsets()->encodingForName( s ); setCharset( charset ); } void KNComposer::slotSetCharsetKeyboard() { int newCS = KNHelper::selectDialog(this, i18n("Select Charset"), a_ctSetCharset->items(), a_ctSetCharset->currentItem()); if (newCS != -1) { a_ctSetCharset->setCurrentItem(newCS); QString charset = KGlobal::charsets()->encodingForName( a_ctSetCharset->items()[ newCS ] ); setCharset( charset ); } } void KNComposer::slotToggleWordWrap() { if ( a_ctWordWrap->isChecked() ) v_iew->editor()->enableWordWrap( knGlobals.settings()->maxLineLength() ); else v_iew->editor()->disableWordWrap(); } void KNComposer::slotAutoSpellCheckingToggled() { v_iew->editor()->setCheckSpellingEnabled( a_ctAutoSpellChecking->isChecked() ); } void KNComposer::slotUndoRewrap() { if (KMessageBox::warningContinueCancel( this, i18n("This will replace all text you have written.")) == KMessageBox::Continue) { v_iew->editor()->setText(u_nwraped); v_iew->appendSignature(); } } void KNComposer::slotExternalEditor() { if(e_xternalEditor) // in progress... return; QString editorCommand = knGlobals.settings()->externalEditor(); if(editorCommand.isEmpty()) KMessageBox::sorry(this, i18n("No editor configured.\nPlease do this in the settings dialog.")); delete e_ditorTempfile; e_ditorTempfile=new KTemporaryFile(); if(!e_ditorTempfile->open()) { KNHelper::displayTempFileError(this); delete e_ditorTempfile; e_ditorTempfile=0; return; } bool ok=true; QTextCodec *codec=KGlobal::charsets()->codecForName( mCharset, ok ); QString tmp = v_iew->editor()->toWrappedPlainText(); QByteArray local = codec->fromUnicode(tmp); e_ditorTempfile->write(local.data(),local.length()); e_ditorTempfile->flush(); if(!e_ditorTempfile->open()) { KNHelper::displayTempFileError(this); delete e_ditorTempfile; e_ditorTempfile=0; return; } e_xternalEditor=new KProcess(); // construct command line... QStringList command = editorCommand.split(' ', QString::SkipEmptyParts); bool filenameAdded=false; for ( QStringList::Iterator it = command.begin(); it != command.end(); ++it ) { if ((*it).contains("%f")) { (*it).replace(QRegExp("%f"),e_ditorTempfile->fileName()); filenameAdded=true; } (*e_xternalEditor) << (*it); } if(!filenameAdded) // no %f in the editor command (*e_xternalEditor) << e_ditorTempfile->fileName(); connect(e_xternalEditor, SIGNAL(finished(int,QProcess::ExitStatus)),this, SLOT(slotEditorFinished(int,QProcess::ExitStatus))); e_xternalEditor->start(); if(!e_xternalEditor->waitForStarted()) { KMessageBox::error(this, i18n("Unable to start external editor.\nPlease check your configuration in the settings dialog.")); delete e_xternalEditor; e_xternalEditor=0; delete e_ditorTempfile; e_ditorTempfile=0; return; } a_ctExternalEditor->setEnabled(false); // block other edit action while the editor is running... a_ctSpellCheck->setEnabled(false); v_iew->showExternalNotification(); } void KNComposer::slotUpdateStatusBar() { QString typeDesc; switch (m_ode) { case news: typeDesc = i18n("News Article"); break; case mail: typeDesc = i18n("Email"); break; default : typeDesc = i18n("News Article & Email"); } QString overwriteDesc; if (v_iew->editor()->overwriteMode ()) overwriteDesc = i18n(" OVR "); else overwriteDesc = i18n(" INS "); statusBar()->changeItem(i18n(" Type: %1 ", typeDesc), 1); statusBar()->changeItem(i18n(" Charset: %1 ", mCharset ), 2); statusBar()->changeItem(overwriteDesc, 3); statusBar()->changeItem(i18n(" Column: %1 ", v_iew->editor()->columnNumber () + 1), 4); statusBar()->changeItem(i18n(" Line: %1 ", v_iew->editor()->linePosition() + 1), 5); } void KNComposer::slotUpdateCursorPos() { statusBar()->changeItem(i18n(" Column: %1 ", v_iew->editor()->columnNumber () + 1), 4); statusBar()->changeItem(i18n(" Line: %1 ", v_iew->editor()->linePosition() + 1), 5); } void KNComposer::slotConfKeys() { KShortcutsDialog::configure(actionCollection(), KShortcutsEditor::LetterShortcutsAllowed, this, true); } void KNComposer::slotConfToolbar() { saveMainWindowSettings(knGlobals.config()->group( "composerWindow_options") ); KEditToolBar dlg(guiFactory(),this); connect(&dlg,SIGNAL(newToolBarConfig()), this, SLOT(slotNewToolbarConfig())); dlg.exec(); } void KNComposer::slotNewToolbarConfig() { createGUI("kncomposerui.rc"); applyMainWindowSettings(knGlobals.config()->group("composerWindow_options")); } //-------------------------------- ----------------------------------- void KNComposer::slotSubjectChanged(const QString &t) { // replace newlines QString subject = t; subject.replace( '\n', ' ' ); subject.replace( '\r', ' ' ); if ( subject != t ) // setText() sets the cursor to the end v_iew->setSubject( subject ); // update caption if( !subject.isEmpty() ) setCaption( subject ); else setCaption( i18n("No Subject") ); } void KNComposer::slotToBtnClicked() { Akonadi::EmailAddressSelectionDialog dlg( this ); dlg.view()->view()->setSelectionMode( QAbstractItemView::MultiSelection ); if ( !dlg.exec() ) return; QStringList addresses; foreach ( const Akonadi::EmailAddressSelection &selection, dlg.selectedAddresses() ) addresses << selection.quotedEmail(); QString to = v_iew->emailRecipient(); if ( !to.isEmpty() ) to += ", "; to += addresses.join( ", " ); v_iew->setEmailRecipient( to ); } void KNComposer::slotGroupsBtnClicked() { int id=a_rticle->serverId(); KNNntpAccount::Ptr nntp; if(id!=-1) nntp=knGlobals.accountManager()->account(id); if(!nntp) nntp=knGlobals.accountManager()->first(); if(!nntp) { KMessageBox::error(this, i18n("You have no valid news accounts configured.")); v_iew->setGroups( QString() ); return; } if(id==-1) a_rticle->setServerId(nntp->id()); KNGroupSelectDialog *dlg = new KNGroupSelectDialog( this, nntp, v_iew->groups() ); connect( dlg, SIGNAL(loadList(KNNntpAccount::Ptr)), knGlobals.groupManager(), SLOT(slotLoadGroupList(KNNntpAccount::Ptr)) ); connect( KNGlobals::self()->groupManager(), SIGNAL(newListReady(KNGroupListData::Ptr)), dlg, SLOT(slotReceiveList(KNGroupListData::Ptr)) ); if(dlg->exec()) v_iew->setGroups( dlg->selectedGroups() ); delete dlg; } void KNComposer::slotEditorFinished(int, QProcess::ExitStatus exitStatus) { if(exitStatus == QProcess::NormalExit) { e_ditorTempfile->flush(); e_ditorTempfile->seek(0); insertFile(e_ditorTempfile, true); e_xternalEdited=true; } slotCancelEditor(); // cleanup... } void KNComposer::slotCancelEditor() { if (e_xternalEditor) e_xternalEditor->deleteLater(); // this also kills the editor process if it's still running e_xternalEditor=0; delete e_ditorTempfile; e_ditorTempfile=0; a_ctExternalEditor->setEnabled(true); a_ctSpellCheck->setEnabled(true); v_iew->hideExternalNotification(); } void KNComposer::slotAttachmentPopup( const QPoint &point ) { QMenu *menu = static_cast( factory()->container( "attachment_popup", this ) ); if ( menu ) { menu->popup( point ); } } void KNComposer::dragEnterEvent( QDragEnterEvent *event ) { if ( KUrl::List::canDecode( event->mimeData() ) ) { event->setDropAction( Qt::CopyAction ); event->accept(); } } void KNComposer::dropEvent( QDropEvent *event ) { KUrl::List urls = KUrl::List::fromMimeData( event->mimeData() ); foreach ( const KUrl &url, urls ) { KNLoadHelper *helper = new KNLoadHelper(this); if (helper->setURL(url)) { if ( !v_iew->isAttachmentViewVisible() ) { KNHelper::saveWindowSize("composer", size()); v_iew->showAttachmentView(); } v_iew->addAttachment( KNAttachment::Ptr( new KNAttachment( helper ) ) ); a_ttChanged=true; } else { delete helper; } } } //===================================================================================== KNComposer::AttachmentPropertiesDlg::AttachmentPropertiesDlg( KNAttachment::Ptr a, QWidget *parent ) : KDialog( parent ), a_ttachment(a), n_onTextAsText(false) { //init GUI setCaption( i18n("Attachment Properties") ); setButtons( Help | Ok | Cancel ); QWidget *page=new QWidget(this); setMainWidget(page); QVBoxLayout *topL=new QVBoxLayout(page); //file info QGroupBox *fileGB = new QGroupBox( i18n("File"), page ); QGridLayout *fileL=new QGridLayout(fileGB); fileL->setSpacing(5); fileL->setMargin(15); fileL->addItem( new QSpacerItem( 0, fontMetrics().lineSpacing()-9), 0, 0 ); fileL->addWidget(new QLabel(i18n("Name:"), fileGB) ,1,0); fileL->addWidget(new QLabel(QString("%1").arg(a->name()), fileGB), 1,1, Qt::AlignLeft); fileL->addWidget(new QLabel(i18n("Size:"), fileGB), 2,0); fileL->addWidget(new QLabel(a->contentSize(), fileGB), 2,1, Qt::AlignLeft); fileL->setColumnStretch(1,1); topL->addWidget(fileGB); //mime info QGroupBox *mimeGB = new QGroupBox( i18n("Mime"), page ); QGridLayout *mimeL=new QGridLayout(mimeGB); mimeL->setSpacing(5); mimeL->setMargin(15); mimeL->addItem( new QSpacerItem( 0, fontMetrics().lineSpacing()-9), 0, 0 ); m_imeType=new KLineEdit(mimeGB); m_imeType->setText(a->mimeType()); mimeL->addWidget(m_imeType, 1,1); QLabel *label = new QLabel(i18n("&Mime-Type:"), mimeGB); label->setBuddy(m_imeType); mimeL->addWidget(label, 1,0); d_escription=new KLineEdit(mimeGB); d_escription->setText(a->description()); mimeL->addWidget(d_escription, 2,1); label=new QLabel(i18n("&Description:"), mimeGB); label->setBuddy(d_escription); mimeL->addWidget(label, 2,0); e_ncoding=new QComboBox(mimeGB); e_ncoding->setEditable(false); e_ncoding->addItem("7Bit"); e_ncoding->addItem("8Bit"); e_ncoding->addItem("quoted-printable"); e_ncoding->addItem("base64"); if(a->isFixedBase64()) { e_ncoding->setCurrentIndex(3); e_ncoding->setEnabled(false); } else e_ncoding->setCurrentIndex(a->cte()); mimeL->addWidget(e_ncoding, 3,1); label=new QLabel(i18n("&Encoding:"), mimeGB); label->setBuddy(e_ncoding); mimeL->addWidget(label, 3,0); mimeL->setColumnStretch(1,1); topL->addWidget(mimeGB); //connections connect(m_imeType, SIGNAL(textChanged(QString)), this, SLOT(slotMimeTypeTextChanged(QString))); //finish GUI setFixedHeight(sizeHint().height()); KNHelper::restoreWindowSize("attProperties", this, QSize(300,250)); setHelp("anc-knode-editor-advanced"); } KNComposer::AttachmentPropertiesDlg::~AttachmentPropertiesDlg() { KNHelper::saveWindowSize("attProperties", this->size()); } void KNComposer::AttachmentPropertiesDlg::apply() { a_ttachment->setDescription(d_escription->text()); a_ttachment->setMimeType(m_imeType->text()); a_ttachment->setCte(e_ncoding->currentIndex()); } void KNComposer::AttachmentPropertiesDlg::accept() { if ( m_imeType->text().indexOf('/') == -1 ) { KMessageBox::sorry(this, i18n("You have set an invalid mime-type.\nPlease change it.")); return; } else if ( n_onTextAsText && m_imeType->text().indexOf( "text/", 0, Qt::CaseInsensitive ) != -1 && KMessageBox::warningContinueCancel(this, i18n("You have changed the mime-type of this non-textual attachment\nto text. This might cause an error while loading or encoding the file.\nProceed?") ) == KMessageBox::Cancel) return; // update the attachment apply(); KDialog::accept(); } void KNComposer::AttachmentPropertiesDlg::slotMimeTypeTextChanged(const QString &text) { enableButtonOk( !text.isEmpty() ); if(text.left(5)!="text/") { n_onTextAsText=a_ttachment->isFixedBase64(); e_ncoding->setCurrentIndex(3); e_ncoding->setEnabled(false); } else { e_ncoding->setCurrentIndex(a_ttachment->cte()); e_ncoding->setEnabled(true); } } //-------------------------------- // kate: space-indent on; indent-width 2;