00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
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
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
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
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
00107
00108
00109 QHBox * hbox = new QHBox( this );
00110 CHECK_PTR( hbox );
00111
00112 QSizePolicy pol( QSizePolicy::Fixed, QSizePolicy::Fixed );
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 );
00128
00129
00130
00131
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
00149 }
00150
00151
00152 void
00153 KFeedbackForm::sendMail()
00154 {
00155
00156
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
00173
00174
00175 QString body = subject + "\n\n"
00176 + formatComment()
00177 + _questionList->result();
00178
00179
00180
00181
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
00191
00192
00193
00194
00195
00196
00197
00198
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
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,
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