akonadi
erroroverlay.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 "erroroverlay_p.h" 00021 #include "ui_erroroverlay.h" 00022 #include "selftestdialog_p.h" 00023 00024 #include <KDebug> 00025 #include <KIcon> 00026 #include <KLocale> 00027 00028 #include <QtCore/QEvent> 00029 #include <QtGui/QBoxLayout> 00030 #include <QtGui/QLabel> 00031 #include <QtGui/QPalette> 00032 00033 using namespace Akonadi; 00034 00035 //@cond PRIVATE 00036 00037 class ErrorOverlayStatic 00038 { 00039 public: 00040 QVector<QPair<QPointer<QWidget>, QPointer<QWidget> > > baseWidgets; 00041 }; 00042 00043 K_GLOBAL_STATIC( ErrorOverlayStatic, sInstanceOverlay ) 00044 00045 static bool isParentOf( QObject* o1, QObject* o2 ) 00046 { 00047 if ( !o1 || !o2 ) 00048 return false; 00049 if ( o1 == o2 ) 00050 return true; 00051 return isParentOf( o1, o2->parent() ); 00052 } 00053 00054 ErrorOverlay::ErrorOverlay( QWidget *baseWidget, QWidget * parent ) : 00055 QWidget( parent ? parent : baseWidget->window() ), 00056 mBaseWidget( baseWidget ), 00057 ui( new Ui::ErrorOverlay ) 00058 { 00059 Q_ASSERT( baseWidget ); 00060 00061 // check existing overlays to detect cascading 00062 for ( QVector<QPair< QPointer<QWidget>, QPointer<QWidget> > >::Iterator it = sInstanceOverlay->baseWidgets.begin(); 00063 it != sInstanceOverlay->baseWidgets.end(); ) { 00064 if ( (*it).first == 0 || (*it).second == 0 ) { 00065 // garbage collection 00066 it = sInstanceOverlay->baseWidgets.erase( it ); 00067 continue; 00068 } 00069 if ( isParentOf( (*it).first, baseWidget ) ) { 00070 // parent already has an overlay, kill ourselves 00071 mBaseWidget = 0; 00072 hide(); 00073 deleteLater(); 00074 return; 00075 } 00076 if ( isParentOf( baseWidget, (*it).first ) ) { 00077 // child already has overlay, kill that one 00078 delete (*it).second; 00079 it = sInstanceOverlay->baseWidgets.erase( it ); 00080 continue; 00081 } 00082 ++it; 00083 } 00084 sInstanceOverlay->baseWidgets.append( qMakePair( mBaseWidget, QPointer<QWidget>( this ) ) ); 00085 00086 connect( baseWidget, SIGNAL( destroyed() ), SLOT( deleteLater() ) ); 00087 mPreviousState = mBaseWidget->isEnabled(); 00088 00089 ui->setupUi( this ); 00090 ui->notRunningIcon->setPixmap( KIcon( QLatin1String( "akonadi" ) ).pixmap( 64 ) ); 00091 ui->brokenIcon->setPixmap( KIcon( QString::fromLatin1( "dialog-error" ) ).pixmap( 64 ) ); 00092 ui->progressIcon->setPixmap( KIcon( QLatin1String( "akonadi" ) ).pixmap( 32 ) ); 00093 00094 connect( ui->startButton, SIGNAL( clicked() ), SLOT( startClicked() ) ); 00095 connect( ui->selfTestButton, SIGNAL( clicked() ), SLOT( selfTestClicked() ) ); 00096 00097 const ServerManager::State state = ServerManager::state(); 00098 mOverlayActive = state == ServerManager::Running; 00099 serverStateChanged( state ); 00100 connect( ServerManager::self(), SIGNAL( stateChanged( Akonadi::ServerManager::State ) ), 00101 SLOT( serverStateChanged( Akonadi::ServerManager::State ) ) ); 00102 00103 QPalette p = palette(); 00104 p.setColor( backgroundRole(), QColor( 0, 0, 0, 128 ) ); 00105 p.setColor( foregroundRole(), Qt::white ); 00106 setPalette( p ); 00107 setAutoFillBackground( true ); 00108 00109 mBaseWidget->installEventFilter( this ); 00110 00111 reposition(); 00112 } 00113 00114 ErrorOverlay::~ ErrorOverlay() 00115 { 00116 if ( mBaseWidget ) 00117 mBaseWidget->setEnabled( mPreviousState ); 00118 } 00119 00120 void ErrorOverlay::reposition() 00121 { 00122 if ( !mBaseWidget ) 00123 return; 00124 00125 // reparent to the current top level widget of the base widget if needed 00126 // needed eg. in dock widgets 00127 if ( parentWidget() != mBaseWidget->window() ) 00128 setParent( mBaseWidget->window() ); 00129 00130 // follow base widget visibility 00131 // needed eg. in tab widgets 00132 if ( !mBaseWidget->isVisible() ) { 00133 hide(); 00134 return; 00135 } 00136 if ( mOverlayActive ) 00137 show(); 00138 00139 // follow position changes 00140 const QPoint topLevelPos = mBaseWidget->mapTo( window(), QPoint( 0, 0 ) ); 00141 const QPoint parentPos = parentWidget()->mapFrom( window(), topLevelPos ); 00142 move( parentPos ); 00143 00144 // follow size changes 00145 // TODO: hide/scale icon if we don't have enough space 00146 resize( mBaseWidget->size() ); 00147 } 00148 00149 bool ErrorOverlay::eventFilter(QObject * object, QEvent * event) 00150 { 00151 if ( object == mBaseWidget && mOverlayActive && 00152 ( event->type() == QEvent::Move || event->type() == QEvent::Resize || 00153 event->type() == QEvent::Show || event->type() == QEvent::Hide || 00154 event->type() == QEvent::ParentChange ) ) { 00155 reposition(); 00156 } 00157 return QWidget::eventFilter( object, event ); 00158 } 00159 00160 void ErrorOverlay::startClicked() 00161 { 00162 ServerManager::start(); 00163 } 00164 00165 void ErrorOverlay::selfTestClicked() 00166 { 00167 SelfTestDialog dlg; 00168 dlg.exec(); 00169 } 00170 00171 void ErrorOverlay::serverStateChanged( ServerManager::State state ) 00172 { 00173 if ( !mBaseWidget ) 00174 return; 00175 00176 if ( state == ServerManager::Running && mOverlayActive ) { 00177 mOverlayActive = false; 00178 hide(); 00179 mBaseWidget->setEnabled( mPreviousState ); 00180 } else if ( !mOverlayActive ) { 00181 mOverlayActive = true; 00182 if ( mBaseWidget->isVisible() ) 00183 show(); 00184 mPreviousState = mBaseWidget->isEnabled(); 00185 mBaseWidget->setEnabled( false ); 00186 reposition(); 00187 } 00188 00189 if ( mOverlayActive ) { 00190 switch ( state ) { 00191 case ServerManager::NotRunning: 00192 ui->stackWidget->setCurrentWidget( ui->notRunningPage ); 00193 break; 00194 case ServerManager::Broken: 00195 ui->stackWidget->setCurrentWidget( ui->brokenPage ); 00196 break; 00197 case ServerManager::Starting: 00198 ui->progressPage->setToolTip( i18n( "Personal information management service is starting..." ) ); 00199 ui->progressDescription->setText( i18n( "Personal information management service is starting..." ) ); 00200 ui->stackWidget->setCurrentWidget( ui->progressPage ); 00201 break; 00202 case ServerManager::Stopping: 00203 ui->progressPage->setToolTip( i18n( "Personal information management service is shutting down..." ) ); 00204 ui->progressDescription->setText( i18n( "Personal information management service is shutting down..." ) ); 00205 ui->stackWidget->setCurrentWidget( ui->progressPage ); 00206 break; 00207 case ServerManager::Running: 00208 break; 00209 } 00210 } 00211 } 00212 00213 //@endcond 00214 00215 #include "erroroverlay_p.moc"