Class: Ruber::Document

Inherits:
Qt::Object
  • Object
show all
Extended by:
Forwardable
Includes:
Activable, KTextEditorWrapper
Defined in:
lib/ruber/editor/document.rb

Instance Method Summary collapse

Methods included from KTextEditorWrapper

#interface, #method_missing, prepare_wrapper_connections

Methods included from Activable

#activate, #active=, #active?, #deactivate

Constructor Details

#initialize(file = nil, parent = nil) ⇒ Document

Creates a new Ruber::Document.



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/ruber/editor/document.rb', line 119

def initialize file = nil, parent = nil
  super parent
  @active = false
  @doc = KTextEditor::EditorChooser.editor('katepart').create_document( self)
  initialize_wrapper @doc, self.class.instance_variable_get(:@signal_table)
  @views = []
  @doc.openUrl(file.is_a?(String) ? KDE::Url.from_path(file) : file) if file
  @annotation_model = AnnotationModel.new self
  interface('annotation_interface').annotation_model = @annotation_model
  interface('modification_interface').modified_on_disk_warning = true
  @modified_on_disk = false
  @project = DocumentProject.new self
  @project.finalize
  @doc.connect(SIGNAL('modifiedChanged(KTextEditor::Document*)')) do |doc|
    emit modified_changed(@doc.modified?, self)
  end
  @doc.connect(SIGNAL('documentUrlChanged(KTextEditor::Document*)')) do |doc|
    if !doc.url.remote_file?
      Ruber[:components].each_component{|c| c.update_project @project}
    end
    emit document_url_changed self
  end
  
  @doc.connect SIGNAL(:completed) do
    if @doc.url.remote_file?
      Ruber[:components].each_component{|c|c.update_project @project}
    end
    emit completed
  end
  
  @doc.connect SIGNAL('documentNameChanged(KTextEditor::Document*)') do |doc|
    emit document_name_changed doc.document_name, self
  end
  
  @doc.connect(SIGNAL('textChanged(KTextEditor::Document*, KTextEditor::Range, KTextEditor::Range)')){|_, o, n| emit text_modified(o, n, self)}
  
  @doc.connect(SIGNAL('textInserted(KTextEditor::Document*, KTextEditor::Range)')) do |_, r| 
    begin
      emit text_inserted(r, self)
    rescue ArgumentError => e
      ExceptionDialog.new e, nil, true, "An exception was raised from emit text_inserted. See issue number 6 at http://github.com/stcrocco/ruber/issues"
    end
  end
  
  @doc.connect(SIGNAL('textRemoved(KTextEditor::Document*, KTextEditor::Range)')){|_, r| emit text_removed(r, self)}
  @doc.connect(SIGNAL('modifiedOnDisk(KTextEditor::Document*, bool, KTextEditor::ModificationInterface::ModifiedOnDiskReason)')) do |_, mod, reason|
    @modified_on_disk = (reason != KTextEditor::ModificationInterface::OnDiskUnmodified)
    emit modified_on_disk(self, mod, reason)
  end
  connect @doc, SIGNAL('completed(bool)'), self, SIGNAL('completed1(bool)')

end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Ruber::KTextEditorWrapper

Instance Method Details

#active_viewEditorView?

The view which currently has user focus, if any

Returns:

  • (EditorView, nil)

    the view associated with the document which currently has user focus or nil if none of the views associated with the document has user focus



192
193
194
# File 'lib/ruber/editor/document.rb', line 192

def active_view
  @doc.active_view.parent rescue nil
end

#close(ask = true) ⇒ Object

Closes the document. If ask is true, the query_close method is called, asking the user what to do if the document is modified. If the user confirms closing or if there’s no need of confirmation, the following happens:

  • the closing(QObject*) signal is emitted

  • the view (if it exists) is closed

  • the close_url method is called

  • all the documnent extensions are removed

  • al singnals are disconnected from the document

  • the document is disposed of

Returns true if the document was closed and false otherwise

TODO: maybe remove the argument, since this method is not called anymore at



440
441
442
443
444
445
446
447
448
449
450
451
452
# File 'lib/ruber/editor/document.rb', line 440

def close ask = true
  if !ask || query_close
    emit closing(self)
    @project.save unless path.empty?
    @views.dup.each{|v| v.close}
    return false unless close_url false
    @project.close false
    delete_later
    self.disconnect
    true
  else false
  end
end

#create_view(parent = nil) ⇒ Object

