Class: JSON::Editor::MainWindow

Inherits:
Gtk::Window
  • Object
show all
Includes:
Gtk
Defined in:
lib/json/editor.rb

Overview

The editor main window

Instance Method Summary collapse

Constructor Details

#initialize(encoding) ⇒ MainWindow

Returns a new instance of MainWindow.



1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
# File 'lib/json/editor.rb', line 1049

def initialize(encoding)
  @changed  = false
  @encoding = encoding
  super(TOPLEVEL)
  display_title
  set_default_size(800, 600)
  signal_connect(:delete_event) { quit }

  vbox = VBox.new(false, 0)
  add(vbox)
  #vbox.border_width = 0

  @treeview = JSONTreeView.new(self)
  @treeview.signal_connect(:'cursor-changed') do
    display_status('')
  end

  menu_bar = create_menu_bar
  vbox.pack_start(menu_bar, false, false, 0)

  sw = ScrolledWindow.new(nil, nil)
  sw.shadow_type = SHADOW_ETCHED_IN
  sw.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
  vbox.pack_start(sw, true, true, 0)
  sw.add(@treeview)

  @status_bar = Statusbar.new
  vbox.pack_start(@status_bar, false, false, 0)

  @filename ||= nil
  if @filename
    data = read_data(@filename)
    view_new_model Editor.data2model(data)
  end

  signal_connect(:button_release_event) do |_,event|
    if event.button == 2
      c = Gtk::Clipboard.get(Gdk::Selection::PRIMARY)
      if url = c.wait_for_text
        location_open url
      end
      false
    else
      true
    end
  end
end

Instance Method Details

#ask_for_locationObject

Ask for location URI a to load data from. Returns the URI as a string.



1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
# File 'lib/json/editor.rb', line 1318

def ask_for_location
  dialog = Dialog.new(
    "Load data from location...",
    nil, nil,
    [ Stock::OK, Dialog::RESPONSE_ACCEPT ],
    [ Stock::CANCEL, Dialog::RESPONSE_REJECT ]
  )
  hbox = HBox.new(false, 5)

  hbox.pack_start(Label.new("Location:"), false)
  hbox.pack_start(location_input = Entry.new)
  location_input.width_chars = 60
  location_input.text = @location || ''

  dialog.vbox.pack_start(hbox, false)

  dialog.signal_connect(:'key-press-event', &DEFAULT_DIALOG_KEY_PRESS_HANDLER)
  dialog.show_all
  dialog.run do |response|
    if response == Dialog::RESPONSE_ACCEPT
      return @location = location_input.text
    end
  end
  return
ensure
  dialog.destroy if dialog
end

#ask_saveObject

Opens a dialog, asking, if changes should be saved to a file.



1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
# File 'lib/json/editor.rb', line 1140

def ask_save
  if Editor.question_dialog(self,
    "Unsaved changes to JSON model. Save?")
    if @filename
      file_save
    else
      file_save_as
    end
  end
end

#changeObject

Sets editor status to changed, to indicate that the edited data containts unsaved changes.



1111
1112
1113
1114
# File 'lib/json/editor.rb', line 1111

def change
  @changed = true
  display_title
end

#clearObject

Clear the current model, after asking to save all unsaved changes.



1170
1171
1172
1173
1174
# File 'lib/json/editor.rb', line 1170

def clear
  ask_save if @changed
  @filename = nil
  self.view_new_model nil
end

#create_menu_barObject

Creates the menu bar with the pulldown menus and returns it.



1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
# File 'lib/json/editor.rb', line 1098

def create_menu_bar
  menu_bar = MenuBar.new
  @file_menu = FileMenu.new(@treeview)
  menu_bar.append @file_menu.create
  @edit_menu = EditMenu.new(@treeview)
  menu_bar.append @edit_menu.create
  @options_menu = OptionsMenu.new(@treeview)
  menu_bar.append @options_menu.create
  menu_bar
end

#display_status(text) ⇒ Object

Displays text in the status bar.



1132
1133
1134
1135
1136
1137
# File 'lib/json/editor.rb', line 1132

def display_status(text)
  @cid ||= nil
  @status_bar.pop(@cid) if @cid
  @cid = @status_bar.get_context_id('dummy')
  @status_bar.push(@cid, text)
end

#display_titleObject

Display the new title according to the editor’s current state.



1162
1163
1164
1165
1166
1167
# File 'lib/json/editor.rb', line 1162

def display_title
  title = TITLE.dup
  title << ": #@filename" if @filename
  title << " *" if @changed
  self.title = title
end

#edit(json) ⇒ Object

Edit the string json in the editor.



1201
1202
1203
1204
1205
1206
1207
# File 'lib/json/editor.rb', line 1201

def edit(json)
  if json.respond_to? :read
    json = json.read
  end
  data = parse_json json
  view_new_model Editor.data2model(data)
end

#file_open(filename = nil) ⇒ Object

