1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2011-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 #  include "config.h"
28 #endif
29 
30 #include <QString>
31 #include <QVariant>
32 
33 #include "Object.h"
34 #include "QtHandlesUtils.h"
35 #include "octave-qobject.h"
36 #include "qt-graphics-toolkit.h"
37 
38 #include "graphics.h"
39 #include "interpreter.h"
40 
41 namespace QtHandles
42 {
43 
Object(octave::base_qobject & oct_qobj,octave::interpreter & interp,const graphics_object & go,QObject * obj)44   Object::Object (octave::base_qobject& oct_qobj, octave::interpreter& interp,
45                   const graphics_object& go, QObject *obj)
46     : QObject (), m_octave_qobj (oct_qobj), m_interpreter (interp),
47       m_go (go), m_handle (go.get_handle ()), m_qobject (nullptr)
48   {
49     gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
50 
51     octave::autolock guard (gh_mgr.graphics_lock ());
52 
53     if (! guard)
54       qCritical ("QtHandles::Object::Object: "
55                  "creating Object (h=%g) without a valid lock!!!",
56                  m_handle.value ());
57 
58     init (obj);
59   }
60 
61   void
init(QObject * obj,bool)62   Object::init (QObject *obj, bool)
63   {
64     if (m_qobject)
65       qCritical ("QtHandles::Object::init: "
66                  "resetting QObject while in invalid state");
67 
68     m_qobject = obj;
69 
70     if (m_qobject)
71       {
72         m_qobject->setProperty ("QtHandles::Object",
73                                 QVariant::fromValue<void*> (this));
74         connect (m_qobject, SIGNAL (destroyed (QObject*)),
75                  SLOT (objectDestroyed (QObject*)));
76       }
77   }
78 
~Object(void)79   Object::~Object (void)
80   { }
81 
82   graphics_object
object(void) const83   Object::object (void) const
84   {
85     gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
86 
87     octave::autolock guard (gh_mgr.graphics_lock (), false);
88 
89     if (! guard)
90       qCritical ("QtHandles::Object::object: "
91                  "accessing graphics object (h=%g) without a valid lock!!!",
92                  m_handle.value ());
93 
94     return m_go;
95   }
96 
97   void
slotUpdate(int pId)98   Object::slotUpdate (int pId)
99   {
100     gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
101 
102     octave::autolock guard (gh_mgr.graphics_lock ());
103 
104     switch (pId)
105       {
106       // Special case for objects being deleted, as it's very likely
107       // that the graphics_object already has been destroyed when this
108       // is executed (because of the async behavior).
109       case base_properties::ID_BEINGDELETED:
110         beingDeleted ();
111         break;
112 
113       default:
114         if (object ().valid_object ())
115           update (pId);
116         break;
117       }
118   }
119 
120   void
slotFinalize(void)121   Object::slotFinalize (void)
122   {
123     gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
124 
125     octave::autolock guard (gh_mgr.graphics_lock ());
126 
127     finalize ();
128   }
129 
130   void
slotRedraw(void)131   Object::slotRedraw (void)
132   {
133     gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
134 
135     octave::autolock guard (gh_mgr.graphics_lock ());
136 
137     if (object ().valid_object ())
138       redraw ();
139   }
140 
141   void
slotShow(void)142   Object::slotShow (void)
143   {
144     gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
145 
146     octave::autolock guard (gh_mgr.graphics_lock ());
147 
148     if (object ().valid_object ())
149       show ();
150   }
151 
152   void
slotPrint(const QString & file_cmd,const QString & term)153   Object::slotPrint (const QString& file_cmd, const QString& term)
154   {
155     gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
156 
157     octave::autolock guard (gh_mgr.graphics_lock ());
158 
159     if (object ().valid_object ())
160       print (file_cmd, term);
161   }
162 
163   void
update(int)164   Object::update (int /* pId */)
165   { }
166 
167   void
finalize(void)168   Object::finalize (void)
169   {
170     if (m_qobject)
171       {
172         delete m_qobject;
173         m_qobject = nullptr;
174       }
175     deleteLater ();
176   }
177 
178   void
redraw(void)179   Object::redraw (void)
180   { }
181 
182   void
show(void)183   Object::show (void)
184   { }
185 
186   void
print(const QString &,const QString &)187   Object::print (const QString& /* file_cmd */, const QString& /* term */)
188   { }
189 
190   void
beingDeleted(void)191   Object::beingDeleted (void)
192   { }
193 
objectDestroyed(QObject * obj)194   void Object::objectDestroyed (QObject *obj)
195   {
196     if (obj && obj == m_qobject)
197       m_qobject = nullptr;
198   }
199 
200   Object*
parentObject(octave::interpreter & interp,const graphics_object & go)201   Object::parentObject (octave::interpreter& interp, const graphics_object& go)
202   {
203     gh_manager& gh_mgr = interp.get_gh_manager ();
204 
205     octave::autolock guard (gh_mgr.graphics_lock ());
206 
207     Object *parent = qt_graphics_toolkit::toolkitObject
208                      (gh_mgr.get_object (go.get_parent ()));
209 
210     return parent;
211   }
212 
213   Object*
fromQObject(QObject * obj)214   Object::fromQObject (QObject *obj)
215   {
216     QVariant v = obj->property ("QtHandles::Object");
217 
218     if (v.isValid ())
219       return reinterpret_cast<Object *> (qvariant_cast<void*> (v));
220 
221     return nullptr;
222   }
223 
224   void
do_connections(const QObject * receiver,const QObject * emitter)225   Object::do_connections (const QObject *receiver, const QObject *emitter)
226   {
227     if (! emitter)
228       emitter = this;
229 
230     connect (emitter,
231              SIGNAL (interpreter_event (const octave::fcn_callback&)),
232              receiver,
233              SLOT (interpreter_event (const octave::fcn_callback&)));
234 
235     connect (emitter,
236              SIGNAL (interpreter_event (const octave::meth_callback&)),
237              receiver,
238              SLOT (interpreter_event (const octave::meth_callback&)));
239 
240     connect (emitter,
241              SIGNAL (gh_callback_event (const graphics_handle&,
242                                         const std::string&)),
243              receiver,
244              SLOT (gh_callback_event (const graphics_handle&,
245                                       const std::string&)));
246 
247     connect (emitter,
248              SIGNAL (gh_callback_event (const graphics_handle&,
249                                         const std::string&,
250                                         const octave_value&)),
251              receiver,
252              SLOT (gh_callback_event (const graphics_handle&,
253                                       const std::string&,
254                                       const octave_value&)));
255 
256     connect (emitter,
257              SIGNAL (gh_set_event (const graphics_handle&,
258                                    const std::string&,
259                                    const octave_value&)),
260              receiver,
261              SLOT (gh_set_event (const graphics_handle&,
262                                  const std::string&,
263                                  const octave_value&)));
264 
265     connect (emitter,
266              SIGNAL (gh_set_event (const graphics_handle&,
267                                    const std::string&,
268                                    const octave_value&, bool)),
269              receiver,
270              SLOT (gh_set_event (const graphics_handle&,
271                                  const std::string&,
272                                  const octave_value&, bool)));
273 
274     connect (emitter,
275              SIGNAL (gh_set_event (const graphics_handle&,
276                                    const std::string&,
277                                    const octave_value&,
278                                    bool, bool)),
279              receiver,
280              SLOT (gh_set_event (const graphics_handle&,
281                                  const std::string&,
282                                  const octave_value&,
283                                  bool, bool)));
284   }
285 
286 }
287