-
Notifications
You must be signed in to change notification settings - Fork 17
/
FileManagement.py
3730 lines (3436 loc) · 198 KB
/
FileManagement.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Copyright (C) 2003 - 2015 The Board of Regents of the University of Wisconsin System
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
"""This module implements the File Management window for Transana, but can be also run as a stand-alone utility.
The File Management Tool is designed to facilitate local file management, such as copying and moving video
files, and updating the Transana Database when video files have been moved. It is also used for connecting
to an sFTP server or a Storage Resource Broker (SRB) and securely transfering files between the local file
system and the remote computer. """
__author__ = 'David Woods <[email protected]>, Rajas Sambhare <[email protected]>'
import wx # Import wxPython
if __name__ == '__main__':
__builtins__._ = wx.GetTranslation
wx.SetDefaultPyEncoding('utf_8')
# Import Python modules
import base64 # Base64 processing (used by paramiko)
import ctypes # used for connecting to the srbClient DLL/Linked Library in Windows
import exceptions # exception handling
import gettext # localization module
import os # used to determine what files are on the local computer
import pickle # Python pickle module
import re # used in parsing list of files in the list control
import shutil # used to copy files on the local file system
import stat # file information (used with paramiko)
import string # String manipulation
import sys # Python sys module, used in exception reporting
import time # time processing (used with paramiko)
# import paramiko for ssh/sFTP functionality
import paramiko
# Import Transana modules
import DBInterface # Import Transana's Database Interface
import Dialogs # Import Transana's Dialog Boxes
import Misc # import Transana's Miscellaneous functions
import LocalFileTransfer # LOCAL File Transfer Progres Box and File Transfer Logic
import sFTPConnection # sFTP Connection Parameters dialog box
import sFTPFileTransfer # sFTP File Transfer Progress Box and File Transfer Logic
import SRBConnection # SRB Connection Parameters dialog box
import SRBFileTransfer # SRB File Transfer Progress Box and File Tranfer Logic
import TransanaConstants # used for getting list of fileTypes
import TransanaGlobal # get Transana's globals, used to get current encoding
import TransanaImages # Get Transana's images
class FMFileDropTarget(wx.FileDropTarget):
""" This class allows the Source and Destination File Windows to become "Drop Targets" for
wxFileDataObjects, enabling file name drag and drop functionality """
def __init__(self, FMWindow, activeSide):
""" Initialize a File Manager File Drop Target Object """
# Instantiate a wxFileDropTarget
wx.FileDropTarget.__init__(self)
# Identify which widget should receive the File Drop
self.activeSide = activeSide
# This is a pointer to the File Management Window, used to implement the File Drop.
# This is probably bad form. The FileDropTarget Class should probably call
# methods in the class which implements it. However, this seems clearer in my warped
# way of thinking.
self.FileManagementWindow = FMWindow
def OnDropFiles(self, x, y, filenames):
""" Implements File Drop """
# Determine the necessary values to implement the file drop
# on either side of the File Management Screen
if (self.activeSide == 'Left'):
targetLbl = self.FileManagementWindow.lblLeft
# Local and Remote File Systems have different methods for determing the selected Path
if targetLbl.GetLabel() == self.FileManagementWindow.LOCAL_LABEL:
targetDir = self.FileManagementWindow.dirLeft.GetPath()
else:
targetDir = self.FileManagementWindow.GetFullPath(self.FileManagementWindow.remoteDirLeft)
target = self.FileManagementWindow.fileLeft
filter = self.FileManagementWindow.filterLeft
# We need to know the other side to, so it can also be updated if necessary
otherLbl = self.FileManagementWindow.lblRight
# Local and Remote File Systems have different methods for determing the selected Path
if otherLbl.GetLabel() == self.FileManagementWindow.LOCAL_LABEL:
otherDir = self.FileManagementWindow.dirRight.GetPath()
else:
otherDir = self.FileManagementWindow.GetFullPath(self.FileManagementWindow.remoteDirRight)
othertarget = self.FileManagementWindow.fileRight
otherfilter = self.FileManagementWindow.filterRight
elif self.activeSide == 'Right':
targetLbl = self.FileManagementWindow.lblRight
# Local and Remote File Systems have different methods for determing the selected Path
if targetLbl.GetLabel() == self.FileManagementWindow.LOCAL_LABEL:
targetDir = self.FileManagementWindow.dirRight.GetPath()
else:
targetDir = self.FileManagementWindow.GetFullPath(self.FileManagementWindow.remoteDirRight)
target = self.FileManagementWindow.fileRight
filter = self.FileManagementWindow.filterRight
# We need to know the other side to, so it can also be updated if necessary
otherLbl = self.FileManagementWindow.lblLeft
# Local and Remote File Systems have different methods for determing the selected Path
if otherLbl.GetLabel() == self.FileManagementWindow.LOCAL_LABEL:
otherDir = self.FileManagementWindow.dirLeft.GetPath()
else:
otherDir = self.FileManagementWindow.GetFullPath(self.FileManagementWindow.remoteDirLeft)
othertarget = self.FileManagementWindow.fileLeft
otherfilter = self.FileManagementWindow.filterLeft
if os.path.split(filenames[0])[0] != targetDir:
# If a Path has been defined for the Drop Target, copy the files.
# First, determine if it's local or remote receiving the files
if targetLbl.GetLabel() == self.FileManagementWindow.LOCAL_LABEL:
if targetDir != '':
self.FileManagementWindow.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
# for each file in the list...
for fileNm in filenames:
prompt = _('Copying %s to %s')
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
prompt = unicode(prompt, 'utf8')
self.FileManagementWindow.SetStatusText(prompt % (fileNm, targetDir))
# extract the file name...
(dir, fn) = os.path.split(fileNm)
if os.stat(fileNm)[6] < 5000000:
# copy the file to the destination path
shutil.copyfile(fileNm, os.path.join(targetDir, fn))
else:
dlg = LocalFileTransfer.LocalFileTransfer(self.FileManagementWindow, _("Local File Transfer"), fileNm, targetDir)
success = dlg.TransferSuccessful()
dlg.Destroy()
# Update the File Window where the files were dropped.
self.FileManagementWindow.RefreshFileList(targetLbl.GetLabel(), targetDir, target, filter)
# Let's update the target control after every file so that the new files show up in the list ASAP.
# wxYield allows the Windows Message Queue to update the display.
wx.Yield()
self.FileManagementWindow.SetStatusText(_('Copy complete.'))
self.FileManagementWindow.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
# If both sides of the File Manager are pointed to the same folder, we need to update the other
# side too!
if targetDir == otherDir:
self.FileManagementWindow.RefreshFileList(otherLbl.GetLabel(), otherDir, othertarget, otherfilter)
return(True)
# If no Path is defined for the Drop Target, forget about the drop
else:
dlg = Dialogs.ErrorDialog(self.FileManagementWindow, _('No destination path has been specified. File copy cancelled.'))
dlg.ShowModal()
dlg.Destroy()
return(False)
else:
cancelPressed = False
# For each file in the fileList ...
for fileName in filenames:
if cancelPressed:
break
# Divide the fileName into directory and filename portions
(sourceDir, fileNm) = os.path.split(fileName)
# Get the File Size
fileSize = os.path.getsize(fileName)
prompt = _('Copying %s to %s')
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
prompt = unicode(prompt, 'utf8')
self.FileManagementWindow.SetStatusText(prompt % (fileNm, targetDir))
# If we are connected to a Storage Resource Broker ...
if self.FileManagementWindow.connectionType == 'SRB':
# The SRBFileTransfer class handles file transfers and provides Progress Feedback
dlg = SRBFileTransfer.SRBFileTransfer(self.FileManagementWindow, _("SRB File Transfer"), fileNm, fileSize, sourceDir, self.FileManagementWindow.srbConnectionID, targetDir, SRBFileTransfer.srb_UPLOAD, self.FileManagementWindow.srbBuffer)
success = dlg.TransferSuccessful()
dlg.Destroy()
# If we are connected to an sFTP Server ...
elif self.FileManagementWindow.connectionType == 'sFTP':
# The sFTPFileTransfer class handles file transfers and provides Progress Feedback
dlg = sFTPFileTransfer.sFTPFileTransfer(self.FileManagementWindow, _("sFTP File Transfer"), fileNm, sourceDir, targetDir, sFTPFileTransfer.sFTP_UPLOAD)
success = dlg.TransferSuccessful()
dlg.Destroy()
# If the copy was successful ...
if success:
self.FileManagementWindow.SetStatusText(_('Copy complete.'))
# If the copy was not successful, it was cancelled by the user!
else:
self.FileManagementWindow.SetStatusText(_('Copy cancelled.'))
cancelPressed = True
# Let's update the target control after every file so that the new files show up in the list ASAP.
self.FileManagementWindow.RefreshFileList(targetLbl, targetDir, target, filter)
# wxYield allows the Windows Message Queue to update the display.
wx.Yield()
# If both sides of the File Manager are pointed to the same folder, we need to update the other
# side too!
if targetDir == otherDir:
self.FileManagementWindow.RefreshFileList(otherLbl.GetLabel(), otherDir, othertarget, otherfilter)
class FileManagement(wx.Dialog):
""" This displays the main File Management window. """
def __init__(self, parent, id, title):
""" Initialize the Main File Management Window. (You must also call Setup) """
self.parent = parent
# Because of Unicode issues, it's easiest to use Constants for the Local and Remote labels.
# Otherwise, there are comparison problems.
self.LOCAL_LABEL = _('Local:')
if 'unicode' in wx.PlatformInfo:
self.LOCAL_LABEL = unicode(self.LOCAL_LABEL, 'utf8')
self.REMOTE_LABEL = _('Remote:')
if 'unicode' in wx.PlatformInfo:
self.REMOTE_LABEL = unicode(self.REMOTE_LABEL, 'utf8')
# Initialize ConnectionType to sFTP, not SRB
self.connectionType = 'sFTP'
# sFTPConnectionID indicates the Connection status for sFTP
# It is initialized to None, as the connection is not established by default
self.sFTPConnectionID = None
# Initialize the sFTP Home Path to None. We'll get it when we connect.
self.sFTPHomePath = None
# srbConnectionID indicates the Connection ID for the Storage Resource Broker connection.
# It is initialized to None, as the connection is not established by default
self.srbConnectionID = None
# Initialize the SRB Buffer Size to 400000. This size yeilds fast transfers on my office computer with a very fast connection.
self.srbBuffer = '400000'
# A wxDialog is used rather than a wxFrame. While the frame has a Status Bar, which would have made some things
# easier, a Dialog can be displayed modally, which this tool requires.
# The creation of the Dialog follows the model from the wxPython 2.4.0.7 Demo.
# This is necessary for this code to run as a stand-alone program.
# First, create a "PreDialog" which will get displayed in a few steps.
pre = wx.PreDialog()
# If File Management is running as a stand-alone, it needs an additional style that indicates
# that it is being created without a parent.
if __name__ == '__main__':
pre.SetExtraStyle(wx.DIALOG_NO_PARENT)
# Now create the actual GUI Dialog using the Create method
pre.Create(parent, -1, title, pos = wx.DefaultPosition, size = (800,650), style=wx.DEFAULT_DIALOG_STYLE | wx.CAPTION | wx.RESIZE_BORDER)
# Convert the PreDialog into a REAL wrapper of the wxPython extension (whatever that means)
self.this = pre.this
# To look right, the Mac needs the Small Window Variant.
if "__WXMAC__" in wx.PlatformInfo:
self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
# Create the sFTP Connection Dialog (Do it here so values in it are retained)
self.sFTPConnDlg = sFTPConnection.sFTPConnection(self)
# Create the SRB Connection Dialog (Do it here so values in it are retained)
self.SRBConnDlg = SRBConnection.SRBConnection(self)
def Setup(self, showModal=False):
""" Set up the form widgets for the File Management Window """
# remember the showModal setting
self.isModal = showModal
# Create the form's Vertical Sizer
formSizer = wx.BoxSizer(wx.VERTICAL)
# Create a main Horizontal Sizer
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
# File Listings on the Left
filesLeftSizer = wx.BoxSizer(wx.VERTICAL)
# Connection Label
self.lblLeft = wx.StaticText(self, -1, _("Local:"))
# Add label to Sizer
filesLeftSizer.Add(self.lblLeft, 0, wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Directory Listing
self.dirLeft = GenericDirCtrl_MacFix(self, -1, wx.DIRCTRL_DIR_ONLY | wx.BORDER_DOUBLE)
# Add directory listing to Sizer
filesLeftSizer.Add(self.dirLeft, 3, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Set Minimum Size
self.dirLeft.SetSizeHints(minW = 50, minH = 50)
# If we're NOT running stand-alone ...
if __name__ != '__main__':
# Set the initial directory
self.dirLeft.SetPath(TransanaGlobal.configData.videoPath)
# else:
# if os.path.exists('E:\\Video'):
# self.dirLeft.SetPath('E:\\Video')
# Source SRB / sFTP Server Collections listing
self.remoteDirLeft = wx.TreeCtrl(self, -1, style=wx.TR_HAS_BUTTONS | wx.TR_SINGLE | wx.BORDER_DOUBLE)
# This control is not visible initially, as Local Folders, not SRB / sFTP Server Collections are shown
self.remoteDirLeft.Show(False)
# Add directory listing to Sizer
filesLeftSizer.Add(self.remoteDirLeft, 3, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Set Minimum Size
self.remoteDirLeft.SetSizeHints(minW = 50, minH = 50)
# NOTE: Although it would be possible to display files as well as folders in the wxGenericDirCtrls,
# we chose not to so that users could select multiple files at once for manipulation
# File Listing
self.fileLeft = wx.ListCtrl(self, -1, style=wx.LC_REPORT | wx.LC_NO_HEADER | wx.BORDER_DOUBLE)
# Create a single column for the file names
self.fileLeft.InsertColumn(0, "Files")
self.fileLeft.SetColumnWidth(0, 100)
# Add file listing to Sizer
filesLeftSizer.Add(self.fileLeft, 5, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Set Minimum Size
self.fileLeft.SetSizeHints(minW = 50, minH = 50)
# Make the File List a FileDropTarget
dt = FMFileDropTarget(self, 'Left')
self.fileLeft.SetDropTarget(dt)
# We need to rebuild the file types list so the items get translated if a non-English language is being used!
# Start with an empty list
fileChoiceList = []
# For each item in the file types list ...
for item in TransanaConstants.fileTypesList:
# ... add the translated item to the list
fileChoiceList.append(_(item))
# Create the File Types dropdown
self.filterLeft = wx.Choice(self, -1, choices=fileChoiceList)
# Set the default selection to the first item in the list
self.filterLeft.SetSelection(0)
# Add the file types dropdown to the Sizer
filesLeftSizer.Add(self.filterLeft, 0, wx.EXPAND | wx.ALL, 5)
# Set Minimum Size
self.filterLeft.SetSizeHints(minW = 50, minH = 20)
# Buttons in the middle
buttonSizer = wx.BoxSizer(wx.VERTICAL)
if TransanaGlobal.configData.LayoutDirection == wx.Layout_LeftToRight:
# Get the BitMaps for the left and right arrow buttons
bmpLeft = TransanaImages.ArtProv_BACK.GetBitmap()
bmpRight = TransanaImages.ArtProv_FORWARD.GetBitmap()
else:
# Get the BitMaps for the left and right arrow buttons
bmpLeft = TransanaImages.ArtProv_FORWARD.GetBitmap()
bmpRight = TransanaImages.ArtProv_BACK.GetBitmap()
# Top Spacer
buttonSizer.Add((1,1), 1)
# Copy Buttons - Create Label
txtCopy = wx.StaticText(self, -1, _("Copy"))
# Add the button label to the vertical sizer
buttonSizer.Add(txtCopy, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Create left and right arrow bitmap buttons
self.btnCopyToLeft = wx.BitmapButton(self, -1, bmpLeft, size=(36, 24))
self.btnCopyToRight = wx.BitmapButton(self, -1, bmpRight, size=(36, 24))
# Create a Horizontal Sizer for the buttons
hSizer = wx.BoxSizer(wx.HORIZONTAL)
# Add the arrow buttons to the button sizer with a spacer between
hSizer.Add(self.btnCopyToLeft, 0)
hSizer.Add((3, 0))
hSizer.Add(self.btnCopyToRight, 0)
# Add the horizontal button sizer to the vertical button area sizer
buttonSizer.Add(hSizer, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Spacer
buttonSizer.Add((1,1), 2)
# Move Buttons - Create Label
txtMove = wx.StaticText(self, -1, _("Move"))
# Add the button label to the vertical sizer
buttonSizer.Add(txtMove, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Create left and right arrow bitmap buttons
self.btnMoveToLeft = wx.BitmapButton(self, -1, bmpLeft, size=(36, 24))
self.btnMoveToRight = wx.BitmapButton(self, -1, bmpRight, size=(36, 24))
# Create a Horizontal Sizer for the buttons
hSizer = wx.BoxSizer(wx.HORIZONTAL)
# Add the arrow buttons to the button sizer with a spacer between
hSizer.Add(self.btnMoveToLeft, 0)
hSizer.Add((3, 0))
hSizer.Add(self.btnMoveToRight, 0)
# Add the horizontal button sizer to the vertical button area sizer
buttonSizer.Add(hSizer, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Spacer
buttonSizer.Add((1,1), 2)
# Copy All New Buttons - Create Label
txtSynch = wx.StaticText(self, -1, _("Copy All New"))
# Add the button label to the vertical sizer
buttonSizer.Add(txtSynch, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Create left and right arrow bitmap buttons
self.btnSynchToLeft = wx.BitmapButton(self, -1, bmpLeft, size=(36, 24))
self.btnSynchToRight = wx.BitmapButton(self, -1, bmpRight, size=(36, 24))
# Create a Horizontal Sizer for the buttons
hSizer = wx.BoxSizer(wx.HORIZONTAL)
# Add the arrow buttons to the button sizer with a spacer between
hSizer.Add(self.btnSynchToLeft, 0)
hSizer.Add((3, 0))
hSizer.Add(self.btnSynchToRight, 0)
# Add the horizontal button sizer to the vertical button area sizer
buttonSizer.Add(hSizer, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Spacer
buttonSizer.Add((1,1), 2)
# Delete Buttons - Create Label
txtDelete = wx.StaticText(self, -1, _("Delete"))
# Add the button label to the vertical sizer
buttonSizer.Add(txtDelete, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Create left and right arrow bitmap buttons
self.btnDeleteLeft = wx.BitmapButton(self, -1, bmpLeft, size=(36, 24))
self.btnDeleteRight = wx.BitmapButton(self, -1, bmpRight, size=(36, 24))
# Create a Horizontal Sizer for the buttons
hSizer = wx.BoxSizer(wx.HORIZONTAL)
# Add the arrow buttons to the button sizer with a spacer between
hSizer.Add(self.btnDeleteLeft, 0)
hSizer.Add((3, 0))
hSizer.Add(self.btnDeleteRight, 0)
# Add the horizontal button sizer to the vertical button area sizer
buttonSizer.Add(hSizer, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Spacer
buttonSizer.Add((1,1), 2)
# New Folder Buttons - Create Label
txtNewFolder = wx.StaticText(self, -1, _("New Folder"))
# Add the button label to the vertical sizer
buttonSizer.Add(txtNewFolder, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Create left and right arrow bitmap buttons
self.btnNewFolderLeft = wx.BitmapButton(self, -1, bmpLeft, size=(36, 24))
self.btnNewFolderRight = wx.BitmapButton(self, -1, bmpRight, size=(36, 24))
# Create a Horizontal Sizer for the buttons
hSizer = wx.BoxSizer(wx.HORIZONTAL)
# Add the arrow buttons to the button sizer with a spacer between
hSizer.Add(self.btnNewFolderLeft, 0)
hSizer.Add((3, 0))
hSizer.Add(self.btnNewFolderRight, 0)
# Add the horizontal button sizer to the vertical button area sizer
buttonSizer.Add(hSizer, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Spacer
buttonSizer.Add((1,1), 2)
# Update DB Buttons - Create Label
txtUpdateDB = wx.StaticText(self, -1, _("Update DB"))
# Add the button label to the vertical sizer
buttonSizer.Add(txtUpdateDB, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Create left and right arrow bitmap buttons
self.btnUpdateDBLeft = wx.BitmapButton(self, -1, bmpLeft, size=(36, 24))
self.btnUpdateDBRight = wx.BitmapButton(self, -1, bmpRight, size=(36, 24))
# Create a Horizontal Sizer for the buttons
hSizer = wx.BoxSizer(wx.HORIZONTAL)
# Add the arrow buttons to the button sizer with a spacer between
hSizer.Add(self.btnUpdateDBLeft, 0)
hSizer.Add((3, 0))
hSizer.Add(self.btnUpdateDBRight, 0)
# Add the horizontal button sizer to the vertical button area sizer
buttonSizer.Add(hSizer, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Spacer
buttonSizer.Add((1,1), 2)
# If we're running stand-alone ...
if __name__ == '__main__':
# ... hide the UpdateDB Buttons
txtUpdateDB.Show(False)
self.btnUpdateDBLeft.Show(False)
self.btnUpdateDBRight.Show(False)
# Connect Buttons - Create Label
txtConnect = wx.StaticText(self, -1, _("Connect"))
# Add the button label to the vertical sizer
buttonSizer.Add(txtConnect, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Create left and right arrow bitmap buttons
self.btnConnectLeft = wx.BitmapButton(self, -1, bmpLeft, size=(36, 24))
self.btnConnectRight = wx.BitmapButton(self, -1, bmpRight, size=(36, 24))
# Create a Horizontal Sizer for the buttons
hSizer = wx.BoxSizer(wx.HORIZONTAL)
# Add the arrow buttons to the button sizer with a spacer between
hSizer.Add(self.btnConnectLeft, 0)
hSizer.Add((3, 0))
hSizer.Add(self.btnConnectRight, 0)
# Add the horizontal button sizer to the vertical button area sizer
buttonSizer.Add(hSizer, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# NOTE: Commented out because the SRB is dead, and thus no longer an option!
# If we're on Linux ...
## if 'wxGTK' in wx.PlatformInfo:
# ... sFTP is the only choice. SRB isn't supported.
## choices = ['sFTP']
# If we're on Windows or OS X ...
## else:
# ... sFTP and SRB are options.
## choices = ['sFTP', 'SRB 3.3.1']
# Add a Connection Type Choice Box
## self.connectionTypeChoice = wx.Choice(self, -1, choices = choices)
## self.connectionTypeChoice.SetStringSelection(self.connectionType)
## self.connectionTypeChoice.Bind(wx.EVT_CHOICE, self.SetConnectionType)
## buttonSizer.Add(self.connectionTypeChoice, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
##
## SEE OnConnect and RemoteDisconnect Methods for commented-out references to ConnectionTypeChoice as well
# Spacer
buttonSizer.Add((1,1), 2)
# Refresh Buttons - Create Label
self.btnRefresh = wx.Button(self, -1, _("Refresh"))
# Add the button label to the vertical sizer
buttonSizer.Add(self.btnRefresh, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Spacer
buttonSizer.Add((1,1), 2)
# Close Button - Create Label
self.btnClose = wx.Button(self, -1, _("Close"))
# Add the button label to the vertical sizer
buttonSizer.Add(self.btnClose, 0, wx.ALIGN_CENTER | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Spacer
buttonSizer.Add((1,1), 2)
# Help Button - Create Label
self.btnHelp = wx.Button(self, -1, _("Help"))
# Add the button label to the vertical sizer
buttonSizer.Add(self.btnHelp, 0, wx.ALIGN_CENTER | wx.ALL, 5)
# If we're running stand-alone ...
if __name__ == '__main__':
# ... hide the Help Button
self.btnHelp.Show(False)
# Bottom Spacer
buttonSizer.Add((1,1), 1)
# File Listings on the Right
filesRightSizer = wx.BoxSizer(wx.VERTICAL)
# Connection Label
self.lblRight = wx.StaticText(self, -1, _("Local:"))
# Add label to Sizer
filesRightSizer.Add(self.lblRight, 0, wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Directory Listing
self.dirRight = GenericDirCtrl_MacFix(self, -1, wx.DIRCTRL_DIR_ONLY | wx.BORDER_DOUBLE)
# Add directory listing to Sizer
filesRightSizer.Add(self.dirRight, 3, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Set Minimum Size
self.dirRight.SetSizeHints(minW = 50, minH = 50)
# If we're NOT running stand-alone ...
if __name__ != '__main__':
# ... set the initial directory to the video path
self.dirRight.SetPath(TransanaGlobal.configData.videoPath)
# else:
# if os.path.exists('E:\\Video'):
# self.dirRight.SetPath('E:\\Video')
# Destination SRB / sFTP Server Collections listing
self.remoteDirRight = wx.TreeCtrl(self, -1, style=wx.TR_HAS_BUTTONS | wx.TR_SINGLE | wx.BORDER_DOUBLE)
# This control is not visible initially, as Local Folders, not SRB / sFTP Collections are shown
self.remoteDirRight.Show(False)
# Add directory listing to Sizer
filesRightSizer.Add(self.remoteDirRight, 3, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Set Minimum Size
self.remoteDirRight.SetSizeHints(minW = 50, minH = 50)
# NOTE: Although it would be possible to display files as well as folders in the wxGenericDirCtrls,
# we chose not to so that users could select multiple files at once for manipulation
# File Listing
self.fileRight = wx.ListCtrl(self, -1, style=wx.LC_REPORT | wx.LC_NO_HEADER | wx.BORDER_DOUBLE)
# Create a single column for the file names
self.fileRight.InsertColumn(0, "Files")
self.fileRight.SetColumnWidth(0, 100)
# Add file listing to Sizer
filesRightSizer.Add(self.fileRight, 5, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 5)
# Set Minimum Size
self.fileRight.SetSizeHints(minW = 50, minH = 50)
# Make the File List a FileDropTarget
dt = FMFileDropTarget(self, 'Right')
self.fileRight.SetDropTarget(dt)
# We need to rebuild the file types list so the items get translated if a non-English language is being used!
# Start with an empty list
fileChoiceList = []
# For each item in the file types list ...
for item in TransanaConstants.fileTypesList:
# ... add the translated item to the list
fileChoiceList.append(_(item))
# Create the File Types dropdown
self.filterRight = wx.Choice(self, -1, choices=fileChoiceList)
# Set the default selection to the first item in the list
self.filterRight.SetSelection(0)
# Add the file types dropdown to the Sizer
filesRightSizer.Add(self.filterRight, 0, wx.EXPAND | wx.ALL, 5)
# Set Minimum Size
self.filterRight.SetSizeHints(minW = 50, minH = 20)
# Add the three vertical columns to the main sizer
mainSizer.Add(filesLeftSizer, 2, wx.EXPAND, 0)
mainSizer.Add(buttonSizer, 0, wx.EXPAND, 0)
mainSizer.Add(filesRightSizer, 2, wx.EXPAND, 0)
# Add the main Sizer to the form's Sizer
formSizer.Add(mainSizer, 1, wx.EXPAND, 0)
# wxFrames can have Status Bars. wxDialogs can't.
# The File Management Window needs to be a wxDialog, not a wxFrame.
# Yet I want it to have a Status Bar. So I'm going to fake a status bar by
# creating a Panel at the bottom of the screen with text on it.
# Place a Static Text Widget on the Status Bar Panel
self.StatusText = wx.StaticText(self, -1, "", style=wx.ST_NO_AUTORESIZE)
formSizer.Add(self.StatusText, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 5)
# Set the mainSizer as the form's main sizer
self.SetSizer(formSizer)
# Define Events
# Mouse Over Events to enable Button Descriptions in the Status Bar
self.btnCopyToLeft.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnCopyToLeft.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnCopyToRight.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnCopyToRight.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnMoveToLeft.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnMoveToLeft.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnMoveToRight.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnMoveToRight.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnSynchToLeft.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnSynchToLeft.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnSynchToRight.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnSynchToRight.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnDeleteLeft.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnDeleteLeft.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnDeleteRight.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnDeleteRight.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnNewFolderLeft.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnNewFolderLeft.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnNewFolderRight.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnNewFolderRight.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnUpdateDBLeft.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnUpdateDBLeft.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnUpdateDBRight.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnUpdateDBRight.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnConnectLeft.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnConnectLeft.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnConnectRight.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnConnectRight.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnRefresh.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnRefresh.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnClose.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnClose.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
self.btnHelp.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseOver)
self.btnHelp.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
# Define the Event to initiate the beginning of a File Drag operation
self.fileLeft.Bind(wx.EVT_MOTION, self.OnFileStartDrag)
self.fileRight.Bind(wx.EVT_MOTION, self.OnFileStartDrag)
# Button Events (link functionality to button widgets)
self.btnCopyToLeft.Bind(wx.EVT_BUTTON, self.OnCopyMove)
self.btnCopyToRight.Bind(wx.EVT_BUTTON, self.OnCopyMove)
self.btnMoveToLeft.Bind(wx.EVT_BUTTON, self.OnCopyMove)
self.btnMoveToRight.Bind(wx.EVT_BUTTON, self.OnCopyMove)
self.btnSynchToLeft.Bind(wx.EVT_BUTTON, self.OnSynch)
self.btnSynchToRight.Bind(wx.EVT_BUTTON, self.OnSynch)
self.btnDeleteLeft.Bind(wx.EVT_BUTTON, self.OnDelete)
self.btnDeleteRight.Bind(wx.EVT_BUTTON, self.OnDelete)
self.btnNewFolderLeft.Bind(wx.EVT_BUTTON, self.OnNewFolder)
self.btnNewFolderRight.Bind(wx.EVT_BUTTON, self.OnNewFolder)
self.btnUpdateDBLeft.Bind(wx.EVT_BUTTON, self.OnUpdateDB)
self.btnUpdateDBRight.Bind(wx.EVT_BUTTON, self.OnUpdateDB)
self.btnConnectLeft.Bind(wx.EVT_BUTTON, self.OnConnect)
self.btnConnectRight.Bind(wx.EVT_BUTTON, self.OnConnect)
self.btnRefresh.Bind(wx.EVT_BUTTON, self.OnRefresh)
self.btnClose.Bind(wx.EVT_BUTTON, self.CloseWindow)
self.btnHelp.Bind(wx.EVT_BUTTON, self.OnHelp)
# Directory Tree and SRB / sFTP Server Collection Selection Events
self.dirLeft.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnDirSelect)
self.dirRight.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnDirSelect)
self.remoteDirLeft.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnDirSelect)
self.remoteDirRight.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnDirSelect)
# File Filter Events
self.filterLeft.Bind(wx.EVT_CHOICE, self.OnDirSelect)
self.filterRight.Bind(wx.EVT_CHOICE, self.OnDirSelect)
# Form Resize Event
self.Bind(wx.EVT_SIZE, self.OnSize)
# File Manager Close Event
self.Bind(wx.EVT_CLOSE, self.CloseWindow)
# Define the minimum size of this dialog box
self.SetSizeHints(600, 500)
# lay out all the controls
self.Layout()
# Enable Auto Layout
self.SetAutoLayout(True)
TransanaGlobal.CenterOnPrimary(self)
# Call OnSize to set the SRB / sFTP directory control size initially
self.OnSize(None)
# Populate File Lists for initial directory settings
self.RefreshFileList(self.lblLeft.GetLabel(), self.dirLeft.GetPath(), self.fileLeft, self.filterLeft)
self.RefreshFileList(self.lblRight.GetLabel(), self.dirRight.GetPath(), self.fileRight, self.filterRight)
# Show the File Management Window
if showModal:
self.ShowModal()
else:
self.Show(True)
def SetStatusText(self, txt):
""" Update the Text in the fake Status Bar """
self.StatusText.SetLabel(txt)
def RemoteDisconnect(self):
""" Disconnect from the SRB or sFTP Server """
# If we have a SRB connection ...
if self.connectionType == 'SRB':
# Load the SRB DLL / Dynamic Library
if "__WXMSW__" in wx.PlatformInfo:
srb = ctypes.cdll.srbClient
else:
srb = ctypes.cdll.LoadLibrary("srbClient.dylib")
# Break the connection to the SRB.
srb.srb_disconnect(self.srbConnectionID.value)
# Signal that the Connection has been broken by resetting the ConnectionID value to None
self.srbConnectionID = None
# If we have an sFTP connection ...
elif self.connectionType == 'sFTP':
# ... close the sFTP Client ...
self.sFTPClient.close()
# ... close the sFTP Transport ...
self.sFTPTransport.close()
# ... reset the sFTP Connection ID ...
self.sFTPConnectionID = None
# ... and clear the sFTP Home Path.
self.sFTPHomePath = None
# Re-enable the connection type selection
## self.connectionTypeChoice.Enable(True)
def SetConnectionType(self, event):
""" Handle selection of Connection Type """
# Get the selection from the control
selection = self.connectionTypeChoice.GetStringSelection()
# if SRB is selected ...
if selection == 'SRB 3.3.1':
# ... signal that the SRB is in use
self.connectionType = 'SRB'
# If sFTP is selected ...
elif selection == 'sFTP':
# ... signal that the sFTP Server is in use
self.connectionType = 'sFTP'
def OnSize(self, event):
""" Form Resize Event """
# If event != None (We're not on the initial sizing call) ...
if event != None:
# ... call the underlying Resize Event
event.Skip()
# If the LOCAL directory listing is showing on the LEFT ...
if self.dirLeft.IsShown():
# Get the Size and Position of the current Directory Controls
rectLeft = self.dirLeft.GetRect()
# Set the SRB / sFTP Directory Controls to the same position and size as the regular Directory Controls
self.remoteDirLeft.SetDimensions(rectLeft[0], rectLeft[1], rectLeft[2], rectLeft[3])
# If the REMOTE directory listing is showing on the LEFT ...
else:
# Get the Size and Position of the current Directory Controls
rectLeft = self.remoteDirLeft.GetRect()
# Set the SRB / sFTP Directory Controls to the same position and size as the regular Directory Controls
self.dirLeft.SetDimensions(rectLeft[0], rectLeft[1], rectLeft[2], rectLeft[3])
# If the LOCAL directory listing is showing on the RIGHT ...
if self.dirRight.IsShown():
# Get the Size and Position of the current Directory Controls
rectRight = self.dirRight.GetRect()
# Set the SRB / sFTP Directory Controls to the same position and size as the regular Directory Controls
self.remoteDirRight.SetDimensions(rectRight[0], rectRight[1], rectRight[2], rectRight[3])
# If the REMOTE directory listing is showing on the RIGHT ...
else:
# Get the Size and Position of the current Directory Controls
rectRight = self.remoteDirRight.GetRect()
# Set the SRB / sFTP Directory Controls to the same position and size as the regular Directory Controls
self.dirRight.SetDimensions(rectRight[0], rectRight[1], rectRight[2], rectRight[3])
# reset column widths for the File Lists
if self.fileLeft.GetColumnCount() > 0:
self.fileLeft.SetColumnWidth(0, self.fileLeft.GetSizeTuple()[0] - 24)
if self.fileRight.GetColumnCount() > 0:
self.fileRight.SetColumnWidth(0, self.fileRight.GetSizeTuple()[0] - 24)
def CloseWindow(self, event):
""" Clean up upon closing the File Management Window """
try:
# If we are connected to the sFTP server or the SRB, we need to disconnect before closing the window
if (self.sFTPConnectionID != None) or (self.srbConnectionID != None):
self.RemoteDisconnect()
except:
pass
# Destroy the sFTP Connection Dialog
self.sFTPConnDlg.Destroy()
# Destroy the SRB Connection Dialog
self.SRBConnDlg.Destroy()
# Hide the File Management Dialog. (You can't destroy it here, like I used to, because that crashes on Mac as of
# wxPython 2.8.6.1.
self.Show(False)
# As of wxPython 2.8.6.1, you can't destroy yourself during Close on the Mac if you're Modal, and let's delay it a bit
# if you're not Modal.
if not self.isModal:
if self.parent != None:
self.parent.fileManagementWindow = None
wx.CallAfter(self.Destroy)
def OnMouseOver(self, event):
""" Update the Status Bar when a button is moused-over """
# Identify controls for the SOURCE data. Copy, Move, and Synch RIGHT operate left to right, while all
# other controls operate on the side they point to.
if event.GetEventObject().GetId() in [self.btnCopyToRight.GetId(), self.btnMoveToRight.GetId(), self.btnSynchToRight.GetId(),
self.btnDeleteLeft.GetId(), self.btnNewFolderLeft.GetId(), self.btnUpdateDBLeft.GetId(),
self.btnConnectLeft.GetId()]:
# Get the Local / Remote label
sourceLbl = self.lblLeft
# Identify which side of the screen we're working on
sideLbl = _("left")
# The directory control and file path differ for local and remote file systems
# If we are LOCAL ...
if sourceLbl.GetLabel() == self.LOCAL_LABEL:
# ... get the LOCAL path
sourcePath = self.dirLeft.GetPath()
# If we are REMOTE ...
else:
# ... get the REMOTE path
sourcePath = self.GetFullPath(self.remoteDirLeft)
# Get the source File Control
sourceFile = self.fileLeft
# The directory control and file path differ for local and remote file systems
# If the DESTINATION is LOCAL ...
if self.lblRight.GetLabel() == self.LOCAL_LABEL:
# ... get the LOCAL path
destPath = self.dirRight.GetPath()
# If the DESTINATION is REMOTE ...
else:
# ... get the REMOTE path
destPath = self.GetFullPath(self.remoteDirRight)
# Copy, Move, and Synch LEFT operate right to left, while all other controls operate on the side they point to.
elif event.GetEventObject().GetId() in [self.btnCopyToLeft.GetId(), self.btnMoveToLeft.GetId(), self.btnSynchToLeft.GetId(),
self.btnDeleteRight.GetId(), self.btnNewFolderRight.GetId(), self.btnUpdateDBRight.GetId(),
self.btnConnectRight.GetId()]:
# Get the Local / Remote label
sourceLbl = self.lblRight
# Identify which side of the screen we're working on
sideLbl = _("right")
# The directory control and file path differ for local and remote file systems
# If we are LOCAL ...
if sourceLbl.GetLabel() == self.LOCAL_LABEL:
# ... get the LOCAL path
sourcePath = self.dirRight.GetPath()
# If we are REMOTE ...
else:
# ... get the REMOTE path
sourcePath = self.GetFullPath(self.remoteDirRight)
# Get the source File Control
sourceFile = self.fileRight
# The directory control and file path differ for local and remote file systems
# If the DESTINATION is LOCAL ...
if self.lblLeft.GetLabel() == self.LOCAL_LABEL:
# ... get the LOCAL path
destPath = self.dirLeft.GetPath()
# If the DESTINATION is REMOTE ...
else:
# ... get the REMOTE path
destPath = self.GetFullPath(self.remoteDirLeft)
# Determine which button is being moused-over and display an appropriate message in the
# Status Bar
# Copy buttons
if event.GetEventObject().GetId() in [self.btnCopyToLeft.GetId(), self.btnCopyToRight.GetId()]:
# Indicate whether selected files or all files will be copied
if sourceFile.GetSelectedItemCount() == 0:
tempText = _('all')
else:
tempText = _('selected')
# Create the appropriate Status Bar prompt
prompt = _('Copy %s files from %s to %s')
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
tempText = unicode(tempText, 'utf8')
prompt = unicode(prompt, 'utf8')
# Put the prompt in the Status Bar
self.SetStatusText(prompt % (tempText, sourcePath, destPath))
# Move buttons
elif event.GetEventObject().GetId() in [self.btnMoveToLeft.GetId(), self.btnMoveToRight.GetId()]:
# Indicate whether selected files or all files will be copied
if sourceFile.GetSelectedItemCount() == 0:
tempText = _('all')
else:
tempText = _('selected')
# Create the appropriate Status Bar prompt
prompt = _('Move %s files from %s to %s')
# Specify source and destination Folder/Collections in Status Bar
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
tempText = unicode(tempText, 'utf8')
prompt = unicode(prompt, 'utf8')
# Put the prompt in the Status Bar
self.SetStatusText(prompt % (tempText, sourcePath, destPath))
# CopyAllNew buttons
elif event.GetEventObject().GetId() in [self.btnSynchToLeft.GetId(), self.btnSynchToRight.GetId()]:
# Create the appropriate Status Bar prompt
prompt = _('Copy all new files files from %s to %s')
# Specify source and destination Folder/Collections in Status Bar
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
prompt = unicode(prompt, 'utf8')
# Put the prompt in the Status Bar
self.SetStatusText(prompt % (sourcePath, destPath))
# Delete buttons
elif event.GetEventObject().GetId() in [self.btnDeleteLeft.GetId(), self.btnDeleteRight.GetId()]:
# Specify source Folder/Collection in the Status Bar
# If there are files selected in the File List ...
if (sourceFile.GetItemCount() > 0):
# Create the appropriate Status Bar prompt
prompt = _('Delete selected files from %s')
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
prompt = unicode(prompt, 'utf8')
# If there are NO files selected in the File List ...
else:
# Create the appropriate Status Bar prompt
prompt = _('Delete %s')
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
prompt = unicode(prompt, 'utf8')
# Put the prompt in the Status Bar
self.SetStatusText(prompt % sourcePath)
# New Folder button
elif event.GetEventObject().GetId() in [self.btnNewFolderLeft.GetId(), self.btnNewFolderRight.GetId()]:
# Create the appropriate Status Bar prompt
prompt = _('Create new folder in %s')
# Specify source Folder/Collection in the Status Bar
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
prompt = unicode(prompt, 'utf8')
# Put the prompt in the Status Bar
self.SetStatusText(prompt % sourcePath)
# Update DB button
elif event.GetEventObject().GetId() in [self.btnUpdateDBLeft.GetId(), self.btnUpdateDBRight.GetId()]:
if sourceLbl.GetLabel() == self.LOCAL_LABEL:
prompt = _('Update selected file locations in the Transana database to %s')
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
prompt = unicode(prompt, 'utf8')
# Put the prompt in the Status Bar
self.SetStatusText(prompt % sourcePath)
else:
prompt = _('You cannot update the file locations in the database to %s')
if 'unicode' in wx.PlatformInfo:
# Encode with UTF-8 rather than TransanaGlobal.encoding because this is a prompt, not DB Data.
prompt = unicode(prompt, 'utf8')
# Display error message in the Status Bar
self.SetStatusText(prompt % sourcePath)
# Connect button
elif event.GetEventObject().GetId() in [self.btnConnectLeft.GetId(), self.btnConnectRight.GetId()]:
# Status Bar Text needs to indicate whether this button will establish or break
# the connection to the SRB
if sourceLbl.GetLabel() == self.LOCAL_LABEL:
# If our remote server is a SRB ...
if self.connectionType == 'SRB':
# Put the prompt in the Status Bar
self.SetStatusText(_('Connect %s side to SRB') % sideLbl)
else:
# Put the prompt in the Status Bar
self.SetStatusText(_('Connect %s side to sFTP') % sideLbl)
else:
# If our remote server is a SRB ...
if self.connectionType == 'SRB':
# Put the prompt in the Status Bar
self.SetStatusText(_('Disconnect %s side from SRB') % sideLbl)
else:
# Put the prompt in the Status Bar
self.SetStatusText(_('Disconnect %s side from sFTP') % sideLbl)
# Refresh button
elif event.GetEventObject().GetId() == self.btnRefresh.GetId():
# Put the prompt in the Status Bar
self.SetStatusText(_('Refresh File Lists'))