class LoadZeroPointView(QDialog):
    def __init__(self, zeroPointManager: ZeroPointManager):
        super().__init__()
        self.setWindowTitle("Load Zero Point")

        self._zeroPointManager = zeroPointManager
        self._listWidget = QListWidget()

        for zeroPoint in self._zeroPointManager.getZeroPoints():
            listItem = QListWidgetItem(
                f"{zeroPoint.name} : {zeroPoint.offset}")
            self._listWidget.addItem(listItem)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.setZeroPoint)
        buttonBox.rejected.connect(self.reject)

        layout = QFormLayout()
        layout.addRow(self._listWidget)
        layout.addRow(buttonBox)

        self.setLayout(layout)

    def setZeroPoint(self):
        index = self._listWidget.indexFromItem(
            self._listWidget.selectedItems()[0]).row()
        self._zeroPointManager.setNewActiveZeroPoint(index)
        self.close()
예제 #2
0
class AutocompleteWidget(QDialog):

    WIDTH = 300
    HEIGHT = 120

    def __init__(self, suggestions: list):
        super(AutocompleteWidget, self).__init__()
        self.widget = QListWidget()
        self.widget.setStyleSheet("background-color: #232323;")
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Window)
        self.vbox = QVBoxLayout()
        self.label = QLabel("")
        self.vbox.addWidget(self.widget, 10)
        self.vbox.addWidget(self.label, 1)
        self.setLayout(self.vbox)
        self.updateSuggestionList(suggestions)
        self.result = None

    def updateSuggestionList(self, suggestions):
        self.widget.clear()
        if suggestions:
            for keyword in suggestions:
                self.widget.addItem(AutoCompleteListWidgetItem(keyword))
            self.label.setText("Number of suggestions: {}.".format(
                len(suggestions)))
        else:
            self.label.setText("No available suggestions.")
        self.setSize()

    def setSize(self):
        self.setFixedSize(self.minimumSizeHint())
        self.setFixedHeight(AutocompleteWidget.HEIGHT)
        self.setFixedWidth(AutocompleteWidget.WIDTH)

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            self.close()
        if e.key() == Qt.Key_Return:
            selectedItems = self.widget.selectedItems()
            if len(selectedItems) > 0:
                self.result = selectedItems[0]
            self.close()
        if e.key() == Qt.Key_Backspace:
            self.close()
        if e.key() == Qt.Key_Left:
            self.parent().setFocus()
