Suppress compiler warnings about unused function parameters
[lxde/liblxqt.git] / lxqtpower / lxqtpowerproviders.cpp
1 /* BEGIN_COMMON_COPYRIGHT_HEADER
2 * (c)LGPL2+
3 *
4 * LXQt - a lightweight, Qt based, desktop toolset
5 * http://razor-qt.org
6 *
7 * Copyright: 2010-2011 Razor team
8 * Authors:
9 * Alexander Sokoloff <sokoloff.a@gmail.com>
10 * Petr Vanek <petr@scribus.info>
11 *
12 * This program or library is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21
22 * You should have received a copy of the GNU Lesser General
23 * Public License along with this library; if not, write to the
24 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301 USA
26 *
27 * END_COMMON_COPYRIGHT_HEADER */
28
29
30 #include "lxqtpowerproviders.h"
31 #include <QDBusInterface>
32 #include <QProcess>
33 #include <QDebug>
34 #include "lxqtnotification.h"
35 #include <signal.h> // for kill()
36
37 #define UPOWER_SERVICE "org.freedesktop.UPower"
38 #define UPOWER_PATH "/org/freedesktop/UPower"
39 #define UPOWER_INTERFACE UPOWER_SERVICE
40
41 #define CONSOLEKIT_SERVICE "org.freedesktop.ConsoleKit"
42 #define CONSOLEKIT_PATH "/org/freedesktop/ConsoleKit/Manager"
43 #define CONSOLEKIT_INTERFACE "org.freedesktop.ConsoleKit.Manager"
44
45 #define SYSTEMD_SERVICE "org.freedesktop.login1"
46 #define SYSTEMD_PATH "/org/freedesktop/login1"
47 #define SYSTEMD_INTERFACE "org.freedesktop.login1.Manager"
48
49 #define LXQT_SERVICE "org.lxqt.session"
50 #define LXQT_PATH "/LXQtSession"
51 #define LXQT_INTERFACE "org.lxqt.session"
52
53 #define PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
54
55 using namespace LXQt;
56
57 /************************************************
58 Helper func
59 ************************************************/
60 void printDBusMsg(const QDBusMessage &msg)
61 {
62 qWarning() << "** Dbus error **************************";
63 qWarning() << "Error name " << msg.errorName();
64 qWarning() << "Error msg " << msg.errorMessage();
65 qWarning() << "****************************************";
66 }
67
68
69 /************************************************
70 Helper func
71 ************************************************/
72 static bool dbusCall(const QString &service,
73 const QString &path,
74 const QString &interface,
75 const QDBusConnection &connection,
76 const QString & method,
77 PowerProvider::DbusErrorCheck errorCheck = PowerProvider::CheckDBUS
78 )
79 {
80 QDBusInterface dbus(service, path, interface, connection);
81 if (!dbus.isValid())
82 {
83 qWarning() << "dbusCall: QDBusInterface is invalid" << service << path << interface << method;
84 if (errorCheck == PowerProvider::CheckDBUS)
85 {
86 Notification::notify(
87 QObject::tr("Power Manager Error"),
88 QObject::tr("QDBusInterface is invalid")+ "\n\n" + service + " " + path + " " + interface + " " + method,
89 "lxqt-logo.png");
90 }
91 return false;
92 }
93
94 QDBusMessage msg = dbus.call(method);
95
96 if (!msg.errorName().isEmpty())
97 {
98 printDBusMsg(msg);
99 if (errorCheck == PowerProvider::CheckDBUS)
100 {
101 Notification::notify(
102 QObject::tr("Power Manager Error (D-BUS call)"),
103 msg.errorName() + "\n\n" + msg.errorMessage(),
104 "lxqt-logo.png");
105 }
106 }
107
108 // If the method no returns value, we believe that it was successful.
109 return msg.arguments().isEmpty() ||
110 msg.arguments().first().isNull() ||
111 msg.arguments().first().toBool();
112 }
113
114 /************************************************
115 Helper func
116
117 Just like dbusCall(), except that systemd
118 returns a string instead of a bool, and it takes
119 an "interactivity boolean" as an argument.
120 ************************************************/
121 static bool dbusCallSystemd(const QString &service,
122 const QString &path,
123 const QString &interface,
124 const QDBusConnection &connection,
125 const QString &method,
126 bool needBoolArg,
127 PowerProvider::DbusErrorCheck errorCheck = PowerProvider::CheckDBUS
128 )
129 {
130 QDBusInterface dbus(service, path, interface, connection);
131 if (!dbus.isValid())
132 {
133 qWarning() << "dbusCall: QDBusInterface is invalid" << service << path << interface << method;
134 if (errorCheck == PowerProvider::CheckDBUS)
135 {
136 Notification::notify(
137 QObject::tr("Power Manager Error"),
138 QObject::tr("QDBusInterface is invalid")+ "\n\n" + service + " " + path + " " + interface + " " + method,
139 "lxqt-logo.png");
140 }
141 return false;
142 }
143
144 QDBusMessage msg = dbus.call(method, needBoolArg ? QVariant(true) : QVariant());
145
146 if (!msg.errorName().isEmpty())
147 {
148 printDBusMsg(msg);
149 if (errorCheck == PowerProvider::CheckDBUS)
150 {
151 Notification::notify(
152 QObject::tr("Power Manager Error (D-BUS call)"),
153 msg.errorName() + "\n\n" + msg.errorMessage(),
154 "lxqt-logo.png");
155 }
156 }
157
158 // If the method no returns value, we believe that it was successful.
159 if (msg.arguments().isEmpty() || msg.arguments().first().isNull())
160 return true;
161
162 QString response = msg.arguments().first().toString();
163 qDebug() << "systemd:" << method << "=" << response;
164 return response == "yes" || response == "challenge";
165 }
166
167
168 /************************************************
169 Helper func
170 ************************************************/
171 bool dbusGetProperty(const QString &service,
172 const QString &path,
173 const QString &interface,
174 const QDBusConnection &connection,
175 const QString & property
176 )
177 {
178 QDBusInterface dbus(service, path, interface, connection);
179 if (!dbus.isValid())
180 {
181 qWarning() << "dbusGetProperty: QDBusInterface is invalid" << service << path << interface << property;
182 // Notification::notify(QObject::tr("LXQt Power Manager"),
183 // "lxqt-logo.png",
184 // QObject::tr("Power Manager Error"),
185 // QObject::tr("QDBusInterface is invalid")+ "\n\n" + service +" " + path +" " + interface +" " + property);
186
187 return false;
188 }
189
190 QDBusMessage msg = dbus.call("Get", dbus.interface(), property);
191
192 if (!msg.errorName().isEmpty())
193 {
194 printDBusMsg(msg);
195 // Notification::notify(QObject::tr("LXQt Power Manager"),
196 // "lxqt-logo.png",
197 // QObject::tr("Power Manager Error (Get Property)"),
198 // msg.errorName() + "\n\n" + msg.errorMessage());
199 }
200
201 return !msg.arguments().isEmpty() &&
202 msg.arguments().first().value<QDBusVariant>().variant().toBool();
203 }
204
205
206
207
208 /************************************************
209 PowerProvider
210 ************************************************/
211 PowerProvider::PowerProvider(QObject *parent):
212 QObject(parent)
213 {
214 }
215
216
217 PowerProvider::~PowerProvider()
218 {
219 }
220
221
222
223 /************************************************
224 UPowerProvider
225 ************************************************/
226 UPowerProvider::UPowerProvider(QObject *parent):
227 PowerProvider(parent)
228 {
229 }
230
231
232 UPowerProvider::~UPowerProvider()
233 {
234 }
235
236
237 bool UPowerProvider::canAction(Power::Action action) const
238 {
239 QString command;
240 QString property;
241 switch (action)
242 {
243 case Power::PowerHibernate:
244 property = "CanHibernate";
245 command = "HibernateAllowed";
246 break;
247
248 case Power::PowerSuspend:
249 property = "CanSuspend";
250 command = "SuspendAllowed";
251 break;
252
253 default:
254 return false;
255 }
256
257 return dbusGetProperty( // Whether the system is able to hibernate.
258 UPOWER_SERVICE,
259 UPOWER_PATH,
260 PROPERTIES_INTERFACE,
261 QDBusConnection::systemBus(),
262 property
263 )
264 &&
265 dbusCall( // Check if the caller has (or can get) the PolicyKit privilege to call command.
266 UPOWER_SERVICE,
267 UPOWER_PATH,
268 UPOWER_INTERFACE,
269 QDBusConnection::systemBus(),
270 command,
271 // canAction should be always silent because it can freeze
272 // g_main_context_iteration Qt event loop in QMessageBox
273 // on panel startup if there is no DBUS running.
274 PowerProvider::DontCheckDBUS
275 );
276 }
277
278
279 bool UPowerProvider::doAction(Power::Action action)
280 {
281 QString command;
282
283 switch (action)
284 {
285 case Power::PowerHibernate:
286 command = "Hibernate";
287 break;
288
289 case Power::PowerSuspend:
290 command = "Suspend";
291 break;
292
293 default:
294 return false;
295 }
296
297
298 return dbusCall(UPOWER_SERVICE,
299 UPOWER_PATH,
300 UPOWER_INTERFACE,
301 QDBusConnection::systemBus(),
302 command );
303 }
304
305
306
307 /************************************************
308 ConsoleKitProvider
309 ************************************************/
310 ConsoleKitProvider::ConsoleKitProvider(QObject *parent):
311 PowerProvider(parent)
312 {
313 }
314
315
316 ConsoleKitProvider::~ConsoleKitProvider()
317 {
318 }
319
320
321 bool ConsoleKitProvider::canAction(Power::Action action) const
322 {
323 QString command;
324 switch (action)
325 {
326 case Power::PowerReboot:
327 command = "CanReboot";
328 break;
329
330 case Power::PowerShutdown:
331 command = "CanPowerOff";
332 break;
333
334 case Power::PowerHibernate:
335 command = "CanHibernate";
336 break;
337
338 case Power::PowerSuspend:
339 command = "CanSuspend";
340 break;
341
342 default:
343 return false;
344 }
345
346 return dbusCallSystemd(CONSOLEKIT_SERVICE,
347 CONSOLEKIT_PATH,
348 CONSOLEKIT_INTERFACE,
349 QDBusConnection::systemBus(),
350 command,
351 false,
352 // canAction should be always silent because it can freeze
353 // g_main_context_iteration Qt event loop in QMessageBox
354 // on panel startup if there is no DBUS running.
355 PowerProvider::DontCheckDBUS
356 );
357 }
358
359
360 bool ConsoleKitProvider::doAction(Power::Action action)
361 {
362 QString command;
363 switch (action)
364 {
365 case Power::PowerReboot:
366 command = "Reboot";
367 break;
368
369 case Power::PowerShutdown:
370 command = "PowerOff";
371 break;
372
373 case Power::PowerHibernate:
374 command = "Hibernate";
375 break;
376
377 case Power::PowerSuspend:
378 command = "Suspend";
379 break;
380
381 default:
382 return false;
383 }
384
385 return dbusCallSystemd(CONSOLEKIT_SERVICE,
386 CONSOLEKIT_PATH,
387 CONSOLEKIT_INTERFACE,
388 QDBusConnection::systemBus(),
389 command,
390 true
391 );
392 }
393
394 /************************************************
395 SystemdProvider
396
397 http://www.freedesktop.org/wiki/Software/systemd/logind
398 ************************************************/
399
400 SystemdProvider::SystemdProvider(QObject *parent):
401 PowerProvider(parent)
402 {
403 }
404
405
406 SystemdProvider::~SystemdProvider()
407 {
408 }
409
410
411 bool SystemdProvider::canAction(Power::Action action) const
412 {
413 QString command;
414
415 switch (action)
416 {
417 case Power::PowerReboot:
418 command = "CanReboot";
419 break;
420
421 case Power::PowerShutdown:
422 command = "CanPowerOff";
423 break;
424
425 case Power::PowerSuspend:
426 command = "CanSuspend";
427 break;
428
429 case Power::PowerHibernate:
430 command = "CanHibernate";
431 break;
432
433 default:
434 return false;
435 }
436
437 return dbusCallSystemd(SYSTEMD_SERVICE,
438 SYSTEMD_PATH,
439 SYSTEMD_INTERFACE,
440 QDBusConnection::systemBus(),
441 command,
442 false,
443 // canAction should be always silent because it can freeze
444 // g_main_context_iteration Qt event loop in QMessageBox
445 // on panel startup if there is no DBUS running.
446 PowerProvider::DontCheckDBUS
447 );
448 }
449
450
451 bool SystemdProvider::doAction(Power::Action action)
452 {
453 QString command;
454
455 switch (action)
456 {
457 case Power::PowerReboot:
458 command = "Reboot";
459 break;
460
461 case Power::PowerShutdown:
462 command = "PowerOff";
463 break;
464
465 case Power::PowerSuspend:
466 command = "Suspend";
467 break;
468
469 case Power::PowerHibernate:
470 command = "Hibernate";
471 break;
472
473 default:
474 return false;
475 }
476
477 return dbusCallSystemd(SYSTEMD_SERVICE,
478 SYSTEMD_PATH,
479 SYSTEMD_INTERFACE,
480 QDBusConnection::systemBus(),
481 command,
482 true
483 );
484 }
485
486
487 /************************************************
488 LXQtProvider
489 ************************************************/
490 LXQtProvider::LXQtProvider(QObject *parent):
491 PowerProvider(parent)
492 {
493 }
494
495
496 LXQtProvider::~LXQtProvider()
497 {
498 }
499
500
501 bool LXQtProvider::canAction(Power::Action action) const
502 {
503 switch (action)
504 {
505 case Power::PowerLogout:
506 // there can be case when razo-session does not run
507 return dbusCall(LXQT_SERVICE, LXQT_PATH, LXQT_SERVICE,
508 QDBusConnection::sessionBus(), "canLogout",
509 PowerProvider::DontCheckDBUS);
510 default:
511 return false;
512 }
513 }
514
515
516 bool LXQtProvider::doAction(Power::Action action)
517 {
518 QString command;
519
520 switch (action)
521 {
522 case Power::PowerLogout:
523 command = "logout";
524 break;
525
526 default:
527 return false;
528 }
529
530 return dbusCall(LXQT_SERVICE,
531 LXQT_PATH,
532 LXQT_INTERFACE,
533 QDBusConnection::sessionBus(),
534 command
535 );
536 }
537
538 /************************************************
539 LxSessionProvider
540 ************************************************/
541 LxSessionProvider::LxSessionProvider(QObject *parent):
542 PowerProvider(parent)
543 {
544 pid = (Q_PID)qgetenv("_LXSESSION_PID").toLong();
545 }
546
547
548 LxSessionProvider::~LxSessionProvider()
549 {
550 }
551
552
553 bool LxSessionProvider::canAction(Power::Action action) const
554 {
555 switch (action)
556 {
557 case Power::PowerLogout:
558 return pid != 0;
559 default:
560 return false;
561 }
562 }
563
564
565 bool LxSessionProvider::doAction(Power::Action action)
566 {
567 switch (action)
568 {
569 case Power::PowerLogout:
570 if(pid)
571 ::kill(pid, SIGTERM);
572 break;
573 default:
574 return false;
575 }
576
577 return true;
578 }
579
580
581 /************************************************
582 HalProvider
583 ************************************************/
584 HalProvider::HalProvider(QObject *parent):
585 PowerProvider(parent)
586 {
587 }
588
589
590 HalProvider::~HalProvider()
591 {
592 }
593
594
595 bool HalProvider::canAction(Power::Action action) const
596 {
597 Q_UNUSED(action)
598 return false;
599 }
600
601
602 bool HalProvider::doAction(Power::Action action)
603 {
604 Q_UNUSED(action)
605 return false;
606 }
607
608
609 /************************************************
610 CustomProvider
611 ************************************************/
612 CustomProvider::CustomProvider(QObject *parent):
613 PowerProvider(parent),
614 mSettings("power")
615 {
616 }
617
618 CustomProvider::~CustomProvider()
619 {
620 }
621
622 bool CustomProvider::canAction(Power::Action action) const
623 {
624 switch (action)
625 {
626 case Power::PowerShutdown:
627 return mSettings.contains("shutdownCommand");
628
629 case Power::PowerReboot:
630 return mSettings.contains("rebootCommand");
631
632 case Power::PowerHibernate:
633 return mSettings.contains("hibernateCommand");
634
635 case Power::PowerSuspend:
636 return mSettings.contains("suspendCommand");
637
638 case Power::PowerLogout:
639 return mSettings.contains("logoutCommand");
640
641 default:
642 return false;
643 }
644 }
645
646 bool CustomProvider::doAction(Power::Action action)
647 {
648 QString command;
649
650 switch(action)
651 {
652 case Power::PowerShutdown:
653 command = mSettings.value("shutdownCommand").toString();
654 break;
655
656 case Power::PowerReboot:
657 command = mSettings.value("rebootCommand").toString();
658 break;
659
660 case Power::PowerHibernate:
661 command = mSettings.value("hibernateCommand").toString();
662 break;
663
664 case Power::PowerSuspend:
665 command = mSettings.value("suspendCommand").toString();
666 break;
667
668 case Power::PowerLogout:
669 command = mSettings.value("logoutCommand").toString();
670 break;
671
672 default:
673 return false;
674 }
675
676 return QProcess::startDetached(command);
677 }