# 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 <ntqheader.h>
    00017 #include <ntqlayout.h>
    00018 #include <ntqlabel.h>
    00019 #include <ntqmultilineedit.h>
    00020 #include <ntqhbox.h>
    00021
    00022 #include <tdeglobal.h>
    00023 #include <tdeapplication.h>
    00024 #include <tdelocale.h>
    00025 #include <kdebug.h>
    00026 #include <tdeaboutdata.h>
    00027 #include <kiconloader.h>
    00028 #include <kurl.h>
    00029 #include <tdeversion.h>
    00030
    00031 #include "kfeedback.h"
    00032
    00033
    00034 KFeedbackDialog::KFeedbackDialog( const TQString & feedbackMailAddress, const TQString & helpTopic )
    00035      : KDialogBase( Plain, i18n( "Feedback" ), Apply | ( helpTopic.isEmpty() ? Cancel : Cancel | Help ), Apply )
    00036 {
    00037     TQVBoxLayout * layout = new TQVBoxLayout( 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 TQString &    feedbackMailAddress,
    00081                            TQWidget *             parent )
    00082     : TQVBox( parent )
    00083     , _feedbackMailAddress( feedbackMailAddress )
    00084 {
    00085     //
    00086     // Explanation above the question list
    00087     //
    00088
    00089     TQLabel * label = new TQLabel( 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     TQHBox * hbox = new TQHBox( this );
    00110     CHECK_PTR( hbox );
    00111
    00112     TQSizePolicy pol( TQSizePolicy::Fixed, TQSizePolicy::Fixed ); // hor / vert
    00113
    00114     label = new TQLabel( i18n( "Questions marked with " ), hbox );
    00115     CHECK_PTR( label );
    00116     label->setSizePolicy( pol );
    00117
    00118     label = new TQLabel( hbox );
    00119     CHECK_PTR( label );
    00120     label->setPixmap( TDEGlobal::iconLoader()->loadIcon( "edit", TDEIcon::Small ) );
    00121     label->setSizePolicy( pol );
    00122
    00123     label = new TQLabel( i18n( " must be answered before a mail can be sent.") , hbox );
    00124     CHECK_PTR( label );
    00125     label->setSizePolicy( pol );
    00126
    00127     new TQWidget( hbox );    // Fill any leftover space to the right.
    00128
    00129
    00130     //
    00131     // Free-text comment field
    00132     //
    00133
    00134     label = new TQLabel( "\n" + i18n( "&Additional comments:" ), this );      CHECK_PTR( label );
    00135     _comment = new TQMultiLineEdit( this );                            CHECK_PTR( _comment );
    00136
    00137     label->setBuddy( _comment );
    00138 #if (TQT_VERSION < 300)
    00139     _comment->setFixedVisibleLines( 5 );
    00140 #endif
    00141     _comment->setWordWrap( TQMultiLineEdit::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     TQString subject;
    00160
    00161     const TDEAboutData * aboutData = TDEGlobal::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     TQString 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 TQString
    00215 KFeedbackForm::formatComment()
    00216 {
    00217     TQString 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( TQWidget *parent )
    00240     : TQListView( 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 TQString KFeedbackQuestionList::result()
    00271 {
    00272     TQString 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 += TDE_VERSION_STRING;
    00283
    00284     return res;
    00285 }
    00286
    00287
    00288 KFeedbackQuestion* KFeedbackQuestionList::addQuestion( const TQString &       text,
    00289                                 const TQString &  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 TQString &       text,
    00304                                     const TQString &     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 TQString &              text,
    00338                                   const TQString &              id,
    00339                                   bool                  exclusiveAnswer,
    00340                                   bool                  required,
    00341                                   bool                  open   )
    00342     : TQCheckListItem( parent, text )
    00343     , _id( id )
    00344     , _exclusiveAnswer( exclusiveAnswer )
    00345     , _required( required )
    00346 {
    00347     if ( required )
    00348     {
    00349        setPixmap( 0, TDEGlobal::iconLoader()->loadIcon( "edit", TDEIcon::Small ) );
    00350     }
    00351
    00352     setOpen( open );
    00353     _no = nextNo++;
    00354
    00355     parent->questionAdded( this );
    00356 }
    00357
    00358
    00359 void
    00360 KFeedbackQuestion::addAnswer( const TQString & text,
    00361                            const TQString & 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 TQString
    00402 KFeedbackQuestion::result()
    00403 {
    00404     TQString 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 TQString
    00430 KFeedbackQuestion::text()
    00431 {
    00432     return TQCheckListItem::text(0);
    00433 }
    00434
    00435
    00436 TQString
    00437 KFeedbackQuestion::key( int, bool ) const
    00438 {
    00439     TQString 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 TQString &    text,
    00460                               const TQString &    id,
    00461                               bool               exclusive )
    00462     : TQCheckListItem( parent,
    00463                     text,
    00464                     exclusive
    00465                     ? TQCheckListItem::RadioButton
    00466                     : TQCheckListItem::CheckBox )
    00467     , _id( id )
    00468 {
    00469     _no = nextNo++;
    00470 }
    00471
    00472
    00473 TQString
    00474 KFeedbackAnswer::text()
    00475 {
    00476     return TQCheckListItem::text(0);
    00477 }
    00478
    00479
    00480 TQString
    00481 KFeedbackAnswer::key( int, bool ) const
    00482 {
    00483     TQString 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