Ejemplo n.º 1
0
class SystemTray(QWidget):
    """只有托盘"""
    def __init__(self, config_list):
        super().__init__()
        self.tray = QSystemTrayIcon()
        self.tray.setIcon(QIcon('icons/app.ico'))
        self.add_menu(config_list)

    def add_menu(self, config_list):
        """托盘菜单"""
        tray_menu = QMenu()
        # 添加菜单
        for config in config_list:
            params = config.get('params')
            sys_name = params.get('name')
            tray_menu.addAction(OpenAction(params, self))
            stop_bat = params.get('stop_bat', None)
            if stop_bat:
                tray_menu.addAction(StopAction(sys_name, stop_bat, self))
        tray_menu.addAction(ExitAction(self))
        self.tray.setContextMenu(tray_menu)

    def display(self):
        """icon的值: 0-没有图标  1-是提示  2-是警告  3-是错误"""
        self.tray.show()
        self.tray.showMessage(u"启动成功", '请通过右键操作')
Ejemplo n.º 2
0
class IPtray(object):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # self.Lock=threading.RLock()
        self.ip = "0.0.0.0"
        self.app = QApplication(sys.argv)
        self.wMain = QWidget()
        self.tray = QSystemTrayIcon(self.wMain)

    def Ui(self):
        self.sub_getIP()
        self.actExit = QAction("退出")
        self.actExit.triggered.connect(self.forceEx)
        self.tray.setIcon(QIcon(".\icon\ip.png"))
        self.tray.setVisible(True)
        self.trayMenu = QMenu()
        self.trayMenu.addAction(self.actExit)
        self.tray.setContextMenu(self.trayMenu)
        # print("showing message")
        self.tray.showMessage("IP", "你的IP是" + self.ip)
        self.sub_setToolTip()  #getIP运行比较慢, setToolTip放在后面.
        sys.exit(self.app.exec_())

    def forceEx(self):
        sys.exit(self.app.exec_())
        exit()

    def getIP(self):
        # self.Lock.acquire()
        while 1:
            try:
                s = socket(AF_INET, SOCK_DGRAM)
                s.connect(("114.114.114.114", 80))
                self.ip = s.getsockname()[0]
            finally:
                s.close()
                # print("exit getIP")
            sleep(5)
            # self.Lock.release()

    def setToolTip(self):
        while 1:
            self.tray.setToolTip(self.ip)
            # print("exit setToopTip")
            sleep(5)

    def sub_getIP(self):
        self.subThread_getIP = Thread(target=self.getIP, daemon=True)
        self.subThread_getIP.setName("sub_getIP")
        # self.subThread_getIP.setDaemon = True  # 设置为后台线程
        self.subThread_getIP.start()

    # 这个线程要一直运行
    def sub_setToolTip(self):
        self.subThread_setToolTip = Thread(target=self.setToolTip, daemon=True)
        self.subThread_setToolTip.setName("sub_setToolTip")
        # self.subThread_setToolTip.setDaemon(True)  # 设置为后台线程
        self.subThread_setToolTip.start()
Ejemplo n.º 3
0
class Window(QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self.iconGroupBox = QGroupBox()
        self.iconLabel = QLabel()
        self.iconComboBox = QComboBox()
        self.showIconCheckBox = QCheckBox()

        self.messageGroupBox = QGroupBox()
        self.typeLabel = QLabel()
        self.durationLabel = QLabel()
        self.durationWarningLabel = QLabel()
        self.titleLabel = QLabel()
        self.bodyLabel = QLabel()

        self.typeComboBox = QComboBox()
        self.durationSpinBox = QSpinBox()
        self.titleEdit = QLineEdit()
        self.bodyEdit = QTextEdit()
        self.showMessageButton = QPushButton()

        self.minimizeAction = QAction()
        self.maximizeAction = QAction()
        self.restoreAction = QAction()
        self.quitAction = QAction()

        self.trayIcon = QSystemTrayIcon()
        self.trayIconMenu = QMenu()

        self.createIconGroupBox()
        self.createMessageGroupBox()

        self.iconLabel.setMinimumWidth(self.durationLabel.sizeHint().width())

        self.createActions()
        self.createTrayIcon()

        self.showMessageButton.clicked.connect(self.showMessage)
        self.showIconCheckBox.toggled.connect(self.trayIcon.setVisible)
        self.iconComboBox.currentIndexChanged.connect(self.setIcon)
        self.trayIcon.messageClicked.connect(self.messageClicked)
        self.trayIcon.activated.connect(self.iconActivated)

        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.iconGroupBox)
        self.mainLayout.addWidget(self.messageGroupBox)
        self.setLayout(self.mainLayout)

        self.iconComboBox.setCurrentIndex(1)
        self.trayIcon.show()

        self.setWindowTitle("Systray")
        self.resize(400, 300)

    def setVisible(self, visible):
        self.minimizeAction.setEnabled(visible)
        self.maximizeAction.setEnabled(not self.isMaximized())
        self.restoreAction.setEnabled(self.isMaximized() or not visible)
        super().setVisible(visible)

    def closeEvent(self, event):
        if not event.spontaneous() or not self.isVisible():
            return
        if self.trayIcon.isVisible():
            QMessageBox.information(self, "Systray",
                                    "The program will keep running in the system tray. "
                                    "To terminate the program, choose <b>Quit</b> in the context "
                                    "menu of the system tray entry.")
            self.hide()
            event.ignore()

    @Slot(int)
    def setIcon(self, index):
        icon = self.iconComboBox.itemIcon(index)
        self.trayIcon.setIcon(icon)
        self.setWindowIcon(icon)
        self.trayIcon.setToolTip(self.iconComboBox.itemText(index))

    @Slot(str)
    def iconActivated(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            pass
        if reason == QSystemTrayIcon.DoubleClick:
            self.iconComboBox.setCurrentIndex(
                (self.iconComboBox.currentIndex() + 1) % self.iconComboBox.count()
            )
        if reason == QSystemTrayIcon.MiddleClick:
            self.showMessage()

    @Slot()
    def showMessage(self):
        self.showIconCheckBox.setChecked(True)
        selectedIcon = self.typeComboBox.itemData(self.typeComboBox.currentIndex())
        msgIcon = QSystemTrayIcon.MessageIcon(selectedIcon)

        if selectedIcon == -1:  # custom icon
            icon = QIcon(self.iconComboBox.itemIcon(self.iconComboBox.currentIndex()))
            self.trayIcon.showMessage(
                self.titleEdit.text(),
                self.bodyEdit.toPlainText(),
                icon,
                self.durationSpinBox.value() * 1000,
            )
        else:
            self.trayIcon.showMessage(
                self.titleEdit.text(),
                self.bodyEdit.toPlainText(),
                msgIcon,
                self.durationSpinBox.value() * 1000,
            )

    @Slot()
    def messageClicked(self):
        QMessageBox.information(None, "Systray",
                                "Sorry, I already gave what help I could.\n"
                                "Maybe you should try asking a human?")

    def createIconGroupBox(self):
        self.iconGroupBox = QGroupBox("Tray Icon")

        self.iconLabel = QLabel("Icon:")

        self.iconComboBox = QComboBox()
        self.iconComboBox.addItem(QIcon(":/images/bad.png"), "Bad")
        self.iconComboBox.addItem(QIcon(":/images/heart.png"), "Heart")
        self.iconComboBox.addItem(QIcon(":/images/trash.png"), "Trash")

        self.showIconCheckBox = QCheckBox("Show icon")
        self.showIconCheckBox.setChecked(True)

        iconLayout = QHBoxLayout()
        iconLayout.addWidget(self.iconLabel)
        iconLayout.addWidget(self.iconComboBox)
        iconLayout.addStretch()
        iconLayout.addWidget(self.showIconCheckBox)
        self.iconGroupBox.setLayout(iconLayout)

    def createMessageGroupBox(self):
        self.messageGroupBox = QGroupBox("Balloon Message")

        self.typeLabel = QLabel("Type:")

        self.typeComboBox = QComboBox()
        self.typeComboBox.addItem("None", QSystemTrayIcon.NoIcon)
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxInformation),
            "Information",
            QSystemTrayIcon.Information,
        )
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxWarning),
            "Warning",
            QSystemTrayIcon.Warning,
        )
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxCritical),
            "Critical",
            QSystemTrayIcon.Critical,
        )
        self.typeComboBox.addItem(QIcon(), "Custom icon", -1)
        self.typeComboBox.setCurrentIndex(1)

        self.durationLabel = QLabel("Duration:")

        self.durationSpinBox = QSpinBox()
        self.durationSpinBox.setRange(5, 60)
        self.durationSpinBox.setSuffix(" s")
        self.durationSpinBox.setValue(15)

        self.durationWarningLabel = QLabel("(some systems might ignore this hint)")
        self.durationWarningLabel.setIndent(10)

        self.titleLabel = QLabel("Title:")
        self.titleEdit = QLineEdit("Cannot connect to network")
        self.bodyLabel = QLabel("Body:")

        self.bodyEdit = QTextEdit()
        self.bodyEdit.setPlainText("Don't believe me. Honestly, I don't have a clue."
                                   "\nClick this balloon for details.")

        self.showMessageButton = QPushButton("Show Message")
        self.showMessageButton.setDefault(True)

        messageLayout = QGridLayout()
        messageLayout.addWidget(self.typeLabel, 0, 0)
        messageLayout.addWidget(self.typeComboBox, 0, 1, 1, 2)
        messageLayout.addWidget(self.durationLabel, 1, 0)
        messageLayout.addWidget(self.durationSpinBox, 1, 1)
        messageLayout.addWidget(self.durationWarningLabel, 1, 2, 1, 3)
        messageLayout.addWidget(self.titleLabel, 2, 0)
        messageLayout.addWidget(self.titleEdit, 2, 1, 1, 4)
        messageLayout.addWidget(self.bodyLabel, 3, 0)
        messageLayout.addWidget(self.bodyEdit, 3, 1, 2, 4)
        messageLayout.addWidget(self.showMessageButton, 5, 4)
        messageLayout.setColumnStretch(3, 1)
        messageLayout.setRowStretch(4, 1)
        self.messageGroupBox.setLayout(messageLayout)

    def createActions(self):
        self.minimizeAction = QAction("Minimize", self)
        self.minimizeAction.triggered.connect(self.hide)

        self.maximizeAction = QAction("Maximize", self)
        self.maximizeAction.triggered.connect(self.showMaximized)

        self.restoreAction = QAction("Restore", self)
        self.restoreAction.triggered.connect(self.showNormal)

        self.quitAction = QAction("Quit", self)
        self.quitAction.triggered.connect(qApp.quit)

    def createTrayIcon(self):
        self.trayIconMenu = QMenu(self)
        self.trayIconMenu.addAction(self.minimizeAction)
        self.trayIconMenu.addAction(self.maximizeAction)
        self.trayIconMenu.addAction(self.restoreAction)
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.quitAction)

        self.trayIcon = QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
