GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
BaseControl.cc
Go to the documentation of this file.
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 <QEvent>
31 #include <QKeyEvent>
32 #include <QMouseEvent>
33 #include <QWidget>
34 
35 #include "BaseControl.h"
36 #include "ContextMenu.h"
37 #include "QtHandlesUtils.h"
38 
39 #include "graphics.h"
40 #include "interpreter.h"
41 
42 namespace QtHandles
43 {
44 
45  static void
47  {
48  QPalette p = w->palette ();
49 
50  if (props.style_is ("edit")
51  || props.style_is ("listbox"))
52  {
53  p.setColor (QPalette::Base,
54  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
55  p.setColor (QPalette::Text,
56  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
57  }
58  else if (props.style_is ("popupmenu"))
59  {
60  // popumenu (QComboBox) is a listbox with a button, so needs set colors for both
61  QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ());
62  QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ());
63  QString qss = QString ("background: %1 none;\n"
64  "color: %2;")
65  .arg(bcol.name ()).arg (fcol.name ());
66  w->setStyleSheet(qss);
67  return;
68  }
69  else if (props.style_is ("radiobutton")
70  || props.style_is ("checkbox"))
71  {
72  p.setColor (QPalette::Button,
73  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
74  p.setColor (QPalette::WindowText,
75  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
76  }
77  else if (props.style_is ("pushbutton")
78  || props.style_is ("togglebutton"))
79  {
80  QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ());
81  QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ());
82  QString qss = QString ("background: %1 none;\n"
83  "color: %2;")
84  .arg(bcol.name ()).arg (fcol.name ());
85  w->setStyleSheet(qss);
86  return;
87  }
88  else
89  {
90  p.setColor (QPalette::Window,
91  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
92  p.setColor (QPalette::WindowText,
93  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
94  }
95 
96  w->setPalette (p);
97  }
98 
100  octave::interpreter& interp,
101  const graphics_object& go, QWidget *w)
102  : Object (oct_qobj, interp, go, w), m_normalizedFont (false),
103  m_keyPressHandlerDefined (false)
104  {
105  qObject ()->setObjectName ("UIControl");
106  init (w);
107  }
108 
109  void
110  BaseControl::init (QWidget *w, bool callBase)
111  {
112  if (callBase)
113  Object::init (w, callBase);
114 
115  uicontrol::properties& up = properties<uicontrol> ();
116 
117  Matrix bb = up.get_boundingbox (false);
118  w->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)),
119  octave::math::round (bb(2)), octave::math::round (bb(3)));
120  w->setFont (Utils::computeFont<uicontrol> (up, bb(3)));
121  updatePalette (up, w);
122  w->setEnabled (up.enable_is ("on"));
123  w->setToolTip (Utils::fromStdString (up.get_tooltipstring ()));
124  w->setVisible (up.is_visible ());
125  m_keyPressHandlerDefined = ! up.get_keypressfcn ().isempty ();
126 
127  w->installEventFilter (this);
128 
129  m_normalizedFont = up.fontunits_is ("normalized");
130  }
131 
133  { }
134 
135  void
137  {
138  update (uicontrol::properties::ID_POSITION);
139  }
140 
141  void
143  {
144  uicontrol::properties& up = properties<uicontrol> ();
145  QWidget *w = qWidget<QWidget> ();
146 
147  switch (pId)
148  {
149  case uicontrol::properties::ID_POSITION:
150  {
151  Matrix bb = up.get_boundingbox (false);
152  w->setGeometry (octave::math::round (bb(0)), octave::math::round (bb(1)),
153  octave::math::round (bb(2)), octave::math::round (bb(3)));
154  }
155  break;
156 
157  case uicontrol::properties::ID_FONTNAME:
158  case uicontrol::properties::ID_FONTSIZE:
159  case uicontrol::properties::ID_FONTWEIGHT:
160  case uicontrol::properties::ID_FONTANGLE:
161  w->setFont (Utils::computeFont<uicontrol> (up));
162  break;
163 
164  case uicontrol::properties::ID_FONTUNITS:
165  // FIXME: We shouldn't have to do anything, octave should update
166  // the "fontsize" property automatically to the new units.
167  // Hence the actual font used shouldn't change.
168  m_normalizedFont = up.fontunits_is ("normalized");
169  break;
170 
171  case uicontrol::properties::ID_BACKGROUNDCOLOR:
172  case uicontrol::properties::ID_FOREGROUNDCOLOR:
173  updatePalette (up, w);
174  break;
175 
176  case uicontrol::properties::ID_ENABLE:
177  w->setEnabled (up.enable_is ("on"));
178  break;
179 
180  case uicontrol::properties::ID_TOOLTIPSTRING:
181  w->setToolTip (Utils::fromStdString (up.get_tooltipstring ()));
182  break;
183 
184  case base_properties::ID_VISIBLE:
185  w->setVisible (up.is_visible ());
186  break;
187 
188  case uicontrol::properties::ID_KEYPRESSFCN:
189  m_keyPressHandlerDefined = ! up.get_keypressfcn ().isempty ();
190  break;
191 
192  case uicontrol::properties::ID___FOCUS__:
193  if (up.is___focus__ ())
194  w->setFocus ();
195  else
196  w->clearFocus ();
197  break;
198 
199  default:
200  break;
201  }
202  }
203 
204  bool
205  BaseControl::eventFilter (QObject *watched, QEvent *xevent)
206  {
208 
209  switch (xevent->type ())
210  {
211  case QEvent::Resize:
212  if (m_normalizedFont)
213  {
214  octave::autolock guard (gh_mgr.graphics_lock ());
215 
216  qWidget<QWidget> ()->setFont (Utils::computeFont<uicontrol>
217  (properties<uicontrol> ()));
218  }
219  break;
220 
221  case QEvent::MouseButtonPress:
222  {
223  octave::autolock guard (gh_mgr.graphics_lock ());
224 
225  QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);
226  graphics_object go = object ();
227  uicontrol::properties& up = Utils::properties<uicontrol> (go);
228  graphics_object fig = go.get_ancestor ("figure");
229  if (fig)
230  {
231  emit gh_set_event (fig.get_handle (), "currentobject",
232  m_handle.value (), false);
233 
234  if (m->button () != Qt::LeftButton || ! up.enable_is ("on"))
235  {
236  emit gh_set_event (fig.get_handle (), "selectiontype",
237  Utils::figureSelectionType (m), false);
238  emit gh_set_event (fig.get_handle (), "currentpoint",
240  false);
241  emit gh_callback_event (fig.get_handle (),
242  "windowbuttondownfcn");
243  emit gh_callback_event (m_handle, "buttondownfcn");
244 
245  if (m->button () == Qt::RightButton)
246  ContextMenu::executeAt (m_interpreter, up, m->globalPos ());
247  }
248  else
249  {
250  if (up.style_is ("listbox"))
251  emit gh_set_event (fig.get_handle (), "selectiontype",
253  false);
254  else
255  emit gh_set_event (fig.get_handle (), "selectiontype",
256  octave_value ("normal"), false);
257  }
258  }
259  }
260  break;
261 
262  case QEvent::MouseMove:
263  if (qWidget<QWidget> ()->hasMouseTracking ())
264  {
265  octave::autolock guard (gh_mgr.graphics_lock ());
266 
267  QMouseEvent *m = dynamic_cast<QMouseEvent *> (xevent);
268  graphics_object go = object ();
269  graphics_object fig = go.get_ancestor ("figure");
270 
271  if (fig)
272  {
273  emit gh_set_event (fig.get_handle (), "currentpoint",
274  Utils::figureCurrentPoint (fig, m), false);
275  emit gh_callback_event (fig.get_handle (),
276  "windowbuttonmotionfcn");
277  }
278  }
279  break;
280 
281  case QEvent::KeyPress:
283  {
284  octave::autolock guard (gh_mgr.graphics_lock ());
285 
286  octave_scalar_map keyData =
287  Utils::makeKeyEventStruct (dynamic_cast<QKeyEvent *> (xevent));
288  graphics_object fig = object ().get_ancestor ("figure");
289 
290  emit gh_set_event (fig.get_handle (), "currentcharacter",
291  keyData.getfield ("Character"), false);
292  emit gh_callback_event (m_handle, "keypressfcn", keyData);
293  }
294  break;
295 
296  case QEvent::FocusIn:
297  emit gh_set_event (m_handle, "__focus__", "on", false);
298  break;
299 
300  case QEvent::FocusOut:
301  emit gh_set_event (m_handle, "__focus__", "off", false);
302  break;
303 
304  default:
305  break;
306  }
307 
308  return Object::eventFilter (watched, xevent);
309  }
310 
311 }
Definition: dMatrix.h:42
BaseControl(octave::base_qobject &oct_qobj, octave::interpreter &interp, const graphics_object &go, QWidget *w)
Definition: BaseControl.cc:99
void init(QWidget *w, bool callBase=false)
Definition: BaseControl.cc:110
bool eventFilter(QObject *watched, QEvent *e)
Definition: BaseControl.cc:205
void update(int pId)
Definition: BaseControl.cc:142
static void executeAt(octave::interpreter &interp, const base_properties &props, const QPoint &pt)
Definition: ContextMenu.cc:123
graphics_object object(void) const
Definition: Object.cc:83
octave::interpreter & m_interpreter
Definition: Object.h:140
void gh_callback_event(const graphics_handle &h, const std::string &name)
void init(QObject *obj, bool callBase=false)
Definition: Object.cc:62
graphics_handle m_handle
Definition: Object.h:157
void gh_set_event(const graphics_handle &h, const std::string &name, const octave_value &value)
virtual QObject * qObject(void)
Definition: Object.h:82
octave::mutex graphics_lock(void)
Definition: graphics.in.h:6393
graphics_object get_ancestor(const std::string &type) const
Definition: graphics.cc:3905
graphics_handle get_handle(void) const
Definition: graphics.in.h:2815
Base class for Octave interfaces that use Qt.
gh_manager & get_gh_manager(void)
Definition: interpreter.h:295
double value(void) const
Definition: oct-handle.h:78
octave_value getfield(const std::string &key) const
Definition: oct-map.cc:183
Matrix get_boundingbox(bool internal=false, const Matrix &parent_pix_size=Matrix()) const
Definition: graphics.cc:10933
T octave_idx_type m
Definition: mx-inlines.cc:773
std::complex< double > w(std::complex< double > z, double relerr=0)
QColor fromRgb(const Matrix &rgb)
template QFont computeFont< uicontrol >(const uicontrol::properties &props, int height)
std::string figureSelectionType(QMouseEvent *event, bool isDoubleClick)
octave_scalar_map makeKeyEventStruct(QKeyEvent *event)
Matrix figureCurrentPoint(const graphics_object &fig, QMouseEvent *event)
QString fromStdString(const std::string &s)
static void updatePalette(const uicontrol::properties &props, QWidget *w)
Definition: BaseControl.cc:46
double round(double x)
Definition: lo-mappers.h:136