Open the file filename or call the #select_file method to ask for a filename.



1194
1195
1196
1197
1198
# File 'lib/json/editor.rb', line 1194

def file_open(filename = nil)
  filename = select_file('Open as a JSON file') unless filename
  data = load_file(filename) or return
  view_new_model Editor.data2model(data)
end

#file_saveObject

Save the current file.



1210
1211
1212
1213
1214
1215
1216
# File 'lib/json/editor.rb', line 1210

def file_save
  if @filename
    store_file(@filename)
  else
    file_save_as
  end
end

#file_save_asObject

Save the current file as the filename



1219
1220
1221
1222
# File 'lib/json/editor.rb', line 1219

def file_save_as
  filename = select_file('Save as a JSON file')
  store_file(filename)
end

#load_file(filename) ⇒ Object

Load the file named filename into the editor as a JSON document.



1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
# File 'lib/json/editor.rb', line 1246

def load_file(filename)
  if filename
    if File.directory?(filename)
      Editor.error_dialog(self, "Try to select a JSON file!")
      nil
    else
      @filename = filename
      if data = read_data(filename)
        toplevel.display_status("Loaded data from '#@filename'.")
      end
      display_title
      data
    end
  end
end

#load_location(uri) ⇒ Object

Load the data at location uri into the editor as a JSON document.



1263
1264
1265
1266
1267
1268
1269
# File 'lib/json/editor.rb', line 1263

def load_location(uri)
  data = read_data(uri) or return
  @filename = nil
  toplevel.display_status("Loaded data from '#{uri}'.")
  display_title
  data
end

#location_open(uri = nil) ⇒ Object

Open the data at the location uri, if given. Otherwise open a dialog to ask for the uri.



1184
1185
1186
1187
1188
1189
1190
# File 'lib/json/editor.rb', line 1184

def location_open(uri = nil)
  uri = ask_for_location unless uri
  uri or return
  ask_save if @changed
  data = load_location(uri) or return
  view_new_model Editor.data2model(data)
end

#quitObject

Quit this editor, that is, leave this editor’s main loop.



1152
1153
1154
1155
1156
1157
1158
1159
# File 'lib/json/editor.rb', line 1152

def quit
  ask_save if @changed
  if Gtk.main_level > 0
    destroy
    Gtk.main_quit
  end
  nil
end

#read_data(filename) ⇒ Object

Read a JSON document from the file named filename, parse it into a ruby data structure, and return the data.



1282
1283
1284
1285
1286
1287
1288
1289
1290
# File 'lib/json/editor.rb', line 1282

def read_data(filename)
  open(filename) do |f|
    json = f.read
    return parse_json(json)
  end
rescue => e
  Editor.error_dialog(self, "Failed to parse JSON file: #{e}!")
  return
end

#select_file(message) ⇒ Object

Open a file selecton dialog, displaying message, and return the selected filename or nil, if no file was selected.



1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
# File 'lib/json/editor.rb', line 1294

def select_file(message)
  filename = nil
  fs = FileSelection.new(message)
  fs.set_modal(true)
  @default_dir = File.join(Dir.pwd, '') unless @default_dir
  fs.set_filename(@default_dir)
  fs.set_transient_for(self)
  fs.signal_connect(:destroy) { Gtk.main_quit }
  fs.ok_button.signal_connect(:clicked) do
    filename = fs.filename
    @default_dir = File.join(File.dirname(filename), '')
    fs.destroy
    Gtk.main_quit
  end
  fs.cancel_button.signal_connect(:clicked) do
    fs.destroy
    Gtk.main_quit
  end
  fs.show_all
  Gtk.main
  filename
end

#store_file(path) ⇒ Object

Store the current JSON document to path.



1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
# File 'lib/json/editor.rb', line 1225

def store_file(path)
  if path
    data = Editor.model2data(@treeview.model.iter_first)
    File.open(path + '.tmp', 'wb') do |output|
      data or break
      if @options_menu.pretty_item.active?
        output.puts JSON.pretty_generate(data, :max_nesting => false)
      else
        output.write JSON.generate(data, :max_nesting => false)
      end
    end
    File.rename path + '.tmp', path
    @filename = path
    toplevel.display_status("Saved data to '#@filename'.")
    unchange
  end
rescue SystemCallError => e
  Editor.error_dialog(self, "Failed to store JSON file: #{e}!")
end

#unchangeObject

Sets editor status to unchanged, to indicate that the edited data doesn’t containt unsaved changes.



1118
1119
1120
1121
# File 'lib/json/editor.rb', line 1118

def unchange
  @changed = false
  display_title
end

#view_new_model(model) ⇒ Object

Puts a new model model into the Gtk::TreeView to be edited.



1124
1125
1126
1127
1128
1129
# File 'lib/json/editor.rb', line 1124

def view_new_model(model)
  @treeview.model     = model
  @treeview.expanded  = true
  @treeview.expand_all
  unchange
end