I'm trying to make a custom Gtk::Entry
widget (gtkmm4) that accepts only numbers and shows text as currency. Decimal and thousand separators are automatically added to the text. So I derived from Gtk::Entry
and connected the signal_changed()
with a member function that formats the input:
class CurrencyEntry : public Gtk::Entry{
public:
CurrencyEntry() {
set_placeholder_text("0.00");
connectionChange = signal_changed().connect(
sigc::mem_fun(*this, &CurrencyEntry::filterInput)
);
}
protected:
sigc::connection connectionChange;
Glib::ustring oldText;
void filterInput(){
auto currentText = get_text();
/* format currentText */
connectionChange.block();
set_text(currentText);
connectionChange.unblock();
/* move the cursor */
}
};
The problem is: the user presses one key at time, but more than one symbol can be added to the text in specific cases. It seems that the default behavior of the cursor is to always move 1 place per key pressed, ignoring the extra symbols. This is the result (|
is the cursor):
Current Text | Typed Key | Result | Desired Result |
---|---|---|---|
| (empty) |
1 |
0|.01 |
0.01| |
123.45| |
6 |
1,234.5|6 |
1,234.56| |
98|0,123.45| |
7 |
9,8|70,123.45 |
9,87|0,123.45 |
I need to move the cursor to the correct position. At first seemed trivial, but so far I have tried:
Calling
set_position(position)
at the end offilterInput()
.Calling
gtk_editable_set_position( GTK_EDITABLE(this->gobj()), position)
at the end offilterInput()
.Overriding
Entry::on_insert_text(const Glib::ustring& text, int* position)
and change the value pointed by theposition
parameter.Calling
Editable::on_insert_text(const Glib::ustring& text, int* position)
directly at the end offilterInput()
, passing a newposition
value.
Nothing happens. All these commands seem to be ignored or ignore the position parameter. Am I doing something wrong or is this some kind of bug? How can I set the cursor position correctly in a Gtk::Entry
widget?
The position seems not to be updated from the entry's handler. I tried other handlers (like
insert_text
) and the same issue arises. One way to solve this is to, from within you entry's handler, add a function to be executed in the idle loop. In that function, you can update the position. Here is the code:This is a simplified version of you case: all inserted text is transformed to upper case and, if possible, the cursor's position is set to 2. I think you can adapt to your use case from that.