NDEVR
API Documentation
QCustomLineEdit.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: QCustomLineEdit
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/QCustomValidator.h>
34#include "DLLInfo.h"
35#include <NDEVR/QTTools.h>
36#include <NDEVR/String.h>
37#include <NDEVR/ApplicationOptions.h>
38#include <NDEVR/BufferBase.h>
39#include <NDEVR/TimeSpan.h>
40#include <NDEVR/Unit.h>
41#include <NDEVR/BufferBase.h>
42#include <NDEVR/RGBColor.h>
43#include <QLineEdit>
44
45namespace NDEVR
46{
47 class PasswordString;
51 template<class t_type, bool is_number>
53 {
54 public:
60 static fltp08 ValueToFloat(const t_type& value)
61 {
62 UNUSED(value);
63 lib_assert(false, "Trying to convert non-number");
64 return Constant<fltp08>::Invalid;
65 }
66
71 static t_type ValueFromFloat(const fltp08& value)
72 {
73 UNUSED(value);
74 lib_assert(false, "Trying to convert non-number");
75 return Constant<t_type>::Invalid;
76 }
77 };
78
81 template<class t_type>
82 class LineEditResourceSetter<t_type, true>
83 {
84 public:
90 static fltp08 ValueToFloat(const t_type& value)
91 {
92 return cast<fltp08>(value);
93 }
94
99 static t_type ValueFromFloat(const fltp08& value)
100 {
101 return cast<t_type>(value);
102 }
103 };
104
107 template<>
109 {
110 public:
116 static fltp08 ValueToFloat(const TimeSpan& value)
117 {
118 return value.elapsedSeconds();
119 }
120
125 static TimeSpan ValueFromFloat(const fltp08& value)
126 {
127 return TimeSpan(value);
128 }
129 };
130
133 template<>
135 {
136 public:
142 static fltp08 ValueToFloat(const Angle<fltp08>& value)
143 {
144 return value.internal<false>();
145 }
146
152 {
153 return Angle<fltp08>(INTERNAL_ANGLE, value);
154 }
155 };
156
159 template<>
161 {
162 public:
168 static fltp08 ValueToFloat(const Angle<sint04>& value)
169 {
170 return value.internal<false>();
171 }
172
178 {
179 return Angle<sint04>(INTERNAL_ANGLE, value);
180 }
181 };
182 class Keypad;
191 class NDEVR_WIDGETS_API QCustomLineEdit : public QLineEdit
192 {
193 Q_OBJECT
194 public:
195 friend class QCustomComboBox;
200 explicit QCustomLineEdit(QWidget *parent = Q_NULLPTR);
206 explicit QCustomLineEdit(const QString& value, QWidget *parent = Q_NULLPTR);
215 virtual void setTitle(const TranslatedString& title);
231 void setConstantUnit(const ConstPointer<Unit>& unit, uint01 dimension = Constant<uint01>::Invalid);
238 void setCustomUnit(const StringView& unit, UnitCategory fallback_unit, uint01 dimension = Constant<uint01>::Invalid);
244 void setUnitType(UnitCategory unit, uint01 dimension = Constant<uint01>::Invalid);
253 bool isValid() const;
258 void setEditable( bool editable );
263 bool isEditable() const { return m_is_editable; }
268 bool isEditing() const;
273 bool hasUserFocus() const;
297 void setIsPassword(bool is_password, const StringView& encoder = StringView());
302 bool isPassword() const;
307 const String& passwordEncoder() const;
312 void setToolTip(const TranslatedString& tooltip);
318 String getValue(bool allow_placeholder) const;
328 template<class t_angle_type>
330 {
331 setUnitValue(value.template as<INTERNAL_ANGLE>());
332 }
333
337 void setUnitValue(fltp08 value);
348 template<class t_angle_type = fltp08>
349 Angle<t_angle_type> getUnitAngle(bool allow_placeholder = true) const
350 {
351 return Angle<t_angle_type>(INTERNAL_ANGLE, getUnitValue(allow_placeholder));
352 }
353
358 fltp08 getUnitValue(bool allow_placeholder = true) const;
363 template<class t_type>
364 void setup(const TranslatedString& title)
365 {
366 setTitle(title);
367 m_validator.setRegex(StringStream<t_type>::getValidRegex());
368 m_validator.setTypeInfo(GetTypeInfo<t_type>());
369 updateInputMethodHints();
370 }
371
375 void setRegex(const StringView& regex)
376 {
377 m_validator.setRegex(regex);
378 }
379
385 void setup(const TranslatedString& title, UnitCategory unit_type, uint01 dim = Constant<uint01>::Invalid);
391 void setup(const TranslatedString& title, const TypeInfo& type);
396 void setup(GenericOption& option);
397
402 template<class t_type>
404 {
405 setup(option.label(), option.getResource());
406 }
407
415 template<class t_type>
416 void setup(const TranslatedString& title, Resource<t_type>& resource)
417 {
418 setup<t_type>(title);
419 connect(this, &QCustomLineEdit::editingFinishedSignal, this, [this, &resource]
420 {
421 if constexpr(ObjectInfo<t_type>::Number)
422 {
423 if (!customValidator().unit().isNull())
424 resource.set(LineEditResourceSetter<t_type, ObjectInfo<t_type>::Number>::ValueFromFloat(getUnitValue()));
425 else
426 resource.set(getAs<t_type>());
427 }
428 else
429 {
430 resource.set(getAs<t_type>());
431 }
432 });
433 if (m_resource_changed_listener)
434 delete m_resource_changed_listener;
435 m_resource_changed_listener = new QTResourceListener([this, &resource]
436 {
437 if constexpr(ObjectInfo<t_type>::Number)
438 {
439 if (!customValidator().unit().isNull())
440 setUnitValue(LineEditResourceSetter<t_type, ObjectInfo<t_type>::Number>::ValueToFloat(resource.get()));
441 else
442 setValue(resource.get());
443 }
444 else
445 {
446 setValue(resource.get());
447 }
448 }, this);
449 resource.addListener(m_resource_changed_listener);
450 }
451
456 void setup(const TranslatedString& title, Resource<String>& resource);
461 void setup(Resource<String>& resource);
472 template<class t_type>
473 t_type getAs(bool allow_placeholder) const
474 {
475 return getValue(allow_placeholder).getAs<t_type>();
476 }
477
481 template<class t_type>
482 t_type getAs() const
483 {
484 return getValue(m_allow_placeholder_as_value).getAs<t_type>();
485 }
486
490 template<class t_type>
491 typename std::enable_if<ObjectInfo<t_type>::Number, void>::type setValue(const t_type& input_value)
492 {
493 if (m_ignore_focus_lock || !hasUserFocus())
494 {
495 String value;
496 if(m_validator.unit().isNull())
497 value = String(input_value);
498 else if(IsValid(m_validator.unitDimension()))
499 value = m_validator.unit()->toString(input_value, false, 0, Constant<uint04>::Max, 0, false, m_validator.unitDimension());
500 else
501 value = m_validator.unit()->toString(input_value, false, 0, Constant<uint04>::Max, 0, false);
502 _setText(value, false);
503 }
504 }
505
509 void setValue(const PasswordString& input_value);
514 void setValue(const StringView& input_value);
519 void setValue(const TimeSpan& input_value);
524 void setValue(const TranslatedString& input_value);
529 void setValue(const Angle<sint04>& input_value)
530 {
531 setValue(String(input_value));
532 }
533
537 void setValue(const Angle<fltp08>& input_value)
538 {
539 setValue(String(input_value));
540 }
541
545 void setBackgroundColor(const RGBColor& color);
556 template<class t_type>
557 void setPlaceholderValue(const t_type& input_value, bool allow_placeholder_as_value = true)
558 {
559 setAllowPlaceholderAsValue(allow_placeholder_as_value);
560 StringAllocatingView input = StringAllocatingView::Allocate(input_value);
561 m_validator.fixup(input);
562 setPlaceholderText(input.getAs<QString>());
563 }
564
569 void setPlaceholderValue(const TranslatedString& input_value, bool allow_placeholder_as_value = true);
574 QSize sizeHint() const override;
579 QSize minimumSizeHint() const override;
584 void wheelEvent(QWheelEvent *event) override;
589 void forceValue(const StringView& forced_value);
595 bool event(QEvent* event) override;
605 void setStep(fltp08 step);
610 void setAutoShowTooltip(bool auto_show_tooltip) { m_auto_show_tooltip = auto_show_tooltip; }
615 static bool UseKeypad();
620 void setPlaceholderText(const QString& value);
625 void startUserEdit(bool select_all = true);
630 void setFontMultiplier(fltp04 font_multiplier);
635 void setBold(bool is_bold);
636 private:
640 void updateInputMethodHints();
646 void _setText(StringView text, bool translate);
651 void _setInputHint(const TranslatedString& hint);
656 void paintEvent(QPaintEvent *event) override;
662 void setupForUnit(const ConstPointer<Unit>& unit, uint01 dimension = Constant<uint01>::Invalid);
667 virtual void mousePressEvent(QMouseEvent *e) override;
672 virtual void focusInEvent(QFocusEvent *e) override;
677 virtual void focusOutEvent(QFocusEvent *e) override;
681 virtual void creatUnitLister();
685 void updateFont();
690 void _setBackgroundColor(const RGBColor& color);
694 void _updateTooltip();
698 void init();
703 void updateCharColors(const QCustomValidator::InvalidProperties& props);
704 signals:
717 public slots:
729 void onEdited();
730 protected:
733 private:
734 String m_current_value;
735 String m_fixed_up_current_value;
736 String m_last_valid;
737 String m_custom_unit;
738 String m_password_encoder;
739 TranslatedString m_input_hint;
740 TranslatedString m_custom_input_hint;
741 RGBColor m_background_color = Constant<RGBColor>::Invalid;
742 QTResourceListener* m_resource_changed_listener = nullptr;
743 QTResourceListener* m_unit_changed_listener = nullptr;
744 QCustomValidator m_validator;
745 fltp04 m_font_multiplier = 1.0f;
746 bool m_is_editable = true;
747 bool m_auto_show_tooltip = true;
748 bool m_suppress_focus_out = false;
749 bool m_allow_placeholder_as_value = true;
750 bool m_is_bold = false;
751 bool m_ignore_focus_lock = false;
752 bool m_has_edited = false;
753 bool m_hint_resolve_links = false;
754 bool m_is_password = false;
755 private:
756
757 };
758}
Stores an angle in an optimized internal format with support for efficient trigonometric operations.
Definition Angle.h:83
constexpr t_type internal() const
Gets the internal index angle which is the default storage unit for the angle data.
Definition Angle.h:183
The default object to store data of any type that should persist through sessions of the application.
const TranslatedString & label() const
Returns the translated display label for this option.
Resource< t_type > & getResource()
Returns a reference to the underlying Resource holding this option's value.
Provides a constant, unmodifiable pointer that has shared ownership of a dynamically allocated object...
Definition Pointer.hpp:276
static fltp08 ValueToFloat(const Angle< fltp08 > &value)
Converts an Angle<fltp08> to its internal representation.
static Angle< fltp08 > ValueFromFloat(const fltp08 &value)
Constructs an Angle<fltp08> from an internal representation value.
static fltp08 ValueToFloat(const Angle< sint04 > &value)
Converts an Angle<sint04> to its internal representation as fltp08.
static Angle< sint04 > ValueFromFloat(const fltp08 &value)
Constructs an Angle<sint04> from an internal representation value.
static fltp08 ValueToFloat(const TimeSpan &value)
Converts a TimeSpan to its elapsed seconds as fltp08.
static TimeSpan ValueFromFloat(const fltp08 &value)
Constructs a TimeSpan from a floating-point seconds value.
static fltp08 ValueToFloat(const t_type &value)
Converts a numeric value to fltp08.
static t_type ValueFromFloat(const fltp08 &value)
Converts a fltp08 value to the target numeric type.
A basic class for helping convert a Value into a resource.
static t_type ValueFromFloat(const fltp08 &value)
Converts a floating-point number back to the value type.
static fltp08 ValueToFloat(const t_type &value)
Converts a value to a floating-point number.
When passwords are used inside the NDEVR engine, we don't want them logged or visible.
TranslatedString m_title
The display title for the line edit.
void clearBackgroundColor()
Clears any custom background color, reverting to the default.
void setValue(const PasswordString &input_value)
Sets the value from a PasswordString.
void setStep(fltp08 step)
Sets the step increment used when scrolling or using arrow keys on numeric values.
void setAsKeyboardFocus()
Sets this line edit as the primary keyboard focus target.
void setup(GenericOption &option)
Sets up the line edit from a GenericOption, binding title, type, and resource.
void setup(Resource< String > &resource)
Sets up the line edit bound to a String resource, using the resource name as the title.
void setConstantUnit(const ConstPointer< Unit > &unit, uint01 dimension=Constant< uint01 >::Invalid)
Sets a constant unit for value formatting and conversion.
bool isEditing() const
Returns whether the user is currently editing this line edit.
bool event(QEvent *event) override
Handles generic events such as tooltip and theme updates.
const String & passwordEncoder() const
Returns the password encoder string used for cross-session password storage.
void setUnitValue(Angle< t_angle_type > value)
Sets the value as an angle, converting to internal representation first.
void paintEvent(QPaintEvent *event) override
Custom paint event for rendering the line edit with background color and decorations.
virtual void mousePressEvent(QMouseEvent *e) override
Handles mouse press events to initiate editing or show the keypad.
~QCustomLineEdit()
Destroys the line edit and its resources.
QCustomLineEdit(const QString &value, QWidget *parent=Q_NULLPTR)
Constructs a QCustomLineEdit with an initial value and the given parent widget.
QSize sizeHint() const override
Returns the recommended size for the line edit.
void setValue(const TimeSpan &input_value)
Sets the value from a TimeSpan.
void setUnitValue(fltp08 value)
Sets the value as a floating-point number in user-facing units.
RGBColor backgroundColor() const
Returns the current background color of the line edit.
void setToolTip(const TranslatedString &tooltip)
Sets the tooltip text for the line edit.
void clearInputHint()
Clears the input hint text.
void clearValue()
Clears the current value of the line edit.
void setPlaceholderText(const QString &value)
Sets the placeholder text displayed when the field is empty.
void setup(const TranslatedString &title, Resource< String > &resource)
Sets up the line edit bound to a String resource with a title.
void editedSignal()
Emitted when the text is edited by the user.
const QCustomValidator & customValidator() const
Returns a const reference to the custom validator used for input validation.
void setValue(const Angle< fltp08 > &input_value)
Sets the value from an Angle<fltp08>.
void forceValue(const StringView &forced_value)
Ignores validation steps, password encoding, etc.
virtual void creatUnitLister()
Creates a unit lister popup for selecting units.
virtual void setTitle(const TranslatedString &title)
Sets the display title for the line edit, used as a label or placeholder context.
const TranslatedString & inputHint() const
Returns the current input hint text.
void setValue(const TranslatedString &input_value)
Sets the value from a TranslatedString.
void editingFinishedSignal()
Emitted when the user finishes editing (focus lost or enter pressed).
void wheelEvent(QWheelEvent *event) override
Handles mouse wheel events for incrementing or decrementing numeric values.
Angle< t_angle_type > getUnitAngle(bool allow_placeholder=true) const
Returns the current value as an Angle in internal representation.
void setIsPassword(bool is_password, const StringView &encoder=StringView())
Sets this widget to be a password.
void setup(const TranslatedString &title, UnitCategory unit_type, uint01 dim=Constant< uint01 >::Invalid)
Sets up the line edit with a title and unit type.
String getValue() const
Returns the current text value of the line edit.
void setValue(const StringView &input_value)
Sets the value from a StringView.
void setPlaceHolderUnitValue(fltp08 value)
Sets the placeholder value as a floating-point number in user-facing units.
virtual void focusOutEvent(QFocusEvent *e) override
Handles focus-out events to finalize editing.
void setUnitType(UnitCategory unit, uint01 dimension=Constant< uint01 >::Invalid)
Sets the unit type used for value formatting and conversion.
void setup(const TranslatedString &title, const TypeInfo &type)
Sets up the line edit with a title and type info for validation.
t_type getAs() const
Returns the current value converted to the requested type.
void setPlaceholderValue(const t_type &input_value, bool allow_placeholder_as_value=true)
Sets a placeholder value displayed when the field is empty.
bool isPassword() const
Returns whether this line edit is in password mode.
std::enable_if< ObjectInfo< t_type >::Number, void >::type setValue(const t_type &input_value)
Sets the value from a numeric type, applying unit formatting if configured.
String getValue(bool allow_placeholder) const
Returns the current text value of the line edit.
void setBold(bool is_bold)
Sets whether the line edit text is rendered in bold.
void onFinishedSlot()
Slot invoked when editing is finished, to commit the value.
virtual void focusInEvent(QFocusEvent *e) override
Handles focus-in events to begin editing state.
void setAllowPlaceholderAsValue(bool allow)
Sets whether the placeholder text should be treated as a valid value when the field is empty.
void setBackgroundColor(const RGBColor &color)
Sets the background color of the line edit.
QSize minimumSizeHint() const override
Returns the minimum size hint for layout purposes.
bool isValid() const
Returns whether the current text passes validation.
t_type getAs(bool allow_placeholder) const
Returns the current value converted to the requested type.
void setup(const TranslatedString &title)
Sets up the line edit for a specific type with a title, configuring validation accordingly.
void setValue(const Angle< sint04 > &input_value)
Sets the value from an Angle<sint04>.
bool hasUserFocus() const
Returns whether the line edit currently has user focus (keyboard or touch).
void updateColor()
Slot to update the line edit color based on validation state.
void inputHintChangedSignal()
Emitted when the input hint text changes.
void setup(ApplicationOption< t_type > &option)
Sets up the line edit from an ApplicationOption, using its label and resource.
void setFontMultiplier(fltp04 font_multiplier)
Sets a multiplier applied to the base font size.
void setEditable(bool editable)
Sets whether the line edit is editable by the user.
void setAutoShowTooltip(bool auto_show_tooltip)
Sets whether the tooltip should automatically update to show the current value.
fltp08 getUnitValue(bool allow_placeholder=true) const
Returns the current value as a floating-point number in user-facing units.
bool isEditable() const
Returns whether the line edit is currently editable.
TranslatedString m_tooltip
The tooltip text.
void setInputHint(const TranslatedString &hint)
Sets an input hint displayed to guide the user on expected input.
void setup(const TranslatedString &title, Resource< t_type > &resource)
Sets up two-way binding between this line edit and a Resource.
void onEdited()
Slot invoked when the text has been edited by the user.
void setRegex(const StringView &regex)
Sets a custom regex pattern for input validation.
static bool UseKeypad()
Returns whether the touch keypad should be used for input.
void setPlaceholderValue(const TranslatedString &input_value, bool allow_placeholder_as_value=true)
Sets a translated placeholder value displayed when the field is empty.
QCustomValidator & customValidator()
Returns a mutable reference to the custom validator used for input validation.
void startUserEdit(bool select_all=true)
Begins user editing of the line edit, optionally selecting all text.
void setCustomUnit(const StringView &unit, UnitCategory fallback_unit, uint01 dimension=Constant< uint01 >::Invalid)
Sets a custom unit string with a fallback unit category.
QCustomLineEdit(QWidget *parent=Q_NULLPTR)
Constructs a QCustomLineEdit with the given parent widget.
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
Represents a color in the RGB space with optional alpha transparency.
Definition RGBColor.h:57
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
static const char * getValidRegex()
Optionally specified to allow the software to do a check on user or file input to ensure that fromStr...
The core String View class for the NDEVR API.
Definition StringView.h:58
t_type getAs() const
Converts a string into an object.
Definition StringView.h:125
The core String class for the NDEVR API.
Definition String.h:95
Stores a time span, or difference between two times, with an optional start time.
Definition TimeSpan.h:46
constexpr fltp08 elapsedSeconds() const
Returns the elapsed duration in seconds.
Definition TimeSpan.h:213
Any text displayed to the user should be defined as a TranslatedString which allows the program to lo...
Stores information about a type, relevant for certain templated functions.
Definition TypeInfo.h:43
The primary namespace for the NDEVR SDK.
float fltp04
Defines an alias representing a 4 byte floating-point number Bit layout is as follows: -Sign: 1 bit a...
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
constexpr std::enable_if<!ObjectInfo< t_type >::Buffer, TypeInfo >::type GetTypeInfo()
Constructs a TypeInfo for a non-buffer type at compile time using ObjectInfo traits.
Definition TypeInfo.h:125
UnitCategory
A category of unit describing what it relates to.
Definition Unit.h:15
double fltp08
Defines an alias representing an 8 byte floating-point number.
int32_t sint04
-Defines an alias representing a 4 byte, signed integer.
@ INTERNAL_ANGLE
The angle internally used by the angle class.
Definition Angle.h:59
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
Stores a generic option of any type as well as some information about how the user might interact wit...
Information about the object.
Definition ObjectInfo.h:55
Contains the result of a validation check, including the validity state, a suggested fix-up message,...