class ElementPopup(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(Qt.CustomizeWindowHint)
        self.setLayout(QVBoxLayout())
        self.resize(300, 300)
        layout = QHBoxLayout()
        button_add = QPushButton('Add')
        button_close = QPushButton('Close')
        self.list_widget = QListWidget()
        self.list_widget.addItem("Comment")
        self.list_widget.addItem("Channel Send")
        layout.addWidget(button_add)
        layout.addWidget(button_close)
        self.layout().addWidget(self.list_widget)
        self.layout().addLayout(layout)
        button_add.clicked.connect(lambda: self.addElement())
        button_close.clicked.connect(self.close)
        self.exec_()

        qtRectangle = self.frameGeometry()
        centerPoint = QDesktopWidget().availableGeometry().center()
        qtRectangle.moveCenter(centerPoint)
        self.move(qtRectangle.center())

    def addElement(self):
        selectedItem = self.list_widget.selectedItems()
        try:
            widget.add_element(selectedItem[0].text(), selectedItem[0].text())
        except:
            pass
        self.close()

    def mousePressEvent(self, event):
        self.oldPos = event.globalPos()

    def mouseMoveEvent(self, event):
        delta = QPoint(event.globalPos() - self.oldPos)
        #print(delta)
        self.move(self.x() + delta.x(), self.y() + delta.y())
        self.oldPos = event.globalPos()
예제 #4
0
class Randomizer(QWidget):
    """A game randomizer for selecting a random game to play
       from the user's collection. User can select which
       platforms to choose from.
       gamesData: Raw table data in list of dictionaries"""
    def __init__(self, gamesData: list, platformsData: list, genresData: list):
        super(Randomizer, self).__init__()

        self._consoleItems = platformsData
        self._genreItems = genresData
        self._gamesData = gamesData
        self._games = []  # For holding the games to randomize
        self._gameCount = 0
        self._coverdir = path.join("data", "images", "covers")

        self.consoleLabel = QLabel("Platforms")
        self.consoleList = QListWidget()
        self.consoleList.addItems(self._consoleItems)
        self.consoleList.setSelectionMode(QAbstractItemView.MultiSelection)
        self.consoleList.setMaximumWidth(350)
        self.consoleList.itemClicked.connect(self._updateGameCount)

        self.genreLabel = QLabel("Genres")
        self.genreMatchExclusiveCB = QCheckBox("Match exclusive")
        self.genreMatchExclusiveCB.setToolTip(
            "Only match games which exclusively contain the selected genres.")
        self.genreMatchExclusiveCB.setChecked(False)
        self.genreMatchExclusiveCB.stateChanged.connect(self._updateGameCount)
        self.genreList = QListWidget()
        self.genreList.addItems(self._genreItems)
        self.genreList.setSelectionMode(QAbstractItemView.MultiSelection)
        self.genreList.setMaximumWidth(350)
        self.genreList.itemClicked.connect(self._updateGameCount)

        self.btnAll = QPushButton("Select All")
        self.btnAll.setMaximumSize(self.btnAll.sizeHint())
        self.btnAll.clicked.connect(self.consoleList.selectAll)
        self.btnAll.clicked.connect(self.genreList.selectAll)
        self.btnAll.clicked.connect(self._updateGameCount)
        self.btnNone = QPushButton("Select None")
        self.btnNone.setMaximumSize(self.btnNone.sizeHint())
        self.btnNone.clicked.connect(self.consoleList.clearSelection)
        self.btnNone.clicked.connect(self.genreList.clearSelection)
        self.btnNone.clicked.connect(self._updateGameCount)
        self._btnRnd = QPushButton("Randomize")
        self._btnRnd.setMaximumSize(self._btnRnd.sizeHint())
        self._btnRnd.clicked.connect(self._randomize)

        self._lblFont = QFont()
        self._lblFont.setPointSize(14)
        self._lblFont.setBold(True)
        self._lblPlay = QLabel()
        self._lblPlay.setAlignment(Qt.AlignCenter)
        self._lblPlay.setFont(self._lblFont)
        self._lblTitle = QLabel()
        self._lblTitle.setAlignment(Qt.AlignCenter)
        self._lblTitle.setFont(self._lblFont)
        self._lblTitle.setWordWrap(True)

        # Cover image
        self._cover = QLabel()
        self._cover.setVisible(False)
        self._cover.setAlignment(Qt.AlignCenter)
        p = QPixmap(path.join(self._coverdir, "none.png"))
        w = self._cover.width()
        h = self._cover.height()
        self._cover.setPixmap(
            p.scaled(w, h, Qt.KeepAspectRatio, Qt.SmoothTransformation))

        self._hboxButtons = QHBoxLayout()
        self._vboxLists = QVBoxLayout()
        self._vboxConsoles = QVBoxLayout()
        self._hboxGenres = QHBoxLayout()
        self._vboxGenres = QVBoxLayout()
        self._vboxResult = QVBoxLayout()
        self._grid = QGridLayout()
        self._hboxButtons.addWidget(self.btnAll, 0)
        self._hboxButtons.addWidget(self.btnNone, 0)
        self._hboxButtons.addWidget(self._btnRnd, 0)
        self._vboxConsoles.addWidget(self.consoleLabel, 0)
        self._vboxConsoles.addWidget(self.consoleList, 1)
        self._hboxGenres.addWidget(self.genreLabel, 0)
        self._hboxGenres.addWidget(self.genreMatchExclusiveCB, 0)
        self._vboxGenres.addWidget(self.genreList, 1)
        self._vboxLists.addSpacing(10)
        self._vboxLists.addLayout(self._vboxConsoles, 1)
        self._vboxLists.addSpacing(10)
        self._vboxLists.addLayout(self._hboxGenres, 0)
        self._vboxLists.addLayout(self._vboxGenres, 1)
        self._vboxResult.addStretch(3)
        self._vboxResult.addWidget(self._lblPlay, 0)
        self._vboxResult.addWidget(self._lblTitle, 0)
        self._vboxResult.addSpacing(50)
        self._vboxResult.addWidget(self._cover, 0)
        self._vboxResult.addStretch(3)
        self._grid.setMargin(0)
        self._grid.setSpacing(0)
        self._grid.addLayout(self._vboxLists, 0, 0)
        self._grid.addLayout(self._hboxButtons, 1, 0)
        self._grid.addLayout(self._vboxResult, 0, 1, 1, -1)

        self.widget = QWidget()
        self.widget.setLayout(self._grid)

    def _getSelectedItems(self) -> tuple:
        return [x.text() for x in self.consoleList.selectedItems()
                ], [x.text() for x in self.genreList.selectedItems()]

    def _randomize(self):
        platforms, genres = self._getSelectedItems()

        if len(self._games) > 0 and (len(platforms) > 0 or len(genres) > 0):
            choice = randint(0, len(self._games) - 1)
            self._lblPlay.setText("You will play:")
            self._lblTitle.setText(
                f"{self._games[choice]['name']}" if len(platforms) == 1 else
                f"{self._games[choice]['name']} [{self._games[choice]['platform']}]"
            )
            # Cover image
            cover = str(self._games[choice]['id']) + ".jpg"
            if path.exists(path.join(self._coverdir, cover)):
                # Update cover image if the game has one
                pixmap = path.join(self._coverdir, cover)
                self._cover.setVisible(True)
            else:
                pixmap = path.join(self._coverdir, "none.png")
                self._cover.setVisible(False)
            p = QPixmap(pixmap)
            w = self._cover.width()
            h = self._cover.height()
            self._cover.setPixmap(
                p.scaled(w, h, Qt.KeepAspectRatio, Qt.SmoothTransformation))
        elif len(self._games) == 0 and (len(platforms) > 0 or len(genres) > 0):
            self._lblPlay.setText("")
            self._lblTitle.setText("No games found with those criteria.")
            self._cover.setVisible(False)
        else:
            self._lblPlay.setText("")
            self._lblTitle.setText("Select at least one console or genre...")
            self._cover.setVisible(False)

    def _updateGameCount(self):
        platforms, genres = self._getSelectedItems()
        self._gameCount = 0
        self._games = []

        if len(platforms) > 0 or len(genres) > 0:
            for row in self._gamesData:
                if len(platforms) > 0 and len(genres) > 0:
                    if row["platform"] in platforms:
                        if self.genreMatchExclusiveCB.isChecked():
                            count = 0
                            for genre in row["genre"].split(", "):
                                if genre in genres:
                                    count += 1
                                else:  # Not exclusive
                                    count = 0
                                    break
                            if count == len(genres):
                                self._gameCount += 1
                                self._games.append(row)
                        else:
                            for genre in row["genre"].split(", "):
                                if genre in genres:
                                    self._gameCount += 1
                                    self._games.append(row)
                                    break  # We only need to match with one genre
                elif len(platforms) > 0 and len(genres) == 0:
                    if row["platform"] in platforms:
                        self._gameCount += 1
                        self._games.append(row)
                elif len(platforms) == 0 and len(genres) > 0:
                    if self.genreMatchExclusiveCB.isChecked():
                        count = 0
                        for genre in row["genre"].split(", "):
                            if genre in genres:
                                count += 1
                            else:  # Not exclusive
                                count = 0
                                break
                        if count == len(genres):
                            self._gameCount += 1
                            self._games.append(row)
                    else:
                        for genre in row["genre"].split(", "):
                            if genre in genres:
                                self._gameCount += 1
                                self._games.append(row)
                                break  # We only need to match with one genre

    def gameCount(self) -> int:
        return self._gameCount

    def updateLists(self, gamesData: list, platformsData: list,
                    genresData: list):
        self._gamesData = gamesData
        self._consoleItems = platformsData
        self._genreItems = genresData
        self.consoleList.clear()
        self.genreList.clear()

        self.consoleList.addItems(self._consoleItems)
        self.genreList.addItems(self._genreItems)
예제 #5
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('清单')
        self.setFixedSize(320, 480)

        # 布局
        layout = QVBoxLayout()

        # 清单视图
        self.items_view = QListWidget()
        self.items_view.setIconSize(QSize(14, 14))
        self.items_view.doubleClicked.connect(self.toggle_complete)
        layout.addWidget(self.items_view)

        # 按钮布局
        button_layout = QHBoxLayout()
        layout.addLayout(button_layout)

        # delete button
        self.delete_button = QPushButton('DELETE')
        self.delete_button.clicked.connect(self.delete)
        button_layout.addWidget(self.delete_button)

        # Complete button
        self.complete_button = QPushButton('COMPLETE')
        self.complete_button.clicked.connect(self.complete)
        button_layout.addWidget(self.complete_button)

        # add input
        self.add_input = QLineEdit()
        self.add_input.returnPressed.connect(self.add)
        layout.addWidget(self.add_input)

        # add button
        self.add_button = QPushButton('ADD')
        self.add_button.clicked.connect(self.add)
        layout.addWidget(self.add_button)

        # status bar
        self.setStatusBar(QStatusBar())

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

        self.setStyleSheet("""
            QListWidget {
                border: 1px solid #999;
                font-size: 13px;
            }
            
            QListWidget::item {
                color: #000;
                height: 30px;
                border-bottom: 1px solid #dedede;
            }
            QListWidget::item:selected {
                background-color: #fff9dd;
            }
            
            QPushButton {
                height: 24px;
                background-color: #fddb3a;
                font-weight: 900;
            }
            
            QLineEdit {
                padding: 5px;
            }
        """)

        self.items = []
        self.load()
        self.list_items()

    @Slot()
    def add(self):
        name = self.add_input.text()
        if name:
            self.items_view.addItem(QListWidgetItem(name))
            self.add_input.setText('')
            self.items.append({'name': name, 'done': False})
            # self.save()
            db.save(name, False)

    @Slot()
    def delete(self):
        items = self.items_view.selectedItems()
        if items:
            self.items.pop(self.items_view.currentRow())
            db.delete(self.items_view.currentRow() + 1)
            self.items_view.clear()
            self.list_items()
            # self.save()

    @Slot()
    def complete(self):
        items = self.items_view.selectedItems()
        if items:
            item_data = self.items[self.items_view.currentRow()]
            if not item_data['done']:
                icon = QIcon('done.svg')
                items[0].setIcon(icon)
                item_data['done'] = True
                # self.save()
                db.update(True, self.items_view.currentRow() + 1)

    @Slot()
    def toggle_complete(self):
        items = self.items_view.selectedItems()
        if items:
            item_data = self.items[self.items_view.currentRow()]
            if not item_data['done']:
                icon = QIcon('done.svg')
                items[0].setIcon(icon)
                item_data['done'] = True
                db.update(True, self.items_view.currentRow() + 1)
            else:
                icon = QIcon('')
                items[0].setIcon(icon)
                item_data['done'] = False
                db.update(False, self.items_view.currentRow() + 1)
            # self.save()

    def list_items(self):
        for item in self.items:
            list_item = QListWidgetItem(item['name'])
            if item['done']:
                icon = QIcon('done.svg')
                list_item.setIcon(icon)
            self.items_view.addItem(list_item)

    def load(self):
        # with open('data.json', 'r') as f:
        #     self.items = json.load(f)
        self.items = db.select()

    def save(self):
        with open('data.json', 'w') as f:
            json.dump(self.items, f)
예제 #6
0
class MyWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setWindowTitle(
            'Graphical utility for destroying, zeroing, and deleting files')

        self.label_donate = QLabel(
            'Copyright (c) 2021, Aleksandr Suvorov | Donate: 4048 0250 0089 5923'
        )
        self.label_donate.setAlignment(Qt.AlignCenter)

        self.label_logo = QLabel(f'Smart Cleaner<sup> {VERSION}</sup>')
        self.label_logo.setAlignment(Qt.AlignCenter)
        self.label_logo.setStyleSheet('font-size: 48px;')

        self.label_files = QLabel('Files')
        self.label_files.setStyleSheet("color: rgb(84, 180, 40);")

        self.label_dirs = QLabel('Folders')
        self.label_dirs.setStyleSheet("color: rgb(177, 98, 42);")

        self.label_errors = QLabel('Errors')
        self.label_errors.setStyleSheet("color: rgb(255, 68, 44);")

        self.lcd_files = QLCDNumber()
        self.lcd_files.setSegmentStyle(QLCDNumber.Flat)
        self.lcd_files.setStyleSheet("color: rgb(84, 180, 40);")
        self.lcd_dirs = QLCDNumber()
        self.lcd_dirs.setSegmentStyle(QLCDNumber.Flat)
        self.lcd_dirs.setStyleSheet("color: rgb(177, 98, 42);")
        self.lcd_errors = QLCDNumber()
        self.lcd_errors.setSegmentStyle(QLCDNumber.Flat)
        self.lcd_errors.setMinimumHeight(30)
        self.lcd_errors.setStyleSheet("color: rgb(255, 68, 44);")
        self.lcd_files.setDigitCount(15)
        self.lcd_dirs.setDigitCount(15)
        self.lcd_errors.setDigitCount(15)

        self.h_box1 = QHBoxLayout()
        self.h_box1.addWidget(self.label_dirs)
        self.h_box1.addWidget(self.label_files)
        self.h_box1.addWidget(self.label_errors)

        self.h_box2 = QHBoxLayout()
        self.h_box2.addWidget(self.lcd_dirs)
        self.h_box2.addWidget(self.lcd_files)
        self.h_box2.addWidget(self.lcd_errors)

        self.label_cons = QLabel('Information console:')

        self.text_browser = QTextBrowser()
        self.text_browser.setText(
            f'Smart Cleaner v{VERSION} \nUtility for overwriting, zeroing, and deleting files\n'
            f'https://github.com/mysmarthub')

        self.btn_console_clear = QPushButton('Reset')
        self.btn_donate = QPushButton('Donate | Visa: 4048 0250 0089 5923')
        self.btn_donate.setToolTip(
            'We will be grateful for any financial support.\nThis will help the program '
            'develop and remain free.\nThanks!')
        self.btn_exit = QPushButton('Exit')

        self.h_box3 = QHBoxLayout()
        self.h_box3.addWidget(self.btn_donate)
        self.h_box3.addStretch(1)
        self.h_box3.addWidget(self.btn_console_clear)

        self.chb_del_dirs = QCheckBox('Delete folders')
        self.chb_del_dirs.setChecked(True)

        self.label_shred = QLabel('Rewrite:')

        self.spin_box = QSpinBox()
        self.spin_box.setMinimum(1)
        self.spin_box.setMaximum(1000)
        self.spin_box.setValue(30)

        self.h_box4 = QHBoxLayout()
        self.h_box4.addWidget(self.chb_del_dirs)
        self.h_box4.addWidget(self.label_shred)
        self.h_box4.addWidget(self.spin_box)
        self.h_box4.addStretch(1)

        self.list_widget = QListWidget()
        self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.btn_add_folder = QPushButton('+ Folder')
        self.btn_add_files = QPushButton('+ Files')
        self.btn_remove_item = QPushButton('- Remove')
        self.btn_zero_files = QPushButton('Zeroing')
        self.btn_shred_files = QPushButton('Erasing')
        self.btn_del_files = QPushButton('Delete')

        self.h_box5 = QHBoxLayout()
        self.h_box5.addWidget(self.btn_add_folder)
        self.h_box5.addWidget(self.btn_add_files)
        self.h_box5.addWidget(self.btn_remove_item)
        self.h_box5.addStretch(1)
        self.h_box5.addWidget(self.btn_shred_files)
        self.h_box5.addWidget(self.btn_zero_files)
        self.h_box5.addWidget(self.btn_del_files)
        self.h_box5.addWidget(self.btn_exit)

        self.v_box = QVBoxLayout()
        self.v_box.addWidget(self.label_logo)
        self.v_box.addLayout(self.h_box1)
        self.v_box.addLayout(self.h_box2)
        self.v_box.addWidget(self.label_cons)
        self.v_box.addWidget(self.text_browser)
        self.v_box.addLayout(self.h_box3)
        self.v_box.addLayout(self.h_box4)
        self.v_box.addWidget(self.list_widget)
        self.v_box.addLayout(self.h_box5)
        self.v_box.addWidget(self.label_donate)

        self.setLayout(self.v_box)

        self.smart_cleaner = SmartCleaner()

        self.btn_donate.clicked.connect(
            lambda: webbrowser.open('https://yoomoney.ru/to/4100115206129186'))
        self.btn_console_clear.clicked.connect(self.clear_console)
        self.btn_add_folder.clicked.connect(self.add_dir)
        self.btn_add_files.clicked.connect(self.add_files)
        self.btn_remove_item.clicked.connect(self.remove_items)
        self.btn_shred_files.clicked.connect(self.shred_start)
        self.btn_zero_files.clicked.connect(self.zeroing_start)
        self.btn_del_files.clicked.connect(self.delete_start)
        self.btn_exit.clicked.connect(self.close)
        self.smart_cleaner.signal.connect(self.update_information)
        self.smart_cleaner.started.connect(self.at_start)
        self.smart_cleaner.finished.connect(self.at_finish)

    def clear_console(self):
        self.lcd_dirs.display(0)
        self.lcd_files.display(0)
        self.lcd_errors.display(0)
        self.text_browser.setText(
            f'Smart Cleaner v{VERSION} \nUtility for overwriting, zeroing, and deleting files\n'
            f'https://github.com/mysmarthub')

    def add_dir(self) -> None:
        path = QFileDialog.getExistingDirectory(self,
                                                'Select the folder to add: ')
        self._add_path(path)

    def add_files(self) -> None:
        path_tuple = QFileDialog.getOpenFileNames(self,
                                                  'Select files to add: ')
        for path in path_tuple[0]:
            self._add_path(path)

    def add_item(self, item: str) -> None:
        self.list_widget.addItem(item)

    def remove_items(self) -> None:
        for SelectedItem in self.list_widget.selectedItems():
            self.list_widget.takeItem(self.list_widget.row(SelectedItem))
            self.smart_cleaner.path_data.del_path(SelectedItem.text())
            self.text_browser.append(
                f'{SelectedItem.text()}\nThe path was successfully deleted!!!')

    def _add_path(self, path: str) -> None:
        if path:
            if self.smart_cleaner.path_data.add_path(path):
                self.add_item(path)
                self.text_browser.append(
                    f'{path}\nThe path was added successfully!')
            else:
                self.text_browser.append(
                    f'Error when adding or the path was added earlier!!!')

    def shred_start(self):
        self.start(method='shred')

    def zeroing_start(self):
        self.start(method='zero')

    def delete_start(self):
        self.start(method='del')

    def start(self, method='shred'):
        if not self.smart_cleaner.path_data.is_any_data:
            self.show_msg('Warning!', 'There is no data for mashing!!!')
        else:
            reply = QMessageBox.question(
                self, 'Warning!', 'The data will be destroyed, are you sure?',
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply == QMessageBox.Yes:
                if method == 'zero':
                    self.text_browser.append('Files are reset to zero.')
                elif method == 'shred':
                    self.text_browser.append('File mashing is started.')
                elif method == 'del':
                    self.text_browser.append('File deletion started.')
                self.smart_cleaner.work_method = method
                self.smart_cleaner.shreds = self.spin_box.value()
                self.smart_cleaner.delete_a_folder = self.chb_del_dirs.isChecked(
                )
                self.smart_cleaner.start()

    def update_information(self, s: str) -> None:
        self.text_browser.append(s)
        self.update_lcd()

    def update_lcd(self) -> None:
        self.lcd_dirs.display(str(self.smart_cleaner.cleaner.count_del_dirs))
        self.lcd_files.display(str(self.smart_cleaner.cleaner.count_del_files))
        self.lcd_errors.display(str(self.smart_cleaner.num_errors))

    def at_start(self):
        self.from_disable(True)

    def at_finish(self) -> None:
        if self.smart_cleaner.work_method != 'zero':
            self.list_widget.clear()
        self.update_lcd()
        self.from_disable(False)
        self.finish_msg()

    def finish_msg(self) -> None:
        if self.smart_cleaner.work_method == 'zero':
            msg = ('Reset', 'Reset files: ')
            count = self.smart_cleaner.cleaner.count_zero_files
        elif self.smart_cleaner.work_method == 'shred':
            msg = ('Mashing', 'Passageways: ')
            count = self.smart_cleaner.cleaner.count_del_files
        else:
            msg = ('Delete', 'Deleted files: ')
            count = self.smart_cleaner.cleaner.count_del_files
        self.show_msg(
            'Warning!', f'{msg[0]} completed successfully!!!\n'
            f' {msg[1]} {count}\n '
            f'Deleted folders: {self.smart_cleaner.cleaner.count_del_dirs}\n '
            f'Errors: {self.smart_cleaner.num_errors}')

    def from_disable(self, status: bool) -> None:
        self.btn_zero_files.setDisabled(status)
        self.btn_remove_item.setDisabled(status)
        self.btn_add_folder.setDisabled(status)
        self.btn_shred_files.setDisabled(status)
        self.btn_console_clear.setDisabled(status)
        self.btn_add_files.setDisabled(status)
        self.btn_del_files.setDisabled(status)
        self.chb_del_dirs.setDisabled(status)
        self.spin_box.setDisabled(status)
        self.list_widget.setDisabled(status)

    def show_msg(self,
                 title: str = 'Warning!',
                 msg: str = 'Message...') -> None:
        QMessageBox.about(self, title, msg)

    def closeEvent(self, event) -> None:
        reply = QMessageBox.question(
            self, 'Exit', 'Are you sure you want to terminate the program?',
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.hide()
            self.smart_cleaner.wait(3000)
            event.accept()
        else:
            event.ignore()
예제 #7
0
class EditCommentBankWindow(QMainWindow):
    def __init__(self, subject_name):
        QMainWindow.__init__(self)
        self.setWindowTitle("Edit Comment Bank: {} - {} {}".format(
            subject_name, config.APP_NAME, config.APP_VERSION))
        self.setMinimumWidth(1200)
        self.setStyleSheet(config.STYLESHEET)

        self.subject = could_try_harder.load(subject_name)
        self.saved_list = could_try_harder.get_saved_list()

        # Widgets
        self.intro_comment_label = QLabel("Introductory Comment:")
        self.intro_comment_label.setProperty("styleClass", "heading")
        self.intro_comment_textedit = QTextEdit()
        self.comment_bank_label = QLabel("Comment Bank")
        self.comment_bank_label.setProperty("styleClass", "heading")
        self.comment_bank_listwidget = QListWidget()
        self.placeholder_instructions_label = QLabel(
            config.PLACEHOLDER_INSTRUCTIONS)
        self.add_comment_label = QLabel("Add Comment:")
        self.add_comment_entry = QLineEdit()
        self.add_comment_button = QPushButton("Add")
        self.update_comment_label = QLabel("Update Comment:")
        self.update_comment_entry = QLineEdit()
        self.update_comment_button = QPushButton("Update")
        self.delete_comment_button = QPushButton("Delete Comment")
        self.import_comments_combo = QComboBox()
        self.import_comments_button = QPushButton("Import...")
        self.cancel_button = QPushButton("Cancel")
        self.save_button = QPushButton("Save")

        # Layout
        self.layout = QVBoxLayout()
        self.top_layout = QHBoxLayout()
        self.intro_comment_layout = QVBoxLayout()
        self.intro_comment_layout.addWidget(self.intro_comment_label)
        self.intro_comment_layout.addWidget(self.intro_comment_textedit)
        self.top_layout.addLayout(self.intro_comment_layout)
        self.top_layout.addWidget(self.placeholder_instructions_label)
        self.layout.addLayout(self.top_layout)
        self.middle_layout = QVBoxLayout()
        self.middle_layout.addWidget(self.comment_bank_label)
        self.middle_layout.addWidget(self.comment_bank_listwidget)
        self.comment_actions_layout = QHBoxLayout()
        self.comment_actions_layout.addWidget(self.delete_comment_button, 0,
                                              Qt.AlignLeft)
        self.comment_actions_layout.addWidget(self.import_comments_combo, 1,
                                              Qt.AlignRight)
        self.comment_actions_layout.addWidget(self.import_comments_button, 0,
                                              Qt.AlignRight)
        self.middle_layout.addLayout(self.comment_actions_layout)
        self.update_comment_layout = QGridLayout()
        self.update_comment_layout.addWidget(self.update_comment_label, 0, 0)
        self.update_comment_layout.addWidget(self.update_comment_entry, 0, 1)
        self.update_comment_layout.addWidget(self.update_comment_button, 0, 2)
        self.update_comment_layout.addWidget(self.add_comment_label, 1, 0)
        self.update_comment_layout.addWidget(self.add_comment_entry, 1, 1)
        self.update_comment_layout.addWidget(self.add_comment_button, 1, 2)
        self.middle_layout.addLayout(self.update_comment_layout)
        self.layout.addLayout(self.middle_layout)
        self.bottom_layout = QHBoxLayout()
        self.bottom_layout.addWidget(self.cancel_button, 0, Qt.AlignLeft)
        self.bottom_layout.addWidget(self.save_button, 0, Qt.AlignRight)
        self.layout.addLayout(self.bottom_layout)

        # Slot connections
        self.comment_bank_listwidget.itemSelectionChanged.connect(
            self.do_update_comment_bank_selection)
        self.import_comments_button.clicked.connect(self.do_import_comments)
        self.update_comment_button.clicked.connect(self.do_update_comment)
        self.update_comment_entry.returnPressed.connect(self.do_update_comment)
        self.add_comment_button.clicked.connect(self.do_add_comment)
        self.add_comment_entry.returnPressed.connect(self.do_add_comment)
        self.delete_comment_button.clicked.connect(self.do_delete_comment)
        self.cancel_button.clicked.connect(self.do_cancel)
        self.save_button.clicked.connect(self.do_save)

        # Initial UI update
        self.update_ui()

        self.widget = QWidget()
        self.widget.setLayout(self.layout)
        self.setCentralWidget(self.widget)

    def update_ui(self):
        self.update_import_comments_list()
        self.update_intro_comment()
        self.update_comment_bank()

    def update_import_comments_list(self):
        self.import_comments_combo.clear()
        self.import_comments_combo.insertItems(0, self.saved_list)

    def update_intro_comment(self):
        self.intro_comment_textedit.clear()
        self.intro_comment_textedit.insertPlainText(
            self.subject['intro_comment'])

    def update_comment_bank(self):
        self.comment_bank_listwidget.clear()
        self.comment_bank_listwidget.addItems(self.subject['comment_bank'])
        self.do_update_comment_bank_selection()

    @Slot()
    def do_import_comments(self):
        # TODO confirm dialog first
        confirm_msg = QMessageBox(self)
        confirm_msg.setWindowTitle("Confirm")
        confirm_msg.setText("This will override current comments.")
        confirm_msg.setInformativeText("Do you want to continue?")
        confirm_msg.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
        confirm_msg.setDefaultButton(QMessageBox.Yes)
        confirm = confirm_msg.exec()
        if confirm == QMessageBox.Yes:
            if self.import_comments_combo.count() > 0:
                new_subject = could_try_harder.load(
                    self.import_comments_combo.currentText())
                if new_subject:
                    self.subject['intro_comment'] = new_subject[
                        'intro_comment']
                    self.subject['comment_bank'] = new_subject['comment_bank']
                    self.update_ui()
                else:
                    # TODO better error handling here
                    print('Tried to import empty subject.')
                    return
        return

    @Slot()
    def do_update_comment_bank_selection(self):
        if self.comment_bank_listwidget.selectedItems():
            state = True
        else:
            state = False
        self.delete_comment_button.setEnabled(state)
        self.update_comment_button.setEnabled(state)
        # Update the text in the update comment line edit
        self.update_comment_entry.clear()
        if self.comment_bank_listwidget.currentItem():
            self.update_comment_entry.insert(
                self.comment_bank_listwidget.currentItem().text())

    @Slot()
    def do_update_comment(self):
        if self.update_comment_entry.text():
            self.comment_bank_listwidget.currentItem().setText(
                could_try_harder.do_style(
                    self.update_comment_entry.text().strip()))
            self.do_update_comment_bank_selection()

    @Slot()
    def do_add_comment(self):
        if self.add_comment_entry.text():
            self.comment_bank_listwidget.addItem(
                could_try_harder.do_style(
                    self.add_comment_entry.text().strip()))
            self.add_comment_entry.clear()
            self.do_update_comment_bank_selection()

    @Slot()
    def do_delete_comment(self):
        self.comment_bank_listwidget.takeItem(
            self.comment_bank_listwidget.currentRow())
        self.do_update_comment_bank_selection()

    @Slot()
    def do_cancel(self):
        self.close()

    @Slot()
    def do_save(self):
        self.subject['intro_comment'] = could_try_harder.do_style(
            self.intro_comment_textedit.toPlainText().strip())
        self.subject['comment_bank'] = []
        for i in range(self.comment_bank_listwidget.count()):
            self.subject['comment_bank'].append(
                self.comment_bank_listwidget.item(i).text())
        if could_try_harder.save(self.subject):
            self.close()
        else:
            # TODO better error handling here
            print("Save failed.")
예제 #8
0
class SelectPlayersWindow(QDialog):
    def __init__(self, parent=None):
        super(SelectPlayersWindow, self).__init__(parent)
        self.parent = parent
        self.setModal(True)
        self.setWindowTitle("Torna résztvevők")
        self.resize(520, 600)
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)
        self.read_config()

        self.create_torna_selection()

        self.nevek_layout = QHBoxLayout()
        self.layout.addLayout(self.nevek_layout)
        self.show_saved_players()
        self.show_torna_players()

        self.gomb_nev_layout = QVBoxLayout()
        self.nevek_layout.addLayout(self.gomb_nev_layout)
        self.show_current_players()

        self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonbox.clicked.connect(self.buttonbox_click)
        self.layout.addWidget(self.buttonbox)

    def create_torna_selection(self):
        self.tournaments = QComboBox()
        self.tournaments.setModelColumn(0)
        self.tournaments.currentIndexChanged.connect(self.torna_valasztas)
        self.layout.addWidget(self.tournaments)
        self.load_torna()

    def load_torna(self):
        torna = QSqlQueryModel()
        query = QSqlQuery("select * from torna_settings where aktiv=2")
        torna.setQuery(query)
        if torna.record(0).value(0):
            for i in range(torna.rowCount()):
                self.tournaments.addItem(
                    torna.record(i).value(1),
                    torna.record(i).value(0))  # a value(0) a torna_id
        else:
            print("Nincs aktív torna")

    def show_saved_players(self):
        self.saved_players = QListWidget()
        self.saved_players.setFixedHeight(500)
        self.saved_players.setFixedWidth(150)
        self.saved_players.setSortingEnabled(True)
        self.saved_players.itemDoubleClicked.connect(self.add_resztvevo)
        self.load_saved_players()
        self.nevek_layout.addWidget(self.saved_players)

    def show_torna_players(self):
        self.torna_players = QListWidget()
        self.torna_players.setFixedHeight(500)
        self.torna_players.setFixedWidth(150)
        self.torna_players.setSortingEnabled(True)
        self.torna_players.itemDoubleClicked.connect(self.add_resztvevo)
        self.load_torna_players()
        self.nevek_layout.addWidget(self.torna_players)

    def load_saved_players(self):
        players = QSqlQueryModel()
        players_query = QSqlQuery("select * from players where aktiv=1")
        players.setQuery(players_query)
        self.saved_players.clear()
        for i in range(players.rowCount()):
            item = QListWidgetItem(players.record(i).value(1))
            item.setData(Qt.UserRole, players.record(i).value(0))
            self.saved_players.addItem(item)

    def load_torna_players(self):
        players = QSqlQueryModel()
        players_query = QSqlQuery(
            "select * from torna_resztvevok where 1 group by player_id, player_name"
        )
        players.setQuery(players_query)
        self.torna_players.clear()
        for i in range(players.rowCount()):
            item = QListWidgetItem(players.record(i).value(1))
            item.setData(Qt.UserRole, players.record(i).value(0))
            self.torna_players.addItem(item)

    def add_resztvevo(self, item):
        new_item = QListWidgetItem(item)
        new_item.setData(Qt.UserRole, item.data(Qt.UserRole))
        self.current_players.addItem(new_item)
        query = QSqlQuery(
            f"insert into torna_resztvevok (player_id, player_name, torna_id) values ({new_item.data(Qt.UserRole)}, '{new_item.text()}', {self.torna_id})"
        )
        query.exec_()

    def show_current_players(self):
        query = QSqlQuery("select max(player_id) from torna_resztvevok")
        query.exec_()
        while query.next():
            self.first_new_id = int(query.value(0)) + 1
        print(self.first_new_id)
        self.add_new = QPushButton("Új")
        self.add_new.clicked.connect(self.uj_ember)
        self.current_players = QListWidget()
        self.current_players.setFixedHeight(470)
        self.current_players.setFixedWidth(150)
        self.current_players.setSortingEnabled(True)
        self.gomb_nev_layout.addWidget(self.add_new)
        self.current_players.itemDoubleClicked.connect(self.remove_resztvevo)
        self.gomb_nev_layout.addWidget(self.current_players)

    def uj_ember(self):
        ujember, ok = QInputDialog.getText(
            self, "Új versenyző",
            '<html style="font-size: 15px;">Írd be a versenyző nevét!</html>')
        if ok and len(ujember):
            item = QListWidgetItem(ujember)
            item.setData(Qt.UserRole, self.first_new_id)
            self.current_players.addItem(item)
            self.first_new_id += 1

            query = QSqlQuery(
                f"insert into torna_resztvevok (player_id, player_name, torna_id) values ({item.data(Qt.UserRole)}, '{item.text()}', {self.torna_id})"
            )
            query.exec_()

    def remove_resztvevo(self, item):
        self.current_players.takeItem(
            self.current_players.row(self.current_players.selectedItems()[0]))
        # print(item.data(Qt.UserRole), item.text())
        query = QSqlQuery(
            f"delete from torna_resztvevok where player_id={item.data(Qt.UserRole)} and torna_id={self.torna_id}"
        )
        query.exec_()

    def torna_valasztas(self, i):
        self.torna_id = self.tournaments.itemData(i)
        players = QSqlQueryModel()
        players_query = QSqlQuery(
            f"select * from torna_resztvevok where torna_id={self.torna_id}")
        players.setQuery(players_query)
        self.current_players.clear()
        for i in range(players.rowCount()):
            item = QListWidgetItem(players.record(i).value(1))
            item.setData(Qt.UserRole, players.record(i).value(0))
            self.current_players.addItem(item)

    def buttonbox_click(self, b):
        if b.text() == "OK":
            self.accept()
        elif b.text() == "Cancel":
            self.reject()

    def accept(self):
        # for i in range(self.current_players.count()):
        #     item = self.current_players.item(i)
        #     print(self.torna_id, item.data(Qt.UserRole), item.text()) # itt vannak a beszúrandó adatok
        super().accept()
        # INSERT INTO `torna_resztvevok` (`player_id`, `player_name`, `torna_id`)
        # VALUES ('1111', 'teszt_user2', '8892') ON DUPLICATE KEY UPDATE player_name='teszt_user2';
    def read_config(self):
        if os.path.exists('config.ini'):
            # Van config.ini, ki kell értékelni
            config.read('config.ini')
            self.station_id = config['DEFAULT'].get('station id')
            self.secret = config['DEFAULT'].get('secret key')
            # todo módosítani kell a torna_match táblát, hogy tartalmazza a tabla mellett a hozzá tartozó secret-et is
        else:
            # Nincs config.ini, alapértékekkel inicializálni
            msg = QMessageBox(self)
            msg.setStyleSheet("fonz-size: 20px")
            msg.setWindowTitle("Hiányzó beállítás file!")
            msg.setText(
                '<html style="font-size: 14px; color: red">Nem tudtam beolvasni a konfigurációt!<br></html>'
                +
                '<html style="font-size: 16px">Kérem módosítsa a beállításokat!</html>'
            )
            msg.exec_()
            sys.exit(1)
예제 #9
0
class FileSystemWidget(QWidget, DirectoryObserver):
    """
    Widget for listing directory contents and download files from the RDP client.
    """

    # fileDownloadRequested(file, targetPath, dialog)
    fileDownloadRequested = Signal(File, str, FileDownloadDialog)

    def __init__(self, root: Directory, parent: QObject = None):
        """
        :param root: root of all directories. Directories in root will be displayed with drive icons.
        :param parent: parent object.
        """

        super().__init__(parent)
        self.root = root
        self.breadcrumbLabel = QLabel()

        self.titleLabel = QLabel()
        self.titleLabel.setStyleSheet("font-weight: bold")

        self.titleSeparator: QFrame = QFrame()
        self.titleSeparator.setFrameShape(QFrame.HLine)

        self.listWidget = QListWidget()
        self.listWidget.setSortingEnabled(True)
        self.listWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.listWidget.customContextMenuRequested.connect(self.onCustomContextMenu)

        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.addWidget(self.breadcrumbLabel)
        self.verticalLayout.addWidget(self.listWidget)

        self.setLayout(self.verticalLayout)
        self.listWidget.itemDoubleClicked.connect(self.onItemDoubleClicked)

        self.currentPath: Path = Path("/")
        self.currentDirectory: Directory = root
        self.listCurrentDirectory()

        self.currentDirectory.addObserver(self)

    def setWindowTitle(self, title: str):
        """
        Set the window title. When the title is not blank, a title label and a separator is displayed.
        :param title: the new title.
        """

        previousTitle = self.windowTitle()

        super().setWindowTitle(title)

        self.titleLabel.setText(title)

        if previousTitle == "" and title != "":
            self.verticalLayout.insertWidget(0, self.titleLabel)
            self.verticalLayout.insertWidget(1, self.titleSeparator)
        elif title == "" and previousTitle != "":
            self.verticalLayout.removeWidget(self.titleLabel)
            self.verticalLayout.removeWidget(self.titleSeparator)

            # noinspection PyTypeChecker
            self.titleLabel.setParent(None)

            # noinspection PyTypeChecker
            self.titleSeparator.setParent(None)

    def onItemDoubleClicked(self, item: FileSystemItem):
        """
        Handle double-clicks on items in the list. When the item is a directory, the current path changes and the
        contents of the directory are listed. Files are ignored.
        :param item: the item that was clicked.
        """

        if not item.isDirectory() and not item.isDrive():
            return

        if item.text() == "..":
            self.currentPath = self.currentPath.parent
        else:
            self.currentPath = self.currentPath / item.text()

        self.listCurrentDirectory()

    def listCurrentDirectory(self):
        """
        Refresh the list widget with the current directory's contents.
        """

        node = self.root

        for part in self.currentPath.parts[1 :]:
            node = next(d for d in node.directories if d.name == part)

        self.listWidget.clear()
        self.breadcrumbLabel.setText(f"Location: {str(self.currentPath)}")

        if node != self.root:
            self.listWidget.addItem(FileSystemItem("..", FileSystemItemType.Directory))

        for directory in node.directories:
            self.listWidget.addItem(FileSystemItem(directory.name, directory.type))

        for file in node.files:
            self.listWidget.addItem(FileSystemItem(file.name, file.type))

        if node is not self.currentDirectory:
            self.currentDirectory.removeObserver(self)
            node.addObserver(self)
            self.currentDirectory = node
            node.list()

    def onDirectoryChanged(self):
        """
        Refresh the directory view when the directory has changed.
        """

        self.listCurrentDirectory()

    def currentItemText(self) -> str:
        try:
            return self.listWidget.selectedItems()[0].text()
        except IndexError:
            return ""

    def selectedFile(self) -> Optional[File]:
        text = self.currentItemText()

        if text == "":
            return None

        if text == "..":
            return self.currentDirectory.parent

        for sequence in [self.currentDirectory.files, self.currentDirectory.directories]:
            for file in sequence:
                if text == file.name:
                    return file

        return None

    def canDownloadSelectedItem(self) -> bool:
        return self.selectedFile().type == FileSystemItemType.File

    def onCustomContextMenu(self, localPosition: QPoint):
        """
        Show a custom context menu with a "Download file" action when a file is right-clicked.
        :param localPosition: position where the user clicked.
        """
        selectedFile = self.selectedFile()

        if selectedFile is None:
            return

        globalPosition = self.listWidget.mapToGlobal(localPosition)

        downloadAction = QAction("Download file")
        downloadAction.setEnabled(selectedFile.type in [FileSystemItemType.File])
        downloadAction.triggered.connect(self.downloadFile)

        itemMenu = QMenu()
        itemMenu.addAction(downloadAction)

        itemMenu.exec_(globalPosition)

    def downloadFile(self):
        file = self.selectedFile()

        if file.type != FileSystemItemType.File:
            return

        filePath = file.getFullPath()
        targetPath, _ = QFileDialog.getSaveFileName(self, f"Download file {filePath}", file.name)

        if targetPath != "":
            dialog = FileDownloadDialog(filePath, targetPath, self)
            dialog.show()

            self.fileDownloadRequested.emit(file, targetPath, dialog)
예제 #10
0
class DirectorySetChooseDialog(QDialog):
    """ simple dialog to let user choose from the available directory sets """
    def __init__(self, parent, set_pieces_and_playlist_function):
        """ pretty standard constructor: set up class variables, ui elements
            and layout parameters:
                - parent: parent widget of this dialog
                - set_pieces_and_playlist_function: is called to set the pieces
                  and playlist variables of the parent """

        super(DirectorySetChooseDialog, self).__init__(parent)

        # -- create and setup ui elements --
        self._lbl_prompt = QLabel(
            'Please choose one or more from the available directory sets:')
        self._lbl_prompt.setMaximumHeight(30)
        self._listwidget_sets = QListWidget()
        self._checkbox_shuffle = QCheckBox('Shuffle playlist')
        self._checkbox_shuffle.setChecked(True)  # shuffling enabled by default
        self._listwidget_sets.itemDoubleClicked.connect(self.__action_choose)
        self._btn_choose = QPushButton('Choose')
        self._btn_choose.clicked.connect(self.__action_choose)

        # -- setup _listwidget_sets
        options = listdir('../directories')  # get list of available sets
        options.remove('Default.txt')  # remove default entry
        # and reinsert at index 0 to ensure that 'Default' is the first option
        options.insert(0, 'Default.txt')
        self._listwidget_sets.addItems([s[:-4] for s in options])
        self._listwidget_sets.setSelectionMode(  # allow multiple selections
            QAbstractItemView.ExtendedSelection)
        self._listwidget_sets.setCurrentRow(0)  # select default entry

        # -- create layout --
        self._layout = QGridLayout(self)
        self._layout.addWidget(self._lbl_prompt, 0, 0, 1, -1)
        self._layout.addWidget(self._listwidget_sets, 1, 0, 4, -1)
        self._layout.addWidget(self._checkbox_shuffle, 5, 0, 1, -1)
        self._layout.addWidget(self._btn_choose, 6, 0, 1, -1)

        # -- various setup --
        self._set_pieces_and_playlist = set_pieces_and_playlist_function
        self.setModal(True)
        self.setWindowTitle('Please choose a directory set')
        self.setMinimumWidth(600)
        self.setMinimumHeight(400)

    def __action_choose(self):
        """ (gets called when self._btn_choose is clicked)
            loads pieces from selected sets, creates a playlist
            (shuffled if wanted) and calls self._set_pieces_and_playlist """

        selected_sets = self._listwidget_sets.selectedItems()
        selected_str = 'Currently loaded directory set(s):\n"' + \
            '", "'.join([s.text() for s in selected_sets]) + '"'
        pieces = get_pieces_from_sets(
            [s.text() + '.txt' for s in selected_sets])
        playlist = list(pieces.keys())  # must be a list to be shuffled
        shuffled = self._checkbox_shuffle.isChecked()
        if shuffled:
            shuffle(playlist)
        self._set_pieces_and_playlist(pieces, playlist, selected_str, shuffled)
        self.close()
예제 #11
0
class WordSetWidget(PluginWidget):
    """Plugin to show handle word sets from user and gather matching variants
    as a new selection.
    """

    ENABLE = True

    def __init__(self, parent=None):
        super().__init__(parent)
        self.conn = None
        self.set_names = list()
        self.setWindowTitle(self.tr("Word Sets"))
        self.toolbar = QToolBar()
        self.view = QListWidget()
        self.view.setIconSize(QSize(20, 20))
        self.view.itemDoubleClicked.connect(self.open_wordset)
        self.view.setSelectionMode(QAbstractItemView.ExtendedSelection)

        # setup tool bar
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.addAction(FIcon(0xF0415), self.tr("Add Word set"),
                               self.add_wordset)
        self.edit_action = self.toolbar.addAction(FIcon(0xF0DC9),
                                                  self.tr("Edit Word set"),
                                                  self.open_wordset)
        self.remove_action = self.toolbar.addAction(FIcon(0xF0A7A),
                                                    self.tr("Remove Word set"),
                                                    self.remove_wordset)
        self.edit_action.setEnabled(False)
        self.remove_action.setEnabled(False)

        v_layout = QVBoxLayout()
        v_layout.setContentsMargins(0, 0, 0, 0)
        v_layout.setSpacing(0)

        v_layout.addWidget(self.view)
        v_layout.addWidget(self.toolbar)

        self.setLayout(v_layout)

        # Item selected in view
        self.view.selectionModel().selectionChanged.connect(
            self.on_item_selected)

    def on_item_selected(self, *args):
        """Enable the remove button when an item is selected"""
        # Get list of all selected model item indexes
        if self.view.selectionModel().selectedIndexes():
            self.edit_action.setEnabled(True)
            self.remove_action.setEnabled(True)
        else:
            self.edit_action.setEnabled(False)
            self.remove_action.setEnabled(False)

    def import_wordset(self, words, wordset_name):
        """Import given words into a new wordset in database

        Warnings:
            There is NO CHECK on manual user's inputs! Except during DB insertion.

        Args:
            words(list): List of words to be inserted
            wordset_name(str): Name of the word set

        Returns:
            (boolean): Status of the wordset creation
        """
        # Dump the list in a temporary file
        _, filename = tempfile.mkstemp()
        with open(filename, "w") as file:
            [file.write(word + "\n") for word in words]

        # Import the content of the temp file in DB
        result = import_cmd(self.conn, "wordsets", wordset_name, filename)

        if not result["success"]:
            LOGGER.error(result)
            QMessageBox.critical(
                self,
                self.tr("Error while importing set"),
                self.tr("Error while importing set '%s'") % wordset_name,
            )

        os.remove(filename)
        return result["success"]

    def add_wordset(self):
        """Display a window to allow to add/edit/remove word sets

        The set is then imported in database.
        """
        dialog = WordListDialog()

        if dialog.exec_() != QDialog.Accepted:
            return

        wordset_name = None
        while not wordset_name:
            wordset_name, _ = QInputDialog.getText(
                self, self.tr("Create a new set"),
                self.tr("Name of the new set:"))
            if not wordset_name:
                return

            if wordset_name in self.set_names:
                # Name already used
                QMessageBox.critical(
                    self,
                    self.tr("Error while creating set"),
                    self.
                    tr("Error while creating set '%s'; Name is already used") %
                    wordset_name,
                )
                wordset_name = None

        # Import & update view
        self.import_wordset(dialog.model.stringList(), wordset_name)
        self.populate()

    def remove_wordset(self):
        """Delete word set from database"""
        if len(self.view.selectedItems()) == 0:
            # if selection is empty
            return

        reply = QMessageBox.question(
            self,
            self.tr("Drop word set"),
            self.tr("Are you sure you want to remove the selected set(s)?"),
            QMessageBox.Yes | QMessageBox.No,
        )
        if reply != QMessageBox.Yes:
            return

        # Delete all selected sets
        for i in self.view.selectedItems():
            result = drop_cmd(self.conn, "wordsets", i.text())

            if not result["success"]:
                LOGGER.error(result)
                QMessageBox.critical(
                    self,
                    self.tr("Error while deleting set"),
                    self.tr("Error while deleting set '%s'") % i.text(),
                )

        self.populate()

    def open_wordset(self):
        """Display a window to allow to edit the selected word set

        The previous set is dropped and the new is then imported in database.
        """
        wordset_name = self.view.currentItem().text()
        dialog = WordListDialog()

        # populate dialog
        dialog.model.setStringList(
            list(get_words_in_set(self.conn, wordset_name)))

        if dialog.exec_() == QDialog.Accepted:
            # Drop previous
            drop_cmd(self.conn, "wordsets", wordset_name)
            # Import new
            self.import_wordset(dialog.model.stringList(), wordset_name)
            self.populate()

    def on_open_project(self, conn):
        """ override """
        self.conn = conn
        self.on_refresh()

    def on_refresh(self):
        """ override """
        if self.conn:
            self.populate()

    def populate(self):
        """Actualize the list of word sets"""
        self.view.clear()
        self.set_names = list()
        for data in get_wordsets(self.conn):
            set_name = data["name"]
            item = QListWidgetItem()
            item.setText(set_name)
            item.setIcon(FIcon(0xF0A38))
            self.view.addItem(item)
            self.set_names.append(set_name)
예제 #12
0
class SynthPdfWidget(QWidget):
    def __init__(self, status_bar):
        super(SynthPdfWidget, self).__init__()
        self.status_bar = status_bar
        layout = QHBoxLayout()
        self.list_view = QListWidget()
        self.list_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.list_view.setAlternatingRowColors(True)
        self.list_view.itemClicked.connect(self.click_item_signal)
        self.list_view.itemEntered.connect(self.click_item_signal)
        self.list_view.itemSelectionChanged.connect(
            self.change_selection_signal)

        controls_layout = QVBoxLayout()
        controls_layout.setAlignment(Qt.AlignTop)

        select_zone = SelectWidget(self.click_move_up, self.click_move_down,
                                   self.click_invert, self.click_delete)
        select_zone.setMinimumWidth(250)

        add_pages_button = QPushButton("Add Pages From PDF")
        add_pages_button.clicked.connect(self.add_pdf)

        controls_layout.addWidget(select_zone)
        controls_layout.addWidget(add_pages_button)

        layout.addWidget(self.list_view)
        layout.addLayout(controls_layout)
        self.setLayout(layout)

    def _add_pages_from_pdf(self, pdf_path):
        with open(pdf_path, "rb") as file:
            reader = PdfFileReader(file)
            file_name = os.path.basename(pdf_path)
            pages_count = reader.getNumPages()
            for i in range(pages_count):
                new_item = ImageListItem(
                    "page " + str(i + 1) + " (" + file_name + ")",
                    (pdf_path, i))
                self.list_view.addItem(new_item)
            self.status_bar.showMessage("Add " + str(pages_count) + " pages")

    # ----------external methods from create command
    def extern_get_files_and_pages(
        self
    ):  # return selected pages in the form {file1: [p1, p2, ...], file2: [p1, p2, ...], ...}
        to_return = {}
        if len(self.list_view.selectedItems()
               ) == 0:  # nothing selected, add all pages
            items_count = self.list_view.count()
            for item_index in range(items_count):
                item = self.list_view.item(item_index)
                item_data = item.get_data()
                file_name = item_data[0]
                page_index = item_data[1]
                if file_name in to_return:
                    to_return[file_name].append(page_index)
                else:
                    to_return[file_name] = [page_index]
        else:
            for s in self.list_view.selectedItems():
                s_data = s.get_data()
                file_name = s_data[0]
                page_index = s_data[1]
                if file_name in to_return:
                    to_return[file_name].append(page_index)
                else:
                    to_return[file_name] = [page_index]
        return to_return

    # ----------add button-----------------------
    def add_pdf(self):
        files_dialog = QFileDialog()
        files_dialog.setNameFilter("PDF (*.pdf)")
        files_dialog.setFileMode(QFileDialog.ExistingFiles)
        if files_dialog.exec_():
            files = files_dialog.selectedFiles()
            for f_path in files:
                self._add_pages_from_pdf(f_path)

    # ----------List_view signals----------------
    def click_item_signal(self, item):
        self.status_bar.showMessage("Select " + str(item.text()))

    def change_selection_signal(self):
        if len(self.list_view.selectedItems()) == 0:
            # self._set_preview(None)  # nothing selected
            pass

    # ----------list_view commands---------------
    def click_move_up(self):
        selected = self.list_view.selectedItems()
        selected_indexes = [
            self.list_view.indexFromItem(sel).row() for sel in selected
        ]
        selected_indexes.sort()
        if len(selected_indexes) > 0 and selected_indexes[0] > 0:
            for index in selected_indexes:
                prev_item = self.list_view.takeItem(index - 1)
                self.list_view.insertItem(index, prev_item)
            self.status_bar.showMessage("Move " + str(len(selected_indexes)) +
                                        " items")
        else:
            self.status_bar.showMessage("Nothing to move")

    def click_move_down(self):
        selected = self.list_view.selectedItems()
        selected_indexes = [
            self.list_view.indexFromItem(sel).row() for sel in selected
        ]
        selected_indexes.sort()
        sel_count = len(selected_indexes)
        if len(selected_indexes) > 0 and selected_indexes[
                sel_count - 1] < self.list_view.count() - 1:
            for i_index in range(sel_count):
                next_item = self.list_view.takeItem(
                    selected_indexes[sel_count - i_index - 1] + 1)
                self.list_view.insertItem(
                    selected_indexes[sel_count - i_index - 1], next_item)
            self.status_bar.showMessage("Move " + str(len(selected_indexes)) +
                                        " items")
        else:
            self.status_bar.showMessage("Nothing to move")

    def click_invert(self):
        selected = self.list_view.selectedItems()
        selected_indexes = []
        for sel in selected:
            selected_indexes.append(self.list_view.indexFromItem(sel).row())
        total_indexes = [i for i in range(self.list_view.count())]
        new_indexes = []
        for i in total_indexes:
            if i not in selected_indexes:
                new_indexes.append(i)
        self.list_view.clearSelection()
        for i in new_indexes:
            self.list_view.item(i).setSelected(True)
        self.status_bar.showMessage("Invert selection: " + str(new_indexes))

    def click_delete(self):
        selected = self.list_view.selectedItems()
        delete_names = []
        for s in selected:
            s_index = self.list_view.indexFromItem(s).row()
            del_item = self.list_view.takeItem(s_index)
            delete_names.append(del_item.text())
        if len(delete_names) == 0:
            self.status_bar.showMessage("Nothing to delete")
        else:
            self.status_bar.showMessage("Delete items: " +
                                        ", ".join(delete_names))
예제 #13
0
class EditReportsWindow(QMainWindow):
    def __init__(self, subject_name):
        QMainWindow.__init__(self)
        self.setWindowTitle("Edit Reports: {} - {} {}".format(
            subject_name, config.APP_NAME, config.APP_VERSION))
        self.setMinimumWidth(1200)
        self.setStyleSheet(config.STYLESHEET)

        self.subject = could_try_harder.load(subject_name)
        self.student = {}

        # Used to keep track of current student
        self.s_index = 0
        self.load_student()

        # Widgets
        self.previous_student_button = QPushButton("Previous Student")
        self.student_name_label = QLabel()
        self.student_name_label.setProperty("styleClass", "title")
        self.next_student_button = QPushButton("Next Student")
        self.intro_comment_label = QLabel("Introductory Comment")
        self.intro_comment_label.setProperty("styleClass", "heading")
        self.intro_comment = QLabel()
        self.comment_bank_label = QLabel("Comment Bank")
        self.comment_bank_label.setProperty("styleClass", "heading")
        self.comment_bank_listwidget = QListWidget()
        self.add_comment_button = QPushButton("Add Selected Comment")
        self.comment_label = QLabel("Student Comment")
        self.comment_label.setProperty("styleClass", "heading")
        self.comment_textedit = QTextEdit()
        self.cancel_button = QPushButton("Cancel")
        self.save_button = QPushButton("Save")

        # Layout
        self.layout = QVBoxLayout()
        self.top_layout = QHBoxLayout()
        self.top_layout.addWidget(self.previous_student_button, 0,
                                  Qt.AlignLeft)
        self.top_layout.addWidget(self.student_name_label, 1, Qt.AlignCenter)
        self.top_layout.addWidget(self.next_student_button, 0, Qt.AlignRight)
        self.layout.addLayout(self.top_layout)
        self.middle_layout = QVBoxLayout()
        self.middle_layout.addWidget(self.intro_comment_label)
        self.middle_layout.addWidget(self.intro_comment)
        self.middle_layout.addWidget(self.comment_bank_label)
        self.middle_layout.addWidget(self.comment_bank_listwidget)
        self.middle_layout.addWidget(self.add_comment_button)
        self.middle_layout.addWidget(self.comment_label)
        self.middle_layout.addWidget(self.comment_textedit)
        self.layout.addLayout(self.middle_layout)
        self.bottom_layout = QHBoxLayout()
        self.bottom_layout.addWidget(self.cancel_button, 0, Qt.AlignLeft)
        self.bottom_layout.addWidget(self.save_button, 0, Qt.AlignRight)
        self.layout.addLayout(self.bottom_layout)

        # Slots
        self.previous_student_button.clicked.connect(self.do_previous_student)
        self.next_student_button.clicked.connect(self.do_next_student)
        self.comment_bank_listwidget.itemSelectionChanged.connect(
            self.do_update_comment_bank_selection)
        self.add_comment_button.clicked.connect(self.do_add_comment)
        self.cancel_button.clicked.connect(self.do_cancel)
        self.save_button.clicked.connect(self.do_save)

        # Initial UI Update
        self.update_ui()

        self.widget = QWidget()
        self.widget.setLayout(self.layout)
        self.setCentralWidget(self.widget)

    def update_ui(self):
        # Page title
        self.student_name_label.setText(self.student['first_name'] + " " +
                                        self.student['last_name'])

        # Enable/Disabled Next/Previous Buttons
        if self.s_index <= 0:
            self.previous_student_button.setEnabled(False)
        else:
            self.previous_student_button.setEnabled(True)
        if self.s_index < len(self.subject['students']) - 1:
            self.next_student_button.setEnabled(True)
        else:
            self.next_student_button.setEnabled(False)

        self.do_update_comment_bank_selection()

        # Intro comment
        self.intro_comment.setText(
            could_try_harder.do_placeholders(self.subject['intro_comment'],
                                             self.student['first_name'],
                                             self.student['pronouns']))

        # Comment Bank
        self.comment_bank_listwidget.clear()
        for comment in self.subject['comment_bank']:
            self.comment_bank_listwidget.addItem(
                could_try_harder.do_placeholders(comment,
                                                 self.student['first_name'],
                                                 self.student['pronouns']))

        # Student Comment
        self.comment_textedit.clear()
        self.comment_textedit.insertPlainText(self.student['comment'])

    def load_student(self):
        """
        Loads student into the self.student dict temporarily
        """
        self.student = self.subject['students'][self.s_index]

    def save_comment(self):
        """
        Saves student comment into the self.subject dict temporarily. Not saved into the save file.
        """
        comment = self.comment_textedit.toPlainText()
        comment = could_try_harder.do_placeholders(comment,
                                                   self.student['first_name'],
                                                   self.student['pronouns'])
        comment = could_try_harder.do_style(comment)

        self.subject['students'][self.s_index]['comment'] = comment

    @Slot()
    def do_next_student(self):
        if self.s_index < len(self.subject['students']) - 1:
            self.save_comment()
            self.s_index += 1
            self.load_student()
            self.update_ui()

    @Slot()
    def do_previous_student(self):
        if self.s_index > 0:
            self.save_comment()
            self.s_index -= 1
            self.load_student()
            self.update_ui()

    @Slot()
    def do_update_comment_bank_selection(self):
        # Enable/Disable the Add Comment button
        if self.comment_bank_listwidget.selectedItems():
            self.add_comment_button.setEnabled(True)
        else:
            self.add_comment_button.setEnabled(False)

    @Slot()
    def do_add_comment(self):
        # Add a space if we need to.
        if not self.comment_textedit.textCursor().atStart(
        ) and not self.comment_textedit.textCursor().block().text().endswith(
                " "):
            self.comment_textedit.insertPlainText(" ")
        self.comment_textedit.insertPlainText(
            self.comment_bank_listwidget.currentItem().text())

    @Slot()
    def do_save(self):
        self.save_comment()
        if could_try_harder.save(self.subject):
            self.close()
        else:
            # TODO better error handling here
            print("Save failed")

    @Slot()
    def do_cancel(self):
        self.close()
예제 #14
0
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowTitle("{} {}".format(config.APP_NAME,
                                           config.APP_VERSION))
        self.setMinimumWidth(600)
        self.setStyleSheet(config.STYLESHEET)

        # Widgets
        self.import_label = QLabel(
            'Import a CSV class list to add a new class of reports.')
        self.import_button = QPushButton('Import CSV...')
        self.saved_label = QLabel('You have the following saved classes:')
        self.saved_listwidget = QListWidget(self)
        self.edit_comment_bank_button = QPushButton('Edit Comment Bank')
        self.edit_reports_button = QPushButton('Edit Reports')
        self.export_reports_button = QPushButton('Export Reports')
        self.delete_class_button = QPushButton('Delete')

        # Layout
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.import_label)
        self.layout.addWidget(self.import_button)
        self.layout.addWidget(self.saved_label)
        self.layout.addWidget(self.saved_listwidget)
        self.layout.addWidget(self.edit_comment_bank_button)
        self.layout.addWidget(self.edit_reports_button)
        self.layout.addWidget(self.export_reports_button)
        self.layout.addWidget(self.delete_class_button)

        # Initial run of listbox update
        self.update_saved_list()

        # Slot connections
        self.import_button.clicked.connect(self.import_csv)
        self.saved_listwidget.itemSelectionChanged.connect(
            self.do_update_selection)
        self.edit_comment_bank_button.clicked.connect(self.edit_comment_bank)
        self.edit_reports_button.clicked.connect(self.edit_reports)
        self.export_reports_button.clicked.connect(self.export_reports)
        self.delete_class_button.clicked.connect(self.delete_class)

        self.widget = QWidget()
        self.widget.setLayout(self.layout)

        self.setCentralWidget(self.widget)

    @Slot()
    def import_csv(self):
        # TODO proper validation for input will mean building this dialog out
        # properly using QLineEdit
        subject_name, ok = QInputDialog().getText(
            self, "Subject Name", "Enter a name or code for the subject:")
        if subject_name and ok:
            filename, filt = QFileDialog.getOpenFileName(
                self, "Import CSV", os.path.expanduser("~"),
                "Comma Separated (*.csv)")
            if could_try_harder.import_class_list(filename, subject_name):
                self.update_saved_list()
            else:
                # TODO better error handling here
                print("Import Failed")
                return

    def update_saved_list(self):
        self.saved_listwidget.clear()
        self.saved_listwidget.addItems(could_try_harder.get_saved_list())
        self.do_update_selection()

    @Slot()
    def do_update_selection(self):
        if self.saved_listwidget.selectedItems():
            state = True
        else:
            state = False
        self.edit_comment_bank_button.setEnabled(state)
        self.edit_reports_button.setEnabled(state)
        self.export_reports_button.setEnabled(state)
        self.delete_class_button.setEnabled(state)

    @Slot()
    def edit_comment_bank(self):
        subject_name = self.saved_listwidget.currentItem().text()
        self.edit_comment_bank_window = EditCommentBankWindow(subject_name)
        self.edit_comment_bank_window.show()

    @Slot()
    def edit_reports(self):
        subject_name = self.saved_listwidget.currentItem().text()
        self.edit_reports_window = EditReportsWindow(subject_name)
        self.edit_reports_window.show()

    @Slot()
    def export_reports(self):
        subject_name = self.saved_listwidget.currentItem().text()
        filename, filt = QFileDialog.getSaveFileName(self, "Export",
                                                     os.path.expanduser("~"),
                                                     "Text Files (*.txt)")
        if filename:
            if not could_try_harder.export(subject_name, filename):
                # TODO better error handling here
                print("Export failed.")
                return

    @Slot()
    def delete_class(self):
        confirm_msg = QMessageBox(self)
        confirm_msg.setWindowTitle("Confirm")
        confirm_msg.setText(
            "This will delete the class, comment bankd and reports.")
        confirm_msg.setInformativeText("Continue?")
        confirm_msg.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
        confirm_msg.setDefaultButton(QMessageBox.Yes)
        confirm = confirm_msg.exec()
        if confirm == QMessageBox.Yes:
            subject_name = self.saved_listwidget.currentItem().text()
            if not could_try_harder.delete(subject_name):
                # TODO better error handling here
                print("Delete failed.")
            self.update_saved_list()
예제 #15
0
class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()

        self.lastProjectDirectory = None
        self.view = None
        self.items = dict()

        self.loadSettings()

        self.setWindowTitle("2D Tagger")
        self.createActions()
        self.createMenus()
        self.createFileList()
        self.createContainer()
        self.createStatusBar()

    def loadSettings(self):
        try:
            with io.open(Path(__file__).parent / 'app.json', 'r') as f:
                data = json.load(f)
                if 'lastProjectDirectory' in data:
                    self.lastProjectDirectory = data['lastProjectDirectory']
        except:
            pass

    def saveSettings(self):
        data = dict()
        data['lastProjectDirectory'] = self.lastProjectDirectory
        with io.open(Path(__file__).parent / 'app.json', 'w') as f:
            json.dump(data, f, indent=' ')

    def createActions(self):
        # root = QFileInfo(__file__).absolutePath()
        self.openAct = QAction(
            # QIcon(root + '/icons/open.png'),
            "&Open",
            self,
            shortcut=QKeySequence.Open,
            statusTip="Open project",
            triggered=self.openProject)
        self.closeAct = QAction(
            # QIcon(root + '/icons/close.png'),
            "&Close",
            self,
            shortcut=QKeySequence.Close,
            statusTip="Close project",
            triggered=self.closeProject,
            enabled=False)
        self.exitAct = QAction(
            # QIcon(root + '/icons/quit.png'),
            "&Quit",
            self,
            shortcut=QKeySequence.Quit,
            statusTip="Close the application",
            triggered=self.close)
        self.aboutAct = QAction("&About",
                                self,
                                statusTip="Show the application's About box",
                                triggered=self.about)

    def createMenus(self):
        fileMenu = self.menuBar().addMenu("&File")
        fileMenu.addAction(self.openAct)
        fileMenu.addAction(self.closeAct)
        fileMenu.addSeparator()
        fileMenu.addAction(self.exitAct)

        self.menuBar().addSeparator()
        helpMenu = self.menuBar().addMenu("&Help")
        helpMenu.addAction(self.aboutAct)

    def createFileList(self):
        self.files = QListWidget()
        self.files.setSelectionMode(QAbstractItemView.SingleSelection)
        self.files.setSortingEnabled(False)
        self.files.itemSelectionChanged.connect(self.onSelect)
        self.files.itemDoubleClicked.connect(self.onToggle)
        self.files.setEnabled(False)

        dock = QDockWidget("Images", self)
        dock.setAllowedAreas(Qt.LeftDockWidgetArea)
        dock.setFixedWidth(320)
        dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        dock.setWidget(self.files)
        self.addDockWidget(Qt.LeftDockWidgetArea, dock)

    def createContainer(self):
        self.container = QWidget(self)
        self.container.setStyleSheet("View { background: black; }")
        self.container.setLayout(QVBoxLayout())
        self.setCentralWidget(self.container)

    def createStatusBar(self):
        self.statusBar().showMessage("Initialized")

    def enableProjectActions(self, enabled):
        actions = [self.closeAct, self.files]
        for action in actions:
            action.setEnabled(enabled)

    def closeEvent(self, event):
        event.accept()

    def openProject(self, path=None):
        if not path:
            path = QFileDialog.getExistingDirectory(
                self, "Choose image directory", dir=self.lastProjectDirectory)
        if path:
            self.closeProject()

            self.view = View(self)
            self.view.previous.connect(self.onPrevious)
            self.view.next.connect(self.onNext)
            self.container.layout().addWidget(self.view)

            filename = Path(path) / "items.json"
            if filename.exists():
                with io.open(filename, 'r') as f:
                    self.items = json.load(f)
            else:
                self.items = dict()
            for filename in find_images(Path(path)):
                if filename in self.items:
                    continue
                self.items[filename] = dict({"active": True})

            self.refreshItems()
            self.files.setItemSelected(self.files.item(0), True)

            self.enableProjectActions(True)

            self.lastProjectDirectory = path
            self.saveProject()
            self.saveSettings()

    def saveProject(self):
        if not self.view:
            return
        with io.open(Path(self.lastProjectDirectory) / "items.json", 'w') as f:
            json.dump(self.items, f, indent='  ')

    def closeProject(self):
        self.enableProjectActions(False)
        if self.view:
            self.container.layout().removeWidget(self.view)
            self.view.close()
            self.view = None
        self.items = dict()
        self.refreshItems()

    def selection(self):
        selection = self.files.selectedItems()
        if len(selection) > 0:
            return selection[0].text()
        return None

    def refreshItems(self):
        filenames = sorted(self.items.keys())
        for i in range(len(filenames)):
            filename = filenames[i]
            item = self.items[filename]
            file = self.files.item(i)
            if not file:
                file = QListWidgetItem(filenames[i])
                self.files.insertItem(i, file)
            if item['active']:
                file.setTextColor(QColor.fromRgbF(0.0, 0.5, 0.0))
            else:
                file.setTextColor(QColor.fromRgbF(0.5, 0.0, 0.0))
        while self.files.count() > len(filenames):
            self.files.takeItem(len(filenames))

    @Slot()
    def onToggle(self, item):
        self.items[
            item.text()]['active'] = not self.items[item.text()]['active']
        self.refreshItems()
        self.saveProject()

    @Slot()
    def onSelect(self):
        selection = self.selection()
        if self.view:
            self.view.save()
            if selection:
                self.view.load(Path(self.lastProjectDirectory) / selection)

    @Slot()
    def onPrevious(self):
        if self.files.count() == 0:
            return
        index = 0
        selection = self.selection()
        if selection:
            for i in range(self.files.count()):
                item = self.files.item(i)
                if item.text() == selection:
                    index = i - 1
                    break
        if index < 0:
            index = self.files.count() - 1
        self.files.setItemSelected(self.files.item(index), True)

    @Slot()
    def onNext(self):
        if self.files.count() == 0:
            return
        index = 0
        selection = self.selection()
        if selection:
            for i in range(self.files.count()):
                item = self.files.item(i)
                if item.text() == selection:
                    index = i + 1
                    break
        if index >= self.files.count():
            index = 0
        self.files.setItemSelected(self.files.item(index), True)

    @Slot(str)
    def showMessage(self, message):
        self.statusBar().showMessage(message)

    def about(self):
        QMessageBox.about(
            self, "About Application",
            "The <b>2D Tagger</b> can load images, manually tag/label images and export result."
        )
예제 #16
0
class TimerWindow(QWidget):

    elapsed_time = 0
    thread_running = False
    #api_token = 'fea20970f5bb1b75c96dfa8985fd15b2a3c0f8a8d3261381d0176a05475781ee88d9f7252511e5e085b99e1cee37efa86f7364b7ed5203bccd2c2fd9b76057fe'
    apa = IdleTime()
    workingthread = None
    systray = None
    db = Database()
    api_token = db.readDatabase()['userdata']['api_token']

    def __init__(self):
        super().__init__()
        self.title = 'Timey'
        self.left = 10
        self.top = 10
        self.width = 440
        self.height = 680
        self.initUI()
        self.NetworkSetup()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setWindowIcon(QIcon(Config.icon))
        self.setGeometry(self.left, self.top, self.width, self.height)

        layout = QGridLayout()
        self.setLayout(layout)
        layout.setColumnStretch(1, 4)
        layout.setColumnStretch(2, 4)

        style = """
            background-color: white;
            border-bottom: 1px solid #fff123;
            """

        self.setStyleSheet(style)
        self.labeltimer = QLabel('00:00:00', self)
        self.labeltimer.setAlignment(Qt.AlignCenter)
        self.labeltimer.setStyleSheet("""QLabel {
    font: medium Ubuntu;
    font-size: 32px;
    color: #006325;
    border-width:1px;
} """)

        fa5_icon = qta.icon('fa5s.play')
        #fa5_button = QtGui.QPushButton(fa5_icon, 'Font Awesome! (regular)')
        self.button = QPushButton(fa5_icon, "Start")
        self.button.clicked.connect(self.clickStart)
        self.button.setStyleSheet("""QPushButton {
    #background-color: #f06325;
    #color: white;
    #font-color: white;

    #min-width:  70px;
    #max-width:  70px;
    #min-height: 70px;
    #max-height: 70px;

    #border-radius: 35px;
    #border-width: 1px;
    border-color: #ae32a0;
    border-style: solid;
}
QPushButton:hover {
    background-color: #328930;
}
QPushButton:pressed {
    background-color: black;
    color: black;
    border-width:10px;
}
""")

        #self.label4 = QLabel('Working: ', self)
        #self.label4.setAlignment(Qt.AlignCenter)
        self.label3 = QLabel('None', self)
        self.label3.setAlignment(Qt.AlignCenter)

        self.test = QListWidget(self)
        self.test.addItem("item4")
        self.test.itemSelectionChanged.connect(self.selectItem)

        self.addtask = QLineEdit(self)
        #fa5_plusicon = qta.icon('fa5s.plus')
        self.addtaskbutton = QPushButton(qta.icon('fa5s.plus'), "Add")
        self.addtaskbutton.clicked.connect(self._click_additem)

        self.deltaskbutton = QPushButton(qta.icon('fa5s.minus'), "Del")
        self.deltaskbutton.clicked.connect(self._click_deltask)

        self.tasks = QListWidget(self)
        self.tasks.addItem("No tasks")

        layout.addWidget(self.labeltimer, 0, 0)
        layout.addWidget(self.button, 0, 1)
        #layout.addWidget(self.label4,1,0)
        layout.addWidget(self.label3, 1, 0)
        layout.addWidget(self.test, 2, 0)
        layout.addWidget(self.addtask, 3, 0)
        layout.addWidget(self.addtaskbutton, 3, 1)
        layout.addWidget(self.deltaskbutton, 3, 2)
        layout.addWidget(self.tasks, 4, 0)

        self.show()
        print("init end")

    def _update_timer(self):
        if self.thread_running == True:
            self.thread_running = False
            return 0
        while True:
            #self.elapsed_time = time.time()
            self.thread_running = True
            ''' this is little weired.. but works for now '''
            if self.apa.thread_exit == True or self.thread_exit == True:
                data = api.activity_current(self.api_token)
                print(data)
                if not data.get('error'):
                    api.activity_stop(self.api_token, data['id'])
                self.button.setText('Start')
                self.workingthread.exit()
                self.thread_running = False
                break
            self.elapsed_time += 1
            self.labeltimer.setText(self._online_time(self.elapsed_time))
            time.sleep(1)

    def _click_additem(self):
        print("oh oh oh oh")
        print(self.addtask.text())
        text = self.addtask.text()
        project_id = None

        if len(text) > 0:
            print("This seems acceptable")
            for _x in self.test.selectedItems():
                project_id = _x.data(Qt.UserRole)
            print(project_id)

            if project_id == None:
                QMessageBox.information(self, 'PyQt5 message',
                                        "Please select a a project first",
                                        QMessageBox.Ok)
            else:
                api.task_add(self.api_token, project_id, text)
                self.selectItem()
        else:
            QMessageBox.information(self, 'PyQt5 message',
                                    "Please enter a taskname first!",
                                    QMessageBox.Ok)
            print("please enter a name of the task you want to add first")

    def _click_deltask(self):
        print("Ooopsie")

        task_id = None
        for _x in self.tasks.selectedItems():
            task_id = _x.data(Qt.UserRole)

        print(task_id)

        if task_id is not None:
            api.task_delete(self.api_token, task_id)
            self.selectItem()
        else:
            QMessageBox.information(self, 'PyQt5 message',
                                    "unable to delete task, no such task_id",
                                    QMessageBox.Ok)

    def clickStart(self):
        logging.debug("click start/stop button")
        print(self.button.text())
        #self.test.clear()
        data = {}
        ''' user click start timer '''
        if self.button.text() == 'Start':
            project_id = None
            task_id = None
            for _x in self.test.selectedItems():
                project_id = _x.data(Qt.UserRole)

            for _x in self.tasks.selectedItems():
                task_id = _x.data(Qt.UserRole)

            if project_id == None:
                msgBox = QMessageBox()
                msgBox.setIcon(QMessageBox.Information)
                msgBox.setText("Please select a project first")
                msgBox.setWindowTitle("Select project")
                msgBox.setStandardButtons(QMessageBox.Ok)
                msgBox.exec()
                print("Please select one of your project first")
                return 0
            else:
                data = api.activity_start(self.api_token, project_id, task_id)
            ''' this need to be fix '''
            try:
                if data.get('error'):
                    errorBox = DialogBox()
                    returnValue = errorBox.MsgBox(
                        data.get('error') +
                        "Do you want to stop current activity?", "error")

                    if returnValue == QMessageBox.Ok:
                        data = api.activity_current(self.api_token)
                        print(data)
                        api.activity_stop(self.api_token, data['id'])
                        print("Time to do something weired!")

                    return 0  #do we need this?

                    #print(data.get('error'))
                elif data:
                    #apa = IdleTime()
                    self.apa.thread_exit = False
                    print(self.workingthread)
                    self.workingthread = QThread()
                    self.workingthread.started.connect(self.apa.thread_handle)
                    #self.apa.moveToThread(self.workingthread)
                    self.workingthread.start()

                    self.thread_exit = False
                    t = threading.Thread(target=self._update_timer)
                    t.start()
                    self.systray.StartWorking.setText("Stop Working")
                    self.button.setText('Stop')
                    fa5s_icon = qta.icon('fa5s.stop')
                    self.button.setIcon(fa5s_icon)
                    self.test.setDisabled(True)
                    return 1
            except AttributeError:
                ''' if we reach this stage we either got an invalid API response (no error field) or our internet connection isnt working '''
                #errorBox = DialogBox()
                #errorBox.MsgBox("No internet connection or invalid API response", "error")
                QMessageBox.information(
                    self, 'error',
                    "No internet connection or invalid API response",
                    QMessageBox.Ok)

        else:
            ''' stop activity if its running '''
            data = api.activity_current(self.api_token)
            print(data)
            api.activity_stop(self.api_token, data['id'])
            self.thread_exit = True
            self.apa.thread_exit = True
            self.systray.StartWorking.setText("Start Working")
            self.button.setText('Start')
            fa5s_icon = qta.icon('fa5s.play')
            self.button.setIcon(fa5s_icon)
            self.test.setDisabled(False)
        print("end of clickstart")

    def selectItem(self):
        for _x in self.test.selectedItems():
            self.label3.setText(_x.text())
            print(_x.text())
            print(_x.data(Qt.UserRole))
        try:
            data = api.task_get(self.api_token, _x.data(Qt.UserRole))
        except ApiException:
            data = self.db.searchTask(_x.data(Qt.UserRole))
        self.tasks.clear()
        print(data)
        for _x in data:
            item = QListWidgetItem(_x["name"], self.tasks)
            item.setData(Qt.UserRole, _x["task_id"])

        #print(self.test.text())

    def NetworkSetup(self):
        self.test.clear()
        data_p2 = None
        data_p = None
        try:
            data_p = api.get_projects(self.api_token)
        except ApiException:
            data_p = self.db.readDatabase()["projects"]

        #print("data_p:")
        #print(data_p)
        #print("data_p2")
        #print(data_p2)

        l = []
        print(data_p)
        for _x in data_p:
            print("loop")
            print(_x)
            #self.test.addItem(_x["name"])
            item = QListWidgetItem(_x["name"], self.test)
            item.setData(Qt.UserRole, _x["id"])
            #l = []
            try:
                lol = api.task_get(self.api_token, _x["id"])
                print(lol)
                for _x in lol:
                    #if len(lol) > 0:
                    l.append(_x)
            except ApiException:
                pass
            #print(lol)
        print(l)
        if len(l) > 0:
            self.db.saveTasks(l)

        end_date = datetime.utcnow().isoformat()
        start_date = datetime.utcnow().replace(hour=0,
                                               minute=0,
                                               second=0,
                                               microsecond=0).isoformat()
        try:
            data = api.get_activity(self.api_token, start_date, end_date)
        except ApiException:
            data = [{"duration": 20}, {"duration": 400}, {"duration": 300}]

        print(data)
        for _x in data:
            #self.db.save_activity()
            self.elapsed_time += _x['duration']
        ''' Set timer '''
        self.labeltimer.setText(self._online_time(self.elapsed_time))

        if len(data) > 0:
            self.db.save_activity(data)

        try:
            whoami = api.whoami(self.api_token)
            self.db.saveUser(whoami["username"], whoami["api_token"],
                             whoami['api_expire'])
            self.db.saveProjects(data_p)
        except (ApiException, TypeError):
            pass
        #self.db.saveTasks

    def _online_time(self, data):
        hour = 0
        minute = 0
        second = 0
        hour = int(data / 60 / 60)
        data = data - (hour * 3600)
        minute = int(data / 60)
        data = data - (minute * 60)
        second = int(data)

        if hour < 10:
            hour = "0" + str(hour)
        if minute < 10:
            minute = "0" + str(minute)
        if second < 10:
            second = "0" + str(second)

        time_string = str(hour) + ":" + str(minute) + ":" + str(second)

        return time_string

    def closeEvent(self, event):
        data = api.activity_current(self.api_token)
        print(data)
        try:
            if data.get('error'):
                msg = "are you sure you want to quit?"
            elif data.get('id'):
                msg = "Are you sure you want to quit? if you quit the app we will stop the timetracker."
        except:
            msg = "Are you sure you want to quit"
            #pass

        errorBox = DialogBox()
        returnValue = errorBox.MsgBox(msg, "error")

        if returnValue == QMessageBox.Ok:
            #if data.get('id'):
            try:
                api.activity_stop(self.api_token, data['id'])
            except (TypeError, KeyError):
                pass
            self.thread_exit = True
            self.apa.thread_exit = True
            time.sleep(2)
            event.accept()
        else:
            event.ignore()
        print("close event")
class AddMovieDialog(QDialog):
    client = Client()

    def __init__(self, parent):
        super(AddMovieDialog, self).__init__(parent)
        self.setWindowTitle("Add Movie")
        main_layout = QVBoxLayout(self)

        self.selected_movies = None

        search_layout = QHBoxLayout()
        main_layout.addLayout(search_layout)

        self.search_field = QLineEdit()
        self.search_field.returnPressed.connect(self.find_action)
        self.search_field.setPlaceholderText("Search movies...")
        search_layout.addWidget(self.search_field)

        self.find_all_checkbx = QCheckBox("Find All")
        search_layout.addWidget(self.find_all_checkbx)

        self.result_list = QListWidget()
        self.result_list.setSelectionMode(QListWidget.ExtendedSelection)
        main_layout.addWidget(self.result_list)

        button_layout = QHBoxLayout()
        main_layout.addLayout(button_layout)

        add_bttn = QPushButton("Add Movie")
        add_bttn.clicked.connect(self.accept)

        add_all_bttn = QPushButton("Add All Movies")
        add_all_bttn.clicked.connect(self.add_all_action)

        cancel_bttn = QPushButton("Cancel")
        cancel_bttn.clicked.connect(self.reject)

        button_layout.addWidget(add_bttn)
        button_layout.addWidget(add_all_bttn)
        button_layout.addWidget(cancel_bttn)

    def keyPressEvent(self, event):
        event.ignore()

    def add_all_action(self):
        for i in range(self.result_list.count()):
            self.result_list.setItemSelected(self.result_list.item(i), True)

        self.accept()

    def accept(self):
        selected_items = self.result_list.selectedItems()
        if not selected_items:
            return

        self.selected_movies = [
            i.movie_data for i in selected_items
            if not self.client.find_movie(i.movie_data["id"])
        ]
        super(AddMovieDialog, self).accept()

    def find_action(self):
        movie_title = self.search_field.text()
        if len(movie_title):
            self.result_list.clear()

            for item in find_movie(
                    movie_title, all_pages=self.find_all_checkbx.isChecked()):
                MovieItem(self.result_list, item)
예제 #18
0
class SteamAccountSwitcherGui(QMainWindow, Accounts, DialogAccount,
                              DialogImportAccount, DialogSteamapiKey, Settings,
                              SystemTray):
    account_dialog_window: QDialog
    submit_button: QPushButton
    tray_menu: QMenu

    def __init__(self):
        QMainWindow.__init__(self)
        signal.signal(signal.SIGINT, self.exit_app)
        self.setWindowTitle("Steam Account Switcher")
        self.setMinimumSize(300, 200)
        self.resize(300, 300)

        # Logo
        self.switcher_logo = QIcon("logo.png")
        self.setWindowIcon(self.switcher_logo)
        if platform.system() == "Windows":  # windows taskbar app icon fix
            import ctypes
            win_appid = 'github.tommis.steam_account_switcher'
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
                win_appid)

        from steamswitcher import SteamSwitcher

        self.switcher = SteamSwitcher()
        self.args = self.switcher.args
        self.main_widget = QWidget()

        if self.args.gui or self.switcher.settings.get(
                "show_on_startup", True) and not self.args.no_gui:
            self.show()
        elif self.args.no_gui and self.args.no_tray:
            self.exit_app()

        self.menu_bar = self.menuBar()
        self.file_menu = self.menu_bar.addMenu(_("File"))
        self.settings_menu = self.menu_bar.addMenu(_("Settings"))
        self.size_menu = self.menu_bar.addMenu(_("Size"))

        refresh_action = QAction(_("Refresh"), self)
        import_action = QAction(_("Import accounts"), self)
        open_skinsdir_action = QAction(_("Skins dir"), self)
        about_action = QAction(_("About"), self)
        exit_action = QAction(_("Exit"), self)

        refresh_action.triggered.connect(Accounts.steamapi_refresh)
        import_action.triggered.connect(
            lambda: DialogImportAccount.import_accounts_dialog(self))
        open_skinsdir_action.triggered.connect(self.open_skinsdir)
        about_action.triggered.connect(lambda: DialogAbout.about_dialog(self))
        exit_action.triggered.connect(self.exit_app)

        refresh_action.setShortcut("F5")
        exit_action.setShortcut("Ctrl+Q")

        self.file_menu.addActions([
            refresh_action, import_action, open_skinsdir_action, about_action
        ])
        self.file_menu.addSeparator()
        self.file_menu.addAction(exit_action)

        set_steamapi_key = QAction(_("Set steamapi key"), self)
        show_avatars = QAction(_("Show avatars"), self, checkable=True)
        use_systemtray = QAction(_("Use systemtray"), self, checkable=True)

        after_login_menu = QMenu(_("After login"))

        after_login_behaviour_group = QActionGroup(after_login_menu)
        nothing_behaviour = QAction(_('Nothing'),
                                    after_login_behaviour_group,
                                    checkable=True,
                                    data="nothing")
        close_behaviour = QAction(_('Close'),
                                  after_login_behaviour_group,
                                  checkable=True,
                                  data="close")
        minimize_behaviour = QAction(_('Minimize to taskbar'),
                                     after_login_behaviour_group,
                                     checkable=True,
                                     data="minimize")
        minimize_tray_behaviour = QAction(_('Minimize to tray'),
                                          after_login_behaviour_group,
                                          checkable=True,
                                          data="minimize_tray")

        after_login_menu.addActions([
            nothing_behaviour, close_behaviour, minimize_behaviour,
            minimize_tray_behaviour
        ])

        behaviour_switcher = {
            "close": lambda: close_behaviour.setChecked(True),
            "minimize": lambda: minimize_behaviour.setChecked(True),
            "minimize_tray": lambda: minimize_tray_behaviour.setChecked(True)
        }
        behaviour_switcher.get(self.switcher.settings["behavior_after_login"],
                               lambda: nothing_behaviour.setChecked(True))()

        after_login_menu.triggered.connect(self.set_after_login_action)

        self.systemtray(self.main_widget)

        set_steamapi_key.triggered.connect(lambda: self.steamapi_key_dialog())
        show_avatars.triggered.connect(lambda: self.set_show_avatars())
        use_systemtray.triggered.connect(lambda: self.set_use_systemtray())

        self.settings_menu.addAction(set_steamapi_key)
        self.settings_menu.addSeparator()
        self.settings_menu.addActions([show_avatars, use_systemtray])
        self.settings_menu.addMenu(after_login_menu)

        show_avatars.setChecked(self.switcher.settings.get("show_avatars"))
        use_systemtray.setChecked(self.switcher.settings.get("use_systemtray"))

        set_size_small = QAction(_("Small"), self)
        set_size_medium = QAction(_("Medium"), self)
        set_size_large = QAction(_("Large"), self)
        set_size_small.triggered.connect(lambda: self.set_size("small"))
        set_size_medium.triggered.connect(lambda: self.set_size("medium"))
        set_size_large.triggered.connect(lambda: self.set_size("large"))
        self.size_menu.addActions(
            [set_size_small, set_size_medium, set_size_large])

        set_size_small.setShortcut("Ctrl+1")
        set_size_medium.setShortcut("Ctrl+2")
        set_size_large.setShortcut("Ctrl+3")

        self.add_button = QPushButton(_("Add account"))
        self.edit_button = QPushButton(_("Edit account"))
        self.edit_button.setDisabled(True)

        self.buttons = QHBoxLayout()
        self.buttons.addWidget(self.add_button)
        self.buttons.addWidget(self.edit_button)

        self.layout = QVBoxLayout()
        self.main_widget.setLayout(self.layout)

        self.accounts_list = QListWidget()
        self.accounts_list.setDragDropMode(QAbstractItemView.InternalMove)
        self.layout.addWidget(self.accounts_list)
        self.layout.addLayout(self.buttons)

        self.layout.setSpacing(10)
        self.accounts_list.setSpacing(1)

        self.import_accounts_window = QDialog()

        self.load_accounts()

        def edit_button_enabled():
            if self.accounts_list.selectedItems():
                self.edit_button.setEnabled(True)
            else:
                self.edit_button.setEnabled(False)

        # Signals and Slots
        self.add_button.clicked.connect(lambda: self.account_dialog(True))
        self.edit_button.clicked.connect(lambda: self.account_dialog(False))
        self.accounts_list.itemSelectionChanged.connect(edit_button_enabled)
        self.accounts_list.doubleClicked.connect(lambda: self.steam_login(
            self.accounts_list.currentIndex().data(5)))
        self.accounts_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.accounts_list.customContextMenuRequested.connect(
            lambda: RightClickMenu.show_rightclick_menu(self))
        #self.accounts_list.layoutChanged.connect(lambda: self.account_reordered)
        #self.accounts_list.dropEvent(self.dropEvent(QDropEvent))

        self.setCentralWidget(self.main_widget)

        if self.args.no_tray:
            print("test")
        elif self.switcher.settings.get("use_systemtray") or self.args.tray:
            self.tray_icon.show()

        if self.switcher.first_run or self.args.first_run:
            self.steamapi_key_dialog()
        elif not self.switcher.first_run and \
             not self.is_valid_steampi_key(self.switcher.settings["steam_api_key"]):
            self.tray_icon.showMessage("No api key",
                                       "Set the steam web api key.",
                                       self.switcher_logo)

    def exit_app(self):
        self.tray_icon.hide()
        QApplication.quit()

    def open_steam_profile(
        self,
        account,
    ):
        webbrowser.open(account["steam_user"].get("profileurl"))

    def open_skinsdir(self):
        if self.switcher.system_os == "Windows":
            os.startfile(self.switcher.skins_dir)
        elif self.switcher.system_os == "Linux":
            subprocess.Popen(["xdg-open", self.switcher.skins_dir])

    def dropEvent(self, event):
        print("hallo")

    def set_stay_on_top(self):
        pass