Ejemplo n.º 4
0
class Chrono(QMainWindow):
    def __init__(self, parent=None):
        super(Chrono, self).__init__(parent)

        self.createMenus()
        self.createSystemTrayIcon()

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.tick)
        self.isRunning = False
        self.refresh_rate = 100  # ms

        self.progressBar = QProgressBar()
        self.progressBar.setValue(0)
        self.begin_time = self.end_time = 0

        self.label = QLabel(" ")
        self.button = QPushButton()
        self.button.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
        self.end_delay = self.begin_delay = 0

        bottomLayout = QHBoxLayout()
        bottomLayout.addWidget(self.progressBar)
        bottomLayout.addWidget(self.button)
        self.button.clicked.connect(self.pause)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.label)
        mainLayout.addLayout(bottomLayout)
        centralWidget = QWidget()
        centralWidget.setLayout(mainLayout)
        self.setCentralWidget(centralWidget)

        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)

        self.notification = self.notification_popup = self.notification_tray = self.notification_sound = True
        self.notification_soundfile = os.path.dirname(
            sys.argv[0]) + '/notification.mp3'  # os.path.dirname(__file__) +

        self.setWindowTitle(TITLE)
        self.resize(400, self.sizeHint().height())
        self.setFixedHeight(self.sizeHint().height())

    def createMenus(self):
        menus = QMenuBar()
        fileMenu = menus.addMenu("&Fichier")
        file_newMenu = fileMenu.addMenu(
            self.style().standardIcon(QStyle.SP_FileIcon), "Nouveau")
        file_newMenu.addAction("Date", self.createDateDialog, 'CTRL+D')
        file_newMenu.addAction("Durée", self.createDurationDialog, 'CTRL+N')
        fileMenu.addSeparator()
        fileMenu.addAction(self.style().standardIcon(QStyle.SP_BrowserStop),
                           "Quitter", sys.exit, 'CTRL+Q')

        optionMenu = menus.addMenu("&Options")
        optionMenu.addAction(
            self.style().standardIcon(QStyle.SP_MessageBoxInformation),
            "Évènements", self.createNotificationPopup, 'CTRL+O')
        optionMenu.addAction(
            QAction("Rester au premier plan",
                    optionMenu,
                    triggered=self.stayOnTop,
                    checkable=True))
        aideMenu = menus.addMenu("&Aide")
        aideMenu.addAction(
            self.style().standardIcon(QStyle.SP_DialogHelpButton),
            "À propos", lambda: QMessageBox.information(
                self, "À propos", TITLE + " " + str(VERSION)), 'CTRL+H')
        aideMenu.addSeparator()
        aideMenu.addAction(
            self.style().standardIcon(QStyle.SP_TitleBarMenuButton),
            "À propos de Qt", QApplication.aboutQt, 'CTRL+A')

        self.setMenuBar(menus)

    def createSystemTrayIcon(self):
        self.tray = QSystemTrayIcon()
        self.tray.setIcon(QIcon(os.path.dirname(sys.argv[0]) +
                                '/icon.svg'))  # os.path.dirname(__file__) +
        self.tray.setToolTip(TITLE)
        self.tray.show()

        systemTrayMenu = QMenu()
        pauseAction = QAction(self.style().standardIcon(QStyle.SP_MediaPause),
                              "Pause / Reprendre", systemTrayMenu)
        pauseAction.triggered.connect(self.pause)

        systemTrayMenu.addAction(pauseAction)

        systemTrayMenu.addSeparator()
        systemTrayMenu.addAction(
            self.style().standardIcon(QStyle.SP_BrowserStop), "Quitter",
            sys.exit)
        self.tray.setContextMenu(systemTrayMenu)
        self.tray.activated.connect(self.show)

    def stayOnTop(self):
        self.setWindowFlags(self.windowFlags() ^ Qt.WindowStaysOnTopHint)
        # self.windowFlags() | Qt.CustomizeWindowHint | Qt.Window | Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint)  # Qt.Dialog | Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint)
        self.show()

    def createNotificationPopup(self):
        popup = QDialog(self)
        popup.setFixedSize(popup.sizeHint().height(), popup.sizeHint().width())
        popup.setWindowTitle("Évènements")
        innerLayout = QVBoxLayout()

        GroupBox = QGroupBox("Activer les notifications")
        GroupBox.setCheckable(True)
        GroupBox.setChecked(self.notification)

        checkBox_popup = QCheckBox("Afficher une popup")
        checkBox_notification = QCheckBox("Afficher une notification")
        checkBox_sound = QCheckBox("Jouer un son")

        if self.notification_popup:
            checkBox_popup.setCheckState(Qt.Checked)
        if self.notification_tray:
            checkBox_notification.setCheckState(Qt.Checked)
        if self.notification_sound:
            checkBox_sound.setCheckState(Qt.Checked)

        innerLayout.addWidget(checkBox_popup)
        innerLayout.addWidget(checkBox_notification)
        innerLayout.addWidget(checkBox_sound)
        innerLayout.addStretch(1)
        GroupBox.setLayout(innerLayout)

        button = QPushButton("Ok")
        button.clicked.connect(lambda: self.changeNotificationSettings(
            popup, GroupBox, checkBox_popup, checkBox_notification,
            checkBox_sound))

        outerLayout = QVBoxLayout()
        outerLayout.addWidget(GroupBox)
        outerLayout.addWidget(button)
        popup.setLayout(outerLayout)

        popup.exec_()

    def changeNotificationSettings(self, popup, GroupBox, checkBox_popup,
                                   checkBox_notification, checkBox_sound):
        self.notification, self.notification_popup, self.notification_tray, self.notification_sound = GroupBox.isChecked(
        ), checkBox_popup.isChecked(), checkBox_notification.isChecked(
        ), checkBox_sound.isChecked()
        if not any([
                self.notification_popup, self.notification_tray,
                self.notification_sound
        ]):
            self.notification = False
        popup.close()

    def createDateDialog(self):
        popup = QDialog(self)
        popup.setFixedSize(270, 60)
        popup.setWindowTitle("Nouvelle date")
        layout = QHBoxLayout()

        prefix = QLabel("Heure cible: ")
        layout.addWidget(prefix)

        qline = QTimeEdit()
        qline.setDisplayFormat("hh:mm:ss")
        qline.setTime(QTime.currentTime())
        layout.addWidget(qline)

        button = QPushButton("Ok")
        button.clicked.connect(lambda: self.createDate(popup,
                                                       qline.time().hour(),
                                                       qline.time().minute(),
                                                       qline.time().second()))

        layout.addWidget(button)

        popup.setLayout(layout)
        popup.exec_()

    def createDurationDialog(self):
        popup = QDialog(self)
        popup.setFixedSize(150, 150)
        popup.setWindowTitle("Nouvelle durée")
        layout = QVBoxLayout()

        hourLayout = QHBoxLayout()
        hourLabel = QLabel("Heures:")
        hourSpin = QSpinBox()
        hourLayout.addWidget(hourLabel)
        hourLayout.addWidget(hourSpin)

        minuteLayout = QHBoxLayout()
        minuteLabel = QLabel("Minutes:")
        minuteSpin = QSpinBox()
        minuteLayout.addWidget(minuteLabel)
        minuteLayout.addWidget(minuteSpin)

        secondLayout = QHBoxLayout()
        secondLabel = QLabel("Secondes:")
        secondSpin = QSpinBox()
        secondLayout.addWidget(secondLabel)
        secondLayout.addWidget(secondSpin)

        layout.addLayout(hourLayout)
        layout.addLayout(minuteLayout)
        layout.addLayout(secondLayout)

        button = QPushButton("Ok")
        button.clicked.connect(lambda: self.createDuration(
            popup, hourSpin.value(), minuteSpin.value(), secondSpin.value()))
        layout.addWidget(button)

        popup.setLayout(layout)
        popup.exec_()

    def createDuration(self, popup: QDialog, hours: int, minutes: int,
                       seconds: int):
        popup.close()

        self.begin_time = datetime.timestamp(datetime.now())
        self.end_time = self.begin_time + seconds + minutes * 60 + hours * 3600
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(0)

        self.isRunning = True
        self.timer.stop()
        self.timer.start(self.refresh_rate)

    def createDate(self, popup: QDialog, hours: int, minutes: int,
                   seconds: int):
        popup.close()

        self.begin_time = datetime.timestamp(datetime.now())

        now = datetime.now().time()
        target = time(hours, minutes, seconds)
        now_delta = timedelta(hours=now.hour,
                              minutes=now.minute,
                              seconds=now.second)
        target_delta = timedelta(hours=target.hour,
                                 minutes=target.minute,
                                 seconds=target.second)

        if target_delta == now_delta:
            self.end_time = self.begin_time + 60 * 60 * 24
        else:
            d = target_delta - now_delta
            self.end_time = self.begin_time + d.seconds

        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(0)

        self.isRunning = True
        self.timer.stop()
        self.timer.start(self.refresh_rate)

    def tick(self):
        self.progressBar.setValue(
            100 * (datetime.timestamp(datetime.now()) - self.begin_time) /
            (self.end_time - self.begin_time))

        seconds = int(
            ceil(self.end_time - datetime.timestamp(datetime.now())) % 60)
        minutes = int(
            ceil(self.end_time - datetime.timestamp(datetime.now())) / 60 % 60)
        hours = int(
            ceil(self.end_time - datetime.timestamp(datetime.now())) / 3600)

        self.label.setText(f'{hours:02}:{minutes:02}:{seconds:02}')
        self.setWindowTitle(f'{TITLE} - {hours:02}:{minutes:02}:{seconds:02}')
        self.tray.setToolTip(f'{hours:02}:{minutes:02}:{seconds:02}')

        if datetime.timestamp(datetime.now()) >= self.end_time:
            self.isRunning = False
            self.timer.stop()
            self.progressBar.setRange(0, 0)
            self.show()
            self.notify()

    def notify(self):
        if not self.notification:
            return
        if self.notification_tray:
            self.tray.showMessage(
                "Finished", "Le décompte est terminé",
                self.style().standardIcon(QStyle.SP_MessageBoxInformation))
        if self.notification_sound:
            test = QMediaPlayer()
            test.setMedia(QUrl.fromLocalFile(self.notification_soundfile))
            test.play()
        if self.notification_popup:
            QMessageBox.information(self, "Finished",
                                    "Le décompte est terminé")

    def pause(self):
        if not self.isRunning:
            return
        self.progressBar.setDisabled(self.timer.isActive())
        if self.timer.isActive():
            self.end_delay = self.end_time - datetime.timestamp(datetime.now())
            self.begin_delay = datetime.timestamp(
                datetime.now()) - self.begin_time
            print(self.begin_time)
            print(self.end_time)
            print(self.end_delay)
            self.statusBar.showMessage("Pause")
            self.tray.setToolTip(self.tray.toolTip() + ' - Pause')
            self.timer.stop()
            self.button.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        else:
            self.begin_time = datetime.timestamp(
                datetime.now()) - self.begin_delay
            self.end_time = datetime.timestamp(datetime.now()) + self.end_delay
            print(self.begin_time)
            print(self.end_time)
            self.statusBar.clearMessage()
            self.timer.start()
            self.button.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))

    # Override
    def closeEvent(self, event):
        self.hide()
        event.ignore()
