Sophie

Sophie

distrib > Mandriva > 2010.1 > x86_64 > by-pkgid > 05ea160c3e539040248c38fe5960670d > files > 1

kdepimlibs4-4.4.5-0.2mdv2010.2.src.rpm

Index: kdepimlibs/akonadi/erroroverlay.cpp
===================================================================
--- kdepimlibs/akonadi/erroroverlay.cpp	(révision 1088137)
+++ kdepimlibs/akonadi/erroroverlay.cpp	(révision 1088138)
@@ -18,7 +18,7 @@
 */
 
 #include "erroroverlay_p.h"
-#include "servermanager.h"
+#include "ui_erroroverlay.h"
 #include "selftestdialog_p.h"
 
 #include <KDebug>
@@ -53,7 +53,8 @@
 
 ErrorOverlay::ErrorOverlay( QWidget *baseWidget, QWidget * parent ) :
     QWidget( parent ? parent : baseWidget->window() ),
-    mBaseWidget( baseWidget )
+    mBaseWidget( baseWidget ),
+    ui( new Ui::ErrorOverlay )
 {
   Q_ASSERT( baseWidget );
 
@@ -85,35 +86,26 @@
   connect( baseWidget, SIGNAL(destroyed()), SLOT(deleteLater()) );
   mPreviousState = mBaseWidget->isEnabled();
 
-  QBoxLayout *topLayout = new QVBoxLayout( this );
-  topLayout->addStretch();
-  mIconLabel = new QLabel( this );
-  mIconLabel->setPixmap( KIcon( QString::fromLatin1("dialog-error") ).pixmap( 64 ) );
-  mIconLabel->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
-  topLayout->addWidget( mIconLabel );
+  ui->setupUi( this );
+  ui->staticIconLabel->setPixmap( KIcon( QString::fromLatin1("dialog-error") ).pixmap( 64 ) );
+  ui->progressIconLabel->setPixmap( KIcon( QLatin1String( "akonadi") ).pixmap( 32 ) );
 
-  mDescLabel = new QLabel( this );
-  mDescLabel->setText( i18n( "<p style=\"color: white;\"><b>Akonadi not operational.<br/>"
+  ui->staticDescriptionLabel->setText( i18n( "<p><b>Akonadi not operational.<br/>"
       "<a href=\"details\" style=\"color: white;\">Details...</a></b></p>" ) );
-  mDescLabel->setWordWrap( true );
-  mDescLabel->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
-  connect( mDescLabel, SIGNAL(linkActivated(QString)), SLOT(linkActivated()) );
-  topLayout->addWidget( mDescLabel );
-  topLayout->addStretch();
+  connect( ui->staticDescriptionLabel, SIGNAL(linkActivated(QString)), SLOT(linkActivated()) );
 
-  setToolTip( i18n( "The Akonadi personal information management framework is not operational.\n"
+  ui->staticPage->setToolTip( i18n( "The Akonadi personal information management framework is not operational.\n"
       "Click on \"Details...\" to obtain detailed information on this problem." ) );
+  ui->stackWidget->setCurrentWidget( ui->staticPage );
 
-  mOverlayActive = ServerManager::isRunning();
-  if ( mOverlayActive )
-    started();
-  else
-    stopped();
-  connect( ServerManager::self(), SIGNAL(started()), SLOT(started()) );
-  connect( ServerManager::self(), SIGNAL(stopped()), SLOT(stopped()) );
+  const ServerManager::State state = ServerManager::state();
+  mOverlayActive = state == ServerManager::Running;
+  serverStateChanged( state );
+  connect( ServerManager::self(), SIGNAL(stateChanged(ServerManager::State)), SLOT(serverStateChanged(ServerManager::State)));
 
   QPalette p = palette();
   p.setColor( backgroundRole(), QColor( 0, 0, 0, 128 ) );
+  p.setColor( foregroundRole(), Qt::white );
   setPalette( p );
   setAutoFillBackground( true );
 
@@ -174,25 +166,44 @@
   dlg.exec();
 }
 
-void ErrorOverlay::started()
+void ErrorOverlay::serverStateChanged( ServerManager::State state )
 {
   if ( !mBaseWidget )
     return;
-  mOverlayActive = false;
-  hide();
-  mBaseWidget->setEnabled( mPreviousState );
-}
 
-void ErrorOverlay::stopped()
-{
-  if ( !mBaseWidget )
-    return;
-  mOverlayActive = true;
-  if ( mBaseWidget->isVisible() )
-    show();
-  mPreviousState = mBaseWidget->isEnabled();
-  mBaseWidget->setEnabled( false );
-  reposition();
+  if ( state == ServerManager::Running && mOverlayActive ) {
+    mOverlayActive = false;
+    hide();
+    mBaseWidget->setEnabled( mPreviousState );
+  } else if ( !mOverlayActive ) {
+    mOverlayActive = true;
+    if ( mBaseWidget->isVisible() )
+      show();
+    mPreviousState = mBaseWidget->isEnabled();
+    mBaseWidget->setEnabled( false );
+    reposition();
+  }
+
+  if ( mOverlayActive ) {
+    switch ( state ) {
+      case ServerManager::NotRunning:
+      case ServerManager::Broken:
+        ui->stackWidget->setCurrentWidget( ui->staticPage );
+        break;
+      case ServerManager::Starting:
+        ui->progressPage->setToolTip( i18n( "Akonadi personal information management service is starting...") );
+        ui->progressDescriptionLabel->setText( i18n( "Akonadi personal information management service is starting...") );
+        ui->stackWidget->setCurrentWidget( ui->progressPage );
+        break;
+      case ServerManager::Stopping:
+        ui->progressPage->setToolTip( i18n( "Akonadi personal information management service is shutting down...") );
+        ui->progressDescriptionLabel->setText( i18n( "Akonadi personal information management service is shutting down...") );
+        ui->stackWidget->setCurrentWidget( ui->progressPage );
+        break;
+      case ServerManager::Running:
+        break;
+    }
+  }
 }
 
 //@endcond
Index: kdepimlibs/akonadi/erroroverlay.ui
===================================================================
--- kdepimlibs/akonadi/erroroverlay.ui	(révision 0)
+++ kdepimlibs/akonadi/erroroverlay.ui	(révision 1088138)
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ErrorOverlay</class>
+ <widget class="QWidget" name="ErrorOverlay">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QStackedWidget" name="stackWidget">
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="staticPage">
+      <layout class="QVBoxLayout" name="verticalLayout_2">
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>118</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QLabel" name="staticIconLabel">
+         <property name="text">
+          <string/>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignCenter</set>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="staticDescriptionLabel">
+         <property name="text">
+          <string/>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignCenter</set>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>118</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="progressPage">
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <item>
+        <spacer name="verticalSpacer_3">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>113</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <spacer name="horizontalSpacer">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QLabel" name="progressIconLabel">
+           <property name="text">
+            <string/>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignCenter</set>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QProgressBar" name="progressBar">
+           <property name="maximum">
+            <number>0</number>
+           </property>
+           <property name="value">
+            <number>6735</number>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_2">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QLabel" name="progressDescriptionLabel">
+         <property name="text">
+          <string/>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignCenter</set>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer_4">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>113</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: kdepimlibs/akonadi/servermanager.cpp
===================================================================
--- kdepimlibs/akonadi/servermanager.cpp	(révision 1088137)
+++ kdepimlibs/akonadi/servermanager.cpp	(révision 1088138)
@@ -30,7 +30,10 @@
 #include <KGlobal>
 
 #include <QtDBus>
+#include <QTimer>
 
+#include <boost/scoped_ptr.hpp>
+
 #define AKONADI_CONTROL_SERVICE QLatin1String("org.freedesktop.Akonadi.Control")
 #define AKONADI_SERVER_SERVICE QLatin1String("org.freedesktop.Akonadi")
 
@@ -40,9 +43,12 @@
 {
   public:
     ServerManagerPrivate() :
-      instance( new ServerManager( this ) )
+      instance( new ServerManager( this ) ), mState( ServerManager::NotRunning ), mSafetyTimer( new QTimer )
     {
-      operational = instance->isRunning();
+      mState = instance->state();
+      mSafetyTimer->setSingleShot( true );
+      mSafetyTimer->setInterval( 10000 );
+      QObject::connect( mSafetyTimer.get(), SIGNAL(timeout()), instance, SLOT(timeout()) );
     }
 
     ~ServerManagerPrivate()
@@ -62,19 +68,37 @@
 
     void checkStatusChanged()
     {
-      const bool status = instance->isRunning();
-      if ( status == operational )
-        return;
-      operational = status;
-      if ( operational )
-        emit instance->started();
-      else
-        emit instance->stopped();
+      setState( instance->state() );
     }
 
+    void setState( ServerManager::State state )
+    {
+
+      if ( mState != state ) {
+        mState = state;
+        emit instance->stateChanged( state );
+        if ( state == ServerManager::Running )
+          emit instance->started();
+        else if ( state == ServerManager::NotRunning || state == ServerManager::Broken )
+          emit instance->stopped();
+
+        if ( state == ServerManager::Starting || state == ServerManager::Stopping )
+          mSafetyTimer->start();
+        else
+          mSafetyTimer->stop();
+      }
+    }
+
+    void timeout()
+    {
+      if ( mState == ServerManager::Starting || mState == ServerManager::Stopping )
+        setState( ServerManager::Broken );
+    }
+
     ServerManager *instance;
     static int serverProtocolVersion;
-    bool operational;
+    ServerManager::State mState;
+    boost::scoped_ptr<QTimer> mSafetyTimer;
 };
 
 int ServerManagerPrivate::serverProtocolVersion = -1;
@@ -103,6 +127,20 @@
 
 bool ServerManager::start()
 {
+  const bool controlRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE );
+  const bool serverRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_SERVER_SERVICE );
+  if (  controlRegistered && serverRegistered )
+    return true;
+
+  // TODO: use AKONADI_CONTROL_SERVICE_LOCK instead once we depend on a recent enough Akonadi server
+  const bool controlLockRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE + QLatin1String(".lock") );
+  if ( controlLockRegistered || controlRegistered ) {
+    kDebug() << "Akonadi server is already starting up";
+    sInstance->setState( Starting );
+    return true;
+  }
+
+  kDebug() << "executing akonadi_control";
   const bool ok = QProcess::startDetached( QLatin1String("akonadi_control") );
   if ( !ok ) {
     kWarning() << "Unable to execute akonadi_control, falling back to D-Bus auto-launch";
@@ -113,6 +151,7 @@
       return false;
     }
   }
+  sInstance->setState( Starting );
   return true;
 }
 
