GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
Menu.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2011-2022 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 <QAction>
31#include <QMainWindow>
32#include <QMenu>
33#include <QMenuBar>
34
35#include "Figure.h"
36#include "Menu.h"
37#include "QtHandlesUtils.h"
38
39#include "octave-qobject.h"
40
41namespace octave
42{
43
44 static QKeySequence
46 {
47 std::string s (up.get_accelerator ());
48
49 if (! s.empty ())
50 {
51 char c = s[0];
52 int keyMod = Qt::CTRL;
53
54 if (c >= 'A' && c <= 'Z')
55 keyMod |= Qt::SHIFT;
56 if (c >= 'a' && c <= 'z')
57 c -= ('a' - 'A');
58 if (c >= 'A' && c <= 'Z')
59 return QKeySequence (keyMod | static_cast<int> (c));
60 }
61
62 return QKeySequence ();
63 }
64
65 Menu *
66 Menu::create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
67 const graphics_object& go)
68 {
69 Object *parent_obj = parentObject (interp, go);
70
71 if (parent_obj)
72 {
73 QObject *qObj = parent_obj->qObject ();
74
75 if (qObj)
76 return new Menu (oct_qobj, interp, go, new QAction (qObj),
77 parent_obj);
78 }
79
80 return nullptr;
81 }
82
83 Menu::Menu (octave::base_qobject& oct_qobj, octave::interpreter& interp,
84 const graphics_object& go, QAction *action, Object *xparent)
85 : Object (oct_qobj, interp, go, action), m_parent (nullptr),
86 m_separator (nullptr)
87 {
88 uimenu::properties& up = properties<uimenu> ();
89
90 action->setText (Utils::fromStdString (up.get_text ()));
91
92 if (up.is_checked ())
93 {
94 action->setCheckable (true);
95 action->setChecked (up.is_checked ());
96 }
97
98 action->setEnabled (up.is_enable ());
99 action->setShortcut (accelSequence (up));
100 action->setVisible (up.is_visible ());
101
102 if (up.is_separator ())
103 {
104 m_separator = new QAction (action);
105 m_separator->setSeparator (true);
106 m_separator->setVisible (up.is_visible ());
107 }
108
109 MenuContainer *menuContainer = dynamic_cast<MenuContainer *> (xparent);
110
111 if (menuContainer)
112 m_parent = menuContainer->menu ();
113
114 if (m_parent)
115 {
116 int pos = static_cast<int> (up.get_position ());
117
118 if (pos <= 0)
119 {
120 if (m_separator)
121 m_parent->insertAction (nullptr, m_separator);
122 m_parent->insertAction (nullptr, action);
123
124 int count = 0;
125
126 for (auto *a : m_parent->actions ())
127 if (! a->isSeparator ())
128 count++;
129
130 up.get_property ("position").set
131 (octave_value (static_cast<double> (count)), true, false);
132 }
133 else
134 {
135
136 int count = 0;
137 QAction *before = nullptr;
138
139 for (auto *a : m_parent->actions ())
140 {
141 if (! a->isSeparator ())
142 {
143 count++;
144 if (pos <= count)
145 {
146 before = a;
147 break;
148 }
149 }
150 }
151
152 if (m_separator)
153 m_parent->insertAction (before, m_separator);
154 m_parent->insertAction (before, action);
155
156 if (before)
158 else
159 up.get_property ("position").set
160 (octave_value (static_cast<double> (count+1)), true, false);
161 }
162 }
163
164 connect (action, &QAction::triggered, this, &Menu::actionTriggered);
165 }
166
168 { }
169
170 void
171 Menu::update (int pId)
172 {
173 uimenu::properties& up = properties<uimenu> ();
174 QAction *action = qWidget<QAction> ();
175
176 switch (pId)
177 {
178 case uimenu::properties::ID_TEXT:
179 action->setText (Utils::fromStdString (up.get_text ()));
180 break;
181
182 case uimenu::properties::ID_CHECKED:
183 if (up.is_checked ())
184 {
185 action->setCheckable (true);
186 action->setChecked (up.is_checked ());
187 }
188 else
189 {
190 action->setChecked (false);
191 action->setCheckable (false);
192 }
193 break;
194
195 case uimenu::properties::ID_ENABLE:
196 action->setEnabled (up.is_enable ());
197 break;
198
199 case uimenu::properties::ID_ACCELERATOR:
200 if (! action->menu ())
201 action->setShortcut (accelSequence (up));
202 break;
203
204 case uimenu::properties::ID_SEPARATOR:
205 if (up.is_separator ())
206 {
207 if (! m_separator)
208 {
209 m_separator = new QAction (action);
210 m_separator->setSeparator (true);
211 m_separator->setVisible (up.is_visible ());
212 if (m_parent)
213 m_parent->insertAction (action, m_separator);
214 }
215 }
216 else
217 {
218 if (m_separator)
219 delete m_separator;
220 m_separator = nullptr;
221 }
222 break;
223
224 case uimenu::properties::ID_VISIBLE:
225 action->setVisible (up.is_visible ());
226 if (m_separator)
227 m_separator->setVisible (up.is_visible ());
228 break;
229
230 case uimenu::properties::ID_POSITION:
231 {
232 if (m_separator)
233 m_parent->removeAction (m_separator);
234
235 m_parent->removeAction (action);
236
237 int pos = static_cast<int> (up.get_position ());
238 QAction *before = nullptr;
239
240 if (pos > 0)
241 {
242 int count = 0;
243
244 for (auto *a : m_parent->actions ())
245 {
246 if (! a->isSeparator ())
247 {
248 count++;
249 if (pos <= count)
250 {
251 before = a;
252 break;
253 }
254 }
255 }
256 }
257
258 if (m_separator)
259 m_parent->insertAction (before, m_separator);
260
261 m_parent->insertAction (before, action);
262
264 }
265 break;
266
267 default:
268 Object::update (pId);
269 break;
270 }
271 }
272
273 QWidget *
275 {
276 QAction *action = qWidget<QAction> ();
277 QMenu *action_menu = action->menu ();
278
279 if (! action_menu)
280 {
281 action_menu = new QMenu (action->parentWidget ());
282 action->setMenu (action_menu);
283 action->setShortcut (QKeySequence ());
284 connect (action_menu, &QMenu::aboutToShow, this, &Menu::actionHovered);
285 }
286
287 return action_menu;
288 }
289
290 void
292 {
293 QAction *action = qWidget<QAction> ();
294
295 if (action->isCheckable ())
296 action->setChecked (! action->isChecked ());
297 emit gh_callback_event (m_handle, "callback");
298 }
299
300 void
302 {
303 emit gh_callback_event (m_handle, "callback");
304 }
305
306 void
308 {
309 if (m_parent)
310 {
311 double count = 1.0;
312
313 for (auto *a : m_parent->actions ())
314 {
315 if (! a->isSeparator ())
316 {
317 Object *aObj = Object::fromQObject (a);
318
319 if (aObj)
320 {
321 graphics_object go = aObj->object ();
322
323 // Probably overkill as a uimenu child can only be another
324 // uimenu object.
325 if (go.isa ("uimenu"))
326 {
327 uimenu::properties& up = Utils::properties<uimenu> (go);
328
329 up.get_property ("position").set
330 (octave_value (count), true, false);
331 }
332 }
333
334 count++;
335 }
336 }
337 }
338 }
339
340}
virtual QWidget * menu(void)=0
Menu(octave::base_qobject &oct_qobj, octave::interpreter &interp, const graphics_object &go, QAction *action, Object *parent)
Definition: Menu.cc:83
void actionTriggered(void)
Definition: Menu.cc:291
QWidget * m_parent
Definition: Menu.h:73
void updateSiblingPositions(void)
Definition: Menu.cc:307
void actionHovered(void)
Definition: Menu.cc:301
QWidget * menu(void)
Definition: Menu.cc:274
~Menu(void)
Definition: Menu.cc:167
static Menu * create(octave::base_qobject &oct_qobj, octave::interpreter &interp, const graphics_object &go)
Definition: Menu.cc:66
QAction * m_separator
Definition: Menu.h:74
void update(int pId)
Definition: Menu.cc:171
void gh_callback_event(const graphics_handle &h, const std::string &name)
virtual void update(int pId)
Definition: Object.cc:164
static Object * fromQObject(QObject *obj)
Definition: Object.cc:214
graphics_handle m_handle
Definition: Object.h:157
virtual QObject * qObject(void)
Definition: Object.h:82
graphics_object object(void) const
Definition: Object.cc:83
static Object * parentObject(octave::interpreter &interp, const graphics_object &go)
Definition: Object.cc:201
Base class for Octave interfaces that use Qt.
const Qt::KeyboardModifier CTRL
QString fromStdString(const std::string &s)
T::properties & properties(graphics_object obj)
static QKeySequence accelSequence(const uimenu::properties &up)
Definition: Menu.cc:45