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)
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 __init__(self, icon, parent=None): QSystemTrayIcon.__init__(self, icon, parent) self.menu = QtGui.QMenu(parent) # initialize and add the open webpage menu item launch_action = QtGui.QAction('&Open Webpage', self) launch_action.setToolTip('Server is @ ' + ActiveConfig.SERVER_NAME + '.') launch_action.triggered.connect(self.launch_slot) self.menu.addAction(launch_action) self.menu.addSeparator() # initialize and add the exit application menu item exit_action = QtGui.QAction('&Exit', self) exit_action.setToolTip('This is the exit.') exit_action.triggered.connect(self.exit_slot) self.menu.addAction(exit_action) # menu.setToolTipsVisible(True) self.setContextMenu(self.menu) # connect signals self.menu.hovered.connect(self.menu_hovered_slot) self.activated.connect(self.tray_activated_slot) self.server_thread.connect_exit_signal_to_slot(self.exit_slot)
def __init__(self, app, *args, **kwargs): QSystemTrayIcon.__init__(self, *args, **kwargs) self.app = app self.menu = QMenu() self.setContextMenu(self.menu) self.menu.aboutToShow.connect(self.update) self.opened_notes = {}
def __init__(self, app, *args, **kwargs): QSystemTrayIcon.__init__(self, *args, **kwargs) self.app = app self.menu = QMenu() self.setContextMenu(self.menu) self.menu.aboutToShow.connect(self.update) self.opened_notes = {} self.activated.connect(self._activated)
def __init__(self, *args, **kwargs): QSystemTrayIcon.__init__(self, *args, **kwargs) self.app = QApplication.instance() self.menu = QMenu() self.setContextMenu(self.menu) self.menu.aboutToShow.connect(self.update) self.opened_notes = {} self.activated.connect(self._activated)
def __init__(self, *args, **kwargs): QSystemTrayIcon.__init__(self, *args, **kwargs) self.app = QApplication.instance() self.menu = QMenu() self.setContextMenu(self.menu) self.menu.aboutToShow.connect(self.update) self.opened_notes = {} self.activated.connect(self._activated) self.settings = QSettings('everpad', 'everpad-pad')
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()
def __init__(self, parent=None): icon = self.loadIcon() QSystemTrayIcon.__init__(self, icon, parent) menu = QMenu(parent) VBoxMenu.build(menu) menu.addSeparator() menu.addAction("Exit", lambda: sys.exit(0)) self.connect(menu, SIGNAL("aboutToShow()"), VBoxMenu.check_state) self.setContextMenu(menu) self.setToolTip("VBoxTrayIco") traySignal = "activated(QSystemTrayIcon::ActivationReason)" QObject.connect(self, SIGNAL(traySignal), self.showMenu)
def __init__(self, app, hub, debug=False): BaseWebUI.__init__(self, "index.html", app, hub, debug) self.html = index.html self.agent = '%s v%s' % (USER_AGENT, '.'.join(str(v) for v in VERSION)) log("Starting [%s]..." % self.agent, LEVEL_INFO) # Setup the system tray icon if sys.platform == 'darwin': tray_icon = 'evominer_16x16_mac.png' elif sys.platform == "win32": tray_icon = 'evominer_16x16.png' else: tray_icon = 'evominer_32x32_ubuntu.png' self.trayIcon = QSystemTrayIcon(self._getQIcon(tray_icon)) self.trayIcon.setToolTip(tray_icon_tooltip) # Setup the tray icon context menu self.trayMenu = QMenu() self.showAppAction = QAction('&Show %s' % APP_NAME, self) f = self.showAppAction.font() f.setBold(True) self.showAppAction.setFont(f) self.trayMenu.addAction(self.showAppAction) self.aboutAction = QAction('&About...', self) self.trayMenu.addAction(self.aboutAction) self.trayMenu.addSeparator() self.exitAction = QAction('&Exit', self) self.trayMenu.addAction(self.exitAction) # Add menu to tray icon self.trayIcon.setContextMenu(self.trayMenu) # connect signals self.trayIcon.activated.connect(self._handleTrayIconActivate) self.exitAction.triggered.connect(self.handleExitAction) self.aboutAction.triggered.connect(self.handleAboutAction) self.showAppAction.triggered.connect(self._handleShowAppAction) self.app.aboutToQuit.connect(self._handleAboutToQuit) # Setup notification support self.system_tray_running_notified = False self.notifier = Notify(APP_NAME) self.trayIcon.show()
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 __init__(self, icon, parent=None): QSystemTrayIcon.__init__(self, icon, parent) self.setToolTip("usb-resetter 1.0 (Left\Right-Click)") self.parent = parent self.activated.connect(self.toggleP) menu = QMenu(parent) self.fmenu = QMenu("Fast reset", parent) self.fmenu.setToolTip("List of filtered devices to fast reset") aboutAction = QAction("About", self) aboutAction.triggered.connect(parent.show_about) quitAction = QAction("Exit", self) quitAction.triggered.connect(parent.exitEvent) menu.addMenu(self.fmenu) menu.addSeparator() menu.addAction(aboutAction) menu.addAction(quitAction) self.setContextMenu(menu)
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_()
def __init__(self, *args, **kwargs): QSystemTrayIcon.__init__(self, *args, **kwargs) self.app = QApplication.instance() self.menu = QMenu() self.setContextMenu(self.menu) self.menu.aboutToShow.connect(self.update) self.opened_notes = {} self.activated.connect(self._activated) self.settings = QSettings('everpad', 'everpad-pad') # Configure logger. self.logger = logging.getLogger('everpad-indicator') self.logger.setLevel(logging.DEBUG) fh = logging.FileHandler( os.path.expanduser('~/.everpad/logs/everpad.log')) fh.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) self.logger.addHandler(fh)
def __init__(self, app, *args, **kwargs): """Init indicator Keyword Arguments: app -- QApplication Returns: None """ QSystemTrayIcon.__init__(self, *args, **kwargs) self._action_threads = [] self._cached_notes = {} self.menu = QMenu() self.setContextMenu(self.menu) self.app = app app.indicator = self self.menu.aboutToShow.connect(self.update) self.auth_dialog = AuthDialog(self.app) self._notes = [] self.notes_get.connect(self.notes_getted) self.get_notes()
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 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 __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__(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 __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()
#refactor def _quit(): app.quit() qDebug('bye!') def show_window(thereason): if thereason == QSystemTrayIcon.ActivationReason.Trigger: if main_window.isVisible() == True: main_window.hide() main_window.show() #create the QApplication instance before any other widget app = QApplication(sys.argv) app.setQuitOnLastWindowClosed(False) ico = QIcon(os.path.join(os.getcwd(),'yhn.png')) systrayico = QSystemTrayIcon(ico) systrayico.activated.connect(show_window) systrayico.show() x_pos = systrayico.geometry().left() y_pos = app.desktop().availableGeometry(app.desktop().primaryScreen()).topLeft().y() main_window = MainWindow(x_pos, y_pos, 420, 500) sys.exit(app.exec_())
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 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 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 MainWindow(QWidget, Ui_Form): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.appname = "poliBeePsync" self.settings_fname = 'pbs-settings.ini' self.data_fname = 'pbs.data' self.setupUi(self) self.w = QWidget() self.about_text() self.timer = QTimer(self) # settings_path is a string containing the path to settings self.settings_path = None # settings is a dictionary of settings self.settings = None # load_settings() sets settings_path and settings self.load_settings() self.load_data() self.timer.timeout.connect(self.syncfiles) self.timer.start(1000 * 60 * int(self.settings['UpdateEvery'])) self.loginthread = LoginThread(self.user) self.loginthread.signal_error.sig.connect(self.myStream_message) self.loginthread.signal_error.sig.connect(self.loginstatus) self.loginthread.signal_ok.sig.connect(self.myStream_message) self.loginthread.signal_ok.sig.connect(self.loginstatus) self.refreshcoursesthread = RefreshCoursesThread(self.user) self.refreshcoursesthread.dumpuser.sig.connect(self.dumpUser) self.refreshcoursesthread.newcourses.sig.connect(self.addtocoursesview) self.refreshcoursesthread.newcourses.sig.connect(self.syncnewcourses) self.refreshcoursesthread.refreshed.sig.connect(self.myStream_message) self.refreshcoursesthread.removable.sig.connect(self.rmfromcoursesview) self.downloadthread = DownloadThread(self.user, self.settings['RootFolder']) self.downloadthread.download_signal.connect( self.update_course_download) #self.downloadthread.download_signal.connect(self._resizeview) self.downloadthread.initial_sizes.connect(self.setinizialsizes) self.downloadthread.data_signal.connect(self.update_file_localtime) self.userCode.setText(str(self.user.username)) self.userCode.textEdited.connect(self.setusercode) self.password.setText(self.user.password) self.password.textEdited.connect(self.setpassword) self.trylogin.clicked.connect(self.testlogin) self.courses_model = CoursesListModel(self.user.available_courses) self.coursesView.setModel(self.courses_model) self._resizeview() self.refreshCourses.clicked.connect(self.refreshcourses) self.courses_model.dataChanged.connect(self.dumpUser) self.syncNow.clicked.connect(self.syncfiles) #self.pushButton.clicked.connect(self.syncfiles) #self.pushButton.clicked.connect(self.inittextincourses) if self.settings['SyncNewCourses'] == str(True): self.sync_new = Qt.Checked else: self.sync_new = Qt.Unchecked self.rootfolder.setText(self.settings['RootFolder']) self.rootfolder.textChanged.connect(self.rootfolderslot) self.addSyncNewCourses.setCheckState(self.sync_new) self.addSyncNewCourses.stateChanged.connect(self.syncnewslot) self.timerMinutes.setValue(int(self.settings['UpdateEvery'])) self.timerMinutes.valueChanged.connect(self.updateminuteslot) self.changeRootFolder.clicked.connect(self.chooserootdir) #self.version_label.setText("Current version: {}.".format(__version__)) #self.pushButton_2.clicked.connect(self.checknewversion) self.trayIconMenu = QMenu() self.trayIcon = QSystemTrayIcon(self.icon, self.w) self.trayIcon.activated.connect(self._activate_traymenu) self.createTray() def _resizeview(self, **kwargs): self.coursesView.setColumnWidth(3, 160) self.coursesView.resizeColumnToContents(1) self.coursesView.setColumnWidth(0, 320) def inittextincourses(self): self.statusLabel.setText('Started syncing.') def checknewversion(self): rawdata = requests.get( 'https://pypi.python.org/pypi/poliBeePsync/json') latest = json.loads(rawdata.text)['info']['version'] self.version_label.setTextFormat(Qt.RichText) self.version_label.setOpenExternalLinks(True) self.version_label.setLocale( QLocale(QLocale.English, QLocale.UnitedStates)) self.version_label.setScaledContents(True) self.version_label.setWordWrap(True) if latest != __version__: newtext = """<p>Current version: {}.<br> Latest version: {}. </p> <p>Visit <a href='http://www.davideolianas.com/polibeepsync/index.html#how-to\ -install-upgrade-remove'>here</a> to find out how to upgrade. """.format(__version__, latest) else: newtext = "Current version: {} up-to-date.".format(__version__) self.version_label.setText(newtext) def _update_time(self, folder, file, path_list): print('inside ', folder.name) print('path_list: ', path_list) while len(path_list) > 0: namegoto = path_list.pop(0) print('namegoto: ', namegoto) # perché a volte è vuoto? if namegoto != "": fakefolder = Folder(namegoto, 'fake') print('contained folders: ', folder.folders) ind = folder.folders.index(fakefolder) goto = folder.folders[ind] self._update_time(goto, file, path_list) if file in folder.files: ind = folder.files.index(file) thisfile = folder.files[ind] thisfile.local_creation_time = file.local_creation_time self.dumpUser() def update_file_localtime(self, data, **kwargs): course, coursefile, path = data rootpath = os.path.join(self.settings['RootFolder'], course.save_folder_name) if path.startswith(rootpath): partial = path[len(rootpath):] path_list = partial.split(os.path.sep) self._update_time(course.documents, coursefile, path_list) def update_course_download(self, course, **kwargs): logger.info('download size updated') if course in self.user.available_courses: updating = self.user.available_courses[course.name] updating.downloaded_size = course.downloaded_size row = self.courses_model.courses.index(updating) where = self.courses_model.index(row, 3) self.courses_model.dataChanged.emit(where, where) self.dumpUser() def setinizialsizes(self, course, **kwargs): if course in self.user.available_courses: updating = self.user.available_courses[course.name] updating.downloaded_size = course.downloaded_size updating.total_file_size = course.total_file_size row = self.courses_model.courses.index(updating) where = self.courses_model.index(row, 3) self.courses_model.dataChanged.emit(where, where) self.dumpUser() def syncnewcourses(self, newlist): if self.settings['SyncNewCourses'] == 'True': for elem in newlist: elem.sync = True def load_settings(self): for path in [ user_config_dir(self.appname), user_data_dir(self.appname) ]: try: os.makedirs(path, exist_ok=True) except OSError: logger.critical('OSError while calling os.makedirs.', exc_info=True) self.myStream_message("I couldn't create {}.\nStart" " poliBeePsync with --debug " "error to get more details.") self.settings_path = os.path.join(user_config_dir(self.appname), self.settings_fname) defaults = { 'UpdateEvery': '60', 'RootFolder': os.path.join(os.path.expanduser('~'), self.appname), 'SyncNewCourses': 'False' } self.settings = filesettings.settingsFromFile(self.settings_path, defaults) def load_data(self): try: with open( os.path.join(user_data_dir(self.appname), self.data_fname), 'rb') as f: self.user = pickle.load(f) self.myStream_message("Data has been loaded successfully.") except FileNotFoundError: logger.error('Settings file not found.', exc_info=True) self.user = User('', '') self.myStream_message("I couldn't find data in the" " predefined directory. Ignore this" "message if you're using poliBeePsync" " for the first time.") def loginstatus(self, status): self.login_attempt.setText(status) # @Slot(int) # def notifynew(self, state): # if state == 2: # self.settings['NotifyNewCourses'] = 'True' # else: # self.settings['NotifyNewCourses'] = 'False' # filesettings.settingsToFile(self.settings, self.settings_path) @Slot(int) def syncnewslot(self, state): if state == 2: self.settings['SyncNewCourses'] = 'True' else: self.settings['SyncNewCourses'] = 'False' filesettings.settingsToFile(self.settings, self.settings_path) @Slot(int) def updateminuteslot(self, minutes): self.settings['UpdateEvery'] = str(minutes) filesettings.settingsToFile(self.settings, self.settings_path) self.timer.start(1000 * 60 * int(self.settings['UpdateEvery'])) @Slot(str) def rootfolderslot(self, path): self.settings['RootFolder'] = path filesettings.settingsToFile(self.settings, self.settings_path) def chooserootdir(self): currentdir = self.settings['RootFolder'] flags = QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly newroot = QFileDialog.getExistingDirectory(None, "Open Directory", currentdir, flags) if newroot != "" and str(newroot) != currentdir: self.settings['RootFolder'] = str(newroot) filesettings.settingsToFile(self.settings, self.settings_path) self.rootfolder.setText(newroot) # we delete the already present downloadthread and recreate it # because otherwise it uses the old download folder. I don't know # if there's a cleaner approach del self.downloadthread self.downloadthread = DownloadThread(self.user, self.settings['RootFolder']) self.downloadthread.dumpuser.sig.connect(self.dumpUser) self.downloadthread.course_finished.sig.connect( self.myStream_message) self.downloadthread.signal_error.sig.connect(self.myStream_message) def setusercode(self): newcode = self.userCode.text() self.user.username = newcode try: self.dumpUser() if len(newcode) == 8: self.myStream_message( "User code changed to {}.".format(newcode)) except OSError: self.myStream_message("I couldn't save data to disk. Run" " poliBeePsync with option --debug" " error to get more details.") logger.error( 'OSError raised while trying to write the User' 'instance to disk.', exc_info=True) def setpassword(self): newpass = self.password.text() self.user.password = newpass try: self.dumpUser() self.myStream_message("Password changed.") except OSError: self.myStream_message("I couldn't save data to disk. Run" " poliBeePsync with option --debug" " error to get more details.") logger.error( 'OSError raised while trying to write the User' 'instance to disk.', exc_info=True) def testlogin(self): if not self.loginthread.isRunning(): self.loginthread.exiting = False self.loginthread.start() self.login_attempt.setStyleSheet("color: rgba(0, 0, 0, 255);") self.login_attempt.setText("Logging in, please wait.") def addtocoursesview(self, addlist): for elem in addlist: self.courses_model.insertRows(0, 1, elem) def rmfromcoursesview(self, removelist): for elem in removelist: index = self.courses_model.courses.index(elem) self.courses_model.removeRows(index, 1) def dumpUser(self): # we don't use the message... with open(os.path.join(user_data_dir(self.appname), self.data_fname), 'wb') as f: pickle.dump(self.user, f) def refreshcourses(self): self.statusLabel.setText( 'Searching for online updates...this may take a' ' while.') if not self.loginthread.isRunning(): self.loginthread.exiting = False self.loginthread.signal_ok.sig.connect(self.do_refreshcourses) self.loginthread.start() def do_refreshcourses(self): self.loginthread.signal_ok.sig.disconnect(self.do_refreshcourses) if not self.refreshcoursesthread.isRunning(): self.refreshcoursesthread.exiting = False self.refreshcoursesthread.start() @Slot() def syncfiles(self): self.refreshcoursesthread.finished.connect(self.do_syncfiles) self.refreshcourses() def do_syncfiles(self): self.refreshcoursesthread.finished.disconnect(self.do_syncfiles) self.inittextincourses() self.downloadthread.start() @Slot(str) def myStream_message(self, message): self.status.moveCursor(QTextCursor.End) self.status.insertPlainText(message + "\n\n") def createTray(self): restoreAction = QAction("&Restore", self, triggered=self.showNormal) quitAction = QAction("&Quit", self, triggered=qApp.quit) self.trayIconMenu.addAction(restoreAction) self.trayIconMenu.addAction(quitAction) self.trayIcon.setContextMenu(self.trayIconMenu) self.trayIcon.show() def _activate_traymenu(self, reason): if reason == QSystemTrayIcon.ActivationReason.Trigger: self.showNormal() else: self.trayIconMenu.activateWindow() self.trayIconMenu.popup(QCursor.pos()) def closeEvent(self, event): self.hide() event.ignore() def about_text(self): self.label_3 = QLabel() self.label_3.setTextFormat(Qt.RichText) self.label_3.setOpenExternalLinks(True) self.label_3.setLocale(QLocale(QLocale.English, QLocale.UnitedStates)) self.label_3.setScaledContents(True) self.label_3.setWordWrap(True) text = """ <html> <head/> <body> <p>poliBeePsync is a program written by Davide Olianas, released under GNU GPLv3+.</p> <p>Feel free to contact me at <a href=\"mailto:[email protected]\">[email protected]</a> for suggestions and bug reports.</p> <p>More information is available on the <a href=\"http://www.davideolianas.com/polibeepsync\"> <span style=\" text-decoration: underline; color:#0000ff;\"> official website</span></a>. </p> </body> </html> """ if pysideVersion == '1.2.2': self.label_3.setText( QApplication.translate("Form", text, None, QApplication.UnicodeUTF8)) else: self.label_3.setText(QApplication.translate("Form", text, None))
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()
def initSearch(self): self.s.show() # self.seaProc = Popen(["python", # self.instdir + "/searchui.py"]) def initManager(self): self.m.show() # self.manProc = Popen(["python", # self.instdir + "/managerui.py"]) if __name__ == '__main__': import sys app = QApplication(sys.argv) display = app.desktop() if not QSystemTrayIcon.isSystemTrayAvailable(): QMessageBox.critical(None, "System Tray", "No system tray detected, use alternate means to \ interface with Tag Manager.") sys.exit(1) QApplication.setQuitOnLastWindowClosed(False) ignition = SysTray(display) sys.exit(app.exec_())
class WebUI(BaseWebUI): def __init__(self, app, hub, debug=False): BaseWebUI.__init__(self, "index.html", app, hub, debug) self.html = index.html self.agent = '%s v%s' % (USER_AGENT, '.'.join(str(v) for v in VERSION)) log("Starting [%s]..." % self.agent, LEVEL_INFO) # Setup the system tray icon if sys.platform == 'darwin': tray_icon = 'ombre_16x16.png' elif sys.platform == "win32": tray_icon = 'ombre_16x16.png' else: tray_icon = 'ombre_32x32.png' self.trayIcon = QSystemTrayIcon(self._getQIcon(tray_icon)) self.trayIcon.setToolTip(tray_icon_tooltip) # Setup the tray icon context menu self.trayMenu = QMenu() self.showAppAction = QAction('&Show %s' % APP_NAME, self) f = self.showAppAction.font() f.setBold(True) self.showAppAction.setFont(f) self.trayMenu.addAction(self.showAppAction) self.aboutAction = QAction('&About...', self) self.trayMenu.addAction(self.aboutAction) self.trayMenu.addSeparator() self.exitAction = QAction('&Exit', self) self.trayMenu.addAction(self.exitAction) # Add menu to tray icon self.trayIcon.setContextMenu(self.trayMenu) # connect signals self.trayIcon.activated.connect(self._handleTrayIconActivate) self.exitAction.triggered.connect(self.handleExitAction) self.aboutAction.triggered.connect(self.handleAboutAction) self.showAppAction.triggered.connect(self._handleShowAppAction) self.app.aboutToQuit.connect(self._handleAboutToQuit) # Setup notification support self.system_tray_running_notified = False self.notifier = Notify(APP_NAME) self.trayIcon.show() def run(self): # load user's pool list # load_pools(self.app.property("AppPath")) self.view.loadFinished.connect(self._load_finished) # self.view.load(qt_core.QUrl(self.url)) self.view.setHtml(index.html, qt_core.QUrl(self.url)) self.resetWindowSize() self.center() self.timer = QTimer(self) self.timer.timeout.connect(self._updateHashRate) self.timer.start(2000) self.wait(1) self.timer2 = QTimer(self) self.timer2.timeout.connect(self._reportError) self.timer2.start(2000) self.trayIcon.show() self.show() def closeEvent(self, event): """ Override QT close event """ event.ignore() self.hide() if not self.system_tray_running_notified: self.notify("%s is still running at system tray." % APP_NAME, "Running Status") self.system_tray_running_notified = True def resetWindowSize(self): ws = qt_core.QSize( WINDOW_WIDTH, HEAD_ROW_HEIGHT + POOL_ROW_HEIGHT * (len([p for p in self.hub.pools.all_pools if not p['is_hidden']])) + BOTTOM_MARGIN) self.setFixedSize(ws) def _getQIcon(self, icon_file): _icon_path = os.path.join(self.app.property("ResPath"), 'icons', icon_file) return QIcon(_icon_path) def _handleTrayIconActivate(self, reason): if reason == QSystemTrayIcon.DoubleClick: self.showNormal() self.activateWindow() def handleExitAction(self, show_confirmation=False): reply = QMessageBox.No if show_confirmation: reply = QMessageBox.question(self, 'Exit %s?' % APP_NAME, "Are you sure to exit %s?" % APP_NAME, QMessageBox.Yes, QMessageBox.No) if not show_confirmation or reply == QMessageBox.Yes: self.trayIcon.hide() QTimer.singleShot(250, self.app.quit) def _handleShowAppAction(self): self.showNormal() self.activateWindow() def handleAboutAction(self): self.showNormal() self.about() def _reportError(self): for pool_info in self.hub.pools.all_pools: if 'error' in pool_info: if pool_info['error'] is not None: self.hub.report_error(pool_info['id'], pool_info['error']) else: self.hub.report_error(pool_info['id'], 'ERROR_END') pool_info.pop("error", None) def _updateHashRate(self): _sum_hashrates = 0. for pool_info in self.hub.pools.all_pools: _json = {'pool_id': pool_info['id']} hash_rates = pool_info[ 'hash_report'] if 'hash_report' in pool_info else {} if len(hash_rates) > 0: _hash_rates = dict(hash_rates) _total_hash_rate = reduce( lambda x, y: x + y, [_hash_rates[k] for k in _hash_rates]) _json['hash_rate'] = _total_hash_rate _sum_hashrates += _total_hash_rate pool_info['total_hashrate'] = _total_hash_rate else: _json['hash_rate'] = 0.0 # reset hashrate if 'hash_report' in pool_info and 'thr_list' in pool_info: if pool_info['thr_list'] is not None: for thr in pool_info['thr_list']: pool_info['hash_report'].update( {'%d' % thr._thr_id: 0.0}) work_report = pool_info[ 'work_report'] if 'work_report' in pool_info else {} if 'work_submited' in work_report and work_report[ 'work_submited'] > 0: _json['shares_good'] = work_report[ 'work_accepted'] if 'work_accepted' in work_report else 0 _json['shares_total'] = work_report['work_submited'] _json['shares_pct'] = "%.2f%%" % ( _json['shares_good'] * 100.0 / _json['shares_total'], ) else: _json['shares_good'] = 0 _json['shares_total'] = 0 _json['shares_pct'] = "0.00%" if 'difficulty' in work_report: _json['difficulty'] = "%.f" % work_report['difficulty'] else: _json['difficulty'] = "0" self.hub.update_hashrate(json.dumps(_json)) self.trayIcon.setToolTip( "%s\nHashrate: %s" % (tray_icon_tooltip, human_readable_hashrate(_sum_hashrates))) def _load_finished(self): #This is the actual context/frame a webpage is running in. # Other frames could include iframes or such. main_page = self.view.page() main_frame = main_page.mainFrame() # ATTENTION here's the magic that sets a bridge between Python to HTML main_frame.addToJavaScriptWindowObject("app_hub", self.hub) if self.is_first_load: ## Avoid re-settings on page reload (if happened) change_setting = main_page.settings().setAttribute settings = web_core.QWebSettings change_setting(settings.DeveloperExtrasEnabled, self.debug) change_setting(settings.LocalStorageEnabled, True) change_setting(settings.OfflineStorageDatabaseEnabled, True) change_setting(settings.OfflineWebApplicationCacheEnabled, True) change_setting(settings.JavascriptCanOpenWindows, True) change_setting(settings.PluginsEnabled, False) # Show web inspector if debug on if self.debug: self.inspector = web_core.QWebInspector() self.inspector.setPage(self.view.page()) self.inspector.show() #Tell the HTML side, we are open for business main_frame.evaluateJavaScript("app_ready()") # send pool list to HTML for rendering self.hub.create_pool_list() # Resize main window to fit web content (avoid scroll bars showed) main_page.setViewportSize(main_frame.contentsSize()) #self.setFixedSize(860, 360) # resume mining jobs for p in self.hub.pools.all_pools: if 'is_mining' in p and p['is_mining']: self.hub.start_stop_mining(p['id']) self.is_first_load = False def _handleAboutToQuit(self): log("%s is about to quit..." % APP_NAME, LEVEL_INFO) for pool_info in self.hub.pools.all_pools: if not 'thr_list' in pool_info or pool_info['thr_list'] is None: pool_info['is_mining'] = False else: # shut down threads for thr in pool_info['thr_list']: thr.shutdown() thr.join() # shut down RPC client pool_info['rpc'].shutdown() pool_info['rpc'].join() pool_info[ 'is_mining'] = True # save mining status to resume on next start if manager: manager.shutdown() # save pool list self.hub.pools.save_all() def notify(self, message, title="", icon=None, msg_type=None): if self.notifier.notifier is not None: self.notifier.notify(title, message, icon) else: self.showMessage(message, title, msg_type) def showMessage(self, message, title="", msg_type=None, timeout=2000): """Displays 'message' through the tray icon's showMessage function, with title 'title'. 'type' is one of the enumerations of 'common.MessageTypes'. """ if msg_type is None or msg_type == MSG_TYPE_INFO: icon = QSystemTrayIcon.Information elif msg_type == MSG_TYPE_WARNING: icon = QSystemTrayIcon.Warning elif msg_type == MSG_TYPE_CRITICAL: icon = QSystemTrayIcon.Critical title = "%s - %s" % (APP_NAME, title) if title else APP_NAME self.trayIcon.showMessage(title, message, icon, timeout) def about(self): QMessageBox.about(self, "About", \ u"%s <br><br>Copyright© 2017 - Sumokoin Projects<br><br>\ <b>www.sumokoin.org</b>" % self.agent) def wait(self, timeout=1): for _ in range(timeout * 10): sleep(0.1) self.app.processEvents()
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
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.appname = "poliBeePsync" self.settings_fname = 'pbs-settings.ini' self.data_fname = 'pbs.data' self.setupUi(self) self.w = QWidget() self.about_text() self.timer = QTimer(self) # settings_path is a string containing the path to settings self.settings_path = None # settings is a dictionary of settings self.settings = None # load_settings() sets settings_path and settings self.load_settings() self.load_data() self.timer.timeout.connect(self.syncfiles) self.timer.start(1000 * 60 * int(self.settings['UpdateEvery'])) self.loginthread = LoginThread(self.user) self.loginthread.signal_error.sig.connect(self.myStream_message) self.loginthread.signal_error.sig.connect(self.loginstatus) self.loginthread.signal_ok.sig.connect(self.myStream_message) self.loginthread.signal_ok.sig.connect(self.loginstatus) self.refreshcoursesthread = RefreshCoursesThread(self.user) self.refreshcoursesthread.dumpuser.sig.connect(self.dumpUser) self.refreshcoursesthread.newcourses.sig.connect(self.addtocoursesview) self.refreshcoursesthread.newcourses.sig.connect(self.syncnewcourses) self.refreshcoursesthread.refreshed.sig.connect(self.myStream_message) self.refreshcoursesthread.removable.sig.connect(self.rmfromcoursesview) self.downloadthread = DownloadThread(self.user, self.settings['RootFolder']) self.downloadthread.download_signal.connect( self.update_course_download) #self.downloadthread.download_signal.connect(self._resizeview) self.downloadthread.initial_sizes.connect(self.setinizialsizes) self.downloadthread.data_signal.connect(self.update_file_localtime) self.userCode.setText(str(self.user.username)) self.userCode.textEdited.connect(self.setusercode) self.password.setText(self.user.password) self.password.textEdited.connect(self.setpassword) self.trylogin.clicked.connect(self.testlogin) self.courses_model = CoursesListModel(self.user.available_courses) self.coursesView.setModel(self.courses_model) self._resizeview() self.refreshCourses.clicked.connect(self.refreshcourses) self.courses_model.dataChanged.connect(self.dumpUser) self.syncNow.clicked.connect(self.syncfiles) #self.pushButton.clicked.connect(self.syncfiles) #self.pushButton.clicked.connect(self.inittextincourses) if self.settings['SyncNewCourses'] == str(True): self.sync_new = Qt.Checked else: self.sync_new = Qt.Unchecked self.rootfolder.setText(self.settings['RootFolder']) self.rootfolder.textChanged.connect(self.rootfolderslot) self.addSyncNewCourses.setCheckState(self.sync_new) self.addSyncNewCourses.stateChanged.connect(self.syncnewslot) self.timerMinutes.setValue(int(self.settings['UpdateEvery'])) self.timerMinutes.valueChanged.connect(self.updateminuteslot) self.changeRootFolder.clicked.connect(self.chooserootdir) #self.version_label.setText("Current version: {}.".format(__version__)) #self.pushButton_2.clicked.connect(self.checknewversion) self.trayIconMenu = QMenu() self.trayIcon = QSystemTrayIcon(self.icon, self.w) self.trayIcon.activated.connect(self._activate_traymenu) self.createTray()
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))