Ejemplo n.º 5
0
class GUI:
    def __init__(self, root):
        self.root = root
        self.app = QApplication([])
        self.icons = {
            "timelapse": QIcon(resource_path('icons/timelapse.png')),
            "sync": QIcon(resource_path('icons/sync.png')),
            "sync_disabled": QIcon(resource_path('icons/sync_disabled.png')),
            "logo": QIcon(resource_path('icons/logo.png')),
            "settings": QIcon(resource_path('icons/settings.png')),
            "github": QIcon(resource_path('icons/github.png'))
        }

        self.main_window = MainWindow(self)
        self.offset_window = None
        self.settings_window = None
        self.messages = [[], []]
        self.section_labels = [
            self.main_window.ui.right_status,
            self.main_window.ui.right_status_2
        ]

        menu = QMenu('FS Time Sync')
        menu.setStyleSheet("""
        QMenu {
            background-color: #151515;
            color: #ffffff;
        }
        QMenu::item {
            padding: 5px 10px 5px 10px;
        }
        QMenu::item:selected {
            background-color: #ffffff;
            color: #151515;
        }
        """)
        self.tray_actions = {}
        self.tray_actions["sync_now"] = menu.addAction("Sync Now")
        self.tray_actions["sync_now"].triggered.connect(
            lambda: self.root.sync_sim(force=True))
        self.tray_actions["hide_show"] = menu.addAction("Hide")
        self.tray_actions["hide_show"].triggered.connect(self.hide)
        self.tray_actions["exit"] = menu.addAction("Exit")
        self.tray_actions["exit"].triggered.connect(self.exit)

        self.tray = QSystemTrayIcon()
        self.tray.setIcon(self.icons['logo'])
        self.tray.setToolTip("FS Time Sync")
        self.tray.setContextMenu(menu)
        self.tray.activated.connect(self.trayActivated)
        self.tray.show()

    def main_window_act(self, func, *args, **kwargs):
        self.main_window.act.emit([func, args, kwargs])

    def hide(self):
        self.tray_actions["hide_show"].setText("Show")
        self.tray_actions["hide_show"].triggered.connect(self.show)
        if self.offset_window:
            self.offset_window.close()
        self.main_window.saveState()
        self.main_window.hide()

    def trayActivated(self, reason):
        if reason == self.tray.ActivationReason.Trigger:
            self.show()

    def single_instance_triggered(self):
        self.tray.showMessage("FS Time Sync",
                              "FS Time Sync is already running.")
        self.show()

    def show(self):
        self.tray_actions["hide_show"].setText("Hide")
        self.tray_actions["hide_show"].triggered.connect(self.hide)
        self.main_window.show()
        # Brings window forward, but doesn't force it to stay active.
        self.main_window.setWindowState(Qt.WindowActive)
        self.main_window.setWindowState(Qt.WindowNoState)

    def exit(self):
        self.app.quit()

    def start(self):
        # Add single instance trigger.
        self.root.si.add_trigger(self.single_instance_triggered)

        # Settings are triggered here.
        if not self.root.settings.get(
                "startup", "tray"):  # Start regularly or as tray icon
            self.main_window.show()
        else:
            self.tray.showMessage("FS Time Sync",
                                  "FS Time Sync Started in Tray.")
            self.tray_actions["hide_show"].setText("Show")
            self.tray_actions["hide_show"].triggered.connect(self.show)

        if self.root.settings.get("startup", "auto_sync"):
            self.root.enable_live_sync()

        self.app.exec_()

    def add_message(self, section, code, msg):
        for message in self.messages[section]:
            if message["code"] == code:
                message["msg"] = msg
                break
        else:
            self.messages[section].append({"code": code, "msg": msg})

        self.main_window.act.emit([self.section_labels[section].setText, msg])

    def remove_message(self, section, code):
        for message in self.messages[section]:
            if message["code"] == code:
                self.messages[section].remove(message)
                break
        else:
            return  # No action just return

        if len(self.messages[section]) > 0:
            print(self.messages[section])
            self.main_window.act.emit([
                self.section_labels[section].setText,
                self.messages[section][-1]["msg"]
            ])
        else:
            self.main_window.act.emit(
                [self.section_labels[section].setText, ""])
Ejemplo n.º 6
0
class MainWindow(QObject):
    def __init__(self, parent=None):
        """Main window, holding all user interface including.

        Args:
          parent: parent class of main window
        Returns:
          None
        Raises:
          None
        """
        super(MainWindow, self).__init__()

        self._window = None
        self._old_pos = None

        self._tray = QSystemTrayIcon(self._window)
        if self._tray.isSystemTrayAvailable():
            self._tray.setIcon(QIcon('./media/dekban.png'))
        else:
            self._tray = None

        self.setup_ui()

    @property
    def window(self):
        """The main window object"""
        return self._window

    def setup_ui(self):
        loader = QUiLoader()
        file = QFile('./main_window.ui')
        file.open(QFile.ReadOnly)
        self._window = loader.load(file)
        file.close()

        self._window.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
        self._window.installEventFilter(self)

        self.center()
        self._old_pos = self._window.pos()

        self.set_title()
        self.set_buttons()
        self.set_edits()
        self.set_icon_combo()
        self.set_tray()

        self._tray.show()

    def set_title(self):
        """Setup label"""
        self._window.title.setText('Welcome to PySide2 Tutorial')

        font = QFont("Arial", 20, QFont.Black)

        self._window.title.setFont(font)
        # set widget size (x, y, width, height)
        self._window.title.setGeometry(0, 0, 600, 30)
        # set alignment
        self._window.title.setAlignment(Qt.AlignBottom | Qt.AlignCenter)

    def set_buttons(self):
        """Setup buttons"""
        self._window.send_btn.setText('Send Msg')
        self._window.exit_btn.setText('Exit')

        self._window.send_btn.setIcon(QIcon('./media/import.svg'))

        self._window.send_btn.clicked.connect(self.send_message)
        self._window.exit_btn.clicked.connect(self.exit)

    def set_edits(self):
        """Setup line edit and text edit"""
        self._window.title_line.setPlaceholderText('Input Msg Title')
        self._window.msg_edit.setPlaceholderText('Input Msg')

    def set_icon_combo(self):
        """Setup options in icon select combobox."""
        self._window.icon_combo.addItem(QIcon('./media/font.png'), 'font')
        self._window.icon_combo.addItem(QIcon('./media/paint.png'), 'paint')
        self._window.icon_combo.addItem(QIcon('./media/dekban.png'), 'default')
        self._window.icon_combo.currentIndexChanged.connect(self.set_icon)

    def set_tray(self):
        menu = QMenu(self._window)
        action_show = menu.addAction("Show/Hide")
        action_show.triggered.connect(
            lambda: self._window.hide()
            if self._window.isVisible() else self._window.show())
        action_quit = menu.addAction("Quit")
        action_quit.triggered.connect(self._window.close)

        self._tray.setContextMenu(menu)

    def eventFilter(self, obj, event):
        if obj is self._window:
            if event.type() == QtCore.QEvent.MouseButtonPress:
                self.mouse_press_event(event)
            elif event.type() == QtCore.QEvent.MouseMove:
                self.mouse_move_event(event)
        return super(MainWindow, self).eventFilter(obj, event)

    def center(self):
        qr = self._window.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self._window.move(qr.topLeft())

    def mouse_press_event(self, event):
        self._old_pos = event.globalPos()

    def mouse_move_event(self, event):
        delta_x = int(event.globalPos().x()) - self._old_pos.x()
        delta_y = int(event.globalPos().y()) - self._old_pos.y()
        self._window.move(self._window.x() + delta_x,
                          self._window.y() + delta_y)
        self._old_pos = event.globalPos()

    @QtCore.Slot(int)
    def set_icon(self, index):
        icon = self._window.icon_combo.itemIcon(index)
        self._tray.setIcon(icon)

    @QtCore.Slot()
    def send_message(self):
        title = self._window.title_line.text()
        msg = self._window.msg_edit.toPlainText()

        self._tray.showMessage(title, msg,
                               QIcon('./media/dekban.png'))

    @QtCore.Slot()
    def exit(self):
        self._window.close()
class Indicator():
    APP_NAME = 'FortiVPN Quick Tray'

    def __init__(self):
        self.app = QApplication([])
        self.app.setQuitOnLastWindowClosed(False)
        self.indicator = QSystemTrayIcon()
        self.indicator.setIcon(QIcon(self._get_file('./icons/icon.png')))
        self.indicator.setContextMenu(self._build_menu())
        self.indicator.setVisible(True)
        self.indicator.setToolTip('OFF')

        self.indicator.activated.connect(self._click_indicator)

        self.logs_dialog = QTextEdit()
        self.logs_dialog.setWindowTitle(f'{self.APP_NAME} - Logs')
        self.logs_dialog.setFixedSize(440, 440)
        self.logs_dialog.setReadOnly(True)
        self.logs_dialog.setWindowIcon(
            QIcon(self._get_file('./icons/icon.png')))

        self.vpn_config = '/etc/openfortivpn/config'
        self.vpn_process = None
        self.vpn_logs_file = NamedTemporaryFile(delete=False)

        self.vpn_thread = VPNThread(self.vpn_logs_file)
        self.vpn_thread.status.connect(self._update_vpn_status)
        self.vpn_thread.log.connect(self.logs_dialog.append)

        self.app_update_thread = AppUpdateThread(self._get_file('./version'))
        self.app_update_thread.update_available.connect(
            self._show_update_notification)
        self.app_update_thread.start()

    def run(self):
        self.app.exec_()
        sys.exit()

    def _build_menu(self):
        menu = QMenu()

        self.connect_action = QAction('Connect')
        self.disconnect_action = QAction('Disconnect')
        self.config_action = QAction('Config')
        self.logs_action = QAction('Logs')
        self.exit_action = QAction('Exit')

        self.disconnect_action.setDisabled(True)

        self.connect_action.triggered.connect(self._click_connect)
        self.disconnect_action.triggered.connect(self._click_disconnect)
        self.config_action.triggered.connect(self._click_config)
        self.logs_action.triggered.connect(self._click_logs)
        self.exit_action.triggered.connect(self._click_exit)

        menu.addAction(self.connect_action)
        menu.addAction(self.disconnect_action)
        menu.addSeparator()
        menu.addAction(self.config_action)
        menu.addAction(self.logs_action)
        menu.addSeparator()
        menu.addAction(self.exit_action)

        return menu

    def _click_connect(self):
        self.indicator.setIcon(QIcon(self._get_file('./icons/try.png')))
        self.indicator.setToolTip('TRYING')

        self.connect_action.setDisabled(True)
        self.config_action.setDisabled(True)

        with open(self.vpn_logs_file.name, 'w+b') as f:
            try:
                self.vpn_process = Popen(split('pkexec openfortivpn -c ' +
                                               self.vpn_config),
                                         stdin=PIPE,
                                         stdout=f,
                                         stderr=f)
                self.vpn_process.communicate(timeout=1)
            except TimeoutExpired:
                pass

        self.vpn_thread.start()

    def _click_disconnect(self):
        try:
            run(split('pkexec kill ' + str(self.vpn_process.pid)))
        except ChildProcessError:
            pass

    def _click_config(self):
        config_file, _ = QFileDialog.getOpenFileName(
            caption='Select config file',
            dir='/',
            filter='All files (*)',
            options=QFileDialog.DontUseNativeDialog)

        if config_file:
            self.vpn_config = config_file

    def _click_logs(self):
        if not self.vpn_thread.isRunning():
            with open(self.vpn_logs_file.name) as logs:
                self.logs_dialog.setPlainText(logs.read())

        self.logs_dialog.show()

    def _click_exit(self):
        if self.indicator.toolTip() == 'ON':
            _ = QMessageBox.warning(
                None, self.APP_NAME,
                'VPN is still ON. Please Disconnect first before exiting')

            return

        if self.vpn_logs_file.name:
            remove_log_file(self.vpn_logs_file.name)

        self.app.quit()

    def _get_file(self, file_path):
        try:
            base = sys._MEIPASS
        except Exception:
            base = path.abspath('.')

        return path.join(base, file_path)

    def _click_indicator(self, event):
        if event == QSystemTrayIcon.ActivationReason.Trigger:
            self._click_logs()

    def _update_vpn_status(self, message):
        if message == 'ERR':
            self.indicator.setIcon(QIcon(self._get_file('./icons/err.png')))
            self.indicator.setToolTip('ERROR')
            self.connect_action.setDisabled(False)
            self.config_action.setDisabled(False)
            pass

        if message == 'ON':
            self.indicator.setIcon(QIcon(self._get_file('./icons/on.png')))
            self.indicator.setToolTip('ON')
            self.disconnect_action.setDisabled(False)
            pass

        if message == 'OFF':
            self.indicator.setIcon(QIcon(self._get_file('./icons/icon.png')))
            self.indicator.setToolTip('OFF')
            self.disconnect_action.setDisabled(True)
            self.connect_action.setDisabled(False)
            self.config_action.setDisabled(False)
            pass

    def _show_update_notification(self, flag):
        if flag and self.indicator.supportsMessages:
            self.indicator.showMessage(
                self.APP_NAME, 'There is a new update available',
                QIcon(self._get_file('./icons/icon.png')))
Ejemplo n.º 8
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.setWindowTitle("ctpbee桌面端")
        # self.setWindowFlag(Qt.FramelessWindowHint)  # 去边框 可能会导致闪屏异常
        self.setStyleSheet(qss)
        self.animation_show()
        #
        G.mainwindow = self
        self.exit_ = False
        self._page_history = []
        self._page_maxsize = 10
        self.job = Job()
        self.kline_job = KInterfaceObject()
        self.record_work = RecordWorker()
        self.bee_ext = None
        self.tray_init()
        self.shortcut_init()
        ##
        self.status_msg = QLabel("实时信息")
        self.market_msg = QLabel("最新行情")
        self.statusbar.addPermanentWidget(self.status_msg, stretch=5)
        self.statusbar.addPermanentWidget(self.market_msg, stretch=5)
        # btn
        self.pre_page_btn.clicked.connect(self.pre_page_slot)
        self.home_btn.clicked.connect(self.home_handle)
        self.market_btn.clicked.connect(self.market_handle)
        self.order_btn.clicked.connect(self.order_handle)
        self.strategy_btn.clicked.connect(self.strategy_handle)
        self.setting_btn.clicked.connect(self.config_handle)
        self.log_btn.clicked.connect(self.log_handle)
        self.order_btn.clicked.connect(self.order_handle)
        self.backtrack_btn.clicked.connect(self.backtrack_handle)
        self.kline_btn.clicked.connect(self.kline_handle)
        #
        # self.menuBar.triggered.connect(self.menu_triggered)
        # widgets
        self.map_ = []
        self.home_widget = None
        self.strategy_widget = None
        self.account_widget = None
        self.market_widget = None
        self.order_widget = None
        self.kline_widget = None
        self.log_dialog = None
        self.cfg_dialog = None
        self.backtrack_widget = None

    def sign_in_success(self):
        self.bee_ext = CtpbeeApi('default_setting', current_app)
        self.bee_ext.map[EVENT_ACCOUNT] = self.on_account
        self.bee_ext.map[EVENT_CONTRACT] = self.on_contract
        self.bee_ext.map[EVENT_BAR] = self.on_bar
        self.bee_ext.map[EVENT_ORDER] = self.on_order
        self.bee_ext.map[EVENT_POSITION] = self.on_position
        self.bee_ext.map[EVENT_TICK] = self.on_tick
        self.bee_ext.map[EVENT_SHARED] = self.on_shared
        self.bee_ext.map[EVENT_TRADE] = self.on_trade
        self.bee_ext.map[EVENT_TIMER] = self.on_realtime
        #
        contracts = {
            contract.local_symbol: contract.name
            for contract in self.bee_ext.app.recorder.get_all_contracts()
        }
        G.all_contracts = contracts
        self.home_handle()

    def menu_triggered(self, q):
        q = q.text()
        if q == "退出应用":
            self.quit()

    def animation_show(self):
        self.animation = QPropertyAnimation(self, b'windowOpacity')
        self.animation.stop()
        self.animation.setDuration(500)
        self.animation.setStartValue(0)
        self.animation.setEndValue(1)
        self.animation.start()

    @property
    def page_history(self):
        return self._page_history

    @page_history.setter
    def page_history(self, val):
        if len(self._page_history) == self._page_maxsize:  # 达到最大容量
            self._page_history.pop(0)  # 弹出第一项
        self._page_history.append(val)

    def pre_page_slot(self):
        try:
            i = self.page_history.pop()
            while i == self.stackedWidget.currentIndex():
                i = self.page_history.pop()
            self.stackedWidget.setCurrentIndex(i)
        except IndexError:
            TipDialog("到底啦~")

    def shortcut_init(self):
        sc = G.config.SHORTCUT
        for name, sho in sc.items():
            if sho == '--':
                continue
            temp = QShortcut(QKeySequence(self.tr(sho)), self)
            temp.activated.connect(getattr(self, f"{name}_handle"))
            setattr(self, f"{name}_sc", temp)

    def update_shortcut(self):
        sc = G.config.SHORTCUT
        for name, sho in sc.items():
            getattr(self, f"{name}_sc").setKey(QKeySequence(self.tr(sho)))

    def page_map(self, w):
        name = w.__class__.__name__
        if name not in self.map_:
            self.map_.append(name)
        i = self.map_.index(name)
        self.page_history = i
        return i

    def home_handle(self):
        if self.home_widget is None:
            self.home_widget = HomeWidget(self)
            self.stackedWidget.addWidget(self.home_widget)
        self.stackedWidget.setCurrentIndex(self.page_map(self.home_widget))

    def strategy_handle(self):
        if self.strategy_widget is None:
            self.strategy_widget = StrategyWidget(self)
            self.stackedWidget.addWidget(self.strategy_widget)
        self.stackedWidget.setCurrentIndex(self.page_map(self.strategy_widget))

    def backtrack_handle(self):
        if self.backtrack_widget is None:
            self.backtrack_widget = BacktrackWidget(self)
            self.stackedWidget.addWidget(self.backtrack_widget)
        self.stackedWidget.setCurrentIndex(self.page_map(
            self.backtrack_widget))

    def market_handle(self):
        if self.market_widget is None:
            self.market_widget = MarketWidget(self)
            self.stackedWidget.addWidget(self.market_widget)
        self.stackedWidget.setCurrentIndex(self.page_map(self.market_widget))
        G.current_page = "market"

    def kline_handle(self):
        if self.kline_widget is None:
            self.kline_widget = KlineWidget(self)
            self.stackedWidget.addWidget(self.kline_widget)
        self.stackedWidget.setCurrentIndex(self.page_map(self.kline_widget))
        if G.choice_local_symbol:
            self.kline_widget.symbol_list.setCurrentText(G.choice_local_symbol)
        self.kline_widget.k_line_reload()

    def order_handle(self):
        if self.order_widget is None:
            self.order_widget = OrderWidget(self)
        self.order_widget.show()
        self.order_widget.raise_()

    def config_handle(self):
        if self.cfg_dialog is None:
            self.cfg_dialog = ConfigDialog(self)
        self.cfg_dialog.show()
        self.cfg_dialog.raise_()

    def log_handle(self):
        if self.log_dialog is None:
            self.log_dialog = LogDialog(self)
        self.log_dialog.show()
        self.log_dialog.raise_()

    def on_account(self, ext, account: AccountData) -> None:
        account = account._to_dict()
        G.account = account
        self.job.account_signal.emit(account)

    def on_contract(self, ext, contract: ContractData):
        pass

    def on_bar(self, ext, bar: BarData) -> None:
        """ vue kline"""
        # timestamp = round(bar.datetime.timestamp() * 1000)
        # info = [timestamp, bar.open_price, bar.high_price, bar.low_price,
        #         bar.close_price, bar.volume]
        """ echarts kline """
        timestamp = bar.datetime.strftime("%Y/%m/%d %H:%M:%S")
        info = [
            timestamp, bar.open_price, bar.close_price, bar.low_price,
            bar.high_price, bar.volume
        ]
        #
        if bar.local_symbol == G.choice_local_symbol:
            data = {bar.local_symbol: info}
            self.kline_job.qt_to_js.emit(json.dumps(data))
        # 存入文件
        self.record_work.record_sig.emit(bar.local_symbol, info)

    def on_order(self, ext, order: OrderData) -> None:
        active_orders = []
        for order1 in self.bee_ext.app.recorder.get_all_active_orders():
            o1 = order1._to_dict()
            active_orders.append(o1)
        self.job.order_activate_signal.emit(active_orders)

        orders = []
        for order2 in self.bee_ext.app.recorder.get_all_orders():
            o2 = order2._to_dict()
            orders.append(o2)
        self.job.order_order_signal.emit(orders)

    def on_realtime(*args):
        self = args[0]
        all_positions = self.bee_ext.app.recorder.get_all_positions()
        self.job.order_position_signal.emit(all_positions)

    def on_position(self, ext, position: PositionData) -> None:
        pass

    def on_tick(self, ext, tick: TickData) -> None:
        self.market_msg.setText(f"最新行情:{tick.name}   {tick.last_price}")
        tick = tick._to_dict()
        local_symbol = tick['local_symbol']
        G.ticks[local_symbol] = tick
        if G.current_page == "market":
            self.job.market_signal.emit(tick)
        self.job.kline_tick_signal.emit(tick)

    def on_shared(self, ext, shared: SharedData) -> None:
        pass

    def on_trade(self, ext, trade: TradeData) -> None:
        trades = []
        for trade in self.bee_ext.app.recorder.get_all_trades():
            t = trade._to_dict()
            trades.append(t)
        self.job.order_trade_signal.emit(trades)

    def on_init(self, ext, init):
        pass

    def tray_init(self):
        icon = QIcon(":menu/images/bee_temp_grey.png")
        menu = QMenu()
        openAction = menu.addAction("🍯 界面")
        settingAction = menu.addAction("⚙ 设置")
        exitAction = menu.addAction("❎ 退出")
        settingAction.triggered.connect(self.config_handle)
        openAction.triggered.connect(self.show)
        exitAction.triggered.connect(self.quit)
        self.tray = QSystemTrayIcon()
        self.tray.setIcon(icon)
        self.tray.setContextMenu(menu)
        self.tray.activated.connect(self.iconActivated)
        self.tray.show()
        self.tray.setToolTip("ctpbee桌面端")

    def quit(self):
        self.exit_ = True
        self.close()

    def iconActivated(self, reason):
        if reason is QSystemTrayIcon.Trigger:
            self.show()
            self.raise_()

    def closeEvent(self, event: QCloseEvent):
        if self.exit_:
            G.pool_done = True
            self.tray.deleteLater()
            try:
                for k, v in current_app.extensions.items():
                    current_app.suspend_extension(k)
                current_app.release()
            except:
                pass
            if self.cfg_dialog:
                self.cfg_dialog.close()
            if self.log_dialog:
                self.log_dialog.close()
            if self.order_widget:
                self.order_widget.close()
            event.accept()
        else:
            self.tray.showMessage("ctpbee", "以最小化隐藏在托盘", msecs=1)
            self.hide()
            event.ignore()
