1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtSystems module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include "qdeclarativeserviceold_p.h"
35
36#include <QQmlEngine>
37#include <QQmlInfo>
38
39QT_BEGIN_NAMESPACE
40
41/*!
42 \qmltype Service
43 \instantiates QDeclarativeService
44
45 \brief The Service element holds an instance of a service object.
46 \inherits QObject
47
48 \ingroup qml-serviceframework
49
50 The Service element is part of the Qt ServiceFramework API and
51 provides a client instance of the service object. This element is a simplified
52 reflection of the QServiceInterfaceDescriptor class that allows the specification of
53 the Service::interfaceName to locate the default service implemented at this interface.
54
55 \sa ServiceList
56*/
57QDeclarativeService::QDeclarativeService()
58 : m_serviceInstance(0), m_componentComplete(false)
59{
60 m_serviceManager = new QServiceManager();
61}
62
63QDeclarativeService::~QDeclarativeService()
64{
65 delete m_serviceInstance;
66}
67
68/*!
69 \qmlproperty bool Service::valid read-only
70
71 This property holds whether a default service was found at the
72 interface name and corresponds to QServiceInterfaceDescriptor::isValid().
73*/
74bool QDeclarativeService::isValid() const
75{
76 return m_descriptor.isValid();
77}
78
79void QDeclarativeService::setInterfaceDesc(const QServiceInterfaceDescriptor &desc)
80{
81 if (desc == m_descriptor)
82 return;
83
84 m_descriptor = desc;
85
86 if (m_serviceInstance)
87 delete m_serviceInstance;
88 setServiceObject(0);
89}
90
91QServiceInterfaceDescriptor QDeclarativeService::interfaceDesc() const
92{
93 return m_descriptor;
94}
95
96/*!
97 \qmlproperty QString Service::interfaceName
98
99 This property holds the interface name of the service that
100 corresponds to QServiceInterfaceDescriptor::interfaceName().
101*/
102void QDeclarativeService::setInterfaceName(const QString &serviceInterface)
103{
104 m_interface = serviceInterface;
105 updateDescriptor();
106}
107
108QString QDeclarativeService::interfaceName() const
109{
110 if (isValid())
111 return m_descriptor.interfaceName();
112 else
113 return "No Interface";
114}
115
116/*!
117 \qmlproperty QString Service::serviceName
118
119 This property holds the service name of the service that
120 corresponds to QServiceInterfaceDescriptor::serviceName().
121*/
122QString QDeclarativeService::serviceName() const
123{
124 if (isValid())
125 return m_descriptor.serviceName();
126 else
127 return "No Service";
128}
129
130void QDeclarativeService::setServiceName(const QString &service)
131{
132 m_service = service;
133}
134
135/*!
136 \qmlproperty int Service::majorVersion
137
138 This property holds the major version number of the service that
139 corresponds to QServiceInterfaceDescriptor::majorVersion().
140*/
141int QDeclarativeService::majorVersion() const
142{
143 if (isValid())
144 return m_descriptor.majorVersion();
145 else
146 return 0;
147}
148
149void QDeclarativeService::setMajorVersion(int version)
150{
151 m_major = version;
152 updateDescriptor();
153}
154
155/*!
156 \qmlproperty int Service::minorVersion
157
158 This property holds the minor version number of the service that
159 corresponds to QServiceInterfaceDescriptor::minorVersion().
160*/
161int QDeclarativeService::minorVersion() const
162{
163 if (isValid())
164 return m_descriptor.minorVersion();
165 else
166 return 0;
167}
168
169void QDeclarativeService::setMinorVersion(int version)
170{
171 m_minor = version;
172 updateDescriptor();
173}
174
175/*!
176 \qmlproperty QObject* Service::serviceObject
177
178 This property holds an instance of the service object which
179 can be used to make metaobject calls to the service. This
180 corresponds to QServiceManager::loadInterface().
181*/
182QObject* QDeclarativeService::serviceObject()
183{
184 if (m_serviceInstance) {
185 return m_serviceInstance;
186 }
187
188 if (isValid()) {
189 QObject *object = m_serviceManager->loadInterface(descriptor: m_descriptor);
190 setServiceObject(object);
191 if (!m_serviceInstance) {
192 emit error(errorString: QLatin1String("Failed to create object"));
193 return m_serviceInstance;
194 }
195 emit serviceObjectChanged();
196 connect(sender: m_serviceInstance, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)),
197 receiver: this, SLOT(IPCFault(QService::UnrecoverableIPCError)));
198 m_error.clear();
199 return m_serviceInstance;
200 } else {
201 return 0;
202 }
203}
204
205/*!
206 \qmlproperty QString Service::error
207
208 This property holds the last error the was received, if any
209
210 */
211
212QString QDeclarativeService::lastError() const
213{
214 return m_error;
215}
216
217void QDeclarativeService::IPCFault(QService::UnrecoverableIPCError errorValue)
218{
219 switch (errorValue) {
220 default:
221 case QService::ErrorUnknown:
222 m_error = QLatin1String("IPC Error: Unkown Error");
223 break;
224 case QService::ErrorServiceNoLongerAvailable:
225 m_error = QLatin1String("IPC Error: Service no longer available");
226 break;
227 case QService::ErrorOutofMemory:
228 m_error = QLatin1String("IPC Error: Out of memory");
229 break;
230 case QService::ErrorPermissionDenied:
231 m_error = QLatin1String("IPC Error: Permission Denied");
232 break;
233 case QService::ErrorInvalidArguments:
234 m_error = QLatin1String("IPC Error: Invalid Arguments");
235 break;
236 }
237 emit error(errorString: m_error);
238 m_serviceInstance->deleteLater();
239 setServiceObject(0);
240}
241
242void QDeclarativeService::updateDescriptor()
243{
244 if (!m_componentComplete)
245 return;
246
247 if (m_interface.isEmpty())
248 return;
249
250 QServiceInterfaceDescriptor new_desc;
251
252 if (m_minor == 0 && m_major == 0 && m_service.isEmpty()){
253 new_desc = m_serviceManager->interfaceDefault(interfaceName: m_interface);
254 }
255 else {
256 QServiceFilter filter;
257 if (!m_service.isEmpty())
258 filter.setServiceName(m_service);
259
260
261 if (m_minor != 0 || m_major != 0) {
262 const QString version = QString::number(m_major) + "." + QString::number(m_minor);
263 filter.setInterface(interfaceName: m_interface, version);
264 }
265
266 QList<QServiceInterfaceDescriptor> list = m_serviceManager->findInterfaces(filter);
267 if (!list.isEmpty())
268 new_desc = list.takeFirst();
269 }
270
271 if (new_desc != m_descriptor) {
272 m_descriptor = new_desc;
273 if (m_serviceInstance)
274 emit serviceObjectChanged();
275 }
276
277 if (!isValid()) {
278 qWarning() << "WARNING: No service found for interface name: " << m_interface << m_service << m_major << m_minor;
279 }
280}
281
282void QDeclarativeService::setServiceObject(QObject *object)
283{
284 if (m_serviceInstance != object) {
285 m_serviceInstance = object;
286 emit serviceObjectChanged();
287 }
288}
289
290void QDeclarativeService::classBegin()
291{
292
293}
294
295void QDeclarativeService::componentComplete()
296{
297 m_componentComplete = true;
298 updateDescriptor();
299}
300
301bool QDeclarativeService::operator ==(const QServiceInterfaceDescriptor& other ) const
302{
303 if ( m_descriptor == other)
304 return true;
305
306 return false;
307}
308
309/*!
310 \qmltype ServiceList
311 \instantiates QDeclarativeServiceList
312
313 \brief The ServiceList element holds a list of \l Service elements.
314 \inherits QObject
315
316 \ingroup qml-serviceframework
317
318 The ServiceList element is part of the Qt ServiceFramework API and
319 provides a list of \l Service elements at the interface ServiceList::interfaceName with
320 minimum version match ServiceList::minVersion properties. This list can be used to
321 select the desired service and instantiate a service object for access via the QMetaObject.
322
323 This element is a simplified reflection of the QServiceFilter class that provides a list
324 of simplified QServiceInterfaceDescriptors. Similarly, if the ServiceList::serviceName
325 and ServiceList::versionMatch are not provided they will respectively default to an empty
326 string with a minimum verison match.
327
328 \sa Service
329*/
330QDeclarativeServiceList::QDeclarativeServiceList()
331 : m_service(QString()),
332 m_interface(),
333 m_major(1),
334 m_minor(1),
335 m_match(QDeclarativeServiceList::Minimum),
336 m_componentComplete(false)
337{
338 serviceManager = new QServiceManager(this);
339}
340
341QDeclarativeServiceList::~QDeclarativeServiceList()
342{
343 while (m_services.count())
344 delete m_services.takeFirst();
345}
346/*!
347 \qmlproperty QString ServiceList::serviceName
348
349 This property holds the interface name of the services that
350 corresponds to setting QServiceFilter::setService().
351*/
352void QDeclarativeServiceList::setServiceName(const QString &service)
353{
354 m_service = service;
355 updateFilterResults();
356 if (m_componentComplete)
357 emit serviceNameChanged();
358}
359
360QString QDeclarativeServiceList::serviceName() const
361{
362 return m_service;
363}
364
365/*!
366 \qmlproperty QString ServiceList::interfaceName
367
368 This property holds the interface name of the services that
369 corresponds to setting QServiceFilter::setInterface().
370*/
371void QDeclarativeServiceList::setInterfaceName(const QString &serviceInterface)
372{
373 m_interface = serviceInterface;
374 updateFilterResults();
375 if (m_componentComplete)
376 emit interfaceNameChanged();
377}
378
379QString QDeclarativeServiceList::interfaceName() const
380{
381 return m_interface;
382}
383
384/*!
385 \qmlproperty int ServiceList::majorVersion
386
387 This property holds the major version number of the service filter that
388 corresponds to QServiceFilter::majorVersion().
389*/
390void QDeclarativeServiceList::setMajorVersion(int major)
391{
392 m_major = major;
393 updateFilterResults();
394 if (m_componentComplete)
395 emit majorVersionChanged();
396}
397
398int QDeclarativeServiceList::majorVersion() const
399{
400 return m_major;
401}
402
403/*!
404 \qmlproperty int ServiceList::minorVersion
405
406 This property holds the minor version number of the service filter that
407 corresponds to QServiceFilter::minorVersion().
408*/
409void QDeclarativeServiceList::setMinorVersion(int minor)
410{
411 m_minor = minor;
412 updateFilterResults();
413 if (m_componentComplete)
414 emit minorVersionChanged();
415}
416
417int QDeclarativeServiceList::minorVersion() const
418{
419 return m_minor;
420}
421
422/*!
423 \qmlproperty int ServiceList::monitorServiceRegistrations
424
425 This property controls the behaviour of the list when new services are
426 registered or deregistered. Setting this property to true means the list
427 will be automatically updated when a service is added or removed. Caution,
428 your service object will be deleted if the service is unregistered, even if
429 the service is still running.
430*/
431
432void QDeclarativeServiceList::setMonitorServiceRegistrations(bool updates)
433{
434 if (updates == false) {
435 disconnect(receiver: this, SLOT(servicesAddedRemoved()));
436 }
437 else {
438 connect(sender: serviceManager, SIGNAL(serviceAdded(QString,QService::Scope)),
439 receiver: this, SLOT(servicesAddedRemoved()));
440 connect(sender: serviceManager, SIGNAL(serviceRemoved(QString,QService::Scope)),
441 receiver: this, SLOT(servicesAddedRemoved()));
442 }
443
444 if (m_dynamicUpdates != updates)
445 emit monitorServiceRegistrationsChanged();
446
447 m_dynamicUpdates = updates;
448}
449
450void QDeclarativeServiceList::servicesAddedRemoved()
451{
452 // invoke in another event loop run
453 QMetaObject::invokeMethod(obj: this, member: "updateServiceList", type: Qt::QueuedConnection);
454}
455
456bool QDeclarativeServiceList::monitorServiceRegistrations() const
457{
458 return m_dynamicUpdates;
459}
460
461/*!
462 \qmlproperty enumeration ServiceList::versionMatch
463
464 This property holds the version match rule of the service filter that
465 corresponds to QServiceFilter::versionMatchRule(). Within QML the values
466 ServiceList.Exact and ServiceList.Minimum correspond to
467 QServiceFilter::ExactVersionMatch and QServiceFilter::MinimumVersionMatch
468 respectively.
469*/
470void QDeclarativeServiceList::setVersionMatch(MatchRule match)
471{
472 m_match = match;
473 updateFilterResults();
474 if (m_componentComplete)
475 emit versionMatchChanged();
476}
477
478QDeclarativeServiceList::MatchRule QDeclarativeServiceList::versionMatch() const
479{
480 return m_match;
481}
482
483
484void QDeclarativeServiceList::updateServiceList()
485{
486 if (!m_componentComplete)
487 return;
488
489 const QString version = QString::number(m_major) + "." + QString::number(m_minor);
490
491 QServiceFilter filter;
492
493 if (!m_service.isEmpty())
494 filter.setServiceName(m_service);
495
496 if (m_match == QDeclarativeServiceList::Exact)
497 filter.setInterface(interfaceName: m_interface, version, rule: QServiceFilter::ExactVersionMatch);
498 else if (!m_interface.isEmpty())
499 filter.setInterface(interfaceName: m_interface, version);
500
501 const QList<QServiceInterfaceDescriptor> newlist = serviceManager->findInterfaces(filter);
502
503 QSet<QServiceInterfaceDescriptor> currentServices = QSet<QServiceInterfaceDescriptor>::fromList(list: m_currentList);
504 QSet<QServiceInterfaceDescriptor> newServices = QSet<QServiceInterfaceDescriptor>::fromList(list: newlist);
505
506 if (currentServices == newServices) {
507 return;
508 }
509
510 const QSet<QServiceInterfaceDescriptor> addServices = newServices.subtract(other: currentServices);
511 const QSet<QServiceInterfaceDescriptor> delServices = currentServices.subtract(
512 other: QSet<QServiceInterfaceDescriptor>::fromList(list: newlist));
513
514 foreach (const QServiceInterfaceDescriptor &desc, delServices) {
515 foreach (QDeclarativeService *service, m_services) {
516 if (*service == desc) {
517 m_services.removeOne(t: service);
518 delete service;
519 }
520 }
521 m_currentList.removeOne(t: desc);
522 }
523
524 foreach (const QServiceInterfaceDescriptor &desc, addServices) {
525 QDeclarativeService *service = new QDeclarativeService();
526 service->setInterfaceDesc(desc);
527 m_services.append(t: service);
528 m_currentList.append(t: desc);
529 }
530
531 emit resultsChanged();
532}
533
534void QDeclarativeServiceList::updateFilterResults()
535{
536 if (!m_componentComplete)
537 return;
538
539 const QString version = QString::number(m_major) + "." + QString::number(m_minor);
540
541 QServiceFilter filter;
542
543 if (!m_service.isEmpty())
544 filter.setServiceName(m_service);
545
546 if (m_match == QDeclarativeServiceList::Exact)
547 filter.setInterface(interfaceName: m_interface, version, rule: QServiceFilter::ExactVersionMatch);
548 else if (!m_interface.isEmpty())
549 filter.setInterface(interfaceName: m_interface, version);
550
551 QList<QServiceInterfaceDescriptor> list = serviceManager->findInterfaces(filter);
552
553 if (list == m_currentList) {
554 return;
555 }
556
557 m_currentList = list;
558
559 while (m_services.count()) //for now we refresh the entire list
560 delete m_services.takeFirst();
561
562 for (int i = 0; i < list.size(); i++) {
563 QDeclarativeService *service = new QDeclarativeService();
564 service->setInterfaceDesc(list.at(i));
565 m_services.append(t: service);
566 }
567
568 emit resultsChanged();
569}
570
571/*!
572 \qmlproperty QQmlListProperty ServiceList::services
573
574 This property holds the list of \l Service elements that match
575 the Service::interfaceName and minimum Service::versionNumber properties.
576*/
577QQmlListProperty<QDeclarativeService> QDeclarativeServiceList::services()
578{
579 return QQmlListProperty<QDeclarativeService>(this,
580 0,
581 s_append,
582 s_count,
583 s_at,
584 s_clear);
585}
586
587void QDeclarativeServiceList::classBegin()
588{
589}
590
591void QDeclarativeServiceList::componentComplete()
592{
593 if (!m_componentComplete) {
594 m_componentComplete = true;
595 updateFilterResults();
596 }
597}
598
599void QDeclarativeServiceList::listUpdated()
600{
601 if (m_componentComplete)
602 emit resultsChanged();
603}
604
605void QDeclarativeServiceList::s_append(QQmlListProperty<QDeclarativeService> *prop, QDeclarativeService *service)
606{
607 QDeclarativeServiceList* list = static_cast<QDeclarativeServiceList*>(prop->object);
608 list->m_services.append(t: service);
609 list->listUpdated();
610}
611int QDeclarativeServiceList::s_count(QQmlListProperty<QDeclarativeService> *prop)
612{
613 return static_cast<QDeclarativeServiceList*>(prop->object)->m_services.count();
614}
615
616QDeclarativeService* QDeclarativeServiceList::s_at(QQmlListProperty<QDeclarativeService> *prop, int index)
617{
618 return static_cast<QDeclarativeServiceList*>(prop->object)->m_services[index];
619}
620
621void QDeclarativeServiceList::s_clear(QQmlListProperty<QDeclarativeService> *prop)
622{
623 QDeclarativeServiceList* list = static_cast<QDeclarativeServiceList*>(prop->object);
624 qDeleteAll(c: list->m_services);
625 list->m_services.clear();
626 list->listUpdated();
627}
628#include "moc_qdeclarativeserviceold_p.cpp"
629
630QT_END_NAMESPACE
631

source code of qtsystems/src/imports/serviceframework/qdeclarativeserviceold.cpp