Piggy 0.4.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/CHANGES.txt +91 -0
  2. data/INSTALL.txt +77 -0
  3. data/LICENCE.txt +339 -0
  4. data/README.txt +27 -0
  5. data/UNINSTALL.txt +24 -0
  6. data/bin/directory_diff +6 -0
  7. data/bin/ftp_browser +6 -0
  8. data/bin/piggy +6 -0
  9. data/lib/directory_diff.rb +35 -0
  10. data/lib/ftp_browser.rb +33 -0
  11. data/lib/icons/auto-select-for-del.ico +0 -0
  12. data/lib/icons/auto-select-right.ico +0 -0
  13. data/lib/icons/auto-upload-right.ico +0 -0
  14. data/lib/icons/back.ico +0 -0
  15. data/lib/icons/checked.ico +0 -0
  16. data/lib/icons/copy.png +0 -0
  17. data/lib/icons/cut.png +0 -0
  18. data/lib/icons/dir.ico +0 -0
  19. data/lib/icons/dirup.ico +0 -0
  20. data/lib/icons/file.ico +0 -0
  21. data/lib/icons/fileopen.png +0 -0
  22. data/lib/icons/filesave.ico +0 -0
  23. data/lib/icons/gallery.ico +0 -0
  24. data/lib/icons/generate.ico +0 -0
  25. data/lib/icons/minus.png +0 -0
  26. data/lib/icons/move-right-dir.ico +0 -0
  27. data/lib/icons/move-right-file.ico +0 -0
  28. data/lib/icons/newer-file.ico +0 -0
  29. data/lib/icons/next-image.ico +0 -0
  30. data/lib/icons/paste.png +0 -0
  31. data/lib/icons/plus.png +0 -0
  32. data/lib/icons/preview.png +0 -0
  33. data/lib/icons/previous-image.ico +0 -0
  34. data/lib/icons/reload.ico +0 -0
  35. data/lib/icons/remove-selected.ico +0 -0
  36. data/lib/icons/rotate.ico +0 -0
  37. data/lib/icons/slides.ico +0 -0
  38. data/lib/icons/stop-slides.ico +0 -0
  39. data/lib/icons/unchecked-dir.ico +0 -0
  40. data/lib/icons/unchecked.ico +0 -0
  41. data/lib/icons/upload-selected.ico +0 -0
  42. data/lib/icons/upload.ico +0 -0
  43. data/lib/piggy-core/alive_check.rb +44 -0
  44. data/lib/piggy-core/debug.rb +21 -0
  45. data/lib/piggy-core/encoding.rb +11 -0
  46. data/lib/piggy-core/environment.rb +66 -0
  47. data/lib/piggy-core/exifr_adapter.rb +85 -0
  48. data/lib/piggy-core/file_info.rb +218 -0
  49. data/lib/piggy-core/ftp_adapter.rb +106 -0
  50. data/lib/piggy-core/htmlgen.rb +242 -0
  51. data/lib/piggy-core/nconvert_thumbsgen.rb +73 -0
  52. data/lib/piggy-core/options.rb +116 -0
  53. data/lib/piggy-core/options_persistence.rb +54 -0
  54. data/lib/piggy-core/progress.rb +48 -0
  55. data/lib/piggy-core/rmagick_thumbnail_page_generator.rb +30 -0
  56. data/lib/piggy-core/thumbnail_generator.rb +79 -0
  57. data/lib/piggy-core/thumbnail_page_generator.rb +542 -0
  58. data/lib/piggy-core/upload_info.rb +41 -0
  59. data/lib/piggy-core/version.rb +18 -0
  60. data/lib/piggy-core/winshell.rb +240 -0
  61. data/lib/piggy-gui/directory_diff_widget.rb +398 -0
  62. data/lib/piggy-gui/filtered_file_list.rb +243 -0
  63. data/lib/piggy-gui/fox_thumbsgen.rb +18 -0
  64. data/lib/piggy-gui/ftp_browser_widget.rb +395 -0
  65. data/lib/piggy-gui/html_generation_dialog.rb +157 -0
  66. data/lib/piggy-gui/image_processor.rb +140 -0
  67. data/lib/piggy-gui/multiimagecanvas.rb +163 -0
  68. data/lib/piggy-gui/options_dialog.rb +85 -0
  69. data/lib/piggy-gui/piggy_image_browser.rb +776 -0
  70. data/lib/piggy-gui/pipe_log.rb +67 -0
  71. data/lib/piggy-gui/progress_with_dialog.rb +51 -0
  72. data/lib/piggy-gui/require-fox.rb +87 -0
  73. data/lib/piggy.rb +35 -0
  74. data/lib/templates/fuss.htm +10 -0
  75. data/lib/templates/kopf.htm +13 -0
  76. data/lib/templates/navigation.htm +11 -0
  77. data/lib/templates/slideshow.htm +129 -0
  78. data/lib/templates/slideshow.js +691 -0
  79. data/lib/templates/styles/basic/style.css +27 -0
  80. data/lib/templates/styles/black/style.css +64 -0
  81. data/lib/templates/styles/roundedbox/roundedbox_lo.gif +0 -0
  82. data/lib/templates/styles/roundedbox/roundedbox_lu.gif +0 -0
  83. data/lib/templates/styles/roundedbox/roundedbox_ro.gif +0 -0
  84. data/lib/templates/styles/roundedbox/roundedbox_ru.gif +0 -0
  85. data/lib/templates/styles/roundedbox/style.css +70 -0
  86. data/lib/templates/styles/shadow/lo.gif +0 -0
  87. data/lib/templates/styles/shadow/lu.gif +0 -0
  88. data/lib/templates/styles/shadow/ro.gif +0 -0
  89. data/lib/templates/styles/shadow/ru.gif +0 -0
  90. data/lib/templates/styles/shadow/style.css +63 -0
  91. data/test/file_info_test.rb +117 -0
  92. data/test.rb +8 -0
  93. data/web/IMAGE_PROCESSING.txt +53 -0
  94. data/web/INSTALL.txt +74 -0
  95. data/web/extern.gif +0 -0
  96. data/web/ftp-browser.png +0 -0
  97. data/web/index-de.html +60 -0
  98. data/web/index.html +57 -0
  99. data/web/piggy.png +0 -0
  100. data/web/style.css +14 -0
  101. metadata +177 -0
