• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

selftestdialog.cpp

00001 /*
00002     Copyright (c) 2008 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "selftestdialog_p.h"
00021 #include "agentmanager.h"
00022 #include "session_p.h"
00023 #include "servermanager_p.h"
00024 
00025 #include <akonadi/private/xdgbasedirs_p.h>
00026 
00027 #include <KDebug>
00028 #include <KIcon>
00029 #include <KFileDialog>
00030 #include <KLocale>
00031 #include <KMessageBox>
00032 #include <KRun>
00033 #include <KStandardDirs>
00034 
00035 #include <QtCore/QFileInfo>
00036 #include <QtCore/QProcess>
00037 #include <QtCore/QSettings>
00038 #include <QtCore/QTextStream>
00039 #include <QtDBus/QtDBus>
00040 #include <QtGui/QApplication>
00041 #include <QtGui/QClipboard>
00042 #include <QtGui/QStandardItemModel>
00043 #include <QtSql/QSqlDatabase>
00044 #include <QtSql/QSqlError>
00045 
00046 // @cond PRIVATE
00047 
00048 #define AKONADI_CONTROL_SERVICE QLatin1String("org.freedesktop.Akonadi.Control")
00049 #define AKONADI_SERVER_SERVICE QLatin1String("org.freedesktop.Akonadi")
00050 #define AKONADI_SEARCH_SERVICE QLatin1String("org.kde.nepomuk.services.nepomukqueryservice")
00051 
00052 using namespace Akonadi;
00053 
00054 static QString makeLink( const QString &file )
00055 {
00056   return QString::fromLatin1( "<a href=\"%1\">%2</a>" ).arg( file, file );
00057 }
00058 
00059 enum SelfTestRole {
00060   ResultTypeRole = Qt::UserRole,
00061   FileIncludeRole,
00062   ListDirectoryRole,
00063   EnvVarRole,
00064   SummaryRole,
00065   DetailsRole
00066 };
00067 
00068 SelfTestDialog::SelfTestDialog(QWidget * parent) :
00069     KDialog( parent )
00070 {
00071   setCaption( i18n( "Akonadi Server Self-Test" ) );
00072   setButtons( Close | User1 | User2 );
00073   setButtonText( User1, i18n( "Save Report..." ) );
00074   setButtonIcon( User1, KIcon( QString::fromLatin1("document-save") ) );
00075   setButtonText( User2, i18n( "Copy Report to Clipboard" ) );
00076   setButtonIcon( User2, KIcon( QString::fromLatin1("edit-copy") ) );
00077   showButtonSeparator( true );
00078   ui.setupUi( mainWidget() );
00079 
00080   mTestModel = new QStandardItemModel( this );
00081   ui.testView->setModel( mTestModel );
00082   connect( ui.testView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
00083            SLOT(selectionChanged(QModelIndex)) );
00084   connect( ui.detailsLabel, SIGNAL(linkActivated(QString)), SLOT(linkActivated(QString)) );
00085 
00086   connect( this, SIGNAL(user1Clicked()), SLOT(saveReport()) );
00087   connect( this, SIGNAL(user2Clicked()), SLOT(copyReport()) );
00088 
00089   runTests();
00090 }
00091 
00092 void SelfTestDialog::hideIntroduction()
00093 {
00094   ui.introductionLabel->hide();
00095 }
00096 
00097 QStandardItem* SelfTestDialog::report( ResultType type, const KLocalizedString & summary, const KLocalizedString & details)
00098 {
00099   QStandardItem *item = new QStandardItem( summary.toString() );
00100   switch ( type ) {
00101     case Skip:
00102       item->setIcon( KIcon( QString::fromLatin1("dialog-ok") ) );
00103       break;
00104     case Success:
00105       item->setIcon( KIcon( QString::fromLatin1("dialog-ok-apply") ) );
00106       break;
00107     case Warning:
00108       item->setIcon( KIcon( QString::fromLatin1("dialog-warning") ) );
00109       break;
00110     case Error:
00111     default:
00112       item->setIcon( KIcon( QString::fromLatin1("dialog-error") ) );
00113   }
00114   item->setEditable( false );
00115   item->setWhatsThis( details.toString() );
00116   item->setData( type, ResultTypeRole );
00117   item->setData( summary.toString( 0 ), SummaryRole );
00118   item->setData( details.toString( 0 ), DetailsRole );
00119   mTestModel->appendRow( item );
00120   return item;
00121 }
00122 
00123 void SelfTestDialog::selectionChanged(const QModelIndex &index )
00124 {
00125   if ( index.isValid() ) {
00126     ui.detailsLabel->setText( index.data( Qt::WhatsThisRole ).toString() );
00127     ui.detailsGroup->setEnabled( true );
00128   } else {
00129     ui.detailsLabel->setText( QString() );
00130     ui.detailsGroup->setEnabled( false );
00131   }
00132 }
00133 
00134 void SelfTestDialog::runTests()
00135 {
00136   const QString driver = serverSetting( QLatin1String("General"), "Driver", QLatin1String("QMYSQL") ).toString();
00137   testSQLDriver();
00138   if (driver == QLatin1String( "QPSQL" )) {
00139     testPSQLServer();
00140   }
00141   else {
00142     testMySQLServer();
00143     testMySQLServerLog();
00144     testMySQLServerConfig();
00145   }
00146   testAkonadiCtl();
00147   testServerStatus();
00148   testSearchStatus();
00149   testProtocolVersion();
00150   testResources();
00151   testServerLog();
00152   testControlLog();
00153 }
00154 
00155 QVariant SelfTestDialog::serverSetting(const QString & group, const char *key, const QVariant &def ) const
00156 {
00157   const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
00158   QSettings settings( serverConfigFile, QSettings::IniFormat );
00159   settings.beginGroup( group );
00160   return settings.value( QString::fromLatin1(key), def );
00161 }
00162 
00163 bool SelfTestDialog::useStandaloneMysqlServer() const
00164 {
00165   const QString driver = serverSetting( QLatin1String("General"), "Driver", QLatin1String("QMYSQL") ).toString();
00166   if ( driver != QLatin1String( "QMYSQL" ) )
00167     return false;
00168   const bool startServer = serverSetting( driver, "StartServer", true ).toBool();
00169   if ( !startServer )
00170     return false;
00171   return true;
00172 }
00173 
00174 bool SelfTestDialog::runProcess(const QString & app, const QStringList & args, QString & result) const
00175 {
00176   QProcess proc;
00177   proc.start( app, args );
00178   const bool rv = proc.waitForFinished();
00179   result.clear();
00180   result += QString::fromLocal8Bit( proc.readAllStandardError() );
00181   result += QString::fromLocal8Bit( proc.readAllStandardOutput() );
00182   return rv;
00183 }
00184 
00185 void SelfTestDialog::testSQLDriver()
00186 {
00187   const QString driver = serverSetting( QLatin1String("General"), "Driver", QLatin1String("QMYSQL") ).toString();
00188   const QStringList availableDrivers = QSqlDatabase::drivers();
00189   const KLocalizedString detailsOk = ki18n( "The QtSQL driver '%1' is required by your current Akonadi server configuration and was found on your system." )
00190       .subs( driver );
00191   const KLocalizedString detailsFail = ki18n( "The QtSQL driver '%1' is required by your current Akonadi server configuration.\n"
00192       "The following drivers are installed: %2.\n"
00193       "Make sure the required driver is installed." )
00194       .subs( driver )
00195       .subs( availableDrivers.join( QLatin1String(", ") ) );
00196   QStandardItem *item = 0;
00197   if ( availableDrivers.contains( driver ) )
00198     item = report( Success, ki18n( "Database driver found." ), detailsOk );
00199   else
00200     item = report( Error, ki18n( "Database driver not found." ), detailsFail );
00201   item->setData( XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite ), FileIncludeRole );
00202 }
00203 
00204 void SelfTestDialog::testMySQLServer()
00205 {
00206   if ( !useStandaloneMysqlServer() ) {
00207     report( Skip, ki18n( "MySQL server executable not tested." ),
00208             ki18n( "The current configuration does not require an internal MySQL server." ) );
00209     return;
00210   }
00211 
00212   const QString driver = serverSetting( QLatin1String("General"), "Driver", QLatin1String("QMYSQL") ).toString();
00213   const QString serverPath = serverSetting( driver,  "ServerPath", QLatin1String("") ).toString(); // ### default?
00214 
00215   const KLocalizedString details = ki18n( "You currently have configured Akonadi to use the MySQL server '%1'.\n"
00216       "Make sure you have the MySQL server installed, set the correct path and ensure you have the "
00217       "necessary read and execution rights on the server executable. The server executable is typically "
00218       "called 'mysqld', its locations varies depending on the distribution." ).subs( serverPath );
00219 
00220   QFileInfo info( serverPath );
00221   if ( !info.exists() )
00222     report( Error, ki18n( "MySQL server not found." ), details );
00223   else if ( !info.isReadable() )
00224     report( Error, ki18n( "MySQL server not readable." ), details );
00225   else if ( !info.isExecutable() )
00226     report( Error, ki18n( "MySQL server not executable." ), details );
00227   else if ( !serverPath.contains( QLatin1String("mysqld") ) )
00228     report( Warning, ki18n( "MySQL found with unexpected name." ), details );
00229   else
00230     report( Success, ki18n( "MySQL server found." ), details );
00231 
00232   // be extra sure and get the server version while we are at it
00233   QString result;
00234   if ( runProcess( serverPath, QStringList() << QLatin1String( "--version" ), result ) ) {
00235     const KLocalizedString details = ki18n( "MySQL server found: %1" ).subs( result );
00236     report( Success, ki18n( "MySQL server is executable." ), details );
00237   } else {
00238     const KLocalizedString details = ki18n( "Executing the MySQL server '%1' failed with the following error message: '%2'" )
00239         .subs( serverPath ).subs( result );
00240     report( Error, ki18n( "Executing the MySQL server failed." ), details );
00241   }
00242 }
00243 
00244 void SelfTestDialog::testMySQLServerLog()
00245 {
00246   if ( !useStandaloneMysqlServer() ) {
00247     report( Skip, ki18n( "MySQL server error log not tested." ),
00248             ki18n( "The current configuration does not require an internal MySQL server." ) );
00249     return;
00250   }
00251 
00252   const QString logFileName = XdgBaseDirs::saveDir( "data", QLatin1String( "akonadi/db_data" ) )
00253       + QDir::separator() + QString::fromLatin1( "mysql.err" );
00254   const QFileInfo logFileInfo( logFileName );
00255   if ( !logFileInfo.exists() || logFileInfo.size() == 0 ) {
00256     report( Success, ki18n( "No current MySQL error log found." ),
00257       ki18n( "The MySQL server did not report any errors during this startup into '%1'." ).subs( logFileName ) );
00258     return;
00259   }
00260   QFile logFile( logFileName );
00261   if ( !logFile.open( QFile::ReadOnly | QFile::Text  ) ) {
00262     report( Error, ki18n( "MySQL error log not readable." ),
00263       ki18n( "A MySQL server error log file was found but is not readable: %1" ).subs( makeLink( logFileName ) ) );
00264     return;
00265   }
00266   bool warningsFound = false;
00267   QStandardItem *item = 0;
00268   while ( !logFile.atEnd() ) {
00269     const QString line = QString::fromUtf8( logFile.readLine() );
00270     if ( line.contains( QLatin1String( "error" ), Qt::CaseInsensitive ) ) {
00271       item = report( Error, ki18n( "MySQL server log contains errors." ),
00272         ki18n( "The MySQL server error log file '%1' contains errors." ).subs( makeLink( logFileName ) ) );
00273       item->setData( logFileName, FileIncludeRole );
00274       return;
00275     }
00276     if ( !warningsFound && line.contains( QLatin1String( "warn" ), Qt::CaseInsensitive ) ) {
00277       warningsFound = true;
00278     }
00279   }
00280   if ( warningsFound ) {
00281     item = report( Warning, ki18n( "MySQL server log contains warnings." ),
00282                    ki18n( "The MySQL server log file '%1' contains warnings." ).subs( makeLink( logFileName ) ) );
00283   } else {
00284     item = report( Success, ki18n( "MySQL server log contains no errors." ),
00285                    ki18n( "The MySQL server log file '%1' does not contain any errors or warnings." )
00286                          .subs( makeLink( logFileName ) ) );
00287   }
00288   item->setData( logFileName, FileIncludeRole );
00289 
00290   logFile.close();
00291 }
00292 
00293 void SelfTestDialog::testMySQLServerConfig()
00294 {
00295   if ( !useStandaloneMysqlServer() ) {
00296     report( Skip, ki18n( "MySQL server configuration not tested." ),
00297             ki18n( "The current configuration does not require an internal MySQL server." ) );
00298     return;
00299   }
00300 
00301   QStandardItem *item = 0;
00302   const QString globalConfig = XdgBaseDirs::findResourceFile( "config", QLatin1String( "akonadi/mysql-global.conf" ) );
00303   const QFileInfo globalConfigInfo( globalConfig );
00304   if ( !globalConfig.isEmpty() && globalConfigInfo.exists() && globalConfigInfo.isReadable() ) {
00305     item = report( Success, ki18n( "MySQL server default configuration found." ),
00306                    ki18n( "The default configuration for the MySQL server was found and is readable at %1." )
00307                    .subs( makeLink( globalConfig ) ) );
00308     item->setData( globalConfig, FileIncludeRole );
00309   } else {
00310     report( Error, ki18n( "MySQL server default configuration not found." ),
00311             ki18n( "The default configuration for the MySQL server was not found or was not readable. "
00312                   "Check your Akonadi installation is complete and you have all required access rights." ) );
00313   }
00314 
00315   const QString localConfig  = XdgBaseDirs::findResourceFile( "config", QLatin1String( "akonadi/mysql-local.conf" ) );
00316   const QFileInfo localConfigInfo( localConfig );
00317   if ( localConfig.isEmpty() || !localConfigInfo.exists() ) {
00318     report( Skip, ki18n( "MySQL server custom configuration not available." ),
00319             ki18n( "The custom configuration for the MySQL server was not found but is optional." ) );
00320   } else if ( localConfigInfo.exists() && localConfigInfo.isReadable() ) {
00321     item = report( Success, ki18n( "MySQL server custom configuration found." ),
00322                    ki18n( "The custom configuration for the MySQL server was found and is readable at %1" )
00323                    .subs( makeLink( localConfig ) ) );
00324     item->setData( localConfig, FileIncludeRole );
00325   } else {
00326     report( Error, ki18n( "MySQL server custom configuration not readable." ),
00327             ki18n( "The custom configuration for the MySQL server was found at %1 but is not readable. "
00328                   "Check your access rights." ).subs( makeLink( localConfig ) ) );
00329   }
00330 
00331   const QString actualConfig = XdgBaseDirs::saveDir( "data", QLatin1String( "akonadi" ) ) + QLatin1String("/mysql.conf");
00332   const QFileInfo actualConfigInfo( actualConfig );
00333   if ( actualConfig.isEmpty() || !actualConfigInfo.exists() || !actualConfigInfo.isReadable() ) {
00334     report( Error, ki18n( "MySQL server configuration not found or not readable." ),
00335             ki18n( "The MySQL server configuration was not found or is not readable." ) );
00336   } else {
00337     item = report( Success, ki18n( "MySQL server configuration is usable." ),
00338                    ki18n( "The MySQL server configuration was found at %1 and is readable.").subs( makeLink( actualConfig ) ) );
00339     item->setData( actualConfig, FileIncludeRole );
00340   }
00341 }
00342 
00343 void SelfTestDialog::testPSQLServer()
00344 {
00345   const QString dbname = serverSetting( QLatin1String( "QPSQL" ), "Name", QLatin1String( "akonadi" )).toString();
00346   const QString hostname = serverSetting( QLatin1String( "QPSQL" ), "Host", QLatin1String( "localhost" )).toString();
00347   const QString username = serverSetting( QLatin1String( "QPSQL" ), "User", QLatin1String( "akonadi" )).toString();
00348   const QString password = serverSetting( QLatin1String( "QPSQL" ), "Password", QLatin1String( "akonadi" )).toString();
00349   const int port = serverSetting( QLatin1String( "QPSQL" ), "Port", 5432).toInt();
00350 
00351   QSqlDatabase db = QSqlDatabase::addDatabase( QLatin1String( "QPSQL" ) );
00352   db.setHostName( hostname );
00353   db.setDatabaseName( dbname );
00354   db.setUserName( username );
00355   db.setPassword( password );
00356   db.setPort( port );
00357 
00358   if ( !db.open() ) {
00359     const KLocalizedString details = ki18n( db.lastError().text().toLatin1() );
00360     report( Error, ki18n( "Cannot connect to PostgreSQL server." ),  details);
00361   }
00362   else {
00363     report( Success, ki18n( "PostgreSQL server found." ),
00364                    ki18n( "The PostgreSQL server was found and connection is working."));
00365   }
00366   db.close();
00367 }
00368 
00369 void SelfTestDialog::testAkonadiCtl()
00370 {
00371   const QString path = KStandardDirs::findExe( QLatin1String("akonadictl") );
00372   if ( path.isEmpty() ) {
00373     report( Error, ki18n( "akonadictl not found" ),
00374                  ki18n( "The program 'akonadictl' needs to be accessible in $PATH. "
00375                        "Make sure you have the Akonadi server installed." ) );
00376     return;
00377   }
00378   QString result;
00379   if ( runProcess( path, QStringList() << QLatin1String( "--version" ), result ) ) {
00380     report( Success, ki18n( "akonadictl found and usable" ),
00381                    ki18n( "The program '%1' to control the Akonadi server was found "
00382                          "and could be executed successfully.\nResult:\n%2" ).subs( path ).subs( result ) );
00383   } else {
00384     report( Error, ki18n( "akonadictl found but not usable" ),
00385                  ki18n( "The program '%1' to control the Akonadi server was found "
00386                        "but could not be executed successfully.\nResult:\n%2\n"
00387                        "Make sure the Akonadi server is installed correctly." ).subs( path ).subs( result ) );
00388   }
00389 }
00390 
00391 void SelfTestDialog::testServerStatus()
00392 {
00393   if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE ) ) {
00394     report( Success, ki18n( "Akonadi control process registered at D-Bus." ),
00395                    ki18n( "The Akonadi control process is registered at D-Bus which typically indicates it is operational." ) );
00396   } else {
00397     report( Error, ki18n( "Akonadi control process not registered at D-Bus." ),
00398                  ki18n( "The Akonadi control process is not registered at D-Bus which typically means it was not started "
00399                        "or encountered a fatal error during startup."  ) );
00400   }
00401 
00402   if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_SERVER_SERVICE ) ) {
00403     report( Success, ki18n( "Akonadi server process registered at D-Bus." ),
00404                    ki18n( "The Akonadi server process is registered at D-Bus which typically indicates it is operational." ) );
00405   } else {
00406     report( Error, ki18n( "Akonadi server process not registered at D-Bus." ),
00407                  ki18n( "The Akonadi server process is not registered at D-Bus which typically means it was not started "
00408                        "or encountered a fatal error during startup."  ) );
00409   }
00410 }
00411 
00412 void SelfTestDialog::testSearchStatus()
00413 {
00414   bool searchAvailable = false;
00415   if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_SEARCH_SERVICE ) ) {
00416     searchAvailable = true;
00417     report( Success, ki18n( "Nepomuk search service registered at D-Bus." ),
00418                    ki18n( "The Nepomuk search service is registered at D-Bus which typically indicates it is operational." ) );
00419   } else {
00420     report( Error, ki18n( "Nepomuk search service not registered at D-Bus." ),
00421                    ki18n( "The Nepomuk search service is not registered at D-Bus which typically means it was not started "
00422                           "or encountered a fatal error during startup."  ) );
00423   }
00424 
00425   if ( searchAvailable ) {
00426     // check which backend is used
00427     QDBusInterface interface( QLatin1String( "org.kde.NepomukStorage" ), QLatin1String( "/nepomukstorage" ) );
00428     const QDBusReply<QString> reply = interface.call( QLatin1String( "usedSopranoBackend" ) );
00429     if ( reply.isValid() ) {
00430       const QString name = reply.value();
00431 
00432       // put blacklisted backends here
00433       if ( name.contains( QLatin1String( "redland" ) ) ) {
00434         report( Error, ki18n( "Nepomuk search service uses inappropriate backend." ),
00435                        ki18n( "The Nepomuk search service uses the '%1' backend, which is not "
00436                               "recommended for use with Akonadi." ).subs( name ) );
00437       } else {
00438         report( Success, ki18n( "Nepomuk search service uses an appropriate backend. " ),
00439                          ki18n( "The Nepomuk search service uses one of the recommended backends." ) );
00440       }
00441     }
00442   }
00443 }
00444 
00445 void SelfTestDialog::testProtocolVersion()
00446 {
00447   if ( Internal::serverProtocolVersion() < 0 ) {
00448     report( Skip, ki18n( "Protocol version check not possible." ),
00449             ki18n( "Without a connection to the server it is not possible to check if the protocol version meets the requirements." ) );
00450     return;
00451   }
00452   if ( Internal::serverProtocolVersion() < SessionPrivate::minimumProtocolVersion() ) {
00453     report( Error, ki18n( "Server protocol version is too old." ),
00454             ki18n( "The server protocol version is %1, but at least version %2 is required. "
00455                   "Install a newer version of the Akonadi server." )
00456                   .subs( Internal::serverProtocolVersion() )
00457                   .subs( SessionPrivate::minimumProtocolVersion() ) );
00458   } else {
00459     report( Success, ki18n( "Server protocol version is recent enough." ),
00460             ki18n( "The server Protocol version is %1, which equal or newer than the required version %2." )
00461                 .subs( Internal::serverProtocolVersion() )
00462                 .subs( SessionPrivate::minimumProtocolVersion() ) );
00463   }
00464 }
00465 
00466 void SelfTestDialog::testResources()
00467 {
00468   AgentType::List agentTypes = AgentManager::self()->types();
00469   bool resourceFound = false;
00470   foreach ( const AgentType &type, agentTypes ) {
00471     if ( type.capabilities().contains( QLatin1String("Resource") ) ) {
00472       resourceFound = true;
00473       break;
00474     }
00475   }
00476 
00477   const QStringList pathList = XdgBaseDirs::findAllResourceDirs( "data", QLatin1String( "akonadi/agents" ) );
00478   QStandardItem *item = 0;
00479   if ( resourceFound ) {
00480     item = report( Success, ki18n( "Resource agents found." ), ki18n( "At least one resource agent has been found." ) );
00481   } else {
00482     item = report( Error, ki18n( "No resource agents found." ),
00483       ki18n( "No resource agents have been found, Akonadi is not usable without at least one. "
00484             "This usually means that no resource agents are installed or that there is a setup problem. "
00485             "The following paths have been searched: '%1'. "
00486             "The XDG_DATA_DIRS environment variable is set to '%2', make sure this includes all paths "
00487             "where Akonadi agents are installed to." )
00488           .subs( pathList.join( QLatin1String(" ") ) )
00489           .subs( QString::fromLocal8Bit( qgetenv( "XDG_DATA_DIRS" ) ) ) );
00490   }
00491   item->setData( pathList, ListDirectoryRole );
00492   item->setData( QByteArray( "XDG_DATA_DIRS" ), EnvVarRole );
00493 }
00494 
00495 void Akonadi::SelfTestDialog::testServerLog()
00496 {
00497   QString serverLog = XdgBaseDirs::saveDir( "data", QLatin1String( "akonadi" ) )
00498       + QDir::separator() + QString::fromLatin1( "akonadiserver.error" );
00499   QFileInfo info( serverLog );
00500   if ( !info.exists() || info.size() <= 0 ) {
00501     report( Success, ki18n( "No current Akonadi server error log found." ),
00502                    ki18n( "The Akonadi server did not report any errors during its current startup." ) );
00503   } else {
00504     QStandardItem *item = report( Error, ki18n( "Current Akonadi server error log found." ),
00505       ki18n( "The Akonadi server did report error during startup into %1." ).subs( makeLink( serverLog ) ) );
00506     item->setData( serverLog, FileIncludeRole );
00507   }
00508 
00509   serverLog += QLatin1String(".old");
00510   info.setFile( serverLog );
00511   if ( !info.exists() || info.size() <= 0 ) {
00512     report( Success, ki18n( "No previous Akonadi server error log found." ),
00513                    ki18n( "The Akonadi server did not report any errors during its previous startup." ) );
00514   } else {
00515     QStandardItem *item = report( Error, ki18n( "Previous Akonadi server error log found." ),
00516       ki18n( "The Akonadi server did report error during its previous startup into %1." ).subs( makeLink( serverLog ) ) );
00517     item->setData( serverLog, FileIncludeRole );
00518   }
00519 }
00520 
00521 void SelfTestDialog::testControlLog()
00522 {
00523   QString controlLog = XdgBaseDirs::saveDir( "data", QLatin1String( "akonadi" ) )
00524       + QDir::separator() + QString::fromLatin1( "akonadi_control.error" );
00525   QFileInfo info( controlLog );
00526   if ( !info.exists() || info.size() <= 0 ) {
00527     report( Success, ki18n( "No current Akonadi control error log found." ),
00528                    ki18n( "The Akonadi control process did not report any errors during its current startup." ) );
00529   } else {
00530     QStandardItem *item = report( Error, ki18n( "Current Akonadi control error log found." ),
00531       ki18n( "The Akonadi control process did report error during startup into %1." ).subs( makeLink( controlLog ) ) );
00532     item->setData( controlLog, FileIncludeRole );
00533   }
00534 
00535   controlLog += QLatin1String(".old");
00536   info.setFile( controlLog );
00537   if ( !info.exists() || info.size() <= 0 ) {
00538     report( Success, ki18n( "No previous Akonadi control error log found." ),
00539                    ki18n( "The Akonadi control process did not report any errors during its previous startup." ) );
00540   } else {
00541     QStandardItem *item = report( Error, ki18n( "Previous Akonadi control error log found." ),
00542       ki18n( "The Akonadi control process did report error during its previous startup into %1." ).subs( makeLink( controlLog ) ) );
00543     item->setData( controlLog, FileIncludeRole );
00544   }
00545 }
00546 
00547 
00548 QString SelfTestDialog::createReport()
00549 {
00550   QString result;
00551   QTextStream s( &result );
00552   s << "Akonadi Server Self-Test Report" << endl;
00553   s << "===============================" << endl;
00554 
00555   for ( int i = 0; i < mTestModel->rowCount(); ++i ) {
00556     QStandardItem *item = mTestModel->item( i );
00557     s << endl;
00558     s << "Test " << (i + 1) << ":  ";
00559     switch ( item->data( ResultTypeRole ).toInt() ) {
00560       case Skip:
00561         s << "SKIP"; break;
00562       case Success:
00563         s << "SUCCESS"; break;
00564       case Warning:
00565         s << "WARNING"; break;
00566       case Error:
00567       default:
00568         s << "ERROR"; break;
00569     }
00570     s << endl << "--------" << endl;
00571     s << endl;
00572     s << item->data( SummaryRole ).toString() << endl;
00573     s << "Details: " << item->data( DetailsRole ).toString() << endl;
00574     if ( item->data( FileIncludeRole ).isValid() ) {
00575       s << endl;
00576       const QString fileName = item->data( FileIncludeRole ).toString();
00577       QFile f( fileName );
00578       if ( f.open( QFile::ReadOnly ) ) {
00579         s << "File content of '" << fileName << "':" << endl;
00580         s << f.readAll() << endl;
00581       } else {
00582         s << "File '" << fileName << "' could not be opened" << endl;
00583       }
00584     }
00585     if ( item->data( ListDirectoryRole ).isValid() ) {
00586       s << endl;
00587       const QStringList pathList = item->data( ListDirectoryRole ).toStringList();
00588       if ( pathList.isEmpty() )
00589         s << "Directory list is empty." << endl;
00590       foreach ( const QString &path, pathList ) {
00591         s << "Directory listing of '" << path << "':" << endl;
00592         QDir dir( path );
00593         dir.setFilter( QDir::AllEntries | QDir::NoDotAndDotDot );
00594         foreach ( const QString &entry, dir.entryList() )
00595           s << entry << endl;
00596       }
00597     }
00598     if ( item->data( EnvVarRole ).isValid() ) {
00599       s << endl;
00600       const QByteArray envVarName = item->data( EnvVarRole ).toByteArray();
00601       const QByteArray envVarValue = qgetenv( envVarName );
00602       s << "Environment variable " << envVarName << " is set to '" << envVarValue << "'" << endl;
00603     }
00604   }
00605 
00606   s << endl;
00607   s.flush();
00608   return result;
00609 }
00610 
00611 void SelfTestDialog::saveReport()
00612 {
00613   const QString fileName =  KFileDialog::getSaveFileName( KUrl(), QString(), this, i18n("Save Test Report") );
00614   if ( fileName.isEmpty() )
00615     return;
00616 
00617   QFile file( fileName );
00618   if ( !file.open( QFile::ReadWrite ) ) {
00619     KMessageBox::error( this, i18n( "Could not open file '%1'", fileName ) );
00620     return;
00621   }
00622 
00623   file.write( createReport().toUtf8() );
00624   file.close();
00625 }
00626 
00627 void SelfTestDialog::copyReport()
00628 {
00629   QApplication::clipboard()->setText( createReport() );
00630 }
00631 
00632 void SelfTestDialog::linkActivated(const QString & link)
00633 {
00634   KRun::runUrl( KUrl::fromPath( link ), QLatin1String("text/plain"), this );
00635 }
00636 
00637 // @endcond
00638 
00639 #include "selftestdialog_p.moc"

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.2-20100208
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal