예제 #1
0
 def download_button_click(self):
     flag = False
     for check_box in self.check_box_list:
         if check_box.isChecked():
             constant.SERVICE.parse_image(self.comic_info, check_box.property("chapter_info"),
                                          self.load_download_task_signa.emit)
             if not flag:
                 QMessageBox.information(self, "下载通知", "正在解析选中章节", QMessageBox.StandardButton.Yes)
                 flag = True
 def deleteRowFromTable(self):
     """Using the view's selection model, find out which row is
     selected and remove it."""
     if self.selectionModel().hasSelection():
         index = self.selectionModel().currentIndex()
         self.model.removeRow(index.row(), index)
     else:
         QMessageBox.information(self, "No Row Selected",
                                 "No row selected for deletion.")
예제 #3
0
 def show_trial_over_and_die(self):
     QMessageBox.information(
         self,
         "Trial Over",
         "Your trial period is over. Please purchase Blobbackup to continue using it.",
     )
     self.logger.info("Trial over displayed.")
     webbrowser.open(PAYMENT_URL)
     sys.exit()
예제 #4
0
 def accept(self, success, message):
     self.set_elements_enabled(True)
     self.loading_dialog.hide()
     if not success:
         QMessageBox.warning(self, "Change Password Failed", message)
         self.logger.info("Change password failed displayed")
         return
     self.logger.info("Changed password")
     QMessageBox.information(self, "Password Changed",
                             "Password successfully changed.")
     super().accept()
예제 #5
0
 def wrapper(self, *args, **kwargs):
     try:
         return func(self, *args, **kwargs)
     except Exception as e:
         if isinstance(e, serial.serialutil.SerialException):
             self.disable_widgets()
             self.clear_servo()
             self.port_refresh_button_clicked(None)
             QMessageBox.critical(None, "Error", "Disconnected from device")
         else:
             QMessageBox.information(None, "Error", str(e))
 def removeRow(self, row, index):
     """Remove a row the model. Call values_edited to 
     update the totals in the Money Left Over table."""
     if self._data != [] and index.row() != len(self._data) - 1:
         self._data.pop(row)
     else:
         QMessageBox.information(QApplication.activeWindow(),
                                 "No Row Selected",
                                 "No row selected for deletion.")
     self.values_edited.emit()
     self.layoutChanged.emit()
     return True
예제 #7
0
    def generate(self):
        temp_cfg = open('_tempcfg.json', 'w')
        cfg = self.get_current_configuration()
        json.dump(cfg, temp_cfg, indent=4)
        temp_cfg.close()

        generate_header('_tempcfg.json')

        os.remove('_tempcfg.json')
        QMessageBox.information(self, "Success",
                                "File Generated Successfully!",
                                QMessageBox.StandardButton.Ok,
                                QMessageBox.StandardButton.Ok)
예제 #8
0
 def start_clicked(self):
     dir = self.download_dir.text()
     if not dir:
         QMessageBox.information(self, "错误","请输入存储目录")
         return
     if not os.path.exists(dir):
         os.mkdir(dir)
     self.thread.dir = dir
     url = self.url_input.text()
     print(url)
     self.thread.url = url
     pwd = '/'.join(os.getcwd().split('\\'))+'/'+dir
     btn = QPushButton("删除图片")
     if pwd not in self.dict:
         btn.clicked.connect(self.del_pic)
         self.dict[pwd] = btn
         self.tableupdate(pwd , self.thread.max_page_num , self.dict[pwd] )
예제 #9
0
    def saveImage(self):
        """Save the image displayed in the label."""
        #TODO: Add different functionality for the way in which the user can save their image.
        if self.image.isNull() == False:
            image_file, _ = QFileDialog.getSaveFileName(
                self, "Save Image", "",
                "PNG Files (*.png);;JPG Files (*.jpeg *.jpg );;Bitmap Files (*.bmp);;\
                    GIF Files (*.gif)")

            if image_file and self.image.isNull() == False:
                self.image.save(image_file)
            else:
                QMessageBox.information(self, "Error", "Unable to save image.",
                                        QMessageBox.Ok)
        else:
            QMessageBox.information(self, "Empty Image",
                                    "There is no image to save.",
                                    QMessageBox.Ok)
예제 #10
0
 def exec(self):
     s = QApplication.clipboard().text()
     if QMessageBox.information(self, 'exec', s, QMessageBox.Ok
                                | QMessageBox.Cancel) != QMessageBox.Ok:
         return
     try:
         exec(s)
     except BaseException as e:
         logger.exception(e)
