Class: Ruber::FilteredOutputWidget

Inherits:
OutputWidget show all
Defined in:
lib/ruber/filtered_output_widget.rb

Overview

OutputWidget which allows the user to filter the contents, displaying only the items which match a given regexp.

This widget provides a line edit to enter the regexp, which is shown using a ‘Create filter’ action from the context menu. When the user presses the Return key from within the line edit, a filter is created from the current text and applied (if the line edit is empty, any existing filter is removed). If the user doesn’t want to create the filter, the line edit is hidden by pressing ESC while within it.

The filter is implemented using a FilteredOutputWidget::FilterModel, which is a slightly modified Qt::SortFilterProxyModel. Most of the times, however, you don’t need to worry about this, as all the methods provided by this class still use indexes referred to the source model. This means that, most of the times, adding filtering capability to an output widget is as simple as having it inherit from FilteredOutputWidget rather than from OutputWidget.

Besides the ‘Create Filter’, this class adds two other entries to the context menu: ‘Clear Filter’, which removes the existring filter, and a ‘Ignore Filter’ toggle action, which allows to temporarily disable the filter without removing it. Also, a new UI state, called ‘no_filter’ is defined: it’s true if no filter is applied and false otherwise

===Slots

  • create_filter_from_editor
  • clear_filter
  • ignore_filter(bool)
  • show_editor

Direct Known Subclasses

Ruber::FilesRunner::OutputWidget, Ruber::FindInFiles::FindWidget, RSpec::ToolWidget

Defined Under Namespace

Classes: FilterModel

Constant Summary

Constants inherited from OutputWidget

IsTitleRole, OutputTypeRole

Instance Attribute Summary (collapse)

Attributes inherited from OutputWidget

action_list, actions, auto_scroll, ignore_word_wrap_option, model, skip_first_file_in_title, view, working_dir

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods inherited from OutputWidget

#clear_output, #create_widgets, #do_auto_scroll, #fill_menu, #find_filename_in_index, #find_filename_in_string, #has_title?, #hints, #load_settings, #pinned_down?, #rows_changed, #selection_changed, #set_color_for, #set_output_type, #setup_model, #show_menu, #text_for_clipboard, #title=, #update_index_color, #with_auto_scrolling

Methods included from GuiStatesHandler

#change_state, included, #initialize_states_handler, #register_action_handler, #remove_action_handler_for, #state

Constructor Details

- (FilteredOutputWidget) initialize(parent = nil, opts = {})

Creates a new FilteredOutputWidget.

The arguments have the same meaning as in OutputWidget.new. The only difference is that opts can also contain a :filter entry. If given, it is the filter model to use (which should be derived from FilteredOutputWidget::FilterModel or provide the same api); if this entry is missing, a new FilteredOutputWidget::FilterModel will be used



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/ruber/filtered_output_widget.rb', line 75

def initialize parent = nil, opts = {}
  super parent, opts
  @filter_model = opts[:filter] || FilterModel.new
  @filter_model.parent = self
  @filter_model.dynamic_sort_filter = true
  @filter_model.source_model = model
  view.model = @filter_model
  disconnect @model, SIGNAL('rowsInserted(QModelIndex, int, int)'), self, SLOT('do_auto_scroll(QModelIndex, int, int)')
  connect @filter_model, SIGNAL('rowsInserted(QModelIndex, int, int)'), self, SLOT('do_auto_scroll(QModelIndex, int, int)')
  connect view.selection_model, SIGNAL('selectionChanged(QItemSelection, QItemSelection)'), self, SLOT('selection_changed(QItemSelection, QItemSelection)')
  @editor = KDE::LineEdit.new self
  connect @editor, SIGNAL('returnPressed(QString)'), self, SLOT(:create_filter_from_editor)
  layout.add_widget @editor, 2, 0
  def @editor.keyReleaseEvent e
    super
    hide if e.key == Qt::Key_Escape and e.modifiers == 0
  end
  @editor.hide
  @editor.completion_object = KDE::Completion.new
  @action_list.insert_before 1, nil, 'create_filter', 'ignore_filter', 'clear_filter'
  create_standard_actions
  set_state 'no_filter', true
end

Instance Attribute Details

- (Object) filter_model (readonly) Also known as: filter

The model used to filter the contents of the output widget



59
60
61
# File 'lib/ruber/filtered_output_widget.rb', line 59

def filter_model
  @filter_model
end

Class Method Details

+ (Object) keyReleaseEvent(e)



88
89
90
91
# File 'lib/ruber/filtered_output_widget.rb', line 88

def @editor.keyReleaseEvent e
  super
  hide if e.key == Qt::Key_Escape and e.modifiers == 0
end

Instance Method Details

- (Object) clear_filter

Removes the existing filter (if any).

This means that, after calling this method, all items will be accepted



112
113
114
115
# File 'lib/ruber/filtered_output_widget.rb', line 112

