1 /*
2  * SPDX-FileCopyrightText: 2012~2017 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "fcitxqtwatcher_p.h"
9 #include <QDBusConnection>
10 #include <QDBusConnectionInterface>
11 #include <QDBusServiceWatcher>
12 #include <QDir>
13 
14 namespace fcitx {
15 
FcitxQtWatcher(QObject * parent)16 FcitxQtWatcher::FcitxQtWatcher(QObject *parent)
17     : QObject(parent), d_ptr(new FcitxQtWatcherPrivate(this)) {}
18 
FcitxQtWatcher(const QDBusConnection & connection,QObject * parent)19 FcitxQtWatcher::FcitxQtWatcher(const QDBusConnection &connection,
20                                QObject *parent)
21     : FcitxQtWatcher(parent) {
22     setConnection(connection);
23 }
24 
~FcitxQtWatcher()25 FcitxQtWatcher::~FcitxQtWatcher() { delete d_ptr; }
26 
availability() const27 bool FcitxQtWatcher::availability() const {
28     Q_D(const FcitxQtWatcher);
29     return d->availability_;
30 }
31 
setConnection(const QDBusConnection & connection)32 void FcitxQtWatcher::setConnection(const QDBusConnection &connection) {
33     Q_D(FcitxQtWatcher);
34     return d->serviceWatcher_.setConnection(connection);
35 }
36 
connection() const37 QDBusConnection FcitxQtWatcher::connection() const {
38     Q_D(const FcitxQtWatcher);
39     return d->serviceWatcher_.connection();
40 }
41 
setWatchPortal(bool portal)42 void FcitxQtWatcher::setWatchPortal(bool portal) {
43     Q_D(FcitxQtWatcher);
44     d->watchPortal_ = portal;
45 }
46 
watchPortal() const47 bool FcitxQtWatcher::watchPortal() const {
48     Q_D(const FcitxQtWatcher);
49     return d->watchPortal_;
50 }
51 
serviceName() const52 QString FcitxQtWatcher::serviceName() const {
53     Q_D(const FcitxQtWatcher);
54     if (d->mainPresent_) {
55         return FCITX_MAIN_SERVICE_NAME;
56     }
57     if (d->portalPresent_) {
58         return FCITX_PORTAL_SERVICE_NAME;
59     }
60     return QString();
61 }
62 
setAvailability(bool availability)63 void FcitxQtWatcher::setAvailability(bool availability) {
64     Q_D(FcitxQtWatcher);
65     if (d->availability_ != availability) {
66         d->availability_ = availability;
67         Q_EMIT availabilityChanged(d->availability_);
68     }
69 }
70 
watch()71 void FcitxQtWatcher::watch() {
72     Q_D(FcitxQtWatcher);
73     if (d->watched_) {
74         return;
75     }
76 
77     connect(&d->serviceWatcher_, &QDBusServiceWatcher::serviceOwnerChanged,
78             this, &FcitxQtWatcher::imChanged);
79     d->serviceWatcher_.addWatchedService(FCITX_MAIN_SERVICE_NAME);
80     if (d->watchPortal_) {
81         d->serviceWatcher_.addWatchedService(FCITX_PORTAL_SERVICE_NAME);
82     }
83 
84     if (connection().interface()->isServiceRegistered(
85             FCITX_MAIN_SERVICE_NAME)) {
86         d->mainPresent_ = true;
87     }
88     if (d->watchPortal_ && connection().interface()->isServiceRegistered(
89                                FCITX_PORTAL_SERVICE_NAME)) {
90         d->portalPresent_ = true;
91     }
92 
93     updateAvailability();
94 
95     d->watched_ = true;
96 }
97 
unwatch()98 void FcitxQtWatcher::unwatch() {
99     Q_D(FcitxQtWatcher);
100     if (!d->watched_) {
101         return;
102     }
103     disconnect(&d->serviceWatcher_, &QDBusServiceWatcher::serviceOwnerChanged,
104                this, &FcitxQtWatcher::imChanged);
105     d->mainPresent_ = false;
106     d->portalPresent_ = false;
107     d->watched_ = false;
108     updateAvailability();
109 }
110 
isWatching() const111 bool FcitxQtWatcher::isWatching() const {
112     Q_D(const FcitxQtWatcher);
113     return d->watched_;
114 }
115 
imChanged(const QString & service,const QString &,const QString & newOwner)116 void FcitxQtWatcher::imChanged(const QString &service, const QString &,
117                                const QString &newOwner) {
118     Q_D(FcitxQtWatcher);
119     if (service == FCITX_MAIN_SERVICE_NAME) {
120         if (!newOwner.isEmpty()) {
121             d->mainPresent_ = true;
122         } else {
123             d->mainPresent_ = false;
124         }
125     } else if (service == FCITX_PORTAL_SERVICE_NAME) {
126         if (!newOwner.isEmpty()) {
127             d->portalPresent_ = true;
128         } else {
129             d->portalPresent_ = false;
130         }
131     }
132 
133     updateAvailability();
134 }
135 
updateAvailability()136 void FcitxQtWatcher::updateAvailability() {
137     Q_D(FcitxQtWatcher);
138     setAvailability(d->mainPresent_ || d->portalPresent_);
139 }
140 } // namespace fcitx
141