/*
* File name : kfeedback . cpp
* Summary : User feedback form
* License : LGPL - See file COPYING . LIB for details .
* Author : Stefan Hundhammer < sh @ suse . de >
*
* Updated : 2004 - 11 - 23
*/
# include <tqheader.h>
# include <tqlayout.h>
# include <tqlabel.h>
# include <tqmultilineedit.h>
# include <tqhbox.h>
# include <tdeglobal.h>
# include <kapp.h>
# include <tdelocale.h>
# include <kdebug.h>
# include <tdeaboutdata.h>
# include <kiconloader.h>
# include <kurl.h>
# include "kfeedback.h"
KFeedbackDialog : : KFeedbackDialog ( const TQString & feedbackMailAddress ,
const TQString & helpTopic )
: KDialogBase ( Plain , // dialogFace
i18n ( " Feedback " ) , // caption
Apply | Cancel
| ( helpTopic . isEmpty ( ) ? 0 : ( int ) Help ) , // buttonMask
Apply ) // defaultButton
{
TQVBoxLayout * layout = new TQVBoxLayout ( plainPage ( ) , 0 , spacingHint ( ) ) ;
setButtonApply ( KGuiItem ( i18n ( " &Mail this... " ) ) ) ;
if ( ! helpTopic . isEmpty ( ) )
setHelp ( helpTopic ) ;
_form = new KFeedbackForm ( feedbackMailAddress , plainPage ( ) ) ;
TQ_CHECK_PTR ( _form ) ;
layout - > addWidget ( _form ) ;
checkSendButton ( ) ;
connect ( this , TQ_SIGNAL ( applyClicked ( ) ) ,
_form , TQ_SLOT ( sendMail ( ) ) ) ;
connect ( _form , TQ_SIGNAL ( mailSent ( ) ) ,
this , TQ_SLOT ( hide ( ) ) ) ;
connect ( _form , TQ_SIGNAL ( mailSent ( ) ) ,
this , TQ_SIGNAL ( mailSent ( ) ) ) ;
connect ( _form , TQ_SIGNAL ( checkComplete ( ) ) ,
this , TQ_SLOT ( checkSendButton ( ) ) ) ;
}
KFeedbackDialog : : ~ KFeedbackDialog ( )
{
// NOP
}
void
KFeedbackDialog : : checkSendButton ( )
{
enableButtonApply ( _form - > readyToSend ( ) ) ;
}
KFeedbackForm : : KFeedbackForm ( const TQString & feedbackMailAddress ,
TQWidget * parent )
: TQVBox ( parent )
, _feedbackMailAddress ( feedbackMailAddress )
{
//
// Explanation above the question list
//
TQLabel * label = new TQLabel ( i18n ( " <p><b>Please tell us your opinion about this program.</b></p> "
" <p>You will be able to review everything in your mailer "
" before any mail is sent.<br> "
" Nothing will be sent behind your back.</p> "
) , this ) ;
//
// Question list
//
_questionList = new KFeedbackQuestionList ( this ) ;
TQ_CHECK_PTR ( _questionList ) ;
connect ( _questionList , TQ_SIGNAL ( checkComplete ( ) ) ,
this , TQ_SLOT ( slotCheckComplete ( ) ) ) ;
//
// Explanation below the question list
//
TQHBox * hbox = new TQHBox ( this ) ;
TQ_CHECK_PTR ( hbox ) ;
TQSizePolicy pol ( TQSizePolicy : : Fixed , TQSizePolicy : : Fixed ) ; // hor / vert
label = new TQLabel ( i18n ( " Questions marked with " ) , hbox ) ;
TQ_CHECK_PTR ( label ) ;
label - > setSizePolicy ( pol ) ;
label = new TQLabel ( hbox ) ;
TQ_CHECK_PTR ( label ) ;
label - > setPixmap ( TDEGlobal : : iconLoader ( ) - > loadIcon ( " edit " , TDEIcon : : Small ) ) ;
label - > setSizePolicy ( pol ) ;
label = new TQLabel ( i18n ( " must be answered before a mail can be sent. " ) , hbox ) ;
TQ_CHECK_PTR ( label ) ;
label - > setSizePolicy ( pol ) ;
new TQWidget ( hbox ) ; // Fill any leftover space to the right.
//
// Free-text comment field
//
label = new TQLabel ( " \n " + i18n ( " &Additional Comments: " ) , this ) ; TQ_CHECK_PTR ( label ) ;
_comment = new TQMultiLineEdit ( this ) ; TQ_CHECK_PTR ( _comment ) ;
label - > setBuddy ( _comment ) ;
_comment - > setWordWrap ( TQMultiLineEdit : : FixedColumnWidth ) ;
_comment - > setWrapColumnOrWidth ( 70 ) ;
}
KFeedbackForm : : ~ KFeedbackForm ( )
{
// NOP
}
void
KFeedbackForm : : sendMail ( )
{
//
// Build mail subject
//
TQString subject ;
const TDEAboutData * aboutData = TDEGlobal : : instance ( ) - > aboutData ( ) ;
if ( aboutData )
subject = aboutData - > programName ( ) + " - " + aboutData - > version ( ) ;
else
subject = kapp - > name ( ) ;
subject = " [kde-feedback] " + subject + " user feedback " ;
//
// Build mail body
//
TQString body = subject + " \n \n "
+ formatComment ( )
+ _questionList - > result ( ) ;
//
// Build "mailto:" URL from all this
//
KURL mail ;
mail . setProtocol ( " mailto " ) ;
mail . setPath ( _feedbackMailAddress ) ;
mail . setQuery ( " ?subject= " + KURL : : encode_string ( subject ) +
" &body= " + KURL : : encode_string ( body ) ) ;
// TODO: Check for maximum command line length.
//
// The hard part with this is how to get this from all that 'autoconf'
// stuff into 'config.h' or some other include file without hardcoding
// anything - this is too system dependent.
//
// Actually send mail
//
kapp - > invokeMailer ( mail ) ;
emit mailSent ( ) ;
}
void
KFeedbackForm : : slotCheckComplete ( )
{
emit checkComplete ( ) ;
}
TQString
KFeedbackForm : : formatComment ( )
{
TQString result = _comment - > text ( ) ;
if ( ! result . isEmpty ( ) )
{
result = " <comment> \n " + result + " \n </comment> \n \n " ;
}
return result ;
}
bool
KFeedbackForm : : readyToSend ( )
{
return _questionList - > isComplete ( ) ;
}
KFeedbackQuestionList : : KFeedbackQuestionList ( TQWidget * parent )
: TQListView ( parent )
{
addColumn ( " " ) ;
header ( ) - > hide ( ) ;
}
KFeedbackQuestionList : : ~ KFeedbackQuestionList ( )
{
// NOP
}
bool
KFeedbackQuestionList : : isComplete ( )
{
KFeedbackQuestion * question = firstQuestion ( ) ;
while ( question )
{
if ( question - > isRequired ( ) & & ! question - > isAnswered ( ) )
return false ;
question = question - > nextQuestion ( ) ;
}
return true ;
}
TQString
KFeedbackQuestionList : : result ( )
{
TQString res ;
KFeedbackQuestion * question = firstQuestion ( ) ;
while ( question )
{
res + = question - > result ( ) ;
question = question - > nextQuestion ( ) ;
}
return res ;
}
KFeedbackQuestion *
KFeedbackQuestionList : : addQuestion ( const TQString & text ,
const TQString & id ,
bool exclusiveAnswer ,
bool required )
{
KFeedbackQuestion * question = new KFeedbackQuestion ( this , text , id ,
exclusiveAnswer ,
required ) ;
TQ_CHECK_PTR ( question ) ;
return question ;
}
void
KFeedbackQuestionList : : addYesNoQuestion ( const TQString & text ,
const TQString & id ,
bool required )
{
KFeedbackQuestion * question = new KFeedbackQuestion ( this , text , id ,
true , // exclusive
required ) ;
TQ_CHECK_PTR ( question ) ;
question - > addAnswer ( i18n ( " yes " ) , " yes " ) ;
question - > addAnswer ( i18n ( " no " ) , " no " ) ;
}
void
KFeedbackQuestionList : : questionAnswered ( )
{
emit checkComplete ( ) ;
}
void
KFeedbackQuestionList : : questionAdded ( KFeedbackQuestion * question )
{
if ( question - > isRequired ( ) )
emit checkComplete ( ) ;
}
static int nextNo = 0 ;
KFeedbackQuestion : : KFeedbackQuestion ( KFeedbackQuestionList * parent ,
const TQString & text ,
const TQString & id ,
bool exclusiveAnswer ,
bool required ,
bool open )
: TQCheckListItem ( parent , text )
, _id ( id )
, _exclusiveAnswer ( exclusiveAnswer )
, _required ( required )
{
if ( required )
{
setPixmap ( 0 , TDEGlobal : : iconLoader ( ) - > loadIcon ( " edit " , TDEIcon : : Small ) ) ;
}
setOpen ( open ) ;
_no = nextNo + + ;
parent - > questionAdded ( this ) ;
}
void
KFeedbackQuestion : : addAnswer ( const TQString & text ,
const TQString & id )
{
new KFeedbackAnswer ( this , text , id , _exclusiveAnswer ) ;
}
bool
KFeedbackQuestion : : isAnswered ( )
{
if ( ! _exclusiveAnswer )
{
/**
* If any number of answers is permitted for this question , this
* question is always considered to be answered .
* */
return true ;
}
/**
* If this question requires an exclusive answer , exactly one of them
* should be checked . We don ' t need to bother about more than one being
* checked here - TQListView does that for us .
* */
KFeedbackAnswer * answer = firstAnswer ( ) ;
while ( answer )
{
if ( answer - > isChecked ( ) )
return true ;
answer = answer - > nextAnswer ( ) ;
}
return false ;
}
TQString
KFeedbackQuestion : : result ( )
{
TQString res ;
int answers = 0 ;
KFeedbackAnswer * answer = firstAnswer ( ) ;
while ( answer )
{
if ( answer - > isChecked ( ) )
{
res + = _id + " = \" " + answer - > id ( ) + " \" \n " ;
answers + + ;
}
answer = answer - > nextAnswer ( ) ;
}
if ( answers > 1 )
{
res = " \n " + res + " \n " ;
}
return res ;
}
TQString
KFeedbackQuestion : : text ( )
{
return TQCheckListItem : : text ( 0 ) ;
}
TQString
KFeedbackQuestion : : key ( int , bool ) const
{
TQString no ;
no . sprintf ( " %08d " , _no ) ;
return no ;
}
KFeedbackQuestionList *
KFeedbackQuestion : : questionList ( ) const
{
return dynamic_cast < KFeedbackQuestionList * > ( listView ( ) ) ;
}
KFeedbackAnswer : : KFeedbackAnswer ( KFeedbackQuestion * parent ,
const TQString & text ,
const TQString & id ,
bool exclusive )
: TQCheckListItem ( parent ,
text ,
exclusive
? TQCheckListItem : : RadioButton
: TQCheckListItem : : CheckBox )
, _id ( id )
{
_no = nextNo + + ;
}
TQString
KFeedbackAnswer : : text ( )
{
return TQCheckListItem : : text ( 0 ) ;
}
TQString
KFeedbackAnswer : : key ( int , bool ) const
{
TQString no ;
no . sprintf ( " %08d " , _no ) ;
return no ;
}
void
KFeedbackAnswer : : stateChange ( bool newState )
{
if ( newState & & question ( ) - > isRequired ( ) )
{
KFeedbackQuestionList * list = question ( ) - > questionList ( ) ;
if ( list )
list - > questionAnswered ( ) ;
}
}
# include "kfeedback.moc"
// EOF