Logo Search packages:      
Sourcecode: kmess version File versions

likeback.cpp

/***************************************************************************
 *   Copyright (C) 2006 by Sebastien Laout                                 *
 *   slaout@linux62.org                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.         *
 ***************************************************************************/


#include <KAboutData>
#include <KAction>
#include <KActionCollection>
#include <KApplication>
#include <KComponentData>
#include <KConfigGroup>
#include <KEMailSettings>
#include <KMessageBox>
#include <KStandardDirs>

#include "likeback.h"
#include "likebackbar.h"
#include "likebackdialog.h"
#include "likeback_p.h"
#include "../../kmessdebug.h"



// Constructor
00041 LikeBack::LikeBack( Button buttons, bool showBarByDefault, KConfig *config, const KAboutData *aboutData )
 : QObject()
{
  // Use default KApplication config and aboutData if not provided:
  if( config == 0 )
  {
    config = KGlobal::config().data();
  }
  if( aboutData == 0 )
  {
    aboutData = KGlobal::mainComponent().aboutData();
  }

  // Initialize properties (1/2):
  d = new LikeBackPrivate();
  d->buttons          = buttons;
  d->config           = config->group( "LikeBack" );
  d->aboutData        = aboutData;
  d->showBarByDefault = showBarByDefault;

  // Initialize properties (2/2) [Needs aboutData to be set]:
  d->showBar = userWantsToShowBar();

  // Initialize the button-bar:
  d->bar = new LikeBackBar( this );

  // Show the information message if it is the first time, and if the button-bar is shown:
  showInformationMessage();

  // Show the bar if that's wanted by the developer or the user:
  if( d->showBar )
  {
    d->bar->startTimer();
  }
}



// Destructor
00080 LikeBack::~LikeBack()
{
  delete d;
}



// Set the windows listing flag
00088 void LikeBack::setWindowNamesListing(WindowListing windowListing)
{
  d->windowListing = windowListing;
}



// Return the windows listing flag
00096 LikeBack::WindowListing LikeBack::windowNamesListing()
{
  return d->windowListing;
}



// Set which languages are accepted by the developers for the comments
00104 void LikeBack::setAcceptedLanguages( const QStringList &locales )
{
  d->acceptedLocales          = locales;
}



// Return the accepted languages for the comments
00112 QStringList LikeBack::acceptedLocales()
{
  return d->acceptedLocales;
}



// Set the site address where to send feedback
00120 void LikeBack::setServer(const QString &hostName, const QString &remotePath, quint16 hostPort)
{
  d->hostName   = hostName;
  d->remotePath = remotePath;
  d->hostPort   = hostPort;
}



// Get the developers site hostname
00130 QString LikeBack::hostName()
{
  return d->hostName;
}



// Get the path on the developers site
00138 QString LikeBack::remotePath()
{
  return d->remotePath;
}



// Get the developers site port
00146 quint16 LikeBack::hostPort()
{
  return d->hostPort;
}



// Disable the LikeBack Bar
00154 void LikeBack::disableBar()
{
  d->disabledCount++;
  if( d->bar && d->disabledCount > 0 )
  {
    d->bar->hide();
    d->bar->stopTimer();
  }
}



// Enable the LikeBack Bar
00167 void LikeBack::enableBar()
{
  d->disabledCount--;

#ifdef KMESSDEBUG_LIKEBACK
  if( d->disabledCount < 0 )
  {
    kError() << "Enabled more times than it was disabled. Please refer to the disableBar() documentation for more information and hints.";
  }
#endif

  if( d->bar && d->disabledCount <= 0 )
  {
    d->bar->startTimer();
  }
}



// Get whether the bar is enabled or not
00187 bool LikeBack::enabledBar()
{
  return d->disabledCount <= 0;
}



// Display the Send Comments dialog
00195 void LikeBack::execCommentDialog( Button type, const QString &initialComment, const QString &windowPath, const QString &context )
{
  disableBar();

  LikeBackDialog dialog( type, initialComment, windowPath, context, this );
  dialog.exec();

  enableBar();
}



// Display the Send Comments dialog
00208 void LikeBack::execCommentDialogFromHelp()
{
  execCommentDialog( AllButtons, /*initialComment=*/"", /*windowPath=*/"HelpMenuAction" );
}



// Retrieve which feedback buttons are active
00216 LikeBack::Button LikeBack::buttons()
{
  return d->buttons;
}



// Get the KAboutData stored object
00224 const KAboutData* LikeBack::aboutData()
{
  return d->aboutData;
}