@@ -0,0 +1,243 @@
1
+ require 'set'
2
+ require 'piggy-core/environment'
3
+ require 'piggy-core/winshell'
4
+ require 'piggy-gui/require-fox'
5
+
6
+ # Allows to choose from a predefined set of files in the list.
7
+ # The definition of choosable files may be given as a block.
8
+ # Chosen, unchosen and unchoosable files are rendered differently.
9
+ class FilteredFileList < Fox::FXFileList
10
+ include Fox
11
+ include Responder
12
+
13
+ attr_reader(:chosenFiles)
14
+ attr_writer(:choosable)
15
+
16
+ def initialize(parent)
17
+ super(parent, nil, 0, ICONLIST_MINI_ICONS|ICONLIST_AUTOSIZE)
18
+ @imageProcessor = ImageProcessor.new(getApp)
19
+ @chosenFiles = Set.new
20
+ @choosable = proc { |file| true }
21
+ @shell = WinShell.instance
22
+ initIcons
23
+ end
24
+
25
+ def initIcons
26
+ @checkedIcon = getIcon("checked.ico")
27
+ @uncheckedIcon = getIcon("unchecked.ico")
28
+ end
29
+
30
+ def getIcon(filename)
31
+ iconPath = File.join(PIGGY_PATH, 'icons', filename)
32
+ @imageProcessor.loadIcon(iconPath)
33
+ end
34
+
35
+ def getItemRubyFilename(index)
36
+ fox2Ruby(getItemFilename(index))
37
+ end
38
+
39
+ def getItemRubyPathname(index)
40
+ fox2Ruby(getItemPathname(index))
41
+ end
42
+
43
+ def replaceFileIcon(index, rubyfile, modus)
44
+ return nil if modus == nil
45
+ icon = (modus == 'add' ? @checkedIcon : @uncheckedIcon)
46
+ if FOXVERSION_GE_1_2
47
+ setItemMiniIcon(index, icon)
48
+ else
49
+ file = ruby2Fox(rubyfile)
50
+ replaceItem(index, file, icon, icon)
51
+ end
52
+ end
53
+
54
+ def chooseAllInFilelist
55
+ (0..getNumItems-1).each do
56
+ |i|
57
+ if(isItemFile(i) && supports(getItemRubyFilename(i)))
58
+ shortName = getItemRubyFilename(i)
59
+ longName = getItemRubyPathname(i)
60
+ @chosenFiles.add(longName)
61
+ replaceFileIcon(i, shortName, 'add')
62
+ end
63
+ end
64
+ end
65
+
66
+ def supports(filename)
67
+ return @choosable.call(filename)
68
+ end
69
+
70
+ def getSelectedImageFiles(fullPath = false, modus = nil)
71
+ selectedInd = (0..getNumItems-1).select do
72
+ |i|
73
+ isItemSelected(i) and
74
+ isItemFile(i) and
75
+ supports(getItemRubyFilename(i))
76
+ end
77
+ selectedFiles = selectedInd.collect do
78
+ |i|
79
+ shortName = getItemRubyFilename(i)
80
+ longName = getItemRubyPathname(i)
81
+ replaceFileIcon(i, shortName, modus)
82
+ fullPath ? longName : shortName
83
+ end
84
+ return selectedFiles
85
+ end
86
+
87
+ def addSelectedFiles
88
+ getSelectedImageFiles(true, 'add').each { |file|
89
+ @chosenFiles.add(file)
90
+ }
91
+ end
92
+
93
+ def removeSelectedFiles
94
+ getSelectedImageFiles(true, 'remove').each { |file|
95
+ @chosenFiles.delete(file)
96
+ }
97
+ end
98
+
99
+ def updateFileList
100
+ scan(true)
101
+ (0..getNumItems-1).each do
102
+ |i|
103
+ if(isItemFile(i))
104
+ shortName = getItemRubyFilename(i)
105
+ if(supports(shortName))
106
+ longName = getItemRubyPathname(i)
107
+ if(@chosenFiles.include?(longName))
108
+ replaceFileIcon(i, shortName, 'add')
109
+ else
110
+ replaceFileIcon(i, shortName, 'remove')
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ def addIndex(i)
118
+ longName = getItemRubyPathname(i)
119
+ shortName = getItemRubyFilename(i)
120
+ @chosenFiles.add(longName)
121
+ replaceFileIcon(i, shortName, 'add')
122
+ end
123
+
124
+ def removeIndex(i)
125
+ longName = getItemRubyPathname(i)
126
+ shortName = getItemRubyFilename(i)
127
+ @chosenFiles.delete(longName)
128
+ replaceFileIcon(i, shortName, 'remove')
129
+ end
130
+
131
+ def chooseSavedInstead(original, saved)
132
+ originalIndex = getIndex(original)
133
+ savedIndex = getIndex(saved)
134
+ removeIndex(originalIndex) unless originalIndex < 0
135
+ unless savedIndex < 0
136
+ addIndex(savedIndex)
137
+ selectIndex(savedIndex)
138
+ end
139
+ end
140
+
141
+ def getIndex(path)
142
+ rubyPath = rubyPath(path)
143
+ (0..getNumItems-1).each do
144
+ |i|
145
+ if(isItemFile(i))
146
+ longName = getItemRubyPathname(i)
147
+ if(rubyPath(longName) == rubyPath)
148
+ return i
149
+ end
150
+ end
151
+ end
152
+ return -1
153
+ end
154
+
155
+ def rubyPath(path)
156
+ @shell.rubyPath(path)
157
+ end
158
+
159
+ def assumeSelected(path)
160
+ index = getIndex(path)
161
+ unless index < 0 || itemSelected?(index)
162
+ killSelection()
163
+ selectItem(index)
164
+ end
165
+ end
166
+
167
+ def chosenSequence
168
+ seq = Array.new
169
+ @chosenFiles.each { |file| seq.push(file) }
170
+ seq.sort! { |x, y| x <=> y }
171
+ end
172
+
173
+ def goToDirectory(dirname)
174
+ self.directory = ruby2Fox(rubyPath(dirname))
175
+ @chosenFiles = Set.new
176
+ end
177
+
178
+ def getCurrentDirectory
179
+ fox2Ruby(self.directory)
180
+ end
181
+
182
+ # Return index or -1
183
+ def selectNextChosen
184
+ block = proc { |i|
185
+ if(isItemFile(i) &&
186
+ @chosenFiles.include?(getItemRubyPathname(i)))
187
+ killSelection
188
+ makeItemVisible(i)
189
+ selectItem(i)
190
+ return i
191
+ end
192
+ }
193
+ startingPoint = lastSelectedIndex + 1
194
+ (startingPoint..getNumItems-1).each(&block)
195
+ (0..startingPoint-1).each(&block)
196
+ return -1
197
+ end
198
+
199
+ def selectPreviousChosen
200
+ max = getNumItems - 1
201
+ startingPoint = firstSelectedIndex
202
+ startingPoint = max+1 if(startingPoint < 0 || startingPoint > max)
203
+ (0..max).each do
204
+ |index|
205
+ i = (max - index + startingPoint) % (max + 1)
206
+ if(isItemFile(i) &&
207
+ @chosenFiles.include?(getItemRubyPathname(i)))
208
+ killSelection
209
+ makeItemVisible(i)
210
+ selectItem(i)
211
+ return i
212
+ end
213
+ end
214
+ return -1
215
+ end
216
+
217
+ def firstSelectedIndex
218
+ max = getNumItems-1
219
+ (0..max).each do
220
+ |i|
221
+ return i if(isItemSelected(i))
222
+ end
223
+ -1
224
+ end
225
+
226
+ def lastSelectedIndex
227
+ max = getNumItems-1
228
+ (0..max).each do
229
+ |i|
230
+ r = max - i
231
+ return r if(isItemSelected(r))
232
+ end
233
+ -1
234
+ end
235
+
236
+ def anyFilesChosen?
237
+ return !@chosenFiles.empty?
238
+ end
239
+
240
+ def numFilesChosen
241
+ return @chosenFiles.size
242
+ end
243
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/ruby
2
+ ## $Id: fox_thumbsgen.rb 181 2007-12-12 23:33:46Z Sascha $
3
+
4
+ require 'piggy-core/thumbnail_page_generator'
5
+ require 'piggy-core/thumbnail_generator'
6
+ require 'piggy-gui/image_processor'
7
+
8
+ class FoxThumbnailPageGenerator < ThumbnailPageGenerator
9
+
10
+ protected
11
+
12
+ def imageProcessing(progress)
13
+ imageProcessor = ImageProcessor.new(client.getApp)
14
+ @imageGenerator = ThumbnailGenerator.new(imageProcessor, @options)
15
+ @imageGenerator.setOutputDirectory(imageOutputPath)
16
+ @imageGenerator.generate(@inputFilenames, progress)
17
+ end
18
+ end
@@ -0,0 +1,395 @@
1
+ #!/usr/bin/ruby
2
+ # $Id: ftp_browser_widget.rb 192 2008-02-02 19:21:34Z Sascha $
3
+
4
+ # FtpBrowserWidget manages FTP transfer for Piggy.
5
+
6
+ require 'piggy-core/options'
7
+ require 'piggy-core/ftp_adapter'
8
+ require 'piggy-core/upload_info'
9
+ require 'piggy-gui/directory_diff_widget'
10
+
11
+ class FtpBrowserDialog < Fox::FXDialogBox
12
+ include Fox
13
+
14
+ def initialize(window, options = PiggyOptions.new)
15
+ super(window, "Piggy FTP Client", DECOR_ALL)
16
+ @frame = FXVerticalFrame.new(self)
17
+ @frame.setLayoutHints(LAYOUT_FILL_X|LAYOUT_FILL_Y)
18
+ @browser = FtpBrowserWidget.new(@frame, options)
19
+ connect(SEL_CLOSE, method(:onCmdClose))
20
+ @browser.quitButton.connect(SEL_COMMAND, method(:onQuitButton))
21
+ end
22
+
23
+ def options
24
+ @browser.options
25
+ end
26
+
27
+ def create
28
+ resize(800, 600)
29
+ place(PIGGY_WINDOW_PLACEMENT)
30
+ super
31
+ end
32
+
33
+ # Send whenever this window is about to close
34
+ def onCmdClose(sender, sel, ptr)
35
+ @browser.prepareClosure
36
+ return 0
37
+ end
38
+
39
+ def onQuitButton(sender, sel, ptr)
40
+ handle(sender, MKUINT(ID_ACCEPT, SEL_COMMAND), nil)
41
+ end
42
+ end
43
+
44
+ class FtpBrowserMainWindow < DirectoryDiffMainWindow
45
+ include Fox
46
+
47
+ def initialize(app, options = PiggyOptions.new)
48
+ super(app, options)
49
+ end
50
+
51
+ def titleString
52
+ "Piggy FTP Browser"
53
+ end
54
+
55
+ def setMainWidget(options)
56
+ @browser = FtpBrowserWidget.new(@frame, options)
57
+ end
58
+ end
59
+
60
+ class FtpBrowserWidget < DirectoryDiffWidget
61
+ include Fox
62
+
63
+ def initialize(window, options = PiggyOptions.new)
64
+ @ftpAdapter = FtpAdapter.new(options)
65
+ @connectionDataVerified = false
66
+ super(window, options)
67
+ end
68
+
69
+ def loadIcons
70
+ super
71
+ @reloadIcon = basicLoadIcon('reload.ico')
72
+ @autoSelectForDelIco = basicLoadIcon('auto-select-for-del.ico')
73
+ @removeSelectedIco = basicLoadIcon('remove-selected.ico')
74
+ @autoSelectRightIcon = basicLoadIcon('auto-select-right.ico')
75
+ @uploadIcon = basicLoadIcon('auto-upload-right.ico')
76
+ @moveRightDirIcon = basicLoadIcon('move-right-dir.ico')
77
+ @moveRightFileIcon = basicLoadIcon('move-right-file.ico')
78
+ end
79
+
80
+ def initializeControlsOL
81
+ @labels.push(FXLabel.new(@leftListPropFrame, "FTP server:"))
82
+ @serverField = FXTextField.new(@leftListPropFrame, 32)
83
+ @labels.push(FXLabel.new(@leftListPropFrame, "User:"))
84
+ @userField = FXTextField.new(@leftListPropFrame, 32)
85
+ @labels.push(FXLabel.new(@leftListPropFrame, "Password:"))
86
+ @passwordField = FXTextField.new(@leftListPropFrame, 32)
87
+ @passwordField.setTextStyle(TEXTFIELD_PASSWD)
88
+ @labels.push(FXLabel.new(@leftListPropFrame, "Destination path:"))
89
+ @leftPathField = FXTextField.new(@leftListPropFrame, 32)
90
+ end
91
+
92
+ def initializeControlsUL
93
+ @updateButton = FXButton.new(@leftButtonsFrame,
94
+ "\tUpdate list",
95
+ @reloadIcon)
96
+ super
97
+ @autoSelectForDelButton = FXButton.new(@leftButtonsFrame,
98
+ "\tChoose files automatically",
99
+ @autoSelectForDelIco)
100
+ @removeSelectedLeftButton = FXButton.new(@leftButtonsFrame,
101
+ "\tRemove selected files",
102
+ @removeSelectedIco)
103
+ end
104
+
105
+ def initializeControlsUR
106
+ super
107
+ @autoSelectRightButton = FXButton.new(@rightButtonsFrame,
108
+ "\tChoose files automatically",
109
+ @autoSelectRightIcon)
110
+ @uploadSelectedButton = FXButton.new(@rightButtonsFrame,
111
+ "\tUpload selected",
112
+ @uploadIcon)
113
+ end
114
+
115
+ def connectEvents
116
+ super
117
+ @serverField.connect(SEL_COMMAND) {
118
+ @options.ftpHost = @serverField.getText
119
+ }
120
+ @userField.connect(SEL_COMMAND) {
121
+ @options.ftpUser = @userField.getText
122
+ }
123
+ @updateButton.connect(SEL_COMMAND, method(:onCmdUpdate))
124
+ @autoSelectForDelButton.connect(SEL_COMMAND, method(:onCmdAutoSelectLeft))
125
+ @removeSelectedLeftButton.connect(SEL_COMMAND, method(:onCmdRemoveSelectedLeft))
126
+ @autoSelectRightButton.connect(SEL_COMMAND, method(:onCmdAutoSelectRight))
127
+ @uploadSelectedButton.connect(SEL_COMMAND, method(:onCmdUpload))
128
+ end
129
+
130
+ def setDefaults
131
+ @serverField.setText(@options.ftpHost)
132
+ @userField.setText(@options.ftpUser)
133
+ @rightPathField.setText(@options.localDestinationPath)
134
+ @leftPathField.setText(@options.remoteDestinationPath)
135
+ end
136
+
137
+ # accessing
138
+
139
+ def leftPath
140
+ @options.remoteDestinationPath
141
+ end
142
+
143
+ def setLeftPath(p)
144
+ @options.remoteDestinationPath = FilePath.internPath(p)
145
+ @leftPathField.setText(leftPath) #fixme winpath
146
+ end
147
+
148
+ def password
149
+ @passwordField.getText
150
+ end
151
+
152
+ def host
153
+ @serverField.getText
154
+ end
155
+
156
+ def user
157
+ @userField.getText
158
+ end
159
+
160
+ # update
161
+
162
+ def updateStatusIconsRight
163
+ (0..@rightFileList.getNumItems - 1).each do
164
+ |index|
165
+ file = itemFilename(@rightFileList, index)
166
+ myInfo = @rightContents[file]
167
+ otherInfo = @leftContents[file]
168
+ icon = if myInfo.directory?
169
+ otherInfo ? @dirIcon : @moveRightDirIcon
170
+ else
171
+ if otherInfo
172
+ otherInfo.mtime < myInfo.mtime ? @newerFileIcon : @fileIcon
173
+ else
174
+ @moveRightFileIcon
175
+ end
176
+ end
177
+ @rightFileList.setItemMiniIcon(index, icon)
178
+ end
179
+ end
180
+
181
+ def updateLeftList
182
+ updateFtpList if @connectionDataVerified
183
+ end
184
+
185
+ def ftpDo(&block) # don't chdir in block
186
+ getApp.beginWaitCursor
187
+ @leftFileList.clearItems
188
+ @leftContents = DirectoryContents.new(leftPath)
189
+ begin
190
+ @connectionDataVerified = false
191
+ @ftpAdapter.connect(host, user, password)
192
+ @connectionDataVerified = true
193
+ @ftpAdapter.chdir(leftPath)
194
+ block.call # <------ the call
195
+ updateList(@ftpAdapter.nlst, @leftFileList, @leftContents) do
196
+ |file, path|
197
+ @ftpAdapter.info(file, path)
198
+ end
199
+ rescue SocketError => ex
200
+ error(ex.message)
201
+ rescue Net::FTPError => ex
202
+ error(ex.message)
203
+ rescue StandardError => ex
204
+ error(ex.message)
205
+ rescue Timeout::Error => ex
206
+ error("Timeout - operation took longer than expected. \nCheck network connection and try again.")
207
+ ensure
208
+ @ftpAdapter.close
209
+ end
210
+ getApp.endWaitCursor
211
+ end
212
+
213
+ def updateFtpList
214
+ ftpDo {} # every ftp action includes an update :-)
215
+ end
216
+
217
+ # actions
218
+
219
+ def autoSelectLeft
220
+ list = @leftFileList
221
+ list.killSelection
222
+ (0..list.getNumItems-1).each do
223
+ |index|
224
+ file = itemFilename(list, index)
225
+ myInfo = @leftContents[file]
226
+ otherInfo = @rightContents[file]
227
+ select = if myInfo.directory?
228
+ false
229
+ elsif otherInfo
230
+ false
231
+ else
232
+ true
233
+ end
234
+ list.selectItem(index) if select
235
+ end
236
+ end
237
+
238
+ def autoSelectRight
239
+ list = @rightFileList
240
+ list.killSelection
241
+ (0..list.getNumItems-1).each do
242
+ |index|
243
+ file = itemFilename(list, index)
244
+ myInfo = @rightContents[file]
245
+ otherInfo = @leftContents[file]
246
+ select = if myInfo.directory?
247
+ false
248
+ elsif otherInfo && otherInfo.directory?
249
+ false
250
+ elsif !otherInfo || otherInfo.mtime < myInfo.mtime
251
+ true
252
+ else
253
+ false
254
+ end
255
+ list.selectItem(index) if select
256
+ end
257
+ end
258
+
259
+ def ftpDeleteLeft(files)
260
+ ftpDo {
261
+ files.each { |file|
262
+ @ftpAdapter.delete(file)
263
+ }
264
+ }
265
+ updateStatusIcons
266
+ end
267
+
268
+ def ftpUploadRight(hash, totalSize)
269
+ ftpDo do
270
+ progressDialog = FXProgressDialog.new(self,
271
+ 'Transferring data',
272
+ 'Transferring data')
273
+ begin
274
+ progressDialog.setProgress(1)
275
+ progressDialog.setTotal(totalSize)
276
+ progressDialog.create
277
+ progressDialog.show
278
+ progressDialog.repaint
279
+ hash.keys.sort.each do
280
+ |file|
281
+ @ftpAdapter.upload(rightPath, file) { |data|
282
+ progressDialog.setMessage(ruby2Fox("Transferring #{File.basename(file)}"))
283
+ progressDialog.increment(data.size)
284
+ progressDialog.repaint
285
+ }
286
+ end
287
+ ensure
288
+ progressDialog.hide
289
+ end
290
+ end
291
+ updateStatusIcons
292
+ end
293
+
294
+ def askAndUploadSelection
295
+ sel = selectionInList(@rightFileList)
296
+ return false if sel.empty?
297
+ files = sel.collect { |e| FilePath.join(rightPath, e) }
298
+ uploadInfo = UploadInfo.new(files)
299
+ num = uploadInfo.numFiles
300
+ if(num < 1)
301
+ FXMessageBox.information(self, MBOX_OK, 'No files',
302
+ 'No files found in selected directories!')
303
+ return false
304
+ end
305
+ answer = FXMessageBox.question(self, MBOX_YES_NO, 'Really upload?',
306
+ "Upload #{num} fil#{num == 1 ? 'e' : 'es'}?")
307
+ ftpUploadRight(uploadInfo.bytesHash, uploadInfo.bytes) if answer == MBOX_CLICKED_YES
308
+ end
309
+
310
+ def askAndFtpDeleteSelection
311
+ sel = selectionInList(@leftFileList)
312
+ dirs = sel.select { |file|
313
+ @leftContents[file].directory?
314
+ }
315
+ return error("Sorry, can't remove directories, yet") unless dirs.empty?
316
+ return false if sel.empty?
317
+ num = sel.size
318
+ answer = FXMessageBox.question(self, MBOX_YES_NO, 'Really delete?',
319
+ "Delete #{num} fil#{num == 1 ? 'e' : 'es'}?")
320
+ ftpDeleteLeft(sel) if answer == MBOX_CLICKED_YES
321
+ end
322
+
323
+ # events
324
+
325
+ def onCmdUpdate(sender, sel, ptr)
326
+ updateFtpList
327
+ updateStatusIcons
328
+ end
329
+
330
+ def onCmdAutoSelectLeft(sender, sel, ptr)
331
+ autoSelectLeft
332
+ end
333
+
334
+ def onCmdRemoveSelectedLeft(sender, sel, ptr)
335
+ askAndFtpDeleteSelection
336
+ end
337
+
338
+ def onCmdAutoSelectRight(sender, sel, ptr)
339
+ autoSelectRight
340
+ end
341
+
342
+ def onCmdUpload(sender, sel, event)
343
+ askAndUploadSelection
344
+ end
345
+
346
+ def onMenuLeftList(sender, sel, event)
347
+ selection = selectionInList(@leftFileList)
348
+ pane = FXMenuPane.new(self)
349
+ # FXMenuSeparator.new(pane)
350
+ item = FXMenuCommand.new(pane, "&Remove selected")
351
+ if(selection.empty?)
352
+ item.disable
353
+ else
354
+ item.connect(SEL_COMMAND){ |sender, sel, event|
355
+ askAndFtpDeleteSelection
356
+ }
357
+ end
358
+ pane.create
359
+ pane.popup(nil, event.root_x, event.root_y)
360
+ getApp.runModalWhileShown(pane)
361
+ return 1
362
+ end
363
+
364
+ def onMenuRightList(sender, sel, event)
365
+ selection = selectionInList(@rightFileList)
366
+ pane = FXMenuPane.new(self)
367
+ item = FXMenuCommand.new(pane, "&Upload selected")
368
+ if(selection.empty?)
369
+ item.disable
370
+ else
371
+ item.connect(SEL_COMMAND){ |sender, sel, event|
372
+ askAndUploadSelection
373
+ }
374
+ end
375
+ # FXMenuSeparator.new(pane)
376
+ pane.create
377
+ pane.popup(nil, event.root_x, event.root_y)
378
+ getApp.runModalWhileShown(pane)
379
+ return 1
380
+ end
381
+
382
+ # open/close
383
+
384
+ def inCreate
385
+ updateRightList
386
+ updateStatusIcons
387
+ @fourSplitter.setVSplit(2450)
388
+ end
389
+
390
+ def prepareClosure
391
+ @ftpAdapter.close
392
+ super
393
+ end
394
+ end
395
+