捐赠支持塞班原创作品 | dospy智能手机网新改版 | 智能手机软件下载频道新上线! | 手机访问:wap.dospy.com |




站内全文搜索,由谷歌和塞班合作提供
站内全文搜索,由百度和塞班合作提供

 
标题: ------教程-----iPro7中关于文件管理器2的源代码分析
563255107
排长
Rank: 3Rank: 3


UID 9780224
精华 0
积分 291
帖子 291
威望 0 点
财富值 370 塞班币
贡献值 0 点
好评度 0 点
交易信用 0 点
原创小红花 0 朵
人气值 0 点
阅读权限 10
注册 2009-5-23
手机型号 
状态 离线
 
发表于 2011-3-31 23:51  资料  个人空间  短消息  加为好友 
------教程-----iPro7中关于文件管理器2的源代码分析

大家好,我是小马,上一节我分析了iPro7中关于数据库的源代码分析今天来讲解iPro7的文件管理器2的源代码分析,代码很长很长还希望想学习的可以认真看完,写的很清楚,如果还有哪里不懂的可以联系我,跟帖,内信或者邮箱563255107@qq.com====================================好了教程开始==============================================


class File_Manager2(object, ) :




    __module__ = __name__
    def prepare(s):#调用文件管理器时用到的准备,比如说快捷方式的设定,这个与一个类里面的__init__初始化类似
        try :#异常处理,防止程序出错,先尝试执行下面的语句块,如果遇到意外不能执行,则执行except里的语句块
            from keycapture import KeyCapturer as KeyCapturer#引入keycapture模块为下面的快捷键做铺垫
            s.select_capture = KeyCapturer(lambda p, :  s.select() )#创建KeyCapture对象,这里的lambda p, :  s.select() 是创建了一个匿名对象
            s.backward_capture = KeyCapturer(lambda p, :  s.backward() )
            s.next_page_capture = KeyCapturer(lambda p, :  s.next_page() )
            s.last_page_capture = KeyCapturer(lambda p, :  s.last_page() )
            try :
                from key_codes import EKeyRightArrow as EKeyRightArrow#引入key)codes模块,方便我们定义快捷方式
                from key_codes import EKeyLeftArrow as EKeyLeftArrow
                from key_codes import EKeyStar as EKeyStar
                from key_codes import EKeyHash as EKeyHash
            except :
                EKeyRightArrow, EKeyLeftArrow, EKeyStar, EKeyHash = (63496, 63495, 42, 35)#这里依次对应导航键的左键,右键,*键,#键
            s.select_capture.keys = (EKeyRightArrow, )#定义相应函数要捕获的按键,这里定义导航右键为选择键
            s.backward_capture.keys = (EKeyLeftArrow, )
            s.next_page_capture.keys = (EKeyHash, )#这里定义#键为向下翻一页
            s.last_page_capture.keys = (EKeyStar, )#这里定义*键为向上翻一页
            s.capture_tuple = (s.select_capture, s.backward_capture, s.next_page_capture, s.last_page_capture)#把所有要捕获的按键集中起来方便捕获
        except :
            pass#这里的pass的意思是什么也不做
        s.PM = ui.popup_menu#你可以暂时把这里的ui理解为appuifw








    def start_capture(s):#开始按键捕获
        try :#异常处理跟上面的一样
            map(lambda x, : x.start() , s.capture_tuple)#map函数,把上面我们定义的要捕获的按键元祖依次代入start函数进行执行
        except :
            pass








    def stop_capture(s):#停止按键捕获
        try :
            map(lambda x, : x.stop() , s.capture_tuple)#跟上面的开始捕获一样的,不多解释
        except :
            pass








    def return_ui(s):
        pass








    def select(s):#定义选择文件
        if s.list == [] : #如果得到的列表为空则直接返回
            return None
        else : #如果列表不为空的话
            try :
                import keypress
                try :
                    from key_codes import EKeySelect as EKeySelect#从key_codes模块导入EKeySelect 注:导航中间的确定键
                except :
                    EKeySelect = 63557
                s.direction = 0 #这里的s.direction 参数是为了表明是在当前目录下,如果为-1 则表示后退返回上一级目录,如果为1 则表示前进到下一级目录
                keypress.simulate_key(EKeySelect, EKeySelect)#调用keypress模块里的simulate_key函数,模拟按确定键
            except :
                pass
            pass








    def backward(s):#定义返回上一级
        if s.list == s.disks : #这里是为了排除隐患,如果一直返回的话会返回到跟目录(注:c:,d:,e:,z,如果到根目录还返回的话会出错的,这里定义到了根目录直接退出这个函数
            return None
        else : #如果没到根目录,接着返回上一级
            try :
                import keypress
                try :
                    from key_codes import EKeySelect as EKeySelect
                except :
                    EKeySelect = 63557
                s.direction = -1 #注意到这里没,这里就是我前面提到的返回上一级目录的标识
                keypress.simulate_key(EKeySelect, EKeySelect)
            except :
                pass
            pass








    def next_page(s):#定义向下翻页
        try :
            import keypress
            try :
                from key_codes import EKeyDownArrow as EKeyDownArrow
            except :
                EKeyDownArrow = 63498
            map(lambda x, :  keypress.simulate_key(EKeyDownArrow, EKeyDownArrow) , range(6))#map函数,具体这里的range(6) ,我不清楚为何这样使用,不过这里的作用是使光标向下连续移动6下
        except :
            pass








    def last_page(s):#定义向上翻页
        try :
            import keypress
            try :
                from key_codes import EKeyUpArrow as EKeyUpArrow
            except :
                EKeyUpArrow = 63498
            map(lambda x, :  keypress.simulate_key(EKeyUpArrow, EKeyUpArrow) , range(6))#这里跟上面的向下翻页是一样的
        except :
            pass








    def focus(s, fg):#定义转到后台时执行的动作
        if s.path != '历史文件\' : #如果路径不为历史文件这个路径的话
            if fg : #如果程序在前台运行,执行快捷键的准备,并开始捕获
                s.prepare()
                s.start_capture()
            else : #如果程序转到后台了停止按键捕获
                s.stop_capture()
            pass
        elif fg : #如果路径是历史文件,并且程序在前台运行,因为我们定义了历史管理,所以这里我们就停止按键捕获
            s.prepare()
            s.stop_capture()








    def history_manager(s):#历史管理
        history_list = [h for h in history.list if os.path.isfile(en(h)) ]#这里的history.list是历史文件里的文件路径,这里用到了列表里的一个技巧,首先去history.list里的一个文件,判断是否是一个文件,如果是就把它加入到history_list里面,如果不是就接着判断下一个
        list = [(u'%s(%s)' % (os.path.basename(i), os.path.dirname(i))) for i in history_list]#这里的%s代表一个字符串,与后面的元素一一相对应,分别为文件的名字和文件的路径名
        if history_list == [] : #如果得到的历史列表为空,提示用户无历史记录,然后返回
            ui.note(zw('无历史记录'))
            return None
        ask = ui.popup_menu(list, zw('历史文件'))#如果记录不为空,弹出菜单请用户选择一个历史记录
        if ask is None : #如果用户选择取消,直接返回
            return None
        else : #如果用户选择了一个历史记录,返回选择的文件的路径
            return history_list[ask]








    def AskDir(s, path = '', title = '选择目录'.decode('u8'), disks = e32.drive_list(), dirs = [], auto_return_ui = False, body_process = False):#目录浏览
        s.prepare()#准备快捷键处理
        s.title = title
        s.disks = [en(i) for i in disks]#这里也等于["C:","D:","E:","Z:"]
        s.disks.extend([i[0].upper() + i[1 : ] for i in dirs])#这里的i[0].upper()处理是为了把某个文件的路径的第一个字母,比如c,e等等转换成大写字母,至于为什么呢,因为用e32.drive_list()得到的都是大写字母,不知道大家发现没有,这里转换成大写是为了避免出错
        s.path = path
        if len(s.path) > 0 : #如果参数path不为空,且不是以"\"结尾的,就在路径后面加上一个"\"
            if  not (s.path.endswith('\\')) :
                s.path += '\\'
            s.path = path[0].upper() + path[1 : ]#这里的处理同样是为了把第一个字母转换成大写的,
        if  not (os.path.isdir(s.path)) : #如果提供的参数path不是一个存在的路径那么直接把path置为空
            s.path = ''
        s.direction = 1#工作方式设置为1,表示前进,进入下一级
        s.old_focus = ui.app.focus#保存程序原来的焦点(也就是程序在前台还是后台)
        ui.app.focus = s.focus#调用focus函数
        s.start_capture()#开始按键捕获
        while True : #这里是核心,比较重要,要好好分析才能理解
        ①  if s.path == '' : #如果提供的参数path为空,则把列表设置为根目录,让用户选择
                s.find = s.disks
                s.list = [zw(i) for i in s.disks]
                s.choose = s.PM(s.list, s.title)
        ③  else : #如果提供的参数path不为空
                try :
                    s.find = [i for i in os.listdir(s.path) if os.path.isdir(s.path + i) ]#把path路径下的文件夹加入到s.find列表中
                except OSError :
                    s.find = []
                s.list = [(u'[%s]' % zw(i)) for i in s.find]#转换成中文,并以"[文件夹路径]"这样的形式显示
                s.list.insert(0, (zw('/%s/') % zw(s.path.split('\\')[-2])))#在显示的列表的第一行插入上一级的路径的名字,例如提供的path为"e:\\system\\iPro7",经过上面的处理后path变为"e:\\system\\iPro7\\",加入我们现在进入到了iPro7这个文件夹下,那么第一行会显示/iPro7/,然后下面的才是iPro7下的文件夹
                s.choose = s.PM(s.list, s.title)#弹出可供选择的路径,供用户选择
        ④      if s.choose is not None : #如果用户选择了,把s.choose的值减1
                    s.choose -= 1
                pass
            if s.choose is None : #如果用户没有选择,判断提供的参数path是否为空,不为空则表示返回上一级,如果path为空,则停止按键捕获,并且返回
                if  not (s.path == '') :
                    s.direction = -1
                else :
                    s.stop_capture()
                    ui.app.focus = s.old_focus
                    return None
                pass
        ⑤  if s.choose == -1 and s.direction != -1 : #如果用户选择了第一个(注:上一级路径),且s.direction标识不是-1(注:返回上一级路径),停止按键捕获,返回选择的路径(注:这里先判断s.direction != -1是判断用户是否选择了返回上一级,否则容易乱的)
                s.stop_capture()
                ui.app.focus = s.old_focus
                return s.path
         ② elif s.direction == 1 : #如果s.direction标识为1(注:表示进入到下一级目录),则更新现在的path路径值为用户当前选择的路径,注意这里并没有退出while循环,如果path不以"\"结尾,在path路径末尾加上"\"
                s.path += s.find[s.choose]
                if  not (s.path.endswith('\\')) :
                    s.path += '\\'
                pass
            elif s.direction == 0 : #如果用户不是选择第一个且s.direction标识为0(注:表示选择当前目录),则更新现在的path路径值为用户当前选择的路径,现在已经完成了任务,退出while循环并返回用户选择的路径,如果path不以"\"结尾,在path路径末尾加上"\"
                s.path += s.find[s.choose]
                if  not (s.path.endswith('\\')) :
                    s.path += '\\'
                s.stop_capture() #停止按键捕获
                ui.app.focus = s.old_focus
                return s.path #退出while循环
            elif s.direction == -1 : #如果s.direction 的标识为-1(注:返回上一级目录)
                if s.path[ : -1] in s.disks : #如果已经返回到根目录了把s.path的值置为空,这里要注意为何是s.path[:-1]呢,因为现在的根目录已经变成["C:\","D:\","E:\","Z:\"]其中的一个,这里使用-1 表示不包括"\"正好达到我们的要求
                    s.path = ''
                else : #这里是处理返回上一级目录的核心代码,注意了!
                    for i in range((len(s.path) - 2), -1, -1): #注意这里是为了得到s.path的长度-2的值且倒数输出,(这里不太好理解,我举个例子:for i in range(5,-1,-1):print i,   将会输入5,4,3,2,1,0 )  你会又疑惑了为什么要减2呢,(我再举个例子:s.path="e:\system\iPro7\"  减2之后就把s.path里面的最后的那个"\"屏蔽掉了,注意现在s.path[0]是e ,从零开始计数的,所以我们要减2)
                        if s.path == '\\' : #这里一直在for中循环,直到找到倒数第二个"\"标志为止,好了现在我们已经得到上一级的目录了,厉害吧
                            s.path = s.path[ : (i + 1)] #这里把s.path[ : (i + 1)] 是为了让s.path中最后保留下"\"符号
                            break
                    pass
                pass
            s.direction = 1 #设置默认的工作方式为1,(进入到下一级目录)
    #哇 ,好长啊,有点看不懂了都,没关系慢慢来多看几遍就理解了,下面我会举几个例子来让你好好理解下程序是如何执行这段代码的:假如我们为path提供的参数为空,首先呈现给我们的应该是根目录这里执行①,然后我们选择E盘这里执行到②了,因为我们默认的工作方式就是s.direction = 1,然后执行③因为现在的path已经不是空了而是我们选择的"E:\"了,然后我们选择第一个,并摁导航中间的确定键,或者导航右键则执行到④,紧接着会执行⑤,至此退出while循环,其他的运行方式跟这个很类似了我就不多举例了(具体测试方法可以在iPor7中把浏览器设置为浏览器2,然后再工作目录中,选择添加目录进行测试)








    def AskFile(s, path = '', title = '选择文件'.decode('u8'), disks = e32.drive_list(), ext = [], dirs = [], auto_return_ui = False, body_process = False, history_read_only = False, multi = False, able_history = True):#文件浏览,跟目录浏览基本差不多
        s.prepare()#仍然是快捷键的准备
        s.title = title
        s.disks = [en(i) for i in disks]
        s.disks.extend([i[0].upper() + i[1 : ] for i in dirs])
        if able_history : #是否显示历史文件目录,默认显示历史文件
            s.disks.insert(0, '历史文件')#在显示的根目录下插入"历史文件"这一项
        s.path = path
        if s.path != '历史文件\\' : #判断提供的path参数如果不是"历史文件\\"这个路径,进一步判断path的长度,如果不为空且不是以"\\"结尾的,在path结尾添加"\\"
            if len(s.path) > 0 :
                if  not (s.path.endswith('\\')) :
                    s.path += '\\'
                s.path = path[0].upper() + path[1 : ] #把路径的第一个字母转换成大写字母
            if  not (os.path.isdir(s.path)) : #判断所给路径是否是真是路径,如果不是把path的值置为空
                s.path = ''
            pass
        s.ext = [x.lower() for x in ext] #把提供的后缀转换成小写字母
        s.direction = 1 #设置默认工作方式为进入下一级目录
        s.old_focus = ui.app.focus #取得程序原来的焦点
        ui.app.focus = s.focus #当程序焦点变化时调用focus函数
        s.start_capture()
        e32.ao_sleep(0.1) #暂停0.1秒的时间
        while True : #这里有是核心代码了,注意了一直循环直到用户选择文件或者取消选择
            if s.path == '' : #如果提供的path为空把s.find置为根目录
                s.find = s.find_dir = s.disks
                s.find_file = [] #创建一个空列表来存储查找到的文件
                s.list = [zw(i) for i in s.find_dir] #把列表设置为根目录
            elif s.path == '历史文件\\' : #如果提供的path为"历史文件"则停止按键捕获,调用前面我们提供的history_manager函数来处理
                s.stop_capture()
                ask_history = s.history_manager()#从历史记录中打开想找的文件
                if ask_history is None : #如果用户选择了取消,把path路径置为空,并开始按键捕获,重头开始选择文件(相当于退出了历史文件管理)
                    s.path = ''
                    s.start_capture()
                    continue #后面的语句块都不会执行,直接从while开始重新执行,并选择文件
                else : #如果选择了文件,还原程序原来的焦点退出while循环,返回选择的文件的路径
                    ui.app.focus = s.old_focus
                    return [en(ask_history)]
                pass
            else : #如果提供的path不为空也不是"历史文件\\"
                try :
                    s._find = os.listdir(s.path) #使用s._find来存储s.path路径下的文件夹和文件
                except OSError : #如果出现异常,则把s.find置为空列表
                    s._find = []
                s.find_dir = [i for i in s._find if os.path.isdir(s.path + i) ] #把s.find列表里的文件夹分离出来保存到s.find_dir里
                if len(s.ext) > 0 : #如果存在后缀限制,把s._find里符合后缀限制的的文件分离出来
                    s.find_file = [i for i in s._find if os.path.isfile(s.path + i) and os.path.splitext(i)[-1].lower() in s.ext ]
                else : #如果没有后缀限制,把所有的文件分离出来
                    s.find_file = [i for i in s._find if os.path.isfile(s.path + i) ]
                s.find = s.find_dir + s.find_file #把两个列表组合,得到所有的文件夹和文件
                s.list = [(u'[%s]' % zw(i)) for i in s.find_dir] #把文件夹以"[文件夹名字]"的形式添加到s.list列表中
                s.list.extend([zw(i) for i in s.find_file]) #把文件以名字的形式添加到s.list列表中,这就是为什么前面我们把文件夹和文件分开
            if s.list == [] : #如果得到的列表为空,比如说我们找到某个空目录之后等等情况,使用全局提示用户无内容
                import globalui
                s.stop_capture()
                globalui.global_msg_query(zw('无内容'), s.title)
                s.start_capture()
                s.choose = None #没有内容当然就没有选择了,把它置为None下面我们判断会用到的
                s.direction = -1 #设置工作方式为返回上一级,这个目录都没有我们想要的文件了当然得返回了,哈哈
            else :  #如果列表不为空,显示供选择的列表,让用户选择
                s.choose = s.PM(s.list, s.title)
            if s.choose is None : #如果用户选择取消或这目录为空(上面我提到过的)
                if s.path != '' : #判断路径是否为空,不为空设置工作方式为返回上一级
                    s.direction = -1
                else : #如果路径为空的话(这种可能应该是用户已经回到了根目录仍然选择返回,也就是返回程序主界面,编辑界面)停止按键捕获并返回一个空列表
                    s.stop_capture()
                    ui.app.focus = s.old_focus
                    return []
                pass
            if s.direction == 0 or s.direction == 1 : #根据上面我们得到的工作方式来执行相应的动作,如果工作方式为0 或者1
                s.path += s.find[s.choose] #更新s.path为选择一个文件或这路径之后的路径
                if s.find[s.choose] in s.find_file : #如果选择了一个文件则停止捕获并返回选择的文件的路径,例如选择了"e:\\data\\iPro7\\text.py"则返回"e:\\data\\iPro7\\text.py"
                    s.stop_capture()
                    ui.app.focus = s.old_focus
                    return [s.path]
                else : #如果选择的是一个文件夹,判断当前的s.path 是否以"\\"结尾,如果不是就添加,并设置工作方式为进入下一级目录,继续while循环
                    if  not (s.path.endswith('\\')) :
                        s.path += '\\'
                    s.direction = 1
                    continue
                pass
            elif s.direction == -1 : #这里就是我们处理前面我们设置的工作方式了
                if s.path[ : -1] in s.disks : #如果返回到了根目录,把s。path的值置为空
                    s.path = ''
                else : #如果没到根目录,
                    for i in range((len(s.path) - 2), -1, -1):#注意这里是为了得到s.path的长度-2的值且倒数输出,(这里不太好理解,我举个例子:for i in range(5,-1,-1):print i,   将会输入5,4,3,2,1,0 )  你会又疑惑了为什么要减2呢,(我再举个例子:s.path="e:\system\iPro7\"  减2之后就把s.path里面的最后的那个"\"屏蔽掉了,注意现在s.path[0]是e ,从零开始计数的,所以我们要减2)
                        if s.path == '\\' : #这里一直在for中循环,直到找到倒数第二个"\"标志为止,好了现在我们已经得到上一级的目录了,厉害吧
                            s.path = s.path[ : (i + 1)]  #这里把s.path[ : (i + 1)] 是为了让s.path中最后保留下"\"符号
                            break #跳出while循环
                    pass
                s.direction = 1 #设置默认的工作方式是进入下一级目录




