def get_string(widget): if isinstance(widget, Gtk.Entry): result = _u(widget.get_text()) elif isinstance(widget, Gtk.ComboBoxText): index = widget.get_active() result = widget.options[index] elif isinstance(widget, Gtk.Grid): result = _u(widget.entry.get_text()) else: raise TypeError(_("Unhandled widget class!")) return result
def _match_anywhere(self, completion, entrystr, iter, data): """ Check if the entrystring is a substring of our text_column. Args: entrystr (str): The text extracted from the entry so far. Note that we do not use this at all. Instead we fetch ``self.get_entry().get_segment_text`` in order to get only the text of the currently edited segment. iter: Iterator position indicating the model row we check against. This works because ``self.get_entry()._on_changed`` makes sure that the completion model is set properly according to ``self.get_entry().current_segment``. data: Arbitrary user data. Returns: bool: ``True`` if ``self.get_entry.get_segment_text`` is a substring, ``False`` if not. Note this is a custom match function, for details on the general generic solution [please see|https://lazka.github.io/pgi-docs/#Gtk-3.0/ callbacks.html#Gtk.EntryCompletionMatchFunc]. """ result = False entry = self.get_entry() modelstring = '' hit = self.get_model()[iter][0] # We only need to check if the string was matched at all. Otherwise # there are no 'segments' anyway. if hit and entry.match: modelstring = _u(hit) segment_text = entry.get_segment_text() result = segment_text in modelstring return result
def get_config_value(self): """ Return the id of the selected item. Returns: six.text_type: Identifier of the selected item """ return _u(self.get_active_id())
def get_config_value(self): """ Return the selected path. Returns: six.text_type: Selected file path. """ return _u(self._entry.get_text())
def test_update_initial_fact(self, current_fact_box, fact): """Make sure update re-creates as widgets as expected.""" assert not current_fact_box.content.get_children() current_fact_box.update(fact) assert len(current_fact_box.content.get_children()) == 3 label = current_fact_box.content.get_children()[0] expectation = '{activity.name}@{activity.category}'.format(activity=fact.activity) assert expectation in _u(label.get_text())
def test_update_initial_fact(self, current_fact_box, fact): """Make sure update re-creates as widgets as expected.""" assert not current_fact_box.content.get_children() current_fact_box.update(fact) assert len(current_fact_box.content.get_children()) == 3 label = current_fact_box.content.get_children()[0] expectation = '{activity.name}@{activity.category}'.format( activity=fact.activity) assert expectation in _u(label.get_text())
def get_time(widget): if isinstance(widget, Gtk.Entry): result = _u(widget.get_text()) # We are tollerant against malformed time information. try: result = datetime.datetime.strptime(result, '%H:%M:%S').time() except ValueError: result = datetime.datetime.strptime(result, '%H:%M').time() else: raise TypeError(_("Unhandled widget class!")) return result
def _on_choose_clicked(self, widget): """Open a dialog to select path and update entry widget with it.""" toplevel = get_parent_window(self) dialog = Gtk.FileChooserDialog(_("Please choose a directory"), toplevel, Gtk.FileChooserAction.SAVE, (_("_Cancel"), Gtk.ResponseType.CANCEL, _("_Save"), Gtk.ResponseType.OK)) dialog.set_filename(self.get_config_value()) response = dialog.run() if response == Gtk.ResponseType.OK: self._entry.set_text(_u(dialog.get_filename())) dialog.destroy()
def _on_changed(self, widget): """ Callback triggered whenever entry text is changed. Its main task is to keep track of which segment of the raw fact string the user is currently editing. For this the whole string is inspected and matched against our regex. By comparing the current cursor position with individual matched segment spans a guess about which one is currently edited is made. """ def get_segment(match): """ Return the segment the cursor is currently in. Returns: text_type or None: Segment identifier or None if cursor not within any segment. """ result = None cursor_position = self.get_position() segments = ['timeinfo', 'tags', 'description'] if self._split_activity_autocomplete: segments.extend(('activity', 'category')) else: segments.append('activity+category') for segment in segments: start, end = _get_segment_boundaries(segment, match) if start <= cursor_position <= end: result = segment return result def run_autocomplete(segment): completion = self.get_completion() completion.set_model(completion.segment_models[segment]) self.match = helpers.decompose_raw_fact_string(_u(self.get_text()), raw=True) # Do nothing if we could not 'match' the raw string. # Please note that the completions 'match function' will be run # regardless of what we do here. if self.match: self.current_segment = get_segment(self.match) if self.current_segment in ('activity', 'category', 'activity+category'): run_autocomplete(self.current_segment)
def get_config_value(self): """ Return time entered into the widget. The entered time has to match either ``HH:MM:SS`` or ``HH:MM`` form, otherwise an error is thrown. Returns: datetime.time: Selected time. Raises: ValueError: When the text entered in the field does not constitute a valid time. """ result = _u(self.get_text()) # We are tollerant against malformed time information. try: result = datetime.datetime.strptime(result, '%H:%M:%S').time() except ValueError: result = datetime.datetime.strptime(result, '%H:%M').time() return result
def _on_start_tracking_button(self, button): """ Start a new *ongoing fact*. Note: Whilst we accept the full ``raw_fact`` syntax, we ignore any ``Fact.end`` information encoded in the string. Unlike legacy hamster we *only* deal with *ongoing facts* in this widget. """ # [FIXME] # This should be done in one place only. And the hamster-lib. If at all # via hamster-lib.helpers. def complete_tmp_fact(fact): """Apply fallback logic in case no start time has been encoded.""" if not fact.start: fact.start = datetime.datetime.now() # Make sure we dismiss any extracted end information. fact.end = None return fact raw_fact = _u(self.raw_fact_entry.props.text) try: fact = Fact.create_from_raw_fact(raw_fact) except Exception as error: helpers.show_error(helpers.get_parent_window(self), error) else: fact = complete_tmp_fact(fact) try: fact = self._controler.store.facts.save(fact) except Exception as error: helpers.show_error(self.get_top_level(), error) else: self.emit('tracking-started') self._controler.signal_handler.emit('facts-changed') self.reset()
def replace_segment_text( self, segment_string, ): """ Replace the substring of the entry text that matches ``self.current_segment``. Args: segment_string (text_type): New text that is to replace the old. Returns: None """ def add_prefix(segment, string): # [TODO] # Once autocompletion supports more segments with prefixes, this will # need to be extended. result = string if segment == 'category': result = '@{}'.format(string) return result if not self.match: return match = self.match segment = self.current_segment segment_string = add_prefix(segment, segment_string) segment_start, segment_end = _get_segment_boundaries(segment, match) old_string = _u(self.get_text()) new_string = '{}{}{}'.format( old_string[:segment_start], segment_string, old_string[segment_end:], ) self.set_text(new_string) self.set_position(segment_start + len(segment_string))
def _on_start_tracking_button(self, button): """ Start a new *ongoing fact*. Note: Whilst we accept the full ``raw_fact`` syntax, we ignore any ``Fact.end`` information encoded in the string. Unlike legacy hamster we *only* deal with *ongoing facts* in this widget. """ # [FIXME] # This should be done in one place only. And the hamster-lib. If at all # via hamster-lib.helpers. def complete_tmp_fact(fact): """Apply fallback logic in case no start time has been encoded.""" if not fact.start: fact.start = datetime.datetime.now() # Make sure we dismiss any extracted end information. fact.end = None return fact raw_fact = _u(self.raw_fact_entry.props.text) try: fact = Fact.create_from_raw_fact(raw_fact) except Exception as error: helpers.show_error(self.get_toplevel(), error) else: fact = complete_tmp_fact(fact) try: fact = self._controler.store.facts.save(fact) except Exception as error: helpers.show_error(self.get_top_level(), error) else: self.emit('tracking-started') self._controler.signal_handler.emit('facts-changed') self.reset()
def get_description_value(): """Get unicode value from widget.""" text_view = self._description_widget.get_child() text_buffer = text_view.get_buffer() start, end = text_buffer.get_bounds() return _u(text_buffer.get_text(start, end, True))
def get_raw_fact_value(): """Get text from raw fact entry field.""" return _u(self._raw_fact_widget.get_text())
def test__get_fact_label(self, current_fact_box, fact): """Make sure that the label matches expectations.""" result = current_fact_box._get_fact_label(fact) assert isinstance(result, Gtk.Label) assert _u(result.get_text()) == text_type(fact)
def _on_match_selected(self, completion, model, iter): """Callback to be executed once a match is selected by the user.""" entry = self.get_entry() name = _u(model[iter][0]) entry.replace_segment_text(name) return True