Ejemplo n.º 9
0
class Window(QWidget):
    def __init__(self, parent=None):
        super(Window, self).__init__()
        self.path = None
        self.settings()
        self.create_widgets()
        self.create_layout()

    def settings(self):
        self.resize(300, 120)
        self.setWindowTitle('Mp3 Downloader')

    def create_widgets(self):
        self.edit_url = QLineEdit()
        self.edit_name = QLineEdit()
        self.btn_select_path = QPushButton('Select path', self)
        self.btn_select_path.clicked.connect(self.select_path)
        self.btn_download = QPushButton('Download mp3', self)
        self.btn_download.clicked.connect(self.download)

    def create_layout(self):
        self.layout = QFormLayout()
        self.layout.addRow('Nome:', self.edit_name)
        self.layout.addRow('Url:', self.edit_url)
        self.layout.addRow('Selecionar destino:', self.btn_select_path)
        self.layout.addRow(self.btn_download)
        self.setLayout(self.layout)

    def select_path(self):
        self.path = QFileDialog.getExistingDirectory(self, 'Selecionar Pasta')

    def download(self):
        if self.verify_fields():
            self.manage_interface(False)
            self.thread_qt()

    def verify_fields(self):
        if self.path is None:
            return False
        else:
            strings = [self.edit_url, self.edit_name.text(), self.path]
            regex_validate = QRegExp('*.mp3')
            regex_validate.setPatternSyntax(QRegExp.Wildcard)
            emptys = 0
            for string in strings:
                if len(string.split()) == 0:
                    emptys += 1
                if emptys == 0 and regex_validate.exactMatch(
                        self.edit_url.text()):
                    return True

    def thread_qt(self):
        url = self.edit_url.text()
        name = self.edit_name.text()
        path = self.edit_path.text()
        self.thre = DownloaderMusic()
        self.thre.finished.connect(self.downfin)
        self.thre.start()

    def manage_interface(self, state):
        self.btn_download.setEnabled(state)
        self.edit_name.setEnabled(state)
        self.edit_url.setEnabled(state)
        self.btn_select_path

    def downfin(self):
        self.notify_icon = QSystemTrayIcon()
        self.notify_icon.setVisible(True)
        self.notify_icon.showMessage(
            'Download Finalizado',
            u'O download da sua música foi realizado com sucesso.',
            QSystemTrayIcon.Information, 3000)
        self.manage_interface(True)
Ejemplo n.º 10
0
class UI:
    """
    WSL2 端口自动转发
    """
    def __init__(self, qt_application=None):
        self.qt_application = qt_application
        # 实例化配置管理类
        self.settings_manage = SettingsManage()
        self.__setting = self.settings_manage.get()

        # 实例化windows命令处理类
        self.wsl2 = WinCmd()

        # 初始化启动脚本
        if not isfile(self.wsl2.WSL_VBS_PATH):
            copyfile(self.wsl2.WSL_VBS_PATH_TEMP, self.wsl2.WSL_VBS_PATH)
        if not isfile(self.wsl2.WSL_BAT_PATH):
            self.settings_manage.save_file_content(
                self.wsl2.WSL_BAT_PATH,
                self.__setting.get('wsl_bat_content', ''))
        # 加载UI文件
        self.ui = QUiLoader().load(ResourcePath.resource_path('lib/wsl2.ui'))

        # 设置界面图标
        app_icon = QIcon(ResourcePath.resource_path("lib/logo.ico"))
        self.ui.setWindowIcon(app_icon)

        # 设置选中状态
        self.ui.auto_start_wsl.setChecked(
            self.__setting.get('auto_start_wsl', False))
        self.ui.fire_wall_open.setChecked(
            self.__setting.get('fire_wall_open', False))
        self.ui.fire_wall_close.setChecked(
            self.__setting.get('fire_wall_close', False))

        # 设置文本框的值
        self.ui.port_text.appendPlainText('\n'.join(
            self.__setting.get('ports', [])))
        self.ui.bat_text.appendPlainText(self.wsl2.get_bat_script())

        # 按钮监听
        self.ui.get_wsl2_ip.clicked.connect(self.__get_wsl2_ip)
        self.ui.port_add.clicked.connect(self.__port_add)
        self.ui.port_del.clicked.connect(self.__port_del)
        self.ui.port_info.clicked.connect(self.__port_info)
        self.ui.wsl_l_v.clicked.connect(self.__wsl_l_v)
        self.ui.port_reset.clicked.connect(self.__port_reset)
        self.ui.end_wsl.clicked.connect(self.__end_wsl)
        self.ui.start_wsl.clicked.connect(self.__start_wsl)
        self.ui.start_wsl_all.clicked.connect(self.start_wsl_all)
        self.ui.save_settings.clicked.connect(self.__save_settings)
        self.ui.save_settings_ports.clicked.connect(self.__save_settings)

        # 设置系统托盘图标的菜单
        tp_icon = QIcon(ResourcePath.resource_path("lib/logo.ico"))
        self.tp = QSystemTrayIcon(self.ui)
        self.tp.setIcon(tp_icon)

        self.ui_hide = QAction(icon=tp_icon,
                               text='隐藏(Hide)',
                               triggered=self.ui.hide)
        self.ui_show = QAction(icon=tp_icon,
                               text='显示(Show)',
                               triggered=self.ui.show)
        self.ui_exit = QAction(icon=tp_icon,
                               text='退出(Exit)',
                               triggered=self.__quit_app)
        self.tp_menu = QMenu()
        self.tp_menu.addAction(self.ui_hide)
        self.tp_menu.addAction(self.ui_show)
        self.tp_menu.addAction(self.ui_exit)
        self.tp.setContextMenu(self.tp_menu)
        self.tp.activated.connect(self.__tp_connect_action)
        self.tp.show()
        self.tp.showMessage('WSL2AutoPortForward', 'WSL2端口自动转发工具已启动',
                            QSystemTrayIcon.MessageIcon.Information)

    def __tp_connect_action(self, activation_reason):
        """
        监听托盘图标点击
        :param activation_reason: 点击类型
        :return:
        """
        if activation_reason == QSystemTrayIcon.ActivationReason.Trigger:
            # 左单击
            if self.ui.isHidden():
                self.ui.show()
            else:
                self.ui.hide()
        elif activation_reason == QSystemTrayIcon.ActivationReason.Context:
            # 右单击
            self.tp_menu.show()
        elif activation_reason == QSystemTrayIcon.ActivationReason.DoubleClick:
            # 双击
            self.ui.show()

    def __quit_app(self):
        """
        退出APP
        :return:
        """
        re = QMessageBox.question(self.ui, "提示", "退出系统",
                                  QMessageBox.Yes | QMessageBox.No,
                                  QMessageBox.No)
        if re == QMessageBox.Yes:
            # 关闭窗体程序
            self.qt_application.quit()
            # 在应用程序全部关闭后,TrayIcon其实还不会自动消失,
            # 直到你的鼠标移动到上面去后,才会消失,
            # 这是个问题,(如同你terminate一些带TrayIcon的应用程序时出现的状况),
            # 这种问题的解决我是通过在程序退出前将其setVisible(False)来完成的。
            self.tp.setVisible(False)

    def __wsl_l_v(self):
        """
        获取wsl信息
        :return:
        """
        wsl_l_v_txt = '  ' + self.wsl2.wsl_l_v(exec_run=True).replace(
            '\x00', '').strip()
        if not wsl_l_v_txt:
            # 未查询到wsl信息提示
            wsl_l_v_txt = '未查询到wsl信息!'
            QMessageBox.information(self.ui, '系统提示', wsl_l_v_txt)
        self.ui.wsl_l_v_text.setPlainText(wsl_l_v_txt)

    def __get_wsl2_ip(self):
        wsl2_ip_info = self.wsl2.get_wsl2_ip()
        if not wsl2_ip_info:
            # 未查询到端口转发信息提示
            QMessageBox.information(self.ui, '系统提示', '未查询到IP信息!')
        else:
            wsl2_ip_info = 'WSL2当前IP为:' + wsl2_ip_info
            self.ui.wsl_l_v_text.setPlainText(wsl2_ip_info)

    def __port_add(self):
        wsl2_ip_info = self.wsl2.get_wsl2_ip()
        if not wsl2_ip_info:
            # 未查询到端口转发信息提示
            QMessageBox.information(self.ui, '系统提示', '未查询到IP信息!')
        else:
            self.ui.result_text.clear()
            ports = self.ui.port_text.toPlainText()
            port_str = ''
            for port in ports.splitlines():
                if not port.strip():
                    continue
                self.__port_add_one(port, wsl2_ip_info)
                port_str += (',' + port if port_str else port)
            self.__fire_wall_rule_add(port_str)
            self.ui.result_text.appendPlainText('Succeed!')

    def __port_del(self, del_port=True, del_fire=True):
        self.ui.result_text.clear()
        ports = self.ui.port_text.toPlainText()
        if del_port:
            for port in ports.splitlines():
                if not port.strip():
                    continue
                self.__port_del_one(port)
        if del_fire:
            self.__fire_wall_rule_del()
        self.ui.result_text.appendPlainText('Succeed!')

    def __port_reset(self):
        port_info = self.wsl2.port_info()
        self.ui.result_text.clear()
        for port in port_info:
            self.__port_del_one(port['port'])
        self.__fire_wall_rule_del()
        self.ui.result_text.appendPlainText('Succeed!')

    def __port_info(self):
        """
        获取端口转发信息
        :return:
        """
        info_str = self.wsl2.port_info(True).strip()
        if not info_str:
            # 未查询到端口转发信息提示
            info_str = '未查询到端口转发信息!'
            QMessageBox.information(self.ui, '系统提示', info_str)
        self.ui.result_text.setPlainText(info_str)

    def __wsl2_auto_port_forward(self):
        """
        一键自动转发
        @return:
        """

        self.__port_del(del_port=False, del_fire=True)
        self.__port_add()

    def __end_wsl(self):
        """
        停止wsl
        :return:
        """
        self.start_qt_process(self.wsl2.end_wsl(exec_run=False))
        info_str = 'wsl 已全部停止'
        QMessageBox.information(self.ui, '系统提示', info_str)

    def __start_wsl(self):
        """
        启动wsl
        :return:
        """
        self.start_qt_process(self.wsl2.start_wsl(exec_run=False))

    def start_wsl_all(self):
        """
        启动wsl并转发端口
        :return:
        """
        self.__start_wsl()
        self.__wsl2_auto_port_forward()

    def __save_settings(self):
        """
        保存全部配置
        :return:
        """
        # 保存脚本
        self.__save_bat_script()

        # 保存配置信息
        self.settings_manage.set('fire_wall_open',
                                 self.ui.fire_wall_open.isChecked())
        self.settings_manage.set('fire_wall_close',
                                 self.ui.fire_wall_close.isChecked())
        self.settings_manage.set('auto_start_wsl',
                                 self.ui.auto_start_wsl.isChecked())
        self.settings_manage.set('ports',
                                 self.ui.port_text.toPlainText().splitlines())

        # 保存成功提示
        QMessageBox.information(self.ui, '系统提示', '配置保存成功!')

    def __save_bat_script(self):
        """
        保存启动脚本
        :return:
        """
        content = self.ui.bat_text.toPlainText()
        self.settings_manage.set('wsl_bat_content', content)
        self.wsl2.save_bat_script(content)

    def __fire_wall_rule_add(self, port):
        """
        添加防火墙
        :param port: 端口号,多个端口逗号隔开
        :return:
        """
        if self.ui.fire_wall_open.isChecked():
            self.start_qt_process(
                self.wsl2.fire_wall_rule_add(
                    wsl_port=port,
                    wall_type=self.wsl2.FireWallRuleIn,
                    exec_run=False))
            self.ui.result_text.appendPlainText('>>> 添加防火墙:【' +
                                                self.wsl2.FireWallRuleIn +
                                                '】...')
            self.start_qt_process(
                self.wsl2.fire_wall_rule_add(
                    wsl_port=port,
                    wall_type=self.wsl2.FireWallRuleOut,
                    exec_run=False))
            self.ui.result_text.appendPlainText('>>> 添加防火墙:【' +
                                                self.wsl2.FireWallRuleOut +
                                                '】...')

    def __fire_wall_rule_del(self):
        """
        删除防火墙
        :return:
        """
        if self.ui.fire_wall_close.isChecked():
            self.start_qt_process(
                self.wsl2.fire_wall_rule_del(
                    wall_type=self.wsl2.FireWallRuleIn, exec_run=False))
            self.ui.result_text.appendPlainText('>>> 删除防火墙:【' +
                                                self.wsl2.FireWallRuleIn +
                                                '】...')
            self.start_qt_process(
                self.wsl2.fire_wall_rule_del(
                    wall_type=self.wsl2.FireWallRuleOut, exec_run=False))
            self.ui.result_text.appendPlainText('>>> 删除防火墙:【' +
                                                self.wsl2.FireWallRuleOut +
                                                '】...')

    def __port_add_one(self, port, wsl2_ip_info):
        """
        添加单个端口
        :param port: 端口号
        :param wsl2_ip_info: 转发的IP
        :return:
        """
        self.start_qt_process(
            self.wsl2.port_add(wsl_ip=wsl2_ip_info,
                               wsl_port=port,
                               exec_run=False))
        self.ui.result_text.appendPlainText('>>> 添加端口:【' + port + '】...')

    def __port_del_one(self, port):
        """
        删除单个端口
        :param port: 端口号
        :return:
        """
        self.start_qt_process(self.wsl2.port_del(wsl_port=port,
                                                 exec_run=False))
        self.ui.result_text.appendPlainText('>>> 删除端口:【' + port + '】...')

    def start_qt_process(self, cmd):
        """
        启动子进程执行耗时命令
        :param cmd:
        :return:
        """
        process = QProcess(self.ui)
        process.start(cmd)
        result = process.waitForStarted()
        return result