Creats a view for the document. parent is the view’s parent widget. Raises RuntimeError if the document already has a view.



332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/ruber/editor/document.rb', line 332

def create_view parent = nil
  inner_view = @doc.create_view nil
  view = EditorView.new self, inner_view, parent
  @views << view
  gui = view.send(:internal)
  action = gui.action_collection.action('file_save_as')
  disconnect action, SIGNAL(:triggered), @doc, SLOT('documentSaveAs()')
  connect action, SIGNAL(:triggered), self, SLOT(:document_save_as)
  action = gui.action_collection.action('file_save')
  disconnect action, SIGNAL(:triggered), @doc, SLOT('documentSave()')
  connect action, SIGNAL(:triggered), self, SLOT(:save)
  view.connect(SIGNAL('closing(QWidget*)')) do |v| 
    emit closing_view v, self
    @views.delete v
  end
  emit view_created(view, self)
  view
end

#editingObject

Executes the given block inside a pair of start_editing/end_editing calls.



417
418
419
420
421
422
423
# File 'lib/ruber/editor/document.rb', line 417

def editing
  begin
    @doc.start_editing
    yield
  ensure @doc.end_editing
  end
end

#execute_action(name, arg = nil) ⇒ Object

Executes the action with name name contained in document’s view’s action collection. This is made by having the action emit the triggered() or toggled(bool) signal (depending on whether it’s a standard action or a KDE::ToggleAction). In the second case, arg is the argument passed to the signal.

Returns true if name is the name of an action and false otherwise.

Note: for this method to work, a view should have been created for the document, otherwise this method will always return *false.



208
209
210
# File 'lib/ruber/editor/document.rb', line 208

def execute_action name, arg = nil
  @view ? @view.execute_action( name, arg) : false
end

#extension(name) ⇒ Object

Returns the document extension with name name or nil if such an extension doesn’t exist



245
246
247
# File 'lib/ruber/editor/document.rb', line 245

def extension name
  @project.extension name
end

#file_type_match?(mimetypes = [], patterns = []) ⇒ Boolean