예제 #11
0
 def inherit_backup_history(self):
     email = config["meta"]["email"]
     if verify_password(email):
         password = get_password_from_keyring()
         choose_computer_dialog = ChooseComputerDialog(
             email,
             password,
             "Choose the computer to inherit backup history from.",
         )
         if choose_computer_dialog.exec():
             computer_id = choose_computer_dialog.computer_id
             computer = get_computer(email, password, computer_id)
             computer_name = computer["name"]
             reply = QMessageBox.information(
                 self,
                 "Inherit Backup History?",
                 f"You are about to inherit the backup history of the computer '{computer_name}'. Your current computer's backups will be replaced by the backups of '{computer_name}'. This is an irreversible operation. Continue?",
                 QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                 QMessageBox.StandardButton.No,
             )
             if reply == QMessageBox.StandardButton.Yes:
                 self.main_window.stop_backup()
                 current_computer_id = config["meta"]["computer_id"]
                 inherit_computer(email, password, computer_id, current_computer_id)
                 QMessageBox.information(
                     self,
                     "Inherited Backup History",
                     f"Successfully inherited the backup history of '{computer_name}'. Note that settings like inclusions, exclusions, schedule, etc. were not inherited.",
                 )
                 save_last_backed_up(
                     "Backup history inherited. Creating first backup of this computer."
                 )
                 if computer["last_backed_up_at"]:
                     save_selected_files(
                         format_selected_files(
                             int(computer["last_backed_up_num_files"]),
                             int(computer["last_backed_up_size"]),
                         )
                     )
                 self.main_window.toggle_backup()
                 self.reject()
예제 #12
0
    def save_to_file(self, configuration: Union[Dict[str, Any], None],
                     out_file_path: str) -> None:
        if configuration is None:
            return

        try:
            if not out_file_path:
                return

            file = open(out_file_path, 'w')
            json.dump(configuration, file, indent=4)
            file.close()

            QMessageBox.information(self, 'Success',
                                    'Configuration Saved Successfully!',
                                    QMessageBox.StandardButton.Ok,
                                    QMessageBox.StandardButton.Ok)
        except IOError:
            QMessageBox.critical(self, 'Failure', 'Unexpected Error Occurred',
                                 QMessageBox.StandardButton.Ok,
                                 QMessageBox.StandardButton.Ok)
    def displayItemValues(self):
        """Simple method that demonstrates how to retrieve the values 
        from the widgets."""
        # Get the model index of the item (in this case the view_button)
        # at the viewport coordinates
        index = self.table_view.indexAt(
            self.pos())  # Get the index of the button pushed
        row = index.row()  # Get the row of that button
        # Use the row value to get the index of the cells in that row, column 1
        widget_index = self.table_view.model().sibling(row, 1, QModelIndex())
        # Use indexWidget to get the QDateEdit widget
        date_edit_widget = self.table_view.indexWidget(widget_index)

        # Get value from the cell in column 0 for the selected row
        name = self.table_view.model().sibling(row, 0, QModelIndex()).data()

        # Display name and date in a QMessageBox
        QMessageBox.information(
            self, "User Information", f"""Name: {name}<br>
            <b>Birthdate: </b>{date_edit_widget.date().toString("MM/dd/yyyy")}"""
        )
예제 #14
0
    def check_update(self, test=False):
        try:
            release = github.get_latest_release(Const.author,
                                                Const.app_name,
                                                timeout=5)
            Log.append(self.check_update, 'Info', release)

            if test or common.compare_version(Const.version,
                                              release['tag_name']):
                if len(release['assets']) > 0:
                    QMessageBox.information(
                        self.lang.title_check_update, '%s\n%s\n\n%s' %
                        (self.lang.description_new_version, release['body'],
                         release['assets'][0]['browser_download_url']))
                else:
                    QMessageBox.information(
                        self.lang.title_check_update, '%s\n%s\n\n%s' %
                        (self.lang.description_new_version, release['body'],
                         release['assets'][0]['browser_download_url']))
        except:
            Log.append(self.check_update, 'Warning', common.get_exception())
예제 #15
0
 def quit_application(self):
     reply = QMessageBox.information(
         self,
         "Quit Blobbackup?",
         "Are you sure you want to quit Blobbackup?",
         QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
         QMessageBox.StandardButton.No,
     )
     if reply == QMessageBox.StandardButton.Yes:
         if self.backup_thread.backup_running():
             self.backup_thread.stop_backup()
         self.logger.info("Quit application.")
         sys.exit()
