kfeedback.cpp

00001 
00002 /*
00003  *   File name:      kfeedback.cpp
00004  *   Summary: User feedback form
00005  *   License: LGPL - See file COPYING.LIB for details.
00006  *   Author:  Stefan Hundhammer <sh@suse.de>
00007  *   modified by Eggert Ehmke <eggert.ehmke@berlin.de>
00008  *
00009  *   Updated: 2002-02-24
00010  *
00011  *   $Id: kfeedback_8cpp-source.html,v 1.10 2007/07/05 17:37:51 kuddel-fl Exp $
00012  *
00013  */
00014 
00015 
00016 #include <qheader.h>
00017 #include <qlayout.h>
00018 #include <qlabel.h>
00019 #include <qmultilineedit.h>
00020 #include <qhbox.h>
00021 
00022 #include <kglobal.h>
00023 #include <kapplication.h>
00024 #include <klocale.h>
00025 #include <kdebug.h>
00026 #include <kaboutdata.h>
00027 #include <kiconloader.h>
00028 #include <kurl.h>
00029 #include <kdeversion.h>
00030 
00031 #include "kfeedback.h"
00032 
00033 
00034 KFeedbackDialog::KFeedbackDialog( const QString & feedbackMailAddress, const QString & helpTopic )
00035      : KDialogBase( Plain, i18n( "Feedback" ), Apply | ( helpTopic.isEmpty() ? Cancel : Cancel | Help ), Apply )
00036 {
00037     QVBoxLayout * layout = new QVBoxLayout( plainPage(), 0, spacingHint() );
00038     // setButtonApplyText( i18n( "&Mail this..." ) ); deprecated
00039     setButtonApply(KGuiItem (i18n( "&Mail this..." )));
00040 
00041     if ( ! helpTopic.isEmpty() )
00042        setHelp( helpTopic );
00043 
00044     _form = new KFeedbackForm( feedbackMailAddress, plainPage() );
00045     CHECK_PTR( _form );
00046 
00047     layout->addWidget( _form );
00048     checkSendButton();
00049 
00050     connect( this,  SIGNAL( applyClicked() ),
00051             _form, SLOT  ( sendMail()  ) );
00052 
00053     connect( _form, SIGNAL( mailSent()    ),
00054             this,  SLOT  ( hide()  ) );
00055 
00056     connect( _form, SIGNAL( mailSent()    ),
00057             this,  SIGNAL( mailSent()  ) );
00058 
00059     connect( _form, SIGNAL( checkComplete()   ),
00060             this,  SLOT  ( checkSendButton() ) );
00061 }
00062 
00063 
00064 KFeedbackDialog::~KFeedbackDialog()
00065 {
00066     // NOP
00067 }
00068 
00069 
00070 void
00071 KFeedbackDialog::checkSendButton()
00072 {
00073     enableButtonApply( _form->readyToSend() );
00074 }
00075 
00076 
00077 
00078 
00079 
00080 KFeedbackForm::KFeedbackForm( const QString &    feedbackMailAddress,
00081                            QWidget *             parent )
00082     : QVBox( parent )
00083     , _feedbackMailAddress( feedbackMailAddress )
00084 {
00085     //
00086     // Explanation above the question list
00087     //
00088 
00089     QLabel * label = new QLabel( i18n( "<p><b>Please tell us your opinion about this program.</b></p>"
00090                                    "<p>You will be able to review everything in your mailer "
00091                                    "before any mail is sent.<br>"
00092                                    "Nothing will be sent behind your back.</p>"
00093                                    ), this );
00094     //
00095     // Question list
00096     //
00097 
00098     _questionList = new KFeedbackQuestionList( this );
00099     CHECK_PTR( _questionList );
00100 
00101     connect( _questionList, SIGNAL( checkComplete()     ),
00102             this,        SLOT  ( slotCheckComplete() ) );
00103 
00104 
00105     //
00106     // Explanation below the question list
00107     //
00108 
00109     QHBox * hbox = new QHBox( this );
00110     CHECK_PTR( hbox );
00111 
00112     QSizePolicy pol( QSizePolicy::Fixed, QSizePolicy::Fixed ); // hor / vert
00113 
00114     label = new QLabel( i18n( "Questions marked with " ), hbox );
00115     CHECK_PTR( label );
00116     label->setSizePolicy( pol );
00117 
00118     label = new QLabel( hbox );
00119     CHECK_PTR( label );
00120     label->setPixmap( KGlobal::iconLoader()->loadIcon( "edit", KIcon::Small ) );
00121     label->setSizePolicy( pol );
00122 
00123     label = new QLabel( i18n( " must be answered before a mail can be sent.") , hbox );
00124     CHECK_PTR( label );
00125     label->setSizePolicy( pol );
00126 
00127     new QWidget( hbox );    // Fill any leftover space to the right.
00128 
00129 
00130     //
00131     // Free-text comment field
00132     //
00133 
00134     label = new QLabel( "\n" + i18n( "&Additional comments:" ), this );      CHECK_PTR( label );
00135     _comment = new QMultiLineEdit( this );                            CHECK_PTR( _comment );
00136 
00137     label->setBuddy( _comment );
00138 #if (QT_VERSION < 300)
00139     _comment->setFixedVisibleLines( 5 );
00140 #endif
00141     _comment->setWordWrap( QMultiLineEdit::FixedColumnWidth );
00142     _comment->setWrapColumnOrWidth( 70 );
00143 }
00144 
00145 
00146 KFeedbackForm::~KFeedbackForm()
00147 {
00148     // NOP
00149 }
00150 
00151 
00152 void
00153 KFeedbackForm::sendMail()
00154 {
00155     //
00156     // Build mail subject
00157     //
00158 
00159     QString subject;
00160 
00161     const KAboutData * aboutData = KGlobal::instance()->aboutData();
00162 
00163     if ( aboutData )
00164       subject = aboutData->programName() + "-" + aboutData->version();
00165     else
00166       subject = kapp->name();
00167 
00168     subject += " user feedback";
00169 
00170 
00171     //
00172     // Build mail body
00173     //
00174 
00175     QString body = subject + "\n\n"
00176        + formatComment()
00177        + _questionList->result();
00178 
00179 
00180     //
00181     // Build "mailto:" URL from all this
00182     //
00183 
00184     KURL mail;
00185     mail.setProtocol( "mailto" );
00186     mail.setPath( _feedbackMailAddress );
00187     mail.setQuery( "?subject="     + KURL::encode_string( subject ) +
00188                  "&body="   + KURL::encode_string( body ) );
00189 
00190     // TODO: Check for maximum command line length.
00191     //
00192     // The hard part with this is how to get this from all that 'autoconf'
00193     // stuff into 'config.h' or some other include file without hardcoding
00194     // anything - this is too system dependent.
00195 
00196 
00197     //
00198     // Actually send mail
00199     //
00200 
00201     kapp->invokeMailer( mail );
00202 
00203     emit mailSent();
00204 }
00205 
00206 
00207 void
00208 KFeedbackForm::slotCheckComplete()
00209 {
00210     emit checkComplete();
00211 }
00212 
00213 
00214 QString
00215 KFeedbackForm::formatComment()
00216 {
00217     QString result = _comment->text();
00218 
00219     if ( ! result.isEmpty() )
00220     {
00221        result = "<comment>\n" + result + "\n</comment>\n\n";
00222     }
00223 
00224     return result;
00225 }
00226 
00227 
00228 bool
00229 KFeedbackForm::readyToSend()
00230 {
00231     return _questionList->isComplete();
00232 }
00233 
00234 
00235 
00236 
00237 
00238 
00239 KFeedbackQuestionList::KFeedbackQuestionList( QWidget *parent )
00240     : QListView( parent )
00241 {
00242     addColumn( "" );
00243     header()->hide();
00244 }
00245 
00246 
00247 KFeedbackQuestionList::~KFeedbackQuestionList()
00248 {
00249     // NOP
00250 }
00251 
00252 
00253 bool
00254 KFeedbackQuestionList::isComplete()
00255 {
00256     KFeedbackQuestion * question = firstQuestion();
00257 
00258     while ( question )
00259     {
00260        if ( question->isRequired() && ! question->isAnswered() )
00261            return false;
00262 
00263        question = question->nextQuestion();
00264     }
00265 
00266     return true;
00267 }
00268 
00269 
00270 QString KFeedbackQuestionList::result()
00271 {
00272     QString res;
00273     KFeedbackQuestion * question = firstQuestion();
00274 
00275     while ( question )
00276     {
00277       res += question->result();
00278 
00279       question = question->nextQuestion();
00280     }
00281     res += "Compiled on KDE version: ";
00282     res += KDE_VERSION_STRING;
00283 
00284     return res;
00285 }
00286 
00287 
00288 KFeedbackQuestion* KFeedbackQuestionList::addQuestion( const QString &       text,
00289                                 const QString &  id,
00290                                 bool             exclusiveAnswer,
00291                                 bool             required )
00292 {
00293     KFeedbackQuestion * question = new KFeedbackQuestion( this, text, id,
00294                                                    exclusiveAnswer,
00295                                                    required );
00296     CHECK_PTR( question );
00297 
00298     return question;
00299 }
00300 
00301 
00302 void
00303 KFeedbackQuestionList::addYesNoQuestion( const QString &       text,
00304                                     const QString &     id,
00305                                     bool                required )
00306 {
00307 
00308     KFeedbackQuestion * question = new KFeedbackQuestion( this, text, id,
00309                                                    true,       // exclusive
00310                                                    required );
00311     CHECK_PTR( question );
00312     question->addAnswer( i18n( "yes" ), "yes" );
00313     question->addAnswer( i18n( "no"  ), "no"  );
00314 }
00315 
00316 
00317 void
00318 KFeedbackQuestionList::questionAnswered()
00319 {
00320     emit checkComplete();
00321 }
00322 
00323 void
00324 KFeedbackQuestionList::questionAdded( KFeedbackQuestion * question)
00325 {
00326     if ( question->isRequired() )
00327        emit checkComplete();
00328 }
00329 
00330 
00331 
00332 
00333 
00334 static int nextNo = 0;
00335 
00336 KFeedbackQuestion::KFeedbackQuestion( KFeedbackQuestionList *  parent,
00337                                   const QString &              text,
00338                                   const QString &              id,
00339                                   bool                  exclusiveAnswer,
00340                                   bool                  required,
00341                                   bool                  open   )
00342     : QCheckListItem( parent, text )
00343     , _id( id )
00344     , _exclusiveAnswer( exclusiveAnswer )
00345     , _required( required )
00346 {
00347     if ( required )
00348     {
00349        setPixmap( 0, KGlobal::iconLoader()->loadIcon( "edit", KIcon::Small ) );
00350     }
00351 
00352     setOpen( open );
00353     _no = nextNo++;
00354 
00355     parent->questionAdded( this );
00356 }
00357 
00358 
00359 void
00360 KFeedbackQuestion::addAnswer( const QString & text,
00361                            const QString & id   )
00362 {
00363     new KFeedbackAnswer( this, text, id, _exclusiveAnswer );
00364 }
00365 
00366 
00367 bool
00368 KFeedbackQuestion::isAnswered()
00369 {
00370     if ( ! _exclusiveAnswer )
00371     {
00377        return true;
00378     }
00379 
00380 
00387     KFeedbackAnswer *answer = firstAnswer();
00388 
00389     while ( answer )
00390     {
00391        if ( answer->isChecked() )
00392            return true;
00393 
00394        answer = answer->nextAnswer();
00395     }
00396 
00397     return false;
00398 }
00399 
00400 
00401 QString
00402 KFeedbackQuestion::result()
00403 {
00404     QString res;
00405     int answers = 0;
00406 
00407     KFeedbackAnswer *answer = firstAnswer();
00408 
00409     while ( answer )
00410     {
00411        if ( answer->isChecked() )
00412        {
00413            res += _id + "=\"" + answer->id() + "\"\n";
00414            answers++;
00415        }
00416 
00417        answer = answer->nextAnswer();
00418     }
00419 
00420     if ( answers > 1 )
00421     {
00422        res = "\n" + res + "\n";
00423     }
00424 
00425     return res;
00426 }
00427 
00428 
00429 QString
00430 KFeedbackQuestion::text()
00431 {
00432     return QCheckListItem::text(0);
00433 }
00434 
00435 
00436 QString
00437 KFeedbackQuestion::key( int, bool ) const
00438 {
00439     QString no;
00440     no.sprintf( "%08d", _no );
00441 
00442     return no;
00443 }
00444 
00445 
00446 KFeedbackQuestionList *
00447 KFeedbackQuestion::questionList() const
00448 {
00449     return dynamic_cast<KFeedbackQuestionList *>( listView() );
00450 }
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 KFeedbackAnswer::KFeedbackAnswer( KFeedbackQuestion *   parent,
00459                               const QString &    text,
00460                               const QString &    id,
00461                               bool               exclusive )
00462     : QCheckListItem( parent,
00463                     text,
00464                     exclusive
00465                     ? QCheckListItem::RadioButton
00466                     : QCheckListItem::CheckBox )
00467     , _id( id )
00468 {
00469     _no = nextNo++;
00470 }
00471 
00472 
00473 QString
00474 KFeedbackAnswer::text()
00475 {
00476     return QCheckListItem::text(0);
00477 }
00478 
00479 
00480 QString
00481 KFeedbackAnswer::key( int, bool ) const
00482 {
00483     QString no;
00484     no.sprintf( "%08d", _no );
00485 
00486     return no;
00487 }
00488 
00489 
00490 void
00491 KFeedbackAnswer::stateChange( bool newState )
00492 {
00493     if ( newState && question()->isRequired() )
00494     {
00495        KFeedbackQuestionList * list = question()->questionList();
00496 
00497        if ( list )
00498            list->questionAnswered();
00499     }
00500 }
00501 
00502 
00503 
00504 // EOF

Generated on Thu Jul 5 19:36:06 2007 for kshowmail by  doxygen 1.5.0