#真不容易啊,这个文件管理器终于分析完了,还是老规矩哪里不懂的可以联系我,或者跟帖提问我会尽量回答的



后面我会相继分析模块管理,等等


评分次数:1 次  财富值: +12     

本帖最近 评分/打赏 记录
lisen9065   2011-4-1 07:30  财富值  +12    精品文章,辛苦了。




[fly]小马专用[/fly]
顶部
lisen9065 (DDC)
高级版主
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
学业繁忙、不在。


论坛建设奖  
UID 10350802
精华 0
积分 6666
帖子 6666
威望 89 点
财富值 27791 塞班币
贡献值 120 点
好评度 109 点
交易信用 0 点
原创小红花 31 朵
人气值 195 点
阅读权限 100
注册 2009-6-21
手机型号  S60v3/Android Pad
来自 江门新会(人在华农)
状态 在线
 
发表于 2011-4-1 07:31  资料  个人空间  短消息  加为好友  添加 lisen9065 为MSN好友 通过MSN和 lisen9065 交谈 QQ
很长很详细,辛苦了!





        Sina/TX微博: @DDC_lisen_仔森


Twitter: @DDC_lisen                                      


顶部
A10633035
排长
Rank: 3Rank: 3



UID 20466788
精华 0
积分 229
帖子 229
威望 0 点
财富值 220 塞班币
贡献值 0 点
好评度 0 点
交易信用 0 点
原创小红花 0 朵
人气值 0 点
阅读权限 10
注册 2010-7-6
手机型号  Nokia N80
来自 佛山
状态 离线
 
