GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ListBoxControl.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 <QListWidget>
31 #include <QEvent>
32 #include <QMouseEvent>
33 
34 #include "Container.h"
35 #include "ListBoxControl.h"
36 #include "QtHandlesUtils.h"
37 
38 #include "octave-qobject.h"
39 
40 namespace QtHandles
41 {
42 
43  static void
44  updateSelection (QListWidget *list, const Matrix& value)
45  {
46  octave_idx_type n = value.numel ();
47  int lc = list->count ();
48 
49  list->clearSelection ();
50 
51  for (octave_idx_type i = 0; i < n; i++)
52  {
53  int idx = octave::math::round (value(i));
54 
55  if (1 <= idx && idx <= lc)
56  {
57  list->item (idx-1)->setSelected (true);
58  list->scrollToItem (list->item (idx-1));
59  if (i == 0
60  && list->selectionMode () == QAbstractItemView::SingleSelection)
61  break;
62  }
63  else
64  {
65  // Invalid selection.
66  list->clearSelection ();
67  break;
68  }
69  }
70  }
71 
72  ListBoxControl*
74  octave::interpreter& interp,
75  const graphics_object& go)
76  {
77  Object *parent = parentObject (interp, go);
78 
79  if (parent)
80  {
81  Container *container = parent->innerContainer ();
82 
83  if (container)
84  return new ListBoxControl (oct_qobj, interp, go,
85  new QListWidget (container));
86  }
87 
88  return nullptr;
89  }
90 
92  octave::interpreter& interp,
93  const graphics_object& go, QListWidget *list)
94  : BaseControl (oct_qobj, interp, go, list), m_blockCallback (false),
95  m_selectionChanged (false)
96  {
97  uicontrol::properties& up = properties<uicontrol> ();
98 
99  list->addItems (Utils::fromStringVector (up.get_string_vector ()));
100  if ((up.get_max () - up.get_min ()) > 1)
101  list->setSelectionMode (QAbstractItemView::ExtendedSelection);
102  else
103  list->setSelectionMode (QAbstractItemView::SingleSelection);
104  Matrix value = up.get_value ().matrix_value ();
105  if (value.numel () > 0)
106  {
107  octave_idx_type n = value.numel ();
108  int lc = list->count ();
109 
110  for (octave_idx_type i = 0; i < n; i++)
111  {
112  int idx = octave::math::round (value(i));
113 
114  if (1 <= idx && idx <= lc)
115  {
116  list->item (idx-1)->setSelected (true);
117  list->scrollToItem (list->item (idx-1));
118  if (i == 0 && (list->selectionMode ()
119  == QAbstractItemView::SingleSelection))
120  break;
121  }
122  }
123  }
124 
125  list->viewport ()->installEventFilter (this);
126 
127  connect (list, SIGNAL (itemSelectionChanged (void)),
128  SLOT (itemSelectionChanged (void)));
129  connect (list, SIGNAL (activated (const QModelIndex &)),
130  SLOT (itemActivated (const QModelIndex &)));
131  connect (list, SIGNAL (itemPressed (QListWidgetItem*)),
132  SLOT (itemPressed (QListWidgetItem*)));
133  }
134 
136  { }
137 
138  void
140  {
141  uicontrol::properties& up = properties<uicontrol> ();
142  QListWidget *list = qWidget<QListWidget> ();
143 
144  switch (pId)
145  {
146  case uicontrol::properties::ID_STRING:
147  m_blockCallback = true;
148  list->clear ();
149  list->addItems (Utils::fromStringVector (up.get_string_vector ()));
150  updateSelection (list, up.get_value ().matrix_value ());
151  m_blockCallback = false;
152  break;
153 
154  case uicontrol::properties::ID_MIN:
155 
156  case uicontrol::properties::ID_MAX:
157  if ((up.get_max () - up.get_min ()) > 1)
158  list->setSelectionMode (QAbstractItemView::ExtendedSelection);
159  else
160  list->setSelectionMode (QAbstractItemView::SingleSelection);
161  break;
162 
163  case uicontrol::properties::ID_VALUE:
164  m_blockCallback = true;
165  updateSelection (list, up.get_value ().matrix_value ());
166  m_blockCallback = false;
167  break;
168 
169  default:
170  BaseControl::update (pId);
171  break;
172  }
173  }
174 
175  void
177  {
178  if (! m_blockCallback)
179  {
180  QListWidget *list = qWidget<QListWidget> ();
181 
182  QModelIndexList l = list->selectionModel ()->selectedIndexes ();
183  Matrix value (dim_vector (1, l.size ()));
184  int i = 0;
185 
186  for (const auto& idx : l)
187  value(i++) = idx.row () + 1;
188 
189  emit gh_set_event (m_handle, "value", octave_value (value), false);
190  emit gh_callback_event (m_handle, "callback");
191  }
192 
193  m_selectionChanged = false;
194  }
195 
196  void
198  {
199  if (! m_blockCallback)
200  m_selectionChanged = true;
201  }
202 
203  void
204  ListBoxControl::itemActivated (const QModelIndex &)
205  {
206  m_selectionChanged = true;
207  }
208  void
209  ListBoxControl::itemPressed (QListWidgetItem*)
210  {
211  m_selectionChanged = true;
212  }
213 
214  bool
215  ListBoxControl::eventFilter (QObject *watched, QEvent *e)
216  {
217  // listbox change
218  if (watched == m_qobject)
219  {
220  switch (e->type ())
221  {
222  case QEvent::KeyRelease:
223  if (m_selectionChanged)
225  m_selectionChanged = false;
226  break;
227 
228  default:
229  break;
230  }
231 
232  return Object::eventFilter (watched, e);
233  }
234  // listbox viewport
235  else
236  {
237  bool override_return = false;
238  QListWidget *list = qWidget<QListWidget> ();
239 
240  switch (e->type ())
241  {
242  case QEvent::MouseButtonPress:
243  {
244  QMouseEvent *m = dynamic_cast<QMouseEvent *> (e);
245 
246  if (m->button () & Qt::RightButton)
247  override_return = true;
248  else
249  {
250  if (! list->indexAt (m->pos ()).isValid ())
251  override_return = true;
252  m_selectionChanged = true;
253  }
254  break;
255  }
256  case QEvent::MouseButtonRelease:
257  {
258  QMouseEvent *m = dynamic_cast<QMouseEvent *> (e);
259 
260  if (m->button () & Qt::RightButton)
261  override_return = true;
262 
263  else if (! list->indexAt (m->pos ()).isValid ())
264  {
265  list->setCurrentRow (list->count () - 1);
266  override_return = true;
267  }
268 
269  if (m_selectionChanged)
271  m_selectionChanged = false;
272 
273  break;
274  }
275  default:
276  break;
277 
278  }
279  return BaseControl::eventFilter (watched, e) || override_return;
280  }
281  }
282 }
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:377
Definition: dMatrix.h:42
RowVector row(octave_idx_type i) const
Definition: dMatrix.cc:416
bool eventFilter(QObject *watched, QEvent *e)
Definition: BaseControl.cc:205
void update(int pId)
Definition: BaseControl.cc:142
void itemPressed(QListWidgetItem *)
bool eventFilter(QObject *watched, QEvent *e)
ListBoxControl(octave::base_qobject &oct_qobj, octave::interpreter &interp, const graphics_object &go, QListWidget *list)
static ListBoxControl * create(octave::base_qobject &oct_qobj, octave::interpreter &interp, const graphics_object &go)
void itemActivated(const QModelIndex &)
QObject * m_qobject
Definition: Object.h:159
virtual Container * innerContainer(void)=0
static Object * parentObject(octave::interpreter &interp, const graphics_object &go)
Definition: Object.cc:201
void gh_callback_event(const graphics_handle &h, const std::string &name)
graphics_handle m_handle
Definition: Object.h:157
void gh_set_event(const graphics_handle &h, const std::string &name, const octave_value &value)
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
Base class for Octave interfaces that use Qt.
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
QStringList fromStringVector(const string_vector &v)
static void updateSelection(QListWidget *list, const Matrix &value)
double round(double x)
Definition: lo-mappers.h:136