@@ -124,6 +163,7 @@
   if ( !iface.isValid() )
     return false;
   iface.call( QDBus::NoBlock, QString::fromLatin1("shutdown") );
+  sInstance->setState( Stopping );
   return true;
 }
 
@@ -136,31 +176,57 @@
 
 bool ServerManager::isRunning()
 {
-  if ( !QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE ) ||
-       !QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_SERVER_SERVICE ) ) {
-    return false;
+  return state() == Running;
+}
+
+ServerManager::State ServerManager::state()
+{
+  ServerManager::State previousState = NotRunning;
+  if ( sInstance.exists() ) // be careful, this is called from the ServerManager::Private ctor, so using sInstance unprotected can cause infinite recursion
+    previousState = sInstance->mState;
+
+  const bool controlRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE );
+  const bool serverRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_SERVER_SERVICE );
+  if (  controlRegistered && serverRegistered ) {
+    // check if the server protocol is recent enough
+    if ( sInstance.exists() ) {
+      if ( Internal::serverProtocolVersion() >= 0 &&
+           Internal::serverProtocolVersion() < SessionPrivate::minimumProtocolVersion() )
+        return Broken;
+    }
+
+    // HACK see if we are a agent ourselves and skip the test below which can in some cases deadlock the server
+    // and is not really needed in this case anyway since we happen to know at least one agent is available
+    QObject *obj = QDBusConnection::sessionBus().objectRegisteredAt( QLatin1String("/") );
+    if ( obj && dynamic_cast<AgentBase*>( obj ) )
+      return Running;
+
+    // besides the running server processes we also need at least one resource to be operational
+    AgentType::List agentTypes = AgentManager::self()->types();
+    foreach ( const AgentType &type, agentTypes ) {
+      if ( type.capabilities().contains( QLatin1String("Resource") ) )
+        return Running;
+    }
+    return Broken;
   }
 