发表于 2011-4-3 08:43  资料  个人空间  短消息  加为好友 
很好好強大!





繁星流动,和你同路……
顶部
♂天涯一角 (请辞了~)
荣誉会员
Rank: 12Rank: 12Rank: 12
( DDC预备队)角度决定视野!


塞班元勋奖  
UID 12633588
精华 0
积分 14710
帖子 14710
威望 89 点
财富值 30656 塞班币
贡献值 15 点
好评度 109 点
交易信用 0 点
原创小红花 29 朵
人气值 229 点
阅读权限 60
注册 2009-10-1
手机型号  Android/Symbian
来自 内蒙古(现在湖北)
状态 离线
 
发表于 2011-4-3 10:29  资料  个人空间  短消息  加为好友 
标记上,有时间在好好学习下





【最新出品】MBTI权威职业测试最新版☜点此下载
追心之所向,持久坚持...为了明天,继续奋斗...

顶部
笑洏芣語
司令
Rank: 10Rank: 10Rank: 10
smilence、


UID 17908346
精华 0
积分 8181
帖子 8181
威望 0 点
财富值 8345 塞班币
贡献值 0 点
好评度 1 点
交易信用 0 点
原创小红花 0 朵
人气值 14 点
阅读权限 50
注册 2010-4-14
手机型号  E71+6220c+5320xm
来自 辽宁沈阳
状态 离线
 
