editors/FileManagementPanel.py
changeset 951 7f9a9c47a317
parent 815 e4f24593a758
child 1571 486f94a8032c
equal deleted inserted replaced
950:bf896711921c 951:7f9a9c47a317
    24 
    24 
    25 import os
    25 import os
    26 import shutil
    26 import shutil
    27 
    27 
    28 import wx
    28 import wx
       
    29 import wx.lib.buttons
    29 
    30 
    30 from EditorPanel import EditorPanel
    31 from EditorPanel import EditorPanel
    31 from util.BitmapLibrary import GetBitmap
    32 from util.BitmapLibrary import GetBitmap
    32 
    33 from controls import FolderTree
    33 DRIVE, FOLDER, FILE = range(3)
       
    34 
    34 
    35 FILTER = _("All files (*.*)|*.*|CSV files (*.csv)|*.csv")
    35 FILTER = _("All files (*.*)|*.*|CSV files (*.csv)|*.csv")
    36 
       
    37 def sort_folder(x, y):
       
    38     if x[1] == y[1]:
       
    39         return cmp(x[0], y[0])
       
    40     elif x[1] != FILE:
       
    41         return -1
       
    42     else:
       
    43         return 1
       
    44 
       
    45 def splitpath(path):
       
    46     head, tail = os.path.split(path)
       
    47     if head == "":
       
    48         return [tail]
       
    49     elif tail == "":
       
    50         return splitpath(head)
       
    51     return splitpath(head) + [tail]
       
    52     
       
    53 class FolderTree(wx.Panel):
       
    54     
       
    55     def __init__(self, parent, folder, filter, editable=True):
       
    56         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
       
    57         
       
    58         main_sizer = wx.BoxSizer(wx.VERTICAL)
       
    59         
       
    60         self.Tree = wx.TreeCtrl(self, 
       
    61               style=wx.TR_HAS_BUTTONS|
       
    62                     wx.TR_SINGLE|
       
    63                     wx.SUNKEN_BORDER|
       
    64                     wx.TR_HIDE_ROOT|
       
    65                     wx.TR_LINES_AT_ROOT|
       
    66                     wx.TR_EDIT_LABELS)
       
    67         if wx.Platform == '__WXMSW__':
       
    68             self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnTreeItemExpanded, self.Tree)
       
    69             self.Tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
       
    70         else:
       
    71             self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnTreeItemExpanded, self.Tree)
       
    72         self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnTreeItemCollapsed, self.Tree)
       
    73         self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnTreeBeginLabelEdit, self.Tree)
       
    74         self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnTreeEndLabelEdit, self.Tree)
       
    75         main_sizer.AddWindow(self.Tree, 1, flag=wx.GROW)
       
    76         
       
    77         self.Filter = wx.ComboBox(self, style=wx.CB_READONLY)
       
    78         self.Bind(wx.EVT_COMBOBOX, self.OnFilterChanged, self.Filter)
       
    79         main_sizer.AddWindow(self.Filter, flag=wx.GROW)
       
    80         
       
    81         self.SetSizer(main_sizer)
       
    82         
       
    83         self.Folder = folder
       
    84         self.Editable = editable
       
    85         
       
    86         self.TreeImageList = wx.ImageList(16, 16)
       
    87         self.TreeImageDict = {}
       
    88         for item_type, bitmap in [(DRIVE, "tree_drive"),
       
    89                                   (FOLDER, "tree_folder"),
       
    90                                   (FILE, "tree_file")]:
       
    91             self.TreeImageDict[item_type] = self.TreeImageList.Add(GetBitmap(bitmap))
       
    92         self.Tree.SetImageList(self.TreeImageList)
       
    93         
       
    94         self.Filters = {}
       
    95         filter_parts = filter.split("|")
       
    96         for idx in xrange(0, len(filter_parts), 2):
       
    97             if filter_parts[idx + 1] == "*.*":
       
    98                 self.Filters[filter_parts[idx]] = ""
       
    99             else:
       
   100                 self.Filters[filter_parts[idx]] = filter_parts[idx + 1].replace("*", "")
       
   101             self.Filter.Append(filter_parts[idx])
       
   102             if idx == 0:
       
   103                 self.Filter.SetStringSelection(filter_parts[idx])
       
   104             
       
   105         self.CurrentFilter = self.Filters[self.Filter.GetStringSelection()]
       
   106     
       
   107     def _GetFolderChildren(self, folderpath, recursive=True):
       
   108         items = []
       
   109         if wx.Platform == '__WXMSW__' and folderpath == "/":
       
   110             for c in xrange(ord('a'), ord('z')):
       
   111                 drive = os.path.join("%s:\\" % chr(c))
       
   112                 if os.path.exists(drive):
       
   113                     items.append((drive, DRIVE, self._GetFolderChildren(drive, False)))
       
   114         else:
       
   115             try:
       
   116                 files = os.listdir(folderpath)
       
   117             except:
       
   118                 return []
       
   119             for filename in files:
       
   120                 if not filename.startswith("."):
       
   121                     filepath = os.path.join(folderpath, filename)
       
   122                     if os.path.isdir(filepath):
       
   123                         if recursive:
       
   124                             children = len(self._GetFolderChildren(filepath, False))
       
   125                         else:
       
   126                             children = 0
       
   127                         items.append((filename, FOLDER, children))
       
   128                     elif (self.CurrentFilter == "" or 
       
   129                           os.path.splitext(filename)[1] == self.CurrentFilter):
       
   130                         items.append((filename, FILE, None))
       
   131         if recursive:
       
   132             items.sort(sort_folder)
       
   133         return items
       
   134     
       
   135     def GetTreeCtrl(self):
       
   136         return self.Tree
       
   137     
       
   138     def RefreshTree(self):
       
   139         root = self.Tree.GetRootItem()
       
   140         if not root.IsOk():
       
   141             root = self.Tree.AddRoot("")
       
   142         self.GenerateTreeBranch(root, self.Folder)
       
   143         
       
   144     def GenerateTreeBranch(self, root, folderpath):
       
   145         item, item_cookie = self.Tree.GetFirstChild(root)
       
   146         for idx, (filename, item_type, children) in enumerate(self._GetFolderChildren(folderpath)):
       
   147             if not item.IsOk():
       
   148                 item = self.Tree.AppendItem(root, filename, self.TreeImageDict[item_type])
       
   149                 if wx.Platform != '__WXMSW__':
       
   150                     item, item_cookie = self.Tree.GetNextChild(root, item_cookie)
       
   151             elif self.Tree.GetItemText(item) != filename:
       
   152                 item = self.Tree.InsertItemBefore(root, idx, filename, self.TreeImageDict[item_type])
       
   153             filepath = os.path.join(folderpath, filename)
       
   154             if item_type != FILE:
       
   155                 if self.Tree.IsExpanded(item):
       
   156                     self.GenerateTreeBranch(item, filepath)
       
   157                 elif children > 0:
       
   158                     self.Tree.SetItemHasChildren(item)
       
   159             item, item_cookie = self.Tree.GetNextChild(root, item_cookie)
       
   160         to_delete = []
       
   161         while item.IsOk():
       
   162             to_delete.append(item)
       
   163             item, item_cookie = self.Tree.GetNextChild(root, item_cookie)
       
   164         for item in to_delete:
       
   165             self.Tree.Delete(item)
       
   166 
       
   167     def ExpandItem(self, item):
       
   168         self.GenerateTreeBranch(item, self.GetPath(item))
       
   169         self.Tree.Expand(item)
       
   170     
       
   171     def OnTreeItemActivated(self, event):
       
   172         self.ExpandItem(event.GetItem())
       
   173         event.Skip()
       
   174     
       
   175     def OnTreeLeftDown(self, event):
       
   176         item, flags = self.Tree.HitTest(event.GetPosition())
       
   177         if flags & wx.TREE_HITTEST_ONITEMBUTTON and not self.Tree.IsExpanded(item):
       
   178             self.ExpandItem(item)
       
   179         else:
       
   180             event.Skip()
       
   181     
       
   182     def OnTreeItemExpanded(self, event):
       
   183         item = event.GetItem()
       
   184         self.GenerateTreeBranch(item, self.GetPath(item))
       
   185         event.Skip()
       
   186 
       
   187     def OnTreeItemCollapsed(self, event):
       
   188         item = event.GetItem()
       
   189         self.Tree.DeleteChildren(item)
       
   190         self.Tree.SetItemHasChildren(item)
       
   191         event.Skip()
       
   192 
       
   193     def OnTreeBeginLabelEdit(self, event):
       
   194         item = event.GetItem()
       
   195         if self.Editable and not self.Tree.ItemHasChildren(item):
       
   196             event.Skip()
       
   197         else:
       
   198             event.Veto()
       
   199     
       
   200     def OnTreeEndLabelEdit(self, event):
       
   201         old_filepath = self.GetPath(event.GetItem())
       
   202         new_filepath = os.path.join(os.path.split(old_filepath)[0], event.GetLabel())
       
   203         if new_filepath != old_filepath:
       
   204             if not os.path.exists(new_filepath):
       
   205                 os.rename(old_filepath, new_filepath)
       
   206                 event.Skip()
       
   207             else:
       
   208                 message =  wx.MessageDialog(self, 
       
   209                     _("File '%s' already exists!") % event.GetLabel(), 
       
   210                     _("Error"), wx.OK|wx.ICON_ERROR)
       
   211                 message.ShowModal()
       
   212                 message.Destroy()
       
   213                 event.Veto()
       
   214     
       
   215     def OnFilterChanged(self, event):
       
   216         self.CurrentFilter = self.Filters[self.Filter.GetStringSelection()]
       
   217         self.RefreshTree()
       
   218         event.Skip()
       
   219     
       
   220     def _SelectItem(self, root, parts):
       
   221         if len(parts) == 0:
       
   222             self.Tree.SelectItem(root)
       
   223         else:
       
   224             item, item_cookie = self.Tree.GetFirstChild(root)
       
   225             while item.IsOk():
       
   226                 if self.Tree.GetItemText(item) == parts[0]:
       
   227                     if (self.Tree.ItemHasChildren(item) and 
       
   228                         not self.Tree.IsExpanded(item)):
       
   229                         self.Tree.Expand(item)
       
   230                         wx.CallAfter(self._SelectItem, item, parts[1:])
       
   231                     else:
       
   232                         self._SelectItem(item, parts[1:])
       
   233                     return
       
   234                 item, item_cookie = self.Tree.GetNextChild(root, item_cookie)
       
   235     
       
   236     def SetPath(self, path):
       
   237         if path.startswith(self.Folder):
       
   238             root = self.Tree.GetRootItem()
       
   239             if root.IsOk():
       
   240                 relative_path = path.replace(os.path.join(self.Folder, ""), "")
       
   241                 self._SelectItem(root, splitpath(relative_path))
       
   242     
       
   243     def GetPath(self, item=None):
       
   244         if item is None:
       
   245             item = self.Tree.GetSelection()
       
   246         if item.IsOk():
       
   247             filepath = self.Tree.GetItemText(item)
       
   248             parent = self.Tree.GetItemParent(item)
       
   249             while parent.IsOk() and parent != self.Tree.GetRootItem():
       
   250                 filepath = os.path.join(self.Tree.GetItemText(parent), filepath)
       
   251                 parent = self.Tree.GetItemParent(parent)
       
   252             return os.path.join(self.Folder, filepath)
       
   253         return self.Folder
       
   254 
    36 
   255 class FileManagementPanel(EditorPanel):
    37 class FileManagementPanel(EditorPanel):
   256     
    38     
   257     def _init_Editor(self, parent):
    39     def _init_Editor(self, parent):
   258         self.Editor = wx.Panel(parent)
    40         self.Editor = wx.Panel(parent)