// Get the KDE config stored object
00232 KConfig *LikeBack::config()
{
  return d->config.config();
}



// Return an action which opens the Send Comment dialog window
00240 KAction* LikeBack::sendACommentAction( KActionCollection *parent )
{
  if( d->action == 0 )
  {
    d->action = new KAction( KIcon("mail-message-new"), i18n("&Send a Comment to the Developers"), this );
    connect( d->action, SIGNAL(         triggered(bool) ),
             this,      SLOT  ( execCommentDialog()     ) );

    parent->addAction( "likeBackSendComment", d->action );
  }

  return d->action;
}



// Return whether the user wants to enable the likeback bar or not
00257 bool LikeBack::userWantsToShowBar()
{
  // Store the button-bar per version, so it can be disabled by the developer for the final version:
  return d->config.readEntry( "userWantToShowBarForVersion_" + d->aboutData->version(), d->showBarByDefault );
}



// Set whether the user wants to enable the likeback bar or not
00266 void LikeBack::setUserWantsToShowBar( bool showBar )
{
  if( showBar == d->showBar )
    return;

  d->showBar = showBar;

  // Store the button-bar per version, so it can be disabled by the developer for the final version:
  d->config.writeEntry( "userWantToShowBarForVersion_" + d->aboutData->version(), showBar );
  d->config.sync(); // Make sure the option is saved, even if the application crashes after that.

  if( showBar )
    d->bar->startTimer();
}



// Show a dialog box to introduce the user to LikeBack
00284 void LikeBack::showInformationMessage()
{
  // Load and register the images needed by the message:
  KIconLoader *loader = KIconLoader::global();
  QString likeIconPath   ( loader->iconPath( "likeback_like",    KIconLoader::Small ) );
  QString dislikeIconPath( loader->iconPath( "likeback_dislike", KIconLoader::Small ) );
  QString bugIconPath    ( loader->iconPath( "likeback_bug",     KIconLoader::Small ) );
  QString featureIconPath( loader->iconPath( "likeback_feature", KIconLoader::Small ) );

  // Show a message reflecting the allowed types of comment:
  Button buttons = d->buttons;
  int nbButtons = ( buttons & Like    ? 1 : 0 ) +
                  ( buttons & Dislike ? 1 : 0 ) +
                  ( buttons & Bug     ? 1 : 0 ) +
                  ( buttons & Feature ? 1 : 0 );

  // Construct the welcome phrase
  QString welcomePhrase;
  if( isDevelopmentVersion( d->aboutData->version() ) )
  {
    welcomePhrase = i18nc( "Welcome dialog text,header text for test apps",
                           "Welcome to this testing version of %1.", d->aboutData->programName() );
  }
  else
  {
    welcomePhrase = i18nc( "Welcome dialog text,header text for released apps",
                           "Welcome to %1.", d->aboutData->programName() );
  }

  // Construct the like and dislike explanation
  QString likeAndDislikePhrase;
  if( ( buttons & LikeBack::Like ) && ( buttons & LikeBack::Dislike ) )
  {
    likeAndDislikePhrase = i18nc( "Welcome dialog text,explanation for both the like and dislike buttons",
                                  "Each time you have a great or frustrating experience, "
                                  "please click the appropriate face below the window title-bar, "
                                  "briefly describe what you like or dislike and click Send." );
  }
  else if( buttons & LikeBack::Like )
  {
    likeAndDislikePhrase = i18nc( "Welcome dialog text,explanation for the like button alone",
                                  "Each time you have a great experience, "
                                  "please click the smiling face below the window title-bar, "
                                  "briefly describe what you like and click Send." );
  }
  else
  {
    likeAndDislikePhrase = i18nc( "Welcome dialog text,explanation for the dislike button alone",
                                  "Each time you have a frustrating experience, "
                                  "please click the frowning face below the window title-bar, "
                                  "briefly describe what you dislike and click Send." );
  }

  // Construct the bug report explanation
  QString bugPhrase;
  if( buttons & LikeBack::Bug )
  {
    bugPhrase = i18nc( "Welcome dialog text,explanation for the bug button",
                       "If you experience an improper behavior in the application, just click "
                       "the broken-object icon in the top-right corner of the window, describe "
                       "it and click Send." );
  }

  // Construct the usage examples
  QString examplesBlocks;
  if( buttons & LikeBack::Like )
  {
    examplesBlocks += "<span><img src=\"" + likeIconPath + "\"> &nbsp;" +
                      i18nc( "Welcome dialog text,usage example",
                             "<b>I like</b> the new artwork. Very refreshing." ) +
                      "</span><br/>";
  }
  if( buttons & LikeBack::Dislike )
  {
    examplesBlocks += "<span><img src=\"" + dislikeIconPath + "\"> &nbsp;" +
                      i18nc( "Welcome dialog text,usage example",
                             "<b>I dislike</b> the welcome page of that assistant. Too time consuming." ) +
                      "</span><br/>";
  }
  if( buttons & LikeBack::Bug )
  {
    examplesBlocks += "<span><img src=\"" + bugIconPath + "\"> &nbsp;" +
                      i18nc( "Welcome dialog text,usage example",
                             "<b>The application has an improper behaviour</b> when clicking the Add button. Nothing happens." ) +
                      "</span><br/>";
  }
  if( buttons & LikeBack::Feature )
  {
    examplesBlocks += "<span><img src=\"" + featureIconPath + "\"> &nbsp;" +
                      i18nc( "Welcome dialog text,usage example",
                             "<b>I desire a new feature</b> allowing me to send my work by email." ) +
                      "</span><br/>";
  }

  // Finally, merge all the strings together
  QString dialogText( "<h3>%1</h3>"
                      "<p>%2</p>"
                      "<p>%3</p>"
                      "<p>%4</p>"
                      "<h3>%5:</h3>"
                      "<p>%6</p>" );
  dialogText = dialogText.arg( welcomePhrase )
                         .arg( i18nc( "Welcome dialog text,us=the developers,it=the application",
                                      "To help us improve it, your comments are important." ) )
                         .arg( likeAndDislikePhrase )
                         .arg( bugPhrase )
                         .arg( i18ncp( "Welcome dialog text,header for the examples", "Example", "Examples", nbButtons ) )
                         .arg( examplesBlocks );

  // And show them
  KMessageBox::information( 0,
                            dialogText,
                            i18nc( "Welcome dialog title", "Help Improve the Application" ),
                            "LikeBack_starting_information" );
}



