def main(): setStyle() app = QApplication(sys.argv) settings = SettingsWindow() image_output = TestImageOutput(settings) ir_board = ir.IrBoard(image_output) print u"Версия библиотеки инфракрасная ручка ",ir_board.getVersion() win = MainWindow(settings) win.show() tray_menu = QMenu() tray_menu.addAction(QIcon(':/main/restore.png'), u"Восстановить", win.show) tray_menu.addAction(QIcon(':/main/calibrate.png'), u"Калибровка", win.calibrate) tray_menu.addAction(QIcon(':/main/cogwheel.png'), u"Настройка", win.settings_window.show) tray_menu.addSeparator() tray_menu.addAction(QIcon(':/main/close.png'), u"Выход", app.quit) tray = QSystemTrayIcon() tray.setIcon(QIcon(':/main/webcam.png')) tray.setContextMenu(tray_menu) tray.show() return app.exec_()
class DBusTrayMainWindow(QMainWindow): """A sample main window""" def __init__(self): QMainWindow.__init__(self) self.setup_gui() def setup_gui(self): """Sets up a sample gui interface.""" central_widget = QWidget(self) central_widget.setObjectName('central_widget') self.label = QLabel('Hello World') self.input_field = QLineEdit() change_button = QPushButton('Change text') close_button = QPushButton('close') quit_button = QPushButton('quit') central_layout = QVBoxLayout() button_layout = QHBoxLayout() central_layout.addWidget(self.label) central_layout.addWidget(self.input_field) # a separate layout to display buttons horizontal button_layout.addWidget(change_button) button_layout.addWidget(close_button) button_layout.addWidget(quit_button) central_layout.addLayout(button_layout) central_widget.setLayout(central_layout) self.setCentralWidget(central_widget) # create a system tray icon. Uncomment the second form, to have an # icon assigned, otherwise you will only be seeing an empty space in # system tray self.systemtrayicon = QSystemTrayIcon(self) self.systemtrayicon.show() # set a fancy icon self.systemtrayicon.setIcon(QIcon.fromTheme('help-browser')) change_button.clicked.connect(self.change_text) quit_button.clicked.connect(QApplication.instance().quit) close_button.clicked.connect(self.hide) # show main window, if the system tray icon was clicked self.systemtrayicon.activated.connect(self.icon_activated) def icon_activated(self, reason): if reason == QSystemTrayIcon.Trigger: self.setVisible(self.isHidden()) def change_text(self): self.label.setText(self.input_field.text()) def closeEvent(self, evt): # only hide, if the user requests a close evt.ignore() self.hide()
class MainWnd(QMainWindow): def __init__(self, shell, icon): super(MainWnd, self).__init__() self._shell = shell self.icon = icon self.context_menu = None self.tray_icon = None self.myProcess = None if not QSystemTrayIcon.isSystemTrayAvailable(): msg = "I couldn't detect any system tray on this system." _logger.error(msg) QMessageBox.critical(None, "Listen 1", msg) sys.exit(1) self.init_ui() def init_ui(self): self.setWindowIcon(self.icon) self.setWindowTitle('Listen 1') self.create_tray_icon(self.icon) self.tray_icon.show() self.on_start() def on_tray_activated(self, reason=None): _logger.debug("Tray icon activated.") def on_start(self): self.myProcess = MyWorkerThread() self.myProcess.start() QDesktopServices.openUrl('http://localhost:8888/') def on_open(self): if sys.platform.startswith('darwin'): url = '/Applications/Listen 1.app/Contents/MacOS/media/music/' QDesktopServices.openUrl(QUrl.fromLocalFile(url)) else: QDesktopServices.openUrl(QUrl.fromLocalFile('./media/music')) def on_quit(self): if self.myProcess is not None: # graceful shutdown web server tornado.ioloop.IOLoop.instance().stop() self._shell.quit_app() def create_actions(self): """ Creates QAction object for binding event handlers. """ self.start_action = QAction( "&打开 Listen 1", self, triggered=self.on_start) self.open_action = QAction( "&离线音乐文件夹", self, triggered=self.on_open) self.quit_action = QAction( "&退出", self, triggered=self.on_quit) def create_context_menu(self): menu = QMenu(self) menu.addAction(self.start_action) menu.addAction(self.open_action) menu.addAction(self.quit_action) return menu def create_tray_icon(self, icon): self.create_actions() self.context_menu = self.create_context_menu() self.tray_icon = QSystemTrayIcon(self) self.tray_icon.setContextMenu(self.context_menu) self.tray_icon.setIcon(icon) self.tray_icon.activated.connect(self.on_tray_activated)
class ActivityStatus(QMainWindow): """ Main application window, responsible for application lifecycle """ def __init__(self): QMainWindow.__init__(self, None, Qt.FramelessWindowHint) self.__settings = Settings() self.__activityManager = ActivityManager(self.__settings) self.__trayIcon = QSystemTrayIcon(self) self.__managerController = ActivityManagerControl(self, self.__activityManager) self.__appMenu = QMenu(self) self.__closeAction = QAction(self.tr('Close'), self) self.__appIcon = resources.getIcon('pomidor.png') self._configureActions() self._configureMenu() self._setupTrayIcon() self._configureMainWindow() self._setupEventHooks() logging.debug('Application started') def _setupTrayIcon(self): """ Set initial image on tray icon """ self.__trayIcon.setIcon(self.__appIcon) self.__trayIcon.show() self.__trayIcon.activated.connect(self._trayIconClicked) self.__trayIcon.setContextMenu(self.__appMenu) def _configureMainWindow(self): """Configure main window contents""" self.setCentralWidget(self.__managerController) self.setWindowIcon(self.__appIcon) def _setupEventHooks(self): """Connect to event hooks provided by the activity manager""" self.__activityManager.activityStarted += self._hideMainWindow self.__activityManager.workActivityEnded += self._notifyActivityEnding self.__activityManager.breakActivityEnded += self._notifyActivityEnding self.__activityManager.activityTimeChanged += self._showRemainingTime def _configureMenu(self): """Configure application menu, add all actions and separators""" self.__appMenu.addActions(self.__managerController.actionList) self.__appMenu.addSeparator() self.__appMenu.addAction(self.__closeAction) def _configureActions(self): """Configure actions of the main controller""" self.__closeAction.triggered.connect(_closeApplication) def _trayIconClicked(self, reason): """ Process the click on the tray icon @param reason: how the icon was clicked """ logging.debug('Tray icon clicked') if reason == QSystemTrayIcon.Trigger: if self.isVisible(): self._hideMainWindow() else: self._showMainWindw() def closeEvent(self, event): """ Prevent main window from closing by clicking on close button @param event: the event, which controls the operation @type event: QCloseEvent """ event.ignore() self._hideMainWindow() def _hideMainWindow(self, _=''): """Hide main window from the screen""" logging.debug('Main window is hidden') self.setVisible(False) def _showMainWindw(self): """Show main window near-by to the system tray icon""" logging.debug('Main window is shown') self.setVisible(True) trayIconGeometry = self.__trayIcon.geometry() screenGeometry = QApplication.desktop().screenGeometry(trayIconGeometry.topLeft()) self.move(_calculateWindowPosition(screenGeometry, trayIconGeometry, self.width(), self.height())) def _notifyActivityEnding(self): """Invoke activity ending action""" logging.debug('Notifying user about action ending') process = Process(target=_executeAction, args=(self.__settings.endActivityAction,)) process.start() self.__trayIcon.setIcon(self.__appIcon) def _showRemainingTime(self, seconds): """ Show remaining time to the user @param seconds: remaining time @type seconds: int """ if seconds > 60: time = int(seconds / 60) else: time = seconds text = "{0:02d}".format(time) basePixelMap = resources.getPixelMap('pomidor.png') painter = QPainter(basePixelMap) painter.setFont(QFont("PT Sans", 64, QFont.Bold)) painter.setPen(QPen(QColor(0, 0, 0))) painter.drawText(basePixelMap.rect(), Qt.AlignCenter, text) painter.setFont(QFont("PT Sans", 58, QFont.Bold)) painter.setPen(QPen(QColor(240, 240, 240))) painter.drawText(basePixelMap.rect(), Qt.AlignCenter, text) painter.end() self.__trayIcon.setIcon(QIcon(basePixelMap))
class SysTray(QWidget): # instdir = '/'.join(realpath(__file__).split('/')[:-1]) def __init__(self, display, parent=None): super(SysTray, self).__init__(parent) self.m = managerui.uiManager() self.s = searchui.uiSearch(display) self.menuActions() self.trayIconAndMenu() self.trayIcon.show() # def mycloseEvent(self): # if self.manProc: # self.manProc.kill() # if self.seaProc: # self.seaProc.kill() def trayIconAndMenu(self): self.trayMenu = QMenu(self) self.trayMenu.addAction(self.openSearch) self.trayMenu.addAction(self.openManager) self.trayMenu.addSeparator() self.trayMenu.addAction(self.quitAction) self.trayIcon = QSystemTrayIcon(self) self.icon = QIcon(":/res/ooo-base.png") self.trayIcon.setIcon(self.icon) self.trayIcon.setToolTip("Tag Manager Menu") self.trayIcon.setContextMenu(self.trayMenu) def iconActivated(self, reason): pass def menuActions(self): self.openSearch = QAction("S&earch", self, triggered=self.initSearch) self.openManager = QAction("M&anage Files", self, triggered=self.initManager) self.quitAction = QAction("&Quit", self, triggered=qApp.quit) # These halt the system tray icons execution # will have to thread these calls @Slot() def initSearch(self): self.s.show() # self.seaProc = Popen(["python", # self.instdir + "/searchui.py"]) def initManager(self): self.m.show()
class MainWindow(QDialog): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.stopSign = 0 self.ws = 0 self.comment = '' self.clipboard = QApplication.clipboard() self.setWindowTitle(u'勤務表') self.setWindowIcon(QIcon('./img/tray.png')) self.systemTrayIcon = QSystemTrayIcon(self) self.systemTrayIcon.setIcon(QIcon('./img/tray.png')) self.systemTrayIcon.setVisible(True) self.systemTrayIcon.show() self.systemTrayIcon.activated.connect(self.on_systemTrayIcon_activated) self.tableLabel = QLabel('select *.xls file') self.pathText = QLineEdit() self.triggerBtn = QPushButton(u'檢查 / 開始') self.browseBtn = QPushButton(u' 瀏覽 ') self.stopBtn = QPushButton(u'停止') self.table = QTableWidget(26,0,self) self.setUpTable() self.hbox1 = QHBoxLayout() self.hbox2 = QHBoxLayout() self.hbox3 = QHBoxLayout() self.hbox4 = QHBoxLayout() self.hbox1.addWidget(self.pathText) self.hbox1.addWidget(self.browseBtn) self.hbox1.addWidget(self.triggerBtn) self.browseBtn.clicked.connect(self.OpenFile) self.triggerBtn.clicked.connect(self.setupTypeThread) self.stopBtn.clicked.connect(self.threadStop) self.status = QTreeWidget(self) self.status.setHeaderHidden(True) self.hbox2.addWidget(self.status) self.hbox3.addWidget(self.table) self.hbox4.addWidget(self.stopBtn) self.setGeometry(200, 200, 700, 400) self.status.setFixedHeight (80) self.layout = QVBoxLayout() self.layout.addWidget(self.tableLabel) self.layout.addLayout(self.hbox1) self.layout.addLayout(self.hbox2) self.layout.addLayout(self.hbox3) self.layout.addLayout(self.hbox4) self.setLayout(self.layout) self.stopBtn.setEnabled(False) def setUpTable(self): self.table.horizontalHeader().setVisible(False) for i in xrange(0, 26, 1): self.vhfont = QFont('Times', pointSize = 10, weight=QFont.Bold) timePos = i+6 if i == 0: item = QTableWidgetItem(u'[標題]') elif i == 1: item = QTableWidgetItem(u'[設定]') elif 2 < timePos < 24: item = QTableWidgetItem(('{0}~{1}').format(timePos, timePos+1)) else: item = QTableWidgetItem(('{0}~{1}').format(timePos-24, timePos-23)) item.setFont(self.vhfont) item.setTextAlignment(Qt.AlignCenter) self.table.setVerticalHeaderItem(i, item) def on_systemTrayIcon_activated(self, reason): if reason == QSystemTrayIcon.DoubleClick: if self.isHidden(): try: self.typeThread self.threadStop() except: pass self.show() else: self.hide() def setupTypeThread(self): self.clipboard.setText('') det = self.loadDetec() self.ws, vaild = self.checkTableValidation(det, self.table) ws = [] for col in self.ws: ws.append(col[0]) self.addStatus( u' 狀態: 檢查勤務表狀態....', 0) errStat = self.check(ws) if vaild != True and self.table.columnCount()!=0: self.addStatus( vaild, 1) elif self.table.columnCount() ==0: self.addStatus( u' 錯誤: 請載入勤務表', 1) self.typeThread = startType(self.ws) self.typeThread.threadDone.connect(self.showDoneMsg, Qt.QueuedConnection) self.typeThread.toTray.connect(self.toTray, Qt.QueuedConnection) self.typeThread.toCilpboard.connect(self.toCilpboard, Qt.QueuedConnection) self.typeThread.enableButtons.connect(self.enableButtons, Qt.QueuedConnection) self.typeThread.showErrMsg.connect(self.showErrMsg, Qt.QueuedConnection) self.typeThread.addStatus.connect(self.addStatus, Qt.QueuedConnection) if not self.typeThread.isRunning() and vaild == True and errStat == True: self.addStatus( u' 狀態: 檢查通過,開始進行登打作業....', -1) self.browseBtn.setEnabled(False) self.triggerBtn.setEnabled(False) self.stopBtn.setEnabled(True) self.typeThread.start() def toTray(self, state): if state: pass self.hide() self.systemTrayIcon.showMessage(u'輸入中',u'勤務表背景輸入中....\n\n雙擊圖示可暫停程序', msecs=1000000) else: self.show() def toCilpboard(self, text): self.clipboard.setText(text) def threadStop(self): self.typeThread.stopSign = 1 if self.typeThread.isRunning(): self.browseBtn.setEnabled(True) self.triggerBtn.setEnabled(True) self.stopBtn.setEnabled(False) def addStatus(self, text, err): subTreeItem = QTreeWidgetItem(self.status) subTreeItem.setText(0, text) self.activateWindow() if err == 1: font = QFont('Serif', 10, QFont.Bold) subTreeItem.setFont(0, font) subTreeItem.setForeground(0, QBrush(Qt.white)) subTreeItem.setBackground(0, QBrush(QColor(150,0,0))) elif err == 0: font = QFont('Serif', 10, QFont.Bold) subTreeItem.setFont(0, font) subTreeItem.setForeground(0, QBrush(Qt.black)) subTreeItem.setBackground(0, QBrush(Qt.white)) else: font = QFont('Serif', 10, QFont.Bold) subTreeItem.setFont(0, font) subTreeItem.setForeground(0, QBrush(Qt.white)) subTreeItem.setBackground(0, QBrush(QColor(0,150,0))) self.status.scrollToItem(subTreeItem, QAbstractItemView.PositionAtCenter) def showErrMsg(self, title, msg): self.addStatus( u'錯誤: ' + msg, 1) QMessageBox.warning(self, title, msg, QMessageBox.Ok) def showDoneMsg(self): self.addStatus( u'完成: 完成!', 1) QMessageBox.warning(self, u'完成!', u'完成!', QMessageBox.Ok) def enableButtons(self): self.clipboard.setText(self.comment) self.browseBtn.setEnabled(True) self.triggerBtn.setEnabled(True) self.stopBtn.setEnabled(False) self.show() def OpenFile(self): fileName = QFileDialog.getOpenFileName(self, "Open File.", "/home") self.comment = '' ext = fileName[0].split('.')[-1] if ext == 'xls' or ext == 'xlsx': self.pathText.setText(fileName[0]) sheet = open_workbook(fileName[0]).sheets()[0] self.setFixedHeight(550) self.addStatus( u' 狀態: 載入勤務表: [' + fileName[0] + ']', -1) for col in xrange(self.table.columnCount()-1,-1,-1): self.table.removeColumn(col) ws, header, headerNum = self.loadWS(sheet) self.appendTable(header, ws) self.check(ws) self.comment += self.yieldcomment(sheet) self.ws = ws else: self.showErrMsg(u'錯誤',u'選取檔案不是EXCEL檔') self.ws = 0 def checkTableValidation(self, detCol, table): # .[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ws = [[], [], [], [], [], [], [], [], [], []] errStat = True if len(detCol) == 0 or (0 in detCol): errStat = u' 狀態: 勤務表標頭錯誤,點選 [ --請選擇-- ] 選取有效標頭' for i in xrange(len(detCol)-1): if sorted(detCol)[i] == sorted(detCol)[i+1]: errStat = u' 狀態: 勤務表標頭重複' print detCol for c in xrange(table.columnCount()): col = [] colNum = detCol[c] for r in xrange(2, 26, 1): col.append(table.item(r,c).text()) ws[colNum-1].append(col) for i in xrange(len(ws)): if len(ws[i]) == 0: ws[i].append(['','','','','','','','','','','','','','','','','','','','','','','','']) return (ws), errStat def loadWS(self, sheet): header, headerNum, ws= [],[],[] for c in xrange(3, 26 ,1): title = (sheet.cell_value(3, c)) if len(title) != 0 and len(header) <6: header.append(title) col = [] for m in xrange(7, 31, 1): try: col.append(str(sheet.cell_value(m, c)).strip('()').replace('.0', '').replace('.', ',')) except: col.append(u'error') ws.append(col) return ws, header, headerNum def appendTable(self, header, ws): try: font = QFont('TypeWriter', pointSize = 10, weight=QFont.Bold) for text in header: self.table.insertColumn(0) for c in xrange(len(header)): det = self.determine(header[c]) item = QTableWidgetItem(header[c]) if det == 0: item.setBackground(QBrush(QColor('#FF8D00'))) else: item.setBackground(QBrush(QColor('#005588'))) item.setFont(font) item.setTextAlignment(Qt.AlignCenter) self.table.setItem(0, c, item) nComboBox = self.newCombo() nComboBox.setCurrentIndex(det) self.table.setCellWidget(1, c, (nComboBox)) for r in xrange(2,26,1): item = QTableWidgetItem(ws[c][r-2]) item.setFont(font) item.setTextAlignment(Qt.AlignCenter) self.table.setItem(r, c, item) self.addStatus( u' 狀態: 勤務表預覽成功', -1) return 0 except: self.addStatus( u' 狀態: 勤務表預覽失敗', 1) return 'error' def loadDetec(self): det = [] for col in xrange(self.table.columnCount()): det.append( self.table.cellWidget(1, col).currentIndex()) return det def newCombo(self): taskList = [u'--請選擇--', u'值班', u'救護勤務', u'備勤', u'待命服勤', u'水源查察', u'消防查察', u'宣導勤務', u'訓(演)練', u'專案勤務', u'南山救護站'] nComboBox = QComboBox() nComboBox.addItems(taskList) for i in xrange(len(taskList)): if i == 0: nComboBox.setItemData(i, QColor('#550000'), Qt.BackgroundColorRole) nComboBox.setItemData(i, Qt.AlignCenter, Qt.TextAlignmentRole) nComboBox.setStyleSheet("text-align: right; font: bold 13px;") return nComboBox def setTableErr(self, row, state): if state == 'illegal' : color = '#CC0033' elif state == 'repeated' : color = '#FF8D00' elif state == 'legal' : color = '#201F1F' for col in xrange(self.table.columnCount()): self.table.item(row,col).setBackground(QBrush(QColor(color))) def check(self, ws): errStat = True for m in xrange(2,26): self.setTableErr(m, 'legal') for i in xrange(24): ary = [] for j in xrange(len(ws)): for each in ws[j][i].replace(' ', '').split(','): try: if each == "A": ary.append(-1) elif each == '' : pass else: each == ary.append(int(each)) except: errStat = False timePos = i+8 rptErrMSG = u" 錯誤: 於 {0} ~ {1} 時 數字: {2} --不合法, 請修正" self.setTableErr(i+2, 'illegal') print timePos if timePos < 23: print 'a' self.addStatus(rptErrMSG.format(timePos, timePos+1, each), 1) else: self.addStatus(rptErrMSG.format(timePos-24, timePos-23, each), 1) ary = sorted(ary) for idx in xrange(len(ary)-1): if ary[idx] == ary[idx+1]: errStat = False timePos = i+8 rptErrMSG = u" 錯誤: 於 {0} ~ {1} 時 數字: {2} --番號重複, 請修正" self.setTableErr(i+2, 'repeated') if timePos < 23: self.addStatus(rptErrMSG.format(timePos, timePos+1, str(ary[idx]).replace('-1', 'A')), 1) else: self.addStatus(rptErrMSG.format(timePos-24, timePos-23, str(ary[idx]).replace('-1', 'A')), 1) return errStat def determine(self, title): cmpfactor = 0 smp = [u'值班', u'救護分隊務', u'備', u'待命服', u'水源', u'消防', u'宣導', u'訓演練', u'專案其它', u'南山站'] for index, each in zip(xrange(len(smp)),smp): for text in each: for elem in title: cmpfactor += ( elem == text ) if cmpfactor > 0: return index+1 return 0 def yieldcomment(self, sheet): comment0, comment1 = '', '' # for i,j in [[24,27], [27,27], [29,27], [29,35]]: # try: # comment0 += (smart_str(sheet.cell_value(i, j)) + '\n') # except: # pass for i,j in [[31,3], [32,3], [33,3], [34,3]]: try: comment1 += (sheet.cell_value(i, j) + '\n') except: pass return comment1
class serverManagerWindow(QMainWindow): def __init__(self, _app, parent=None): QMainWindow.__init__(self, parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.iTrayIcon = QSystemTrayIcon() self.iTrayIcon.setIcon(QIcon("drapes.ico")) self.iTrayIcon.show() self.iTrayIcon.setToolTip("One world, One dream!") self.iTrayIcon.activated.connect(self.iconActivated) self.quitAction = QAction("&Quit", self, triggered=QApplication.quit) self.trayIconMenu = QMenu(self) self.trayIconMenu.addAction(self.quitAction) self.iTrayIcon.setContextMenu(self.trayIconMenu) #选择MYSQL保留用户信息 QObject.connect(self.ui.mysql_groupBox, SIGNAL("clicked()"), self, SLOT("choiceSql()")) #选择XT文件留用户信息 QObject.connect(self.ui.text_groupBox, SIGNAL("clicked()"), self, SLOT("choiceTxt()")) #选择XML文件留用户信息 QObject.connect(self.ui.xml_groupBox, SIGNAL("clicked()"), self, SLOT("choiceXml()")) #节面显示英文 QObject.connect(self.ui.actionEnglish, SIGNAL("activated()"), self, SLOT("loadEnglish()")) #节面显示中文 QObject.connect(self.ui.actionChinese, SIGNAL("activated()"), self, SLOT("loadChinese()")) #加载配置文件 QObject.connect(self.ui.actionLoad_Config, SIGNAL("activated()"), self, SLOT("loadConfig()")) #保留配置文件 QObject.connect(self.ui.actionSave_Config, SIGNAL("activated()"), self, SLOT("saveConfig()")) #about操作 QObject.connect(self.ui.actionAbout, SIGNAL("activated()"), self, SLOT("about()")) #选择XML文件 QObject.connect(self.ui.openXml_pushButton, SIGNAL("clicked()"), self, SLOT("xml_open()")) #选择TXT文件 QObject.connect(self.ui.openText_pushButton, SIGNAL("clicked()"), self, SLOT("txt_open()")) #启动服务 QObject.connect(self.ui.startServer_pushButton, SIGNAL("clicked()"), self, SLOT("startServer()")) #停止服务 QObject.connect(self.ui.stopServer_pushButton, SIGNAL("clicked()"), self, SLOT("stopServer()")) self.ui.sqlTypeComboBox.activated[str].connect(self.sqlServer) QObject.connect(self.ui.openSqlpushButton, SIGNAL("clicked()"), self, SLOT("database_open()")) #界面语言 self.translator = None self.app = _app self.translator = QTranslator() self.connect = None self.users = None self.ControlMediaPath = None self.ControlMedia = None self.delUsrInfo = None self.userModel = QStandardItemModel() self.userModel.setHorizontalHeaderItem(0, QStandardItem("user")) self.userModel.setHorizontalHeaderItem(1, QStandardItem("friends")) self.userModel.setVerticalHeaderItem(0, QStandardItem("1")) self.userModel.setVerticalHeaderItem(1, QStandardItem("2")) self.userModel.setVerticalHeaderItem(2, QStandardItem("3")) self.loginUserModel = QStandardItemModel() self.loginUserModel.setHorizontalHeaderItem(0, QStandardItem("user")) self.loginUserModel.setHorizontalHeaderItem(1, QStandardItem("instance")) self.messageModel = QStandardItemModel() self.messageModel.setHorizontalHeaderItem(0, QStandardItem("message")) #读取系统配置文件 self.readConfig(configFile) self.statusBar().showMessage("server is stopped!") self.ui.userInfo_tableView.setModel(self.userModel) self.createUserInfoContextMenu() self.ui.loginUsers_tableView.setModel(self.loginUserModel) self.createloginUsersContextMenu() self.ui.messageLogs_listView.setModel(self.messageModel) #界面多语处理 self.updateLanguage(self.language) self.center() def iconActivated(self, reason): if reason == QSystemTrayIcon.DoubleClick: self.show() print "iconActivated" def closeEvent(self, event): event.ignore() self.hide() print "closeEvent" # def changeEvent(self,event): # if (event.type() == QEvent.WindowStateChange) and (self.isMinimized()): # QTimer.singleShot(100, self, SLOT("close")) # # print "changeEvent" def sqlServer(self, index): if index == "MySQL": self.ui.openSqlpushButton.setDisabled(True) self.ui.userLineEdit.setEnabled(True) self.ui.passwordlineEdit.setEnabled(True) if index == "Sqlite": self.ui.openSqlpushButton.setEnabled(True) self.ui.userLineEdit.setDisabled(True) self.ui.passwordlineEdit.setDisabled(True) def center(self): screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def createUserInfoContextMenu(self): '''添加用户信息快捷菜单''' #pylint: disable=W0201 self.addUserAct = QAction(self) # self.addUserAct.setText("add User") self.delUserAct = QAction(self) # self.delUserAct.setText("del User") self.undoDelUserAct = QAction(self) # self.undoDelUserAct.setText("undo del User") self.saveDataRowAct = QAction(self) # self.saveDataRowAct.setText("save Data") self.ui.userInfo_tableView.addAction(self.addUserAct) self.ui.userInfo_tableView.addAction(self.delUserAct) self.ui.userInfo_tableView.addAction(self.undoDelUserAct) self.ui.userInfo_tableView.addAction(self.saveDataRowAct) QObject.connect(self.addUserAct, SIGNAL("activated()"), self, SLOT("userInfoAddRow()")) QObject.connect(self.delUserAct, SIGNAL("activated()"), self, SLOT("userInfoDelRow()")) QObject.connect(self.undoDelUserAct, SIGNAL("activated()"), self, SLOT("userInfoUndoDelRow()")) QObject.connect(self.saveDataRowAct, SIGNAL("activated()"), self, SLOT("userInfoSaveData()")) self.ui.userInfo_tableView.setContextMenuPolicy(Qt.ActionsContextMenu) def userInfoAddRow(self): '''添加一条用户数据''' # self.userModel.appendRow(QStandardItem("")) index = self.ui.userInfo_tableView.selectionModel().currentIndex() model = self.ui.userInfo_tableView.model() if not model.insertRow(index.row() + 1, index.parent()): return for column in range(model.columnCount(index.parent())): child = model.index(index.row() + 1, column, index.parent()) model.setData(child, "[No data]", Qt.EditRole) uiDebug("userInfoAddRow") def userInfoDelRow(self): '''删除数据,且保留此次删除的数据''' model = self.ui.userInfo_tableView.model() index = self.ui.userInfo_tableView.selectionModel().currentIndex() user = model.item(index.row(), 0).index().data() friendlist = model.item(index.row(), 1).index().data() self.delUsrInfo = [index.row(), user, friendlist] # print self.delUsrInfo try: model.removeRow(index.row(), index.parent()) self.users.deleteUser(user) self.users.userDataSave() #pylint: disable=W0702 except: pass uiDebug("userInfoDelRow") def userInfoUndoDelRow(self): '''恢复前次删除的数据''' if self.delUsrInfo != None: model = self.ui.userInfo_tableView.model() if not model.insertRow(self.delUsrInfo[0]): return user = self.delUsrInfo[1] friendlist = self.delUsrInfo[2] self.userModel.setItem(self.delUsrInfo[0], 0, QStandardItem(user)) self.userModel.setItem(self.delUsrInfo[0], 1, QStandardItem(friendlist)) if user != "[No data]": self.users.addUser(user, "admin") if friendlist != "[No data]": for friend in friendlist.split(","): self.users.addUserFriend(user, friend) self.users.userDataSave() self.delUsrInfo = None uiDebug("userInfoUndoDelRow") def userInfoSaveData(self): '''保留用户数据''' if self.users: model = self.ui.userInfo_tableView.model() index = self.ui.userInfo_tableView.selectionModel().currentIndex() for row in range(model.rowCount(index.parent())): user = model.item(row, 0).index().data() friendlist = model.item(row, 1).index().data() if user != "[No data]": self.users.addUser(user, "admin") if friendlist != "[No data]": for friend in friendlist.split(","): if friend != '': self.users.addUserFriend(user, friend) self.users.userDataSave() self.clearUserInfo() self.showUserinfo() uiDebug("userInfoSaveData") def showConfig(self): '''显示配置''' # print self.Config.getControlMedia() # print self.Config.getControlMediaPath() # print self.ControlMedia # print self.ControlMediaPath self.ui.information_textBrowser.setText("Control Media: " + self.ControlMedia) self.ui.information_textBrowser.append("Control Media path: " + self.ControlMediaPath) def showUserinfo(self): '''显示用户信息''' userlist = self.users.getUsers() print "showUserinfo " print userlist row = 0 for user in userlist: friends = userlist[user] self.userModel.setItem(row, 0, QStandardItem(user)) self.userModel.setItem(row, 1, QStandardItem(friends)) row = row + 1 #pylint: disable=W0201 self.delUsrInfo = None def clearUserInfo(self): '''清除用户信息''' self.userModel.clear() self.delUsrInfo = None def userConfig(self): self.showConfig() if self.users != None: del self.users #服务器配置 if self.ControlMedia == mediaValue[txt]: #txt文件保留用户信息 self.users = txtUserControl(self.ControlMediaPath) self.ui.text_groupBox.setChecked(True) self.ui.text_lineEdit.setText(self.ControlMediaPath) elif self.ControlMedia == mediaValue[xml]: #xml文件保留用户信息 self.users = xmlUserControl(self.ControlMediaPath) self.ui.xml_groupBox.setChecked(True) self.ui.xml_lineEdit.setText(self.ControlMediaPath) elif self.ControlMedia == mediaValue[mysql]: #mysql数据库保留用户信息 self.ui.mysql_groupBox.setChecked(True) self.ui.ServerLineEdit.setText(self.ControlMediaPath) self.ui.sqlTypeComboBox.setCurrentIndex(0) # print "mysql" self.sqlServer(mysql) elif self.ControlMedia == mediaValue[sqlite]: self.ui.mysql_groupBox.setChecked(True) self.ui.ServerLineEdit.setText(self.ControlMediaPath) self.ui.sqlTypeComboBox.setCurrentIndex(1) self.users = sqliteUserControl(self.ControlMediaPath) self.sqlServer(sqlite) # print "sqlite" #用户数据初始化 try: self.users.userDataInit() # self.showUserinfo() #pylint: disable=W0702 except: self.users = None if self.users != None: self.clearUserInfo() self.showUserinfo() def readConfig(self, _file): '''读取服务器端配置文件''' #pylint: disable=W0201 self.Config = serverConfig(_file) self.ControlMedia = self.Config.getControlMedia() self.ControlMediaPath = self.Config.getControlMediaPath() self.language = self.Config.getLanguage() self.userConfig() uiDebug("readConfig") def startServer(self): '''#启动服务''' self.ui.startServer_pushButton.setEnabled(False) self.ui.stopServer_pushButton.setEnabled(True) self.connect = server_twisted.serverMain(8002, self.users) self.saveConfig() # self.readConfig(configFile) self.userConfig() self.ui.mysql_groupBox.setDisabled(True) self.ui.text_groupBox.setDisabled(True) self.ui.xml_groupBox.setDisabled(True) self.statusBar().showMessage("server is starting!") if self.users != None: self.clearUserInfo() self.showUserinfo() uiDebug("startServer") def stopServer(self): ''' #停止服务''' if self.connect != None: self.ui.startServer_pushButton.setEnabled(True) self.ui.stopServer_pushButton.setEnabled(False) self.ui.mysql_groupBox.setDisabled(False) self.ui.text_groupBox.setDisabled(False) self.ui.xml_groupBox.setDisabled(False) #pylint: disable=E1101 reactor.disconnectAll() # self.clearUserInfo() self.statusBar().showMessage("server is stopped!") uiDebug("stopServer") def loadChinese(self): '''加载中文''' self.updateLanguage(Chinese) def loadEnglish(self): '''加载英文''' self.updateLanguage(English) def updateLanguage(self, language): '''设置界面语言''' if self.translator != None: self.app.removeTranslator(self.translator) if language == Chinese: #中文处理 self.translator.load(chineseLanguageFile) self.app.installTranslator(self.translator) self.Config.setLanguage(Chinese) elif language == English: #英文处理 self.Config.setLanguage(English) else: pass #更新界面 self.retranslateUi() #保留配置 self.Config.saveServerConfig() def txt_open(self): self.fileOpen(self.ui.text_lineEdit, txt) def xml_open(self): self.fileOpen(self.ui.xml_lineEdit, xml) def database_open(self): self.fileOpen(self.ui.ServerLineEdit, mysql) def fileOpen(self, lineEdit, filters): openFile = QFileDialog.getOpenFileName(self, "Find Files", QDir.currentPath(), filters="*." + filters) uiDebug(openFile) if openFile != None : lineEdit.setText(openFile[0]) self.setUserConfig() self.showConfig() def choiceSql(self): uiDebug("choiceMysql") self.ui.text_groupBox.setChecked(False) self.ui.xml_groupBox.setChecked(False) if self.ui.sqlTypeComboBox.currentText() == mysql: self.ui.openSqlpushButton.setDisabled(True) self.ui.userLineEdit.setEnabled(True) self.ui.passwordlineEdit.setEnabled(True) if self.ui.sqlTypeComboBox.currentText() == sqlite: self.ui.openSqlpushButton.setEnabled(True) self.ui.userLineEdit.setDisabled(True) self.ui.passwordlineEdit.setDisabled(True) def choiceTxt(self): uiDebug("choiceTxt") self.ui.mysql_groupBox.setChecked(False) self.ui.xml_groupBox.setChecked(False) def choiceXml(self): uiDebug("choiceXml") self.ui.mysql_groupBox.setChecked(False) self.ui.text_groupBox.setChecked(False) def setUserConfig(self): '''保留用户配置''' if self.ui.xml_groupBox.isChecked() == True: if self.ui.xml_lineEdit.text() != "": self.ControlMedia = xml self.ControlMediaPath = self.ui.xml_lineEdit.text() uiDebug("setUserConfig xml: " + xml) if self.ui.text_groupBox.isChecked() == True: if self.ui.text_lineEdit.text() != "": self.ControlMedia = txt self.ControlMediaPath = self.ui.text_lineEdit.text() uiDebug("setUserConfig txt: " + txt) if self.ui.mysql_groupBox.isChecked() == True: if self.ui.sqlTypeComboBox.currentText() == mysql: self.ControlMedia = mysql uiDebug("setUserConfig mysql: " + mysql) if self.ui.sqlTypeComboBox.currentText() == sqlite: self.ControlMedia = sqlite uiDebug("setUserConfig sqlite: " + sqlite) self.ControlMediaPath = self.ui.ServerLineEdit.text() self.Config.setContrlMedia(self.ControlMedia) self.Config.setControlMediaPath(self.ControlMediaPath) self.userConfig() def createloginUsersContextMenu(self): '''添加登陆用户快捷菜单''' #pylint: disable=W0201 self.killUserAct = QAction(self) # self.killUserAct.setText("kill user") self.messageUserAct = QAction(self) # self.messageUserAct.setText("message user") self.ui.loginUsers_tableView.addAction(self.killUserAct) self.ui.loginUsers_tableView.addAction(self.messageUserAct) QObject.connect(self.killUserAct, SIGNAL("activated()"), self, SLOT("killUser()")) QObject.connect(self.messageUserAct, SIGNAL("activated()"), self, SLOT("messageUser()")) self.ui.loginUsers_tableView.setContextMenuPolicy(Qt.ActionsContextMenu) def killUser(self): '''踢出一个用户''' try: index = self.ui.loginUsers_tableView.selectionModel().currentIndex() model = self.ui.loginUsers_tableView.model() user = model.item(index.row(), 0).index().data() self.connect.killUser(user) #pylint: disable=W0702 except: pass # model.removeRow(index.row(), index.parent()) uiDebug("killUser") def messageUser(self): '''发送消息给用户''' uiDebug("messageUser") def addUsers(self, user, instance): '''添加一条登陆用户数据''' index = self.ui.loginUsers_tableView.selectionModel().currentIndex() model = self.ui.loginUsers_tableView.model() row = model.rowCount(index.parent()) model.setItem(row, 0, QStandardItem(user)) model.setItem(row, 1, QStandardItem(str(instance))) uiDebug("loginUser") def removeUser(self, user): '''删除一条登陆用户数据''' index = self.ui.loginUsers_tableView.selectionModel().currentIndex() model = self.ui.loginUsers_tableView.model() maxRow = model.rowCount(index.parent()) # print user for row in range(maxRow): # print row # print model.item(row, 0).index().data() # print type(model.item(row, 0).index().data()) if user == model.item(row, 0).index().data(): model.removeRow(row, index.parent()) uiDebug("logoutUser") def refreshReceMessage(self, message): '''添加接收信息''' model = self.ui.messageLogs_listView.model() # model.setItem(model.rowCount(),QStandardItem(message)) model.appendRow(QStandardItem(message)) uiDebug("refreshReceMessage") def refreshSendMessage(self, message): '''添加发送信息''' model = self.ui.messageLogs_listView.model() # model.setItem(model.rowCount(),QStandardItem(message)) model.appendRow(QStandardItem(message)) uiDebug("refreshSendMessage") def retranslateUi(self): self.addUserAct.setText(QApplication.translate("MainWindow", "add User", None, QApplication.UnicodeUTF8)) self.delUserAct.setText(QApplication.translate("MainWindow", "del User", None, QApplication.UnicodeUTF8)) self.undoDelUserAct.setText(QApplication.translate("MainWindow", "undo del User", None, QApplication.UnicodeUTF8)) self.saveDataRowAct.setText(QApplication.translate("MainWindow", "save Data", None, QApplication.UnicodeUTF8)) self.killUserAct.setText(QApplication.translate("MainWindow", "kill User", None, QApplication.UnicodeUTF8)) self.messageUserAct.setText(QApplication.translate("MainWindow", "message User", None, QApplication.UnicodeUTF8)) self.quitAction.setText(QApplication.translate("MainWindow", "Quit", None, QApplication.UnicodeUTF8)) self.iTrayIcon.setToolTip(QApplication.translate("MainWindow", "One world, One dream!", None, QApplication.UnicodeUTF8)) self.ui.retranslateUi(self) def loadConfig(self): '''加载配置文件''' configfile = QFileDialog.getOpenFileName(self, "Load Config File", QDir.currentPath(), filter="*.cfg") uiDebug(configfile) if configfile != None : self.readConfig(configfile) self.stopServer() self.startServer() self.showConfig() uiDebug("loadConfig") def saveConfig(self): '''保留配置文件''' self.setUserConfig() self.Config.saveServerConfig() uiDebug("saveConfig") def about(self): '''about''' aboutInfo = '''<HTML> <p>xdIm ver 0.2.0</p> <p>xdIm program is a software program by xd.</p> <p>Copy Right : "(C) 2008-2010 Programmers and Coders Everywhere"</p> <p><a href="http://www.xdIm.org/">http://www.xdIm.org</a></p> </HTML>"''' tranAboutInfo = QApplication.translate("MainWindow", aboutInfo, None, QApplication.UnicodeUTF8) QMessageBox.information(self, "xdIm information", tranAboutInfo) uiDebug("about")
class SyncWindow(QMainWindow): """ Application main window. This class is meant to handle every widget needed by the application, as well as other needed global objects and behavior. """ failedLogIn = Signal() syncStarted = Signal() loginRequested = Signal(( str, str, )) statusChanged = Signal(( str, str, int, )) def __init__(self, parent=None): super(SyncWindow, self).__init__(parent) # Sets up several UI aspects self.tray = QSystemTrayIcon(self) self.tray.setIcon(QIcon(QPixmap(':/resources/icon.png'))) self.tray.show() self.setStyleSheet('SyncWindow {background: white}') self.setWindowTitle('IQBox') self.setWindowIcon(QIcon(QPixmap(':/resources/logobar.png'))) self.statusBar().setFont(View.labelsFont()) self.syncThread = None # Initializes the window with a `LoginView` widget. self.loginView() def loginView(self): """ Initializes a `LoginView` object and sets it up as the main window's central widget. """ login = LoginView() login.login.connect(self.onLogin) self.failedLogIn.connect(login.onFailedLogIn) self.setCentralWidget(login) self.setFixedSize(login.size()) self.statusBar().hide() def syncView(self): """ Initializes a `SyncView` object and sets it up as the main window's central widget. """ syncview = SyncView() self.setCentralWidget(syncview) self.setFixedSize(syncview.size()) self.statusBar().show() self.statusChanged.connect(syncview.status.setMessage) syncview.sync.connect(self.onSync) @Slot(str, str, str, bool) def onLogin(self, host, username, passwd, ssl): """ Slot. Triggers a log in request to the server. :param host: Indicates the hostname of the FTP server :param username: Username to log in into the FTP server :param passwd: Password to log in into the FTP server :param ssl: Indicates whether the FTP needs SSL support """ self.sync = Sync(host, ssl) self.syncStarted.connect(self.sync.initQueue) self.sync.server.downloadProgress.connect(self.onDownloadProgress) self.sync.server.uploadProgress.connect(self.onUploadProgress) self.sync.server.fileEvent.connect(self.onFileEvent) self.sync.server.badFilenameFound.connect(self.badNameWarning) self.sync.server.loginCompleted.connect(self.onLoginCompleted) self.sync.server.fileEventCompleted.connect(self.onFileEventCompleted) self.sync.server.ioError.connect(self.onIOError) # Added by Si self.sync.server.textStatus.connect(self.setStatus) self.sync.statusChanged.connect(self.setStatus) self.loginRequested.connect(self.sync.server.onLogin) self.syncThread = QThread() self.sync.moveToThread(self.syncThread) self.syncThread.start() QApplication.instance().lastWindowClosed.connect(self.syncThread.quit) self.loginRequested.emit(username, passwd) @Slot(bool, str) def onLoginCompleted(self, ok, msg): if not ok: self.showMessageBox(msg) self.failedLogIn.emit() else: self.syncView() @Slot() def onFileEventCompleted(self): # Workaround because there's an exception # when there's a file IO error # Ideally it should be managed elsewhere # But I don't know the code intimately enough yet. try: self.currentFile except AttributeError: self.currentFile = '' self.statusChanged.emit('Completed', self.currentFile, 100) @Slot(str) def onSync(self, localdir): """ Slot. Triggers a server checkout. :param localdir: Absolute local directory path where to keep the files """ self.sync.setLocalDir(localdir) self.sync.local.ioError.connect(self.onIOError) self.syncStarted.emit() self.setStatus('Syncing') def showMessageBox(self, msg): warning = QMessageBox(self) warning.setFont(View.labelsFont()) warning.setStyleSheet('QMessageBox {background: white}') warning.setWindowTitle("Error") warning.setText(msg) warning.setIcon(QMessageBox.Warning) warning.addButton("Ok", QMessageBox.AcceptRole).setFont(View.editsFont()) warning.exec_() @Slot(int, int) def onProgress(self, action, total, progress): """ Slot. Triggers download progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ if progress <= 0: return else: percent = (progress * 100) / total self.statusChanged.emit(action, self.currentFile, percent) @Slot(str) def setStatus(self, msg): self.statusChanged.emit(msg, '', 0) @Slot(int, int) def onDownloadProgress(self, total, progress): """ Slot. Triggers upload progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ self.onProgress('Downloading', total, progress) @Slot(int, int) def onUploadProgress(self, total, progress): """ Slot. Triggers download progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ self.onProgress('Uploading', total, progress) @Slot(str) def onFileEvent(self, filename): """ Slot. Updates the current download filename to be used in the UI :param filename: Name of the file that is being downloaded """ self.currentFile = filename @Slot(str) def onIOError(self, filename): self.showMessageBox('Error reading: "{}"'.format(filename)) @Slot(str) def badNameWarning(self, filename): self.showMessageBox( 'Will not sync "{}". Invalid filename'.format(filename))
class SyncWindow(QMainWindow): """ Application main window. This class is meant to handle every widget needed by the application, as well as other needed global objects and behavior. """ failedLogIn = Signal() syncStarted = Signal() loginRequested = Signal((str, str,)) statusChanged = Signal((str, str, int,)) def __init__(self, parent=None): super(SyncWindow, self).__init__(parent) # Sets up several UI aspects self.tray = QSystemTrayIcon(self) self.tray.setIcon(QIcon(QPixmap(':/resources/icon.png'))) self.tray.show() self.setStyleSheet('SyncWindow {background: white}') self.setWindowTitle('IQBox') self.setWindowIcon(QIcon(QPixmap(':/resources/logobar.png'))) self.statusBar().setFont(View.labelsFont()) self.syncThread = None # Initializes the window with a `LoginView` widget. self.loginView() def loginView(self): """ Initializes a `LoginView` object and sets it up as the main window's central widget. """ login = LoginView() login.login.connect(self.onLogin) self.failedLogIn.connect(login.onFailedLogIn) self.setCentralWidget(login) self.setFixedSize(login.size()) self.statusBar().hide() def syncView(self): """ Initializes a `SyncView` object and sets it up as the main window's central widget. """ syncview = SyncView() self.setCentralWidget(syncview) self.setFixedSize(syncview.size()) self.statusBar().show() self.statusChanged.connect(syncview.status.setMessage) syncview.sync.connect(self.onSync) @Slot(str, str, str, bool) def onLogin(self, host, username, passwd, ssl): """ Slot. Triggers a log in request to the server. :param host: Indicates the hostname of the FTP server :param username: Username to log in into the FTP server :param passwd: Password to log in into the FTP server :param ssl: Indicates whether the FTP needs SSL support """ self.sync = Sync(host, ssl) self.syncStarted.connect(self.sync.initQueue) self.sync.server.downloadProgress.connect(self.onDownloadProgress) self.sync.server.uploadProgress.connect(self.onUploadProgress) self.sync.server.fileEvent.connect(self.onFileEvent) self.sync.server.badFilenameFound.connect(self.badNameWarning) self.sync.server.loginCompleted.connect(self.onLoginCompleted) self.sync.server.fileEventCompleted.connect(self.onFileEventCompleted) self.sync.server.ioError.connect(self.onIOError) # Added by Si self.sync.server.textStatus.connect(self.setStatus) self.sync.statusChanged.connect(self.setStatus) self.loginRequested.connect(self.sync.server.onLogin) self.syncThread = QThread() self.sync.moveToThread(self.syncThread) self.syncThread.start() QApplication.instance().lastWindowClosed.connect(self.syncThread.quit) self.loginRequested.emit(username, passwd) @Slot(bool, str) def onLoginCompleted(self, ok, msg): if not ok: self.showMessageBox(msg) self.failedLogIn.emit() else: self.syncView() @Slot() def onFileEventCompleted(self): # Workaround because there's an exception # when there's a file IO error # Ideally it should be managed elsewhere # But I don't know the code intimately enough yet. try: self.currentFile except AttributeError: self.currentFile = '' self.statusChanged.emit('Completed', self.currentFile, 100) @Slot(str) def onSync(self, localdir): """ Slot. Triggers a server checkout. :param localdir: Absolute local directory path where to keep the files """ self.sync.setLocalDir(localdir) self.sync.local.ioError.connect(self.onIOError) self.syncStarted.emit() self.setStatus('Syncing') def showMessageBox(self, msg): warning = QMessageBox(self) warning.setFont(View.labelsFont()) warning.setStyleSheet('QMessageBox {background: white}') warning.setWindowTitle("Error") warning.setText(msg) warning.setIcon(QMessageBox.Warning) warning.addButton("Ok", QMessageBox.AcceptRole).setFont(View.editsFont()) warning.exec_() @Slot(int, int) def onProgress(self, action, total, progress): """ Slot. Triggers download progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ if progress <= 0: return else: percent = (progress * 100) / total self.statusChanged.emit(action, self.currentFile, percent) @Slot(str) def setStatus(self, msg): self.statusChanged.emit(msg, '', 0) @Slot(int, int) def onDownloadProgress(self, total, progress): """ Slot. Triggers upload progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ self.onProgress('Downloading', total, progress) @Slot(int, int) def onUploadProgress(self, total, progress): """ Slot. Triggers download progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ self.onProgress('Uploading', total, progress) @Slot(str) def onFileEvent(self, filename): """ Slot. Updates the current download filename to be used in the UI :param filename: Name of the file that is being downloaded """ self.currentFile = filename @Slot(str) def onIOError(self, filename): self.showMessageBox('Error reading: "{}"'.format(filename)) @Slot(str) def badNameWarning(self, filename): self.showMessageBox( 'Will not sync "{}". Invalid filename'.format(filename))