Akonadi

erroroverlay.cpp
1 /*
2  Copyright (c) 2008 Volker Krause <[email protected]>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "erroroverlay_p.h"
21 #include "ui_erroroverlay.h"
22 #if 0
23 #include "selftestdialog_p.h"
24 #endif
25 
26 #include <QIcon>
27 #include <KLocalizedString>
28 #include <KStandardGuiItem>
29 
30 #include <QEvent>
31 #include <QPalette>
32 
33 using namespace Akonadi;
34 
35 //@cond PRIVATE
36 
37 class ErrorOverlayStatic
38 {
39 public:
41 };
42 
43 Q_GLOBAL_STATIC(ErrorOverlayStatic, sInstanceOverlay)
44 
45 // return true if o1 is a parent of o2
46 static bool isParentOf(QWidget *o1, QWidget *o2)
47 {
48  if (!o1 || !o2) {
49  return false;
50  }
51  if (o1 == o2) {
52  return true;
53  }
54  if (o2->isWindow()) {
55  return false;
56  }
57  return isParentOf(o1, o2->parentWidget());
58 }
59 
60 ErrorOverlay::ErrorOverlay(QWidget *baseWidget, QWidget *parent)
61  : QWidget(parent ? parent : baseWidget->window())
62  , mBaseWidget(baseWidget)
63  , mOverlayActive(false)
64  , mBaseWidgetIsParent(false)
65  , ui(new Ui::ErrorOverlay)
66 {
67  Q_ASSERT(baseWidget);
68 
69  mBaseWidgetIsParent = isParentOf(mBaseWidget, this);
70 
71  // check existing overlays to detect cascading
72  for (QVector<QPair< QPointer<QWidget>, QPointer<QWidget> > >::Iterator it = sInstanceOverlay->baseWidgets.begin();
73  it != sInstanceOverlay->baseWidgets.end();) {
74  if ((*it).first == nullptr || (*it).second == nullptr) {
75  // garbage collection
76  it = sInstanceOverlay->baseWidgets.erase(it);
77  continue;
78  }
79  if (isParentOf((*it).first, baseWidget)) {
80  // parent already has an overlay, kill ourselves
81  mBaseWidget = nullptr;
82  hide();
83  deleteLater();
84  return;
85  }
86  if (isParentOf(baseWidget, (*it).first)) {
87  // child already has overlay, kill that one
88  delete(*it).second;
89  it = sInstanceOverlay->baseWidgets.erase(it);
90  continue;
91  }
92  ++it;
93  }
94  sInstanceOverlay->baseWidgets.append(qMakePair(mBaseWidget, QPointer<QWidget>(this)));
95 
96  connect(baseWidget, &QObject::destroyed, this, &QObject::deleteLater);
97  mPreviousState = !mBaseWidget->testAttribute(Qt::WA_ForceDisabled);
98 
99  ui->setupUi(this);
100  ui->notRunningIcon->setPixmap(QIcon::fromTheme(QStringLiteral("akonadi")).pixmap(64));
101  ui->brokenIcon->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-error")).pixmap(64));
102  ui->progressIcon->setPixmap(QIcon::fromTheme(QStringLiteral("akonadi")).pixmap(32));
103  ui->quitButton->setText(KStandardGuiItem::quit().text());
104  ui->detailsQuitButton->setText(KStandardGuiItem::quit().text());
105 
106  ui->quitButton->hide();
107  ui->detailsQuitButton->hide();
108 
109  connect(ui->startButton, &QAbstractButton::clicked, this, &ErrorOverlay::startClicked);
110  connect(ui->quitButton, &QAbstractButton::clicked, this, &ErrorOverlay::quitClicked);
111  connect(ui->detailsQuitButton, &QAbstractButton::clicked, this, &ErrorOverlay::quitClicked);
112  connect(ui->selfTestButton, &QAbstractButton::clicked, this, &ErrorOverlay::selfTestClicked);
113 
115  mOverlayActive = (state == ServerManager::Running);
116  serverStateChanged(state);
117 
118  connect(ServerManager::self(), &ServerManager::stateChanged, this, &ErrorOverlay::serverStateChanged);
119 
120  QPalette p = palette();
121  p.setColor(backgroundRole(), QColor(0, 0, 0, 128));
122  p.setColor(foregroundRole(), Qt::white);
123  setPalette(p);
124  setAutoFillBackground(true);
125 
126  mBaseWidget->installEventFilter(this);
127 
128  reposition();
129 }
130 
131 ErrorOverlay::~ErrorOverlay()
132 {
133  if (mBaseWidget && !mBaseWidgetIsParent) {
134  mBaseWidget->setEnabled(mPreviousState);
135  }
136 }
137 
138 void ErrorOverlay::reposition()
139 {
140  if (!mBaseWidget) {
141  return;
142  }
143 
144  // reparent to the current top level widget of the base widget if needed
145  // needed eg. in dock widgets
146  if (parentWidget() != mBaseWidget->window()) {
147  setParent(mBaseWidget->window());
148  }
149 
150  // follow base widget visibility
151  // needed eg. in tab widgets
152  if (!mBaseWidget->isVisible()) {
153  hide();
154  return;
155  }
156  if (mOverlayActive) {
157  show();
158  }
159 
160  // follow position changes
161  const QPoint topLevelPos = mBaseWidget->mapTo(window(), QPoint(0, 0));
162  const QPoint parentPos = parentWidget()->mapFrom(window(), topLevelPos);
163  move(parentPos);
164 
165  // follow size changes
166  // TODO: hide/scale icon if we don't have enough space
167  resize(mBaseWidget->size());
168 }
169 
170 bool ErrorOverlay::eventFilter(QObject *object, QEvent *event)
171 {
172  if (object == mBaseWidget && mOverlayActive &&
173  (event->type() == QEvent::Move || event->type() == QEvent::Resize ||
174  event->type() == QEvent::Show || event->type() == QEvent::Hide ||
175  event->type() == QEvent::ParentChange)) {
176  reposition();
177  }
178  return QWidget::eventFilter(object, event);
179 }
180 
181 void ErrorOverlay::startClicked()
182 {
184  if (state == ServerManager::Running) {
185  serverStateChanged(state);
186  } else {
188  }
189 }
190 
191 void ErrorOverlay::quitClicked()
192 {
193  qApp->quit();
194 }
195 
196 void ErrorOverlay::selfTestClicked()
197 {
198 #if 0
199  SelfTestDialog dlg;
200  dlg.exec();
201 #endif
202 }
203 
204 void ErrorOverlay::serverStateChanged(ServerManager::State state)
205 {
206  if (!mBaseWidget) {
207  return;
208  }
209 
210  if (state == ServerManager::Running) {
211  if (mOverlayActive) {
212  mOverlayActive = false;
213  hide();
214  if (!mBaseWidgetIsParent) {
215  mBaseWidget->setEnabled(mPreviousState);
216  }
217  }
218  } else if (!mOverlayActive) {
219  mOverlayActive = true;
220  if (mBaseWidget->isVisible()) {
221  show();
222  }
223 
224  if (!mBaseWidgetIsParent) {
225  mPreviousState = !mBaseWidget->testAttribute(Qt::WA_ForceDisabled);
226  mBaseWidget->setEnabled(false);
227  }
228 
229  reposition();
230  }
231 
232  if (mOverlayActive) {
233  switch (state) {
235  ui->stackWidget->setCurrentWidget(ui->notRunningPage);
236  break;
238  ui->stackWidget->setCurrentWidget(ui->brokenPage);
239  if (!ServerManager::brokenReason().isEmpty()) {
240  ui->brokenDescription->setText(
241  i18nc("%1 is a reason why", "Cannot connect to the Personal information management service.\n\n%1",
243  }
244  break;
246  ui->progressPage->setToolTip(i18n("Personal information management service is starting..."));
247  ui->progressDescription->setText(i18n("Personal information management service is starting..."));
248  ui->stackWidget->setCurrentWidget(ui->progressPage);
249  break;
251  ui->progressPage->setToolTip(i18n("Personal information management service is shutting down..."));
252  ui->progressDescription->setText(i18n("Personal information management service is shutting down..."));
253  ui->stackWidget->setCurrentWidget(ui->progressPage);
254  break;
256  ui->progressPage->setToolTip(i18n("Personal information management service is performing a database upgrade."));
257  ui->progressDescription->setText(i18n("Personal information management service is performing a database upgrade.\n"
258  "This happens after a software update and is necessary to optimize performance.\n"
259  "Depending on the amount of personal information, this might take a few minutes."));
260  ui->stackWidget->setCurrentWidget(ui->progressPage);
261  break;
263  break;
264  }
265  }
266 }
267 
268 //@endcond
269 
270 #include "moc_erroroverlay_p.cpp"
void resize(int w, int h)
QEvent::Type type() const const
const QPalette & palette() const const
KJOBWIDGETS_EXPORT QWidget * window(KJob *job)
void setColor(QPalette::ColorGroup group, QPalette::ColorRole role, const QColor &color)
QWidget * window() const const
static QString brokenReason()
Returns the reason why the Server is broken, if known.
KGuiItem quit()
static ServerManager * self()
Returns the singleton instance of this class, for connecting to its signals.
virtual int exec()
void setParent(QWidget *parent)
QPalette::ColorRole foregroundRole() const const
Server is shutting down.
Definition: servermanager.h:55
QString i18nc(const char *context, const char *text, const TYPE &arg...)
static State state()
Returns the state of the server.
QPalette::ColorRole backgroundRole() const const
void clicked(bool checked)
virtual bool eventFilter(QObject *watched, QEvent *event)
Server is performing a database upgrade as part of a new startup.
Definition: servermanager.h:57
void deleteLater()
void hide()
Server is not running, could be no one started it yet or it failed to start.
Definition: servermanager.h:52
static bool start()
Starts the server.
Server was started but is not yet running.
Definition: servermanager.h:53
void move(int x, int y)
QAbstractItemView::State state() const const
QString i18n(const char *text, const TYPE &arg...)
virtual bool event(QEvent *event) override
Server is running and operational.
Definition: servermanager.h:54
Definition: item.h:44
Helper integration between Akonadi and Qt.
QWidget * parentWidget() const const
State
Enum for the various states the server can be in.
Definition: servermanager.h:51
QIcon fromTheme(const QString &name)
A dialog that checks the current status of the Akonadi system.
void stateChanged(Akonadi::ServerManager::State state)
Emitted whenever the server state changes.
void setAutoFillBackground(bool enabled)
void show()
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void destroyed(QObject *obj)
Server is not operational and an error has been detected.
Definition: servermanager.h:56
QPoint mapFrom(const QWidget *parent, const QPoint &pos) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Jun 5 2020 23:08:54 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.