def clear_filter
  @filter_model.filter_reg_exp = ''
  set_state 'no_filter', true
end

Slot Signature:

clear_filter()

- (Object) copy (private)

Override of OutputWidget#copy which takes into account the filter. This means that only the items in the filter model will be taken into account.

Note: the indexes passed to text_for_clipboard refer to the source model, as in OutputWidget, not to the filter model.



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/ruber/filtered_output_widget.rb', line 187

def copy
  items = []
  stack = []
  @filter_model.row_count.times do |r|
    @filter_model.column_count.times do |c|
      stack << @filter_model.index(r, c)
    end
  end
  until stack.empty?
    it =  stack.shift
    items << @filter_model.map_to_source(it)
    (@filter_model.row_count(it)-1).downto(0) do |r|
      (@filter_model.column_count(it)-1).downto(0) do |c|
        stack.unshift it.child(r, c)
      end
    end
  end
  clp = KDE::Application.clipboard
  clp.text = text_for_clipboard items
end

- (Object) copy_selected (private)

Override of OutputWidget#copy_selected.

Note: the indexes passed to text_for_clipboard refer to the source model, as in OutputWidget, not to the filter model.



214
215
216
217
218
# File 'lib/ruber/filtered_output_widget.rb', line 214

def copy_selected
  clp = KDE::Application.clipboard
  indexes = @view.selection_model.selected_indexes.map{|i| @filter_model.map_to_source i}
  clp.text = text_for_clipboard indexes
end

- (Object) create_filter_from_editor (private)

Changes the filter accordig to the text in the line edit.

If the line edit is empty, the filter will be removed. Otherwise, it will be set to the regexp corresponding to the text in the editor



169
170
171
172
173
174
175
176
177
178
# File 'lib/ruber/filtered_output_widget.rb', line 169

def create_filter_from_editor
  text = @editor.text
  if !text.empty?
    mod = @editor.completion_object.add_item text
    @filter_model.filter_reg_exp = text
    set_state 'no_filter', false
  else clear_filter
  end
  @editor.hide
end

Slot Signature:

create_filter_from_editor()

- (Object) create_standard_actions (private)

Creates the ‘Create Filter’, ‘Ignore Filter’ and ‘Clear Filter’ actions, their state handlers and makes the necessary signal-slot connections



142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/ruber/filtered_output_widget.rb', line 142

def create_standard_actions
  super
  acts = []
  acts << KDE::Action.new('Create Filter', self){self.object_name = 'create_filter'}
  acts << KDE::Action.new('Clear Filter', self){self.object_name = 'clear_filter'}
  acts << KDE::ToggleAction.new('Ignore Filter', self){self.object_name = 'ignore_filter'}
  acts.each{|a| actions[a.object_name] = a}
  connect actions['create_filter'], SIGNAL(:triggered), self, SLOT(:show_editor)
  connect actions['clear_filter'], SIGNAL(:triggered), self, SLOT(:clear_filter)
  connect actions['ignore_filter'], SIGNAL('toggled(bool)'), self, SLOT('ignore_filter(bool)')
  register_action_handler actions['clear_filter'], '!no_filter'
  register_action_handler actions['ignore_filter'], '!no_filter'
end

- (Object) ignore_filter(val) (private)

Instructs the filter model to ignore or not the filter according to val.



159
160
161
# File 'lib/ruber/filtered_output_widget.rb', line 159

def ignore_filter val
  @filter_model.ignore_filter = val
end

Slot Signature:

ignore_filter(bool)

- (Object) maybe_open_file(idx) (private)

Override of OutputWidget#maybe_open_file.

It converts the index idx to the source model before passing it to super. If idx already refers to the source model, it is passed as it is to super.



226
227
228
229
# File 'lib/ruber/filtered_output_widget.rb', line 226

def maybe_open_file idx
  idx = @filter_model.map_to_source idx if idx.model.same? @filter_model
  super idx
end

- (Object) scroll_to(idx)



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/ruber/filtered_output_widget.rb', line 117

def scroll_to idx
  case idx
  when Numeric
    rc = @filter_model.row_count
    if idx >= rc then idx = rc -1
    elsif idx < 0 and idx.abs < rc then idx = rc + idx
    elsif idx < 0 then idx = 0
    end
    mod_idx = @filter_model.index idx, 0
    @view.scroll_to mod_idx
  when Qt::ModelIndex
    idx = @filter_model.map_from_source idx unless idx.model == @filter_model
    idx = @filter_model.index(@filter_model.row_count - 1, 0) unless idx.valid?
    @view.scroll_to idx
  when nil
    @view.scroll_to @filter_model.index(@filter_model.row_count - 1, 0)
  end
end

- (Object) show_editor

Shows the line edit where the user can enter the filter regexp and gives it focus



102
103
104
105
# File 'lib/ruber/filtered_output_widget.rb', line 102

def show_editor
  @editor.show
  @editor.set_focus
end

Slot Signature:

show_editor()