def main(): app = QtWidgets.QApplication(sys.argv) app.setOrganizationName("Leitisoft") app.setOrganizationDomain("leitschuh.net") app.setApplicationName("SnapSort") app.setQuitOnLastWindowClosed(False) w = QtWidgets.QWidget() wait_window = TrayIcon(QtGui.QIcon("resources/images/icon_systray.png"), w) wait_window.show() sys.exit(app.exec_())
def main(): __pychecker__ = 'unusednames=tray' gnome.program_init('tray', SamplerConfig.version) unique = Service.unique() if not unique: return client = gconf.client_get_default() gconf_dir = GConfDir(client, Keys.root, gconf.CLIENT_PRELOAD_ONELEVEL) tray = TrayIcon(client) gtk.main() del gconf_dir
def main(): initialize_config() # Configure logging. Reset with every restart logging.basicConfig( format='%(asctime)s [%(levelname)s]:[%(threadName)s] %(message)s', filename=log_file_path, filemode='w', level=logging.INFO) logging.info("Starting Safe Eyes") if not running(): validate_config() global break_screen global core global notification global tray_icon global language global context context = {} language = Utility.load_language(config['language']) # Initialize the Safe Eyes Context context['version'] = SAFE_EYES_VERSION tray_icon = TrayIcon(config, language, show_settings, show_about, enable_safeeyes, disable_safeeyes, on_quit) break_screen = BreakScreen(on_skipped, on_postponed, break_screen_glade, style_sheet_path) break_screen.initialize(config, language) core = SafeEyesCore(context, show_notification, show_alert, close_alert, on_countdown, tray_icon.next_break_time) core.initialize(config, language) core.start() notification = Notification(language) handle_system_suspend() Gtk.main() else: logging.info('SafeEyes is already running') sys.exit(0)
def __init__(self, parent): wx.Frame.__init__(self, parent, -1, "Battery state", style=wx.BORDER_DEFAULT, size=( 240, 120, )) self.panel = wx.Panel(self, -1) self._params = { dr.BAT_CHARGINGSTATE: "Charging state", dr.BAT_PRESENTRATE: "Present rate", dr.BAT_PRESENTVOLTAGE: "Present voltage", dr.BAT_REMAININGCAPACITY: "Remaining capacity" } self._ys = [10, 35, 60, 85] make_text_ctrl = lambda y: wx.TextCtrl(self.panel, -1, "", pos=(150, y), style=wx.TE_READONLY, size=(80, -1)) make_static_text = lambda text, y: wx.StaticText( self.panel, -1, text, pos=(10, y)) self._st = map(make_static_text, self._params.values(), self._ys) self._ed = dict(zip(self._params, map(make_text_ctrl, self._ys))) #updater self.info_getter = dr.IGSys("BAT0") self.fill_info(None) self.Bind(wx.EVT_TIMER, self.fill_info) self.timer = wx.Timer(self) self.timer.Start(3000) self.fill_info(None) self.tray = TrayIcon(self)
def __init__(self, parent=None): QtGui.QMainWindow.__init__(self, parent) self.setWindowTitle(u'掉话分析') self.setWindowIcon(QtGui.QIcon(resource_path('img/log.png'))) self.centralwidget = QWidget() self.setCentralWidget(self.centralwidget) self.resize(1000, 500) self.mainLayout = QtGui.QVBoxLayout() self.mainLayout.setAlignment(QtCore.Qt.AlignTop) self.mainLayout.setContentsMargins(5, 2, 5, 2) # select directory self.selectDirectoryLayout = QtGui.QHBoxLayout() self.selectDirectoryLineEdit = QtGui.QLineEdit() self.selectDirectoryLineEdit.setTextMargins(10, 0, 10, 0) self.selectDirectoryLineEdit.setMinimumHeight(25) self.selectDirectoryLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.selectDirectoryBtn = QtGui.QPushButton(u'选择文件夹') self.selectDirectoryBtn.connect(self.selectDirectoryBtn, QtCore.SIGNAL('clicked()'), self.selectDirectoryMethod) self.selectDirectoryLayout.addWidget(self.selectDirectoryBtn) self.selectDirectoryLayout.addWidget(self.selectDirectoryLineEdit) # download the log [from http://172.28.199.58/watch/index_prod.html#/watchda_web/logCollection] self.downloadLogLayout = QtGui.QHBoxLayout() self.dlBinderNumberLineEdit = QtGui.QLineEdit() self.dlBinderNumberLineEdit.setTextMargins(10, 0, 10, 0) self.dlBinderNumberLineEdit.setMinimumHeight(25) self.dlBinderNumberLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.dlImportBinderNumberBtn = QtGui.QPushButton(u'导入绑定号') self.dlImportBinderNumberBtn.connect(self.dlImportBinderNumberBtn, QtCore.SIGNAL('clicked()'), self.dlImportBinderNumberMethod) self.downloadLogLayout.addWidget(self.dlImportBinderNumberBtn) self.downloadLogLayout.addWidget(self.dlBinderNumberLineEdit) # analytics key word self.keywordLayout = QtGui.QHBoxLayout() self.keywordLineEdit = QtGui.QLineEdit() self.keywordLineEdit.setPlaceholderText(u'reportCallFailLD =') self.keywordLineEdit.setTextMargins(10, 0, 10, 0) self.keywordLineEdit.setMinimumHeight(25) self.keywordLineEdit.setFont(QtFontUtil().getFont('Monospace', 12)) self.keywordBtn = QtGui.QPushButton(u'输入关键字') self.keywordBtn.setDisabled(True) self.keywordLayout.addWidget(self.keywordBtn) self.keywordLayout.addWidget(self.keywordLineEdit) # operate buttons self.btnsLayout = QtGui.QHBoxLayout() self.downloadLogBtn = QtGui.QPushButton(u'下载日志') self.unzipBtn = QtGui.QPushButton(u'解压日志') self.analyticsBtn = QtGui.QPushButton(u'开始分析') self.generateDocumentBtn = QtGui.QPushButton(u'生成文档') self.openDirBtn = QtGui.QPushButton(u'打开文件夹') self.unzipBtn.setMinimumHeight(25) self.analyticsBtn.setMinimumHeight(25) self.generateDocumentBtn.setMinimumHeight(25) self.openDirBtn.setMinimumHeight(25) self.downloadLogBtn.connect(self.downloadLogBtn, QtCore.SIGNAL('clicked()'), self.downloadLogMethod) self.unzipBtn.connect(self.unzipBtn, QtCore.SIGNAL('clicked()'), self.unZipMethod) self.analyticsBtn.connect(self.analyticsBtn, QtCore.SIGNAL('clicked()'), self.analyticsMethod) self.analyticsBtn.connect(self.analyticsBtn, QtCore.SIGNAL('combineLogSignal(QString)'), self.combineLogWithAttr) self.generateDocumentBtn.connect(self.generateDocumentBtn, QtCore.SIGNAL('clicked()'), self.genDocMethod) self.openDirBtn.connect(self.openDirBtn, QtCore.SIGNAL('clicked()'), self.openDirMethod) self.btnsLayout.addWidget(self.downloadLogBtn) self.btnsLayout.addWidget(self.unzipBtn) self.btnsLayout.addWidget(self.analyticsBtn) self.btnsLayout.addWidget(self.generateDocumentBtn) self.btnsLayout.addWidget(self.openDirBtn) # show log self.LogTextEdit = QtGui.QTextEdit() self.LogTextEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.LogTextEdit.setFont(QtFontUtil().getFont('Monospace', 12)) self.LogTextEdit.connect(self.LogTextEdit, QtCore.SIGNAL('appendLogSignal(QString)'), self.appendLog) # addLayout self.mainLayout.addLayout(self.selectDirectoryLayout) self.mainLayout.addLayout(self.downloadLogLayout) self.mainLayout.addLayout(self.keywordLayout) self.mainLayout.addLayout(self.btnsLayout) self.mainLayout.addWidget(self.LogTextEdit) self.centralwidget.setLayout(self.mainLayout) # 优化文件数据分析性能,已分组形式进行, 这两个变量记录总共需要分析的分组数量,以及已经分析的组数 # self.analyticsGroupTotalSize = 0 # self.processedGroupSize = 0 # self.processedGroupLock = threading.Lock() # 接收 keywordLineEdit 中输入的关键字 self.analyKeyword = None # 接收基础信息 baseAttr 的关键字 self.baseAttrKeyword = None # # 搜索keyword 时,返回包含keyword的行数据 # self.searchedKeywordLines = "" # # 搜索基础信息baseAttr时, 返回包含baseAttr的行数据 # self.searchedBaseAttrLines = "" # 保存分析的日志信息集合 self.analyticsLogList = [] # 保存基本信息的集合 self.baseAttrList = [] # 多线程中进行集合过滤的锁 self.filterLogLock = threading.Lock() self.filterAttrLock = threading.Lock() # 保存最后分析结果 CallFailBean 的集合 self.callFailList = [] # 保存从excel 导入的绑定号集合 self.binderNumberList = [] # 显示托盘 self.tray = TrayIcon(parent=self, clickEnable=False) self.tray.connect(self.tray, QtCore.SIGNAL('showTrayMsgSignal(QString)'), self.showTrayMsg)
class CallFailWindow(QtGui.QMainWindow): def __init__(self, parent=None): QtGui.QMainWindow.__init__(self, parent) self.setWindowTitle(u'掉话分析') self.setWindowIcon(QtGui.QIcon(resource_path('img/log.png'))) self.centralwidget = QWidget() self.setCentralWidget(self.centralwidget) self.resize(1000, 500) self.mainLayout = QtGui.QVBoxLayout() self.mainLayout.setAlignment(QtCore.Qt.AlignTop) self.mainLayout.setContentsMargins(5, 2, 5, 2) # select directory self.selectDirectoryLayout = QtGui.QHBoxLayout() self.selectDirectoryLineEdit = QtGui.QLineEdit() self.selectDirectoryLineEdit.setTextMargins(10, 0, 10, 0) self.selectDirectoryLineEdit.setMinimumHeight(25) self.selectDirectoryLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.selectDirectoryBtn = QtGui.QPushButton(u'选择文件夹') self.selectDirectoryBtn.connect(self.selectDirectoryBtn, QtCore.SIGNAL('clicked()'), self.selectDirectoryMethod) self.selectDirectoryLayout.addWidget(self.selectDirectoryBtn) self.selectDirectoryLayout.addWidget(self.selectDirectoryLineEdit) # download the log [from http://172.28.199.58/watch/index_prod.html#/watchda_web/logCollection] self.downloadLogLayout = QtGui.QHBoxLayout() self.dlBinderNumberLineEdit = QtGui.QLineEdit() self.dlBinderNumberLineEdit.setTextMargins(10, 0, 10, 0) self.dlBinderNumberLineEdit.setMinimumHeight(25) self.dlBinderNumberLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.dlImportBinderNumberBtn = QtGui.QPushButton(u'导入绑定号') self.dlImportBinderNumberBtn.connect(self.dlImportBinderNumberBtn, QtCore.SIGNAL('clicked()'), self.dlImportBinderNumberMethod) self.downloadLogLayout.addWidget(self.dlImportBinderNumberBtn) self.downloadLogLayout.addWidget(self.dlBinderNumberLineEdit) # analytics key word self.keywordLayout = QtGui.QHBoxLayout() self.keywordLineEdit = QtGui.QLineEdit() self.keywordLineEdit.setPlaceholderText(u'reportCallFailLD =') self.keywordLineEdit.setTextMargins(10, 0, 10, 0) self.keywordLineEdit.setMinimumHeight(25) self.keywordLineEdit.setFont(QtFontUtil().getFont('Monospace', 12)) self.keywordBtn = QtGui.QPushButton(u'输入关键字') self.keywordBtn.setDisabled(True) self.keywordLayout.addWidget(self.keywordBtn) self.keywordLayout.addWidget(self.keywordLineEdit) # operate buttons self.btnsLayout = QtGui.QHBoxLayout() self.downloadLogBtn = QtGui.QPushButton(u'下载日志') self.unzipBtn = QtGui.QPushButton(u'解压日志') self.analyticsBtn = QtGui.QPushButton(u'开始分析') self.generateDocumentBtn = QtGui.QPushButton(u'生成文档') self.openDirBtn = QtGui.QPushButton(u'打开文件夹') self.unzipBtn.setMinimumHeight(25) self.analyticsBtn.setMinimumHeight(25) self.generateDocumentBtn.setMinimumHeight(25) self.openDirBtn.setMinimumHeight(25) self.downloadLogBtn.connect(self.downloadLogBtn, QtCore.SIGNAL('clicked()'), self.downloadLogMethod) self.unzipBtn.connect(self.unzipBtn, QtCore.SIGNAL('clicked()'), self.unZipMethod) self.analyticsBtn.connect(self.analyticsBtn, QtCore.SIGNAL('clicked()'), self.analyticsMethod) self.analyticsBtn.connect(self.analyticsBtn, QtCore.SIGNAL('combineLogSignal(QString)'), self.combineLogWithAttr) self.generateDocumentBtn.connect(self.generateDocumentBtn, QtCore.SIGNAL('clicked()'), self.genDocMethod) self.openDirBtn.connect(self.openDirBtn, QtCore.SIGNAL('clicked()'), self.openDirMethod) self.btnsLayout.addWidget(self.downloadLogBtn) self.btnsLayout.addWidget(self.unzipBtn) self.btnsLayout.addWidget(self.analyticsBtn) self.btnsLayout.addWidget(self.generateDocumentBtn) self.btnsLayout.addWidget(self.openDirBtn) # show log self.LogTextEdit = QtGui.QTextEdit() self.LogTextEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.LogTextEdit.setFont(QtFontUtil().getFont('Monospace', 12)) self.LogTextEdit.connect(self.LogTextEdit, QtCore.SIGNAL('appendLogSignal(QString)'), self.appendLog) # addLayout self.mainLayout.addLayout(self.selectDirectoryLayout) self.mainLayout.addLayout(self.downloadLogLayout) self.mainLayout.addLayout(self.keywordLayout) self.mainLayout.addLayout(self.btnsLayout) self.mainLayout.addWidget(self.LogTextEdit) self.centralwidget.setLayout(self.mainLayout) # 优化文件数据分析性能,已分组形式进行, 这两个变量记录总共需要分析的分组数量,以及已经分析的组数 # self.analyticsGroupTotalSize = 0 # self.processedGroupSize = 0 # self.processedGroupLock = threading.Lock() # 接收 keywordLineEdit 中输入的关键字 self.analyKeyword = None # 接收基础信息 baseAttr 的关键字 self.baseAttrKeyword = None # # 搜索keyword 时,返回包含keyword的行数据 # self.searchedKeywordLines = "" # # 搜索基础信息baseAttr时, 返回包含baseAttr的行数据 # self.searchedBaseAttrLines = "" # 保存分析的日志信息集合 self.analyticsLogList = [] # 保存基本信息的集合 self.baseAttrList = [] # 多线程中进行集合过滤的锁 self.filterLogLock = threading.Lock() self.filterAttrLock = threading.Lock() # 保存最后分析结果 CallFailBean 的集合 self.callFailList = [] # 保存从excel 导入的绑定号集合 self.binderNumberList = [] # 显示托盘 self.tray = TrayIcon(parent=self, clickEnable=False) self.tray.connect(self.tray, QtCore.SIGNAL('showTrayMsgSignal(QString)'), self.showTrayMsg) # 选择文件夹 def selectDirectoryMethod(self): lastDir = self.getLastOpenDir() dirPath = unicode( QtGui.QFileDialog.getExistingDirectory(None, u'选择文件夹', lastDir)) if not dirPath or not os.path.exists(dirPath): self.appendLog(u'您尚未选择日志文件路径! 请先选择日志路径。') return logStr = u'日志路径为: ' + str(dirPath) self.appendLog(logStr) self.selectDirectoryLineEdit.setText(dirPath) # 获取QFileDialog 上次打开的路径 def getLastOpenDir(self): lastDir = self.selectDirectoryLineEdit.text() if lastDir: return str(lastDir) # open last remember directory lastDir = QSettingsUtil.getLastDir() if not QtCore.QDir(lastDir).exists(): lastDir = 'd://' return str(lastDir) # download log. load binder number(下载日志时,需要提前导入绑定号) # 操作excel 数据 https://www.cnblogs.com/lhj588/archive/2012/01/06/2314181.html def dlImportBinderNumberMethod(self): filePath = unicode( QtGui.QFileDialog.getOpenFileName(None, 'Select file', self.getLastOpenDir(), 'binder_number(*.xls *.xlsx)')) if not filePath: return # print 'binderNumberFilePath: ', filePath binderNumberListStr = '' try: data = xlrd.open_workbook(unicode(filePath)) binderNumberTable = data.sheets()[0] # print 'table row: ', binderNumberTable.nrows # print 'table col: ', binderNumberTable.ncols for i in range(binderNumberTable.ncols): binderNumberColList = binderNumberTable.col_values(i) for binderNumber in binderNumberColList: if binderNumber not in self.binderNumberList: self.binderNumberList.append(binderNumber) binderNumberListStr += (binderNumber + '|') # print 'table col: ', binderNumberTable.col_values(i) # print 'table row: ', binderNumberTable.row_values(i) except Exception as e: self.binderNumberList = [] raise e print 'binderNumberList: ', self.binderNumberList self.dlBinderNumberLineEdit.setText(binderNumberListStr) # 点击下载日志按钮,从服务器[http://172.28.199.58/watch/index_prod.html#/watchda_web/logCollection]下载日志 def downloadLogMethod(self): selectDir = str(self.selectDirectoryLineEdit.text()) if not selectDir: self.appendLog(u'您尚未选择日志文件路径! 请先选择日志路径。') return importedBinderNumbers = str(self.dlBinderNumberLineEdit.text()) if not importedBinderNumbers: self.appendLog(u'请导入需要下载日志的绑定号!') return # self.doDownloadLog(log_call_back=self.emitAppendLogSignal) threadUtil = ThreadUtil(funcName=self.doDownloadLog, log_call_back=self.emitAppendLogSignal) threadUtil.setDaemon(True) threadUtil.start() # 开始下载日志 def doDownloadLog(self, log_call_back): dlLogByWeb = DownloadLogByWeb() dlLogByWeb.setCallBack(log_call_back) dlLogByWeb.login() dlLogByWeb.setBinderNumberList(self.binderNumberList) dlLogByWeb.downloadLog() # 点击解压日志按钮 def unZipMethod(self): # self.doUnzipFile(log_call_back=self.emitAppendLogSignal) threadUtil = ThreadUtil(funcName=self.doUnzipFile, log_call_back=self.emitAppendLogSignal) threadUtil.setDaemon(True) threadUtil.start() # 解压文件 def doUnzipFile(self, log_call_back): selectDir = str(self.selectDirectoryLineEdit.text()) if not selectDir: log_call_back(u'您尚未选择日志文件路径! 请先选择日志路径。') return zipFileUtil = ZipFileUtil(log_call_back) zipFileUtil.recursiveUnZipFile(selectDir) log_call_back(u'解压完成') # 点击分析日志按钮 def analyticsMethod(self): self.analyticsBtn.setDisabled(True) self.generateDocumentBtn.setDisabled(True) self.doAnalyticsWithGroup() """ 开始分析, 分析步骤: # 1. 先将文件进行分组;利用线程分组策略,每一线程处理多个文件 (!!多进程操作文件的情况下,已去除!!) 2. 先分析给定的关键字,在单个数据文件中进行搜索;利用多进程读取策略读取单个文件(提升速度) 3. 再搜索基础信息,同样在分组数据中进行搜索;(基本信息BaseAttrBean: binderNumber, machineMode, osVersion 等) 4. 组合数据,则将 AnalyticsLogBean 内容与 baseAttr 基本信息进行整合,保存进 CallFailBeanList 中。便于后面生成文档。 """ def doAnalyticsWithGroup(self): selectDir = str(self.selectDirectoryLineEdit.text()) if not selectDir: logMsg = u'您尚未选择日志文件路径! 请先选择日志路径。' self.appendLog(logMsg) self.analyticsBtn.setEnabled(True) self.generateDocumentBtn.setEnabled(True) return allFilePaths = FileUtil.getAllFiles(selectDir) print 'len(allFilePaths): ', len(allFilePaths) supportFilePaths = [] for filePath in allFilePaths: if SupportFiles.hasSupportFile(filePath) and \ not SupportFiles.hasContainsPath(filePath, *self.removeThePathKeys()): supportFilePaths.append(filePath) if not supportFilePaths: return # self.analyticsGroupTotalSize = len([supportFilePaths[i:i+10] for i in xrange(0, len(supportFilePaths), 10)]) print 'len(supportFilePaths): ', len(supportFilePaths) # print 'len(analyticsGroupTotalSize): ', self.analyticsGroupTotalSize # 1. 数组分组,以10个一组 # for i in xrange(0, len(supportFilePaths), 10): # filePathList = supportFilePaths[i:i+10] # # print 'filePathList: ', filePathList # # 2,3 进行分组数据搜索 # # 无线程版 # # self.doSearchFile(filePathList) # threadUtil = ThreadUtil(funcName=self.doSearchFile, filePaths=filePathList) # threadUtil.setDaemon(True) # threadUtil.start() # self.doSearchFile(supportFilePaths) # 去除多线程分组,默认采用多进程分析文件,避免同时使用多线程的情况下使用多进程,否则电脑会被冲爆 threadUtil = ThreadUtil(funcName=self.doSearchFile, filePaths=supportFilePaths) threadUtil.setDaemon(True) threadUtil.start() # 2,3 进行分组数据搜索 def doSearchFile(self, filePaths): if not filePaths: return # 进行搜索前,确认本次搜索关键字 self.analyKeyword = str(self.keywordLineEdit.text()) if str( self.keywordLineEdit.text()).strip() else str("reportCallFailLD =") self.baseAttrKeyword = str("base attribute info") # 搜索关键字信息 for filePath in filePaths: # print "filePath---> : %s --> currentThread: %s" % (_translateUtf8(filePath), threading.currentThread().getName()) self.searchkeywordByMultiProcess(filePath) # 再搜索基本信息 for filePath in filePaths: self.searchBaseAttrByMultiProcess(filePath) # 4. 组合数据,去主线程组装数据 self.emitCombineLogSignal(threading.currentThread().getName()) def combineLogSignal(self, thread_name): pass def emitCombineLogSignal(self, thread_name): self.analyticsBtn.emit(QtCore.SIGNAL('combineLogSignal(QString)'), thread_name) # 4. 组合数据,主线程组装数据(提高优先级) def combineLogWithAttr(self, thread_name): print u'----线程%s已完成工作, 正在使用线程%s开始组装数据-----' % ( thread_name, threading.currentThread().getName()) # self.processedGroupSize += 1 # logMsg = u'一共需要分析:' + str(self.analyticsGroupTotalSize) + u'组,已经分析:' + str(self.processedGroupSize) \ # + u'组,剩余:' + str(self.analyticsGroupTotalSize - self.processedGroupSize) + u'组。' logMsg = u'已分析完文件,正在开始组装数据' self.appendLog(logMsg) print logMsg # if self.analyticsGroupTotalSize == self.processedGroupSize: for analyLog in self.analyticsLogList: analyLogTxt = analyLog.logTxt analyLogFilePath = analyLog.filePath analyLogStr = re.search(r'ReportCallFailLD\s(\{.+})', analyLogTxt).group(1) analyLogJson = self.convertStr2JsonStr(analyLogStr) if not analyLogJson: continue for baseAttr in self.baseAttrList: binderNumber = baseAttr.binderNumber # 组合同一个绑定号数据 if analyLogStr.find( binderNumber) != -1 or analyLogFilePath.find( binderNumber) != -1: callFail = CallFailBean() callFail.binderNumber = binderNumber callFail.machineMode = baseAttr.machineMode callFail.osVersion = baseAttr.osVersion callFail.failTime = analyLog.logTime callFail.voiceNetworkType = analyLogJson[ 'voiceNetWorkTypeLD'] callFail.dialMode = analyLogJson['selfDialModeLD'] callFail.causeCode = analyLogJson['callFailCauseCodeLD'] callFail.vendorCauseCode = analyLogJson[ 'callFailVendorCauseLD'] callFail.logText = analyLogTxt callFail.logFilePath = analyLogFilePath print '----> callFail (bindNumber: %s, machineMode: %s, osVersion: %s, failTime: %s, ' \ 'voiceNetworkType: %s, dailMode: %s, causeCode: %s, vendorCause: %s, logText: %s,' \ ' logFilePath: %s) ' \ % (callFail.binderNumber, callFail.machineMode, callFail.osVersion, callFail.failTime, callFail.voiceNetworkType, callFail.dialMode, callFail.causeCode, callFail.vendorCauseCode, callFail.logText, callFail.logFilePath) self.callFailList.append(callFail) self.analyticsBtn.setEnabled(True) self.generateDocumentBtn.setEnabled(True) logMsg = u'---------- 日志分析完毕 -----------' self.appendLog(logMsg) self.emitTrayMsgSignal(u'日志分析完毕') print '------------- over ---------------' # end if self.analyticsGroupTotalSize == self.processedGroupSize: (此处只做一个end if 语句记号) # 多进程操作文件,搜索输入关键字 def searchkeywordByMultiProcess(self, file_path): searchKeywordMultiProcess = SearchKeywordByMultiProcess( file_path, self, self.searchKeywordCallBack, self.analyKeyword) searchKeywordMultiProcess.createAndDoJobs() # 多进程操作文件,用于状态回调 @staticmethod def searchKeywordCallBack(self, status, file_path, searchedLogJobs): # print '-0---searchKeywordCallBack keyword:%s == lines: %s, status: %s' % (self.analyKeyword, searchedLogList, status) if not self.analyKeyword: return if status == SearchByMultiProcess.STATUS_PROCESSING: logMsg = u'正在分析文件:' + _translateUtf8(file_path) self.dologCallBack(self.emitAppendLogSignal, logMsg) return if not searchedLogJobs: return for searchedLogJob in searchedLogJobs: if not searchedLogJob: continue for searchedLog in searchedLogJob: if not searchedLog: continue self.filterAnalyLog2List(self.analyticsLogList, searchedLog) # 多进程操作文件,搜索基础信息 def searchBaseAttrByMultiProcess(self, file_path): searchBaseAttrMultiProcess = SearchBaseAttrByMultiProcess( file_path, self, self.searchBaseAttrCallBack, self.baseAttrKeyword) searchBaseAttrMultiProcess.createAndDoJobs() # 多进程操作文件,用于状态回调 @staticmethod def searchBaseAttrCallBack(self, status, file_path, searchedBaseAttrJobs): if not self.baseAttrKeyword: return if status == SearchByMultiProcess.STATUS_PROCESSING: return if not searchedBaseAttrJobs: return for searchedBaseAttrJob in searchedBaseAttrJobs: if not searchedBaseAttrJob: continue for searchedBaseAttr in searchedBaseAttrJob: if not searchedBaseAttr: continue self.filterBaseAttr2List(self.baseAttrList, searchedBaseAttr) # 在文件中,搜索关键字,并返回该关键字所在的行数据 def searchWordInFile(self, keyword, file_path, log_call_back=None): if not file_path or not keyword.strip(): return filePath = _translate('', file_path, None) file = QFile(filePath) if not file.open(QtCore.QIODevice.ReadOnly): logMsg = u'无法打开文件:' + _translateUtf8(file_path) self.dologCallBack(log_call_back, logMsg) file.close() return logMsg = u'正在分析文件:' + _translateUtf8(file_path) self.dologCallBack(log_call_back, logMsg) # stream = QtCore.QTextStream(file) # stream.setCodec('UTF-8') # data = stream.readAll() # file.close() # stream.flush() # dataTmp = StringIO.StringIO(data) searchedText = '' # while True: with open(filePath) as f: print 'len(file): ', len(f.readlines()) for line in f: textLine = str(_translateUtf8(line)) if textLine == '': # logMsg = u'已分析完文件:' + _translateUtf8(file_path) # log_call_back(logMsg) # print logMsg break textLineLower = textLine.lower() keywordIndex = textLineLower.find(keyword.lower()) if keywordIndex != -1: searchedText += textLine # release StringIO memory # dataTmp.close() return searchedText # 处理 log_call_back 函数,去除None空回调和返回信息的问题 def dologCallBack(self, log_call_back=None, msg=None): if not log_call_back or not msg: return log_call_back(msg) # 将字符串转换为json 格式 # http://www.runoob.com/python/python-reg-expressions.html def convertStr2JsonStr(self, string): if not string: return None string = string.replace("\'", "\"") strList = re.findall(r'([A-Za-z0-9]+=)', string) for strTmp in strList: strTmp = strTmp.replace("=", "") string = string.replace(strTmp, "\"" + strTmp + "\"") string = string.replace("=", ":") # print '---> string: ', string # print '---> strList: ', strList jsonStr = None try: jsonStr = json.loads(string) except Exception as e: pass # print "json >>> ", jsonStr return jsonStr # 过滤日志信息, 去重后添加进集合 def filterAnalyLog2List(self, analyticsLogList, analyLogBean): with self.filterLogLock: if not analyLogBean: return if len(analyticsLogList) == 0: analyticsLogList.append(analyLogBean) return if not self.hasListContainLog(analyticsLogList, analyLogBean): # print '>>>> append analyticsLogList: %s ---> analyLogBean:%s' % (analyticsLogList, analyLogBean) analyticsLogList.append(analyLogBean) # 集合中是否已经包含了重复LOG def hasListContainLog(self, analyticsLogList, analyLogBean): for analyLog in analyticsLogList: if analyLog.logTxt == analyLogBean.logTxt: return True elif analyLogBean in analyticsLogList: return True return False # 过滤 baseAttr 信息, 去重后添加进集合 def filterBaseAttr2List(self, baseAttrList, baseAttr): with self.filterAttrLock: if not baseAttr: return if len(baseAttrList) == 0: baseAttrList.append(baseAttr) return if not self.hasListContainAttr(baseAttrList, baseAttr): # print '>>>> append baseAttrList: %s ---> baseAttr:%s' % (baseAttrList, baseAttr) baseAttrList.append(baseAttr) # 集合中是否已经包含了重复attr属性 def hasListContainAttr(self, baseAttrList, baseAttr): for baseAttrTmp in baseAttrList: if baseAttrTmp.binderNumber == baseAttr.binderNumber: return True elif baseAttr in baseAttrList: return True return False # 找出有效的基础信息,进行json 转换 def filterBaseAttr2Json(self, searchedBaseAttr): if not searchedBaseAttr: return None baseAttrJson = None baseAttrList = re.findall(r'BaseAttr(\{.+})', searchedBaseAttr) # print '---> baseAttrList: ', baseAttrList if baseAttrList: for baseAttrStr in baseAttrList: baseAttrJson = self.convertStr2JsonStr(baseAttrStr) # print '==> baseAttrJson: ', baseAttrJson if baseAttrJson: return baseAttrJson return baseAttrJson # 点击生成文档按钮 def genDocMethod(self): selectDir = self.selectDirectoryLineEdit.text() if not selectDir: logMsg = u'您尚未选择日志文件路径! 请先选择日志路径。' self.appendLog(logMsg) return if not self.callFailList: logMsg = u'请先分析LOG, 再生成文档!' self.appendLog(logMsg) return # self.doGenDocFile(self.emitAppendLogSignal) threadUtil = ThreadUtil(funcName=self.doGenDocFile, log_call_back=self.emitAppendLogSignal) threadUtil.setDaemon(True) threadUtil.start() def doGenDocFile(self, log_call_back): docTitle = u'# 问题分析' docSecondTitle = u'## 上层分析' docTempleteBinder = u'绑定号: ' docTempleteMachine = u'+ 机型 : ' docTempleteTime = u'+ 时间点: ' docTempleteNetworkType = u'+ 通话类型:' docTempleteDialMode = u'+ 通话方向:' docTempleteCause = u'+ 掉话code: ' docTempleteDetail = u'+ 详情:' print 'callFailList len: ', len(self.callFailList) for callFail in self.callFailList: docFilePath = callFail.logFilePath binderNumber = callFail.binderNumber docFilePathTmp = re.findall(r'([A-Za-z0-9_.]+)', docFilePath) docFilePath.rfind(binderNumber) fileDirPath = '' for fileDirPathTmp in docFilePathTmp: if fileDirPathTmp == binderNumber: fileDirPathIndex = docFilePath.find(binderNumber) fileDirPath = docFilePath[:fileDirPathIndex + len(binderNumber) + 1] break elif fileDirPathTmp.find(binderNumber) != -1: fileDirPathIndex = docFilePath.find(binderNumber) fileDirPath = docFilePath[:fileDirPathIndex] else: fileDirPath = os.path.join( str(self.selectDirectoryLineEdit.text()), binderNumber) FileUtil.mkdirNotExist(fileDirPath) print 'docFilePath: ', fileDirPath fileName = binderNumber + u'_问题分析.txt' filePath = os.path.join(fileDirPath, fileName) hasFileExists = os.path.exists(filePath) docFile = open(filePath, 'a+') docContentBinderNumber = str(docTempleteBinder + binderNumber).encode('utf-8') docContentMachine = str(docTempleteMachine + callFail.machineMode + "\t" + callFail.osVersion).encode('utf-8') docContentTime = str(docTempleteTime + callFail.failTime).encode('utf-8') docContentNetworkType = str(docTempleteNetworkType + callFail.voiceNetworkType).encode( 'utf-8') docContentDialMode = str(docTempleteDialMode + callFail.dialMode).encode('utf-8') docContentCause = str(docTempleteCause + callFail.vendorCauseCode).encode('utf-8') docContentDetail = str(docTempleteDetail + callFail.logText).encode('utf-8') if not hasFileExists: docFile.write('\n' + docTitle + '\n') docFile.write('\n' + docContentBinderNumber + '\n') docFile.write('\n' + docSecondTitle + '\n') docFile.write('\n' + docContentMachine + '\n') else: docFile.write('\n\n\n') docFile.write(docContentTime + '\n') docFile.write(docContentNetworkType + '\n') docFile.write(docContentDialMode + '\n') docFile.write(docContentCause + '\n') docFile.write(docContentDetail + '\n') docFile.flush() docFile.close() logMsg = u'已生成文档:' + _translateUtf8(filePath) log_call_back(logMsg) print logMsg self.release() logMsg = u'---------- 文档生成完毕 -----------' log_call_back(logMsg) self.emitTrayMsgSignal(u'文档生成完毕') # 打开文件夹 def openDirMethod(self): selectDir = self.selectDirectoryLineEdit.text() if not selectDir: logMsg = u'您尚未选择日志文件路径! 请先选择日志路径。' self.appendLog(logMsg) return os.startfile(unicode(selectDir)) # 需要去除包含以下关键字的路径 def removeThePathKeys(self): return ["traces", "bugreport", "diag_logs"] # release def release(self): # 清空本次数据 self.analyKeyword = None self.baseAttrKeyword = None self.analyticsLogList = [] self.baseAttrList = [] self.callFailList = [] # self.analyticsGroupTotalSize = 0 # self.processedGroupSize = 0 # 显示操作日志 def appendLog(self, logTxt): self.LogTextEdit.append(_translateUtf8(logTxt)) # 解决在子线程中刷新UI 的问题。' QWidget::repaint: Recursive repaint detected ' def appendLogSignal(self, logTxt): pass def emitAppendLogSignal(self, logTxt): self.LogTextEdit.emit(QtCore.SIGNAL('appendLogSignal(QString)'), logTxt) # 托盘消息 def showTrayMsg(self, trayMsg): self.tray.show() # show 5 min self.tray.showMsg(trayMsg) def showTrayMsgSignal(self, trayMsg): pass def emitTrayMsgSignal(self, trayMsg): self.tray.emit(QtCore.SIGNAL('showTrayMsgSignal(QString)'), trayMsg) def keyPressEvent(self, event): # 设置 "Ctrl+w" 快捷键,用于关闭 tab if event.key() == QtCore.Qt.Key_W and event.modifiers( ) == QtCore.Qt.ControlModifier: self.close()
def mouseReleaseEvent(self, QMouseEvent): self.moveFlag = False self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) if __name__ == '__main__': os_system = platform.system() # myself_anime_connect = False if os_system == "Darwin": # MAC 要改 工作路徑,此路徑為 Applications 絕對路徑。 os.chdir('/Applications/MyselfAnime.app/Contents/Macos') app = QtWidgets.QApplication(sys.argv) if not connect_myself_anime(): msg = QtWidgets.QMessageBox() msg.setIcon(QtWidgets.QMessageBox.Critical) msg.setText("請確認可以進入 <a href=https://myself-bbs.com/portal.php>MyselfAnime</a> 網站") msg.setWindowTitle("無法取得 MyselfAnime 網站資料!") msg.setWindowIcon(QtGui.QIcon('./image/logo.ico')) msg.exec_() else: # myStyle = MyProxyStyle() # app.setStyle(myStyle) anime = Anime(pid=os.getpid(), os_system=os_system) # config = Config(anime=anime) about = About() # anime.menu.actions()[0].triggered.connect(config.show) anime.show() tray_icon = TrayIcon(anime) app.exec_() kill_pid(os.getpid())
def __init__(self, parent=None): QtGui.QMainWindow.__init__(self, parent) self.setWindowTitle(u'拆分Excel数据') self.setWindowIcon(QtGui.QIcon(resource_path('img/log.png'))) self.centralwidget = QWidget() self.setCentralWidget(self.centralwidget) self.resize(650, 500) self.mainLayout = QtGui.QVBoxLayout() self.mainLayout.setAlignment(QtCore.Qt.AlignTop) self.mainLayout.setContentsMargins(5, 10, 5, 2) # 选取excel文件 self.excelFileLayout = QtGui.QHBoxLayout() self.selectExcelFileBtn = QtGui.QPushButton(u'选择Excel文件') self.selectExcelFileBtn.connect(self.selectExcelFileBtn, QtCore.SIGNAL('clicked()'), self.selectExcelFileMethod) self.selectExcelFileLineEdit = QtGui.QLineEdit() self.selectExcelFileLineEdit.setTextMargins(10, 0, 10, 0) self.selectExcelFileLineEdit.setMinimumHeight(25) self.selectExcelFileLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.excelFileLayout.addWidget(self.selectExcelFileBtn) self.excelFileLayout.addWidget(self.selectExcelFileLineEdit) # excel 行限制条件 directory self.LineConditionLayout = QtGui.QHBoxLayout() self.LineConditionStartLineEdit = QtGui.QLineEdit() self.LineConditionStartLineEdit.setTextMargins(10, 0, 10, 0) self.LineConditionStartLineEdit.setMinimumHeight(25) self.LineConditionStartLineEdit.setPlaceholderText(u'开始行号') self.LineConditionStartLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.LineConditionEndLineEdit = QtGui.QLineEdit() self.LineConditionEndLineEdit.setTextMargins(10, 0, 10, 0) self.LineConditionEndLineEdit.setMinimumHeight(25) self.LineConditionEndLineEdit.setPlaceholderText(u'结束行号') self.LineConditionEndLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.LineConditionIntervalTitle = QtGui.QLabel() self.LineConditionIntervalTitle.setText(u'行拆分间隔条数:') self.LineConditionIntervalTitle.setFont(QtFontUtil().getFont( '微软雅黑', 14)) self.LineConditionIntervalEdit = QtGui.QLineEdit() self.LineConditionIntervalEdit.setTextMargins(10, 0, 10, 0) self.LineConditionIntervalEdit.setMinimumHeight(25) self.LineConditionIntervalEdit.setPlaceholderText('0') self.LineConditionIntervalEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.LineConditionTitle = QtGui.QLabel() self.LineConditionTitle.setText(u' 行数据: ') self.LineConditionTitle.setFont(QtFontUtil().getFont('微软雅黑', 14)) self.LineConditionLabel = QtGui.QLabel() self.LineConditionLabel.setText(u'-->') self.LineConditionLabel.setFont(QtFontUtil().getFont('Monospace', 12)) self.LineConditionLayout.addWidget(self.LineConditionTitle) self.LineConditionLayout.addWidget(self.LineConditionStartLineEdit) self.LineConditionLayout.addWidget(self.LineConditionLabel) self.LineConditionLayout.addWidget(self.LineConditionEndLineEdit) self.LineConditionLayout.addStretch() self.LineConditionLayout.addWidget(self.LineConditionIntervalTitle) self.LineConditionLayout.addWidget(self.LineConditionIntervalEdit) # excel 列限制条件 directory self.ColumnConditionLayout = QtGui.QHBoxLayout() self.ColumnConditionStartLineEdit = QtGui.QLineEdit() self.ColumnConditionStartLineEdit.setTextMargins(10, 0, 10, 0) self.ColumnConditionStartLineEdit.setMinimumHeight(25) self.ColumnConditionStartLineEdit.setPlaceholderText(u'开始列号') self.ColumnConditionStartLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.ColumnConditionEndLineEdit = QtGui.QLineEdit() self.ColumnConditionEndLineEdit.setTextMargins(10, 0, 10, 0) self.ColumnConditionEndLineEdit.setMinimumHeight(25) self.ColumnConditionEndLineEdit.setPlaceholderText(u'结束列号') self.ColumnConditionEndLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.ColumnConditionIntervalTitle = QtGui.QLabel() self.ColumnConditionIntervalTitle.setText(u'列拆分间隔条数:') self.ColumnConditionIntervalTitle.setFont(QtFontUtil().getFont( '微软雅黑', 14)) self.ColumnConditionIntervalEdit = QtGui.QLineEdit() self.ColumnConditionIntervalEdit.setTextMargins(10, 0, 10, 0) self.ColumnConditionIntervalEdit.setMinimumHeight(25) self.ColumnConditionIntervalEdit.setPlaceholderText('0') self.ColumnConditionIntervalEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.ColumnConditionTitle = QtGui.QLabel() self.ColumnConditionTitle.setText(u' 列数据: ') self.ColumnConditionTitle.setFont(QtFontUtil().getFont('微软雅黑', 14)) self.ColumnConditionLabel = QtGui.QLabel() self.ColumnConditionLabel.setText(u'-->') self.ColumnConditionLabel.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.ColumnConditionLayout.addWidget(self.ColumnConditionTitle) self.ColumnConditionLayout.addWidget(self.ColumnConditionStartLineEdit) self.ColumnConditionLayout.addWidget(self.ColumnConditionLabel) self.ColumnConditionLayout.addWidget(self.ColumnConditionEndLineEdit) self.ColumnConditionLayout.addStretch() self.ColumnConditionLayout.addWidget(self.ColumnConditionIntervalTitle) self.ColumnConditionLayout.addWidget(self.ColumnConditionIntervalEdit) # operate buttons self.btnsLayout = QtGui.QHBoxLayout() self.splitExcelBtn = QtGui.QPushButton(u'开始拆分') self.splitExcelBtn.setMinimumHeight(25) self.splitExcelBtn.connect(self.splitExcelBtn, QtCore.SIGNAL('clicked()'), self.splitExcelDataMethod) self.openDirBtn = QtGui.QPushButton(u'打开文件夹') self.openDirBtn.setMinimumHeight(25) self.openDirBtn.connect(self.openDirBtn, QtCore.SIGNAL('clicked()'), self.openDirMethod) self.btnsLayout.addWidget(self.splitExcelBtn) self.btnsLayout.addWidget(self.openDirBtn) # show log self.LogTextEdit = QtGui.QTextEdit() self.LogTextEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.LogTextEdit.setFont(QtFontUtil().getFont('Monospace', 12)) self.LogTextEdit.connect(self.LogTextEdit, QtCore.SIGNAL('appendLogSignal(QString)'), self.appendLog) # addLayout self.mainLayout.addLayout(self.excelFileLayout) self.mainLayout.addSpacing(10) self.mainLayout.addLayout(self.LineConditionLayout) self.mainLayout.addLayout(self.ColumnConditionLayout) self.mainLayout.addSpacing(10) self.mainLayout.addLayout(self.btnsLayout) self.centralwidget.setLayout(self.mainLayout) self.mainLayout.addWidget(self.LogTextEdit) # excelFileDataList 为新生成的每一个新excel 数据集合的集合 self.excelFileDataList = [] # 显示托盘 self.tray = TrayIcon(parent=self, clickEnable=False) self.tray.connect(self.tray, QtCore.SIGNAL('showTrayMsgSignal(QString)'), self.showTrayMsg)
class SplitExcelWindow(QtGui.QMainWindow): def __init__(self, parent=None): QtGui.QMainWindow.__init__(self, parent) self.setWindowTitle(u'拆分Excel数据') self.setWindowIcon(QtGui.QIcon(resource_path('img/log.png'))) self.centralwidget = QWidget() self.setCentralWidget(self.centralwidget) self.resize(650, 500) self.mainLayout = QtGui.QVBoxLayout() self.mainLayout.setAlignment(QtCore.Qt.AlignTop) self.mainLayout.setContentsMargins(5, 10, 5, 2) # 选取excel文件 self.excelFileLayout = QtGui.QHBoxLayout() self.selectExcelFileBtn = QtGui.QPushButton(u'选择Excel文件') self.selectExcelFileBtn.connect(self.selectExcelFileBtn, QtCore.SIGNAL('clicked()'), self.selectExcelFileMethod) self.selectExcelFileLineEdit = QtGui.QLineEdit() self.selectExcelFileLineEdit.setTextMargins(10, 0, 10, 0) self.selectExcelFileLineEdit.setMinimumHeight(25) self.selectExcelFileLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.excelFileLayout.addWidget(self.selectExcelFileBtn) self.excelFileLayout.addWidget(self.selectExcelFileLineEdit) # excel 行限制条件 directory self.LineConditionLayout = QtGui.QHBoxLayout() self.LineConditionStartLineEdit = QtGui.QLineEdit() self.LineConditionStartLineEdit.setTextMargins(10, 0, 10, 0) self.LineConditionStartLineEdit.setMinimumHeight(25) self.LineConditionStartLineEdit.setPlaceholderText(u'开始行号') self.LineConditionStartLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.LineConditionEndLineEdit = QtGui.QLineEdit() self.LineConditionEndLineEdit.setTextMargins(10, 0, 10, 0) self.LineConditionEndLineEdit.setMinimumHeight(25) self.LineConditionEndLineEdit.setPlaceholderText(u'结束行号') self.LineConditionEndLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.LineConditionIntervalTitle = QtGui.QLabel() self.LineConditionIntervalTitle.setText(u'行拆分间隔条数:') self.LineConditionIntervalTitle.setFont(QtFontUtil().getFont( '微软雅黑', 14)) self.LineConditionIntervalEdit = QtGui.QLineEdit() self.LineConditionIntervalEdit.setTextMargins(10, 0, 10, 0) self.LineConditionIntervalEdit.setMinimumHeight(25) self.LineConditionIntervalEdit.setPlaceholderText('0') self.LineConditionIntervalEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.LineConditionTitle = QtGui.QLabel() self.LineConditionTitle.setText(u' 行数据: ') self.LineConditionTitle.setFont(QtFontUtil().getFont('微软雅黑', 14)) self.LineConditionLabel = QtGui.QLabel() self.LineConditionLabel.setText(u'-->') self.LineConditionLabel.setFont(QtFontUtil().getFont('Monospace', 12)) self.LineConditionLayout.addWidget(self.LineConditionTitle) self.LineConditionLayout.addWidget(self.LineConditionStartLineEdit) self.LineConditionLayout.addWidget(self.LineConditionLabel) self.LineConditionLayout.addWidget(self.LineConditionEndLineEdit) self.LineConditionLayout.addStretch() self.LineConditionLayout.addWidget(self.LineConditionIntervalTitle) self.LineConditionLayout.addWidget(self.LineConditionIntervalEdit) # excel 列限制条件 directory self.ColumnConditionLayout = QtGui.QHBoxLayout() self.ColumnConditionStartLineEdit = QtGui.QLineEdit() self.ColumnConditionStartLineEdit.setTextMargins(10, 0, 10, 0) self.ColumnConditionStartLineEdit.setMinimumHeight(25) self.ColumnConditionStartLineEdit.setPlaceholderText(u'开始列号') self.ColumnConditionStartLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.ColumnConditionEndLineEdit = QtGui.QLineEdit() self.ColumnConditionEndLineEdit.setTextMargins(10, 0, 10, 0) self.ColumnConditionEndLineEdit.setMinimumHeight(25) self.ColumnConditionEndLineEdit.setPlaceholderText(u'结束列号') self.ColumnConditionEndLineEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.ColumnConditionIntervalTitle = QtGui.QLabel() self.ColumnConditionIntervalTitle.setText(u'列拆分间隔条数:') self.ColumnConditionIntervalTitle.setFont(QtFontUtil().getFont( '微软雅黑', 14)) self.ColumnConditionIntervalEdit = QtGui.QLineEdit() self.ColumnConditionIntervalEdit.setTextMargins(10, 0, 10, 0) self.ColumnConditionIntervalEdit.setMinimumHeight(25) self.ColumnConditionIntervalEdit.setPlaceholderText('0') self.ColumnConditionIntervalEdit.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.ColumnConditionTitle = QtGui.QLabel() self.ColumnConditionTitle.setText(u' 列数据: ') self.ColumnConditionTitle.setFont(QtFontUtil().getFont('微软雅黑', 14)) self.ColumnConditionLabel = QtGui.QLabel() self.ColumnConditionLabel.setText(u'-->') self.ColumnConditionLabel.setFont(QtFontUtil().getFont( 'Monospace', 12)) self.ColumnConditionLayout.addWidget(self.ColumnConditionTitle) self.ColumnConditionLayout.addWidget(self.ColumnConditionStartLineEdit) self.ColumnConditionLayout.addWidget(self.ColumnConditionLabel) self.ColumnConditionLayout.addWidget(self.ColumnConditionEndLineEdit) self.ColumnConditionLayout.addStretch() self.ColumnConditionLayout.addWidget(self.ColumnConditionIntervalTitle) self.ColumnConditionLayout.addWidget(self.ColumnConditionIntervalEdit) # operate buttons self.btnsLayout = QtGui.QHBoxLayout() self.splitExcelBtn = QtGui.QPushButton(u'开始拆分') self.splitExcelBtn.setMinimumHeight(25) self.splitExcelBtn.connect(self.splitExcelBtn, QtCore.SIGNAL('clicked()'), self.splitExcelDataMethod) self.openDirBtn = QtGui.QPushButton(u'打开文件夹') self.openDirBtn.setMinimumHeight(25) self.openDirBtn.connect(self.openDirBtn, QtCore.SIGNAL('clicked()'), self.openDirMethod) self.btnsLayout.addWidget(self.splitExcelBtn) self.btnsLayout.addWidget(self.openDirBtn) # show log self.LogTextEdit = QtGui.QTextEdit() self.LogTextEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.LogTextEdit.setFont(QtFontUtil().getFont('Monospace', 12)) self.LogTextEdit.connect(self.LogTextEdit, QtCore.SIGNAL('appendLogSignal(QString)'), self.appendLog) # addLayout self.mainLayout.addLayout(self.excelFileLayout) self.mainLayout.addSpacing(10) self.mainLayout.addLayout(self.LineConditionLayout) self.mainLayout.addLayout(self.ColumnConditionLayout) self.mainLayout.addSpacing(10) self.mainLayout.addLayout(self.btnsLayout) self.centralwidget.setLayout(self.mainLayout) self.mainLayout.addWidget(self.LogTextEdit) # excelFileDataList 为新生成的每一个新excel 数据集合的集合 self.excelFileDataList = [] # 显示托盘 self.tray = TrayIcon(parent=self, clickEnable=False) self.tray.connect(self.tray, QtCore.SIGNAL('showTrayMsgSignal(QString)'), self.showTrayMsg) # 选取Excel 文件 def selectExcelFileMethod(self): filePath = unicode( QtGui.QFileDialog.getOpenFileName(None, 'Select excel', self.getLastOpenDir(), 'binder_number(*.xls *.xlsx)')) if not filePath: return self.selectExcelFileLineEdit.setText(filePath) # 获取QFileDialog 上次打开的路径 def getLastOpenDir(self): lastDir = self.selectExcelFileLineEdit.text() if lastDir: return str(lastDir) # open last remember directory lastDir = QSettingsUtil.getLastDir() if not QtCore.QDir(lastDir).exists(): lastDir = 'd://' return str(lastDir) def splitExcelDataMethod(self): # self.doSplitExcelData(log_call_back=self.emitAppendLogSignal) threadUtil = ThreadUtil(funcName=self.doSplitExcelData, log_call_back=self.emitAppendLogSignal) threadUtil.setDaemon(True) threadUtil.start() def doSplitExcelData(self, log_call_back): # 先进行清空操作 self.excelFileDataList = [] filePath = str(self.selectExcelFileLineEdit.text()) if not filePath: log_call_back(u'请先选择Excel文件') log_call_back(u'行拆分和列拆分,是互斥操作,优先行拆分.') startLineStr = str(self.LineConditionStartLineEdit.text()) endLineStr = str(self.LineConditionEndLineEdit.text()) lineIntervalStr = str(self.LineConditionIntervalEdit.text()) startColumnStr = str(self.ColumnConditionStartLineEdit.text()) endColumnStr = str(self.ColumnConditionEndLineEdit.text()) columnIntervalStr = str(self.ColumnConditionIntervalEdit.text()) try: data = xlrd.open_workbook(unicode(filePath)) dataTable = data.sheets()[0] tableRow = dataTable.nrows tableColumn = dataTable.ncols # print 'table row: ', tableRow # print 'table col: ', tableColumn # 配合 xrange ()的方式 excelStartLine = int(startLineStr) - 1 if startLineStr else 0 excelEndLine = int(endLineStr) if endLineStr else tableRow excelLineInterval = int(lineIntervalStr) if lineIntervalStr else -1 excelStartColumn = int(startColumnStr) - 1 if startColumnStr else 0 excelEndColumn = int(endColumnStr) if endColumnStr else tableColumn excelColumnInterval = int( columnIntervalStr) if columnIntervalStr else -1 if excelLineInterval < 0 and excelColumnInterval < 0: log_call_back(u'必须要有一个行或者列拆分间隔!') return if excelStartLine < 0 or excelStartLine > tableRow or excelStartLine > excelEndLine or excelEndLine < 0 \ or excelStartColumn < 0 or excelStartColumn > tableColumn or excelStartColumn > excelEndColumn \ or excelEndColumn < 0: log_call_back(u'参数不合法,请重新输入!') return cellDataList = [] newLineNo = 0 newColumnNo = 0 # 先准备数据 for i in xrange(excelStartLine, excelEndLine): for j in xrange(excelStartColumn, excelEndColumn): # print 'i = %d, j= %d ' % (i, j) # rowDataList = dataTable.row_values(i) # columnDataList = dataTable.col_values(j) # cellData = dataTable.cell(i, j).value # print 'rowDataList: ', rowDataList # print 'columnDataList: ', columnDataList # print 'cellData: ', cellData # print 'i = %d , interval = %d , sp = %d ' % (i, excelLineInterval, i % excelLineInterval) if i != 0 and excelLineInterval > 0 and i % excelLineInterval == 0: newLineNo = 0 elif j != 0 and excelColumnInterval > 0 and j % excelColumnInterval == 0: newColumnNo = 0 else: pass excelData = ExcelData() excelData.lineNo = newLineNo excelData.columnNo = newColumnNo excelData.value = dataTable.cell(i, j).value cellDataList.append(excelData) newColumnNo += 1 newLineNo += 1 newColumnNo = 0 # 拆分数据,到各个excel文件中去 tempList = [] for i in xrange(len(cellDataList)): if tempList and cellDataList[i].lineNo == 0 and cellDataList[ i].columnNo == 0: self.excelFileDataList.append(tempList) tempList = [] tempList.append(cellDataList[i]) if i == len(cellDataList) - 1: self.excelFileDataList.append(tempList) # print 'excelFileDataList: ', self.excelFileDataList # for excelList in self.excelFileDataList: # print '-------------------------------' # for cellData in excelList: # print 'cellData: ', cellData interval = excelLineInterval if excelLineInterval > 0 else \ (excelColumnInterval if excelColumnInterval > 0 else -1) self.genExcelData(self.excelFileDataList, interval, log_call_back) except Exception as e: raise e def genExcelData(self, allExcelDataList, interval, log_call_back): if not allExcelDataList: log_call_back(u'未生成相关数据!') return if interval == -1: log_call_back(u'拆分间隔未设置,不做数据拆分!') return selectExcelFileName = FileUtil.getFilePathWithName( str(self.selectExcelFileLineEdit.text())) for i in xrange(len(allExcelDataList)): excelFileName = str(selectExcelFileName) + str("_") + str( (i + 1) * interval) + str(".xls") # print 'excelFileName: ', excelFileName workbook = xlwt.Workbook(encoding='utf-8') sheetData = workbook.add_sheet("split_data") for cellData in allExcelDataList[i]: # print 'cellData===', cellData sheetData.write(cellData.lineNo, cellData.columnNo, cellData.value) workbook.save(unicode(excelFileName)) log_call_back(u'excel文件拆分完毕!') # 打开文件夹 def openDirMethod(self): excelFilePath = str(self.selectExcelFileLineEdit.text()) if not excelFilePath: logMsg = u'请先选择Excel 文件' self.appendLog(logMsg) return parentPath = unicode(FileUtil.getFileDir(excelFilePath)) # print 'parentPath: %s' % parentPath os.startfile(parentPath) # 显示操作日志 def appendLog(self, logTxt): self.LogTextEdit.append(_translateUtf8(logTxt)) # 解决在子线程中刷新UI 的问题。' QWidget::repaint: Recursive repaint detected ' def appendLogSignal(self, logTxt): pass def emitAppendLogSignal(self, logTxt): self.LogTextEdit.emit(QtCore.SIGNAL('appendLogSignal(QString)'), logTxt) # 托盘消息 def showTrayMsg(self, trayMsg): self.tray.show() # show 5 min self.tray.showMsg(trayMsg) def showTrayMsgSignal(self, trayMsg): pass def emitTrayMsgSignal(self, trayMsg): self.tray.emit(QtCore.SIGNAL('showTrayMsgSignal(QString)'), trayMsg) def keyPressEvent(self, event): # 设置 "Ctrl+w" 快捷键,用于关闭 tab if event.key() == QtCore.Qt.Key_W and event.modifiers( ) == QtCore.Qt.ControlModifier: self.close()
import sys from PyQt5.QtWidgets import QApplication from MainWindow import RelaxWindow from TrayIcon import TrayIcon if __name__ == '__main__': app = QApplication(sys.argv) # 主界面 relaxWindow = RelaxWindow() relaxWindow.show() # 托盘图标 tray_icon = TrayIcon(relaxWindow) tray_icon.show() # 事件驱动 sys.exit(app.exec_())
def __init__(self, config, root, app): # mainwindow 初始化 ====================================================================== super().__init__() self.app = app # 保存传入的初始化数据 Add('config') Space["config"] = config Add('root') Space["root"] = root TrayIcon_img = dir_mix(Space["root"], Space["config"]['cover']) # 用人物预览图作为托盘图标 和 显示图标 with open(dir_mix(Space["root"], Space["config"]['Script']), 'r', encoding='utf-8') as f: Add('Script') Space["Script"] = json.loads(f.read()) # 获取Script的参数 Setting = Space["Script"]["Setting"] # 获取Setting的数据集合 self.ImageSize = Setting["ImageSize"] Add('Change') Space['Change'] = Setting["Change"] try: self.sound_Actions = Space["Script"]["sound"] except: pass Add('Info') Space['Info'] = {} Space['Info']["Play_complete"] = {} # 播放组件是否播放完毕设置 Space['Info']["Move"] = {} Space['Info']["Move"]["Window"] = {} Add('Control_Api') Space['Control_Api'] = {} # 核心控制器类 Add("CoreControl") Space["CoreControl"] = Special_Control.CoreControl() self.setupUi(self) # 创建标准窗口 self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # 设置窗口背景透明 self.setWindowTitle( Space["config"]['Name']) # 把窗口名称设置成config.json中的Name键的值 self.setWindowIcon(QtGui.QIcon(TrayIcon_img)) # 设置Icon self.Cache = {} # 图片缓存字典 # 组件创建 self.label = Special_Label(self) # 创建特殊的Label self.PlayBoard = PlayBoard() # 创建播放器 self.PlayBoard.play.connect(self.graph) self.Find = Find() # 实例化指令查询插件 self.sound = QtMultimedia.QMediaPlayer() # 创立音频播放组件 Space['BGMPlayer'] = QtMultimedia.QMediaPlayer() Space['BGMPlaylist'] = QtMultimedia.QMediaPlaylist() self.User = User() # User组件 (会创建CommonSet,在Setbox前加载) self.Setbox = Setbox(self) self.ChangeWindowFlags(True) # 核心控制器绑定组件 ============================================ Space["CoreControl"].play.connect(self.PlayNew) Space["CoreControl"].sound.connect(self.soundPlay) Space["CoreControl"].ChangeSize.connect(self.ChangeSize) Space["CoreControl"].Move.connect(self.MovePeson) Space["CoreControl"].clean.connect(self.PlayBoard.terminate) Space["CoreControl"].clean.connect(self.Setbox.close) Space["CoreControl"].clean.connect(self.close) Space["CoreControl"].clean.connect(self.app.exit) # Special_Label组件事件绑定 ============================================ self.label.LeftButton_release.connect( self.LeftButton_release) # 绑定鼠标左键点击事件[松开左键] self.label.LeftButton_click.connect( self.LeftButton_click) # 绑定鼠标左键点击事件[松开左键] self.label.RightButton_release.connect( self.RightButton_release) # 绑定鼠标右键点击事件[松开右键] self.label.RightButton_Move.connect(self.RightButton_Move) # 设置事件绑定 =========================== self.Setbox.MovePeson.connect(self.MovePeson) self.Setbox.ResetWindowFlag.connect(self.ChangeWindowFlags) # TrayIcon 组件 ===================================== self.TrayIcon = TrayIcon(self) self.TrayIcon.setIcon(QtGui.QIcon(TrayIcon_img)) self.TrayIcon.show() self.TrayIcon.AddActions("退出", self.close_) self.TrayIcon.AddActions("设置", self.Setbox.show) # 线程启动 self.PlayBoard.start() if Space['CommonSet']["Change"] != None: Space['Change'] = Space['CommonSet']["Change"] self.ChangeSize() # 设置窗口初始大小 # Importer plugin.Importer()
class window_graphics(QtWidgets.QMainWindow, graphics_window): def __init__(self, config, root, app): # mainwindow 初始化 ====================================================================== super().__init__() self.app = app # 保存传入的初始化数据 Add('config') Space["config"] = config Add('root') Space["root"] = root TrayIcon_img = dir_mix(Space["root"], Space["config"]['cover']) # 用人物预览图作为托盘图标 和 显示图标 with open(dir_mix(Space["root"], Space["config"]['Script']), 'r', encoding='utf-8') as f: Add('Script') Space["Script"] = json.loads(f.read()) # 获取Script的参数 Setting = Space["Script"]["Setting"] # 获取Setting的数据集合 self.ImageSize = Setting["ImageSize"] Add('Change') Space['Change'] = Setting["Change"] try: self.sound_Actions = Space["Script"]["sound"] except: pass Add('Info') Space['Info'] = {} Space['Info']["Play_complete"] = {} # 播放组件是否播放完毕设置 Space['Info']["Move"] = {} Space['Info']["Move"]["Window"] = {} Add('Control_Api') Space['Control_Api'] = {} # 核心控制器类 Add("CoreControl") Space["CoreControl"] = Special_Control.CoreControl() self.setupUi(self) # 创建标准窗口 self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # 设置窗口背景透明 self.setWindowTitle( Space["config"]['Name']) # 把窗口名称设置成config.json中的Name键的值 self.setWindowIcon(QtGui.QIcon(TrayIcon_img)) # 设置Icon self.Cache = {} # 图片缓存字典 # 组件创建 self.label = Special_Label(self) # 创建特殊的Label self.PlayBoard = PlayBoard() # 创建播放器 self.PlayBoard.play.connect(self.graph) self.Find = Find() # 实例化指令查询插件 self.sound = QtMultimedia.QMediaPlayer() # 创立音频播放组件 Space['BGMPlayer'] = QtMultimedia.QMediaPlayer() Space['BGMPlaylist'] = QtMultimedia.QMediaPlaylist() self.User = User() # User组件 (会创建CommonSet,在Setbox前加载) self.Setbox = Setbox(self) self.ChangeWindowFlags(True) # 核心控制器绑定组件 ============================================ Space["CoreControl"].play.connect(self.PlayNew) Space["CoreControl"].sound.connect(self.soundPlay) Space["CoreControl"].ChangeSize.connect(self.ChangeSize) Space["CoreControl"].Move.connect(self.MovePeson) Space["CoreControl"].clean.connect(self.PlayBoard.terminate) Space["CoreControl"].clean.connect(self.Setbox.close) Space["CoreControl"].clean.connect(self.close) Space["CoreControl"].clean.connect(self.app.exit) # Special_Label组件事件绑定 ============================================ self.label.LeftButton_release.connect( self.LeftButton_release) # 绑定鼠标左键点击事件[松开左键] self.label.LeftButton_click.connect( self.LeftButton_click) # 绑定鼠标左键点击事件[松开左键] self.label.RightButton_release.connect( self.RightButton_release) # 绑定鼠标右键点击事件[松开右键] self.label.RightButton_Move.connect(self.RightButton_Move) # 设置事件绑定 =========================== self.Setbox.MovePeson.connect(self.MovePeson) self.Setbox.ResetWindowFlag.connect(self.ChangeWindowFlags) # TrayIcon 组件 ===================================== self.TrayIcon = TrayIcon(self) self.TrayIcon.setIcon(QtGui.QIcon(TrayIcon_img)) self.TrayIcon.show() self.TrayIcon.AddActions("退出", self.close_) self.TrayIcon.AddActions("设置", self.Setbox.show) # 线程启动 self.PlayBoard.start() if Space['CommonSet']["Change"] != None: Space['Change'] = Space['CommonSet']["Change"] self.ChangeSize() # 设置窗口初始大小 # Importer plugin.Importer() def ChangeWindowFlags(self, init=True): Flags = 0 for i in Space['WindowFlags']: Flags = Flags | i self.setWindowFlags(QtCore.Qt.WindowType(Flags)) if init: return if not self.isVisible(): self.setVisible(True) def MovePeson(self): self.move(Space['Info']["Move"]["Window"]['PersonX'], Space['Info']["Move"]["Window"]['PersonY']) # 同步移动,拖动窗口时候同时移动人物 def show(self): super().show() Space['Info']["Move"]["Window"]['PersonX'] = self.pos().x() Space['Info']["Move"]["Window"]['PersonY'] = self.pos().y() # 在标准窗口show()后才可以获取窗口的x,y坐标 def PlayNew(self, name): # 播放新的动作 self.PlayBoard.Action = name self.PlayBoard.stop = True def close_(self): Space["CoreControl"].clean.emit() def soundPlay(self, sound_name): path = dir_mix(Space["root"], path_read(self.sound_Actions[sound_name]["path"])) url = QtCore.QUrl.fromLocalFile(path) self.sound.setMedia(QtMultimedia.QMediaContent(url)) self.sound.play() def RightButton_release(self): self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) # 拖动完成必然松开右键才能操作别的,只同步最新拖动后的人物x,y数据,节省资源 Space['Info']["Move"]["Window"]['PersonX'] = self.pos().x() Space['Info']["Move"]["Window"]['PersonY'] = self.pos().y() def RightButton_Move(self, x, y): Space["CoreControl"].stopAllAction.emit() self.move(x, y) self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor)) if self.Setbox.MoveWithPerson: self.Setbox.move(x - 800, y) def LeftButton_click(self, x, y): self.Find.LeftClick(x, y, Space['Change']) def LeftButton_release(self, x, y): self.Find.LeftRelease(x, y, Space['Change']) # self.PlayBoard.stop = True def ChangeSize(self): # Space['Change']:图片缩放系数,>0 [理论是多大都可以,但是你改100看我不 *%*&%] width = int(self.ImageSize[0] * Space['Change']) height = int(self.ImageSize[1] * Space['Change']) self.resize(width, height) self.label.setGeometry(0, 0, width, height) def graph(self, paths): hash_ = hash(paths) if Space["CommonSet"]["Cache"]: if hash_ not in self.Cache.keys(): #print(hash(paths)) self.Cache[hash_] = QtGui.QImage(paths) self.label.setPixmap( QtGui.QPixmap.fromImage(self.Cache[hash_].scaled( self.label.width(), self.label.height()).mirrored( Space['CommonSet']["mirrored"], False))) else: self.Cache.clear() self.label.setPixmap( QtGui.QPixmap.fromImage( QtGui.QImage(paths).scaled( self.label.width(), self.label.height()).mirrored( Space['CommonSet']["mirrored"], False)))
def OnInit(self): self.sysIcon = TrayIcon(self) self.oafRoot.putNotifier("tray", self.sysIcon) return True
def create_tray(self): self.tray = TrayIcon(self) self.tray.setVisible(True) self.app.processEvents()
class ToolTabWidget(QtGui.QTabWidget): def __init__(self, app, args=None, host=None, port=None): QtGui.QTabWidget.__init__(self) self.app = app if args: if args.lang: self.lang = args.lang self.setContentsMargins(0, 0, 0, 0) self.init_variables() # Initialization GUI variables self.VarsGui = DataVarsGui() self.VarsGui.importGui() self.VarsGui.flIniFile() ClientObj = ApiClient(app, self) self.FirstWidget = ClientObj.MainWidget self.PlusWidget = QtGui.QWidget(self) self.tabbar = MyTabBar(self) self.setTabBar(self.tabbar) QtGui.QIcon.setThemeName("Calculate") self.gui_icon = QtGui.QIcon.fromTheme("video-display") self.other_icon = QtGui.QIcon.fromTheme("list-add") if self.other_icon.isNull(): self.other_icon = QtGui.QIcon.fromTheme("preferences-desctop") self.addTab(self.FirstWidget, self.gui_icon, self.new_con_txt) self.addTab(self.PlusWidget, self.other_icon, "") self.last_close_index = -1 self.tabCloseRequested.connect(self.close_tab) self.selected.connect(self.add_tab) self.selected.connect(self.changeWindowTitle) self.setTabsClosable(True) self.tabbar.tabButton(1, QtGui.QTabBar.ButtonPosition.RightSide).hide() if not self.get_size(): # definition of screen resolution prim_screen = self.app.desktop().primaryScreen() d_size = self.app.desktop().screenGeometry(prim_screen).size() # resize main widget if d_size.height() < 768: self.resize(900, 560) else: self.resize(900, 700) self.setMinimumHeight(100) self.setMinimumWidth(500) self.setWindowTitle(self.Name) self.setStyleSheet( """ QTabBar::tab:last { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); border: 2px solid #C4C4C3; border-bottom-color: #C2C7CB; border-top-left-radius: 4px; border-top-right-radius: 4px; padding-left: 3px; margin-left: 3px; margin-bottom: 5px; margin-top: 2px; width: 18px;} QTabBar::tab:last::hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E9E9E9, stop: 0.4 #E5E5E5, stop: 0.5 #E1E1E1, stop: 1.0 #DDDDDD);} """ ) self.setWindowIcon(QtGui.QIcon("/usr/share/pixmaps/calculate-console-offline.png")) self.show() self.app.processEvents() self.connect_dict = {} self.connect_count = 0 if not host or host == "localhost": host = "127.0.0.1" self.FirstWidget.connect_to_localhost(host, port) if self.FirstWidget.ClientObj.client: if host in ["127.0.0.1", "localhost"]: self.localhost_ClientObj = self.FirstWidget.ClientObj if not host in self.connect_dict: self.connect_dict[host] = [port] else: if port: if not port in self.connect_dict[host]: self.connect_dict[host].append(port) self.create_tray() if self.FirstWidget.ClientObj.client: self.tray.set_icon(True) def connect_count_changed(self, host, port, count): if count: if not host in self.connect_dict: self.connect_dict[host] = [port] else: if port: if not port in self.connect_dict[host]: self.connect_dict[host].append(port) else: if host in self.connect_dict: if port in self.connect_dict[host]: self.connect_dict[host].remove(port) if not self.connect_dict[host]: self.connect_dict.pop(host) if self.connect_dict: self.setWindowIcon(QtGui.QIcon("/usr/share/pixmaps/calculate-console-online.png")) if hasattr(self, "tray"): self.tray.set_icon(True) else: self.setWindowIcon(QtGui.QIcon("/usr/share/pixmaps/calculate-console-offline.png")) if hasattr(self, "tray"): self.tray.set_icon(False) def init_variables(self): try: self.Version = self.VarsGui.Get("cl_ver") except: self.Version = "" try: self.Name = self.VarsGui.Get("cl_name") except: self.Name = "Calculate Console" self.new_con_txt = _("New connection") self.sys_update_pid = None def close_tab(self, cur_num=None, hard=False): exit_flag = 0 if cur_num == None: cur_num = self.currentIndex() if cur_num != self.count() - 1: # for delete widget self.setCurrentIndex(cur_num) wgt = self.currentWidget() if wgt == self.FirstWidget and not hard: return exit_flag if wgt._closeEvent(): wgt.close() self.last_close_index = cur_num if cur_num: self.setCurrentIndex(cur_num - 1) else: self.setCurrentIndex(0) self.removeTab(cur_num) exit_flag = 1 if self.count() < 2: self.add_tab() return exit_flag def add_tab(self): if self.currentIndex() == self.count() - 1: # not add if exists clean tab for tab_num in range(self.count() - 1): self.setCurrentIndex(tab_num) if not self.currentWidget().ClientObj.client: return 0 ClientObj = ApiClient(self.app, self) widget = ClientObj.MainWidget widget.cur_window_title = self.Name self.insertTab(self.count() - 1, widget, self.gui_icon, self.new_con_txt) self.setCurrentIndex(self.count() - 2) if self.currentWidget().ClientObj.client: self.tabbar.setTabEnabled(self.count() - 1, True) else: self.tabbar.setTabEnabled(self.count() - 1, False) def rename_tab(self, text=None, ind=None): if not text: text = self.new_con_txt if not ind: ind = self.currentIndex() self.setTabText(ind, text) def changeWindowTitle(self, tab_num): try: text = self.currentWidget().cur_window_title self.setWindowTitle(text) except AttributeError: pass def setWindowTitle(self, title): self.currentWidget().cur_window_title = title super(ToolTabWidget, self).setWindowTitle(title) def create_tray(self): self.tray = TrayIcon(self) self.tray.setVisible(True) self.app.processEvents() def translate(self, lang=None): self.new_con_txt = _("New connection") self.new_con_txt = self.new_con_txt.decode("utf-8") current = self.currentIndex() # not add if exists clean tab for tab_num in range(self.count() - 1): self.setCurrentIndex(tab_num) if not self.currentWidget().ClientObj.client: self.setTabText(tab_num, self.new_con_txt) self.setCurrentIndex(current) if hasattr(self, "tray"): self.tray.translate() def set_localhost(self, ClientObj): self.localhost_ClientObj = ClientObj # if ClientObj: # self.connect_dict[ClientObj.host_name] = \ # [ClientObj, self.currentIndex()] # self.tabbar.tabButton(self.currentIndex(), \ # QtGui.QTabBar.ButtonPosition.RightSide).hide() def find_host(self, host_name, port): ind = self.currentIndex() for i in xrange(self.count() - 1): self.setCurrentIndex(i) wgt = self.currentWidget() if hasattr(wgt, "ClientObj"): ClientObj = wgt.ClientObj if host_name == ClientObj.host_name and port == ClientObj.port and ClientObj.client: self.removeTab(ind) return 1 self.setCurrentIndex(ind) return 0 def closeEvent(self, event): self.cur_pos = self.pos() self.hide() event.ignore() def _closeEvent(self): for tab_num in range(self.count()): if not self.close_tab(0, True): return 1 self.set_size() save_path = os.path.join("/tmp", "calculate-" + pwd.getpwuid(os.getuid()).pw_name) if os.path.isdir(save_path): shutil.rmtree(save_path) self.app.exit() def get_size(self): conf_path = self.VarsGui.Get("cl_gui_config_path") homePath = self.VarsGui.Get("ur_home_path") self.user_config = conf_path.replace("~", homePath) self.config = ConfigParser.ConfigParser() self.config.read(self.user_config) try: size = self.config.get("gui", "size") except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): return False tup_size = map(lambda x: int(x), size.split(",")) self.resize(tup_size[0], tup_size[1]) return True def set_size(self): self.config = ConfigParser.ConfigParser() self.config.read(self.user_config) try: self.config.set("gui", "size", ",".join(map(lambda x: str(x), self.size().toTuple()))) self.config.write(open(self.user_config, "w")) except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): return False def keyPressEvent(self, e): if e.key() == QtCore.Qt.Key_Return: self.currentWidget().keyPressEvent(e) else: QtGui.QTabWidget.keyPressEvent(self, e)