Huh!
Long name, but that is what it does. It select any number of files from any number of folders, and stores them in a list. Than, with all these files, you can do whatever you want in your application. You can see why I made this box, and how I use it here:
http://www.inverudio.com/programs/BiosAnalyzer/BiosAnalyzer.php
That is, if you have Windows, as for Linux I need to change the threading stuff, so that it could work (plot graphs).
Why I am submitting here, and not to SVN? Because, widget is not polished for library, and since I don’t have experience in writing libraries, I thought that someone on this list may know better how to encapsulate these two classes in the best way.
In particular, in my application, I use some globals, and for libraries, that is not acceptable, as far as I know. Code is below. Note that ‘ba.frame…’ stuff is my main application (BiosAnalyzer -> ba), and I left it in this code so that you could see how I use this widget. To me it is not that obvious what functions and variables should be kept/added in order to make this widget most usable, and extensible. That is why I am showing it here to more experienced programmers.
#nameofthiswidgetcanbeanythingmeaningfulbuthopefullyshorterthansubjectofthisemail
global fileformats
global numberOfSelectedFiles
global currentPath
global filesAndPathsT
numberOfSelectedFiles = 0
currentPath = ‘’
filesAndPathsT = []
MyTextDropTarget and dragAndDropMenu class select many files from different folders.
class MyTextDropTarget(wx.TextDropTarget):
def __init__(self, object):
wx.TextDropTarget.__init__(self)
self.object = object
i=0
global filesAndPathsT
for [data,currentPath] in filesAndPathsT:
data = data+'|'+currentPath
self.object.InsertStringItem(i, data)
i +=1
def OnDropText(self, x, y, data):
global currentPath
global filesAndPathsT
global numberOfSelectedFiles
if [data,currentPath] not in filesAndPathsT:
filesAndPathsT.append([data,currentPath])
data = data+'|'+currentPath
self.object.InsertStringItem(numberOfSelectedFiles, data)
numberOfSelectedFiles +=1
class dragAndDropMenu(wx.Frame):
def __init__(self, parent, id, title):
global currentPath
global numberOfSelectedFiles
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(690, 460))
self.SetIcon(wx.Icon('ba.ico', wx.BITMAP_TYPE_ICO))
panel = wx.Panel(self, -1)
extensionLabel = wx.StaticText(panel, -1, 'Show files with extension.\nLeave blanc to show all files:')
self.extension = wx.TextCtrl(panel, -1, 'txt', size = (23,20))
self.dir = wx.GenericDirCtrl(panel, -1, dir='/home/', style=wx.DIRCTRL_DIR_ONLY, size = wx.Size(250, 400))
self.dir.SetDefaultPath(self.dir.GetPath())
tip_label = wx.StaticText(panel, -1, ' Select and drag files here.\n Press "Ctrl" to select many files.')
self.files = wx.ListCtrl(panel, -1, style=wx.LC_LIST, size = wx.Size(170, 370))
self.selected = wx.ListCtrl(panel, -1, style=wx.LC_LIST, size = wx.Size(220, 350))
self.moreFiles = []
self.diselected = []
self.fileIndex = []
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.clear = wx.Button(panel, -1, 'Clear All', size = wx.Size(100, 25))
self.done = wx.Button(panel, -1, 'Done', size = wx.Size(50, 25))
self.cancel = wx.Button(panel, -1, 'Cancel', size = wx.Size(50, 25))
hbox1.Add(extensionLabel, 0, wx.ALIGN_CENTRE)
hbox1.Add(self.extension, 0, wx.ALIGN_CENTRE)
vbox1.Add(hbox1, 0, wx.ALIGN_CENTRE)
vbox1.Add(self.files, 0, wx.ALIGN_CENTRE)
vbox.Add(tip_label, 0, wx.ALIGN_CENTRE)
vbox.Add(self.selected, 0, wx.ALIGN_CENTRE)
hbox.Add(self.clear, 0, wx.ALIGN_CENTRE)
hbox.Add(self.done, 0, wx.ALIGN_CENTRE)
hbox.Add(self.cancel, 0, wx.ALIGN_CENTRE)
vbox.Add(hbox, 0, wx.ALIGN_CENTRE)
dt = MyTextDropTarget(self.selected)
self.selected.SetDropTarget(dt)
self.Bind(wx.EVT_CLOSE, self.OnClose)
wx.EVT_LIST_BEGIN_DRAG(self, self.files.GetId(), self.OnDragInit)
wx.EVT_LIST_ITEM_SELECTED(self, self.files.GetId(), self.OnSelectFile)
wx.EVT_LIST_ITEM_DESELECTED(self, self.files.GetId(), self.OnDeselectFile)
wx.EVT_LIST_ITEM_SELECTED(self, self.selected.GetId(), self.OnSelectSelectedFiles)
wx.EVT_LIST_ITEM_DESELECTED(self, self.selected.GetId(), self.OnDeselectSelectedFiles)
wx.EVT_BUTTON(self.clear, self.clear.GetId(), self.OnClearAll)
wx.EVT_BUTTON(self.done, self.done.GetId(), self.OnDone)
wx.EVT_BUTTON(self.cancel, self.cancel.GetId(), self.OnCancel)
#wx.EVT_LIST_DELETE_ITEM(self, self.selected.GetId(), self.OnClearSelect)
tree = self.dir.GetTreeCtrl()
wx.EVT_TREE_SEL_CHANGED(self, tree.GetId(), self.OnSelectFolder)
sizer = wx.FlexGridSizer(1, 3, 5, 5)
sizer.AddMany((self.dir,vbox1,vbox))
border = wx.BoxSizer()
border.Add(sizer, 10, wx.ALL, 15)
panel.SetSizer(border)
self.Centre()
#self.OnClearAll(None)
#numberOfSelectedFiles = 0
#currentPath = os.path.basename(currentPath)
# this is not working. should set the trenutno path, not blank
self.dir.SetDefaultPath(currentPath)
def OnSelectFolder(self, event, cdir = ''):
global currentPath
if cdir == '':
currentPath = self.dir.GetPath()
else:
currentPath = cdir
list = os.listdir(currentPath)
self.files.ClearAll()
fil = re.compile("."+str(self.extension.GetValue())+"$", re.IGNORECASE)
filtered = filter(fil.search, list)
for i in range(len(filtered)):
self.files.InsertStringItem(0, filtered[i])
self.moreFiles = []
def OnSelectFile(self, event):
self.moreFiles.append(self.files.GetItemText(event.GetIndex()))
def OnDeselectFile(self, event):
cur = self.files.GetItemText(event.GetIndex())
if cur in self.moreFiles:
self.moreFiles.remove(cur)
def OnSelectSelectedFiles(self, event):
ind = (array(self.fileIndex)).searchsorted(event.GetIndex())
self.diselected.insert(ind, self.selected.GetItemText(event.GetIndex()))
self.fileIndex.insert(ind, event.GetIndex())
if len(self.diselected) > 0:
self.clear.SetLabel('Clear selection')
else:
self.clear.SetLabel('Clear All')
def OnDeselectSelectedFiles(self, event):
cur = self.selected.GetItemText(event.GetIndex())
if cur in self.diselected:
self.fileIndex.remove(self.fileIndex[self.diselected.index(cur)])
self.diselected.remove(cur)
if len(self.diselected) > 0:
self.clear.SetLabel('Clear selection')
else:
self.clear.SetLabel('Clear All')
def OnDragInit(self, event):
for i in range(len(self.moreFiles)):
text = self.moreFiles[i]
tdo = wx.PyTextDataObject(text)
tds = wx.DropSource(self.files)
tds.SetData(tdo)
tds.DoDragDrop(True)
def OnClearAll(self, event):
if len(self.diselected)>0:
self.OnClearSelected(None)
else:
global filesAndPathsT
global numberOfSelectedFiles
numberOfSelectedFiles = 0
self.selected.ClearAll()
filesAndPathsT = []
def OnClearSelected(self, event):
global filesAndPathsT
global numberOfSelectedFiles
for i in range(len(self.diselected)-1,-1,-1):
if self.diselected[i].split('|') in filesAndPathsT:
filesAndPathsT.remove(self.diselected[i].split('|'))
self.selected.DeleteItem(self.fileIndex[i])
numberOfSelectedFiles -= 1
self.diselected = []
self.fileIndex = []
self.clear.SetLabel('Clear All')
def OnDone(self, event):
global filesAndPathsT
ba.frame.filesAndPaths = filesAndPathsT[:]
ba.frame.file_choice.SetValue(True)
ba.frame.fileIndex = 0
ba.frame.checkUserInput(self)
ba.frame.Enable()
self.Close(True)
def OnCancel(self, event):
ba.frame.Enable()
ba.frame.checkUserInput(self)
self.Close(True)
def OnClose(self, event):
ba.frame.Enable()
ba.frame.checkUserInput(self)
self.Destroy()
There it is. There are many places for improvement, like the appearance, which is in my opinion very ugly, but my main aim was functionality.
If you decide to fix this, let me know when you do, as I would like to see what will this become!
Take care
Lazar Kovacevic
inverudio.com
PS. i didn’t mention benefits of having this widget, but I think it is obvious.