예제 #19
0
class ImageToPdfWidget(QWidget):
    def __init__(self, status_link):
        super(ImageToPdfWidget, self).__init__()
        LABEL_WIDTH = 80
        self.last_selected_items = []
        self.options_mode = 0
        self.update_status_combobox = False
        layout = QHBoxLayout()
        self.status_bar = status_link
        self.list_view = QListWidget()
        self.list_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.list_view.setAlternatingRowColors(True)
        self.list_view.itemClicked.connect(self.click_item_signal)
        self.list_view.itemEntered.connect(self.click_item_signal)
        self.list_view.itemSelectionChanged.connect(
            self.change_selection_signal)

        controls_layout = QVBoxLayout()
        controls_layout.setAlignment(Qt.AlignTop)

        select_zone = SelectWidget(self.click_move_up, self.click_move_down,
                                   self.click_invert, self.click_delete)

        # options zone -------------------------------------
        options_zone = QGroupBox("Options")
        self.options_zone_layout = QVBoxLayout()

        self.options_mode_combobox = QComboBox()
        self._add_items_to_mode_combobox(self.options_mode_combobox)
        options_mode_label = QLabel("Mode")
        options_mode_label.setMaximumWidth(LABEL_WIDTH)
        options_mode_layout = QHBoxLayout()
        options_mode_layout.addWidget(options_mode_label)
        options_mode_layout.addWidget(self.options_mode_combobox)
        self.options_zone_layout.addLayout(options_mode_layout)
        self.option_source_widget = OptionsFromSourceWidget(
            label_width=LABEL_WIDTH, status_bar=self.status_bar)
        self.options_a_widget = OptionsAWidget(label_width=LABEL_WIDTH,
                                               status_bar=self.status_bar)
        self.options_mode_combobox.currentIndexChanged.connect(
            self.change_options_mode_signal)
        self.change_options_mode_signal(self.options_mode)

        options_zone.setLayout(self.options_zone_layout)

        # Add files button and final structures ---------------------------
        add_file_button = QPushButton("Add Files")
        add_file_button.clicked.connect(self.click_add_files)
        controls_layout.addWidget(select_zone)
        controls_layout.addWidget(options_zone)
        controls_layout.addWidget(add_file_button)

        # image preview ---------------------------------------------------
        image_prev_layout = QVBoxLayout()
        image_prev_layout.setContentsMargins(0, 0, 4, 0)
        self.IMG_PREVIEW_WIDTH = 256
        self.img_label = QLabel()
        self.img_label.setAlignment(Qt.AlignCenter)
        self.select_text = "Click item to preview"
        self.last_created_pix_path = ""
        self.img_label.setText(self.select_text)
        image_prev_layout.addWidget(self.img_label)
        # slider for the preview scale
        self.img_scale_slider = QSlider()
        self.img_scale_slider.setMinimum(6)
        self.img_scale_slider.setMaximum(2048)
        self.img_scale_slider.setValue(self.IMG_PREVIEW_WIDTH)
        self.img_scale_slider.setOrientation(Qt.Horizontal)
        self.img_scale_slider.valueChanged.connect(
            self.change_scale_slider_signal)
        image_prev_layout.addWidget(self.img_scale_slider)
        self._update_preview()

        layout.addLayout(image_prev_layout)
        layout.addWidget(self.list_view)
        layout.addLayout(controls_layout)
        self.setLayout(layout)
        self.update_status_combobox = True

    def _pillow_to_pixmap(self, img):
        if img.mode == "RGB":
            r, g, b = img.split()
            img = Image.merge("RGB", (b, g, r))
        elif img.mode == "RGBA":
            r, g, b, a = img.split()
            img = Image.merge("RGBA", (b, g, r, a))
        elif img.mode == "L":
            img = img.convert("RGBA")
        img2 = img.convert("RGBA")
        data = img2.tobytes("raw", "RGBA")
        qim = QImage(data, img.size[0], img.size[1], QImage.Format_ARGB32)
        pixmap = QPixmap.fromImage(qim)
        return pixmap

    def _update_preview(self):
        self.img_label.setMinimumWidth(self.IMG_PREVIEW_WIDTH)
        self.img_label.setMaximumWidth(
            max(self.IMG_PREVIEW_WIDTH, self.img_scale_slider.width()))
        if len(self.last_created_pix_path) > 0:
            img = Image.open(self.last_created_pix_path)
            img_pix = self._pillow_to_pixmap(img)
            img_pix = img_pix.scaled(
                QSize(self.IMG_PREVIEW_WIDTH, self.IMG_PREVIEW_WIDTH),
                Qt.KeepAspectRatio)
            self.img_label.setPixmap(img_pix)

    def _set_preview(self, img_path):
        if img_path is None:
            self.last_created_pix_path = ""
            self.img_label.setText(self.select_text)
        else:
            if img_path != self.last_created_pix_path:
                self.last_created_pix_path = img_path
                self._update_preview()

    def _add_items_to_mode_combobox(self, combobox):
        combobox.addItem("From Source")
        combobox.addItem("A4")
        # combobox.addItem("A5")
        # combobox.addItem("A6")
        # combobox.addItem("Letter")

    def _get_filtered_string(self, string):
        to_return_array = []
        for s in string:
            if s.isdigit():
                to_return_array.append(s)
        return "".join(to_return_array)

    def get_images_to_save(self):
        path_array = []
        for i in range(self.list_view.count()):
            path_array.append(self.list_view.item(i).get_data())
        return path_array

    def get_image_parameters(self):  # return as dictionary
        if self.options_mode == 0:
            return {
                "mode": 0,
                "pixels": self.option_source_widget.get_pixel_value(),
                "margin": self.option_source_widget.get_margin_value(),
                "background": self.option_source_widget.get_background_value()
            }
        else:
            return {
                "mode": self.options_mode,
                "align": self.options_a_widget.get_align_value(),
                "margin": self.options_a_widget.get_margin_value(),
                "background": self.options_a_widget.get_background_value()
            }

    def add_items(self, array):
        added_names = []
        for a in array:
            new_name = os.path.basename(a)
            new_item = ImageListItem(new_name, a)
            added_names.append(new_name)
            self.list_view.addItem(new_item)
        self.status_bar.showMessage("Add items: " + ", ".join(added_names))

    def change_scale_slider_signal(self, value):
        self.IMG_PREVIEW_WIDTH = value
        self._update_preview()
        self.status_bar.showMessage("Set preview scale to " + str(value))

    def click_item_signal(self, item):
        pass
        # self._set_preview(item.get_data())
        # self.status_bar.showMessage("Select " + str(item.text()))

    def _get_first_new_index(self, current, last):
        for v in current:
            if v not in last:
                return v
        return current[0]

    def change_selection_signal(self):
        if len(self.list_view.selectedItems()) == 0:
            self._set_preview(None)  # nothing selected
        else:
            selected_indexes = [
                self.list_view.indexFromItem(sel).row()
                for sel in self.list_view.selectedItems()
            ]
            item = self.list_view.item(
                self._get_first_new_index(selected_indexes,
                                          self.last_selected_items))
            self._set_preview(item.get_data())
            self.status_bar.showMessage("Select " + str(item.text()))
            self.last_selected_items = selected_indexes

    def change_options_mode_signal(self, index):
        self.options_mode = index
        if self.options_mode == 0:
            self.options_zone_layout.removeWidget(self.options_a_widget)
            self.options_a_widget.setParent(None)
            self.options_zone_layout.addWidget(self.option_source_widget)
        else:
            self.options_zone_layout.removeWidget(self.option_source_widget)
            self.option_source_widget.setParent(None)
            self.options_zone_layout.addWidget(self.options_a_widget)
        if self.update_status_combobox:
            self.status_bar.showMessage(
                "Set combine mode to \"" +
                self.options_mode_combobox.itemText(index) + "\"")

    def resizeEvent(self, size):
        # self._update_preview()
        pass

    def click_move_up(self):
        selected = self.list_view.selectedItems()
        selected_indexes = [
            self.list_view.indexFromItem(sel).row() for sel in selected
        ]
        selected_indexes.sort()
        if len(selected_indexes) > 0 and selected_indexes[0] > 0:
            for index in selected_indexes:
                prev_item = self.list_view.takeItem(index - 1)
                self.list_view.insertItem(index, prev_item)
            self.status_bar.showMessage("Move " + str(len(selected_indexes)) +
                                        " items")
        else:
            self.status_bar.showMessage("Nothing to move")

    def click_move_down(self):
        selected = self.list_view.selectedItems()
        selected_indexes = [
            self.list_view.indexFromItem(sel).row() for sel in selected
        ]
        selected_indexes.sort()
        sel_count = len(selected_indexes)
        if len(selected_indexes) > 0 and selected_indexes[
                sel_count - 1] < self.list_view.count() - 1:
            for i_index in range(sel_count):
                next_item = self.list_view.takeItem(
                    selected_indexes[sel_count - i_index - 1] + 1)
                self.list_view.insertItem(
                    selected_indexes[sel_count - i_index - 1], next_item)
            self.status_bar.showMessage("Move " + str(len(selected_indexes)) +
                                        " items")
        else:
            self.status_bar.showMessage("Nothing to move")

    def click_invert(self):
        selected = self.list_view.selectedItems()
        selected_indexes = []
        for sel in selected:
            selected_indexes.append(self.list_view.indexFromItem(sel).row())
        total_indexes = [i for i in range(self.list_view.count())]
        new_indexes = []
        for i in total_indexes:
            if i not in selected_indexes:
                new_indexes.append(i)
        self.list_view.clearSelection()
        for i in new_indexes:
            self.list_view.item(i).setSelected(True)
        self.status_bar.showMessage("Invert selection: " + str(new_indexes))

    def click_delete(self):
        selected = self.list_view.selectedItems()
        delete_names = []
        for s in selected:
            s_index = self.list_view.indexFromItem(s).row()
            del_item = self.list_view.takeItem(s_index)
            delete_names.append(del_item.text())
        if len(delete_names) == 0:
            self.status_bar.showMessage("Nothing to delete")
        else:
            self.status_bar.showMessage("Delete items: " +
                                        ", ".join(delete_names))

    def click_add_files(self):
        files_dialog = QFileDialog()
        files_dialog.setNameFilter("Images (*.jpg *.jpeg *.bmp *.png *.tiff)")
        files_dialog.setFileMode(QFileDialog.ExistingFiles)
        if files_dialog.exec_():
            files = files_dialog.selectedFiles()
            self.add_items(files)
