NDEVR
API Documentation
QCustomCombobox.h
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Widgets
28File: QCustomComboBox
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include "DLLInfo.h"
34#include <NDEVR/QCustomValidator.h>
35#include <NDEVR/QCustomLineEdit.h>
36#include <NDEVR/QTTools.h>
37#include <NDEVR/BufferBase.h>
38#include <NDEVR/Dictionary.h>
39#include <NDEVR/String.h>
40#include <NDEVR/Resource.h>
41#include <QComboBox>
42namespace NDEVR
43{
44 class QCustomValidator;
45 class QCustomLineEdit;
54 class NDEVR_WIDGETS_API QCustomComboBox : public QComboBox
55 {
56 Q_OBJECT
57 public:
62 QCustomComboBox(QWidget* parent = nullptr);
77 void setCustomValidator(const QCustomValidator& validator);
90 void setup(const TranslatedString& title, const Buffer<String>& values, const Buffer<TranslatedString>& display_values);
95 bool isUsingCustom() const { return m_using_custom; }
96
102 template<class t_object>
103 void setup(const TranslatedString& title, const Buffer<std::pair<TranslatedString, t_object>>& items)
104 {
106 Buffer<TranslatedString> display_values;
107 for (uint04 i = 0; i < items.size(); i++)
108 {
109 values.add(String(items[i].second));
110 display_values.add(items[i].first);
111 }
112 setup(title, values, display_values);
113 }
114
119 template<class t_object>
120 void setup(const TranslatedString& title, const Buffer<std::pair<String, t_object>>& items)
121 {
123 Buffer<TranslatedString> display_values;
124 for (uint04 i = 0; i < items.size(); i++)
125 {
126 values.add(String(items[i].second));
127 display_values.add(TranslatedString::DirectString(items[i].first));
128 }
129 setup(title, values, display_values);
130 }
131
136 template<class t_object>
137 typename std::enable_if<ObjectInfo<t_object>::Enum>::type setup(const TranslatedString& title, const Buffer<t_object>& items)
138 {
140 Buffer<TranslatedString> display_values;
141 for (uint04 i = 0; i < items.size(); i++)
142 {
143 values.add(String(items[i]));
144 display_values.add(String::DisplayString(items[i]));
145 }
146 setup(title, values, display_values);
147 }
148
153 template<class t_object>
154 typename std::enable_if<ObjectInfo<t_object>::Number>::type setup(const TranslatedString& title, const Buffer<t_object>& items)
155 {
157 Buffer<TranslatedString> display_values;
158 for (uint04 i = 0; i < items.size(); i++)
159 {
160 values.add(String(items[i]));
161 StringAllocatingView s = StringAllocatingView::Allocate(items[i]);
162 customValidator().fixup(s, true, false);
163 display_values.add(TranslatedString(s));
164 }
165 setup(title, values, display_values);
166 }
167
172 template<class t_enum>
173 typename std::enable_if<ObjectInfo<t_enum>::Enum>::type setup(const TranslatedString& title, uint04 size)
174 {
175 setTitle(title);
176 m_values.clear();
177 index_to_enum.clear();
178 for (uint04 i = 0; i < size; i++)
179 {
182 index_to_enum[i] = i;
183 enum_to_index[i] = i;
184 }
186 }
187
192 template<class t_object>
193 typename std::enable_if<!ObjectInfo<t_object>::Enum && !ObjectInfo<t_object>::Number>::type setup(const TranslatedString& title, const Buffer<t_object>& items)
194 {
196 Buffer<TranslatedString> display_values;
197 for (uint04 i = 0; i < items.size(); i++)
198 {
199 values.add(String(items[i]));
200 display_values.add(String::DisplayString(items[i]));
201 }
202 setup(title, values, display_values);
203 }
204
210 template<class t_enum>
211 typename std::enable_if<ObjectInfo<t_enum>::Enum>::type setup(const TranslatedString& title, t_enum first, t_enum last)
212 {
213 setTitle(title);
214 m_values.clear();
215 for (uint04 i = 0; i <= cast<uint04>(last) - cast<uint04>(first); i++)
216 {
217 m_values.add(String(cast<t_enum>(i + cast<uint04>(first))));
219 index_to_enum[i] = i + cast<uint04>(first);
220 enum_to_index[i + cast<uint04>(first)] = i;
221 }
223 }
224
230 template<class t_type>
231 void add(const t_type& value, const TranslatedString& display_value, bool refresh_widget = false)
232 {
233 m_values.add(String(value));
234 m_display_values.add(display_value);
235 if (refresh_widget)
236 refresh();
237 }
238
243 template<class t_type>
244 void remove(const t_type& value, bool refresh_widget = false)
245 {
246 uint04 index = m_values.indexOf(String(value));
247 if (IsValid(index))
248 {
249 m_values.removeIndex(index);
250 m_display_values.removeIndex(index);
251 if (refresh_widget)
252 refresh();
253 }
254 }
255
258 void refresh()
259 {
261 updateGeometry();
262 }
263
271 template<class t_type>
272 void setupResource(const TranslatedString& title, Resource<t_type>& resource)
273 {
274 setTitle(title);
275 connect(this, &QCustomComboBox::edited, this, [this, &resource]
276 {
277 if (!customValidator().unit().isNull())
278 resource.set(LineEditResourceSetter<t_type, ObjectInfo<t_type>::Number>::ValueFromFloat(getUnitValue()));
279 else
280 resource.set(getAs<t_type>());
281 });
284 m_resource_changed_listener = new QTResourceListener([this, &resource]
285 {
286 if (!customValidator().unit().isNull())
287 setUnitValue(LineEditResourceSetter<t_type, ObjectInfo<t_type>::Number>::ValueToFloat(resource.get()));
288 else
289 setValue(resource.get());
290 }, this);
292 }
293
298 void setAutoFormat(bool auto_format) { m_auto_format = auto_format; }
303 template<class t_enum>
304 typename std::enable_if<ObjectInfo<t_enum>::Enum>::type set(t_enum value)
305 {
306 setCurrentIndex(enum_to_index[cast<uint04>(value)]);
307 }
308
312 template<class t_type>
313 t_type getAs() const
314 {
315 if(m_using_custom || currentIndex() == -1 || m_values.size() <= cast<uint04>(currentIndex()))
316 return m_current_custom.template getAs<t_type>();
317 return m_values[currentIndex()].template getAs<t_type>();
318 }
319
324 template<class t_type>
325 t_type getAs(uint04 index) const
326 {
327 return m_values[index].template getAs<t_type>();
328 }
329
333 template<class t_type>
334 void setValue(const t_type& t_value)
335 {
336 setValue(String(t_value));
337 }
338
342 void setValue(const TranslatedString& t_value)
343 {
344 setValue(String(t_value));
345 lib_assert(!isUsingCustom() || t_value == _t("Custom"), "unexpect custom translated string");
346 }
347
356 void setTitle(const TranslatedString& title);
365 QSize minimumSizeHint() const override;
370 QSize sizeHint() const override;
385 void setValue(const String& value);
390 void setToolTip(const TranslatedString& tooltip);
396 void setUnitType(UnitCategory unit, uint01 dimension = Constant<uint01>::Invalid);
402 void setConstantUnit(const ConstPointer<Unit>& unit, uint01 dimension = Constant<uint01>::Invalid);
409 void setCustomUnit(const StringView& unit, UnitCategory fallback_unit, uint01 dimension = Constant<uint01>::Invalid);
415 void setUnitValue(fltp08 value, uint01 unit_dimension = 0);
420 void setAllowCustom(bool allow_custom) { m_allow_custom = allow_custom; refreshWidget(); }
430 const TranslatedString& suffix() const { return m_suffix; }
435 void focusInEvent(QFocusEvent* e) override;
445 bool event(QEvent* event) override;
451 void sortAlphabetically(uint04 start = 0, uint04 size = Constant<uint04>::Invalid);
456 const Buffer<String>& values() const { return m_values; }
465 void showPopup() override;
469 void hidePopup() override;
474 void resizeEvent(QResizeEvent* event) override;
479 void paintEvent(QPaintEvent*) override;
484 void wheelEvent(QWheelEvent* e) override;
489 protected:
502 virtual void onSorted(const Buffer<uint04>& swap_indices);
503 protected slots:
507 void onEdit();
515 void onChange();
516 signals:
520 void edited();
521 private:
525 void _updateTooltip();
526 protected:
527 bool m_is_refreshing = false;
528 bool m_is_changing = false;
533 bool m_is_showing_popup = false;
547 };
548}
Stores an angle in an optimized internal format with support for efficient trigonometric operations.
Definition Angle.h:83
The equivelent of std::vector but with a bit more control.
Definition Buffer.hpp:58
void add(t_type &&object)
Adds object to the end of the buffer.
Definition Buffer.hpp:190
Provides a constant, unmodifiable pointer that has shared ownership of a dynamically allocated object...
Definition Pointer.hpp:276
A hash-based key-value store, useful for quick associative lookups.
Definition Dictionary.h:64
A basic class for helping convert a Value into a resource.
void setCustomUnit(const StringView &unit, UnitCategory fallback_unit, uint01 dimension=Constant< uint01 >::Invalid)
Sets a custom unit string with a fallback unit category.
void setCustomValidator(const QCustomValidator &validator)
Sets the custom validator used for input validation and formatting.
uint04 m_sort_offset
The starting index offset for alphabetical sorting.
bool isUsingCustom() const
Returns whether the combo box is currently using a custom (user-entered) value.
void setUnitType(UnitCategory unit, uint01 dimension=Constant< uint01 >::Invalid)
Sets the unit type used for value formatting and conversion.
void add(const t_type &value, const TranslatedString &display_value, bool refresh_widget=false)
Adds a value and its display string to the combo box.
bool m_allow_custom
Whether custom user-entered values are permitted.
fltp08 getUnitValue() const
Returns the current value as a floating-point number in user-facing units.
QCustomLineEdit * m_line_edit
The embedded line edit for custom value entry.
std::enable_if< ObjectInfo< t_enum >::Enum >::type setup(const TranslatedString &title, uint04 size)
Sets up the combo box with all values of an enum type, given the total count.
Buffer< String > m_values
The internal string values for each option.
void edited()
Emitted when the combo box value is edited by the user.
void setup(const TranslatedString &title, const Buffer< String > &values, const Buffer< TranslatedString > &display_values)
Sets up the combo box with a title, raw values, and corresponding translated display values.
void setValue(const t_type &t_value)
Sets the current value of the combo box.
void hidePopup() override
Hides the popup list of items.
void setValue(const String &value)
Sets the current value from a raw String.
void setup(const TranslatedString &title, const Buffer< std::pair< String, t_object > > &items)
Sets up the combo box from a buffer of String/value pairs.
void sortAlphabetically(uint04 start=0, uint04 size=Constant< uint04 >::Invalid)
Sorts the combo box entries alphabetically by display value.
TranslatedString currentDisplayValue() const
Returns the currently displayed translated string.
bool event(QEvent *event) override
Handles generic events for the combo box, including tooltip and theme updates.
std::enable_if< ObjectInfo< t_object >::Enum >::type setup(const TranslatedString &title, const Buffer< t_object > &items)
Sets up the combo box from a buffer of enum values, using display strings for each.
TranslatedString m_suffix
A suffix appended to each display value.
QCustomComboBox(QWidget *parent=nullptr)
Constructs a QCustomComboBox with the given parent widget.
QCustomValidator & customValidator()
Returns a mutable reference to the custom validator used for input validation.
bool m_is_changing
Whether the selection is currently being changed programmatically.
void setAllowCustom(bool allow_custom)
Sets whether the user can enter a custom value not in the predefined list.
void wheelEvent(QWheelEvent *e) override
Handles mouse wheel events, typically to scroll through values.
void setValue(const TranslatedString &t_value)
Sets the current value from a TranslatedString.
std::enable_if< ObjectInfo< t_enum >::Enum >::type set(t_enum value)
Sets the current selection to the given enum value.
void setTitle(const TranslatedString &title)
Sets the display title for the combo box.
void refreshWidget()
Rebuilds the widget contents from the internal value and display buffers.
void focusInEvent(QFocusEvent *e) override
Handles focus-in events for the combo box.
void adjustLineEditSize()
Adjusts the embedded line edit size to fit the current combo box dimensions.
Buffer< TranslatedString > m_display_values
The translated display strings for each option.
void paintEvent(QPaintEvent *) override
Custom paint event for rendering the combo box.
const TranslatedString & suffix() const
Returns the current suffix appended to display values.
void onEditTextChangedSlot()
Slot invoked when the editable line edit text changes.
bool m_using_custom
Whether the current selection is a custom value.
void setup(const TranslatedString &title, const Buffer< TranslatedString > &values)
Sets up the combo box with a title and a list of translated display values.
QTResourceListener * m_resource_changed_listener
Listener for external resource changes.
std::enable_if<!ObjectInfo< t_object >::Enum &&!ObjectInfo< t_object >::Number >::type setup(const TranslatedString &title, const Buffer< t_object > &items)
Sets up the combo box from a buffer of non-enum, non-number values using display strings.
Dictionary< uint04, uint04 > index_to_enum
Maps combo box indices to enum numeric values.
uint04 m_last_index
The last selected index before the current change.
QSize minimumSizeHint() const override
Returns the minimum size hint for layout purposes.
bool m_is_showing_popup
Whether the popup list is currently visible.
void setAutoFormat(bool auto_format)
Sets whether the combo box should automatically format display values.
void showPopup() override
Shows the popup list of items.
TranslatedString m_tooltip
The tooltip text for the combo box.
t_type getAs() const
Returns the current value converted to the requested type.
const Buffer< String > & values() const
Returns the internal string values of the combo box.
bool m_sort_alphabetically
Whether items should be sorted alphabetically.
Dictionary< uint04, uint04 > enum_to_index
Maps enum numeric values to combo box indices.
void setUnitValue(fltp08 value, uint01 unit_dimension=0)
Sets the value as a floating-point number in user-facing units.
void remove(const t_type &value, bool refresh_widget=false)
Removes a value and its corresponding display string from the combo box.
Angle< fltp08 > getUnitAngle() const
Returns the current value as an Angle in internal representation.
void lockInCustomValue()
Locks in the current custom value as the definitive selection.
uint04 m_custom_index
The index of the custom value entry in the list.
bool m_is_refreshing
Whether the widget is currently being refreshed.
void resizeEvent(QResizeEvent *event) override
Handles widget resize events.
void updateFontSize()
Updates the font size to match the current application theme settings.
void refresh()
Refreshes the widget contents and updates its geometry.
bool m_auto_format
Whether values are automatically formatted before display.
String m_current_custom
The current custom value entered by the user.
t_type getAs(uint04 index) const
Returns the value at the given index converted to the requested type.
void setConstantUnit(const ConstPointer< Unit > &unit, uint01 dimension=Constant< uint01 >::Invalid)
Sets a constant unit for value formatting and conversion.
std::enable_if< ObjectInfo< t_object >::Number >::type setup(const TranslatedString &title, const Buffer< t_object > &items)
Sets up the combo box from a buffer of numeric values, formatting each with the validator.
void setSuffix(const TranslatedString &suffix)
Sets a suffix appended to each display value.
std::enable_if< ObjectInfo< t_enum >::Enum >::type setup(const TranslatedString &title, t_enum first, t_enum last)
Sets up the combo box with a range of enum values from first to last (inclusive).
QSize sizeHint() const override
Returns the recommended size for layout purposes.
void onEdit()
Slot invoked when the user finishes editing the custom line edit.
void setup(const TranslatedString &title, const Buffer< std::pair< TranslatedString, t_object > > &items)
Sets up the combo box from a buffer of TranslatedString/value pairs.
virtual void onSorted(const Buffer< uint04 > &swap_indices)
Called after sorting to allow subclasses to react to reordered indices.
void setToolTip(const TranslatedString &tooltip)
Sets the tooltip text for the combo box.
void clearValue()
Clears the current selection and value.
const Buffer< TranslatedString > & displayValues() const
Returns the translated display values of the combo box.
void setupResource(const TranslatedString &title, Resource< t_type > &resource)
Sets up two-way binding between this combo box and a Resource.
const QCustomValidator & customValidator() const
Returns a const reference to the custom validator used for input validation.
void onChange()
Slot invoked when the selected index changes.
TranslatedString m_title
The display title of the combo box.
A line edit allows users to enter and edit a single line of plain text with useful editing functions,...
Responsible on most user input fields for correcting the input when possible or allerting the user th...
A ResourceListener which will always be executed on the main UI thread and can be tied to a Qt Object...
Definition QTTools.h:493
ResourceListener * addListener(ResourceListener *listener) const
Adds a listener that will be notified when this resource changes.
A core part of the engine, stores variables that can be listened to with ResourceListener which will ...
Definition Resource.h:42
void set(const T &info, bool check_equal=true)
Destructor.
Definition Resource.h:62
const T & get() const
Returns a const reference to the stored value.
Definition Resource.h:89
This class is like a string view, but may optionally store the data internally Useful if the return t...
Definition String.h:1278
The core String View class for the NDEVR API.
Definition StringView.h:58
The core String class for the NDEVR API.
Definition String.h:95
static TranslatedString DisplayString(const t_type &value)
Converts an object into a TranslatedString.
Any text displayed to the user should be defined as a TranslatedString which allows the program to lo...
static TranslatedString DirectString(const StringView &sub_string)
If a string does not have a translation (EG: reading from an already translated string) this operatio...
The primary namespace for the NDEVR SDK.
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
UnitCategory
A category of unit describing what it relates to.
Definition Unit.h:15
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
double fltp08
Defines an alias representing an 8 byte floating-point number.
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408
Information about the object.
Definition ObjectInfo.h:55