Ejemplo n.º 11
0
class Form(QDialog):
    def __init__(self, parent=None):
        self.round = 0
        self.lcd = QLCDNumber(5)
        self.lcd2 = QLCDNumber(5)
        self.clock = QLCDNumber(5)
        super(Form, self).__init__(parent)
        self.setWindowTitle("Pomodoro")
        # Create widgets
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(1, 99)
        self.slider.setValue(25)
        self.slider2 = QSlider(Qt.Horizontal)
        self.slider2.setRange(1, 99)
        self.slider2.setValue(5)
        self.count = self.slider.value() * 60
        self.rest = self.slider2.value() * 60
        self.taskbar_count = 0
        self.taskbar2_count = 0
        self.text = QLabel("How long should the work period be?")
        self.text2 = QLabel("How long should the rest period be?")
        self.work = QLabel("WORK")
        self.pause = QLabel("REST")
        self.rounds = QLabel("Number of rounds: " + str(self.round))
        self.work.setAlignment(Qt.AlignHCenter)
        self.work.setFont(QFont("Times", 18, QFont.Bold))
        self.pause.setAlignment(Qt.AlignHCenter)
        self.pause.setFont(QFont("Times", 18, QFont.Bold))
        self.button = QPushButton("Start timer")
        self.button2 = QPushButton("Stop timer")
        self.reset = QPushButton("Reset rounds")
        self.lcd.display("25:00")
        self.lcd2.display("05:00")
        mins = 25
        secs = "00"
        self.clock.display(f"{mins}:{secs}")
        self.slider.valueChanged.connect(self.first_display)
        self.slider2.valueChanged.connect(self.second_display)
        self.slider.valueChanged.connect(self.clock_display)
        self.button2.hide()
        self.work.hide()
        self.pause.hide()
        self.clock.hide()
        # Create layout and add widgets
        layout = QVBoxLayout()
        layout.addWidget(self.text)
        layout.addWidget(self.lcd)
        layout.addWidget(self.slider)
        layout.addWidget(self.text2)
        layout.addWidget(self.lcd2)
        layout.addWidget(self.slider2)
        layout.addWidget(self.button)
        layout.addWidget(self.button2)
        layout.addWidget(self.work)
        layout.addWidget(self.pause)
        layout.addWidget(self.clock)
        layout.addWidget(self.rounds)
        layout.addWidget(self.reset)
        # Set dialog layout
        self.setLayout(layout)
        self.systemtray_icon = QSystemTrayIcon(QIcon("snake.png"))
        self.systemtray_icon.show()
        self.systemtray_icon.activated.connect(self.icon_activated)
        self.menu = QMenu(parent)
        self.exit_action = self.menu.addAction("Exit")
        self.systemtray_icon.setContextMenu(self.menu)
        self.exit_action.triggered.connect(self.slot_exit)
        # Add signals
        self.slider.valueChanged.connect(self.count_func)
        self.slider2.valueChanged.connect(self.count_func)
        self.button.clicked.connect(self.button_update)
        self.button.clicked.connect(self.timer_func)
        self.button.clicked.connect(self.round_count)
        self.button2.clicked.connect(self.stop)
        self.reset.clicked.connect(self.reset_rounds)

    def reset_rounds(self):
        self.round = 0
        self.rounds.setText("Number of rounds: " + str(self.round))

    def round_count(self):
        self.round += 1
        self.rounds.setText("Number of rounds: " + str(self.round))

    def icon_activated(self, reason):
        if reason in (QSystemTrayIcon.Trigger, QSystemTrayIcon.DoubleClick):
            self.show()

    def closeEvent(self, event):
        self.hide()
        event.ignore()

    def slot_exit(self):
        QApplication.exit(0)

    def first_display(self):
        minute = str(self.slider.sliderPosition())
        second = ":00"
        leading_zero = "0"
        if self.slider.sliderPosition() >= 10:
            self.lcd.display(minute + second)
        else:
            self.lcd.display(leading_zero + minute + second)

    def second_display(self):
        minute = str(self.slider2.sliderPosition())
        second = ":00"
        leading_zero = "0"
        if self.slider2.sliderPosition() >= 10:
            self.lcd2.display(minute + second)
        else:
            self.lcd2.display(leading_zero + minute + second)

    def clock_display(self):
        minute = str(self.slider.sliderPosition())
        second = ":00"
        leading_zero = "0"
        if self.slider.sliderPosition() >= 10:
            self.clock.display(minute + second)
        else:
            self.clock.display(leading_zero + minute + second)

    def count_func(self):
        self.count = self.slider.sliderPosition() * 60
        self.rest = self.slider2.sliderPosition() * 60

    def countdown(self):
        minute, second = divmod(self.count, 60)
        zero = "0"
        show = self.work.show()
        if second < 10 and minute < 10:
            self.clock.display(zero + str(minute) + ":" + zero + str(second))
        elif second < 10:
            self.clock.display(str(minute) + ":" + zero + str(second))
        elif minute < 10:
            self.clock.display(zero + str(minute) + ":" + str(second))
        else:
            self.clock.display(str(minute) + ":" + str(second))
        self.count -= 1
        if self.count < -1:
            self.work.hide()
            self.taskbar_rest()
            show = self.pause.show()
            minute, second = divmod(self.rest, 60)
            zero = "0"
            if self.rest == self.slider2.value() * 60:
                self.show()
            if second < 10 and minute < 10:
                self.clock.display(zero + str(minute) + ":" + zero +
                                   str(second))
            elif second < 10:
                self.clock.display(str(minute) + ":" + zero + str(second))
            elif minute < 10:
                self.clock.display(zero + str(minute) + ":" + str(second))
            else:
                self.clock.display(str(minute) + ":" + str(second))
            self.rest -= 1
            if self.rest < -1:
                self.clock.display("00:00")
                self.taskbar_work()
                self.timer.stop()
                self.stop()
        show

    def timer_func(self):
        timer = QTimer()
        self.timer = timer
        self.timer.timeout.connect(self.countdown)
        self.timer.start(1000)

    def button_update(self):
        self.button.hide()
        self.text.hide()
        self.lcd.hide()
        self.slider.hide()
        self.text2.hide()
        self.lcd2.hide()
        self.slider2.hide()
        self.reset.hide()
        self.clock.show()
        self.button2.show()
        self.work.show()

    def taskbar_rest(self):
        if self.taskbar_count == 0:
            self.systemtray_icon.showMessage("PAUSE", "Time to rest!",
                                             QSystemTrayIcon.Information,
                                             500000)
            self.taskbar_count = 1

    def taskbar_work(self):
        if self.taskbar2_count == 0:
            self.systemtray_icon.showMessage("WORK", "Break over!",
                                             QSystemTrayIcon.Information,
                                             500000)
            self.taskbar2_count = 1

    def stop(self):
        self.timer.stop()
        self.button2.hide()
        self.work.hide()
        self.pause.hide()
        self.clock.hide()
        self.count = self.slider.value() * 60
        self.rest = self.slider2.value() * 60
        self.clock.display(str(self.slider.value()) + ":00")
        self.button.show()
        self.text.show()
        self.lcd.show()
        self.slider.show()
        self.text2.show()
        self.lcd2.show()
        self.slider2.show()
        self.reset.show()
        self.show()
        self.taskbar_count = 0
        self.taskbar2_count = 0