예제 #16
0
    def openImage(self):
        """Load a new image into the """
        image_file, _ = QFileDialog.getOpenFileName(
            self, "Open Image", "",
            "PNG Files (*.png);;JPG Files (*.jpeg *.jpg );;Bitmap Files (*.bmp);;\
                GIF Files (*.gif)")

        if image_file:
            # Reset values when opening an image
            self.parent.zoom_factor = 1
            #self.parent.scroll_area.setVisible(True)
            self.parent.print_act.setEnabled(True)
            self.parent.updateActions()

            # Reset all sliders
            self.parent.brightness_slider.setValue(0)

            # Get image format
            image_format = self.image.format()
            self.image = QImage(image_file)
            self.original_image = self.image.copy()

            #pixmap = QPixmap(image_file)
            self.setPixmap(QPixmap().fromImage(self.image))
            #image_size = self.image_label.sizeHint()
            self.resize(self.pixmap().size())

            #self.scroll_area.setMinimumSize(image_size)

            #self.image_label.setPixmap(pixmap.scaled(self.image_label.size(),
            #    Qt.KeepAspectRatio, Qt.SmoothTransformation))
        elif image_file == "":
            # User selected Cancel
            pass
        else:
            QMessageBox.information(self, "Error", "Unable to open image.",
                                    QMessageBox.Ok)
예제 #17
0
 def restore(self):
     path = QFileDialog.getExistingDirectory()
     if path:
         reply = QMessageBox.information(
             self,
             "Start Restore?",
             f"You are about to restore to {path}. Blobbackup will OVERWRITE any conflicting files. Continue?",
             QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
             QMessageBox.StandardButton.No,
         )
         if reply == QMessageBox.StandardButton.Yes:
             snapshot_id = self.snapshots_combo_box.currentData()
             self.restoring_gui_state()
             self.restore_thread = RestoreThread(
                 self.email,
                 self.password,
                 self.computer_id,
                 snapshot_id,
                 path,
                 self.snapshot_tree_widget,
             )
             self.restore_thread.restored.connect(self.restored)
             self.restore_thread.failed.connect(self.restore_failed)
             self.restore_thread.start()
예제 #18
0
    def saveGraphics(self):
        dbfilename = self.obsTb.dbFilename
        if dbfilename != None:
            self.session = connectDatabase(dbfilename)
        else:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Information)
            msg.setText('The database file is not defined.')
            msg.setInformativeText(
                'In order to set the database file, open the Observation Toolbox'
            )
            msg.setIcon(QMessageBox.Critical)
            msg.exec_()
            return

        if self.gView.unsavedLines == [] and self.gView.unsavedZones == [] and \
                self.gView.unsavedPoints == []:
            QMessageBox.information(self, 'Save',
                                    'No new graphical items to save!')
            return

        for item in self.gView.unsavedLines:
            x1 = round(item.line().x1(), 2)
            y1 = round(item.line().y1(), 2)
            x2 = round(item.line().x2(), 2)
            y2 = round(item.line().y2(), 2)
            line = Line(None, None, x1, y1, x2, y2)
            self.session.add(line)
            self.session.flush()
            label = self.generate_itemGroup([x1, x2], [y1, y2], line.idx)
            self.gView.scene().addItem(label)

        for item in self.gView.unsavedZones:
            xs = []
            ys = []
            for p in item.polygon():
                xs.append(round(p.x(), 2))
                ys.append(round(p.y(), 2))
            zone = Zone(None, None, xs, ys)
            self.session.add(zone)
            self.session.flush()

            label = self.generate_itemGroup(xs, ys, zone.idx)
            self.gView.scene().addItem(label)

        for item in self.gView.unsavedPoints:
            x = round(item.rect().center().x(), 2)
            y = round(item.rect().center().y(), 2)

            point = Point(x, y)
            self.session.add(point)
            self.session.flush()

            label = self.generate_itemGroup([x], [y], point.idx)
            self.gView.scene().removeItem(item)
            self.gView.scene().addItem(label)

        QMessageBox.information(
            self, 'Save',
            '{} point(s), {} line(s) and {} zone(s) saved to database successfully!'
            .format(len(self.gView.unsavedPoints),
                    len(self.gView.unsavedLines),
                    len(self.gView.unsavedZones)))
        self.gView.unsavedLines = []
        self.gView.unsavedZones = []
        self.gView.unsavedPoints = []

        self.session.commit()
예제 #19
0
 def restored(self, target):
     self.reset_gui_state()
     QMessageBox.information(self, "Restore Complete",
                             f"Your files have been restored to {target}.")