Compares the mimetype and file name of the document with a list of mimetypes ( using KDE::MimeType#=~) and/or patterns (using File.fnmatch), returning true if any of the comparisons is successful and false if all fails. Both mimetypes and patterns can be either a string or an array of strings (a single string will be treated as an array containing a single string).

Notes:

  • if both mimetypes and patterns are empty, the comparison always returns true.

  • if the document is not associated with a file (that is, if path returns an empty string) it won’t match any pattern. It will match the text/plain mimetype, however.

  • only the basename of the file will be taken into account for pattern matching. For example, the pattern abc/xyz.jkl will match the pattern xyz.jkl, which wouldn’t be the case if the whole filename was included.

Returns:

  • (Boolean)


229
230
231
232
233
234
235
236
237
238
239
# File 'lib/ruber/editor/document.rb', line 229

def file_type_match? mimetypes = [], patterns = []
  mime = KDE::MimeType.mime_type @doc.mime_type
  mimetypes = Array(mimetypes).reject{|i| i.empty?}
  patterns = Array(patterns).reject{|i| i.empty?}
  base = File.basename path
  if mimetypes.empty? and patterns.empty? then true
  elsif mimetypes.any? {|m| mime =~ m} then true
  elsif patterns.any? {|pat| File.fnmatch? pat, base, File::FNM_DOTMATCH} then true
  else false
  end
end

#has_file?(which = :any) ⇒ Boolean

Whether the document is associated with a file

Depending on the value of which this method can also return true only if the document is associated with a local file or with a remote file. In particular:

  • if it’s @:local@ this method will return true only if the document is associated with a local file

  • if it’s @:remote@, this method will return true only if the document is associated with a remote file

  • with any other value, this method will return true if the document is associated with any file

Parameters:

  • which (Symbol, Object) (defaults to: :any)

    the kind of files which are acceptable

Returns:

  • (Boolean)

    true if the document is associated with a file of the kind matching which and false otherwise



282
283
284
285
286
287
288
289
290
# File 'lib/ruber/editor/document.rb', line 282

def has_file? which = :any
  u = url
  return false if u.empty?
  case which
  when :local then url.local_file?
  when :remote then !url.local_file?
  else true
  end
end

#has_view?Boolean

Returns whether the document has at least one view associated with it.

Returns:

  • (Boolean)

    whether the document has at least one view associated with it



182
183
184
# File 'lib/ruber/editor/document.rb', line 182

def has_view?
  !@views.empty?
end

#iconObject

Returns an appropriate Qt::Icon for the document, depending on the mimetype and the status of the document.



253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/ruber/editor/document.rb', line 253

def icon
  if @modified_on_disk then ICONS[:modified_on_disk]
  elsif @doc.modified? then ICONS[:modified]
  else
    if has_file? :remote
      mime = KDE::MimeType.find_by_content Qt::ByteArray.new(@doc.text)
    else mime = KDE::MimeType.mime_type(@doc.mime_type)
    end
    icon_name = mime.icon_name
    Qt::Icon.new(KDE::IconLoader.load_mime_type_pixmap icon_name)
  end
end

#inspectObject



110
111
112
113
114
# File 'lib/ruber/editor/document.rb', line 110

def inspect
  if disposed? then "< #{self.class} #{object_id} DISPOSED >"
  else super
  end
end

#line(n) ⇒ String

As @KTextEditor::Document#line@

Parameters:

  • n (Integer)

    the line number

Returns:

  • (String)

    the text in the given line or an empty string if the line is out of range



409
410
411
# File 'lib/ruber/editor/document.rb', line 409

def line n
  @doc.line(n) || ''
end

#modified_on_disk?Boolean

Tells whether the document is modified on disk or not

Returns:

  • (Boolean)


306
307
308
# File 'lib/ruber/editor/document.rb', line 306

def modified_on_disk?
  @modified_on_disk
end

#own_projectObject

Returns the DocumentProject associated with the document



367
368
369
# File 'lib/ruber/editor/document.rb', line 367

def own_project
  @project
end

#pathObject

Returns the path of the document



378
379
380
# File 'lib/ruber/editor/document.rb', line 378

def path
  @doc.url.path || ''
end

#pristine?Boolean

Tells whether the document is pristine or not. A pristine document is an empty, unmodified document which hasn’t a file associated with it. The document returned by Document.new is pristine is the second argument is nil, but it’s not pristine if a non-nil second argument was given (because in that case the document has a file associated with it).

Returns:

  • (Boolean)


299
300
301
# File 'lib/ruber/editor/document.rb', line 299

def pristine?
  @doc.url.empty? and !@doc.modified? and @doc.text.nil?
end

#projectObject

Return the project with wider scope the document belongs to. This is:

  • the current global project if it exists and the document is associated with a file belonging to it

  • the document project if there’s no active global project or the document isn’t associated with a file or the file doesn’t belong the global project



358
359
360
361
362
# File 'lib/ruber/editor/document.rb', line 358

def project
  prj = Ruber[:world].active_project
  return @project if path.empty? or !prj
  prj.file_in_project?(url.to_encoded.to_s) ? prj : @project
end

#saveObject

Saves the document. If the document is already associated with a file, it’s saved in that file; otherwise, a Save As dialog is displayed for the user to choose a file name. Returns true if the document was saved and false if it wasn’t for some reason (for example, if the user doesn’t have write perimission on the file or if he pressed the Cancel button in the Save As dialog).

This method is associated with the Save menu entry



319
320
321
322
323
324
325
326
# File 'lib/ruber/editor/document.rb', line 319

def save
  if path.empty? || !is_read_write then document_save_as
  else 
    res = @doc.save
    @project.save
    res
  end
end

#save_settingsObject



371
372
373
# File 'lib/ruber/editor/document.rb', line 371

def save_settings
  @project.save unless path.empty?
end

#textString #text(range, block = false) ⇒ String

Note:

We can’t just delegate this method to the internal @KTextEditor::Document@

The document’s text

because its @text@ method returns nil if there’s no text in the document, instead of an empty string.

Overloads:

  • #textString

    The text in the whole document

    Returns:

    • (String)

      the text in the whole document

  • #text(range, block = false) ⇒ String

    The text contained in the given range

    Parameters:

    • range (KTextEditor::Range)

      the range of text to retrieve

    • block (Boolean) (defaults to: false)

      whether or not to consider the range as a visual block

    Returns:

    • (String)

      the text inside the range. An empty string is returned if the range is invalid



398
399
400
# File 'lib/ruber/editor/document.rb', line 398

def text *args
  @doc.text(*args) || ''
end

#viewsObject

@return [Array<EditorView>] a list of all the views associated with the document



175
176
177
# File 'lib/ruber/editor/document.rb', line 175

def views
  @views.dup
end