Skip to content

Instantly share code, notes, and snippets.

@controversial
Created February 20, 2016 03:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save controversial/45c4f891f059bbcc38e0 to your computer and use it in GitHub Desktop.
Save controversial/45c4f891f059bbcc38e0 to your computer and use it in GitHub Desktop.
FileListOps.py
"""A set of operations for working with the file lists returned from zipfile.ZipFile.namelist()"""
import os
def getParentDirs(path):
""" "test/again/hello" -> ["test", "test/again"] """
dirs = path.split("/")[:-1]
if dirs:
return ["/".join(dirs[:i+1]) for i,d in enumerate(dirs) if dirs[:i+1]]
else:
return []
def getAllDirNames(filelist):
"""["a/b.py","b/c.py","a/b/c.py"] -> ["a","b","a/b"]"""
dirs = set([os.path.split(d)[0] for d in filelist])
for d in list(dirs):
for pd in getParentDirs(d):
dirs.add(pd)
return sorted([d for d in list(dirs) if d])
def depth(path):
"""a/b/c -> 3; a/b/c/d -> 4"""
return path.count("/")+1
def getSubDirs(filelist,path):
"""["a/b/c.py","a/c/d.py"], a -> [b,c]"""
dirs=getAllDirNames(filelist)
return [d for d in dirs if d.startswith(path) and d!=path and depth(d)==depth(path)+1]
def getSubFiles(flst, path):
"""["a/b.py", "a/c.py"], a -> ["a/b.py", "a/c.py"]"""
return [d for d in flst if d.startswith(path) and d!=path and depth(d)==depth(path)+1]
def allSubFiles(flst, path):
return [d for d in flst if d.startswith(path) and d!=path]
def isdir(flist, path):
"""Whether the path is a directory in file list `flist`"""
return path in getAllDirNames(flist)
def isfile(flist, path):
"""Whether the path is a file in file list `flist`"""
return path in flist
def exists(flist, path):
"""Whether the path is either a file or a directory in file list `flist`"""
return isfile(flist,path) or isdir(flist,path)
if __name__ == "__main__":
import zipfile
files=zipfile.ZipFile("example.zip").namelist()
print getSubDirs(files, 'GitHub')
print getSubFiles(files, 'GitHub')
"""Modified version of my file picker to work with unextracted zip files. Modified
to show both files and directories, as well as executing an action every time a
file is tapped instead of selecting one and then finishing."""
import ui, os, console
from zipfile import ZipFile
from FileListOps import *
class DropDown(ui.View):
def __init__(self,p,level,filelist,parent=None,frame=None,width=None,x=None,y=None):
self.path = p
self.fl = filelist
self.subDirs = getSubDirs(self.fl,self.path)
self.subFiles = getSubFiles(self.fl,self.path)
self.open = False
self.level=level
self.arrowClosed = ui.Image.named('iob:ios7_arrow_right_32')
self.arrowOpened = ui.Image.named('iob:ios7_arrow_down_32')
self.folderIcon = ui.Image.named('iob:ios7_folder_outline_32')
self.children = []
self.ydent = 0
self.above = []
self.below = []
self.selected = 0
indent=32*self.level
self.arrow=ui.ImageView(frame=(indent,4,32,32))
self.arrow.image = self.arrowOpened if self.open else self.arrowClosed
self.add_subview(self.arrow)
self.folder=ui.ImageView(frame=(indent+32,4,32,32))
self.folder.image = self.folderIcon
self.add_subview(self.folder)
self.text=ui.Label(frame=(indent+75,4,300,32))
self.text.text = str(os.path.abspath(self.path)).split('/')[-1]
self.text.font=('AvenirNext-Light',20)
self.add_subview(self.text)
def draw(self):
self.height = 40
self.y = 40*len(self.superview.subviews[:self.superview.subviews.index(self)])+self.ydent*40
self.x = 0
self.width = self.superview.width
maxscroll = max(x.y+40 for x in self.superview.subviews)
self.superview.content_size = (0, maxscroll)
def should_open(self):
self.arrow.image = self.arrowOpened
self.open = not self.open
self.above = [x for x in self.superview.subviews if x.y < self.y]
self.below = [x for x in self.superview.subviews if x.y > self.y]
for sd in self.subDirs:
self.children.append(DropDown(sd, self.level+1, self.fl))
self.superview.add_subview(self.children[-1])
self.children[-1].ydent -= len(self.below)
for sd in self.subFiles:
self.children.append(File(sd, self.level+1))
self.superview.add_subview(self.children[-1])
self.children[-1].ydent -= len(self.below)
for b in self.below:
b.ydent += len(self.children)
b.draw()
def should_collapse(self):
self.arrow.image = self.arrowClosed
self.open = not self.open
for sd in self.children:
if sd.selected:
self.superview.superview.deselect()
sd.should_collapse()
self.superview.remove_subview(sd)
self.above = [x for x in self.superview.subviews if x.y < self.y]
self.below = [x for x in self.superview.subviews if x.y > self.y]
for b in set(self.below)-set(self.children):
b.ydent -= len(self.children)
b.draw()
self.children = []
def select(self):
self.superview.superview.select(self)
def touch_began(self, touch):
if not self.selected:
self.background_color = .88, .88, .88
self.selectCanditate=False
x, y = touch.location
a=self.arrow
arrowBounds = list(a.frame[:2]) + [a.x+a.width,a.y+a.height]
if x > arrowBounds[0]-20 and x < arrowBounds[2]+20:
if self.open:
self.should_collapse()
else:
self.should_open()
else:
self.selectCanditate=True
self.initialTouch = touch.location
def touch_ended(self, touch):
if not self.selected:
self.background_color = 1.0, 1.0, 1.0
x, y = touch.location
px, py = self.initialTouch
if self.selectCanditate and abs(x-px) < 5 and abs(y-py) < 5:
self.select()
class File(ui.View):
def __init__(self, name, level):
self.selected=False
self.path = name
self.level=level
self.ydent=0
self.docIcon = ui.Image.named('iob:document_32')
indent=32*self.level
self.file=ui.ImageView(frame=(indent+32,4,32,32))
self.file.image = self.docIcon
self.add_subview(self.file)
self.text=ui.Label(frame=(indent+75,4,300,32))
self.text.text = name.split("/")[-1]
self.text.font=('AvenirNext-Light',20)
self.add_subview(self.text)
def draw(self):
self.height = 40
self.y = 40*len(self.superview.subviews[:self.superview.subviews.index(self)])+self.ydent*40
self.x = 0
self.width = self.superview.width
maxscroll = max(x.y+40 for x in self.superview.subviews)
self.superview.content_size = (0, maxscroll)
def should_collapse(self):
pass
def touch_began(self, touch):
if not self.selected:
self.background_color = .88, .88, .88
self.initialTouch = touch.location
def touch_ended(self, touch):
if not self.selected:
self.background_color = 1.0, 1.0, 1.0
x, y = touch.location
px, py = self.initialTouch
if abs(x-px) < 5 and abs(y-py) < 5:
self.select()
def select(self):
self.superview.superview.select(self)
class SVDelegate:
def scrollview_did_scroll(self, sv):
for sub in sv.subviews:
if not sub.selected:
sub.background_color = 1.0, 1.0, 1.0
yscroll=sv.content_offset[1]
class FilePicker(ui.View):
def __init__(self,path,handle,frame=(0,0,500,500),background_color=(1.0, 1.0, 1.0)):
self.files = ZipFile(path).namelist()
for i,f in enumerate(self.files):
self.files[i]=path+"/"+f
self.background_color=background_color
self.frame=frame
self.scroll=ui.ScrollView(frame=(0,0,self.width,self.height))
self.scroll.delegate = SVDelegate()
self.scroll.add_subview(DropDown(path,0,self.files))
self.add_subview(self.scroll)
self.handle=handle
def select(self,view):
self.handle(view.path)
def getFileName(dir,title=''):
"""Example function that displays a file picker and returns the result"""
global selected
selected = None
def handle(result):
print result
fp=FilePicker(dir,handle,frame=(0,0,500,500))
fp.name = title
fp.right_button_items=[ui.ButtonItem(title='Done', action=lambda sender:fp.close())]
fp.present('sheet')
if __name__ == '__main__':
getFileName('example.zip')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment