/* Copyright (c) 2007 Volker Krause This library 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 library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "control.h" #include "servermanager.h" #include "ui_controlprogressindicator.h" #include "selftestdialog_p.h" #include "erroroverlay_p.h" #include #include #include #include #include #include #include #include using namespace Akonadi; namespace Akonadi { namespace Internal { class ControlProgressIndicator : public QFrame { public: ControlProgressIndicator(QWidget *parent = 0) : QFrame(parent) { setWindowModality(Qt::ApplicationModal); resize(400, 100); setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); ui.setupUi(this); setFrameShadow(QFrame::Plain); setFrameShape(QFrame::Box); } void setMessage(const QString &msg) { ui.statusLabel->setText(msg); } Ui::ControlProgressIndicator ui; }; class StaticControl : public Control { public: StaticControl() : Control() { } }; } K_GLOBAL_STATIC(Internal::StaticControl, s_instance) /** * @internal */ class Control::Private { public: Private(Control *parent) : mParent(parent) , mEventLoop(0) , mProgressIndicator(0) , mSuccess(false) , mStarting(false) , mStopping(false) { } ~Private() { delete mProgressIndicator; } void setupProgressIndicator(const QString &msg, QWidget *parent = 0) { if (!mProgressIndicator) { mProgressIndicator = new Internal::ControlProgressIndicator(parent); } mProgressIndicator->setMessage(msg); } void createErrorOverlays() { foreach (QWidget *widget, mPendingOverlays) { if (widget) { new ErrorOverlay(widget); } } mPendingOverlays.clear(); } void cleanup() { s_instance.destroy(); } bool exec(); void serverStateChanged(ServerManager::State state); QPointer mParent; QEventLoop *mEventLoop; QPointer mProgressIndicator; QList > mPendingOverlays; bool mSuccess; bool mStarting; bool mStopping; }; bool Control::Private::exec() { if (mProgressIndicator) { mProgressIndicator->show(); } kDebug() << "Starting/Stopping Akonadi (using an event loop)."; mEventLoop = new QEventLoop(mParent); mEventLoop->exec(); mEventLoop->deleteLater(); mEventLoop = 0; if (!mSuccess) { kWarning() << "Could not start/stop Akonadi!"; if (mProgressIndicator && mStarting) { QPointer dlg = new SelfTestDialog(mProgressIndicator->parentWidget()); dlg->exec(); delete dlg; if (!mParent) { return false; } } } delete mProgressIndicator; mProgressIndicator = 0; mStarting = false; mStopping = false; const bool rv = mSuccess; mSuccess = false; return rv; } void Control::Private::serverStateChanged(ServerManager::State state) { kDebug() << state; if (mEventLoop && mEventLoop->isRunning()) { // ignore transient states going into the right direction if ((mStarting && (state == ServerManager::Starting || state == ServerManager::Upgrading)) || (mStopping && state == ServerManager::Stopping)) return; mEventLoop->quit(); mSuccess = (mStarting && state == ServerManager::Running) || (mStopping && state == ServerManager::NotRunning); } } Control::Control() : d(new Private(this)) { connect(ServerManager::self(), SIGNAL(stateChanged(Akonadi::ServerManager::State)), SLOT(serverStateChanged(Akonadi::ServerManager::State))); // mProgressIndicator is a widget, so it better be deleted before the QApplication is deleted // Otherwise we get a crash in QCursor code with Qt-4.5 if (QCoreApplication::instance()) { connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(cleanup())); } } Control::~Control() { delete d; } bool Control::start() { if (ServerManager::state() == ServerManager::Stopping) { kDebug() << "Server is currently being stopped, wont try to start it now"; return false; } if (ServerManager::isRunning() || s_instance->d->mEventLoop) { kDebug() << "Server is already running"; return true; } s_instance->d->mStarting = true; if (!ServerManager::start()) { kDebug() << "ServerManager::start failed -> return false"; return false; } return s_instance->d->exec(); } bool Control::stop() { if (ServerManager::state() == ServerManager::Starting) { return false; } if (!ServerManager::isRunning() || s_instance->d->mEventLoop) { return true; } s_instance->d->mStopping = true; if (!ServerManager::stop()) { return false; } return s_instance->d->exec(); } bool Control::restart() { if (ServerManager::isRunning()) { if (!stop()) { return false; } } return start(); } bool Control::start(QWidget *parent) { s_instance->d->setupProgressIndicator(i18n("Starting Akonadi server..."), parent); return start(); } bool Control::stop(QWidget *parent) { s_instance->d->setupProgressIndicator(i18n("Stopping Akonadi server..."), parent); return stop(); } bool Control::restart(QWidget *parent) { if (ServerManager::isRunning()) { if (!stop(parent)) { return false; } } return start(parent); } void Control::widgetNeedsAkonadi(QWidget *widget) { s_instance->d->mPendingOverlays.append(widget); // delay the overlay creation since we rely on widget being reparented // correctly already QTimer::singleShot(0, s_instance, SLOT(createErrorOverlays())); } } #include "moc_control.cpp"