backup_paradise 1.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +452 -0
- data/backup_paradise.gemspec +50 -0
- data/bin/backup_for_ingrid +10 -0
- data/bin/backup_paradise +7 -0
- data/bin/windows_backup_paradise +9 -0
- data/doc/README.gen +390 -0
- data/doc/TODO.md +130 -0
- data/img/BackupParadise_Logo.png +0 -0
- data/lib/backup_paradise/actions/README.md +2 -0
- data/lib/backup_paradise/actions/backup.rb +62 -0
- data/lib/backup_paradise/base/base.rb +529 -0
- data/lib/backup_paradise/base/colours.rb +137 -0
- data/lib/backup_paradise/base/namespace.rb +16 -0
- data/lib/backup_paradise/base/tab.rb +47 -0
- data/lib/backup_paradise/colours/colours.rb +88 -0
- data/lib/backup_paradise/constants/constants.rb +162 -0
- data/lib/backup_paradise/gui/glimmer/libui/backup_for_ingrid/backup_for_ingrid.rb +87 -0
- data/lib/backup_paradise/gui/gtk2/OLD_backup.rb +165 -0
- data/lib/backup_paradise/gui/libui/backup_for_ingrid/backup_for_ingrid.rb +99 -0
- data/lib/backup_paradise/gui/shared_code/simple_backup_widget/simple_backup_widget_module.rb +0 -0
- data/lib/backup_paradise/gui/tk/backup.rb +108 -0
- data/lib/backup_paradise/gui/universal_widgets/simple_backup_widget/simple_backup_widget.rb +921 -0
- data/lib/backup_paradise/images/BACKUP_IMAGE.png +0 -0
- data/lib/backup_paradise/images/right_arrow.png +0 -0
- data/lib/backup_paradise/project/project.rb +40 -0
- data/lib/backup_paradise/requires/require_the_backup_paradise_project.rb +18 -0
- data/lib/backup_paradise/requires/require_yaml.rb +7 -0
- data/lib/backup_paradise/tab/tab.rb +87 -0
- data/lib/backup_paradise/toplevel_methods/cliner.rb +16 -0
- data/lib/backup_paradise/toplevel_methods/config.rb +86 -0
- data/lib/backup_paradise/toplevel_methods/create_and_remove.rb +63 -0
- data/lib/backup_paradise/toplevel_methods/e.rb +16 -0
- data/lib/backup_paradise/toplevel_methods/esystem.rb +19 -0
- data/lib/backup_paradise/toplevel_methods/files_and_directories.rb +181 -0
- data/lib/backup_paradise/toplevel_methods/help.rb +93 -0
- data/lib/backup_paradise/toplevel_methods/misc.rb +153 -0
- data/lib/backup_paradise/toplevel_methods/mountpoint.rb +188 -0
- data/lib/backup_paradise/toplevel_methods/opnn.rb +27 -0
- data/lib/backup_paradise/utility_scripts/backup/backup.rb +1942 -0
- data/lib/backup_paradise/version/version.rb +19 -0
- data/lib/backup_paradise/windows/README.md +1 -0
- data/lib/backup_paradise/windows/windows.rb +101 -0
- data/lib/backup_paradise/www/backup.cgi +63 -0
- data/lib/backup_paradise/yaml/config.yml +82 -0
- data/lib/backup_paradise.rb +5 -0
- data/test/testing_toplevel_functionality.rb +11 -0
- metadata +192 -0
@@ -0,0 +1,921 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# Encoding: UTF-8
|
3
|
+
# frozen_string_literal: true
|
4
|
+
# =========================================================================== #
|
5
|
+
# === BackupParadise::GUI::UniversalWidgets::SimpleBackupWidget
|
6
|
+
#
|
7
|
+
# This is a simple gtk3-widget that can be used to quickly back up data
|
8
|
+
# to an external USB device (or a second harddisc).
|
9
|
+
#
|
10
|
+
# Usage example:
|
11
|
+
#
|
12
|
+
# BackupParadise::GUI::UniversalWidgets::SimpleBackupWidget.new(ARGV)
|
13
|
+
#
|
14
|
+
# =========================================================================== #
|
15
|
+
# require 'backup_paradise/gui/universal_widgets/simple_backup_widget/simple_backup_widget.rb'
|
16
|
+
# =========================================================================== #
|
17
|
+
require 'backup_paradise/base/base.rb'
|
18
|
+
|
19
|
+
module BackupParadise
|
20
|
+
|
21
|
+
module GUI
|
22
|
+
|
23
|
+
module UniversalWidgets
|
24
|
+
|
25
|
+
class SimpleBackupWidget < ::BackupParadise::Base # === BackupParadise::GUI::UniversalWidgets::SimpleBackupWidget
|
26
|
+
|
27
|
+
require 'universal_widgets/base_module/base_module.rb'
|
28
|
+
include ::UniversalWidgets::BaseModule
|
29
|
+
|
30
|
+
# ========================================================================= #
|
31
|
+
# The old ruby-gtk2 code had this:
|
32
|
+
# begin
|
33
|
+
# require 'gtk_paradise/classes/gtk2/information_about_the_harddisc.rb'
|
34
|
+
# rescue LoadError; end
|
35
|
+
# ========================================================================= #
|
36
|
+
|
37
|
+
begin
|
38
|
+
require 'open'
|
39
|
+
rescue LoadError; end
|
40
|
+
|
41
|
+
begin
|
42
|
+
require 'mountpoints'
|
43
|
+
rescue LoadError; end
|
44
|
+
|
45
|
+
# ========================================================================= #
|
46
|
+
# Add backup-paradise related .rb files next:
|
47
|
+
# ========================================================================= #
|
48
|
+
require 'backup_paradise/project/project.rb'
|
49
|
+
require 'backup_paradise/utility_scripts/backup/backup.rb'
|
50
|
+
require 'backup_paradise/actions/backup.rb'
|
51
|
+
require 'backup_paradise/windows/windows.rb'
|
52
|
+
|
53
|
+
# ========================================================================= #
|
54
|
+
# === ARRAY_PREDEFINED_DEVICES
|
55
|
+
# ========================================================================= #
|
56
|
+
ARRAY_PREDEFINED_DEVICES = [
|
57
|
+
ENV['USB1'],
|
58
|
+
ENV['USB2'],
|
59
|
+
ENV['USB3'],
|
60
|
+
ENV['USB4'],
|
61
|
+
ENV['USB5'],
|
62
|
+
ENV['FESTPLATTE1']
|
63
|
+
]
|
64
|
+
|
65
|
+
# ========================================================================= #
|
66
|
+
# === USE_THESE_CSS_RULES
|
67
|
+
# ========================================================================= #
|
68
|
+
USE_THESE_CSS_RULES = '
|
69
|
+
|
70
|
+
.dotted_steelblue_border {
|
71
|
+
border: 2px dotted steelblue;
|
72
|
+
}
|
73
|
+
|
74
|
+
.the_backup_button {
|
75
|
+
border: 3px dotted royalblue;
|
76
|
+
padding: 8px;
|
77
|
+
margin: 4px;
|
78
|
+
color: darkgreen;
|
79
|
+
font-weight: bold;
|
80
|
+
}
|
81
|
+
|
82
|
+
.the_backup_button:hover {
|
83
|
+
color: forestgreen;
|
84
|
+
font-weight: bold;
|
85
|
+
}
|
86
|
+
|
87
|
+
.the_backup_button_for_ingrid {
|
88
|
+
border: 2px dotted royalblue;
|
89
|
+
padding: 5px;
|
90
|
+
margin: 2px;
|
91
|
+
color: royalblue;
|
92
|
+
font-weight: bold;
|
93
|
+
}
|
94
|
+
|
95
|
+
.the_backup_button_for_ingrid_button:hover {
|
96
|
+
color: steelblue;
|
97
|
+
font-weight: bold;
|
98
|
+
}
|
99
|
+
|
100
|
+
'
|
101
|
+
|
102
|
+
# ========================================================================= #
|
103
|
+
# === TITLE
|
104
|
+
# ========================================================================= #
|
105
|
+
TITLE = '💾 Simple Backup Widget 💾'
|
106
|
+
|
107
|
+
# ========================================================================= #
|
108
|
+
# === WIDTH
|
109
|
+
# ========================================================================= #
|
110
|
+
WIDTH = '82% or minimum 1280px'
|
111
|
+
|
112
|
+
# ========================================================================= #
|
113
|
+
# === HEIGHT
|
114
|
+
# ========================================================================= #
|
115
|
+
HEIGHT = '30% or minimum 400px'
|
116
|
+
|
117
|
+
# ========================================================================= #
|
118
|
+
# === USE_THIS_FONT
|
119
|
+
# ========================================================================= #
|
120
|
+
USE_THIS_FONT = :dejavu_condensed_19
|
121
|
+
|
122
|
+
# ========================================================================= #
|
123
|
+
# === LARGER_FONT
|
124
|
+
# ========================================================================= #
|
125
|
+
LARGER_FONT = :dejavu_condensed_21
|
126
|
+
|
127
|
+
# ========================================================================= #
|
128
|
+
# === SMALLER_FONT
|
129
|
+
# ========================================================================= #
|
130
|
+
SMALLER_FONT = :dejavu_condensed_18
|
131
|
+
|
132
|
+
# ========================================================================= #
|
133
|
+
# === USE_THIS_MONOSPACED_FONT
|
134
|
+
# ========================================================================= #
|
135
|
+
USE_THIS_MONOSPACED_FONT = :hack_16
|
136
|
+
|
137
|
+
# ========================================================================= #
|
138
|
+
# === initialize
|
139
|
+
# ========================================================================= #
|
140
|
+
def initialize(
|
141
|
+
commandline_arguments = ARGV,
|
142
|
+
run_already = true
|
143
|
+
)
|
144
|
+
super(:vertical) if use_gtk3?
|
145
|
+
determine_the_GUI_to_be_used(commandline_arguments) # This must come first, even before reset().
|
146
|
+
reset
|
147
|
+
set_commandline_arguments(
|
148
|
+
commandline_arguments
|
149
|
+
)
|
150
|
+
on_delete_event_quit_the_application
|
151
|
+
# self.label_widget.set_markup %Q(
|
152
|
+
# <span size="larger" weight="bold">💾 Backup Script</span>
|
153
|
+
# )
|
154
|
+
run if run_already
|
155
|
+
end
|
156
|
+
|
157
|
+
# ========================================================================= #
|
158
|
+
# === reset (reset tag)
|
159
|
+
# ========================================================================= #
|
160
|
+
def reset
|
161
|
+
super() if respond_to?(:super)
|
162
|
+
reset_the_shared_module # This can come early.
|
163
|
+
reset_the_base_module
|
164
|
+
reset_the_internal_variables
|
165
|
+
infer_the_namespace
|
166
|
+
# ======================================================================= #
|
167
|
+
# === @configuration
|
168
|
+
# ======================================================================= #
|
169
|
+
@configuration = [true, __dir__, namespace?]
|
170
|
+
# ======================================================================= #
|
171
|
+
# === Set the title, width, height and the font in use.
|
172
|
+
# ======================================================================= #
|
173
|
+
title_width_height_font(TITLE, WIDTH, HEIGHT, USE_THIS_FONT)
|
174
|
+
if use_gtk3?
|
175
|
+
handle_CSS_rules
|
176
|
+
end
|
177
|
+
infer_the_size_automatically
|
178
|
+
# ======================================================================= #
|
179
|
+
# === @object_rbackup
|
180
|
+
# ======================================================================= #
|
181
|
+
# @object_rbackup = BackupParadise::Backup.new(nil, :do_not_run_yet)
|
182
|
+
# ======================================================================= #
|
183
|
+
# === @object_hdd_info
|
184
|
+
# ======================================================================= #
|
185
|
+
# @object_hdd_info = ::Gtk::InformationAboutTheHarddisc.new
|
186
|
+
end
|
187
|
+
|
188
|
+
# ========================================================================= #
|
189
|
+
# === favicon?
|
190
|
+
# ========================================================================= #
|
191
|
+
def favicon?
|
192
|
+
:tabble
|
193
|
+
end
|
194
|
+
|
195
|
+
# ========================================================================= #
|
196
|
+
# === smaller_font?
|
197
|
+
# ========================================================================= #
|
198
|
+
def smaller_font?
|
199
|
+
SMALLER_FONT
|
200
|
+
end
|
201
|
+
|
202
|
+
# ========================================================================= #
|
203
|
+
# === update_fdisk
|
204
|
+
#
|
205
|
+
# Use this if you wanna get new fdisk information.
|
206
|
+
#
|
207
|
+
# Or use this:
|
208
|
+
#
|
209
|
+
# `fdisk -l`.gsub!(%r[^(!?/dev).*\n], '')
|
210
|
+
#
|
211
|
+
# ========================================================================= #
|
212
|
+
def update_fdisk
|
213
|
+
return `fdisk -l`.split("\n").delete_if { |line| line !~ /^\/dev/ }.join("\n")
|
214
|
+
end
|
215
|
+
|
216
|
+
# ========================================================================= #
|
217
|
+
# === handle_CSS_rules (CSS tag)
|
218
|
+
# ========================================================================= #
|
219
|
+
def handle_CSS_rules
|
220
|
+
use_gtk_paradise_project_css_file
|
221
|
+
append_project_css_file
|
222
|
+
more_CSS_then_apply_it(USE_THESE_CSS_RULES)
|
223
|
+
end
|
224
|
+
|
225
|
+
# ========================================================================= #
|
226
|
+
# === reset_the_shared_module
|
227
|
+
#
|
228
|
+
# This method can be used for ruby-gtk3 and ruby-libui, among other
|
229
|
+
# toolkits.
|
230
|
+
# ========================================================================= #
|
231
|
+
def reset_the_shared_module
|
232
|
+
# ======================================================================= #
|
233
|
+
# === @file_chooser_dialog
|
234
|
+
# ======================================================================= #
|
235
|
+
@file_chooser_dialog = nil
|
236
|
+
# ======================================================================= #
|
237
|
+
# === @dataset_from_the_config_file
|
238
|
+
# ======================================================================= #
|
239
|
+
@dataset_from_the_config_file = nil
|
240
|
+
if File.exist? BackupParadise.file_config?
|
241
|
+
@dataset_from_the_config_file = YAML.load_file(BackupParadise.file_config?)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# ========================================================================= #
|
246
|
+
# === padding?
|
247
|
+
# ========================================================================= #
|
248
|
+
def padding?
|
249
|
+
0
|
250
|
+
end
|
251
|
+
|
252
|
+
# ========================================================================= #
|
253
|
+
# === border_size?
|
254
|
+
# ========================================================================= #
|
255
|
+
def border_size?
|
256
|
+
0
|
257
|
+
end
|
258
|
+
|
259
|
+
# ========================================================================= #
|
260
|
+
# === create_the_backup_audio_button
|
261
|
+
# ========================================================================= #
|
262
|
+
def create_the_backup_audio_button
|
263
|
+
# ======================================================================= #
|
264
|
+
# === @button_backup_audio
|
265
|
+
# ======================================================================= #
|
266
|
+
@button_backup_audio = button('Backup Audio')
|
267
|
+
@button_backup_audio.hint = 'This button is ad-hoc code to quickly '\
|
268
|
+
'copy all local songs on my home layout. You can modify this '\
|
269
|
+
'by modifying the config.yml file and changing the entry called '\
|
270
|
+
'<b>local_audio_directory</b>.'
|
271
|
+
@button_backup_audio.on_clicked {
|
272
|
+
# ===================================================================== #
|
273
|
+
# First, if the config-dataset exists, sync the combo-box entry.
|
274
|
+
# ===================================================================== #
|
275
|
+
if @dataset_from_the_config_file
|
276
|
+
local_audio_directory = @dataset_from_the_config_file['local_audio_directory'].to_s
|
277
|
+
entry_left?.set_text(
|
278
|
+
local_audio_directory
|
279
|
+
)
|
280
|
+
end
|
281
|
+
do_backup_my_songs
|
282
|
+
}
|
283
|
+
end
|
284
|
+
|
285
|
+
# ========================================================================= #
|
286
|
+
# === create_the_backup_button
|
287
|
+
# ========================================================================= #
|
288
|
+
def create_the_backup_button
|
289
|
+
# ======================================================================= #
|
290
|
+
# === @button_backup
|
291
|
+
# ======================================================================= #
|
292
|
+
@button_backup = button('_Backup the data', self, :use_mnemonics) {
|
293
|
+
:do_backup_the_data
|
294
|
+
}
|
295
|
+
@button_backup.clear_background
|
296
|
+
@button_backup.on_hover(:lightblue)
|
297
|
+
@button_backup.pad8px
|
298
|
+
@button_backup.css_class('the_backup_button')
|
299
|
+
@button_backup.set_size_request(16, 25)
|
300
|
+
@button_backup.set_border_width(2)
|
301
|
+
@button_backup.hint =
|
302
|
+
"Click this button to <b>backup your data</b>. This works for both "\
|
303
|
+
"directories, as well as individual files and special instructions. "\
|
304
|
+
"Special instructions are indicated via a leading : character on "\
|
305
|
+
"the top-left hand side.\n\n"\
|
306
|
+
"Make sure that the USB device(s) are properly connected before "\
|
307
|
+
"clicking any button, though."
|
308
|
+
end
|
309
|
+
|
310
|
+
# ========================================================================= #
|
311
|
+
# === do_backup_the_data
|
312
|
+
# ========================================================================= #
|
313
|
+
def do_backup_the_data(
|
314
|
+
from = from?,
|
315
|
+
to = to?
|
316
|
+
)
|
317
|
+
@label_showing_results.set_text(
|
318
|
+
'Command that will be run: '+"\n\n"+
|
319
|
+
' <b>cp -rv '+from+' '+to+"</b>\n"
|
320
|
+
)
|
321
|
+
@label_showing_results.do_markify
|
322
|
+
Thread.new {
|
323
|
+
e 'Backing up the data next, from `'+
|
324
|
+
sfile(from)+'` to `'+sfile(to)+'`.'
|
325
|
+
copy_from_to(from, to)
|
326
|
+
}
|
327
|
+
end
|
328
|
+
|
329
|
+
# ========================================================================= #
|
330
|
+
# === backup_ingrid_directory
|
331
|
+
#
|
332
|
+
# This is a method for a custom-backup. Other users won't need to use
|
333
|
+
# this method.
|
334
|
+
# ========================================================================= #
|
335
|
+
def backup_ingrid_directory
|
336
|
+
BackupParadise::Windows.backup_ingrid_directory
|
337
|
+
end; alias do_backup_for_ingrid backup_ingrid_directory # === do_backup_for_ingrid
|
338
|
+
|
339
|
+
# ========================================================================= #
|
340
|
+
# === return_backup_complete_message
|
341
|
+
# ========================================================================= #
|
342
|
+
def return_backup_complete_message
|
343
|
+
'Backup complete! Time finish at: '+time_now?
|
344
|
+
end
|
345
|
+
|
346
|
+
# ========================================================================= #
|
347
|
+
# === run_file_chooser_dialog
|
348
|
+
# ========================================================================= #
|
349
|
+
def run_file_chooser_dialog(
|
350
|
+
_ = @file_chooser_dialog
|
351
|
+
)
|
352
|
+
if _ and (_.run == ::Gtk::ResponseType::ACCEPT)
|
353
|
+
filename = _.filename
|
354
|
+
e "filename = #{filename}"
|
355
|
+
e "uri = #{_.uri}"
|
356
|
+
entry_left?.set_text(filename)
|
357
|
+
@file_chooser_dialog.destroy
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
# ========================================================================= #
|
362
|
+
# === create_file_chooser_dialog_widget
|
363
|
+
# ========================================================================= #
|
364
|
+
def create_file_chooser_dialog_widget
|
365
|
+
@file_chooser_dialog = ::Gtk::FileChooserDialog.new(
|
366
|
+
self: self,
|
367
|
+
title: 'Choose a file or directory',
|
368
|
+
action: ::Gtk::FileChooserAction::OPEN,
|
369
|
+
buttons: [[::Gtk::Stock::OPEN, ::Gtk::ResponseType::ACCEPT],
|
370
|
+
[::Gtk::Stock::CANCEL, ::Gtk::ResponseType::CANCEL]]
|
371
|
+
)
|
372
|
+
# ======================================================================= #
|
373
|
+
# === /home/Temp
|
374
|
+
# ======================================================================= #
|
375
|
+
if File.directory? '/home/Temp/'
|
376
|
+
@file_chooser_dialog.add_shortcut_folder('/home/Temp/')
|
377
|
+
end
|
378
|
+
# ======================================================================= #
|
379
|
+
# === /home/x/Temp
|
380
|
+
# ======================================================================= #
|
381
|
+
if File.directory? '/home/x/Temp/'
|
382
|
+
@file_chooser_dialog.add_shortcut_folder('/home/x/Temp/')
|
383
|
+
end
|
384
|
+
# ======================================================================= #
|
385
|
+
# === /home/x/data/
|
386
|
+
# ======================================================================= #
|
387
|
+
if File.directory? HOME_DIRECTORY_OF_THE_USER_X+'data/'
|
388
|
+
@file_chooser_dialog.add_shortcut_folder(HOME_DIRECTORY_OF_THE_USER_X+'data/')
|
389
|
+
end
|
390
|
+
# ======================================================================= #
|
391
|
+
# Add the audio-directory shortcut, defined in the yaml file.
|
392
|
+
# ======================================================================= #
|
393
|
+
if @dataset_from_the_config_file and
|
394
|
+
@dataset_from_the_config_file.has_key?('local_audio_directory')
|
395
|
+
@file_chooser_dialog.add_shortcut_folder(
|
396
|
+
@dataset_from_the_config_file['local_audio_directory'].to_s
|
397
|
+
)
|
398
|
+
end
|
399
|
+
@file_chooser_dialog.add_shortcut_folder('/Ingrid')
|
400
|
+
@file_chooser_dialog.current_folder = Dir.pwd
|
401
|
+
@file_chooser_dialog.do_show_hidden_files
|
402
|
+
# @file_chooser_dialog.destroy
|
403
|
+
end
|
404
|
+
|
405
|
+
# ========================================================================= #
|
406
|
+
# === copy_this_file
|
407
|
+
# ========================================================================= #
|
408
|
+
def copy_this_file(from, b)
|
409
|
+
::BackupParadise.copy_this_file(from, b)
|
410
|
+
end
|
411
|
+
|
412
|
+
# ========================================================================= #
|
413
|
+
# === larger_font?
|
414
|
+
# ========================================================================= #
|
415
|
+
def larger_font?
|
416
|
+
LARGER_FONT
|
417
|
+
end
|
418
|
+
|
419
|
+
# ========================================================================= #
|
420
|
+
# === do_transfer_a_single_file
|
421
|
+
# ========================================================================= #
|
422
|
+
def do_transfer_a_single_file(
|
423
|
+
_ = entry_left?.text?.strip,
|
424
|
+
target = onto?
|
425
|
+
)
|
426
|
+
target = target.dup if target.frozen?
|
427
|
+
target << File.basename(_)
|
428
|
+
|
429
|
+
if _.empty?
|
430
|
+
e 'Please supply a file to transfer.'
|
431
|
+
else
|
432
|
+
e "Now trying to copy #{_} to #{target}."
|
433
|
+
Thread.new {
|
434
|
+
copy_this_file(_, target)
|
435
|
+
pop_up_this_text_over_that_widget(return_backup_complete_message, @button_backup)
|
436
|
+
}
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
# ========================================================================= #
|
441
|
+
# === main_target?
|
442
|
+
#
|
443
|
+
# This method will "return" our main target.
|
444
|
+
# ========================================================================= #
|
445
|
+
def main_target?
|
446
|
+
@backup_to_this_target.text?
|
447
|
+
end
|
448
|
+
|
449
|
+
# ========================================================================= #
|
450
|
+
# === do_backup_my_songs
|
451
|
+
# ========================================================================= #
|
452
|
+
def do_backup_my_songs(
|
453
|
+
to =
|
454
|
+
("#{onto?}#{File.basename(entry_left?.text?)}/").squeeze('/')
|
455
|
+
)
|
456
|
+
to.squeeze!('/')
|
457
|
+
Thread.new {
|
458
|
+
BackupParadise.simple_backup(
|
459
|
+
entry_left?.text?, to
|
460
|
+
)
|
461
|
+
pop_up_this_text_over_that_widget(
|
462
|
+
return_backup_complete_message,
|
463
|
+
@button_backup_audio
|
464
|
+
)
|
465
|
+
}
|
466
|
+
end
|
467
|
+
|
468
|
+
# ========================================================================= #
|
469
|
+
# === time_now?
|
470
|
+
# ========================================================================= #
|
471
|
+
def time_now?
|
472
|
+
return ::Time.now.strftime('%d.%m.%Y, %H:%M:%S')
|
473
|
+
end
|
474
|
+
|
475
|
+
# ========================================================================= #
|
476
|
+
# === entry1?
|
477
|
+
# ========================================================================= #
|
478
|
+
def entry1?
|
479
|
+
@entry1_for_the_backup_from_value
|
480
|
+
end; alias entry_left? entry1? # === entry_left?
|
481
|
+
|
482
|
+
# ========================================================================= #
|
483
|
+
# === create_the_entries (entries tag)
|
484
|
+
# ========================================================================= #
|
485
|
+
def create_the_entries
|
486
|
+
# ======================================================================= #
|
487
|
+
# === @entry1_for_the_backup_from_value
|
488
|
+
# ======================================================================= #
|
489
|
+
@entry1_for_the_backup_from_value = entry
|
490
|
+
@entry1_for_the_backup_from_value.pad4px
|
491
|
+
@entry1_for_the_backup_from_value.bblack1
|
492
|
+
@entry1_for_the_backup_from_value.very_light_yellow_background
|
493
|
+
# ======================================================================= #
|
494
|
+
# === @entry2_for_the_backup_onto_value
|
495
|
+
# ======================================================================= #
|
496
|
+
@entry2_for_the_backup_onto_value = entry
|
497
|
+
@entry2_for_the_backup_onto_value.pad4px
|
498
|
+
@entry2_for_the_backup_onto_value.bblack1
|
499
|
+
@entry2_for_the_backup_onto_value.very_light_yellow_background
|
500
|
+
@entry2_for_the_backup_onto_value.width_height(250, 50)
|
501
|
+
end
|
502
|
+
|
503
|
+
# ========================================================================= #
|
504
|
+
# === from?
|
505
|
+
#
|
506
|
+
# This method has to keep in mind that Strings such as ":ingrid" are
|
507
|
+
# used. This indicates a symbol which has to be treated in a special
|
508
|
+
# manner.
|
509
|
+
#
|
510
|
+
# Furthermore, only directories will have a '/' appended; files must
|
511
|
+
# not have a '/' appended.
|
512
|
+
# ========================================================================= #
|
513
|
+
def from?(
|
514
|
+
i = @entry1_for_the_backup_from_value.text?
|
515
|
+
)
|
516
|
+
if i.is_a?(String) and i.start_with?(':')
|
517
|
+
case i.delete(':').to_sym
|
518
|
+
# ===================================================================== #
|
519
|
+
# === :ingrid
|
520
|
+
# ===================================================================== #
|
521
|
+
when :ingrid
|
522
|
+
i = 'C/ingrid/'
|
523
|
+
end
|
524
|
+
end
|
525
|
+
if i.is_a?(String) and i.frozen?
|
526
|
+
i = i.dup
|
527
|
+
end
|
528
|
+
i.squeeze!('/')
|
529
|
+
if File.directory?(i) and !i.end_with?('/')
|
530
|
+
i << '/'
|
531
|
+
end
|
532
|
+
return i
|
533
|
+
end
|
534
|
+
|
535
|
+
# ========================================================================= #
|
536
|
+
# === copy_from_to
|
537
|
+
#
|
538
|
+
# This is the method that can be used for backing up the data.
|
539
|
+
# ========================================================================= #
|
540
|
+
def copy_from_to(
|
541
|
+
from = from?,
|
542
|
+
to = onto?
|
543
|
+
)
|
544
|
+
unless File.directory? from
|
545
|
+
e "#{sfile(from)} should be a directory."
|
546
|
+
end
|
547
|
+
if from == 'C/ingrid/'
|
548
|
+
# ====================================================================== #
|
549
|
+
# The first entry is a special case, applying to only one particular
|
550
|
+
# situation on Windows. It is retained here on an ad-hoc basis,
|
551
|
+
# but it may be better to move this into another location.
|
552
|
+
# ====================================================================== #
|
553
|
+
BackupParadise::Windows.backup_ingrid_directory
|
554
|
+
elsif File.file?(from)
|
555
|
+
# ====================================================================== #
|
556
|
+
# Backup files here.
|
557
|
+
# ====================================================================== #
|
558
|
+
do_transfer_a_single_file
|
559
|
+
else
|
560
|
+
# ====================================================================== #
|
561
|
+
# Backup directories here.
|
562
|
+
# ====================================================================== #
|
563
|
+
if from.is_a?(String) and from.start_with?(':')
|
564
|
+
case from.delete(':').to_sym
|
565
|
+
# ===================================================================== #
|
566
|
+
# === :everything
|
567
|
+
#
|
568
|
+
# This will default to the registered action stored in the
|
569
|
+
# config.yml file.
|
570
|
+
# ===================================================================== #
|
571
|
+
when :everything
|
572
|
+
if @dataset_from_the_config_file
|
573
|
+
i = @dataset_from_the_config_file['backup_these_directories']
|
574
|
+
BackupParadise::Actions.backup {{
|
575
|
+
backup_these_directories: i,
|
576
|
+
where_to: to
|
577
|
+
}}
|
578
|
+
else
|
579
|
+
e 'No file called config.yml was found. Defaulting to the'
|
580
|
+
e 'current working directory thus.'
|
581
|
+
i = File.absolute_path("#{Dir.pwd}/")
|
582
|
+
end
|
583
|
+
end
|
584
|
+
else
|
585
|
+
begin
|
586
|
+
Thread.new {
|
587
|
+
@spinner.is_active # go_and_spin_now
|
588
|
+
FileUtils.cp_r(from, to)
|
589
|
+
pop_up_this_text_over_that_widget(
|
590
|
+
return_backup_complete_message, @button_backup
|
591
|
+
)
|
592
|
+
@spinner.stop_spinning
|
593
|
+
}
|
594
|
+
rescue Exception => error
|
595
|
+
pp error
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
# ========================================================================= #
|
602
|
+
# === backup_audio_button?
|
603
|
+
# ========================================================================= #
|
604
|
+
def backup_audio_button?
|
605
|
+
@button_backup_audio
|
606
|
+
end
|
607
|
+
|
608
|
+
# ========================================================================= #
|
609
|
+
# === backup_ingrid_button?
|
610
|
+
# ========================================================================= #
|
611
|
+
def backup_ingrid_button?
|
612
|
+
@button_ingrid
|
613
|
+
end
|
614
|
+
|
615
|
+
# ========================================================================= #
|
616
|
+
# === backup_button?
|
617
|
+
# ========================================================================= #
|
618
|
+
def backup_button?
|
619
|
+
@button_backup
|
620
|
+
end
|
621
|
+
|
622
|
+
# ========================================================================= #
|
623
|
+
# === create_the_file_chooser_button
|
624
|
+
# ========================================================================= #
|
625
|
+
def create_the_file_chooser_button
|
626
|
+
# ======================================================================= #
|
627
|
+
# === @button_choose_file
|
628
|
+
# ======================================================================= #
|
629
|
+
@button_choose_file = button('Choose file')
|
630
|
+
@button_choose_file.on_clicked {
|
631
|
+
create_file_chooser_dialog_widget
|
632
|
+
run_file_chooser_dialog
|
633
|
+
}
|
634
|
+
end
|
635
|
+
|
636
|
+
# ========================================================================= #
|
637
|
+
# === choose_file_button?
|
638
|
+
# ========================================================================= #
|
639
|
+
def choose_file_button?
|
640
|
+
@button_choose_file
|
641
|
+
end
|
642
|
+
|
643
|
+
# ========================================================================= #
|
644
|
+
# === create_the_label_showing_results
|
645
|
+
# ========================================================================= #
|
646
|
+
def create_the_label_showing_results
|
647
|
+
@label_showing_results = label
|
648
|
+
end
|
649
|
+
|
650
|
+
# ========================================================================= #
|
651
|
+
# === create_the_buttons (buttons tag, button tag)
|
652
|
+
# ========================================================================= #
|
653
|
+
def create_the_buttons
|
654
|
+
create_the_file_chooser_button
|
655
|
+
create_the_backup_button
|
656
|
+
create_the_backup_audio_button
|
657
|
+
create_the_ingrid_button if is_on_roebe?
|
658
|
+
end
|
659
|
+
|
660
|
+
# ========================================================================= #
|
661
|
+
# === onto
|
662
|
+
# ========================================================================= #
|
663
|
+
def onto?
|
664
|
+
return "#{@entry2_for_the_backup_onto_value.text?}/".squeeze('/')
|
665
|
+
end; alias to? onto? # === to?
|
666
|
+
|
667
|
+
# ========================================================================= #
|
668
|
+
# === create_the_grid (grid tag)
|
669
|
+
# ========================================================================= #
|
670
|
+
def create_the_grid
|
671
|
+
# ======================================================================= #
|
672
|
+
# === @grid
|
673
|
+
# ======================================================================= #
|
674
|
+
@grid = default_grid
|
675
|
+
@grid.pad10px
|
676
|
+
@grid.css_class('dotted_steelblue_border')
|
677
|
+
@grid.set_size_request(100, 50)
|
678
|
+
@grid.row_spacing = 5
|
679
|
+
@grid.line_spacing = 5
|
680
|
+
label_backup_from = text('Backup from:')
|
681
|
+
label_backup_from.make_bold
|
682
|
+
label_backup_from.hint = 'Input which directory '\
|
683
|
+
'you wish to back up. Use the combo-box entry '\
|
684
|
+
'below this widget, or the entry below '\
|
685
|
+
'that combo-box.'
|
686
|
+
@grid.left(label_backup_from)
|
687
|
+
|
688
|
+
label_backup_onto = text('Backup onto:')
|
689
|
+
label_backup_onto.make_bold
|
690
|
+
label_backup_onto.hint = 'Input the target device onto which we will '\
|
691
|
+
'copy the data onto.'
|
692
|
+
@grid.right(label_backup_onto)
|
693
|
+
|
694
|
+
# ======================================================================= #
|
695
|
+
# Next we will add the two main combo-boxes.
|
696
|
+
# ======================================================================= #
|
697
|
+
@grid.left(@combo_box_backup_from)
|
698
|
+
@grid.right(@combo_box_backup_onto)
|
699
|
+
@grid.left(@entry1_for_the_backup_from_value)
|
700
|
+
@grid.right(@entry2_for_the_backup_onto_value)
|
701
|
+
end
|
702
|
+
|
703
|
+
# ========================================================================= #
|
704
|
+
# === create_the_combo_boxes (combo tag)
|
705
|
+
# ========================================================================= #
|
706
|
+
def create_the_combo_boxes
|
707
|
+
# ======================================================================= #
|
708
|
+
# === @combo_box_backup_from
|
709
|
+
#
|
710
|
+
# This is the combo-box that keeps the core entries, such as
|
711
|
+
# "/home/x/songs" and so forth.
|
712
|
+
# ======================================================================= #
|
713
|
+
@combo_box_backup_from = combo_box
|
714
|
+
@combo_box_backup_from.bblack1
|
715
|
+
@combo_box_backup_from.set_border_width(2)
|
716
|
+
# ======================================================================= #
|
717
|
+
# Next we will populate the combo-box with proper entries:
|
718
|
+
# ======================================================================= #
|
719
|
+
_ = BackupParadise.backup_these_directories?.map {|entry| "#{entry}/".squeeze('/') }
|
720
|
+
_.prepend(':everything')
|
721
|
+
_.prepend(':ingrid') if is_on_roebe?
|
722
|
+
@combo_box_backup_from.populate(_)
|
723
|
+
@combo_box_backup_from.the_first_entry_is_active
|
724
|
+
@combo_box_backup_from.hint =
|
725
|
+
':everything means to backup the default action, as-is. If you '\
|
726
|
+
'need a more fine-tuned level of control then simply backup only '\
|
727
|
+
'some directories, or use the entry to the right side of this '\
|
728
|
+
'combo box to backup only individual directories or files.'
|
729
|
+
# ======================================================================= #
|
730
|
+
# === @combo_box_backup_onto
|
731
|
+
# ======================================================================= #
|
732
|
+
@combo_box_backup_onto = combo_box
|
733
|
+
@combo_box_backup_onto.bblack1
|
734
|
+
@combo_box_backup_onto.set_border_width(2)
|
735
|
+
scan_for_mountpoints_then_update_the_appropriate_combo_box
|
736
|
+
end
|
737
|
+
|
738
|
+
# ========================================================================= #
|
739
|
+
# === sync_the_combo_box_values_onto_the_entries_below
|
740
|
+
# ========================================================================= #
|
741
|
+
def sync_the_combo_box_values_onto_the_entries_below
|
742
|
+
_ = @combo_box_backup_from.text?.to_s
|
743
|
+
entry1?.set_text(_)
|
744
|
+
sync_the_second_entry
|
745
|
+
end
|
746
|
+
|
747
|
+
# ========================================================================= #
|
748
|
+
# === sync_the_second_entry
|
749
|
+
# ========================================================================= #
|
750
|
+
def sync_the_second_entry
|
751
|
+
entry2?.set_text(
|
752
|
+
@combo_box_backup_onto.text?.to_s
|
753
|
+
)
|
754
|
+
end
|
755
|
+
|
756
|
+
# ========================================================================= #
|
757
|
+
# === entry2?
|
758
|
+
# ========================================================================= #
|
759
|
+
def entry2?
|
760
|
+
@entry2_for_the_backup_onto_value
|
761
|
+
end
|
762
|
+
|
763
|
+
# ========================================================================= #
|
764
|
+
# === do_handle_the_proper_syncing_when_the_combo_box_entries_are_changed
|
765
|
+
# ========================================================================= #
|
766
|
+
def do_handle_the_proper_syncing_when_the_combo_box_entries_are_changed
|
767
|
+
# ======================================================================= #
|
768
|
+
# Sync any change made in the combo box onto the associated entry.
|
769
|
+
# ======================================================================= #
|
770
|
+
sync_connect(@combo_box_backup_from, entry1?)
|
771
|
+
sync_connect(@combo_box_backup_onto, entry2?)
|
772
|
+
end
|
773
|
+
|
774
|
+
# ========================================================================= #
|
775
|
+
# === scan_for_mountpoints_then_update_the_appropriate_combo_box
|
776
|
+
# ========================================================================= #
|
777
|
+
def scan_for_mountpoints_then_update_the_appropriate_combo_box
|
778
|
+
if Object.const_defined? :Mountpoints
|
779
|
+
@combo_box_backup_onto.clear_old_datapoints
|
780
|
+
@combo_box_backup_onto.populate(Mountpoints[])
|
781
|
+
@combo_box_backup_onto.the_first_entry_is_active
|
782
|
+
sync_the_second_entry
|
783
|
+
end
|
784
|
+
end
|
785
|
+
|
786
|
+
# ========================================================================= #
|
787
|
+
# === create_the_skeleton (create tag, skeleton tag)
|
788
|
+
# ========================================================================= #
|
789
|
+
def create_the_skeleton
|
790
|
+
create_the_label_showing_results
|
791
|
+
create_the_buttons
|
792
|
+
create_the_entries
|
793
|
+
create_the_combo_boxes
|
794
|
+
create_the_grid
|
795
|
+
end
|
796
|
+
|
797
|
+
# ========================================================================= #
|
798
|
+
# === run (run tag)
|
799
|
+
# ========================================================================= #
|
800
|
+
def run
|
801
|
+
run_super
|
802
|
+
end
|
803
|
+
|
804
|
+
# ========================================================================= #
|
805
|
+
# === BackupParadise::GUI::Gtk::SimpleBackupWidget.run
|
806
|
+
# ========================================================================= #
|
807
|
+
def self.run(
|
808
|
+
i = ARGV
|
809
|
+
)
|
810
|
+
require 'gtk_paradise/run'
|
811
|
+
_ = ::BackupParadise::GUI::Gtk::SimpleBackupWidget.new(i)
|
812
|
+
r = ::Gtk.run
|
813
|
+
r << _
|
814
|
+
_.set_parent_widget(r)
|
815
|
+
r.automatic_size_then_automatic_title
|
816
|
+
r.enable_quick_exit
|
817
|
+
r.set_background :white
|
818
|
+
r.is_resizable # <- This line was added due to a possible prior .maximize action.
|
819
|
+
r.top_left_then_run
|
820
|
+
end; self.instance_eval { alias start_gui_application run } # === BackupParadise::GUI::Gtk::SimpleBackupWidget.start_gui_application
|
821
|
+
|
822
|
+
# ========================================================================= #
|
823
|
+
# === BackupParadise::GUI::UniversalWidgets::SimpleBackupWidget[]
|
824
|
+
# ========================================================================= #
|
825
|
+
def self.[](i = ARGV)
|
826
|
+
new(i)
|
827
|
+
end
|
828
|
+
|
829
|
+
# ========================================================================= #
|
830
|
+
# === connect_the_skeleton (connect tag)
|
831
|
+
# ========================================================================= #
|
832
|
+
def connect_the_skeleton
|
833
|
+
abort_on_exception
|
834
|
+
|
835
|
+
outer_vbox = create_vbox # A new vbox.
|
836
|
+
|
837
|
+
header_bar = return_default_header_bar { :with_close_button_and_inferred_title }
|
838
|
+
header_bar.spacing = 10
|
839
|
+
header_bar.add_left(@button_choose_file)
|
840
|
+
header_bar.add_left(@button_backup_audio)
|
841
|
+
@spinner = default_spinner
|
842
|
+
@spinner.is_inactive
|
843
|
+
header_bar.add_right(@spinner)
|
844
|
+
button = icon_theme_image('daytime-sunset-symbolic.symbolic')
|
845
|
+
button.hint = 'Click this icon to show which devices are mounted and '\
|
846
|
+
'update the combo-box showing all mounted devices.'
|
847
|
+
button.on_clicked {
|
848
|
+
scan_for_mountpoints_then_update_the_appropriate_combo_box
|
849
|
+
}
|
850
|
+
header_bar.add_left(button)
|
851
|
+
outer_vbox.minimal(header_bar, 1)
|
852
|
+
outer_vbox.minimal(horizontal_separator, 1)
|
853
|
+
outer_vbox.minimal(@grid, 1)
|
854
|
+
outer_vbox.minimal(horizontal_separator, 1)
|
855
|
+
hbox = create_hbox
|
856
|
+
_ = BackupParadise.project_base_directory?+'images/right_arrow.png'
|
857
|
+
if File.exist? _
|
858
|
+
hbox.minimal(image(_), 5)
|
859
|
+
end
|
860
|
+
hbox.maximal(@button_backup)
|
861
|
+
outer_vbox.minimal(hbox)
|
862
|
+
outer_vbox.minimal(horizontal_separator)
|
863
|
+
if is_on_roebe?
|
864
|
+
outer_vbox.minimal(@button_ingrid)
|
865
|
+
outer_vbox.minimal(horizontal_separator)
|
866
|
+
end
|
867
|
+
outer_vbox.minimal(@label_showing_results)
|
868
|
+
outer_vbox.minimal(horizontal_separator)
|
869
|
+
|
870
|
+
window = create_window_or_runner
|
871
|
+
window << outer_vbox
|
872
|
+
|
873
|
+
properly_prepare_this_window(window,
|
874
|
+
{
|
875
|
+
title: title?,
|
876
|
+
font: font?,
|
877
|
+
width: width?,
|
878
|
+
height: height?,
|
879
|
+
padding: padding?,
|
880
|
+
border_size: border_size?
|
881
|
+
}
|
882
|
+
)
|
883
|
+
window.show_all
|
884
|
+
window.top_left
|
885
|
+
do_all_startup_related_actions
|
886
|
+
run_main
|
887
|
+
end
|
888
|
+
|
889
|
+
# ========================================================================= #
|
890
|
+
# === do_all_startup_related_actions
|
891
|
+
# ========================================================================= #
|
892
|
+
def do_all_startup_related_actions
|
893
|
+
sync_the_combo_box_values_onto_the_entries_below
|
894
|
+
do_handle_the_proper_syncing_when_the_combo_box_entries_are_changed
|
895
|
+
end
|
896
|
+
|
897
|
+
# ========================================================================= #
|
898
|
+
# === create_the_ingrid_button
|
899
|
+
# ========================================================================= #
|
900
|
+
def create_the_ingrid_button
|
901
|
+
# ======================================================================= #
|
902
|
+
# === @button_ingrid
|
903
|
+
# ======================================================================= #
|
904
|
+
@button_ingrid = button('Backup _ingrid', self, :use_mnemonics) {
|
905
|
+
:do_backup_for_ingrid
|
906
|
+
}
|
907
|
+
@button_ingrid.clear_background
|
908
|
+
@button_ingrid.css_class('the_backup_button_for_ingrid')
|
909
|
+
@button_backup.on_hover(:lightblue)
|
910
|
+
@button_ingrid.pad8px
|
911
|
+
@button_ingrid.set_size_request(16, 25)
|
912
|
+
@button_ingrid.set_border_width(2)
|
913
|
+
@button_ingrid.hint = 'This will backup c:\ingrid to '\
|
914
|
+
'the appropriate external USB device.'
|
915
|
+
end
|
916
|
+
|
917
|
+
end; end; end; end
|
918
|
+
|
919
|
+
if __FILE__ == $PROGRAM_NAME
|
920
|
+
BackupParadise::GUI::UniversalWidgets::SimpleBackupWidget.new(ARGV)
|
921
|
+
end # backupwidget
|