Ejemplo n.º 12
0
class SystemTrayIcon(QObject):
    clicked = pyqtSignal()
    double_clicked = pyqtSignal()

    def __init__(self, parent, menu, is_logging=False):
        QObject.__init__(self)

        def getIcon(name):
            return QIcon(':/images/tray_icons/' + name + '.png')

        self._icons = {
            STATUS_INIT: getIcon("disconnected") if is_logging \
                else getIcon("sync"),
            STATUS_DISCONNECTED: getIcon("disconnected"),
            STATUS_WAIT: getIcon("default"),
            STATUS_PAUSE: getIcon("pause"),
            STATUS_IN_WORK: getIcon("sync"),
            STATUS_INDEXING: getIcon("sync"),
        }
        self._statuses = {
            STATUS_INIT: tr("Pvtbox"),
            STATUS_DISCONNECTED: tr("Pvtbox connecting..."),
            STATUS_WAIT: tr("Pvtbox"),
            STATUS_PAUSE: tr("Pvtbox paused"),
            STATUS_IN_WORK: tr("Pvtbox syncing..."),
            STATUS_INDEXING: tr("Pvtbox indexing...")
        }
        self._tray = QSystemTrayIcon(self._icons[STATUS_INIT], parent)
        self.set_tool_tip(self._statuses[STATUS_INIT])
        self._tray.setContextMenu(menu)
        menu.aboutToShow.connect(self.clicked.emit)

        self._tray.activated.connect(self._on_activated)
        self._tray.installEventFilter(self)
        self._tray.setVisible(True)
        self._tray.show()

        self._tray_show_timer = QTimer(self)
        self._tray_show_timer.setInterval(3000)
        self._tray_show_timer.setSingleShot(False)
        self._tray_show_timer.timeout.connect(self.show)

    def eventFilter(self, obj, ev):
        if ev.type() == QEvent.ToolTip:
            self.clicked.emit()
        return False

    def _on_activated(self, reason):
        '''
        Slot for system tray icon activated signal.
        See http://doc.qt.io/qt-5/qsystemtrayicon.html

        @param reason Tray activation reason
        '''

        if reason == QSystemTrayIcon.Trigger:
            # This is usually when left mouse button clicked on tray icon
            self.clicked.emit()
        elif reason == QSystemTrayIcon.DoubleClick:
            self.double_clicked.emit()

    @property
    def menu(self):
        return self._tray.contextMenu()

    def set_tool_tip(self, tip):
        self._tray.setToolTip(tip)

    def show_tray_notification(self, text, title=""):
        if not title:
            title = tr('Pvtbox')
        # Convert strings to unicode
        if type(text) in (str, str):
            text = ensure_unicode(text)
        if type(title) in (str, str):
            title = ensure_unicode(title)

        logger.info("show_tray_notification: %s, title: %s", text, title)
        if self._tray.supportsMessages():
            self._tray.showMessage(title, text)
        else:
            logger.warning("tray does not supports messages")

    def request_to_user(
            self, dialog_id, text, buttons=("Yes", "No"), title="",
            close_button_index=-1, close_button_off=False, parent=None,
            on_clicked_cb=None,
            details=''):

        msg_box = QMessageBox(parent)
        # msg_box = QMessageBox()
        if not title:
            title = tr('Pvtbox')
        msg_box.setWindowTitle(title)
        msg_box.setText(str(text))

        pvtboxIcon = QIcon(':/images/icon.png')
        msg_box.setWindowIcon(pvtboxIcon)

        if details:
            msg_box.setDetailedText(details)

        if close_button_off:
            if get_platform() == 'Darwin':
                msg_box.setWindowFlags(Qt.Tool)
            else:
                msg_box.setWindowFlags(Qt.Dialog |
                                       Qt.CustomizeWindowHint |
                                       Qt.WindowTitleHint)
        msg_box.setAttribute(Qt.WA_MacFrameworkScaled)
        msg_box.setModal(True)

        buttons = list(buttons)
        for button in buttons:
            msg_box.addButton(button, QMessageBox.ActionRole)
        msg_box.show()
        msg_box.raise_()
        msg_box.exec_()
        try:
            button_index = buttons.index(msg_box.clickedButton().text())
        except (ValueError, AttributeError):
            button_index = -1
           # message box was closed with close button
            if len(buttons) == 1 and close_button_index == -1:
                # if only one button then call callback
                close_button_index = 0

            if len(buttons) > close_button_index >= 0:
                button_index = close_button_index

        if button_index >= 0 and callable(on_clicked_cb):
            on_clicked_cb(dialog_id, button_index)

    def update_status_icon(self, new_status, new_substatus):
        icon = self._icons[STATUS_DISCONNECTED] if new_status == STATUS_INIT \
            else self._icons[new_status]
        self._tray.setIcon(icon)
        tool_tip = self._statuses[new_status]
        if new_status == STATUS_IN_WORK and new_substatus == SUBSTATUS_SHARE:
            tool_tip = tr("Pvtbox downloading share...")
        self.set_tool_tip(tool_tip)
        self.show()

    def show(self):
        self._tray.setVisible(True)
        self._tray.show()

    def hide(self):
        if self._tray_show_timer.isActive():
            self._tray_show_timer.stop()
        self._tray.hide()

    def __del__(self):
        self._tray.removeEventFilter(self)
        self._tray.activated.disconnect()
        self.hide()
Ejemplo n.º 13
0
class MyWidget(QWidget):
    def __init__(self):
        super().__init__()

        self.streamfile = ""
        self.streams = {}
        scriptdir = os.path.dirname(os.path.realpath(__file__))
        icon = (scriptdir + os.path.sep + "icon/pyradio.ico")
        self.setWindowIcon(QtGui.QIcon(icon))
        self.setStuff()
        # Tray
        self.tray = QSystemTrayIcon()
        self.tray.setIcon(QtGui.QIcon(icon))
        self.tray.activated.connect(self.call)

        self.icon = QtGui.QIcon()
        self.icon.addFile(icon)
        self.setWindowIcon(self.icon)

        # tray menu
        self.trayIconMenu = QtWidgets.QMenu()
        self.quitAction = QtWidgets.QAction("&Quit", triggered=self.close)
        self.trayIconMenu.addAction(self.quitAction)
        self.tray.setContextMenu(self.trayIconMenu)
        self.trayIconMenu.setStyleSheet(open("css/main.css", "r").read())

        # Media player
        self.radio = vlc.MediaPlayer()
        self.playing = False

        self.pal = QtGui.QPalette(self.palette())

        self.playing_label = QLabel("Stopped")
        self.label = QLabel("Radios:")

        self.label.setAlignment(Qt.AlignCenter)
        self.playing_label.setAlignment(Qt.AlignCenter)
        self.btn = QPushButton("Play/Stop")
        self.btn.clicked.connect(self.control)
        self.list = QListWidget()
        self.list.itemDoubleClicked.connect(self.control)

        self.edit = QPushButton("Edit Radios")
        self.edit.clicked.connect(self.openfile)
        self.refresh = QPushButton("Refresh")
        self.refresh.clicked.connect(self.refreshstreams)

        self.slider = QSlider(QtGui.Qt.Horizontal)
        self.slider.setMaximum(100)
        self.slider.setValue(self.volume)
        self.slider.valueChanged.connect(self.changeVolume)

        self.setStyleSheet(open("css/main.css", "r").read())

        self.refreshstreams()

        self.current = ""
        self.buttons = QHBoxLayout()

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.list)
        self.layout.addWidget(self.playing_label)
        self.layout.addWidget(self.slider)
        self.buttons.addWidget(self.btn)
        self.buttons.addWidget(self.edit)
        self.buttons.addWidget(self.refresh)

        self.layout.addLayout(self.buttons)
        self.setLayout(self.layout)

    def setStuff(self):
        info = self.readInfo()
        print(info)
        if len(info) == 0:
            info = ["", "", "", "", ""]
        if (info[0] == ""):
            self.volume = 80
        else:
            self.volume = int(info[0])
        if info[3].strip() == "false" or info[3] == "":
            if info[1] == "":
                self.resize(800, 600)
            else:
                w, h = info[1].split(" ")
                self.resize(int(w), int(h))
            if info[2] != "":
                x, y = info[2].split(" ")
                self.move(int(x), int(y))
        else:
            self.showMaximized()
        if len(info) < 5:
            # show dialog
            self.chooseStreamfile()
        else:
            self.streamfile = info[4].strip()

    def chooseStreamfile(self):
        self.dialog = QFileDialog(self)
        self.dialog.setFileMode(QFileDialog.AnyFile)
        if self.dialog.exec_():
            filename = self.dialog.selectedFiles()
            self.streamfile = filename[0]

    def changeVolume(self):
        self.volume = self.slider.value()
        self.radio.audio_set_volume(self.volume)

    def getVolume(self):
        try:
            with open("data", "r") as file:
                return int(file.readline())
        except:
            with open("data", "w") as file:
                file.write(str(80))
                return 80

    def control(self):
        if self.playing and self.current == self.streams[
                self.list.currentItem().text()]:
            self.stop()
        else:
            self.radio.stop()
            self.play()

    def stop(self):
        self.radio.stop()
        self.playing_label.setText("Stopped")
        self.playing = False

    def play(self):
        self.current = self.list.currentItem().text()
        for i in self.streams:
            if self.current == i:
                self.current = self.streams[i]
                break
        self.radio = vlc.MediaPlayer(self.current)
        self.radio.play()
        self.radio.audio_set_volume(self.slider.value())
        self.playing_label.setText("Playing")
        self.playing = True
        self.tray.showMessage(self.list.currentItem().text(), "",
                              self.tray.icon(), 1000)

    def next(self):
        isthis = False
        self.current = self.list.currentItem().text()
        for n, i in enumerate(self.streams):
            if isthis:
                self.list.setCurrentRow(n)
                break
            else:
                if self.current == i:
                    isthis = True
                    if n + 1 >= len(self.streams):
                        self.list.setCurrentRow(0)
        self.stop()
        self.play()

    def previous(self):
        isthis = False
        self.current = self.list.currentItem().text()
        for n, i in enumerate(self.streams):
            if isthis:
                self.list.setCurrentRow(n - 2)
                break
            else:
                if self.current == i:
                    isthis = True
                    if n - 1 < 0:
                        self.list.setCurrentRow(len(self.streams) - 1)
                        break
                    elif n == len(self.streams) - 1:
                        self.list.setCurrentRow(n - 1)

        self.stop()
        self.play()

    def openfile(self):
        # Opens radios.txt
        webbrowser.open(self.streamfile)

    def refreshstreams(self):

        # Refreshes the stream list when button pressed
        if self.list.currentItem():
            current = self.list.currentItem().text()
        else:
            current = None
        self.streams = {}
        try:
            with open(self.streamfile, "r") as file:
                lines = file.readlines()
                for line in lines:
                    nline = line.strip().split(":", 1)
                    self.streams[nline[0]] = nline[1].split("#")[0]
        except:
            self.chooseStreamfile()
            self.refreshstreams()
            return

        self.list.clear()

        for i, n in enumerate(self.streams):
            self.list.addItem(n)
            if n == current:
                self.list.setCurrentRow(i)
        if not self.list.currentItem():
            self.list.setCurrentRow(0)

    def changeEvent(self, event):

        # This minimizes the program to tray when Minimize button pressed

        if event.type() == QEvent.WindowStateChange:
            if self.windowState() & Qt.WindowMinimized:
                print(QSystemTrayIcon.isSystemTrayAvailable())
                if QSystemTrayIcon.isSystemTrayAvailable(
                ) and self.isActiveWindow():
                    event.ignore()
                    self.tray.show()
                    self.hide()
                    self.listener = keyboard.Listener(
                        on_release=self.on_release)
                    self.listener.start()

    def closeEvent(self, event):
        file = open("data", "w+")
        info = str(self.volume) + "\n" + str(self.size().width()) + " " + str(self.size().height()) + "\n" +\
               str(self.pos().x()) + " " + str(self.pos().y()) + "\n"
        if (self.isMaximized()):
            info += "true"
        else:
            info += "false"
        info += "\n"
        info += self.streamfile + "\n"
        file.write(info)
        file.close()

    def readInfo(self):
        try:
            with open("data", "r", encoding="utf-8") as file:
                info = file.readlines()
                return info
        except:
            with open("data", "w", encoding="utf-8") as file:
                file.write("")
                return ""

    def keyReleaseEvent(self, event):

        # This is for media controls when radio is opened

        key = event.key()
        if key == Qt.Key_MediaPlay or key == Qt.Key_MediaTogglePlayPause or \
                key == Qt.Key_MediaPause:
            self.control()
        elif key == Qt.Key_MediaNext:
            self.next()
        elif key == Qt.Key_MediaPrevious:
            self.previous()

    def call(self, reason):
        # This is caled when tray icon is pressed
        if reason == QSystemTrayIcon.ActivationReason.Trigger:
            self.show()
            self.setFocus()
            self.listener.stop()
            del self.listener
            self.tray.hide()
            self.setWindowState(Qt.WindowActive)
        elif reason == QSystemTrayIcon.ActivationReason.Context:
            self.tray.contextMenu().show()
        elif reason == QSystemTrayIcon.ActivationReason.MiddleClick:
            print("Middle click on tray icon")
        else:
            print("Unknown reason")

    def on_release(self, key):
        # This is for media controls when program in tray.
        try:
            if key == keyboard.Key.media_play_pause:  # might need a different key
                self.control()
            elif keyboard.Key.media_next == key:  # might need a different key
                self.next()
            elif keyboard.Key.media_previous == key:  # might need a different key
                self.previous()
        except AttributeError as e:
            print(e)
