#coding=utf-8 # # AutoGenSystem # 声明: # 该软件主要是为了解决Android系统更新时,由于版本很多,管理起来复杂,容易出错,于是采用软件 # 自动对系统软件进行组合,目前该软件还没有对生成的文件夹加入命名规范。 # # 2016-1-2 深圳 南山平山村 曾剑锋 # 参考文档: # 1. PySide : How to get the clicked QPushButton object in the QPushButton clicked slot? # http://stackoverflow.com/questions/20320298/pyside-how-to-get-the-clicked-qpushbutton-object-in-the-qpushbutton-clicked-sl # 2. python 字符串split的用法分享 # http://www.jb51.net/article/34998.htm # 3. Python中使用定时器Sleep定时秒及毫秒。 # http://jingyan.baidu.com/article/4b07be3c65263a48b380f3b4.html # 4. 去空格及特殊符号 # http://www.cnblogs.com/huangcong/archive/2011/08/29/2158268.html # 5. Python中函数的参数定义和可变参数 # http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944416.html # 6. python 多线程就这么简单 # http://www.cnblogs.com/fnng/p/3670789.html # 7. python threads can only be started once # http://zhidao.baidu.com/link?url=8x7GpDdNmcL3TQZ0iDibdkx5Y2MdgcxnlATPkvMX4EwXsR2ZxJ37lDapbeehaHNvGmQxjupjnx4ynsxfAuGipC1wbOUoTaHqmzyLcmcffza # # import sys import os import shutil import time import threading from PyQt4.QtCore import * from PyQt4.QtGui import * from ui_AutoGenSystem import Ui_GenSystemUI class AutoGenSystem(QDialog): def __init__(self): QDialog.__init__(self) self.ui = Ui_GenSystemUI() self.ui.setupUi(self) self.setWindowTitle("AutoGenSystem") self.setFixedHeight(self.height()) self.setFixedWidth(self.width()) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint); # 连接信号与槽 self.ui.chooseUbootPath.clicked.connect(lambda :self.dealWithPushButton(self.ui.chooseUbootPath)) self.ui.chooseRecoveryPath.clicked.connect(lambda :self.dealWithPushButton(self.ui.chooseRecoveryPath)) self.ui.chooseBootingPath.clicked.connect(lambda :self.dealWithPushButton(self.ui.chooseBootingPath)) self.ui.chooseFileSystemPath.clicked.connect(lambda :self.dealWithPushButton(self.ui.chooseFileSystemPath)) self.ui.clean.clicked.connect(self.cleanOnClicked) self.ui.current.clicked.connect(self.currentOnClicked) self.ui.autoAll.clicked.connect(self.autoAllOnClicked) #初始化一些全局变量,compound是指合成,也就合成的目录 self.ubootImagePath = "image/uboot/" self.fileSystemImagePath = "image/file_system/" self.recoveryImagePath = "image/recovery/" self.bootingImagePath = "image/booting/" self.readmeFilePath = "image/readme.txt" self.compoundPath = "compound/" self.ubootName = "uboot.img" self.bootingNmae = "boot.img" self.fileSystemName = "system.img" self.recoveryName = "recovery.img" # 检查这些文件路径是否存在 self.checkImagePathExist(self.ubootImagePath, self.fileSystemImagePath, self.recoveryImagePath, self.bootingImagePath, self.readmeFilePath) # 读取readme文件 if os.path.exists(self.readmeFilePath) : readme = open(self.readmeFilePath) self.ui.readme.setPlainText(QString.fromUtf8(readme.read())) readme.close() def currentOnClicked(self): # 检查文本框是否为空 if ( (len(self.ui.ubootPath.text()) == 0) or (len(self.ui.recoveryPath.text()) == 0) or (len(self.ui.bootingPath.text()) == 0) or (len(self.ui.fileSystemPath.text()) == 0) ): QMessageBox.about(self, "mesg", "Please choose all The image files on the left side.") return # 删除之前合成的目录,并重新创建合成目录 self.remakeCompoundDir() # 文件拷贝,并显示进度条、提示信息,5个文件,每次拷贝完一个文件,进度条往前跑20个点,跑完最后一个点就是100了 # 这里的self.compound字符串最后添加了"/",所以生成distPath的时候可以直接字符串连接。 i = 0; i += 1 self.copyImageFile(self.ui.ubootPath.text(), self.compoundPath + self.ubootName, 20 * i, "Copying uboot.img") i += 1 self.copyImageFile(self.ui.recoveryPath.text(), self.compoundPath + self.recoveryName, 20 * i, "Copying recovery.img") i += 1 self.copyImageFile(self.ui.bootingPath.text(), self.compoundPath + self.bootingNmae, 20 * i, "Copying boot.img") i += 1 self.copyImageFile(self.ui.fileSystemPath.text(), self.compoundPath + self.fileSystemName, 20 * i, "Copying system.img") i += 1 self.saveReadMeFile(self.compoundPath + "readme.txt", 20 * i, "Copying readme.txt.") self.ui.info.setText("Current copying is over.") def autoAllOnClicked(self): # 获取文件列表 ubootFiles = os.listdir(self.ubootImagePath) recoveryFiles = os.listdir(self.recoveryImagePath) bootingFiles = os.listdir(self.bootingImagePath) fileSystemFiles = "" if self.ui.systemType.currentIndex() == 0 : fileSystemFiles = os.listdir(self.fileSystemImagePath + "RES") else: fileSystemFiles = os.listdir(self.fileSystemImagePath + "PTC") # 删除之前合成的目录,并重新创建合成目录 self.remakeCompoundDir() # 拷贝文件,并计算进度条每次跳跃的阶数值,总循环次数allFilesCount,每套系统里面需要生成5个文件 # 设置进度条进度,Information tips信息 allFilesCount = len(ubootFiles) * len(recoveryFiles) * len(bootingFiles) * len(fileSystemFiles) processBarStep = 100.0 / allFilesCount / 5 # 每个文件夹5个文件 i = 0 for ubootFile in ubootFiles: for recoveryFile in recoveryFiles: for bootingFile in bootingFiles: for fileSystemFile in fileSystemFiles: newPath = self.compoundPath + ubootFile+"_"+recoveryFile+"_"+bootingFile+"_"+fileSystemFile + "/" os.mkdir(newPath) i += 1 self.copyImageFile(self.ubootImagePath + ubootFile, newPath + self.ubootName, processBarStep * i, "Copying uboot.img") i += 1 self.copyImageFile(self.recoveryImagePath + recoveryFile, newPath + self.recoveryName, processBarStep * i, "Copying recovery.img") i += 1 self.copyImageFile(self.bootingImagePath + bootingFile, newPath + self.bootingNmae, processBarStep * i, "Copying boot.img") i += 1 if self.ui.systemType.currentIndex() == 0 : self.copyImageFile(self.fileSystemImagePath + "RES/" + fileSystemFile, newPath + self.fileSystemName, processBarStep * i, "Copying system.img") else: self.copyImageFile(self.fileSystemImagePath + "PTC/" + fileSystemFile, newPath + self.fileSystemName, processBarStep * i, "Copying system.img") i += 1 self.saveReadMeFile("%s/readme.txt" % newPath, processBarStep * i, "Saving readme.txt.") self.ui.info.setText("AutoAll copying is over.") self.ui.progressBar.setValue(100) def cleanOnClicked(self): self.ui.systemType.setCurrentIndex(0) self.ui.ubootPath.setText("") self.ui.recoveryPath.setText("") self.ui.bootingPath.setText("") self.ui.fileSystemPath.setText("") self.ui.readme.setPlainText("") self.ui.progressBar.setValue(0) self.ui.info.setText("Information Tips.") def dealWithPushButton(self, button): filePath = "" if button.objectName() == "chooseUbootPath" : filePath = self.ubootImagePath elif button.objectName() == "chooseRecoveryPath" : filePath = self.recoveryImagePath elif button.objectName() == "chooseBootingPath" : filePath = self.bootingImagePath elif button.objectName() == "chooseFileSystemPath" : filePath = self.fileSystemImagePath if self.ui.systemType.currentIndex() == 0 : filePath += "/RES" else : filePath += "/PTC" # 检查文件路径是否存在 self.checkImagePathExist(filePath) # 获取文件路径,并将文件路径保存在UI界面的控件里去 choosePathString = QFileDialog.getOpenFileName(self, "Select file", filePath, "*") if len(choosePathString) == 0 : return self.setUIControlsPath(button, choosePathString) def checkImagePathExist(self, *paths): # 由于这里传入的参数可以是多个,可能有些路径有效,有些无效,在这里进行检查,将无效的路径提取出来,并给出提示 unexistPath = "" for path in paths : if not os.path.exists(path) : unexistPath += "\n\t" unexistPath += path unexistPath = unexistPath.strip() # 剔除字符串行头行尾的不显示字符,用于下面的比较和分割 if len(unexistPath) != 0 : if len(unexistPath.split("\n\t")) == 1 : QMessageBox.about(self, "mesg", "Please create this path in current software path:\n\t" + unexistPath + ".") else : QMessageBox.about(self, "mesg", "Please create those path in current software path:\n\t" + unexistPath + ".") exit() def copyImageFile(self, srcPath, distPath, progressBarValue, informationTips): self.ui.info.setText(informationTips) QFile.copy(srcPath, distPath) # 拷贝文件 self.ui.progressBar.setValue(progressBarValue) def copyASystemFile(self, ubootSrcPath, ubootDistPath, bootingSrcPath, bootingDistPath, recoverySrcPath, recoveryDistPath, fileSystemSrcPath, fileSystemDistPath, readmePath, processBarStep, index): # 文件拷贝,并显示进度条、提示信息,5个文件,每次拷贝完一个文件 # 这里的self.compound字符串最后添加了"/",所以生成distPath的时候可以直接字符串连接。 index self.copyImageFile(ubootSrcPath, ubootDistPath, processBarStep * index, "Copying uboot.img") index += 1 self.copyImageFile(bootingSrcPath, bootingDistPath, processBarStep * index, "Copying recovery.img") index += 1 self.copyImageFile(recoverySrcPath, recoveryDistPath, processBarStep * index, "Copying boot.img") index += 1 self.copyImageFile(fileSystemSrcPath, fileSystemDistPath, processBarStep * index, "Copying system.img") index += 1 self.saveReadMeFile(readmePath, processBarStep * index, "Copying readme.txt.") def saveReadMeFile(self, distPath, progressBarValue, informationTips): self.ui.info.setText(informationTips) readme = open( distPath, "w" ) readme.write(self.ui.readme.toPlainText().toUtf8()) # 保存的时候用Utf8,读的时候也是Utf8 readme.flush() readme.close() self.ui.progressBar.setValue(progressBarValue) def remakeCompoundDir(self): # 删除文件夹,创建文件夹,这个过程时间太短貌似有问题,所以加了延时,但目前没有摸清楚这个延时情况该如何解决 if os.path.exists("compound") : shutil.rmtree("compound") time.sleep(1) os.mkdir("compound") def disableAllControls(self): self.ui.systemType.setDisabled(True) self.ui.ubootPath.setDisabled(True) self.ui.recoveryPath.setDisabled(True) self.ui.bootingPath.setDisabled(True) self.ui.fileSystemPath.setDisabled(True) self.ui.readme.setDisabled(True) self.ui.clean.setDisabled(True) self.ui.current.setDisabled(True) self.ui.autoAll.setDisabled(True) def enableAllControls(self): self.ui.systemType.setDisabled(False) self.ui.ubootPath.setDisabled(False) self.ui.recoveryPath.setDisabled(False) self.ui.bootingPath.setDisabled(False) self.ui.fileSystemPath.setDisabled(False) self.ui.readme.setDisabled(False) self.ui.clean.setDisabled(False) self.ui.current.setDisabled(False) self.ui.autoAll.setDisabled(False) def setUIControlsPath(self, button, choosePathString): # 设置UI界面 if button.objectName() == "chooseUbootPath" : self.ui.ubootPath.setText(choosePathString) elif button.objectName() == "chooseRecoveryPath" : self.ui.recoveryPath.setText(choosePathString) elif button.objectName() == "chooseBootingPath" : self.ui.bootingPath.setText(choosePathString) elif button.objectName() == "chooseFileSystemPath" : self.ui.fileSystemPath.setText(choosePathString)