You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
501 lines
9.3 KiB
501 lines
9.3 KiB
|
|
/*
|
|
* 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, TQT_SIGNAL( applyClicked() ),
|
|
_form, TQT_SLOT ( sendMail() ) );
|
|
|
|
connect( _form, TQT_SIGNAL( mailSent() ),
|
|
this, TQT_SLOT ( hide() ) );
|
|
|
|
connect( _form, TQT_SIGNAL( mailSent() ),
|
|
this, TQT_SIGNAL( mailSent() ) );
|
|
|
|
connect( _form, TQT_SIGNAL( checkComplete() ),
|
|
this, TQT_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, TQT_SIGNAL( checkComplete() ),
|
|
this, TQT_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
|