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.



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
1096
# File 'lib/json/editor.rb', line 1050

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.



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
1345
1346
# File 'lib/json/editor.rb', line 1320

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.



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

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.



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

def change
  @changed = true
  display_title
end

#clearObject

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



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

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.



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

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.



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

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.



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

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.



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

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.



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

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.



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

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

#file_save_asObject

Save the current file as the filename



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

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.



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

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.



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

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.



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

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.



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

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.



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

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.



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

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.



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

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.



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

def unchange
  @changed = false
  display_title
end

#view_new_model(model) ⇒ Object

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



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

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