发表于 2011-4-26 09:11  资料  个人空间  短消息  加为好友  QQ
刚刚接触。。支持





顶部
冷色的咖啡
旅长
Rank: 7Rank: 7Rank: 7


UID 28556484
精华 0
积分 1554
帖子 1554
威望 1 点
财富值 1283 塞班币
贡献值 0 点
好评度 1 点
交易信用 0 点
原创小红花 0 朵
人气值 27 点
阅读权限 35
注册 2011-3-26
手机型号  诺基亚N72
状态 离线
 
发表于 2012-1-27 05:49  资料  个人空间  短消息  加为好友  QQ
支持下,学习了





每个人都是独一无二的,我这一生只能做我自己,成为不了别人。

顶部
雨月梦
连长
Rank: 4


UID 31773204
精华 0
积分 424
帖子 424
威望 0 点
财富值 496 塞班币
贡献值 0 点
好评度 0 点
交易信用 0 点
原创小红花 0 朵
人气值 0 点
阅读权限 15
注册 2011-7-30
手机型号  c5-03
状态 离线
 
发表于 2012-2-5 22:13  资料  个人空间  短消息  加为好友 
是不是用了这个文件管理2的模式,触屏就可以流畅浏览文件?新手求教。。。





顶部
 





当前时区 GMT+8, 现在时间是 2012-5-27 16:22
京ICP备12006419号

百度精准投放VIP客户    基于Discuz!  dospy自优化版本1.0 © 2005-2011
Processed in 0.040455 second(s), 7 queries , Gzip enabled

清除 Cookies - 联系我们 - 工作机会 - dospy智能手机网 - 电信与信息服务业务经营许可证京ICP证090114号 - Archiver - WAP