-  // check if the server protocol is recent enough
-  if ( sInstance.exists() ) {
-    if ( Internal::serverProtocolVersion() >= 0 &&
-         Internal::serverProtocolVersion() < SessionPrivate::minimumProtocolVersion() )
-      return false;
+  // TODO: use AKONADI_CONTROL_SERVICE_LOCK instead once we depend on a recent enough Akonadi server
+  const bool controlLockRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE + QLatin1String(".lock") );
+  if ( controlLockRegistered || controlRegistered ) {
+    kDebug() << "Akonadi server is already starting up";
+    if ( previousState == Running )
+      return NotRunning; // we don't know if it's starting or stopping, probably triggered by someone else
+    return previousState;
   }
 
-  // HACK see if we are a agent ourselves and skip the test below which can in some cases deadlock the server
-  // and is not really needed in this case anyway since we happen to know at least one agent is available
-  QObject *obj = QDBusConnection::sessionBus().objectRegisteredAt( QLatin1String("/") );
-  if ( obj && dynamic_cast<AgentBase*>( obj ) )
-    return true;
+  if ( serverRegistered ) {
+    kWarning() << "Akonadi server running without control process!";
+    return Broken;
+  }
 
-  // besides the running server processes we also need at least one resource to be operational
-  AgentType::List agentTypes = AgentManager::self()->types();
-  foreach ( const AgentType &type, agentTypes ) {
-    if ( type.capabilities().contains( QLatin1String("Resource") ) )
-      return true;
-  }
-  return false;
+  if ( previousState == Starting || previousState == Broken ) // valid cases where nothing might be running (yet)
+    return previousState;
+  return NotRunning;
 }
 
 int Internal::serverProtocolVersion()
Index: kdepimlibs/akonadi/erroroverlay_p.h
===================================================================
--- kdepimlibs/akonadi/erroroverlay_p.h	(révision 1088137)
+++ kdepimlibs/akonadi/erroroverlay_p.h	(révision 1088138)
@@ -20,11 +20,17 @@
 #ifndef AKONADI_ERROROVERLAY_P_H
 #define AKONADI_ERROROVERLAY_P_H
 
+#include "servermanager.h"
+
 #include <QtCore/QPointer>
 #include <QtGui/QWidget>
 
-class QLabel;
+#include <boost/scoped_ptr.hpp>
 
+namespace Ui {
+  class ErrorOverlay;
+}
+
 namespace Akonadi {
 
 /**
@@ -54,15 +60,13 @@
 
   private slots:
     void linkActivated();
-    void started();
-    void stopped();
+    void serverStateChanged( ServerManager::State state );
 
   private:
     QPointer<QWidget> mBaseWidget;
-    QLabel *mIconLabel;
-    QLabel *mDescLabel;
     bool mPreviousState;
     bool mOverlayActive;
+    boost::scoped_ptr<Ui::ErrorOverlay> ui;
 
 };
 
Index: kdepimlibs/akonadi/servermanager.h
===================================================================
--- kdepimlibs/akonadi/servermanager.h	(révision 1088137)
+++ kdepimlibs/akonadi/servermanager.h	(révision 1088138)
@@ -42,6 +42,15 @@
 {
   Q_OBJECT
   public:
+    /** Enum for the various states the server can be in. */
+    enum State {
+        NotRunning, ///< Server is not running, could be noone started it yet or it failed to start.
+        Starting, ///< Server was started but is not yet running.
+        Running, ///< Server is running and operational.
+        Stopping, ///< Server is shutting down.
+        Broken ///< Server is not operational and an error has been detected.
+    };
+
     /**
      * Starts the server. This method returns imediately and does not wait
      * until the server is actually up and running. It is not checked if the
@@ -74,6 +83,11 @@
     static bool isRunning();
 
     /**
+     * Returns the state of the server.
+     */
+    static State state();
+
+    /**
      * Returns the singleton instance of this class, for connecting to its
      * signals
      */
@@ -90,6 +104,11 @@
      */
     void stopped();
 
+    /**
+     * Emitted when the server state changes.
+     */
+    void stateChanged( ServerManager::State state );
+
   private:
     //@cond PRIVATE
     friend class ServerManagerPrivate;
@@ -97,6 +116,7 @@
     ServerManagerPrivate* const d;
     Q_PRIVATE_SLOT( d, void serviceOwnerChanged( const QString&, const QString&, const QString& ) )
     Q_PRIVATE_SLOT( d, void checkStatusChanged() )
+    Q_PRIVATE_SLOT( d, void timeout() )
     //@endcond
 };