예제 #20
0
class ImportWindow(QDialog):
    def __init__(self):
        super(ImportWindow, self).__init__()

        self.setContentsMargins(5, 5, 5, 5)

        self._gamesdata = []
        self._platforms = []
        self._regions = set()

        self._platformListPath = Path("data/vgdb/")
        self._platformList = []
        for file in self._platformListPath.iterdir():
            self._platformList.append(file.stem)

        self._lblSelect = QLabel("Select platforms to import from:")

        self._consoleList = QListWidget()
        self._consoleList.addItems(sorted(self._platformList))
        self._consoleList.setSelectionMode(QAbstractItemView.MultiSelection)

        self._btnCancel = QPushButton("Cancel")
        self._btnCancel.clicked.connect(self.close)
        self._btnOK = QPushButton("OK")
        self._btnOK.clicked.connect(self._doImport)

        self._hboxOKCancel = QHBoxLayout()
        self._hboxOKCancel.addStretch(5)
        self._hboxOKCancel.addWidget(self._btnOK, 0)
        self._hboxOKCancel.addWidget(self._btnCancel, 1)

        self._vbox = QVBoxLayout()
        self._vbox.addWidget(self._lblSelect, 0)
        self._vbox.addWidget(self._consoleList, 1)
        self._vbox.addLayout(self._hboxOKCancel, 2)

        self.setLayout(self._vbox)
        self.setWindowTitle("Import games")
        self.setFixedSize(500, 280)
        self._center()

    def _center(self):
        """Centers window on screen"""

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

    def _doImport(self):
        platforms = [x.text() for x in self._consoleList.selectedItems()]
        proceed = QMessageBox.Ok

        if len(platforms) > 1:
            proceed = QMessageBox.warning(
                self, "Import warning",
                "Importing multiple platforms can take a long time.\n"
                "Are you sure you want to proceed?",
                QMessageBox.Cancel | QMessageBox.Ok, QMessageBox.Cancel)

        if proceed == QMessageBox.Ok:
            newData = []
            for file in self._platformListPath.iterdir():
                if file.stem in platforms:
                    self._platforms.append(file.stem)
                    newData.append(createGameData(file))
            for lst in newData:
                for game in lst:
                    self._gamesdata.append(game)
                    self._regions.add(game["region"])
            self.accept()

    def returnData(self):
        return self._gamesdata, self._platforms, self._regions