Ejemplo n.º 14
0
class MainWindow(QMainWindow):
    """The main window of the application

    Currently just displays "Hello, world!".
    """
    def __init__(self):
        QMainWindow.__init__(self)

        icon = QIcon(ICON_IMAGE)

        self.setMinimumSize(300, 50)
        self.setWindowTitle("Echo VR Tray Tool")
        self.setWindowIcon(icon)

        main_widget = QWidget(self)
        self.setCentralWidget(main_widget)

        main_layout = QGridLayout(main_widget)

        discord_status_header = QLabel("Discord status:")
        discord_status_header.setFont(_HEADER_FONT)
        main_layout.addWidget(discord_status_header, 0, 0, Qt.AlignRight)

        self._discord_status_label = QLabel("Unknown")
        main_layout.addWidget(self._discord_status_label, 0, 1, Qt.AlignLeft)

        echo_vr_status_header = QLabel("Echo VR client status:")
        echo_vr_status_header.setFont(_HEADER_FONT)
        main_layout.addWidget(echo_vr_status_header, 1, 0, Qt.AlignRight)

        self._echo_vr_client_status_label = QLabel("Unknown")
        main_layout.addWidget(self._echo_vr_client_status_label, 1, 1,
                              Qt.AlignLeft)

        main_layout.setRowStretch(2, 1)

        self.tray_icon = QSystemTrayIcon(icon, self)

        tray_menu = QMenu()

        show_action = QAction("Show", self)
        show_action.triggered.connect(self.show)
        tray_menu.addAction(show_action)

        quit_action = QAction("Exit", self)
        quit_action.triggered.connect(self._quit)
        tray_menu.addAction(quit_action)

        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.show()

        self._discord_presence_thread = None
        self._start_discord_presence_thread()

    def closeEvent(self, event):
        """Overridden to minimize to tray instead of exiting"""

        event.ignore()
        self.hide()
        self.tray_icon.showMessage(
            "Application is still running",
            "Echo VR Tray Tool was minimized to tray. Right-click and press 'exit' to quit.",
            QSystemTrayIcon.Information,
            3000,
        )

    def _quit(self):
        if self._discord_presence_thread:
            self._discord_presence_thread.exit()
            self._discord_presence_thread.wait()

        qApp.quit()

    def _start_discord_presence_thread(self):
        if self._discord_presence_thread:
            return

        self._discord_presence_thread = DiscordPresenceThread()
        self._discord_presence_thread.connection_status_changed.connect(
            self._discord_connection_status_changed)
        self._discord_presence_thread.game_client_status_changed.connect(
            self._game_client_status_changed)
        self._discord_presence_thread.start()

    def _discord_connection_status_changed(self, connected):
        if connected:
            self._discord_status_label.setText("Connected")
            self._discord_status_label.setStyleSheet(_GREEN_LABEL)
        else:
            self._discord_status_label.setText("Disconnected")
            self._discord_status_label.setStyleSheet(_RED_LABEL)

    def _game_client_status_changed(self, connected):
        if connected:
            self._echo_vr_client_status_label.setText("Connected")
            self._echo_vr_client_status_label.setStyleSheet(_GREEN_LABEL)
        else:
            self._echo_vr_client_status_label.setText("Disconnected")
            self._echo_vr_client_status_label.setStyleSheet(_RED_LABEL)
Ejemplo n.º 15
0
class KnechtWindow(QMainWindow):
    system_tray_click_connected = False
    tree_focus_changed = Signal(QTreeView)
    is_about_to_quit = Signal()

    def __init__(self, app):
        """ The GUI MainWindow Class

        :param modules.gui.main_app.KnechtApp app: Main QApplication class
        """
        super(KnechtWindow, self).__init__()
        self.app = app
        SetupWidget.from_ui_file(self,
                                 Resource.ui_paths['knecht_model_gui'],
                                 custom_widgets={'QColorButton': QColorButton})

        self.rk_icon = QIcon(QPixmap(Resource.icon_paths['RK_Icon']))

        # Set version window title
        self.setWindowTitle(f'{self.windowTitle()} - v{self.app.version}')

        # ---- Setup Main Menu ----
        self.main_menu = MainWindowMenu(self)

        # ---- Tree Setup ----
        tree_view_list = [self.variantTree, self.renderTree]
        tree_file_list = [_('Variantenbaum'), _('Renderliste')]
        tree_filter_widgets = [
            self.lineEdit_Var_filter, self.lineEdit_Ren_filter
        ]

        # View Mgr will replace placeholder presetTree
        self.view_mgr = UiViewManager(self)
        self.view_mgr.view_updated.connect(self._connect_message_browser)
        self.view_mgr.setup_initial_tab_view(self.presetTree)
        # Set presetTree to current View Mgr view to avoid accessing deleted object
        self.presetTree = self.view_mgr.current_view()

        replaced_views = self.view_mgr.setup_default_views(
            tree_view_list, tree_file_list, tree_filter_widgets)

        self.variantTree, self.renderTree = replaced_views[0], replaced_views[
            1]
        for default_view in [self.variantTree, self.renderTree]:
            default_view.setFocusPolicy(Qt.ClickFocus)
            default_view.undo_stack.cleanChanged.disconnect()

        # ---- Setup renderTree ----
        self.renderTree.is_render_view = True
        self.renderTree.accepted_item_types = [Kg.render_preset, Kg.preset]

        # ---- Internal Clipboard ----
        self.clipboard = TreeClipboard()

        # ---- Store last tree with focus ----
        self.last_focus_tree = self.presetTree

        # ---- System tray and taskbar ----
        self.system_tray = QSystemTrayIcon(self.rk_icon, self)
        self.system_tray.hide()

        # ---- Windows taskbar progress indicator ----
        self.taskbar_btn = QWinTaskbarButton(self)
        self.taskbar_progress = self.taskbar_btn.progress()
        # Delayed Taskbar Setup (Main Window needs to be created for correct window handle)
        QTimer.singleShot(1, self.init_taskbar)

        # ---- Generic Info Overlay ----
        self.overlay = MainWindowOverlay(self.centralWidget())

        # ---- Close Action ----
        self.actionBeenden.triggered.connect(self.close)

        # ---- Setup Main UI Widgets ----
        MainWindowWidgets(self)

        # Updater
        self.updater = KnechtUpdate(self)
        self.updater.update_available.connect(
            self.main_menu.info_menu.update_ready)
        QTimer.singleShot(20000, self.auto_update)  # Initial Update check

        self.app.focusChanged.connect(self.app_focus_changed)

        # ---- Translate Ui elements loaded from ui file ----
        translate_main_ui(self)

        self.setAcceptDrops(True)

    def _get_drop_event_files(self, mime_data):
        files = []
        for url in mime_data.urls():
            if not url.isLocalFile():
                continue

            file = Path(url.toLocalFile())

            if file.suffix.casefold(
            ) in self.main_menu.file_menu.supported_file_types:
                files.append(file)

        return files

    def dragEnterEvent(self, event: QDragEnterEvent):
        if event.mimeData().hasUrls():
            if self._get_drop_event_files(event.mimeData()):
                event.acceptProposedAction()
            else:
                event.ignore()

    def dropEvent(self, event: QDropEvent):
        if event.mimeData().hasUrls():
            files = self._get_drop_event_files(event.mimeData())
            if files:
                for file in files:
                    self.main_menu.file_menu.guess_open_file(file)
                event.accept()
                return True

        event.ignore()
        return False

    def app_focus_changed(self, old_widget: QWidget, new_widget: QWidget):
        if isinstance(new_widget, KnechtTreeView):
            self.set_last_focus_tree(new_widget)

    def init_taskbar(self):
        """ Initializes the MS Windows taskbar button"""
        # Needs to be called after window is created/shown
        self.taskbar_btn.setWindow(self.windowHandle())

        self.taskbar_progress.setRange(0, 100)
        self.taskbar_progress.valueChanged.connect(self.taskbar_progress.show)

    def _connect_message_browser(self, view: KnechtTreeView):
        LOGGER.debug('Setting up message browser for: %s', view.objectName())
        view.info_overlay.setup_message_browser(self.messageBrowser,
                                                self.tabWidget)

    def show_tray_notification(self,
                               title: str,
                               message: str,
                               clicked_callback=None):
        if not self.system_tray.isVisible():
            self.system_tray.show()

        # Disconnect existing callback
        if self.system_tray_click_connected:
            try:
                self.system_tray.messageClicked.disconnect()
            except RuntimeError:
                LOGGER.info(
                    'Could not disconnect system tray messageClicked handler.')
            finally:
                self.system_tray_click_connected = False

        if clicked_callback is not None:
            self.system_tray.messageClicked.connect(clicked_callback)
            self.system_tray_click_connected = True

        self.system_tray.showMessage(title, message, self.rk_icon)

    def set_last_focus_tree(self, set_tree_focus):
        if isinstance(set_tree_focus, KnechtTreeView):
            self.last_focus_tree = set_tree_focus

        self.tree_focus_changed.emit(self.last_focus_tree)

    def tree_with_focus(self) -> KnechtTreeView:
        """ Return the current or last known QTreeView in focus """
        widget_in_focus = self.focusWidget()

        if isinstance(widget_in_focus, KnechtTreeView):
            self.last_focus_tree = widget_in_focus

        return self.last_focus_tree

    def check_for_updates(self):
        self.updater.run_update()

    def auto_update(self):
        if self.updater.first_run:
            if FROZEN:
                self.check_for_updates()

    def report_missing_reset(self):
        msg = _(
            'Die Varianten enthalten keine Reset Schaltung! Die zu sendenden Varianten '
            'werden mit vorangegangen Schaltungen kollidieren.')

        self.overlay.display(msg, duration=5000, immediate=True)

    def msg(self, txt: str, duration: int = 4000) -> None:
        self.statusBar().showMessage(txt, duration)
        self.overlay.display(txt, duration, immediate=True)

    def play_finished_sound(self):
        self._play_sound(SoundRsc.finished)

    def play_confirmation_sound(self):
        self._play_sound(SoundRsc.positive)

    def play_hint_sound(self):
        self._play_sound(SoundRsc.hint)

    def play_warning_sound(self):
        self._play_sound(SoundRsc.warning)

    def _play_sound(self, resource_key):
        try:
            sfx = SoundRsc.get_sound(resource_key, self)
            sfx.play()
        except Exception as e:
            LOGGER.error(e)