Akonadi

controlgui.cpp
1/*
2 SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "controlgui.h"
8#include "akonadiwidgets_debug.h"
9#include "erroroverlay_p.h"
10#include "selftestdialog.h"
11#include "servermanager.h"
12#include "ui_controlprogressindicator.h"
13
14#include <KLocalizedString>
15
16#include <QCoreApplication>
17#include <QEventLoop>
18#include <QFrame>
19#include <QPointer>
20#include <QTimer>
21
22using namespace Akonadi;
23using namespace std::chrono_literals;
24namespace Akonadi
25{
26namespace Internal
27{
28class ControlProgressIndicator : public QFrame
29{
31public:
32 explicit ControlProgressIndicator(QWidget *parent = nullptr)
33 : QFrame(parent)
34 {
36 resize(400, 100);
38 ui.setupUi(this);
39
42 }
43
44 void setMessage(const QString &msg)
45 {
46 ui.statusLabel->setText(msg);
47 }
48
49 Ui::ControlProgressIndicator ui;
50};
51
52class StaticControlGui : public ControlGui
53{
55};
56
57} // namespace Internal
58
59Q_GLOBAL_STATIC(Internal::StaticControlGui, s_instance) // NOLINT(readability-redundant-member-init)
60
61/**
62 * @internal
63 */
64class ControlGuiPrivate
65{
66public:
67 explicit ControlGuiPrivate(ControlGui *parent)
68 : mParent(parent)
69 , mProgressIndicator(nullptr)
70 {
71 }
72
73 ~ControlGuiPrivate()
74 {
75 delete mProgressIndicator;
76 }
77
78 void setupProgressIndicator(const QString &msg, QWidget *parent = nullptr)
79 {
80 if (!mProgressIndicator) {
81 mProgressIndicator = new Internal::ControlProgressIndicator(parent);
82 }
83
84 mProgressIndicator->setMessage(msg);
85 }
86
87 void createErrorOverlays()
88 {
89 for (QWidget *widget : std::as_const(mPendingOverlays)) {
90 if (widget) {
91 new ErrorOverlay(widget);
92 }
93 }
94 mPendingOverlays.clear();
95 }
96
97 void cleanup()
98 {
99 // delete s_instance;
100 }
101
102 bool exec();
103 void serverStateChanged(ServerManager::State state);
104
105 QPointer<ControlGui> mParent;
106 QEventLoop *mEventLoop = nullptr;
108 QList<QPointer<QWidget>> mPendingOverlays;
109 bool mSuccess = false;
110
111 bool mStarting = false;
112 bool mStopping = false;
113};
114
115bool ControlGuiPrivate::exec()
116{
117 if (mProgressIndicator) {
118 mProgressIndicator->show();
119 }
120 qCDebug(AKONADIWIDGETS_LOG) << "Starting/Stopping Akonadi (using an event loop).";
121 mEventLoop = new QEventLoop(mParent);
122 mEventLoop->exec();
123 mEventLoop->deleteLater();
124 mEventLoop = nullptr;
125
126 if (!mSuccess) {
127 qCWarning(AKONADIWIDGETS_LOG) << "Could not start/stop Akonadi!";
128 if (mProgressIndicator && mStarting) {
129 QPointer<SelfTestDialog> dlg = new SelfTestDialog(mProgressIndicator->parentWidget());
130 dlg->exec();
131 delete dlg;
132 if (!mParent) {
133 return false;
134 }
135 }
136 }
137
138 delete mProgressIndicator;
139 mProgressIndicator = nullptr;
140 mStarting = false;
141 mStopping = false;
142
143 const bool rv = mSuccess;
144 mSuccess = false;
145 return rv;
146}
147
148void ControlGuiPrivate::serverStateChanged(ServerManager::State state)
149{
150 qCDebug(AKONADIWIDGETS_LOG) << "Server state changed to" << state;
151 if (mEventLoop && mEventLoop->isRunning()) {
152 // ignore transient states going into the right direction
153 if ((mStarting && (state == ServerManager::Starting || state == ServerManager::Upgrading)) || (mStopping && state == ServerManager::Stopping)) {
154 return;
155 }
156 mEventLoop->quit();
157 mSuccess = (mStarting && state == ServerManager::Running) || (mStopping && state == ServerManager::NotRunning);
158 }
159}
160
162 : d(new ControlGuiPrivate(this))
163{
165 d->serverStateChanged(state);
166 });
167 // mProgressIndicator is a widget, so it better be deleted before the QApplication is deleted
168 // Otherwise we get a crash in QCursor code with Qt-4.5
171 d->cleanup();
172 });
173 }
174}
175
176ControlGui::~ControlGui() = default;
177
179{
181 qCDebug(AKONADIWIDGETS_LOG) << "Server is currently being stopped, won't try to start it now";
182 return false;
183 }
184 if (ServerManager::isRunning() || s_instance->d->mEventLoop) {
185 qCDebug(AKONADIWIDGETS_LOG) << "Server is already running";
186 return true;
187 }
188 s_instance->d->mStarting = true;
189 if (!ServerManager::start()) {
190 qCDebug(AKONADIWIDGETS_LOG) << "ServerManager::start failed -> return false";
191 return false;
192 }
193 return s_instance->d->exec();
194}
195
197{
199 return false;
200 }
201 if (!ServerManager::isRunning() || s_instance->d->mEventLoop) {
202 return true;
203 }
204 s_instance->d->mStopping = true;
205 if (!ServerManager::stop()) {
206 return false;
207 }
208 return s_instance->d->exec();
209}
210
212{
214 if (!stop()) {
215 return false;
216 }
217 }
218 return start();
219}
220
222{
223 s_instance->d->setupProgressIndicator(i18n("Starting Akonadi server..."), parent);
224 return start();
225}
226
228{
229 s_instance->d->setupProgressIndicator(i18n("Stopping Akonadi server..."), parent);
230 return stop();
231}
232
234{
236 if (!stop(parent)) {
237 return false;
238 }
239 }
240 return start(parent);
241}
242
244{
245 s_instance->d->mPendingOverlays.append(widget);
246 // delay the overlay creation since we rely on widget being reparented
247 // correctly already
248 QTimer::singleShot(0s, s_instance, []() {
249 s_instance->d->createErrorOverlays();
250 });
251}
252
253} // namespace Akonadi
254
255#include "controlgui.moc"
256
257#include "moc_controlgui.cpp"
Provides methods to ControlGui the Akonadi server process.
Definition controlgui.h:54
ControlGui()
Creates the ControlGui object.
static bool start()
Starts the Akonadi server synchronously if it is not already running.
static bool stop()
Stops the Akonadi server synchronously if it is currently running.
~ControlGui() override
Destroys the ControlGui object.
static void widgetNeedsAkonadi(QWidget *widget)
Disable the given widget when Akonadi is not operational and show an error overlay (given enough spac...
static bool restart()
Restarts the Akonadi server synchronously.
A dialog that checks the current status of the Akonadi system.
static State state()
Returns the state of the server.
static bool isRunning()
Checks if the server is available currently.
static bool start()
Starts the server.
static bool stop()
Stops the server.
State
Enum for the various states the server can be in.
@ Running
Server is running and operational.
@ Starting
Server was started but is not yet running.
@ Upgrading
Server is performing a database upgrade as part of a new startup.
@ NotRunning
Server is not running, could be no one started it yet or it failed to start.
@ Stopping
Server is shutting down.
void stateChanged(Akonadi::ServerManager::State state)
Emitted whenever the server state changes.
static ServerManager * self()
Returns the singleton instance of this class, for connecting to its signals.
QString i18n(const char *text, const TYPE &arg...)
Helper integration between Akonadi and Qt.
QCoreApplication * instance()
int exec(ProcessEventsFlags flags)
bool isRunning() const const
void quit()
void setFrameShadow(Shadow)
void setFrameShape(Shape)
void clear()
Q_OBJECTQ_OBJECT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
QObject * parent() const const
ApplicationModal
FramelessWindowHint
void resize(const QSize &)
void setWindowFlags(Qt::WindowFlags type)
void setWindowModality(Qt::WindowModality windowModality)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:08:30 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.