예제 #20
0
    def loadGraphics(self):
        dbfilename = self.obsTb.dbFilename
        if dbfilename != None:
            self.session = connectDatabase(dbfilename)
        else:
            msg = QMessageBox()
            # msg.setIcon(QMessageBox.Icon.Information)
            msg.setText('The database file is not defined.')
            msg.setInformativeText(
                'In order to set the database file, open the Observation Toolbox'
            )
            msg.setIcon(QMessageBox.Icon.Critical)
            msg.exec()
            return

        for gitem in self.gView.scene().items():
            if isinstance(gitem, QGraphicsItemGroup):
                self.gView.scene().removeItem(gitem)

        q_line = self.session.query(Line)
        q_zone = self.session.query(Zone)
        if q_line.all() == [] and q_zone.all() == []:
            QMessageBox.information(self, 'Warning!',
                                    'There is no graphics to load!')
            return

        line_items = []
        for line in q_line:
            p1 = line.points[0]
            p2 = line.points[1]

            if line.type != None:
                lineType = line.type.name
            else:
                lineType = None
            gItmGroup = self.generate_itemGroup([p1.x, p2.x], [p1.y, p2.y],
                                                str(line.idx), lineType)
            self.gScene.addItem(gItmGroup)

            line_items.append(str(line.idx))

        self.obsTb.line_list_wdgt.clear()
        self.obsTb.line_list_wdgt.addItems(line_items)
        self.obsTb.line_list_wdgt.setCurrentRow(0)

        self.obsTb.line_newRecButton.setEnabled(False)
        self.obsTb.line_saveButton.setEnabled(True)
        self.obsTb.line_saveButton.setText('Edit line(s)')
        self.obsTb.line_saveButton.setIcon(QIcon('icons/edit.png'))

        zone_items = []
        for zone in q_zone:
            if zone.type != None:
                zoneType = zone.type.name
            else:
                zoneType = None
            gItmGroup = self.generate_itemGroup(
                [point.x for point in zone.points],
                [point.y for point in zone.points], str(zone.idx), zoneType)
            self.gScene.addItem(gItmGroup)

            zone_items.append(str(zone.idx))

        self.obsTb.zone_list_wdgt.clear()
        self.obsTb.zone_list_wdgt.addItems(zone_items)
        self.obsTb.zone_list_wdgt.setCurrentRow(0)

        self.obsTb.zone_newRecButton.setEnabled(False)
        self.obsTb.zone_saveButton.setEnabled(True)
        self.obsTb.zone_saveButton.setText('Edit zone(s)')
        self.obsTb.zone_saveButton.setIcon(QIcon('icons/edit.png'))
