예제 #1
0
class SerialPortSelector(QWidget):

    open_port = pyqtSignal(str, int)
    close_port = pyqtSignal()

    def __init__(self, *args):
        super(SerialPortSelector, self).__init__(*args)

        self.disabled = False

        self.init_ui()
        self.add_ports()

    def init_ui(self):
        layout = QHBoxLayout()
        self.setLayout(layout)

        self.ports_list_combobox = QComboBox()
        layout.addWidget(self.ports_list_combobox)

        self.baud_rate_combobox = QComboBox()
        self.baud_rate_combobox.addItems([
            '300', '600', '1200', '2400', '4800', '9600', '19200', '38400',
            '43000', '56000', '57600', '115200'
        ])
        self.baud_rate_combobox.setCurrentText('115200')
        self.baud_rate_combobox.setEditable(True)
        layout.addWidget(self.baud_rate_combobox)

        self.open_btn = QPushButton('打开')
        self.open_btn.clicked.connect(self.handle_open_port)
        layout.addWidget(self.open_btn)

        self.refresh_btn = QPushButton('刷新')
        self.refresh_btn.clicked.connect(self.add_ports)
        layout.addWidget(self.refresh_btn)

    def add_ports(self):
        self.ports_list_combobox.clear()
        for port in comports(False):
            self.ports_list_combobox.addItem(port.name, port)

    def handle_open_port(self):
        if self.disabled:
            self.close_port.emit()
        else:
            port = self.ports_list_combobox.currentText()
            if port == "":
                return
            baud_rate = int(self.baud_rate_combobox.currentText())
            self.open_port.emit(port, baud_rate)

    def set_disable(self, b):
        self.disabled = b
        self.ports_list_combobox.setDisabled(b)
        self.baud_rate_combobox.setDisabled(b)
        if self.disabled:
            self.open_btn.setText('关闭')
        else:
            self.open_btn.setText('打开')
