Akonadi

controlgui.cpp
1 /*
2  Copyright (c) 2007 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 "controlgui.h"
21 #include "servermanager.h"
22 #include "ui_controlprogressindicator.h"
23 #include "selftestdialog.h"
24 #include "erroroverlay_p.h"
25 #include "akonadiwidgets_debug.h"
26 
27 
28 #include <KLocalizedString>
29 
30 #include <QEventLoop>
31 #include <QCoreApplication>
32 #include <QTimer>
33 #include <QPointer>
34 #include <QFrame>
35 
36 using namespace Akonadi;
37 
38 namespace Akonadi
39 {
40 namespace Internal
41 {
42 
43 class ControlProgressIndicator : public QFrame
44 {
45  Q_OBJECT
46 public:
47  explicit ControlProgressIndicator(QWidget *parent = nullptr)
48  : QFrame(parent)
49  {
51  resize(400, 100);
53  ui.setupUi(this);
54 
57  }
58 
59  void setMessage(const QString &msg)
60  {
61  ui.statusLabel->setText(msg);
62  }
63 
64  Ui::ControlProgressIndicator ui;
65 };
66 
67 class StaticControlGui : public ControlGui
68 {
69  Q_OBJECT
70 };
71 
72 } // namespace Internal
73 
74 Q_GLOBAL_STATIC(Internal::StaticControlGui, s_instance) // NOLINT(readability-redundant-member-init)
75 
76 
79 class Q_DECL_HIDDEN ControlGui::Private
80 {
81 public:
82  explicit Private(ControlGui *parent)
83  : mParent(parent)
84  , mEventLoop(nullptr)
85  , mProgressIndicator(nullptr)
86  , mSuccess(false)
87  , mStarting(false)
88  , mStopping(false)
89  {
90  }
91 
92  ~Private()
93  {
94  delete mProgressIndicator;
95  }
96 
97  void setupProgressIndicator(const QString &msg, QWidget *parent = nullptr)
98  {
99  if (!mProgressIndicator) {
100  mProgressIndicator = new Internal::ControlProgressIndicator(parent);
101  }
102 
103  mProgressIndicator->setMessage(msg);
104  }
105 
106  void createErrorOverlays()
107  {
108  for (QWidget *widget : qAsConst(mPendingOverlays)) {
109  if (widget) {
110  new ErrorOverlay(widget);
111  }
112  }
113  mPendingOverlays.clear();
114  }
115 
116  void cleanup()
117  {
118  //delete s_instance;
119  }
120 
121  bool exec();
122  void serverStateChanged(ServerManager::State state);
123 
124  QPointer<ControlGui> mParent;
125  QEventLoop *mEventLoop = nullptr;
127  QList<QPointer<QWidget> > mPendingOverlays;
128  bool mSuccess;
129 
130  bool mStarting;
131  bool mStopping;
132 };
133 
134 bool ControlGui::Private::exec()
135 {
136  if (mProgressIndicator) {
137  mProgressIndicator->show();
138  }
139  qCDebug(AKONADIWIDGETS_LOG) << "Starting/Stopping Akonadi (using an event loop).";
140  mEventLoop = new QEventLoop(mParent);
141  mEventLoop->exec();
142  mEventLoop->deleteLater();
143  mEventLoop = nullptr;
144 
145  if (!mSuccess) {
146  qCWarning(AKONADIWIDGETS_LOG) << "Could not start/stop Akonadi!";
147  if (mProgressIndicator && mStarting) {
148  QPointer<SelfTestDialog> dlg = new SelfTestDialog(mProgressIndicator->parentWidget());
149  dlg->exec();
150  delete dlg;
151  if (!mParent) {
152  return false;
153  }
154  }
155  }
156 
157  delete mProgressIndicator;
158  mProgressIndicator = nullptr;
159  mStarting = false;
160  mStopping = false;
161 
162  const bool rv = mSuccess;
163  mSuccess = false;
164  return rv;
165 }
166 
167 void ControlGui::Private::serverStateChanged(ServerManager::State state)
168 {
169  qCDebug(AKONADIWIDGETS_LOG) << "Server state changed to" << state;
170  if (mEventLoop && mEventLoop->isRunning()) {
171  // ignore transient states going into the right direction
172  if ((mStarting && (state == ServerManager::Starting || state == ServerManager::Upgrading)) ||
173  (mStopping && state == ServerManager::Stopping)) {
174  return;
175  }
176  mEventLoop->quit();
177  mSuccess = (mStarting && state == ServerManager::Running) || (mStopping && state == ServerManager::NotRunning);
178  }
179 }
180 
182  : d(new Private(this))
183 {
185  this, [this](Akonadi::ServerManager::State state) { d->serverStateChanged(state); });
186  // mProgressIndicator is a widget, so it better be deleted before the QApplication is deleted
187  // Otherwise we get a crash in QCursor code with Qt-4.5
189  connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, [this]() {d->cleanup();});
190  }
191 }
192 
194 {
195  delete d;
196 }
197 
199 {
201  qCDebug(AKONADIWIDGETS_LOG) << "Server is currently being stopped, wont try to start it now";
202  return false;
203  }
204  if (ServerManager::isRunning() || s_instance->d->mEventLoop) {
205  qCDebug(AKONADIWIDGETS_LOG) << "Server is already running";
206  return true;
207  }
208  s_instance->d->mStarting = true;
209  if (!ServerManager::start()) {
210  qCDebug(AKONADIWIDGETS_LOG) << "ServerManager::start failed -> return false";
211  return false;
212  }
213  return s_instance->d->exec();
214 }
215 
217 {
219  return false;
220  }
221  if (!ServerManager::isRunning() || s_instance->d->mEventLoop) {
222  return true;
223  }
224  s_instance->d->mStopping = true;
225  if (!ServerManager::stop()) {
226  return false;
227  }
228  return s_instance->d->exec();
229 }
230 
232 {
233  if (ServerManager::isRunning()) {
234  if (!stop()) {
235  return false;
236  }
237  }
238  return start();
239 }
240 
242 {
243  s_instance->d->setupProgressIndicator(i18n("Starting Akonadi server..."), parent);
244  return start();
245 }
246 
248 {
249  s_instance->d->setupProgressIndicator(i18n("Stopping Akonadi server..."), parent);
250  return stop();
251 }
252 
254 {
255  if (ServerManager::isRunning()) {
256  if (!stop(parent)) {
257  return false;
258  }
259  }
260  return start(parent);
261 }
262 
264 {
265  s_instance->d->mPendingOverlays.append(widget);
266  // delay the overlay creation since we rely on widget being reparented
267  // correctly already
268  QTimer::singleShot(0, s_instance, []() { s_instance->d->createErrorOverlays(); });
269 }
270 
271 } // namespace Akonadi
272 
273 #include "controlgui.moc"
void resize(int w, int h)
static bool start()
Starts the Akonadi server synchronously if it is not already running.
Definition: controlgui.cpp:198
void setWindowModality(Qt::WindowModality windowModality)
void setFrameShape(QFrame::Shape)
ControlGui()
Creates the ControlGui object.
Definition: controlgui.cpp:181
static ServerManager * self()
Returns the singleton instance of this class, for connecting to its signals.
static void widgetNeedsAkonadi(QWidget *widget)
Disable the given widget when Akonadi is not operational and show an error overlay (given enough spac...
Definition: controlgui.cpp:263
Server is shutting down.
Definition: servermanager.h:55
Q_OBJECTQ_OBJECT
static State state()
Returns the state of the server.
QCoreApplication * instance()
Server is performing a database upgrade as part of a new startup.
Definition: servermanager.h:57
Provides methods to ControlGui the Akonadi server process.
Definition: controlgui.h:64
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 setFrameShadow(QFrame::Shadow)
QString i18n(const char *text, const TYPE &arg...)
void setWindowFlags(Qt::WindowFlags type)
Server is running and operational.
Definition: servermanager.h:54
~ControlGui()
Destroys the ControlGui object.
Definition: controlgui.cpp:193
Helper integration between Akonadi and Qt.
State
Enum for the various states the server can be in.
Definition: servermanager.h:51
A dialog that checks the current status of the Akonadi system.
void stateChanged(Akonadi::ServerManager::State state)
Emitted whenever the server state changes.
static bool restart()
Restarts the Akonadi server synchronously.
Definition: controlgui.cpp:231
static bool stop()
Stops the server.
ApplicationModal
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
static bool isRunning()
Checks if the server is available currently.
FramelessWindowHint
static bool stop()
Stops the Akonadi server synchronously if it is currently running.
Definition: controlgui.cpp:216
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Jul 1 2020 23:14:20 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.