예제 #21
0
class B23Download(QWidget):
    def __init__(self):
        super(B23Download, self).__init__()
        # setup some flags
        self.is_fetching = False
        self.is_downloading = False

        # default output path
        basepath = os.path.dirname(os.path.abspath(__file__))
        path = os.path.join(basepath, "videos")
        self.output_path = path

        # setup some window specific things
        self.setWindowTitle("Bilibili Favorite Downloader")
        self.setWindowIcon(QIcon("images/icon_bilibili.ico"))
        self.setFixedSize(705, 343)

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

        # top bar layout
        top_layout = QHBoxLayout()

        # detail section
        mid_main_layout = QHBoxLayout()
        mid_right_layout = QVBoxLayout()

        # download section
        bottom_main_layout = QHBoxLayout()
        bottom_right_layout = QVBoxLayout()

        # output path link button
        self.output_btn = QPushButton("📂  Output Path")
        self.output_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.output_btn.setToolTip(self.output_path)
        self.output_btn.clicked.connect(self.set_output_path)

        # status bar
        self.status_bar = QStatusBar()

        # message box
        self.message_box = QMessageBox()

        # setting up widgets
        self.url_edit = QLineEdit()
        self.url_edit.setPlaceholderText("🔍 Enter or paste favorite URL...")
        self.get_btn = QPushButton("Get")
        self.get_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.get_btn.clicked.connect(self.get_details)

        # thumbnail
        pixmap = QPixmap("images/placeholder.png")
        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("Videos: ")
        self.publish_date = QLabel("Published: ")

        # progress bar
        self.progress_bar = QProgressBar()

        # download options
        self.download_btn = QPushButton(" Download Videos ")
        self.download_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.download_btn.clicked.connect(self.get_content)
        self.download_btn.setEnabled(False)
        self.download_btn.setShortcut("Ctrl+Return")
        self.download_btn.setMinimumWidth(200)

        # add widgets and layouts
        top_layout.addWidget(self.url_edit)
        top_layout.addWidget(self.get_btn)

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

        # download section
        bottom_right_layout.addWidget(self.download_btn)
        bottom_main_layout.addWidget(self.progress_bar)
        bottom_main_layout.addSpacing(10)
        bottom_main_layout.addLayout(bottom_right_layout)

        # status bar
        self.status_bar.setSizeGripEnabled(False)
        self.status_bar.addPermanentWidget(self.output_btn)

        # add content to parent layout
        main_layout.addLayout(top_layout)
        main_layout.addSpacing(20)
        main_layout.addLayout(mid_main_layout)
        main_layout.addSpacing(5)
        main_layout.addLayout(bottom_main_layout)
        main_layout.addWidget(self.status_bar)

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

    # get button slot
    def get_details(self):
        text = self.url_edit.text().strip()

        if not text:
            return

        if text.find("fid") < 0:
            self.message_box.warning(
                self,
                "Error",
                ("Input a correct favorite URL!\n"
                 "For example: https://space.bilibili.com/xxx/favlist?fid=xxx..."
                 ),
            )
            return

        if self.get_btn.text() == "Get":
            self.get_btn.setText("Stop")
            # indicate progress bar as busy
            self.progress_bar.setRange(0, 0)
            # set fetching flag
            self.is_fetching = True
            # setup a worker thread to keep UI responsive
            self.media_id = text.split("fid=")[-1].split("&")[0]
            self.worker = WorkerThread(self.media_id)
            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.get_btn.text() == "Stop":
            if self.is_fetching:
                # stop worker thread
                self.worker.terminate()
                # set back the get_btn text
                self.get_btn.setText("Get")
            elif self.is_downloading:
                # stop download thread
                self.download_thread.terminate()
                # show the warning message_box
                self.message_box.information(
                    self,
                    "Interrupted",
                    "Download interrupted!\nThe process was aborted while the file was being downloaded... ",
                )
                # reset progress bar
                self.progress_bar.reset()

    # download options slot
    def get_content(self):
        if self.is_fetching:
            # show the warning message
            self.message_box.critical(
                self,
                "Error",
                "Please wait!\nWait while the details are being fetched... ",
            )
        else:
            # disable the download options
            self.download_btn.setDisabled(True)
            # set downloading flag
            self.is_downloading = True
            # set button to stop
            self.get_btn.setText("Stop")
            self.download_thread = DownloadThread(
                self.media_id,
                self.media_counts,
                self.first_page_medias,
                self.output_path,
            )
            # 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)

    # handling enter key for get/stop button
    def keyPressEvent(self, event):
        self.url_edit.setFocus()
        if (event.key() == Qt.Key.Key_Enter.value
                or event.key() == Qt.Key.Key_Return.value):
            self.get_details()

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

    # response slot
    def response_slot(self, res):
        # set back the button text
        self.get_btn.setText("Get")
        # set the actual thumbnail of requested video
        self.thumb.setPixmap(res.thumb_img)
        # slice the title if it is more than the limit
        if len(res.title) > 50:
            self.title.setText(f"Title: {res.title[:50]}...")
        else:
            self.title.setText(f"Title: {res.title}")
        # cache first page medias
        self.first_page_medias = res.medias
        self.media_counts = res.media_counts
        # set leftover details
        self.author.setText(f"Author: {res.author}")
        self.length.setText(f"Videos: {res.media_counts}")
        self.publish_date.setText(
            f'Published: {time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(res.publish_date))}'
        )
        self.download_btn.setDisabled(False)

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

    # download finished slot
    def download_finished_slot(self):
        # set back the button text
        self.get_btn.setText("Get")
        # now enable the download options
        self.download_btn.setDisabled(False)
        # unset downloading flag
        self.is_downloading = 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_box.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_box.critical(
            self,
            "Error",
            "Error!\nSomething unusual happened and was unable to download...",
        )
예제 #22
0
 def About(self):
     QMessageBox.information(self, 'About', 'Menu Example 0.4')
예제 #23
0
 def restore_failed(self):
     self.setWindowTitle("Restore Files - Blobbackup")
     self.set_elements_enabled(True)
     QMessageBox.information(
         self, "Restore Failed",
         "Blobbackup was unable to restore your files.")
예제 #24
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...'
        )
예제 #25
0
 def about(self):
     QMessageBox.information(self, 'About', 'Basic Editor 0.3')