1 // This is the implementation of the QPyDBusReply class.
2 //
3 // Copyright (c) 2021 Riverbank Computing Limited <info@riverbankcomputing.com>
4 //
5 // This file is part of PyQt5.
6 //
7 // This file may be used under the terms of the GNU General Public License
8 // version 3.0 as published by the Free Software Foundation and appearing in
9 // the file LICENSE included in the packaging of this file. Please review the
10 // following information to ensure the GNU General Public License version 3.0
11 // requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 //
13 // If you do not wish to use this file under the terms of the GPL version 3.0
14 // then you may purchase a commercial license. For more information contact
15 // info@riverbankcomputing.com.
16 //
17 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19
20
21 #include <Python.h>
22
23 #include <QDBusMessage>
24 #include <QDBusPendingCall>
25
26 #include "qpydbusreply.h"
27
28 #include "sipAPIQtDBus.h"
29
30
31 // Extract a reply from a message. The GIL should be held.
QPyDBusReply(const QDBusMessage & reply)32 QPyDBusReply::QPyDBusReply(const QDBusMessage &reply)
33 {
34 *this = reply;
35 }
36
37
38 // Extract a reply from a pending call. The GIL should be held.
QPyDBusReply(const QDBusPendingCall & call)39 QPyDBusReply::QPyDBusReply(const QDBusPendingCall &call)
40 {
41 *this = call;
42 }
43
44
45 // Extract a reply from an error.
QPyDBusReply(const QDBusError & error)46 QPyDBusReply::QPyDBusReply(const QDBusError &error)
47 {
48 _q_value = 0;
49 _q_is_valid = !error.isValid();
50 _q_error = error;
51 }
52
53
54 // Copy a reply. The GIL should be held.
QPyDBusReply(const QPyDBusReply & other)55 QPyDBusReply::QPyDBusReply(const QPyDBusReply &other)
56 {
57 _q_value = other._q_value;
58 Py_XINCREF(_q_value);
59
60 _q_value_variant = other._q_value_variant;
61 _q_is_valid = other._q_is_valid;
62 _q_error = other._q_error;
63 }
64
65
66 // A reply created from a QDBusReply<> mapped type convertor.
QPyDBusReply(PyObject * q_value,bool q_is_valid,const QDBusError & q_error)67 QPyDBusReply::QPyDBusReply(PyObject *q_value, bool q_is_valid, const QDBusError &q_error) : _q_value(q_value), _q_is_valid(q_is_valid), _q_error(q_error)
68 {
69 }
70
71
72 // The dtor. The GIL should be held.
~QPyDBusReply()73 QPyDBusReply::~QPyDBusReply()
74 {
75 Py_XDECREF(_q_value);
76 }
77
78
79 // Return the value of the reply. The GIL should be held.
value(PyObject * type) const80 PyObject *QPyDBusReply::value(PyObject *type) const
81 {
82 if (!_q_is_valid)
83 {
84 PyErr_SetString(PyExc_ValueError, "QDBusReply value is invalid");
85 return 0;
86 }
87
88 // Return any explicit value.
89 if (_q_value)
90 {
91 if (type)
92 {
93 PyErr_SetString(PyExc_ValueError,
94 "'type' argument cannot be used with an explcitly typed reply");
95 return 0;
96 }
97
98 Py_INCREF(_q_value);
99 return _q_value;
100 }
101
102 QVariant val(_q_value_variant);
103
104 return pyqt5_qtdbus_from_qvariant_by_type(val, type);
105 }
106
107
108 // Extract a reply from a message. The GIL should be held.
operator =(const QDBusMessage & reply)109 QPyDBusReply &QPyDBusReply::operator=(const QDBusMessage &reply)
110 {
111 _q_value = 0;
112 _q_error = reply;
113 _q_is_valid = !_q_error.isValid();
114
115 if (_q_is_valid)
116 {
117 QList<QVariant> results = reply.arguments();
118
119 if (results.count() == 0)
120 {
121 Py_INCREF(Py_None);
122 _q_value = Py_None;
123 }
124 else
125 {
126 // Convert this later if requested.
127 _q_value_variant = results.at(0);
128 }
129 }
130
131 return *this;
132 }
133
134
135 // Extract a reply from a pending call. The GIL should be held.
operator =(const QDBusPendingCall & call)136 QPyDBusReply &QPyDBusReply::operator=(const QDBusPendingCall &call)
137 {
138 QDBusPendingCall other(call);
139
140 Py_BEGIN_ALLOW_THREADS
141 other.waitForFinished();
142 Py_END_ALLOW_THREADS
143
144 return *this = other.reply();
145 }
146