kde-playground/kdepimlibs/akonadi/erroroverlay.cpp

259 lines
8.1 KiB
C++
Raw Permalink Normal View History

/*
Copyright (c) 2008 Volker Krause <vkrause@kde.org>
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 "erroroverlay_p.h"
#include "ui_erroroverlay.h"
#include "selftestdialog_p.h"
#include <KDebug>
#include <KIcon>
#include <KLocalizedString>
#include <QtCore/QEvent>
#include <QPalette>
using namespace Akonadi;
//@cond PRIVATE
class ErrorOverlayStatic
{
public:
QVector<QPair<QPointer<QWidget>, QPointer<QWidget> > > baseWidgets;
};
K_GLOBAL_STATIC(ErrorOverlayStatic, sInstanceOverlay)
static bool isParentOf(QObject *o1, QObject *o2)
{
if (!o1 || !o2) {
return false;
}
if (o1 == o2) {
return true;
}
return isParentOf(o1, o2->parent());
}
ErrorOverlay::ErrorOverlay(QWidget *baseWidget, QWidget *parent)
: QWidget(parent ? parent : baseWidget->window())
, mBaseWidget(baseWidget)
, mOverlayActive(false)
, mBaseWidgetIsParent(false)
, ui(new Ui::ErrorOverlay)
{
Q_ASSERT(baseWidget);
mBaseWidgetIsParent = isParentOf(mBaseWidget, this);
// check existing overlays to detect cascading
for (QVector<QPair< QPointer<QWidget>, QPointer<QWidget> > >::Iterator it = sInstanceOverlay->baseWidgets.begin();
it != sInstanceOverlay->baseWidgets.end();) {
if ((*it).first == 0 || (*it).second == 0) {
// garbage collection
it = sInstanceOverlay->baseWidgets.erase(it);
continue;
}
if (isParentOf((*it).first, baseWidget)) {
// parent already has an overlay, kill ourselves
mBaseWidget = 0;
hide();
deleteLater();
return;
}
if (isParentOf(baseWidget, (*it).first)) {
// child already has overlay, kill that one
delete(*it).second;
it = sInstanceOverlay->baseWidgets.erase(it);
continue;
}
++it;
}
sInstanceOverlay->baseWidgets.append(qMakePair(mBaseWidget, QPointer<QWidget>(this)));
connect(baseWidget, SIGNAL(destroyed()), SLOT(deleteLater()));
mPreviousState = mBaseWidget->isEnabled();
ui->setupUi(this);
ui->notRunningIcon->setPixmap(KIcon(QLatin1String("akonadi")).pixmap(64));
ui->brokenIcon->setPixmap(KIcon(QString::fromLatin1("dialog-error")).pixmap(64));
ui->progressIcon->setPixmap(KIcon(QLatin1String("akonadi")).pixmap(32));
ui->quitButton->setText(KStandardGuiItem::quit().text());
ui->detailsQuitButton->setText(KStandardGuiItem::quit().text());
#ifndef KDEPIM_MOBILE_UI
ui->quitButton->hide();
ui->detailsQuitButton->hide();
#endif
connect(ui->startButton, SIGNAL(clicked()), SLOT(startClicked()));
connect(ui->quitButton, SIGNAL(clicked()), SLOT(quitClicked()));
connect(ui->detailsQuitButton, SIGNAL(clicked()), SLOT(quitClicked()));
connect(ui->selfTestButton, SIGNAL(clicked()), SLOT(selfTestClicked()));
const ServerManager::State state = ServerManager::state();
mOverlayActive = (state == ServerManager::Running);
serverStateChanged(state);
connect(ServerManager::self(), SIGNAL(stateChanged(Akonadi::ServerManager::State)),
SLOT(serverStateChanged(Akonadi::ServerManager::State)));
QPalette p = palette();
p.setColor(backgroundRole(), QColor(0, 0, 0, 128));
p.setColor(foregroundRole(), Qt::white);
setPalette(p);
setAutoFillBackground(true);
mBaseWidget->installEventFilter(this);
reposition();
}
ErrorOverlay::~ ErrorOverlay()
{
if (mBaseWidget && !mBaseWidgetIsParent) {
mBaseWidget->setEnabled(mPreviousState);
}
}
void ErrorOverlay::reposition()
{
if (!mBaseWidget) {
return;
}
// reparent to the current top level widget of the base widget if needed
// needed eg. in dock widgets
if (parentWidget() != mBaseWidget->window()) {
setParent(mBaseWidget->window());
}
// follow base widget visibility
// needed eg. in tab widgets
if (!mBaseWidget->isVisible()) {
hide();
return;
}
if (mOverlayActive) {
show();
}
// follow position changes
const QPoint topLevelPos = mBaseWidget->mapTo(window(), QPoint(0, 0));
const QPoint parentPos = parentWidget()->mapFrom(window(), topLevelPos);
move(parentPos);
// follow size changes
// TODO: hide/scale icon if we don't have enough space
resize(mBaseWidget->size());
}
bool ErrorOverlay::eventFilter(QObject *object, QEvent *event)
{
if (object == mBaseWidget && mOverlayActive &&
(event->type() == QEvent::Move || event->type() == QEvent::Resize ||
event->type() == QEvent::Show || event->type() == QEvent::Hide ||
event->type() == QEvent::ParentChange)) {
reposition();
}
return QWidget::eventFilter(object, event);
}
void ErrorOverlay::startClicked()
{
const ServerManager::State state = ServerManager::state();
if (state == ServerManager::Running) {
serverStateChanged(state);
} else {
ServerManager::start();
}
}
void ErrorOverlay::quitClicked()
{
qApp->quit();
}
void ErrorOverlay::selfTestClicked()
{
SelfTestDialog dlg;
dlg.exec();
}
void ErrorOverlay::serverStateChanged(ServerManager::State state)
{
if (!mBaseWidget) {
return;
}
if (state == ServerManager::Running && mOverlayActive) {
mOverlayActive = false;
hide();
if (!mBaseWidgetIsParent) {
mBaseWidget->setEnabled(mPreviousState);
}
} else if (!mOverlayActive) {
mOverlayActive = true;
if (mBaseWidget->isVisible()) {
show();
}
if (!mBaseWidgetIsParent) {
mPreviousState = mBaseWidget->isEnabled();
mBaseWidget->setEnabled(false);
}
reposition();
}
if (mOverlayActive) {
switch (state) {
case ServerManager::NotRunning:
ui->stackWidget->setCurrentWidget(ui->notRunningPage);
break;
case ServerManager::Broken:
ui->stackWidget->setCurrentWidget(ui->brokenPage);
break;
case ServerManager::Starting:
ui->progressPage->setToolTip(i18n("Personal information management service is starting..."));
ui->progressDescription->setText(i18n("Personal information management service is starting..."));
ui->stackWidget->setCurrentWidget(ui->progressPage);
break;
case ServerManager::Stopping:
ui->progressPage->setToolTip(i18n("Personal information management service is shutting down..."));
ui->progressDescription->setText(i18n("Personal information management service is shutting down..."));
ui->stackWidget->setCurrentWidget(ui->progressPage);
break;
case ServerManager::Upgrading:
ui->progressPage->setToolTip(i18n("Personal information management service is performing a database upgrade."));
ui->progressDescription->setText(i18n("Personal information management service is performing a database upgrade.\n"
"This happens after a software update and is necessary to optimize performance.\n"
"Depending on the amount of personal information, this might take a few minutes."));
ui->stackWidget->setCurrentWidget(ui->progressPage);
break;
case ServerManager::Running:
break;
}
}
}
//@endcond
#include "moc_erroroverlay_p.cpp"