예제 #2
0
파일: app.py 프로젝트: Z-zxQ/yt-downloader
class YTdownloader(QWidget):
    def __init__(self):
        super().__init__()
        # setup some flags
        self.isFetching = False
        self.isDownloading = False

        # default output path
        self.outputPath = f'{QDir.homePath()}/videos'

        # setup some window specific things
        self.setWindowTitle('YouTube Downloader')
        self.setWindowIcon(QIcon('assets/yt-icon.ico'))
        self.setFixedSize(705, 343)

        # parent layout
        layout = QVBoxLayout()
        layout.setContentsMargins(15, 15, 15, 10)
        self.setLayout(layout)

        # top bar layout
        topBar = QHBoxLayout()

        # detail section
        detailSec = QHBoxLayout()
        metaSec = QVBoxLayout()

        # download section
        downloadSec = QHBoxLayout()
        downloadBtn = QVBoxLayout()

        # output path link button
        self.outputBtn = QPushButton('📂  Output Path')
        self.outputBtn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.outputBtn.setToolTip(self.outputPath)
        self.outputBtn.clicked.connect(self.setOutputPath)

        # status bar
        self.statusBar = QStatusBar()

        # message box
        self.message = QMessageBox()

        # setting up widgets
        self.urlBox = QLineEdit()
        self.urlBox.setFocusPolicy(Qt.FocusPolicy.ClickFocus or Qt.FocusPolicy.NoFocus)
        self.urlBox.setPlaceholderText('🔍 Enter or paste video URL...')
        self.button = QPushButton('Get')
        self.button.setDefault(True)
        self.button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.button.clicked.connect(self.getDetails)

        # thumbnail
        pixmap = QPixmap('assets\placeholder.jpg')
        self.thumb = QLabel()
        self.thumb.setFixedSize(250, 141)
        self.thumb.setScaledContents(True)
        self.thumb.setPixmap(pixmap)

        # detail widgets
        self.title = QLabel('Title: ')
        self.author = QLabel('Author: ')
        self.length = QLabel('Duration: ')
        self.publish_date = QLabel('Published: ')

        # progress bar
        self.progress_bar = QProgressBar()
        
        # download options
        self.download = QComboBox()
        self.download.setPlaceholderText('Download Video')
        self.download.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.download.activated.connect(lambda: self.getContent(0))
        self.download.setEnabled(False)

        # download audio button
        self.download_audio = QPushButton('Download Audio')
        self.download_audio.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.download_audio.clicked.connect(lambda: self.getContent(1))
        self.download_audio.setEnabled(False)

        # add widgets and layouts
        topBar.addWidget(self.urlBox)
        topBar.addWidget(self.button)

        # detail section
        metaSec.addWidget(self.title)
        metaSec.addWidget(self.author)
        metaSec.addWidget(self.length)
        metaSec.addWidget(self.publish_date)
        detailSec.addWidget(self.thumb)
        detailSec.addSpacing(20)
        detailSec.addLayout(metaSec)

        # download section
        downloadBtn.addWidget(self.download)
        downloadBtn.addWidget(self.download_audio)
        downloadSec.addWidget(self.progress_bar)
        downloadSec.addSpacing(10)
        downloadSec.addLayout(downloadBtn)

        # status bar
        self.statusBar.setSizeGripEnabled(False)
        self.statusBar.addPermanentWidget(self.outputBtn)

        # add content to parent layout
        layout.addLayout(topBar)
        layout.addSpacing(20)
        layout.addLayout(detailSec)
        layout.addSpacing(5)
        layout.addLayout(downloadSec)
        layout.addWidget(self.statusBar)

        # setup a connection thread to keep checking internet connectivity
        self.connection = ConnectionThread()
        self.connection.start()

        # catch the connection response signal
        self.connection.con_response.connect(self.connection_slot)

    # connection slot
    def connection_slot(self, status):
        curMsg = self.statusBar.currentMessage()
        # connection succeeded
        if status:
            if curMsg == '🔴  Disconnected':
                self.statusBar.showMessage('🟢  Connection restored!', 3000)
            elif curMsg != '🟢  Connected':
                self.statusBar.showMessage('🟢  Connected')
        # connection failed
        elif curMsg == '🟢  Connected':
            self.statusBar.showMessage('🔴  Connection interrupted!', 3000)
        elif curMsg != '🔴  Disconnected': 
            self.statusBar.showMessage('🔴  Disconnected')

    # set output path slot
    def setOutputPath(self):
        # update the output path
        path = str(QFileDialog.getExistingDirectory(self, "Select Output Directory"))
        if path:
            self.outputPath = path
            # update tooltip
            self.outputBtn.setToolTip(path)

    # get button slot
    def getDetails(self):
        curMsg = self.statusBar.currentMessage()
        if curMsg == '🔴  Disconnected' or curMsg == '🔴  Connection interrupted!':
            self.message.critical(
                self,
                'Error',
                'Connection failed!\nAre you sure you\'re connected to the internet ? '
            )
        elif self.button.text() == 'Get':
            self.button.setText('Stop')
            # indicate progress bar as busy
            self.progress_bar.setRange(0, 0)
            # set fetching flag
            self.isFetching = True
            # setup a worker thread to keep UI responsive
            self.worker = WorkerThread(self.urlBox.text())
            self.worker.start()
            # catch the finished signal
            self.worker.finished.connect(self.finished_slot)
            # catch the response signal
            self.worker.worker_response.connect(self.response_slot)
            # catch the error signal
            self.worker.worker_err_response.connect(self.err_slot)
        elif self.button.text() == 'Stop':
            if self.isFetching:
                # stop worker thread
                self.worker.terminate()
                # set back the button text
                self.button.setText('Get')
            elif self.isDownloading:
                # stop download thread
                self.download_thread.terminate()
                # show the warning message
                self.message.information(
                    self,
                    'Interrupted',
                    'Download interrupted!\nThe process was aborted while the file was being downloaded... '
                )
                # reset pogress bar
                self.progress_bar.reset()

    # download options slot
    def getContent(self, id):
        if self.isFetching:
            # show the warning message
            self.message.warning(
                self,
                'Warning',
                'Please wait!\nWait while the details are being fetched... '
            )
        else:
            # disable the download options
            self.download.setDisabled(True)
            self.download_audio.setDisabled(True)
            # set downloading flag
            self.isDownloading = True
            # set button to stop 
            self.button.setText('Stop')
            # setup download thread
            if id == 0:
                self.download_thread = DownloadThread(self.yt, self.download.currentText()[:4], self.outputPath)
            else:
                self.download_thread = DownloadThread(self.yt, 'audio', self.outputPath)
            # start the thread
            self.download_thread.start()
            # catch the finished signal
            self.download_thread.finished.connect(self.download_finished_slot)
            # catch the response signal
            self.download_thread.download_response.connect(self.download_response_slot)
            # catch the complete signal
            self.download_thread.download_complete.connect(self.download_complete_slot)
            # catch the error signal
            self.download_thread.download_err.connect(self.download_err_slot)

    # finished slot
    def finished_slot(self):
        # remove progress bar busy indication
        self.progress_bar.setRange(0, 100)
        # unset fetching flag
        self.isFetching = False

    # response slot
    def response_slot(self, res):
        # set back the button text
        self.button.setText('Get')
        # save the yt object for speeding up download
        self.yt = res[0]
        # set the actual thumbnail of requested video
        self.thumb.setPixmap(res[1])
        # slice the title if it is more than the limit
        if len(res[2]) > 50:
            self.title.setText(f'Title:  {res[2][:50]}...')
        else:
            self.title.setText(f'Title:  {res[2]}')
        # set leftover details
        self.author.setText(f'Author:  {res[3]}')
        self.length.setText(f'Duration:  {timedelta(seconds=res[4])}')
        self.publish_date.setText(f'Published:  {res[5].strftime("%d/%m/%Y")}')
        # clear any previous items if any
        self.download.clear()
        # add resolutions as items to the download button and enable them
        self.download.addItems([item for item in res[6]])
        self.download.setDisabled(False)
        self.download_audio.setDisabled(False)

    # error slot
    def err_slot(self):
        # show the warning message
        self.message.warning(
            self,
            'Warning',
            'Something went wrong!\nProbably a broken link or some restricted content... '
        )
        # set back the button text
        self.button.setText('Get')

    # download finished slot
    def download_finished_slot(self):
        # set back the button text
        self.button.setText('Get')
        # now enable the download options
        self.download.setDisabled(False)
        self.download_audio.setDisabled(False)
        # unset downloading flag
        self.isDownloading = False
        # reset pogress bar
        self.progress_bar.reset()

    # download response slot
    def download_response_slot(self, per):
        # update progress bar
        self.progress_bar.setValue(per)
        # adjust the font color to maintain the contrast
        if per > 52:
            self.progress_bar.setStyleSheet('QProgressBar { color: #fff }')
        else:
            self.progress_bar.setStyleSheet('QProgressBar { color: #000 }')
    
    # download complete slot
    def download_complete_slot(self, location):
        # use native separators
        location = QDir.toNativeSeparators(location)
        # show the success message
        if self.message.information(
            self,
            'Downloaded',
            f'Download complete!\nFile was successfully downloaded to :\n{location}\n\nOpen the downloaded file now ?',
            QMessageBox.StandardButtons.Open,
            QMessageBox.StandardButtons.Cancel
        ) is QMessageBox.StandardButtons.Open: subprocess.Popen(f'explorer /select,{location}')

    # download error slot
    def download_err_slot(self):
        # show the error message
        self.message.critical(
            self,
            'Error',
            'Error!\nSomething unusual happened and was unable to download...'
        )