// Return the current window hierarchy
00403 QString LikeBack::activeWindowPath()
{
  // Compute the window hierarchy (from the oldest to the latest, each time prepending to the list):
  QStringList windowNames;
  QWidget *window = kapp->activeWindow();
  while( window )
  {
    QString name( window->objectName() );

    // Append the class name to the window name if it is unnamed:
    if( name == "unnamed" )
    {
      name += QString( ":" ) + window->metaObject()->className();
    }
    windowNames.prepend( name );

    window = dynamic_cast<QWidget*>( window->parent() );
  }

  // Return the string of windows starting by the end (from the oldest to the latest):
  return windowNames.join( " -> " );
}



// Return whether the email address was confirmed by the user
00429 bool LikeBack::emailAddressAlreadyProvided()
{
  return d->config.readEntry( "emailAlreadyAsked", false );
}



// Return the currently saved email address, or the account's email address, if present
00437 QString LikeBack::emailAddress()
{
  KEMailSettings emailSettings;
  return d->config.readEntry( "emailAddress", emailSettings.getSetting( KEMailSettings::EmailAddress ) );
}



// Change the saved email address
00446 void LikeBack::setEmailAddress( const QString &address, bool userProvided )
{
  d->config.writeEntry( "emailAddress", address );
  d->config.writeEntry( "emailAlreadyAsked", ( userProvided || emailAddressAlreadyProvided() ) );
  d->config.sync(); // Make sure the option is saved, even if the application crashes after that.
}



// FIXME: Should be moved to KAboutData? Cigogne will also need it.
00456 bool LikeBack::isDevelopmentVersion( const QString &version )
{
  return version.indexOf( "alpha", 0, Qt::CaseInsensitive ) != -1 ||
         version.indexOf( "beta",  0, Qt::CaseInsensitive ) != -1 ||
         version.indexOf( "rc",    0, Qt::CaseInsensitive ) != -1 ||
         version.indexOf( "svn",   0, Qt::CaseInsensitive ) != -1 ||
         version.indexOf( "cvs",   0, Qt::CaseInsensitive ) != -1;
}



// Return whether the Like button is active
bool LikeBack::isLikeActive() const
{
  return ( d->buttons & Like );
}



// Return whether the Dislike button is active
bool LikeBack::isDislikeActive() const
{
  return ( d->buttons & Dislike );
}



// Return whether the Bug button is active
bool LikeBack::isBugActive() const
{
  return ( d->buttons & Bug );
}



// Return whether the Feature button is active
bool LikeBack::isFeatureActive() const
{
  return ( d->buttons & Feature );
}



#include "likeback.moc"

Generated by  Doxygen 1.6.0   Back to index