예제 #21
0
class VODCutter(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.twitch_client_id = config.TWITCH_API_CLIENT_ID
        self.twitch_oauth_token = config.TWITCH_API_OAUTH_TOKEN

        self.twitch_interface = TwitchInterface(
            api_client_id=config.TWITCH_API_CLIENT_ID,
            api_oauth_token=config.TWITCH_API_OAUTH_TOKEN,
            browser_client_id=config.TWITCH_BROWSER_OAUTH_TOKEN,
            browser_oauth_token=config.TWITCH_BROWSER_OAUTH_TOKEN)

        self.vlc_interface = VLCInterface(config.VLC_PATH)

        self.loaded_video = None

        self.main_layout = QVBoxLayout()

        self.launch_vlc_btn = QPushButton("Launch VLC")

        self.info_layout = QGridLayout()

        self.file_picker_layout = QHBoxLayout()

        self.file_path_field = QLineEdit()
        self.file_browser_btn = QPushButton(text="...")

        self.file_picker_layout.addWidget(self.file_path_field)
        self.file_picker_layout.addWidget(self.file_browser_btn)

        vod_filepath_label = QLabel("VOD Filepath")
        id_twitch_label = QLabel("ID Twitch")
        created_at_label = QLabel("Created at")
        duration_label = QLabel("Duration")
        title_label = QLabel("Title")
        streamer_label = QLabel("Streamer")

        self.id_twitch_field = QLineEdit()
        self.created_at_field = QLineEdit()
        self.duration_field = QLineEdit()
        self.title_field = QLineEdit()
        self.streamer_field = QLineEdit()

        self.id_twitch_field.setEnabled(False)
        self.created_at_field.setEnabled(False)
        self.duration_field.setEnabled(False)
        self.title_field.setEnabled(False)
        self.streamer_field.setEnabled(False)

        self.info_layout.addWidget(vod_filepath_label, 0, 0)
        self.info_layout.addWidget(id_twitch_label, 1, 0)
        self.info_layout.addWidget(created_at_label, 2, 0)
        self.info_layout.addWidget(duration_label, 3, 0)
        self.info_layout.addWidget(title_label, 4, 0)
        self.info_layout.addWidget(streamer_label, 5, 0)

        self.info_layout.addLayout(self.file_picker_layout, 0, 1)
        self.info_layout.addWidget(self.id_twitch_field, 1, 1)
        self.info_layout.addWidget(self.created_at_field, 2, 1)
        self.info_layout.addWidget(self.duration_field, 3, 1)
        self.info_layout.addWidget(self.title_field, 4, 1)
        self.info_layout.addWidget(self.streamer_field, 5, 1)

        self.segments_create_btn = QPushButton("Import Chapters")
        self.download_thumbnails_btn = QPushButton("Download Thumbnails")
        self.download_chatlog_btn = QPushButton("Download Chat Log")

        self.segments_list = QListWidget()

        self.segments_add_btn = QPushButton(text="+")
        self.segments_delete_btn = QPushButton(text="-")

        self.jump_start_btn = QPushButton(text="Jump To Start")
        self.jump_end_btn = QPushButton(text="Jump To End")

        self.set_start_btn = QPushButton(text="Set Start")
        self.set_end_btn = QPushButton(text="Set End")

        self.split_btn = QPushButton(text="Split")

        self.process_selected_btn = QPushButton(
            text="Process Selected Segment")
        self.process_all_btn = QPushButton(text="Process All Segments")

        self.jump_layout = QHBoxLayout()

        self.jump_layout.addWidget(self.jump_start_btn)
        self.jump_layout.addWidget(self.jump_end_btn)

        self.set_layout = QHBoxLayout()

        self.set_layout.addWidget(self.set_start_btn)
        self.set_layout.addWidget(self.set_end_btn)

        self.main_layout.addWidget(self.launch_vlc_btn)
        self.main_layout.addLayout(self.file_picker_layout)
        self.main_layout.addLayout(self.info_layout)
        self.main_layout.addWidget(self.segments_create_btn)
        self.main_layout.addWidget(self.download_thumbnails_btn)
        self.main_layout.addWidget(self.download_chatlog_btn)
        self.main_layout.addWidget(self.segments_list)
        self.main_layout.addWidget(self.segments_add_btn)
        self.main_layout.addWidget(self.segments_delete_btn)
        self.main_layout.addLayout(self.jump_layout)
        self.main_layout.addLayout(self.set_layout)
        self.main_layout.addWidget(self.split_btn)
        self.main_layout.addWidget(self.process_selected_btn)
        self.main_layout.addWidget(self.process_all_btn)

        self.main_widget = QWidget()
        self.main_widget.setLayout(self.main_layout)

        self.setCentralWidget(self.main_widget)

        self.segments_list.itemDoubleClicked.connect(
            self.on_segments_list_doubleclick)

        self.jump_start_btn.clicked.connect(self.jump_to_segment_start)
        self.jump_end_btn.clicked.connect(self.jump_to_segment_end)
        self.set_start_btn.clicked.connect(self.set_segment_start)
        self.set_end_btn.clicked.connect(self.set_segment_end)

        self.download_thumbnails_btn.clicked.connect(self.download_thumbnails)
        self.segments_add_btn.clicked.connect(self.create_segment)
        self.segments_delete_btn.clicked.connect(self.delete_segment)
        self.split_btn.clicked.connect(self.split_selected_segment)
        self.launch_vlc_btn.clicked.connect(self.on_launch_vlc)
        self.file_path_field.returnPressed.connect(self.on_video_url_changed)
        self.file_browser_btn.clicked.connect(self.on_filebrowse_btn_click)
        self.process_selected_btn.clicked.connect(
            self.process_selected_segment)
        self.process_all_btn.clicked.connect(self.process_all_segments)

    def on_launch_vlc(self):
        self.vlc_interface.launch()

    def on_filebrowse_btn_click(self):
        filename = QFileDialog.getOpenFileName(self, "Select a video file")
        if filename[0]:
            self.set_video_file(filename[0])

    def on_video_url_changed(self):
        self.set_video_file(self.file_path_field.text())

    def on_segments_list_doubleclick(self, item):
        current_segment = item.get_segment()
        if current_segment:
            self.vlc_interface.set_current_time(int(
                current_segment.start_time))

    def set_video_file(self, filepath=None):
        self.file_path_field.setText("" if filepath is None else filepath)

        if filepath:
            self.loaded_video = InputVideo()

            if re.search(r"^(?:/|[a-z]:[\\/])", filepath, re.I):
                file_url = "file://" + filepath
                self.loaded_video.is_local = True
            else:
                file_url = filepath

            if not self.loaded_video.is_local:
                streams = streamlink.streams(file_url)
                if streams:
                    self.loaded_video.filepath = streams["best"].url
                else:
                    self.loaded_video.filepath = file_url
            else:
                self.loaded_video.filepath = file_url

            try:
                self.update_twitch_metadatas()
            except requests.exceptions.ConnectionError:
                print("<!!> Can't connect to Twitch API.")

            try:
                self.vlc_interface.open_url(self.loaded_video.filepath)
            except requests.exceptions.ConnectionError:
                print("<!!> Can't connect to local VLC instance.")

    def get_twitch_id_from_filepath(self):
        filename = self.file_path_field.text()

        parsed_filename = re.search("([0-9]+)\.mp4$", filename, re.I)

        if parsed_filename:
            video_id = parsed_filename.group(1)
            return int(video_id)
        else:
            parsed_url = re.search("videos/([0-9]+)", filename, re.I)
            if parsed_url:
                video_id = parsed_url.group(1)
                return int(video_id)
            else:
                raise Exception(
                    f"<!!> Can't find video Twitch id in video filename ({filename})"
                )

    def create_segment_before(self, segment_obj):
        pass

    def create_segment_after(self, segment_obj):
        pass

    def update_twitch_metadatas(self):
        twitch_video_id = self.get_twitch_id_from_filepath()
        metadatas = self.twitch_interface.get_twitch_metadatas(twitch_video_id)

        self.loaded_video.metadatas = metadatas

        duration = parse_duration(metadatas["duration"])

        self.id_twitch_field.setText(metadatas["id"])
        self.created_at_field.setText(str(metadatas["created_at"]))
        self.duration_field.setText(format_time(duration.seconds))
        self.title_field.setText(metadatas["title"])
        self.streamer_field.setText(metadatas["user_login"])

        for moment in self.twitch_interface.get_video_games_list(
                metadatas["id"]):
            s = Segment()

            s.name = f"{moment['description']} ({moment['type']})"
            s.start_time = moment['positionMilliseconds'] / 1000
            s.end_time = (moment['positionMilliseconds'] +
                          moment['durationMilliseconds']) / 1000

            self.segments_list.addItem(SegmentListItem(s))

    def create_segment(self):
        s = Segment()

        s.name = f"Segment {self.segments_list.count()}"
        s.start_time = 0
        s.end_time = self.vlc_interface.get_duration()

        self.segments_list.addItem(SegmentListItem(s))

    def delete_segment(self):
        for item in self.segments_list.selectedItems():
            idx = self.segments_list.indexFromItem(item)
            item = self.segments_list.takeItem(idx.row())
            del item

    def split_selected_segment(self):
        current_time = self.vlc_interface.get_current_time()

        for segment_item in self.segments_list.selectedItems():
            current_segment = segment_item.get_segment()
            if current_segment:
                new_segment = segment_item.split(
                    current_time,
                    name="Splitted " + current_segment.name,
                    split_mode=SPLIT_MODE.ABSOLUTE)
                self.segments_list.addItem(SegmentListItem(new_segment))

    def get_selected_segments(self):
        return list(
            map(lambda item: item.get_segment(),
                self.segments_list.selectedItems()))

    def jump_to_segment_start(self):
        selected_segments = self.get_selected_segments()
        if selected_segments:
            self.vlc_interface.set_current_time(
                math.floor(selected_segments[0].start_time))

    def jump_to_segment_end(self):
        selected_segments = self.get_selected_segments()
        if selected_segments:
            self.vlc_interface.set_current_time(
                math.floor(selected_segments[0].end_time))

    def set_segment_start(self):
        current_time = self.vlc_interface.get_current_time()
        selected_segments = self.segments_list.selectedItems()
        if selected_segments:
            selected_segments[0].get_segment().start_time = current_time
            selected_segments[0].update()

    def set_segment_end(self):
        current_time = self.vlc_interface.get_current_time()
        selected_segments = self.segments_list.selectedItems()
        if selected_segments:
            selected_segments[0].get_segment().end_time = current_time
            selected_segments[0].update()

    def process_selected_segment(self):
        for segment in self.get_selected_segments():
            self.process_segment(segment)

    def process_all_segments(self):
        for idx in range(self.segments_list.count()):
            segment_item = self.segments_list.item(idx)
            self.process_segment(segment_item.get_segment())

    def process_segment(self, segment_obj):
        if not self.loaded_video:
            raise Exception("<!!> No video loaded")

        video_id = self.loaded_video.metadatas.get("id", None)
        created_at = self.loaded_video.metadatas.get("created_at", None)
        user_login = self.loaded_video.metadatas.get("user_login", None)

        if not (video_id and created_at and user_login):
            raise Exception("<!!> Missing video metadatas")

        created_at_timestamp = int(datetime.datetime.timestamp(created_at))

        if self.loaded_video.is_local:
            cmd = f'ffmpeg -i "{self.loaded_video.filepath}" -ss {segment_obj.start_time} -to {segment_obj.end_time} -c:v copy -c:a copy "{user_login}_{created_at_timestamp}_{video_id}.mp4"'
        else:
            cmd = f'streamlink -f --hls-start-offset {format_time(segment_obj.start_time)} --hls-duration {format_time(segment_obj.end_time - segment_obj.start_time)} --player-passthrough hls "{self.loaded_video.filepath}" best -o "{user_login}_{created_at_timestamp}_{video_id}.mp4"'

        print(cmd)

        os.system(cmd)

    def download_thumbnails(self):
        twitch_video_id_str = self.id_twitch_field.text()
        if twitch_video_id_str:
            thumbnails_manifest_url = self.twitch_interface.get_video_thumbnails_manifest_url(
                int(twitch_video_id_str))
            thumbnails_manifest, images_url_list = self.twitch_interface.get_thumbnails_url_from_manifest(
                thumbnails_manifest_url)

            for img in images_url_list:
                r = requests.get(images_url_list[img])
                fp = open(img, "wb")
                fp.write(r.content)
                fp.close()
예제 #22
0
class BrowserWin(QWidget):
    def __init__(self, *args, **kwargs):

        super(BrowserWin, self).__init__(*args, **kwargs)

        # parent Maya window
        self.setParent(mainWindow)
        self.setWindowFlags(Qt.Window)
        # Window settings
        self.setWindowTitle('AC_AssetBrowser')

        # Build window
        self.mainLayout = QVBoxLayout()
        self.btnLayout = QHBoxLayout()
        self.radioLayout = QHBoxLayout()

        # radio buttons load import
        self.radioLabel = QLabel("Action: ")
        self.importRadioBtn = QRadioButton("Import File")
        self.openRadioBtn = QRadioButton("Open File")
        self.saveRadioBtn = QRadioButton("Save File")

        # Find asset directories to load from and populate the drop down
        self.fileType = QComboBox()
        self.__populate_list(self.fileType)
        self.curr_cat = self.fileType.currentText()

        # list of assets in self.list
        self.fileList = QListWidget()
        self.fileList.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.__populate_list(self.fileList,
                             directory=os.path.join(DIRECTORY, self.curr_cat))

        self.fileName = QLineEdit()

        self.loadBtn = QPushButton("Load Asset")
        self.publishBtn = QPushButton("Publish")
        self.closeBtn = QPushButton("Close")

        # Add widgets to layouts
        self.radioLayout.addWidget(self.radioLabel)
        self.radioLayout.addWidget(self.importRadioBtn)
        self.radioLayout.addWidget(self.openRadioBtn)
        self.radioLayout.addWidget(self.saveRadioBtn)

        self.mainLayout.addLayout(self.radioLayout)

        self.mainLayout.addWidget(self.fileType)
        self.mainLayout.addWidget(self.fileList)
        self.mainLayout.addWidget(self.fileName)

        self.btnLayout.addWidget(self.loadBtn)
        self.btnLayout.addWidget(self.publishBtn)
        self.btnLayout.addWidget(self.closeBtn)

        self.mainLayout.addLayout(self.btnLayout)
        self.setLayout(self.mainLayout)

        # Set state of widgets
        self.importRadioBtn.toggle()
        self.fileName.setPlaceholderText("file_name")
        self.fileName.setEnabled(False)
        self.publishBtn.setEnabled(False)

        # Signals
        self.fileType.currentIndexChanged.connect(self.selectionChanged)
        self.loadBtn.clicked.connect(self.loadBtnCmd)
        self.publishBtn.clicked.connect(self.publishBtnCmd)
        self.closeBtn.clicked.connect(self.closeBtnCmd)
        self.importRadioBtn.toggled.connect(self.onImportToggled)
        self.openRadioBtn.toggled.connect(self.onOpenToggled)
        self.saveRadioBtn.toggled.connect(self.onSaveToggled)

    def __populate_list(self, destination, directory=DIRECTORY):
        _dirs = os.listdir(directory)
        _items = [_dir for _dir in _dirs]

        return destination.addItems(_items)

    def selectionChanged(self):
        self.curr_cat = self.fileType.currentText()
        self.fileList.clear()
        self.__populate_list(self.fileList,
                             directory=os.path.join(DIRECTORY, self.curr_cat))

    def loadBtnCmd(self):
        if self.importRadioBtn.isChecked():
            selected_files = self.fileList.selectedItems()
            for _file in selected_files:
                asset_file = os.path.join(DIRECTORY, self.curr_cat,
                                          _file.text())
                cmds.file(asset_file, i=True)
        elif self.openRadioBtn.isChecked():
            selected_file = self.fileList.currentItem()
            asset_file = os.path.join(DIRECTORY, self.curr_cat,
                                      selected_file.text())
            cmds.file(asset_file, o=True, force=True)
        else:
            print("Did you mean to publish this asset?")

    def publishBtnCmd(self):
        if self.saveRadioBtn.isChecked() and self.fileName.text() is not None:
            path_to_save = os.path.join(DIRECTORY, self.curr_cat,
                                        self.fileName.text())
            cmds.file(rn="{}.ma".format(path_to_save))
            cmds.file(save=True)
            self.fileList.clear()
            self.__populate_list(self.fileList,
                                 directory=os.path.join(
                                     DIRECTORY, self.curr_cat))

    def closeBtnCmd(self):
        self.close()

    def onSaveToggled(self):
        items = self.fileList.selectedItems()
        for item in items:
            item.setSelected(False)
        self.fileName.setEnabled(not self.fileName.isEnabled())
        self.publishBtn.setEnabled(not self.publishBtn.isEnabled())

    def onImportToggled(self):
        if self.importRadioBtn.isChecked():
            self.fileList.setSelectionMode(QAbstractItemView.ExtendedSelection)

    def onOpenToggled(self):
        if self.openRadioBtn.isChecked():
            items = self.fileList.selectedItems()
            items.pop()
            for item in items:
                item.setSelected(False)
            self.fileList.setSelectionMode(QAbstractItemView.SingleSelection)
예제 #23
0
class FilterDock(QDockWidget):

    def __init__(self, platforms, regions, genres, years):
        super(FilterDock, self).__init__()

        # QDockWidget settings
        self.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.setFeatures(QDockWidget.DockWidgetClosable)
        self.setFixedHeight(150)
        self.setVisible(False)
        self.setWindowTitle("Filter options")

        # The selected items for each widget are saved in a set-dictionary
        self._selections = defaultdict(set)

        #  Widget settings
        # Platform widgets
        self._platformLabel = QLabel("Platform")
        self._platforms = QListWidget()
        self._platforms.addItems(platforms)
        self._platforms.setSelectionMode(QAbstractItemView.MultiSelection)
        self._platforms.setMaximumWidth(200)
        self._platformVBox = QVBoxLayout()
        self._platformVBox.addWidget(self._platformLabel, 0)
        self._platformVBox.addWidget(self._platforms, 1)

        # Region widgets
        self._regionLabel = QLabel("Region")
        self._regions = QListWidget()
        self._regions.addItems(regions)
        self._regions.setSelectionMode(QAbstractItemView.MultiSelection)
        self._regions.setMaximumWidth(200)
        self._regionVBox = QVBoxLayout()
        self._regionVBox.addWidget(self._regionLabel, 0)
        self._regionVBox.addWidget(self._regions, 1)

        # Genre widgets
        self._genreLabel = QLabel("Genre")
        self._genres = QListWidget()
        self._genres.addItems(genres)
        self._genres.setSelectionMode(QAbstractItemView.MultiSelection)
        self._genres.setMaximumWidth(300)
        self._genreVBox = QVBoxLayout()
        self._genreVBox.addWidget(self._genreLabel, 0)
        self._genreVBox.addWidget(self._genres, 1)

        # Year widgets
        self._yearLabel = QLabel("Year")
        self._years = QListWidget()
        self._years.addItems(years)
        self._years.setSelectionMode(QAbstractItemView.MultiSelection)
        self._years.setMaximumWidth(75)
        self._yearsVbox = QVBoxLayout()
        self._yearsVbox.addWidget(self._yearLabel, 0)
        self._yearsVbox.addWidget(self._years, 1)

        # Inventory widgets
        self._itemType = {1: "Game", 2: "Console", 3: "Accessory"}
        self._item = QCheckBox(self._itemType[1])
        self._item.setTristate(True)
        self._item.setCheckState(Qt.PartiallyChecked)
        self._manual = QCheckBox("Manual")
        self._manual.setTristate(True)
        self._manual.setCheckState(Qt.PartiallyChecked)
        self._box = QCheckBox("Box")
        self._box.setTristate(True)
        self._box.setCheckState(Qt.PartiallyChecked)
        self._inventoryLabelsVBox = QVBoxLayout()
        self._inventorySelectionsVBox = QVBoxLayout()
        self._inventorySelectionsVBox.addStretch(3)
        self._inventorySelectionsVBox.addWidget(self._item, 0)
        self._inventorySelectionsVBox.addWidget(self._box, 1)
        self._inventorySelectionsVBox.addWidget(self._manual, 2)
        self._inventorySelectionsVBox.setAlignment(Qt.AlignLeft)
        self._haveHBox = QHBoxLayout()
        self._haveHBox.addLayout(self._inventoryLabelsVBox, 0)
        self._haveHBox.addLayout(self._inventorySelectionsVBox, 1)
        self._inventoryGroup = QGroupBox("Inventory")
        self._inventoryGroup.setMaximumWidth(120)
        self._inventoryGroup.setLayout(self._haveHBox)

        # Clear and Apply button widgets
        self._clearBtn = QPushButton("Clear selection")
        self._clearBtn.setMaximumSize(self._clearBtn.sizeHint())
        self._clearBtn.clicked.connect(self._clearFilters)
        self._btnHBox = QHBoxLayout()
        self._btnHBox.setAlignment(Qt.AlignBottom | Qt.AlignRight)
        self._btnHBox.addWidget(self._clearBtn, 0)

        # General layout
        mainHBox = QHBoxLayout()
        mainHBox.setAlignment(Qt.AlignLeft)
        mainHBox.addLayout(self._platformVBox, 0)
        mainHBox.addLayout(self._regionVBox, 0)
        mainHBox.addLayout(self._genreVBox, 0)
        mainHBox.addLayout(self._yearsVbox, 0)
        mainHBox.addWidget(self._inventoryGroup, 0)
        mainHBox.addLayout(self._btnHBox, 0)
        mainWidget = QWidget()
        mainWidget.setLayout(mainHBox)
        self.setWidget(mainWidget)

    def _clearFilters(self):
        self._platforms.clearSelection()
        self._regions.clearSelection()
        self._genres.clearSelection()
        self._years.clearSelection()
        self._item.setCheckState(Qt.PartiallyChecked)
        self._box.setCheckState(Qt.PartiallyChecked)
        self._manual.setCheckState(Qt.PartiallyChecked)
        logger.info("Cleared all filters.")

    def getSelections(self):
        self._selections = defaultdict(set)  # Reset selections
        if len(self._platforms.selectedItems()) > 0:
            platforms = [x.text() for x in self._platforms.selectedItems()]
            for platform in platforms:
                self._selections["Platform"].add(platform)
        if len(self._regions.selectedItems()) > 0:
            regions = [x.text() for x in self._regions.selectedItems()]
            for region in regions:
                self._selections["Region"].add(region)
        if len(self._genres.selectedItems()) > 0:
            genres = [x.text() for x in self._genres.selectedItems()]
            for genre in genres:
                self._selections["Genre"].add(genre)
        if len(self._years.selectedItems()) > 0:
            years = [x.text() for x in self._years.selectedItems()]
            for year in years:
                self._selections["Year"].add(year)
        if self._item.checkState() is not Qt.PartiallyChecked:
            self._selections[self._item.text()].add("Yes" if self._item.isChecked() else "No")
        if self._manual.checkState() is not Qt.PartiallyChecked:
            self._selections["Manual"].add("Yes" if self._manual.isChecked() else "No")
        if self._box.checkState() is not Qt.PartiallyChecked:
            self._selections["Box"].add("Yes" if self._box.isChecked() else "No")

        return self._selections

    def setItemType(self, itemType: int):
        if 0 < itemType < 4:
            if self._item.text() in self._selections:
                # Delete previous item entry so we don't search for the wrong type in the wrong table
                del self._selections[self._item.text()]
            self._item.setText(self._itemType[itemType])

    def toggleVisibility(self):
        self.setVisible(False if self.isVisible() else True)

    def updatePlatforms(self, platforms):
        self._platforms.clear()
        self._platforms.addItems(platforms)
        logger.info("Updated platforms list.")

    def updateRegions(self, regions):
        self._regions.clear()
        self._regions.addItems(regions)
        logger.info("Updated regions list.")

    def updateGenres(self, genres):
        self._genres.clear()
        self._genres.addItems(genres)
        logger.info("Updated genres list.")

    def updateYears(self, years):
        self._years.clear()
        self._years.addItems(years)
        logger.info("Updated years list.")