예제 #3
0
class Madoka(QWidget):
    global serialPort, baud, fmt

    def __init__(self):
        global serialPort, baud, fmt
        self.serialLogState = False
        self.fmts = ['bin', 'oct', 'dec', 'hex', 'csv', 'csv+', 'ascii']
        self.baudList = [
            4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 76800, 115200,
            230400, 460800, 921600, 1000000, 2000000, 4000000
        ]
        fmt = self.fmts.index(fmt)
        super().__init__()
        layoutA = QHBoxLayout()

        self.baudBox = QComboBox()
        self.getBaud()
        layoutA.addWidget(self.baudBox)

        self.formatBox = QComboBox()
        self.getFormat()
        layoutA.addWidget(self.formatBox)

        layoutB = QHBoxLayout()
        self.portBox = QComboBox()
        self.getPorts()
        layoutB.addWidget(self.portBox)

        parentLayout = QVBoxLayout()
        parentLayout.addLayout(layoutB)
        parentLayout.addLayout(layoutA)

        self.setLayout(parentLayout)

        self.portBox.currentTextChanged.connect(self.portSelected)
        self.portBox.setCurrentIndex(len(self.ports) - 1)

        self.baudBox.currentTextChanged.connect(self.baudSelected)
        try:
            self.baudBox.setCurrentIndex(self.baudList.index(baud))
        except:
            self.baudBox.setCurrentIndex(-1)

        self.formatBox.currentTextChanged.connect(self.formatSelected)
        self.formatBox.setCurrentIndex(fmt)

        self.button1 = QPushButton()
        self.button1.setText("start")
        self.button1.released.connect(self.btn1Clicked)
        layoutA.addWidget(self.button1)

    def portSelected(self, text):
        global serialPort
        if (text != ''):
            serialPort = self.ports[self.portsIndex.index(text)]
            # print(serialPort)
            # self.erandano.setText(self.port)

    def baudSelected(self, text):
        global baud
        if (text != ''):
            baud = text
            # print(baud)

    def formatSelected(self, text):
        global fmt
        if (text != ''):
            fmt = self.fmts.index(text)
            # print(text)

    def getPorts(self):
        global serialPort
        # sys.stderr.write("\n--- Available ports:\n")
        self.ports = []
        self.portsIndex = []
        for n, (port, desc, devid) in enumerate(sorted(comports()), 1):
            # sys.stderr.write("--- {:2}: {:20} {!r} \n".format(n, port, desc))
            self.ports.append(port)
            print(port)
            self.portsIndex.append("{:2}: {:20} {!r}".format(n, port, desc))
        try:
            serialPort = self.ports.index(serialPort)
        except:
            serialPort = self.ports[len(self.ports) - 1]
        for s in self.portsIndex:
            self.portBox.addItem(s)

    def getBaud(self):
        for b in self.baudList:
            self.baudBox.addItem(str(b))

    def getFormat(self):
        global fmt
        for f in self.fmts:
            self.formatBox.addItem(f)

    def btn1Clicked(self):
        if (self.button1.text() == 'start'):
            self.baudBox.setDisabled(True)
            self.formatBox.setDisabled(True)
            self.button1.setText('stop')
            self.serialLogState = True
            th = threading.Thread(target=printData, daemon=True)
            th.start()
        elif (self.button1.text() == 'stop'):
            self.button1.setText('start')
            self.baudBox.setDisabled(False)
            self.formatBox.setDisabled(False)
            self.serialLogState = False